Added translate_to() method to TranslationServer, and trt() method to Object. This let's you transalte strings into specific (noon app wide) locales.

This commit is contained in:
Relintai 2023-08-29 22:02:31 +02:00
parent bc21dc55a7
commit 65d4c57233
8 changed files with 94 additions and 4 deletions

View File

@ -1593,6 +1593,14 @@ StringName Object::tr(const StringName &p_message) const {
return TranslationServer::get_singleton()->translate(p_message); 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) { void Object::_clear_internal_resource_paths(const Variant &p_var) {
switch (p_var.get_type()) { switch (p_var.get_type()) {
case Variant::OBJECT: { 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("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("can_translate_messages"), &Object::can_translate_messages);
ClassDB::bind_method(D_METHOD("tr", "message"), &Object::tr); 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("is_queued_for_deletion"), &Object::is_queued_for_deletion);
ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free); ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free);

View File

@ -777,6 +777,7 @@ public:
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
StringName tr(const StringName &p_message) const; // translate message (internationalization) 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; // set to true by SceneTree::queue_delete()
bool is_queued_for_deletion() const; bool is_queued_for_deletion() const;

View File

@ -30,9 +30,9 @@
#include "translation.h" #include "translation.h"
#include "core/config/project_settings.h"
#include "core/io/resource_loader.h" #include "core/io/resource_loader.h"
#include "core/os/os.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), // 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. // with the addition of glibc locales with their regional identifiers.
@ -1149,6 +1149,62 @@ StringName TranslationServer::translate(const StringName &p_message) const {
return res; 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<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();
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; TranslationServer *TranslationServer::singleton = nullptr;
bool TranslationServer::_load_translations(const String &p_from) { 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("get_locale_name", "locale"), &TranslationServer::get_locale_name);
ClassDB::bind_method(D_METHOD("translate", "message"), &TranslationServer::translate); 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("add_translation", "translation"), &TranslationServer::add_translation);
ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationServer::remove_translation); ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationServer::remove_translation);

View File

@ -98,6 +98,7 @@ public:
void remove_translation(const Ref<Translation> &p_translation); void remove_translation(const Ref<Translation> &p_translation);
StringName translate(const StringName &p_message) const; StringName translate(const StringName &p_message) const;
StringName translate_to(const StringName &p_message, const String &p_locale) const;
static Vector<String> get_all_locales(); static Vector<String> get_all_locales();
static Vector<String> get_all_locale_names(); static Vector<String> get_all_locale_names();

View File

@ -211,7 +211,7 @@
<member name="time_horizon_agents" type="float" setter="set_time_horizon_agents" getter="get_time_horizon_agents" default="1.0"> <member name="time_horizon_agents" type="float" setter="set_time_horizon_agents" getter="get_time_horizon_agents" default="1.0">
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 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.
</member> </member>
<member name="time_horizon_obstacles" type="float" setter="set_time_horizon_obstacles" getter="get_time_horizon_obstacles" default="8.85252e-34"> <member name="time_horizon_obstacles" type="float" setter="set_time_horizon_obstacles" getter="get_time_horizon_obstacles" default="0.0">
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. 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.
</member> </member>
<member name="velocity" type="Vector2" setter="set_velocity" getter="get_velocity" default="Vector2( 0, 0 )"> <member name="velocity" type="Vector2" setter="set_velocity" getter="get_velocity" default="Vector2( 0, 0 )">

View File

@ -97,7 +97,7 @@
<method name="can_translate_messages" qualifiers="const"> <method name="can_translate_messages" qualifiers="const">
<return type="bool" /> <return type="bool" />
<description> <description>
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].
</description> </description>
</method> </method>
<method name="cancel_free"> <method name="cancel_free">
@ -370,6 +370,17 @@
<return type="StringName" /> <return type="StringName" />
<argument index="0" name="message" type="StringName" /> <argument index="0" name="message" type="StringName" />
<description> <description>
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].
</description>
</method>
<method name="trt" qualifiers="const">
<return type="StringName" />
<argument index="0" name="message" type="StringName" />
<argument index="1" name="locale" type="String" />
<description>
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].
</description> </description>
</method> </method>
</methods> </methods>

View File

@ -63,6 +63,15 @@
<return type="StringName" /> <return type="StringName" />
<argument index="0" name="message" type="StringName" /> <argument index="0" name="message" type="StringName" />
<description> <description>
Returns the current locale's translation for the given message (key).
</description>
</method>
<method name="translate_to" qualifiers="const">
<return type="StringName" />
<argument index="0" name="message" type="StringName" />
<argument index="1" name="locale" type="String" />
<description>
Returns the passed in locale's translation, or the current locale's translation if it can't be found for the given message (key).
</description> </description>
</method> </method>
</methods> </methods>

View File

@ -27,7 +27,7 @@
</method> </method>
</methods> </methods>
<members> <members>
<member name="bind_host" type="String" setter="set_bind_host" getter="get_bind_host" default="&quot;127.0.0.1&quot;"> <member name="bind_host" type="String" setter="set_bind_host" getter="get_bind_host" default="&quot;0.0.0.0&quot;">
</member> </member>
<member name="bind_port" type="int" setter="set_bind_port" getter="get_bind_port" default="8080"> <member name="bind_port" type="int" setter="set_bind_port" getter="get_bind_port" default="8080">
</member> </member>
@ -39,6 +39,8 @@
</member> </member>
<member name="ssl_key" type="String" setter="set_ssl_key" getter="get_ssl_key" default="&quot;&quot;"> <member name="ssl_key" type="String" setter="set_ssl_key" getter="get_ssl_key" default="&quot;&quot;">
</member> </member>
<member name="start_on_ready" type="bool" setter="set_start_on_ready" getter="get_start_on_ready" default="false">
</member>
<member name="use_poll_thread" type="bool" setter="set_use_poll_thread" getter="get_use_poll_thread" default="true"> <member name="use_poll_thread" type="bool" setter="set_use_poll_thread" getter="get_use_poll_thread" default="true">
</member> </member>
<member name="use_ssl" type="bool" setter="set_use_ssl" getter="get_use_ssl" default="false"> <member name="use_ssl" type="bool" setter="set_use_ssl" getter="get_use_ssl" default="false">