diff options
Diffstat (limited to 'core/string')
-rw-r--r-- | core/string/optimized_translation.cpp | 33 | ||||
-rw-r--r-- | core/string/optimized_translation.h | 1 | ||||
-rw-r--r-- | core/string/translation.cpp | 55 | ||||
-rw-r--r-- | core/string/translation.h | 2 | ||||
-rw-r--r-- | core/string/translation_po.cpp | 17 | ||||
-rw-r--r-- | core/string/translation_po.h | 1 | ||||
-rw-r--r-- | core/string/ustring.cpp | 37 | ||||
-rw-r--r-- | core/string/ustring.h | 4 |
8 files changed, 123 insertions, 27 deletions
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp index b130c2fc79..2fb3b54e27 100644 --- a/core/string/optimized_translation.cpp +++ b/core/string/optimized_translation.cpp @@ -267,6 +267,39 @@ StringName OptimizedTranslation::get_message(const StringName &p_src_text, const } } +Vector<String> OptimizedTranslation::get_translated_message_list() const { + Vector<String> msgs; + + const int *htr = hash_table.ptr(); + const uint32_t *htptr = (const uint32_t *)&htr[0]; + const int *btr = bucket_table.ptr(); + const uint32_t *btptr = (const uint32_t *)&btr[0]; + const uint8_t *sr = strings.ptr(); + const char *sptr = (const char *)&sr[0]; + + for (int i = 0; i < hash_table.size(); i++) { + uint32_t p = htptr[i]; + if (p != 0xFFFFFFFF) { + const Bucket &bucket = *(const Bucket *)&btptr[p]; + for (int j = 0; j < bucket.size; j++) { + if (bucket.elem[j].comp_size == bucket.elem[j].uncomp_size) { + String rstr; + rstr.parse_utf8(&sptr[bucket.elem[j].str_offset], bucket.elem[j].uncomp_size); + msgs.push_back(rstr); + } else { + CharString uncomp; + uncomp.resize(bucket.elem[j].uncomp_size + 1); + smaz_decompress(&sptr[bucket.elem[j].str_offset], bucket.elem[j].comp_size, uncomp.ptrw(), bucket.elem[j].uncomp_size); + String rstr; + rstr.parse_utf8(uncomp.get_data()); + msgs.push_back(rstr); + } + } + } + } + return msgs; +} + StringName OptimizedTranslation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const { // The use of plurals translation is not yet supported in OptimizedTranslation. return get_message(p_src_text, p_context); diff --git a/core/string/optimized_translation.h b/core/string/optimized_translation.h index f3dbfe8f5c..1cd12782d0 100644 --- a/core/string/optimized_translation.h +++ b/core/string/optimized_translation.h @@ -81,6 +81,7 @@ protected: public: virtual StringName get_message(const StringName &p_src_text, const StringName &p_context = "") const override; //overridable for other implementations virtual StringName get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context = "") const override; + virtual Vector<String> get_translated_message_list() const override; void generate(const Ref<Translation> &p_from); OptimizedTranslation() {} diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 9ee7f2b17b..d1ac91957a 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -59,6 +59,18 @@ Vector<String> Translation::_get_message_list() const { return msgs; } +Vector<String> Translation::get_translated_message_list() const { + Vector<String> msgs; + msgs.resize(translation_map.size()); + int idx = 0; + for (const KeyValue<StringName, StringName> &E : translation_map) { + msgs.set(idx, E.value); + idx += 1; + } + + return msgs; +} + void Translation::_set_messages(const Dictionary &p_messages) { List<Variant> keys; p_messages.get_key_list(&keys); @@ -140,6 +152,7 @@ void Translation::_bind_methods() { ClassDB::bind_method(D_METHOD("get_plural_message", "src_message", "src_plural_message", "n", "context"), &Translation::get_plural_message, DEFVAL("")); ClassDB::bind_method(D_METHOD("erase_message", "src_message", "context"), &Translation::erase_message, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_message_list"), &Translation::_get_message_list); + ClassDB::bind_method(D_METHOD("get_translated_message_list"), &Translation::get_translated_message_list); ClassDB::bind_method(D_METHOD("get_message_count"), &Translation::get_message_count); ClassDB::bind_method(D_METHOD("_set_messages", "messages"), &Translation::_set_messages); ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages); @@ -293,6 +306,10 @@ void TranslationServer::init_locale_info() { } String TranslationServer::standardize_locale(const String &p_locale) const { + return _standardize_locale(p_locale, false); +} + +String TranslationServer::_standardize_locale(const String &p_locale, bool p_add_defaults) const { // Replaces '-' with '_' for macOS style locales. String univ_locale = p_locale.replace("-", "_"); @@ -354,24 +371,26 @@ String TranslationServer::standardize_locale(const String &p_locale) const { } // Add script code base on language and country codes for some ambiguous cases. - if (script_name.is_empty()) { - for (int i = 0; i < locale_script_info.size(); i++) { - const LocaleScriptInfo &info = locale_script_info[i]; - if (info.name == lang_name) { - if (country_name.is_empty() || info.supported_countries.has(country_name)) { - script_name = info.script; - break; + if (p_add_defaults) { + if (script_name.is_empty()) { + for (int i = 0; i < locale_script_info.size(); i++) { + const LocaleScriptInfo &info = locale_script_info[i]; + if (info.name == lang_name) { + if (country_name.is_empty() || info.supported_countries.has(country_name)) { + script_name = info.script; + break; + } } } } - } - if (!script_name.is_empty() && country_name.is_empty()) { - // Add conntry code based on script for some ambiguous cases. - for (int i = 0; i < locale_script_info.size(); i++) { - const LocaleScriptInfo &info = locale_script_info[i]; - if (info.name == lang_name && info.script == script_name) { - country_name = info.default_country; - break; + if (!script_name.is_empty() && country_name.is_empty()) { + // Add conntry code based on script for some ambiguous cases. + for (int i = 0; i < locale_script_info.size(); i++) { + const LocaleScriptInfo &info = locale_script_info[i]; + if (info.name == lang_name && info.script == script_name) { + country_name = info.default_country; + break; + } } } } @@ -391,8 +410,8 @@ String TranslationServer::standardize_locale(const String &p_locale) const { } int TranslationServer::compare_locales(const String &p_locale_a, const String &p_locale_b) const { - String locale_a = standardize_locale(p_locale_a); - String locale_b = standardize_locale(p_locale_b); + String locale_a = _standardize_locale(p_locale_a, true); + String locale_b = _standardize_locale(p_locale_b, true); if (locale_a == locale_b) { // Exact match. @@ -628,7 +647,7 @@ TranslationServer *TranslationServer::singleton = nullptr; bool TranslationServer::_load_translations(const String &p_from) { if (ProjectSettings::get_singleton()->has_setting(p_from)) { - const Vector<String> &translation_names = ProjectSettings::get_singleton()->get(p_from); + const Vector<String> &translation_names = GLOBAL_GET(p_from); int tcount = translation_names.size(); diff --git a/core/string/translation.h b/core/string/translation.h index 3f97a8d4fc..5e8344baac 100644 --- a/core/string/translation.h +++ b/core/string/translation.h @@ -64,6 +64,7 @@ public: virtual void erase_message(const StringName &p_src_text, const StringName &p_context = ""); virtual void get_message_list(List<StringName> *r_messages) const; virtual int get_message_count() const; + virtual Vector<String> get_translated_message_list() const; Translation() {} }; @@ -102,6 +103,7 @@ class TranslationServer : public Object { static TranslationServer *singleton; bool _load_translations(const String &p_from); + String _standardize_locale(const String &p_locale, bool p_add_defaults) const; StringName _get_message_from_translations(const StringName &p_message, const StringName &p_context, const String &p_locale, bool plural, const String &p_message_plural = "", int p_n = 0) const; diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index fa656b634d..724c1d42bc 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -103,6 +103,23 @@ void TranslationPO::_set_messages(const Dictionary &p_messages) { } } +Vector<String> TranslationPO::get_translated_message_list() const { + Vector<String> msgs; + for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) { + if (E.key != StringName()) { + continue; + } + + for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) { + for (const StringName &E3 : E2.value) { + msgs.push_back(E3); + } + } + } + + return msgs; +} + Vector<String> TranslationPO::_get_message_list() const { // Return all keys in translation_map. diff --git a/core/string/translation_po.h b/core/string/translation_po.h index 7d63af2246..c50ea85744 100644 --- a/core/string/translation_po.h +++ b/core/string/translation_po.h @@ -70,6 +70,7 @@ protected: static void _bind_methods(); public: + Vector<String> get_translated_message_list() const override; void get_message_list(List<StringName> *r_messages) const override; int get_message_count() const override; void add_message(const StringName &p_src_text, const StringName &p_xlated_text, const StringName &p_context = "") override; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index c86c8316fe..2ba389fc4d 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1180,9 +1180,14 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p int len = length(); while (true) { - int end = find(p_splitter, from); - if (end < 0) { - end = len; + int end; + if (p_splitter.is_empty()) { + end = from + 1; + } else { + end = find(p_splitter, from); + if (end < 0) { + end = len; + } } if (p_allow_empty || (end > from)) { if (p_maxsplit <= 0) { @@ -1223,7 +1228,15 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int break; } - int left_edge = rfind(p_splitter, remaining_len - p_splitter.length()); + int left_edge; + if (p_splitter.is_empty()) { + left_edge = remaining_len - 1; + if (left_edge == 0) { + left_edge--; // Skip to the < 0 condition. + } + } else { + left_edge = rfind(p_splitter, remaining_len - p_splitter.length()); + } if (left_edge < 0) { // no more splitters, we're done @@ -1447,15 +1460,25 @@ String String::num(double p_num, int p_decimals) { fmt[5] = 'f'; fmt[6] = 0; } - char buf[256]; + // if we want to convert a double with as much decimal places as as + // DBL_MAX or DBL_MIN then we would theoretically need a buffer of at least + // DBL_MAX_10_EXP + 2 for DBL_MAX and DBL_MAX_10_EXP + 4 for DBL_MIN. + // BUT those values where still giving me exceptions, so I tested from + // DBL_MAX_10_EXP + 10 incrementing one by one and DBL_MAX_10_EXP + 17 (325) + // was the first buffer size not to throw an exception + char buf[325]; #if defined(__GNUC__) || defined(_MSC_VER) - snprintf(buf, 256, fmt, p_num); + // PLEASE NOTE that, albeit vcrt online reference states that snprintf + // should safely truncate the output to the given buffer size, we have + // found a case where this is not true, so we should create a buffer + // as big as needed + snprintf(buf, 325, fmt, p_num); #else sprintf(buf, fmt, p_num); #endif - buf[255] = 0; + buf[324] = 0; //destroy trailing zeroes { bool period = false; diff --git a/core/string/ustring.h b/core/string/ustring.h index 4b6568a502..8af74584f3 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -345,8 +345,8 @@ public: String get_slice(String p_splitter, int p_slice) const; String get_slicec(char32_t p_splitter, int p_slice) const; - Vector<String> split(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const; - Vector<String> rsplit(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const; + Vector<String> split(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; + Vector<String> rsplit(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> split_spaces() const; Vector<float> split_floats(const String &p_splitter, bool p_allow_empty = true) const; Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const; |