Calculate key count for each language.
GitOrigin-RevId: aad64d5cecb70f10e3a1cd013b58c7183ad67d31
This commit is contained in:
parent
0300c3387e
commit
3ac0116988
@ -1722,8 +1722,8 @@ languagePackString key:string value:LanguagePackStringValue = LanguagePackString
|
|||||||
//@description Contains a list of language pack strings @strings A list of language pack strings
|
//@description Contains a list of language pack strings @strings A list of language pack strings
|
||||||
languagePackStrings strings:vector<languagePackString> = LanguagePackStrings;
|
languagePackStrings strings:vector<languagePackString> = LanguagePackStrings;
|
||||||
|
|
||||||
//@description Contains information about a language @code Language code @name Language name @native_name Language native name
|
//@description Contains information about a language @code Language code @name Language name @native_name Language native name @local_key_count Total number of locally available non-deleted keys from the language
|
||||||
languageInfo code:string name:string native_name:string = LanguageInfo;
|
languageInfo code:string name:string native_name:string key_count:int32 = LanguageInfo;
|
||||||
|
|
||||||
//@description Contains information about a language pack @languages List of available languages
|
//@description Contains information about a language pack @languages List of available languages
|
||||||
languagePack languages:vector<languageInfo> = LanguagePack;
|
languagePack languages:vector<languageInfo> = LanguagePack;
|
||||||
@ -3136,7 +3136,7 @@ getLanguagePackInfo = LanguagePack;
|
|||||||
//@description Returns strings from a language in the used language pack by their keys @language_code Language code of strings to return @keys Language pack keys of strings to return; may be empty to get all available strings
|
//@description Returns strings from a language in the used language pack by their keys @language_code Language code of strings to return @keys Language pack keys of strings to return; may be empty to get all available strings
|
||||||
getLanguagePackStrings language_code:string keys:vector<string> = LanguagePackStrings;
|
getLanguagePackStrings language_code:string keys:vector<string> = LanguagePackStrings;
|
||||||
|
|
||||||
//@description Adds or changes a custom language to the used language pack @info Information about the language. Language code must start with 'X' @strings New language pack strings
|
//@description Adds or changes a custom language to the used language pack @info Information about the language. Language code must start with 'X', consist only of English letters, digits and hyphens and be not longer than 64 characters @strings New language pack strings
|
||||||
setCustomLanguage info:languageInfo strings:vector<languagePackString> = Ok;
|
setCustomLanguage info:languageInfo strings:vector<languagePackString> = Ok;
|
||||||
|
|
||||||
//@description Sets new value for a string in a custom language in the used language pack @language_code The code of previously added custom language, must start with 'X' @new_string New language pack string
|
//@description Sets new value for a string in a custom language in the used language pack @language_code The code of previously added custom language, must start with 'X' @new_string New language pack string
|
||||||
|
Binary file not shown.
@ -42,7 +42,9 @@ struct LanguagePackManager::PluralizedString {
|
|||||||
struct LanguagePackManager::Language {
|
struct LanguagePackManager::Language {
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
std::atomic<int32> version_{-1};
|
std::atomic<int32> version_{-1};
|
||||||
|
std::atomic<int32> key_count_{0};
|
||||||
bool is_full_ = false;
|
bool is_full_ = false;
|
||||||
|
bool was_loaded_full_ = false;
|
||||||
bool has_get_difference_query_ = false;
|
bool has_get_difference_query_ = false;
|
||||||
std::unordered_map<string, string> ordinary_strings_;
|
std::unordered_map<string, string> ordinary_strings_;
|
||||||
std::unordered_map<string, PluralizedString> pluralized_strings_;
|
std::unordered_map<string, PluralizedString> pluralized_strings_;
|
||||||
@ -77,16 +79,16 @@ bool LanguagePackManager::check_language_pack_name(Slice name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return name.size() <= 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LanguagePackManager::check_language_code_name(Slice name) {
|
bool LanguagePackManager::check_language_code_name(Slice name) {
|
||||||
for (auto c : name) {
|
for (auto c : name) {
|
||||||
if (c != '-' && !is_alpha(c)) {
|
if (c != '-' && !is_alpha(c) && !is_digit(c)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return name.size() <= 64 && (is_custom_language_code(name) || name.empty() || name.size() >= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LanguagePackManager::is_custom_language_code(Slice language_code) {
|
bool LanguagePackManager::is_custom_language_code(Slice language_code) {
|
||||||
@ -115,6 +117,26 @@ static int32 load_database_language_version(SqliteKeyValue *kv) {
|
|||||||
return to_integer<int32>(str_version);
|
return to_integer<int32>(str_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32 load_database_language_key_count(SqliteKeyValue *kv) {
|
||||||
|
CHECK(kv != nullptr);
|
||||||
|
if (kv->empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
string str_key_count = kv->get("!key_count");
|
||||||
|
if (str_key_count.empty()) {
|
||||||
|
// calculate key count once for the database and cache it
|
||||||
|
int key_count = 0;
|
||||||
|
for (auto &str : kv->get_all()) {
|
||||||
|
key_count += str.first[0] != '!' && (str.second[0] == '1' || str.second[0] == '2');
|
||||||
|
}
|
||||||
|
LOG(INFO) << "Set language key count in database to " << key_count;
|
||||||
|
kv->set("!key_count", to_string(key_count));
|
||||||
|
return key_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return to_integer<int32>(str_key_count);
|
||||||
|
}
|
||||||
|
|
||||||
LanguagePackManager::LanguageDatabase *LanguagePackManager::add_language_database(const string &path) {
|
LanguagePackManager::LanguageDatabase *LanguagePackManager::add_language_database(const string &path) {
|
||||||
auto it = language_databases_.find(path);
|
auto it = language_databases_.find(path);
|
||||||
if (it != language_databases_.end()) {
|
if (it != language_databases_.end()) {
|
||||||
@ -321,13 +343,14 @@ LanguagePackManager::Language *LanguagePackManager::add_language(LanguageDatabas
|
|||||||
.init_with_connection(database->database_.clone(), get_database_table_name(language_pack, language_code))
|
.init_with_connection(database->database_.clone(), get_database_table_name(language_pack, language_code))
|
||||||
.ensure();
|
.ensure();
|
||||||
language->version_ = load_database_language_version(&language->kv_);
|
language->version_ = load_database_language_version(&language->kv_);
|
||||||
|
language->key_count_ = load_database_language_key_count(&language->kv_);
|
||||||
}
|
}
|
||||||
code_it = pack->languages_.emplace(language_code, std::move(language)).first;
|
code_it = pack->languages_.emplace(language_code, std::move(language)).first;
|
||||||
}
|
}
|
||||||
return code_it->second.get();
|
return code_it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LanguagePackManager::language_has_string_unsafe(Language *language, const string &key) {
|
bool LanguagePackManager::language_has_string_unsafe(const Language *language, const string &key) {
|
||||||
return language->ordinary_strings_.count(key) != 0 || language->pluralized_strings_.count(key) != 0 ||
|
return language->ordinary_strings_.count(key) != 0 || language->pluralized_strings_.count(key) != 0 ||
|
||||||
language->deleted_strings_.count(key) != 0;
|
language->deleted_strings_.count(key) != 0;
|
||||||
}
|
}
|
||||||
@ -379,27 +402,26 @@ bool LanguagePackManager::load_language_strings(LanguageDatabase *database, Lang
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(DEBUG) << "Begin to load a language from database";
|
|
||||||
std::lock_guard<std::mutex> database_lock(database->mutex_);
|
std::lock_guard<std::mutex> database_lock(database->mutex_);
|
||||||
std::lock_guard<std::mutex> language_lock(language->mutex_);
|
std::lock_guard<std::mutex> language_lock(language->mutex_);
|
||||||
if (language->is_full_) {
|
if (language->is_full_) {
|
||||||
LOG(DEBUG) << "The language was already loaded";
|
LOG(DEBUG) << "The language is full in memory";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (language->kv_.empty()) {
|
if (language->kv_.empty()) {
|
||||||
LOG(DEBUG) << "The language has no database";
|
LOG(DEBUG) << "The language has no database";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
LOG(DEBUG) << "Begin to load a language from database";
|
||||||
if (keys.empty()) {
|
if (keys.empty()) {
|
||||||
if (language->version_ == -1) {
|
if (language->version_ == -1 && language->was_loaded_full_) {
|
||||||
LOG(DEBUG) << "There is nothing to load";
|
LOG(DEBUG) << "The language has already been loaded";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto all_strings = language->kv_.get_all();
|
auto all_strings = language->kv_.get_all();
|
||||||
for (auto &str : all_strings) {
|
for (auto &str : all_strings) {
|
||||||
if (str.first == "!version") {
|
if (str.first[0] == '!') {
|
||||||
CHECK(to_integer<int32>(str.second) == language->version_);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,17 +430,26 @@ bool LanguagePackManager::load_language_strings(LanguageDatabase *database, Lang
|
|||||||
load_language_string_unsafe(language, str.first, str.second);
|
load_language_string_unsafe(language, str.first, str.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
language->was_loaded_full_ = true;
|
||||||
|
|
||||||
|
if (language->version_ == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
language->is_full_ = true;
|
language->is_full_ = true;
|
||||||
language->deleted_strings_.clear();
|
language->deleted_strings_.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool have_all = true;
|
||||||
for (auto &key : keys) {
|
for (auto &key : keys) {
|
||||||
if (!language_has_string_unsafe(language, key)) {
|
if (!language_has_string_unsafe(language, key)) {
|
||||||
auto value = language->kv_.get(key);
|
auto value = language->kv_.get(key);
|
||||||
if (value.empty()) {
|
if (value.empty()) {
|
||||||
if (language->version_ == -1) {
|
if (language->version_ == -1) {
|
||||||
LOG(DEBUG) << "Have no string with key " << key << " in the database";
|
LOG(DEBUG) << "Have no string with key " << key << " in the database";
|
||||||
return false;
|
have_all = false;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// have full language in the database, so this string is just deleted
|
// have full language in the database, so this string is just deleted
|
||||||
@ -427,7 +458,7 @@ bool LanguagePackManager::load_language_strings(LanguageDatabase *database, Lang
|
|||||||
load_language_string_unsafe(language, key, value);
|
load_language_string_unsafe(language, key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return have_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
td_api::object_ptr<td_api::LanguagePackStringValue> LanguagePackManager::get_language_pack_string_value_object(
|
td_api::object_ptr<td_api::LanguagePackStringValue> LanguagePackManager::get_language_pack_string_value_object(
|
||||||
@ -460,7 +491,7 @@ td_api::object_ptr<td_api::languagePackString> LanguagePackManager::get_language
|
|||||||
}
|
}
|
||||||
|
|
||||||
td_api::object_ptr<td_api::LanguagePackStringValue> LanguagePackManager::get_language_pack_string_value_object(
|
td_api::object_ptr<td_api::LanguagePackStringValue> LanguagePackManager::get_language_pack_string_value_object(
|
||||||
Language *language, const string &key) {
|
const Language *language, const string &key) {
|
||||||
CHECK(language != nullptr);
|
CHECK(language != nullptr);
|
||||||
auto ordinary_it = language->ordinary_strings_.find(key);
|
auto ordinary_it = language->ordinary_strings_.find(key);
|
||||||
if (ordinary_it != language->ordinary_strings_.end()) {
|
if (ordinary_it != language->ordinary_strings_.end()) {
|
||||||
@ -474,8 +505,8 @@ td_api::object_ptr<td_api::LanguagePackStringValue> LanguagePackManager::get_lan
|
|||||||
return get_language_pack_string_value_object(key);
|
return get_language_pack_string_value_object(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
td_api::object_ptr<td_api::languagePackString> LanguagePackManager::get_language_pack_string_object(Language *language,
|
td_api::object_ptr<td_api::languagePackString> LanguagePackManager::get_language_pack_string_object(
|
||||||
const string &key) {
|
const Language *language, const string &key) {
|
||||||
return td_api::make_object<td_api::languagePackString>(key, get_language_pack_string_value_object(language, key));
|
return td_api::make_object<td_api::languagePackString>(key, get_language_pack_string_value_object(language, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,36 +533,50 @@ td_api::object_ptr<td_api::languagePackStrings> LanguagePackManager::get_languag
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LanguagePackManager::get_languages(Promise<td_api::object_ptr<td_api::languagePack>> promise) {
|
void LanguagePackManager::get_languages(Promise<td_api::object_ptr<td_api::languagePack>> promise) {
|
||||||
auto results = make_tl_object<td_api::languagePack>();
|
auto request_promise = PromiseCreator::lambda([actor_id = actor_id(this), language_pack = language_pack_,
|
||||||
|
promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||||
std::lock_guard<std::mutex> packs_lock(database_->mutex_);
|
|
||||||
auto pack_it = database_->language_packs_.find(language_pack_);
|
|
||||||
if (pack_it != database_->language_packs_.end()) {
|
|
||||||
LanguagePack *pack = pack_it->second.get();
|
|
||||||
for (auto &info : pack->language_infos_) {
|
|
||||||
results->languages_.push_back(
|
|
||||||
make_tl_object<td_api::languageInfo>(info.first, info.second.name, info.second.native_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto request_promise = PromiseCreator::lambda(
|
|
||||||
[results = std::move(results), promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
|
||||||
auto r_result = fetch_result<telegram_api::langpack_getLanguages>(std::move(r_query));
|
auto r_result = fetch_result<telegram_api::langpack_getLanguages>(std::move(r_query));
|
||||||
if (r_result.is_error()) {
|
if (r_result.is_error()) {
|
||||||
return promise.set_error(r_result.move_as_error());
|
return promise.set_error(r_result.move_as_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto languages = r_result.move_as_ok();
|
send_closure(actor_id, &LanguagePackManager::on_get_languages, r_result.move_as_ok(), std::move(language_pack),
|
||||||
for (auto &language : languages) {
|
std::move(promise));
|
||||||
results->languages_.push_back(
|
|
||||||
make_tl_object<td_api::languageInfo>(language->lang_code_, language->name_, language->native_name_));
|
|
||||||
}
|
|
||||||
promise.set_value(std::move(results));
|
|
||||||
});
|
});
|
||||||
send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::langpack_getLanguages(language_pack_))),
|
send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::langpack_getLanguages(language_pack_))),
|
||||||
std::move(request_promise));
|
std::move(request_promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LanguagePackManager::on_get_languages(vector<tl_object_ptr<telegram_api::langPackLanguage>> languages,
|
||||||
|
string language_pack,
|
||||||
|
Promise<td_api::object_ptr<td_api::languagePack>> promise) {
|
||||||
|
auto results = make_tl_object<td_api::languagePack>();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> packs_lock(database_->mutex_);
|
||||||
|
auto pack_it = database_->language_packs_.find(language_pack);
|
||||||
|
if (pack_it != database_->language_packs_.end()) {
|
||||||
|
LanguagePack *pack = pack_it->second.get();
|
||||||
|
for (auto &info : pack->language_infos_) {
|
||||||
|
results->languages_.push_back(
|
||||||
|
make_tl_object<td_api::languageInfo>(info.first, info.second.name, info.second.native_name, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &language : languages) {
|
||||||
|
results->languages_.push_back(
|
||||||
|
make_tl_object<td_api::languageInfo>(language->lang_code_, language->name_, language->native_name_, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &language_info : results->languages_) {
|
||||||
|
auto language = add_language(database_, language_pack, language_info->code_);
|
||||||
|
language_info->key_count_ = language->key_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.set_value(std::move(results));
|
||||||
|
}
|
||||||
|
|
||||||
void LanguagePackManager::get_language_pack_strings(string language_code, vector<string> keys,
|
void LanguagePackManager::get_language_pack_strings(string language_code, vector<string> keys,
|
||||||
Promise<td_api::object_ptr<td_api::languagePackStrings>> promise) {
|
Promise<td_api::object_ptr<td_api::languagePackStrings>> promise) {
|
||||||
for (auto &key : keys) {
|
for (auto &key : keys) {
|
||||||
@ -540,16 +585,13 @@ void LanguagePackManager::get_language_pack_strings(string language_code, vector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Language *language = get_language(database_, language_pack_, language_code);
|
Language *language = add_language(database_, language_pack_, language_code);
|
||||||
if (language_has_strings(language, keys)) {
|
if (language_has_strings(language, keys)) {
|
||||||
return promise.set_value(get_language_pack_strings_object(language, keys));
|
return promise.set_value(get_language_pack_strings_object(language, keys));
|
||||||
}
|
}
|
||||||
if (!database_->database_.empty()) {
|
|
||||||
language = add_language(database_, language_pack_, language_code);
|
|
||||||
if (load_language_strings(database_, language, keys)) {
|
if (load_language_strings(database_, language, keys)) {
|
||||||
return promise.set_value(get_language_pack_strings_object(language, keys));
|
return promise.set_value(get_language_pack_strings_object(language, keys));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (keys.empty()) {
|
if (keys.empty()) {
|
||||||
auto request_promise =
|
auto request_promise =
|
||||||
@ -617,7 +659,8 @@ td_api::object_ptr<td_api::Object> LanguagePackManager::get_language_pack_string
|
|||||||
std::lock_guard<std::mutex> lock(language->mutex_);
|
std::lock_guard<std::mutex> lock(language->mutex_);
|
||||||
return get_language_pack_string_value_object(language, key);
|
return get_language_pack_string_value_object(language, key);
|
||||||
}
|
}
|
||||||
if (!database->database_.empty() && load_language_strings(database, language, keys)) {
|
if (load_language_strings(database, language, keys)) {
|
||||||
|
std::lock_guard<std::mutex> lock(language->mutex_);
|
||||||
return get_language_pack_string_value_object(language, key);
|
return get_language_pack_string_value_object(language, key);
|
||||||
}
|
}
|
||||||
return td_api::make_object<td_api::error>(404, "Not Found");
|
return td_api::make_object<td_api::error>(404, "Not Found");
|
||||||
@ -632,15 +675,16 @@ bool LanguagePackManager::is_valid_key(Slice key) {
|
|||||||
return !key.empty();
|
return !key.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LanguagePackManager::save_strings_to_database(Language *language, int32 new_version,
|
void LanguagePackManager::save_strings_to_database(SqliteKeyValue *kv, int32 new_version, bool new_is_full,
|
||||||
vector<std::pair<string, string>> strings) {
|
int32 new_key_count, vector<std::pair<string, string>> strings) {
|
||||||
LOG(DEBUG) << "Save to database a language with new version " << new_version;
|
LOG(DEBUG) << "Save to database a language with new version " << new_version << " and " << strings.size()
|
||||||
|
<< " new strings";
|
||||||
if (new_version == -1 && strings.empty()) {
|
if (new_version == -1 && strings.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(database_->mutex_);
|
std::lock_guard<std::mutex> lock(database_->mutex_);
|
||||||
auto kv = &language->kv_;
|
CHECK(kv != nullptr);
|
||||||
if (kv->empty()) {
|
if (kv->empty()) {
|
||||||
LOG(DEBUG) << "There is no associated database key-value";
|
LOG(DEBUG) << "There is no associated database key-value";
|
||||||
return;
|
return;
|
||||||
@ -658,7 +702,7 @@ void LanguagePackManager::save_strings_to_database(Language *language, int32 new
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (language->is_full_ && str.second == "3") {
|
if (new_is_full && str.second == "3") {
|
||||||
kv->erase(str.first);
|
kv->erase(str.first);
|
||||||
} else {
|
} else {
|
||||||
kv->set(str.first, str.second);
|
kv->set(str.first, str.second);
|
||||||
@ -669,6 +713,10 @@ void LanguagePackManager::save_strings_to_database(Language *language, int32 new
|
|||||||
LOG(DEBUG) << "Set language version in database to " << new_version;
|
LOG(DEBUG) << "Set language version in database to " << new_version;
|
||||||
kv->set("!version", to_string(new_version));
|
kv->set("!version", to_string(new_version));
|
||||||
}
|
}
|
||||||
|
if (new_key_count != -1) {
|
||||||
|
LOG(DEBUG) << "Set language key count in database to " << new_key_count;
|
||||||
|
kv->set("!key_count", to_string(new_key_count));
|
||||||
|
}
|
||||||
kv->commit_transaction().ensure();
|
kv->commit_transaction().ensure();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,13 +727,18 @@ void LanguagePackManager::on_get_language_pack_strings(
|
|||||||
Language *language = get_language(database_, language_pack, language_code);
|
Language *language = get_language(database_, language_pack, language_code);
|
||||||
bool is_version_changed = false;
|
bool is_version_changed = false;
|
||||||
int32 new_database_version = -1;
|
int32 new_database_version = -1;
|
||||||
|
int32 new_key_count = -1;
|
||||||
|
bool new_is_full = false;
|
||||||
vector<std::pair<string, string>> database_strings;
|
vector<std::pair<string, string>> database_strings;
|
||||||
if (language == nullptr || language->version_ < version || !keys.empty()) {
|
if (language == nullptr || language->version_ < version || !keys.empty()) {
|
||||||
if (language == nullptr) {
|
if (language == nullptr) {
|
||||||
language = add_language(database_, language_pack, language_code);
|
language = add_language(database_, language_pack, language_code);
|
||||||
CHECK(language != nullptr);
|
CHECK(language != nullptr);
|
||||||
}
|
}
|
||||||
|
load_language_strings(database_, language, keys);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(language->mutex_);
|
std::lock_guard<std::mutex> lock(language->mutex_);
|
||||||
|
int32 key_count_delta = 0;
|
||||||
if (language->version_ < version || !keys.empty()) {
|
if (language->version_ < version || !keys.empty()) {
|
||||||
vector<td_api::object_ptr<td_api::languagePackString>> strings;
|
vector<td_api::object_ptr<td_api::languagePackString>> strings;
|
||||||
if (language->version_ < version && !(is_diff && language->version_ == -1)) {
|
if (language->version_ < version && !(is_diff && language->version_ == -1)) {
|
||||||
@ -702,11 +755,12 @@ void LanguagePackManager::on_get_language_pack_strings(
|
|||||||
auto str = static_cast<telegram_api::langPackString *>(result.get());
|
auto str = static_cast<telegram_api::langPackString *>(result.get());
|
||||||
auto it = language->ordinary_strings_.find(str->key_);
|
auto it = language->ordinary_strings_.find(str->key_);
|
||||||
if (it == language->ordinary_strings_.end()) {
|
if (it == language->ordinary_strings_.end()) {
|
||||||
|
key_count_delta++;
|
||||||
it = language->ordinary_strings_.emplace(str->key_, std::move(str->value_)).first;
|
it = language->ordinary_strings_.emplace(str->key_, std::move(str->value_)).first;
|
||||||
} else {
|
} else {
|
||||||
it->second = std::move(str->value_);
|
it->second = std::move(str->value_);
|
||||||
}
|
}
|
||||||
language->pluralized_strings_.erase(str->key_);
|
key_count_delta -= language->pluralized_strings_.erase(str->key_);
|
||||||
language->deleted_strings_.erase(str->key_);
|
language->deleted_strings_.erase(str->key_);
|
||||||
if (is_diff) {
|
if (is_diff) {
|
||||||
strings.push_back(get_language_pack_string_object(*it));
|
strings.push_back(get_language_pack_string_object(*it));
|
||||||
@ -721,11 +775,12 @@ void LanguagePackManager::on_get_language_pack_strings(
|
|||||||
std::move(str->many_value_), std::move(str->other_value_)};
|
std::move(str->many_value_), std::move(str->other_value_)};
|
||||||
auto it = language->pluralized_strings_.find(str->key_);
|
auto it = language->pluralized_strings_.find(str->key_);
|
||||||
if (it == language->pluralized_strings_.end()) {
|
if (it == language->pluralized_strings_.end()) {
|
||||||
|
key_count_delta++;
|
||||||
it = language->pluralized_strings_.emplace(str->key_, std::move(value)).first;
|
it = language->pluralized_strings_.emplace(str->key_, std::move(value)).first;
|
||||||
} else {
|
} else {
|
||||||
it->second = std::move(value);
|
it->second = std::move(value);
|
||||||
}
|
}
|
||||||
language->ordinary_strings_.erase(str->key_);
|
key_count_delta -= language->ordinary_strings_.erase(str->key_);
|
||||||
language->deleted_strings_.erase(str->key_);
|
language->deleted_strings_.erase(str->key_);
|
||||||
if (is_diff) {
|
if (is_diff) {
|
||||||
strings.push_back(get_language_pack_string_object(*it));
|
strings.push_back(get_language_pack_string_object(*it));
|
||||||
@ -738,8 +793,8 @@ void LanguagePackManager::on_get_language_pack_strings(
|
|||||||
}
|
}
|
||||||
case telegram_api::langPackStringDeleted::ID: {
|
case telegram_api::langPackStringDeleted::ID: {
|
||||||
auto str = static_cast<const telegram_api::langPackStringDeleted *>(result.get());
|
auto str = static_cast<const telegram_api::langPackStringDeleted *>(result.get());
|
||||||
language->ordinary_strings_.erase(str->key_);
|
key_count_delta -= language->ordinary_strings_.erase(str->key_);
|
||||||
language->pluralized_strings_.erase(str->key_);
|
key_count_delta -= language->pluralized_strings_.erase(str->key_);
|
||||||
language->deleted_strings_.insert(std::move(str->key_));
|
language->deleted_strings_.insert(std::move(str->key_));
|
||||||
if (is_diff) {
|
if (is_diff) {
|
||||||
strings.push_back(get_language_pack_string_object(str->key_));
|
strings.push_back(get_language_pack_string_object(str->key_));
|
||||||
@ -765,6 +820,11 @@ void LanguagePackManager::on_get_language_pack_strings(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key_count_delta != 0) {
|
||||||
|
new_key_count = language->key_count_ + key_count_delta;
|
||||||
|
language->key_count_ = new_key_count;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_diff) {
|
if (is_diff) {
|
||||||
send_closure(
|
send_closure(
|
||||||
G()->td(), &Td::send_update,
|
G()->td(), &Td::send_update,
|
||||||
@ -776,10 +836,15 @@ void LanguagePackManager::on_get_language_pack_strings(
|
|||||||
language->is_full_ = true;
|
language->is_full_ = true;
|
||||||
language->deleted_strings_.clear();
|
language->deleted_strings_.clear();
|
||||||
}
|
}
|
||||||
|
new_is_full = language->is_full_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_custom_language_code(language_code) && new_database_version == -1) {
|
||||||
|
new_database_version = 1;
|
||||||
|
}
|
||||||
|
|
||||||
save_strings_to_database(language, new_database_version, std::move(database_strings));
|
save_strings_to_database(&language->kv_, new_database_version, new_is_full, new_key_count,
|
||||||
|
std::move(database_strings));
|
||||||
|
|
||||||
if (is_diff) {
|
if (is_diff) {
|
||||||
CHECK(language != nullptr);
|
CHECK(language != nullptr);
|
||||||
@ -965,6 +1030,7 @@ Status LanguagePackManager::do_delete_language(string language_code) {
|
|||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> language_lock(language->mutex_);
|
std::lock_guard<std::mutex> language_lock(language->mutex_);
|
||||||
language->version_ = -1;
|
language->version_ = -1;
|
||||||
|
language->key_count_ = load_database_language_key_count(&language->kv_);
|
||||||
language->is_full_ = false;
|
language->is_full_ = false;
|
||||||
language->ordinary_strings_.clear();
|
language->ordinary_strings_.clear();
|
||||||
language->pluralized_strings_.clear();
|
language->pluralized_strings_.clear();
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
|
class SqliteKeyValue;
|
||||||
|
|
||||||
class LanguagePackManager : public NetQueryCallback {
|
class LanguagePackManager : public NetQueryCallback {
|
||||||
public:
|
public:
|
||||||
explicit LanguagePackManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
explicit LanguagePackManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
||||||
@ -90,7 +92,7 @@ class LanguagePackManager : public NetQueryCallback {
|
|||||||
|
|
||||||
static Language *add_language(LanguageDatabase *database, const string &language_pack, const string &language_code);
|
static Language *add_language(LanguageDatabase *database, const string &language_pack, const string &language_code);
|
||||||
|
|
||||||
static bool language_has_string_unsafe(Language *language, const string &key);
|
static bool language_has_string_unsafe(const Language *language, const string &key);
|
||||||
static bool language_has_strings(Language *language, const vector<string> &keys);
|
static bool language_has_strings(Language *language, const vector<string> &keys);
|
||||||
|
|
||||||
static void load_language_string_unsafe(Language *language, const string &key, string &value);
|
static void load_language_string_unsafe(Language *language, const string &key, string &value);
|
||||||
@ -107,10 +109,10 @@ class LanguagePackManager : public NetQueryCallback {
|
|||||||
const std::pair<string, PluralizedString> &str);
|
const std::pair<string, PluralizedString> &str);
|
||||||
static td_api::object_ptr<td_api::languagePackString> get_language_pack_string_object(const string &str);
|
static td_api::object_ptr<td_api::languagePackString> get_language_pack_string_object(const string &str);
|
||||||
|
|
||||||
static td_api::object_ptr<td_api::LanguagePackStringValue> get_language_pack_string_value_object(Language *language,
|
static td_api::object_ptr<td_api::LanguagePackStringValue> get_language_pack_string_value_object(
|
||||||
const string &key);
|
const Language *language, const string &key);
|
||||||
|
|
||||||
static td_api::object_ptr<td_api::languagePackString> get_language_pack_string_object(Language *language,
|
static td_api::object_ptr<td_api::languagePackString> get_language_pack_string_object(const Language *language,
|
||||||
const string &key);
|
const string &key);
|
||||||
|
|
||||||
static td_api::object_ptr<td_api::languagePackStrings> get_language_pack_strings_object(Language *language,
|
static td_api::object_ptr<td_api::languagePackStrings> get_language_pack_strings_object(Language *language,
|
||||||
@ -123,7 +125,8 @@ class LanguagePackManager : public NetQueryCallback {
|
|||||||
|
|
||||||
static bool is_valid_key(Slice key);
|
static bool is_valid_key(Slice key);
|
||||||
|
|
||||||
void save_strings_to_database(Language *language, int32 new_version, vector<std::pair<string, string>> strings);
|
void save_strings_to_database(SqliteKeyValue *kv, int32 new_version, bool new_is_full, int32 new_key_count,
|
||||||
|
vector<std::pair<string, string>> strings);
|
||||||
|
|
||||||
void on_get_language_pack_strings(string language_pack, string language_code, int32 version, bool is_diff,
|
void on_get_language_pack_strings(string language_pack, string language_code, int32 version, bool is_diff,
|
||||||
vector<string> keys, vector<tl_object_ptr<telegram_api::LangPackString>> results,
|
vector<string> keys, vector<tl_object_ptr<telegram_api::LangPackString>> results,
|
||||||
@ -131,6 +134,9 @@ class LanguagePackManager : public NetQueryCallback {
|
|||||||
|
|
||||||
void on_failed_get_difference(string language_pack, string language_code);
|
void on_failed_get_difference(string language_pack, string language_code);
|
||||||
|
|
||||||
|
void on_get_languages(vector<tl_object_ptr<telegram_api::langPackLanguage>> languages, string language_pack,
|
||||||
|
Promise<td_api::object_ptr<td_api::languagePack>> promise);
|
||||||
|
|
||||||
Status do_delete_language(string language_code);
|
Status do_delete_language(string language_code);
|
||||||
|
|
||||||
void on_result(NetQueryPtr query) override;
|
void on_result(NetQueryPtr query) override;
|
||||||
|
@ -1788,7 +1788,7 @@ class CliClient final : public Actor {
|
|||||||
"DELETED", make_tl_object<td_api::languagePackStringValueDeleted>()));
|
"DELETED", make_tl_object<td_api::languagePackStringValueDeleted>()));
|
||||||
|
|
||||||
send_request(make_tl_object<td_api::setCustomLanguage>(
|
send_request(make_tl_object<td_api::setCustomLanguage>(
|
||||||
make_tl_object<td_api::languageInfo>(language_code, name, native_name), std::move(strings)));
|
make_tl_object<td_api::languageInfo>(language_code, name, native_name, 3), std::move(strings)));
|
||||||
} else if (op == "sclsv" || op == "sclsp" || op == "sclsd") {
|
} else if (op == "sclsv" || op == "sclsp" || op == "sclsd") {
|
||||||
string language_code;
|
string language_code;
|
||||||
string key;
|
string key;
|
||||||
|
Loading…
Reference in New Issue
Block a user