diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index cc7380759..6b1bc5173 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3411,6 +3411,9 @@ getLanguagePackInfo language_pack_id:string = LanguagePackInfo; //@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 Fetches latest versions of all strings from a language pack in the current localization target from the server. This method doesn't need to be called explicitly for the current used/base language packs @language_pack_id Language pack identifier +synchronizeLanguagePack language_pack_id:string = Ok; + //@description Adds a custom server language pack to the list of installed language packs in 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; @@ -3423,7 +3426,7 @@ editCustomLanguagePackInfo info:languagePackInfo = Ok; //@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 (including base language pack) 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 which is currently in use (including base language pack) or is being synchronized 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 be5a80c30..73005c142 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 6943242c1..c082f073e 100644 --- a/td/telegram/LanguagePackManager.cpp +++ b/td/telegram/LanguagePackManager.cpp @@ -51,6 +51,7 @@ struct LanguagePackManager::Language { bool is_full_ = false; bool was_loaded_full_ = false; bool has_get_difference_query_ = false; + vector> get_difference_queries_; std::unordered_map ordinary_strings_; std::unordered_map pluralized_strings_; std::unordered_set deleted_strings_; @@ -299,11 +300,18 @@ void LanguagePackManager::on_language_pack_version_changed(bool is_base, int32 n LOG(INFO) << (is_base ? "Base" : "Main") << " language pack " << language_code << " vesrion has changed to " << new_version; + send_language_get_difference_query(language, language_code, version, Auto()); +} + +void LanguagePackManager::send_language_get_difference_query(Language *language, const string &language_code, + int32 version, Promise &&promise) { std::lock_guard lock(language->mutex_); + language->get_difference_queries_.push_back(std::move(promise)); if (language->has_get_difference_query_) { return; } + CHECK(language->get_difference_queries_.size() == 1); language->has_get_difference_query_ = true; auto request_promise = PromiseCreator::lambda([actor_id = actor_id(this), language_pack = language_pack_, language_code, @@ -311,7 +319,7 @@ void LanguagePackManager::on_language_pack_version_changed(bool is_base, int32 n auto r_result = fetch_result(std::move(r_query)); if (r_result.is_error()) { send_closure(actor_id, &LanguagePackManager::on_failed_get_difference, std::move(language_pack), - std::move(language_code)); + std::move(language_code), r_result.move_as_error()); return; } @@ -1028,6 +1036,27 @@ void LanguagePackManager::load_empty_language_pack(const string &language_code) get_language_pack_strings(language_code, vector(), Auto()); } +void LanguagePackManager::synchronize_language_pack(string language_code, Promise promise) { + if (!check_language_code_name(language_code) || language_code.empty()) { + return promise.set_error(Status::Error(400, "Language pack ID is invalid")); + } + if (language_pack_.empty()) { + return promise.set_error(Status::Error(400, "Option \"localization_target\" needs to be set first")); + } + if (is_custom_language_code(language_code)) { + return promise.set_value(Unit()); + } + + Language *language = add_language(database_, language_pack_, language_code); + load_language_strings(database_, language, vector()); + + int32 version = language->version_.load(); + if (version == -1) { + version = 0; + } + send_language_get_difference_query(language, language_code, version, std::move(promise)); +} + static td_api::object_ptr copy_language_pack_string_value( const td_api::LanguagePackStringValue *value) { switch (value->get_id()) { @@ -1205,7 +1234,7 @@ void LanguagePackManager::on_get_language_pack_strings( int32 key_count_delta = 0; if (language->version_ < version || !keys.empty()) { vector> strings; - if (language->version_ < version && !(is_diff && language->version_ == -1)) { + if (language->version_ < version) { LOG(INFO) << "Set language pack " << language_code << " version to " << version; language->version_ = version; new_database_version = version; @@ -1312,10 +1341,18 @@ void LanguagePackManager::on_get_language_pack_strings( if (is_diff) { CHECK(language != nullptr); - std::lock_guard lock(language->mutex_); - if (language->has_get_difference_query_) { - language->has_get_difference_query_ = false; - is_version_changed = true; + vector> get_difference_queries; + { + std::lock_guard lock(language->mutex_); + if (language->has_get_difference_query_) { + language->has_get_difference_query_ = false; + get_difference_queries = std::move(language->get_difference_queries_); + reset_to_empty(language->get_difference_queries_); + is_version_changed = true; + } + } + for (auto &query : get_difference_queries) { + query.set_value(Unit()); } } if (is_version_changed && language_pack == language_pack_ && @@ -1329,15 +1366,26 @@ void LanguagePackManager::on_get_language_pack_strings( } } -void LanguagePackManager::on_failed_get_difference(string language_pack, string language_code) { +void LanguagePackManager::on_failed_get_difference(string language_pack, string language_code, Status error) { Language *language = get_language(database_, language_pack, language_code); CHECK(language != nullptr); - std::lock_guard lock(language->mutex_); - if (language->has_get_difference_query_) { - language->has_get_difference_query_ = false; - if (language_pack == language_pack_ && (language_code == language_code_ || language_code == base_language_code_)) { - send_closure_later(actor_id(this), &LanguagePackManager::on_language_pack_version_changed, - language_code != language_code_, -1); + vector> get_difference_queries; + { + std::lock_guard lock(language->mutex_); + if (language->has_get_difference_query_) { + language->has_get_difference_query_ = false; + if (language_pack == language_pack_ && + (language_code == language_code_ || language_code == base_language_code_)) { + send_closure_later(actor_id(this), &LanguagePackManager::on_language_pack_version_changed, + language_code != language_code_, -1); + } + get_difference_queries = std::move(language->get_difference_queries_); + reset_to_empty(language->get_difference_queries_); + } + } + for (auto &query : get_difference_queries) { + if (query) { + query.set_error(error.clone()); } } } diff --git a/td/telegram/LanguagePackManager.h b/td/telegram/LanguagePackManager.h index 9beee6d2c..169388fe4 100644 --- a/td/telegram/LanguagePackManager.h +++ b/td/telegram/LanguagePackManager.h @@ -62,6 +62,8 @@ class LanguagePackManager : public NetQueryCallback { const string &language_pack, const string &language_code, const string &key); + void synchronize_language_pack(string language_code, Promise promise); + void on_update_language_pack(tl_object_ptr difference); void add_custom_server_language(string language_code, Promise &&promise); @@ -163,7 +165,10 @@ class LanguagePackManager : public NetQueryCallback { void on_get_all_language_pack_strings(string language_pack, string language_code, Result> r_strings); - void on_failed_get_difference(string language_pack, string language_code); + void send_language_get_difference_query(Language *language, const string &language_code, int32 version, + Promise &&promise); + + void on_failed_get_difference(string language_pack, string language_code, Status error); void on_get_language_info(const string &language_pack, td_api::languagePackInfo *language_pack_info); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 3102d1d2a..a98c9e50e 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3189,6 +3189,7 @@ bool Td::is_preauthentication_request(int32 id) { case td_api::processPushNotification::ID: case td_api::getLocalizationTargetInfo::ID: case td_api::getLanguagePackStrings::ID: + case td_api::synchronizeLanguagePack::ID: case td_api::setCustomLanguagePack::ID: case td_api::editCustomLanguagePackInfo::ID: case td_api::setCustomLanguagePackString::ID: @@ -6263,6 +6264,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::synchronizeLanguagePack &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.language_pack_id_); + CREATE_OK_REQUEST_PROMISE(); + send_closure(language_pack_manager_, &LanguagePackManager::synchronize_language_pack, + std::move(request.language_pack_id_), std::move(promise)); +} + void Td::on_request(uint64 id, td_api::addCustomServerLanguagePack &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.language_pack_id_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index d7e2f051e..8ed7d8ce0 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -816,6 +816,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::getLanguagePackStrings &request); + void on_request(uint64 id, td_api::synchronizeLanguagePack &request); + void on_request(uint64 id, td_api::addCustomServerLanguagePack &request); void on_request(uint64 id, td_api::setCustomLanguagePack &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 7da646741..8ec10d1a6 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1861,6 +1861,9 @@ class CliClient final : public Actor { std::tie(language_code, key) = split(args); send_request(td_api::make_object(language_database_path, language_pack, language_code, key)); + } else if (op == "synclp") { + string language_code = args; + send_request(td_api::make_object(language_code)); } else if (op == "acslp") { string language_code = args; send_request(td_api::make_object(language_code));