diff --git a/core/object/object.cpp b/core/object/object.cpp index e33ebf2d3..dec91aa7e 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -1593,6 +1593,14 @@ StringName Object::tr(const StringName &p_message) const { return TranslationServer::get_singleton()->translate(p_message); } +StringName Object::trt(const StringName &p_message, const String &p_locale) const { + if (!_can_translate || !TranslationServer::get_singleton()) { + return p_message; + } + + return TranslationServer::get_singleton()->translate_to(p_message, p_locale); +} + void Object::_clear_internal_resource_paths(const Variant &p_var) { switch (p_var.get_type()) { case Variant::OBJECT: { @@ -1732,6 +1740,7 @@ void Object::_bind_methods() { ClassDB::bind_method(D_METHOD("set_message_translation", "enable"), &Object::set_message_translation); ClassDB::bind_method(D_METHOD("can_translate_messages"), &Object::can_translate_messages); ClassDB::bind_method(D_METHOD("tr", "message"), &Object::tr); + ClassDB::bind_method(D_METHOD("trt", "message", "locale"), &Object::trt); ClassDB::bind_method(D_METHOD("is_queued_for_deletion"), &Object::is_queued_for_deletion); ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free); diff --git a/core/object/object.h b/core/object/object.h index a0e38690d..ddc415fef 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -777,6 +777,7 @@ public: virtual void get_argument_options(const StringName &p_function, int p_idx, List *r_options) const; StringName tr(const StringName &p_message) const; // translate message (internationalization) + StringName trt(const StringName &p_message, const String &p_locale) const; // translate message (translate_to) (internationalization) bool _is_queued_for_deletion; // set to true by SceneTree::queue_delete() bool is_queued_for_deletion() const; diff --git a/core/string/translation.cpp b/core/string/translation.cpp index dba618cb8..cdb1856f5 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -30,9 +30,9 @@ #include "translation.h" +#include "core/config/project_settings.h" #include "core/io/resource_loader.h" #include "core/os/os.h" -#include "core/config/project_settings.h" // ISO 639-1 language codes (and a couple of three-letter ISO 639-2 codes), // with the addition of glibc locales with their regional identifiers. @@ -1149,6 +1149,62 @@ StringName TranslationServer::translate(const StringName &p_message) const { return res; } +StringName TranslationServer::translate_to(const StringName &p_message, const String &p_locale) const { + // Match given message against the translation catalog for the project locale. + + if (!enabled) { + return p_message; + } + + ERR_FAIL_COND_V_MSG(p_locale.length() < 2, p_message, "Could not translate message as configured locale '" + p_locale + "' is invalid."); + + // Locale can be of the form 'll_CC', i.e. language code and regional code, + // e.g. 'en_US', 'en_GB', etc. It might also be simply 'll', e.g. 'en'. + // To find the relevant translation, we look for those with locale starting + // with the language code, and then if any is an exact match for the long + // form. If not found, we fall back to a near match (another locale with + // same language code). + + StringName res; + String lang = get_language_code(p_locale); + bool near_match = false; + + for (const RBSet>::Element *E = translations.front(); E; E = E->next()) { + const Ref &t = E->get(); + ERR_FAIL_COND_V(t.is_null(), p_message); + String l = t->get_locale(); + + bool exact_match = (l == p_locale); + if (!exact_match) { + if (near_match) { + continue; // Only near-match once, but keep looking for exact matches. + } + if (get_language_code(l) != lang) { + continue; // Language code does not match. + } + } + + StringName r = t->get_message(p_message); + if (!r) { + continue; + } + res = r; + + if (exact_match) { + break; + } else { + near_match = true; + } + } + + if (!res) { + // fall back to the app's default locale + return translate(p_message); + } + + return res; +} + TranslationServer *TranslationServer::singleton = nullptr; bool TranslationServer::_load_translations(const String &p_from) { @@ -1233,6 +1289,7 @@ void TranslationServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_locale_name", "locale"), &TranslationServer::get_locale_name); ClassDB::bind_method(D_METHOD("translate", "message"), &TranslationServer::translate); + ClassDB::bind_method(D_METHOD("translate_to", "message", "locale"), &TranslationServer::translate_to); ClassDB::bind_method(D_METHOD("add_translation", "translation"), &TranslationServer::add_translation); ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationServer::remove_translation); diff --git a/core/string/translation.h b/core/string/translation.h index 9f374de9d..042a9dda7 100644 --- a/core/string/translation.h +++ b/core/string/translation.h @@ -98,6 +98,7 @@ public: void remove_translation(const Ref &p_translation); StringName translate(const StringName &p_message) const; + StringName translate_to(const StringName &p_message, const String &p_locale) const; static Vector get_all_locales(); static Vector get_all_locale_names(); diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml index fd50c52dd..f81d6ac39 100644 --- a/doc/classes/NavigationAgent2D.xml +++ b/doc/classes/NavigationAgent2D.xml @@ -211,7 +211,7 @@ The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithm, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. A too high value will slow down agents movement considerably. Must be positive. - + The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithm, are safe with respect to static avoidance obstacles. The larger the number, the sooner the agent will respond to static avoidance obstacles, but less freedom in choosing its velocities. A too high value will slow down agents movement considerably. Must be positive. diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index b542ac743..4b29b52a6 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -97,7 +97,7 @@ - Returns [code]true[/code] if the object can translate strings. See [method set_message_translation] and [method tr]. + Returns [code]true[/code] if the object can translate strings. See [method set_message_translation] and [method tr] and [method trt]. @@ -370,6 +370,17 @@ + Translates a message using translation catalogs configured in the Project Settings. + Only works if message translation is enabled (which it is by default), otherwise it returns the [code]message[/code] unchanged. See [method set_message_translation]. + + + + + + + + Translates a message to the specified locale, of if it can't to the application's default locale using translation catalogs configured in the Project Settings. + Only works if message translation is enabled (which it is by default), otherwise it returns the [code]message[/code] unchanged. See [method set_message_translation]. diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml index badbe369d..4d940a533 100644 --- a/doc/classes/TranslationServer.xml +++ b/doc/classes/TranslationServer.xml @@ -63,6 +63,15 @@ + Returns the current locale's translation for the given message (key). + + + + + + + + Returns the passed in locale's translation, or the current locale's translation if it can't be found for the given message (key). diff --git a/modules/http_server_simple/doc_classes/WebServerSimple.xml b/modules/http_server_simple/doc_classes/WebServerSimple.xml index c508e4c74..b0068f803 100644 --- a/modules/http_server_simple/doc_classes/WebServerSimple.xml +++ b/modules/http_server_simple/doc_classes/WebServerSimple.xml @@ -27,7 +27,7 @@ - + @@ -39,6 +39,8 @@ + +