summaryrefslogtreecommitdiff
path: root/core/string
diff options
context:
space:
mode:
Diffstat (limited to 'core/string')
-rw-r--r--core/string/optimized_translation.cpp6
-rw-r--r--core/string/translation.cpp34
-rw-r--r--core/string/translation.h18
-rw-r--r--core/string/translation_po.cpp40
-rw-r--r--core/string/ustring.cpp63
5 files changed, 102 insertions, 59 deletions
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp
index 93429744fc..07302cc8c3 100644
--- a/core/string/optimized_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -53,7 +53,7 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
int size = Math::larger_prime(keys.size());
Vector<Vector<Pair<int, CharString>>> buckets;
- Vector<Map<uint32_t, int>> table;
+ Vector<HashMap<uint32_t, int>> table;
Vector<uint32_t> hfunc_table;
Vector<CompressedString> compressed;
@@ -108,7 +108,7 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
for (int i = 0; i < size; i++) {
const Vector<Pair<int, CharString>> &b = buckets[i];
- Map<uint32_t, int> &t = table.write[i];
+ HashMap<uint32_t, int> &t = table.write[i];
if (b.size() == 0) {
continue;
@@ -147,7 +147,7 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
int btindex = 0;
for (int i = 0; i < size; i++) {
- const Map<uint32_t, int> &t = table[i];
+ const HashMap<uint32_t, int> &t = table[i];
if (t.size() == 0) {
htw[i] = 0xFFFFFFFF; //nothing
continue;
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index d6d361b5f1..c64f815563 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -95,12 +95,12 @@ StringName Translation::get_message(const StringName &p_src_text, const StringNa
WARN_PRINT("Translation class doesn't handle context. Using context in get_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles context, such as TranslationPO class");
}
- const Map<StringName, StringName>::Element *E = translation_map.find(p_src_text);
+ HashMap<StringName, StringName>::ConstIterator E = translation_map.find(p_src_text);
if (!E) {
return StringName();
}
- return E->get();
+ return E->value;
}
StringName Translation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const {
@@ -215,12 +215,12 @@ static _character_accent_pair _character_to_accented[] = {
Vector<TranslationServer::LocaleScriptInfo> TranslationServer::locale_script_info;
-Map<String, String> TranslationServer::language_map;
-Map<String, String> TranslationServer::script_map;
-Map<String, String> TranslationServer::locale_rename_map;
-Map<String, String> TranslationServer::country_name_map;
-Map<String, String> TranslationServer::variant_map;
-Map<String, String> TranslationServer::country_rename_map;
+HashMap<String, String> TranslationServer::language_map;
+HashMap<String, String> TranslationServer::script_map;
+HashMap<String, String> TranslationServer::locale_rename_map;
+HashMap<String, String> TranslationServer::country_name_map;
+HashMap<String, String> TranslationServer::variant_map;
+HashMap<String, String> TranslationServer::country_rename_map;
void TranslationServer::init_locale_info() {
// Init locale info.
@@ -452,8 +452,8 @@ String TranslationServer::get_locale_name(const String &p_locale) const {
Vector<String> TranslationServer::get_all_languages() const {
Vector<String> languages;
- for (const Map<String, String>::Element *E = language_map.front(); E; E = E->next()) {
- languages.push_back(E->key());
+ for (const KeyValue<String, String> &E : language_map) {
+ languages.push_back(E.key);
}
return languages;
@@ -466,8 +466,8 @@ String TranslationServer::get_language_name(const String &p_language) const {
Vector<String> TranslationServer::get_all_scripts() const {
Vector<String> scripts;
- for (const Map<String, String>::Element *E = script_map.front(); E; E = E->next()) {
- scripts.push_back(E->key());
+ for (const KeyValue<String, String> &E : script_map) {
+ scripts.push_back(E.key);
}
return scripts;
@@ -480,8 +480,8 @@ String TranslationServer::get_script_name(const String &p_script) const {
Vector<String> TranslationServer::get_all_countries() const {
Vector<String> countries;
- for (const Map<String, String>::Element *E = country_name_map.front(); E; E = E->next()) {
- countries.push_back(E->key());
+ for (const KeyValue<String, String> &E : country_name_map) {
+ countries.push_back(E.key);
}
return countries;
@@ -507,7 +507,7 @@ String TranslationServer::get_locale() const {
Array TranslationServer::get_loaded_locales() const {
Array locales;
- for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) {
+ for (const RBSet<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) {
const Ref<Translation> &t = E->get();
ERR_FAIL_COND_V(t.is_null(), Array());
String l = t->get_locale();
@@ -530,7 +530,7 @@ Ref<Translation> TranslationServer::get_translation_object(const String &p_local
Ref<Translation> res;
int best_score = 0;
- for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) {
+ for (const RBSet<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) {
const Ref<Translation> &t = E->get();
ERR_FAIL_COND_V(t.is_null(), nullptr);
String l = t->get_locale();
@@ -599,7 +599,7 @@ StringName TranslationServer::_get_message_from_translations(const StringName &p
StringName res;
int best_score = 0;
- for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) {
+ for (const RBSet<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) {
const Ref<Translation> &t = E->get();
ERR_FAIL_COND_V(t.is_null(), p_message);
String l = t->get_locale();
diff --git a/core/string/translation.h b/core/string/translation.h
index ded6ed5925..f58f6f91a2 100644
--- a/core/string/translation.h
+++ b/core/string/translation.h
@@ -41,7 +41,7 @@ class Translation : public Resource {
RES_BASE_EXTENSION("translation");
String locale = "en";
- Map<StringName, StringName> translation_map;
+ HashMap<StringName, StringName> translation_map;
virtual Vector<String> _get_message_list() const;
virtual Dictionary _get_messages() const;
@@ -74,7 +74,7 @@ class TranslationServer : public Object {
String locale = "en";
String fallback;
- Set<Ref<Translation>> translations;
+ RBSet<Ref<Translation>> translations;
Ref<Translation> tool_translation;
Ref<Translation> doc_translation;
@@ -111,16 +111,16 @@ class TranslationServer : public Object {
String name;
String script;
String default_country;
- Set<String> supported_countries;
+ RBSet<String> supported_countries;
};
static Vector<LocaleScriptInfo> locale_script_info;
- static Map<String, String> language_map;
- static Map<String, String> script_map;
- static Map<String, String> locale_rename_map;
- static Map<String, String> country_name_map;
- static Map<String, String> country_rename_map;
- static Map<String, String> variant_map;
+ static HashMap<String, String> language_map;
+ static HashMap<String, String> script_map;
+ static HashMap<String, String> locale_rename_map;
+ static HashMap<String, String> country_name_map;
+ static HashMap<String, String> country_rename_map;
+ static HashMap<String, String> variant_map;
void init_locale_info();
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index 3f94e064ec..fa656b634d 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -70,21 +70,14 @@ Dictionary TranslationPO::_get_messages() const {
Dictionary d;
- List<StringName> context_l;
- translation_map.get_key_list(&context_l);
- for (const StringName &ctx : context_l) {
- const HashMap<StringName, Vector<StringName>> &id_str_map = translation_map[ctx];
-
+ for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) {
Dictionary d2;
- List<StringName> id_l;
- id_str_map.get_key_list(&id_l);
- // Save list of id and strs associated with a context in a temporary dictionary.
- for (List<StringName>::Element *E2 = id_l.front(); E2; E2 = E2->next()) {
- StringName id = E2->get();
- d2[id] = id_str_map[id];
+
+ for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) {
+ d2[E2.key] = E2.value;
}
- d[ctx] = d2;
+ d[E.key] = d2;
}
return d;
@@ -274,31 +267,24 @@ void TranslationPO::get_message_list(List<StringName> *r_messages) const {
// OptimizedTranslation uses this function to get the list of msgid.
// Return all the keys of translation_map under "" context.
- List<StringName> context_l;
- translation_map.get_key_list(&context_l);
-
- for (const StringName &E : context_l) {
- if (String(E) != "") {
+ for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) {
+ if (E.key != StringName()) {
continue;
}
- List<StringName> msgid_l;
- translation_map[E].get_key_list(&msgid_l);
-
- for (List<StringName>::Element *E2 = msgid_l.front(); E2; E2 = E2->next()) {
- r_messages->push_back(E2->get());
+ for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) {
+ r_messages->push_back(E2.key);
}
}
}
int TranslationPO::get_message_count() const {
- List<StringName> context_l;
- translation_map.get_key_list(&context_l);
-
int count = 0;
- for (const StringName &E : context_l) {
- count += translation_map[E].size();
+
+ for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) {
+ count += E.value.size();
}
+
return count;
}
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 5d998d22d4..015dfbc651 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -4779,6 +4779,17 @@ Vector<uint8_t> String::to_utf32_buffer() const {
}
#ifdef TOOLS_ENABLED
+/**
+ * "Tools TRanslate". Performs string replacement for internationalization
+ * within the editor. A translation context can optionally be specified to
+ * disambiguate between identical source strings in translations. When
+ * placeholders are desired, use `vformat(TTR("Example: %s"), some_string)`.
+ * If a string mentions a quantity (and may therefore need a dynamic plural form),
+ * use `TTRN()` instead of `TTR()`.
+ *
+ * NOTE: Only use `TTR()` in editor-only code (typically within the `editor/` folder).
+ * For translations that can be supplied by exported projects, use `RTR()` instead.
+ */
String TTR(const String &p_text, const String &p_context) {
if (TranslationServer::get_singleton()) {
return TranslationServer::get_singleton()->tool_translate(p_text, p_context);
@@ -4787,6 +4798,18 @@ String TTR(const String &p_text, const String &p_context) {
return p_text;
}
+/**
+ * "Tools TRanslate for N items". Performs string replacement for
+ * internationalization within the editor. A translation context can optionally
+ * be specified to disambiguate between identical source strings in
+ * translations. Use `TTR()` if the string doesn't need dynamic plural form.
+ * When placeholders are desired, use
+ * `vformat(TTRN("%d item", "%d items", some_integer), some_integer)`.
+ * The placeholder must be present in both strings to avoid run-time warnings in `vformat()`.
+ *
+ * NOTE: Only use `TTRN()` in editor-only code (typically within the `editor/` folder).
+ * For translations that can be supplied by exported projects, use `RTRN()` instead.
+ */
String TTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {
if (TranslationServer::get_singleton()) {
return TranslationServer::get_singleton()->tool_translate_plural(p_text, p_text_plural, p_n, p_context);
@@ -4799,9 +4822,10 @@ String TTRN(const String &p_text, const String &p_text_plural, int p_n, const St
return p_text_plural;
}
-/* DTR and DTRN are used for the documentation, handling descriptions extracted
- * from the XML.
- * They also replace `$DOCS_URL` with the actual URL to the documentation's branch,
+/**
+ * "Docs TRanslate". Used for the editor class reference documentation,
+ * handling descriptions extracted from the XML.
+ * It also replaces `$DOCS_URL` with the actual URL to the documentation's branch,
* to allow dehardcoding it in the XML and doing proper substitutions everywhere.
*/
String DTR(const String &p_text, const String &p_context) {
@@ -4815,6 +4839,12 @@ String DTR(const String &p_text, const String &p_context) {
return text.replace("$DOCS_URL", VERSION_DOCS_URL);
}
+/**
+ * "Docs TRanslate for N items". Used for the editor class reference documentation
+ * (with support for plurals), handling descriptions extracted from the XML.
+ * It also replaces `$DOCS_URL` with the actual URL to the documentation's branch,
+ * to allow dehardcoding it in the XML and doing proper substitutions everywhere.
+ */
String DTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {
const String text = p_text.dedent().strip_edges();
const String text_plural = p_text_plural.dedent().strip_edges();
@@ -4831,6 +4861,19 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St
}
#endif
+/**
+ * "Run-time TRanslate". Performs string replacement for internationalization
+ * within a running project. The translation string must be supplied by the
+ * project, as Godot does not provide built-in translations for `RTR()` strings
+ * to keep binary size low. A translation context can optionally be specified to
+ * disambiguate between identical source strings in translations. When
+ * placeholders are desired, use `vformat(RTR("Example: %s"), some_string)`.
+ * If a string mentions a quantity (and may therefore need a dynamic plural form),
+ * use `RTRN()` instead of `RTR()`.
+ *
+ * NOTE: Do not use `RTR()` in editor-only code (typically within the `editor/`
+ * folder). For editor translations, use `TTR()` instead.
+ */
String RTR(const String &p_text, const String &p_context) {
if (TranslationServer::get_singleton()) {
String rtr = TranslationServer::get_singleton()->tool_translate(p_text, p_context);
@@ -4844,6 +4887,20 @@ String RTR(const String &p_text, const String &p_context) {
return p_text;
}
+/**
+ * "Run-time TRanslate for N items". Performs string replacement for
+ * internationalization within a running project. The translation string must be
+ * supplied by the project, as Godot does not provide built-in translations for
+ * `RTRN()` strings to keep binary size low. A translation context can
+ * optionally be specified to disambiguate between identical source strings in
+ * translations. Use `RTR()` if the string doesn't need dynamic plural form.
+ * When placeholders are desired, use
+ * `vformat(RTRN("%d item", "%d items", some_integer), some_integer)`.
+ * The placeholder must be present in both strings to avoid run-time warnings in `vformat()`.
+ *
+ * NOTE: Do not use `RTRN()` in editor-only code (typically within the `editor/`
+ * folder). For editor translations, use `TTRN()` instead.
+ */
String RTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {
if (TranslationServer::get_singleton()) {
String rtr = TranslationServer::get_singleton()->tool_translate_plural(p_text, p_text_plural, p_n, p_context);