diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index c43fde9b3..2ff9d6bef 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3380,16 +3380,19 @@ getLocalizationTargetInfo only_local:Bool = LocalizationTargetInfo; //@description Returns strings from a language pack in the current localization target by their keys @language_pack_id Language pack identifier of the strings to be returned @keys Language pack keys of the strings to be returned; leave empty to request all available strings getLanguagePackStrings language_pack_id:string keys:vector = LanguagePackStrings; -//@description Adds or changes a custom language pack to the current localization target @info Information about the language pack. Language pack ID must start with 'X', consist only of English letters, digits and hyphens, and must not exceed 64 characters @strings Strings of the new language pack +//@description Adds a custom server language pack to the current localization target @language_pack_id Identifier of a language pack to be added; may be different from a name that is used in an "https://t.me/setlanguage/" link +addCustomServerLanguagePack language_pack_id:string = Ok; + +//@description Adds or changes a custom local language pack to the current localization target @info Information about the language pack. Language pack ID must start with 'X', consist only of English letters, digits and hyphens, and must not exceed 64 characters @strings Strings of the new language pack setCustomLanguagePack info:languagePackInfo strings:vector = Ok; -//@description Edits information about a custom language pack in the current localization target @info New information about the custom language pack +//@description Edits information about a custom local language pack in the current localization target @info New information about the custom local language pack editCustomLanguagePackInfo info:languagePackInfo = Ok; -//@description Adds, edits or deletes a string in a custom language pack @language_pack_id Identifier of a previously added custom language pack in the current localization target @new_string New language pack string +//@description Adds, edits or deletes a string in a custom local language pack @language_pack_id Identifier of a previously added custom local language pack in the current localization target @new_string New language pack string setCustomLanguagePackString language_pack_id:string new_string:languagePackString = Ok; -//@description Deletes all information about a language pack in the current localization target. The language pack that is currently in use can't be deleted @language_pack_id Identifier of the language pack to delete +//@description Deletes all information about a language pack in the current localization target. The language pack that is currently in use (including base language pack) can't be deleted @language_pack_id Identifier of the language pack to delete deleteLanguagePack language_pack_id:string = Ok; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 4a3fbf8c5..8e3e18d81 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/LanguagePackManager.cpp b/td/telegram/LanguagePackManager.cpp index 306aaad1a..0f4ad7525 100644 --- a/td/telegram/LanguagePackManager.cpp +++ b/td/telegram/LanguagePackManager.cpp @@ -83,6 +83,7 @@ struct LanguagePackManager::LanguagePack { SqliteKeyValue pack_kv_; // usages should be guarded by database_->mutex_ std::map custom_language_pack_infos_; // sorted by language_code vector> server_language_pack_infos_; // sorted by server + std::unordered_map all_server_language_pack_infos_; std::unordered_map> languages_; }; @@ -465,6 +466,7 @@ LanguagePackManager::Language *LanguagePackManager::add_language(LanguageDatabas info.total_string_count_ = to_integer(all_infos[i + 8]); info.translated_string_count_ = to_integer(all_infos[i + 9]); info.translation_url_ = std::move(all_infos[i + 10]); + pack->all_server_language_pack_infos_.emplace(all_infos[i], info); pack->server_language_pack_infos_.emplace_back(std::move(all_infos[i]), std::move(info)); } } else { @@ -758,6 +760,7 @@ void LanguagePackManager::on_get_languages(vectorlanguage_packs_.find(language_pack); if (pack_it != database_->language_packs_.end()) { LanguagePack *pack = pack_it->second.get(); + std::lock_guard pack_lock(pack->mutex_); for (auto &info : pack->custom_language_pack_infos_) { add_language_info(info.first, info.second); } @@ -845,7 +848,11 @@ void LanguagePackManager::on_get_languages(vectorlanguage_packs_.find(language_pack); if (pack_it != database_->language_packs_.end()) { LanguagePack *pack = pack_it->second.get(); + std::lock_guard pack_lock(pack->mutex_); if (pack->server_language_pack_infos_ != all_server_infos) { + for (auto &info : all_server_infos) { + pack->all_server_language_pack_infos_.emplace(info.first, info.second); + } pack->server_language_pack_infos_ = std::move(all_server_infos); if (!pack->pack_kv_.empty()) { @@ -1266,6 +1273,40 @@ void LanguagePackManager::on_failed_get_difference(string language_pack, string } } +void LanguagePackManager::add_custom_server_language(string language_code, Promise &&promise) { + if (language_pack_.empty()) { + return promise.set_error(Status::Error(400, "Option \"localization_target\" needs to be set first")); + } + if (!check_language_code_name(language_code)) { + return promise.set_error(Status::Error(400, "Language pack ID must contain only letters, digits and hyphen")); + } + if (is_custom_language_code(language_code)) { + return promise.set_error( + Status::Error(400, "Custom local language pack can't be added through addCustomServerLanguagePack")); + } + + if (get_language(database_, language_pack_, language_code) == nullptr) { + return promise.set_error(Status::Error(400, "Language pack not found")); + } + + std::lock_guard packs_lock(database_->mutex_); + auto pack_it = database_->language_packs_.find(language_pack_); + CHECK(pack_it != database_->language_packs_.end()); + LanguagePack *pack = pack_it->second.get(); + std::lock_guard pack_lock(pack->mutex_); + auto it = pack->all_server_language_pack_infos_.find(language_code); + if (it == pack->all_server_language_pack_infos_.end()) { + return promise.set_error(Status::Error(400, "Language pack info not found")); + } + auto &info = pack->custom_language_pack_infos_[language_code]; + info = it->second; + if (!pack->pack_kv_.empty()) { + pack->pack_kv_.set(language_code, get_language_info_string(info)); + } + + promise.set_value(Unit()); +} + Result> LanguagePackManager::convert_to_telegram_api( tl_object_ptr &&str) { if (str == nullptr) { @@ -1398,6 +1439,7 @@ void LanguagePackManager::set_custom_language(td_api::object_ptrlanguage_packs_.find(language_pack_); CHECK(pack_it != database_->language_packs_.end()); LanguagePack *pack = pack_it->second.get(); + std::lock_guard pack_lock(pack->mutex_); auto &info = pack->custom_language_pack_infos_[language_code]; info = r_info.move_as_ok(); if (!pack->pack_kv_.empty()) { @@ -1426,6 +1468,7 @@ void LanguagePackManager::edit_custom_language_info(td_api::object_ptrlanguage_packs_.find(language_pack_); CHECK(pack_it != database_->language_packs_.end()); LanguagePack *pack = pack_it->second.get(); + std::lock_guard pack_lock(pack->mutex_); auto language_info_it = pack->custom_language_pack_infos_.find(language_code); if (language_info_it == pack->custom_language_pack_infos_.end()) { return promise.set_error(Status::Error(400, "Custom language pack is not found")); diff --git a/td/telegram/LanguagePackManager.h b/td/telegram/LanguagePackManager.h index dd7e58e87..668fd3b70 100644 --- a/td/telegram/LanguagePackManager.h +++ b/td/telegram/LanguagePackManager.h @@ -61,6 +61,8 @@ class LanguagePackManager : public NetQueryCallback { void on_update_language_pack(tl_object_ptr difference); + void add_custom_server_language(string language_code, Promise &&promise); + void set_custom_language(td_api::object_ptr &&language_pack_info, vector> strings, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 6746d8d90..1eea195d3 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6194,6 +6194,14 @@ void Td::on_request(uint64 id, td_api::getLanguagePackStrings &request) { std::move(request.language_pack_id_), std::move(request.keys_), std::move(promise)); } +void Td::on_request(uint64 id, td_api::addCustomServerLanguagePack &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.language_pack_id_); + CREATE_OK_REQUEST_PROMISE(); + send_closure(language_pack_manager_, &LanguagePackManager::add_custom_server_language, + std::move(request.language_pack_id_), std::move(promise)); +} + void Td::on_request(uint64 id, td_api::setCustomLanguagePack &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 29196b847..9fb24cbf2 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -809,6 +809,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::getLanguagePackStrings &request); + void on_request(uint64 id, td_api::addCustomServerLanguagePack &request); + void on_request(uint64 id, td_api::setCustomLanguagePack &request); void on_request(uint64 id, td_api::editCustomLanguagePackInfo &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index b509b124f..6b7cbf686 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1846,6 +1846,9 @@ class CliClient final : public Actor { std::tie(language_code, key) = split(args); send_request( make_tl_object(language_database_path, language_pack, language_code, key)); + } else if (op == "acslp") { + string language_code = args; + send_request(td_api::make_object(language_code)); } else if (op == "sclp") { string language_code; string name;