mirror of
https://github.com/godotengine/godot.git
synced 2024-11-21 11:32:13 +00:00
Make editor use translation domains
How editor plugins use this feature: 1. Pick a unique translation domain name. 2. `_enter_tree()`: load translations into that translation domain. 3. Call `set_translation_domain()` for its root UI node. 4. `_exit_tree()`: remove that translation domain. Plugins can also set the translation domain to `godot.editor` for nested nodes that should use editor translations. `EditorFileDialog` automatically does this.
This commit is contained in:
parent
c5d147b9b5
commit
818acb4290
@ -1540,15 +1540,6 @@ String Object::tr(const StringName &p_message, const StringName &p_context) cons
|
||||
return p_message;
|
||||
}
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
|
||||
String tr_msg = TranslationServer::get_singleton()->extractable_translate(p_message, p_context);
|
||||
if (!tr_msg.is_empty() && tr_msg != p_message) {
|
||||
return tr_msg;
|
||||
}
|
||||
|
||||
return TranslationServer::get_singleton()->tool_translate(p_message, p_context);
|
||||
}
|
||||
|
||||
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain(get_translation_domain());
|
||||
return domain->translate(p_message, p_context);
|
||||
}
|
||||
@ -1562,15 +1553,6 @@ String Object::tr_n(const StringName &p_message, const StringName &p_message_plu
|
||||
return p_message_plural;
|
||||
}
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
|
||||
String tr_msg = TranslationServer::get_singleton()->extractable_translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
if (!tr_msg.is_empty() && tr_msg != p_message && tr_msg != p_message_plural) {
|
||||
return tr_msg;
|
||||
}
|
||||
|
||||
return TranslationServer::get_singleton()->tool_translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain(get_translation_domain());
|
||||
return domain->translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
@ -525,22 +525,14 @@ void TranslationServer::setup() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void TranslationServer::set_tool_translation(const Ref<Translation> &p_translation) {
|
||||
tool_translation = p_translation;
|
||||
}
|
||||
|
||||
Ref<Translation> TranslationServer::get_tool_translation() const {
|
||||
return tool_translation;
|
||||
}
|
||||
|
||||
String TranslationServer::get_tool_locale() {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
|
||||
if (TranslationServer::get_singleton()->get_tool_translation().is_valid()) {
|
||||
return tool_translation->get_locale();
|
||||
} else {
|
||||
const PackedStringArray &locales = editor_domain->get_loaded_locales();
|
||||
if (locales.is_empty()) {
|
||||
return "en";
|
||||
}
|
||||
return locales[0];
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
@ -555,97 +547,23 @@ String TranslationServer::get_tool_locale() {
|
||||
}
|
||||
|
||||
StringName TranslationServer::tool_translate(const StringName &p_message, const StringName &p_context) const {
|
||||
if (tool_translation.is_valid()) {
|
||||
StringName r = tool_translation->get_message(p_message, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return p_message;
|
||||
return editor_domain->translate(p_message, p_context);
|
||||
}
|
||||
|
||||
StringName TranslationServer::tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
if (tool_translation.is_valid()) {
|
||||
StringName r = tool_translation->get_plural_message(p_message, p_message_plural, p_n, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_n == 1) {
|
||||
return p_message;
|
||||
}
|
||||
return p_message_plural;
|
||||
}
|
||||
|
||||
void TranslationServer::set_property_translation(const Ref<Translation> &p_translation) {
|
||||
property_translation = p_translation;
|
||||
return editor_domain->translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
StringName TranslationServer::property_translate(const StringName &p_message, const StringName &p_context) const {
|
||||
if (property_translation.is_valid()) {
|
||||
StringName r = property_translation->get_message(p_message, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return p_message;
|
||||
}
|
||||
|
||||
void TranslationServer::set_doc_translation(const Ref<Translation> &p_translation) {
|
||||
doc_translation = p_translation;
|
||||
return property_domain->translate(p_message, p_context);
|
||||
}
|
||||
|
||||
StringName TranslationServer::doc_translate(const StringName &p_message, const StringName &p_context) const {
|
||||
if (doc_translation.is_valid()) {
|
||||
StringName r = doc_translation->get_message(p_message, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return p_message;
|
||||
return doc_domain->translate(p_message, p_context);
|
||||
}
|
||||
|
||||
StringName TranslationServer::doc_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
if (doc_translation.is_valid()) {
|
||||
StringName r = doc_translation->get_plural_message(p_message, p_message_plural, p_n, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_n == 1) {
|
||||
return p_message;
|
||||
}
|
||||
return p_message_plural;
|
||||
}
|
||||
|
||||
void TranslationServer::set_extractable_translation(const Ref<Translation> &p_translation) {
|
||||
extractable_translation = p_translation;
|
||||
}
|
||||
|
||||
StringName TranslationServer::extractable_translate(const StringName &p_message, const StringName &p_context) const {
|
||||
if (extractable_translation.is_valid()) {
|
||||
StringName r = extractable_translation->get_message(p_message, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return p_message;
|
||||
}
|
||||
|
||||
StringName TranslationServer::extractable_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
if (extractable_translation.is_valid()) {
|
||||
StringName r = extractable_translation->get_plural_message(p_message, p_message_plural, p_n, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_n == 1) {
|
||||
return p_message;
|
||||
}
|
||||
return p_message_plural;
|
||||
return doc_domain->translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
bool TranslationServer::is_pseudolocalization_enabled() const {
|
||||
@ -890,5 +808,8 @@ void TranslationServer::load_translations() {
|
||||
TranslationServer::TranslationServer() {
|
||||
singleton = this;
|
||||
main_domain.instantiate();
|
||||
editor_domain = get_or_add_domain("godot.editor");
|
||||
property_domain = get_or_add_domain("godot.properties");
|
||||
doc_domain = get_or_add_domain("godot.documentation");
|
||||
init_locale_info();
|
||||
}
|
||||
|
@ -41,13 +41,11 @@ class TranslationServer : public Object {
|
||||
String fallback;
|
||||
|
||||
Ref<TranslationDomain> main_domain;
|
||||
Ref<TranslationDomain> editor_domain;
|
||||
Ref<TranslationDomain> property_domain;
|
||||
Ref<TranslationDomain> doc_domain;
|
||||
HashMap<StringName, Ref<TranslationDomain>> custom_domains;
|
||||
|
||||
Ref<Translation> tool_translation;
|
||||
Ref<Translation> property_translation;
|
||||
Ref<Translation> doc_translation;
|
||||
Ref<Translation> extractable_translation;
|
||||
|
||||
bool enabled = true;
|
||||
|
||||
bool pseudolocalization_enabled = false;
|
||||
@ -133,18 +131,11 @@ public:
|
||||
int compare_locales(const String &p_locale_a, const String &p_locale_b) const;
|
||||
|
||||
String get_tool_locale();
|
||||
void set_tool_translation(const Ref<Translation> &p_translation);
|
||||
Ref<Translation> get_tool_translation() const;
|
||||
StringName tool_translate(const StringName &p_message, const StringName &p_context = "") const;
|
||||
StringName tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
|
||||
void set_property_translation(const Ref<Translation> &p_translation);
|
||||
StringName property_translate(const StringName &p_message, const StringName &p_context = "") const;
|
||||
void set_doc_translation(const Ref<Translation> &p_translation);
|
||||
StringName doc_translate(const StringName &p_message, const StringName &p_context = "") const;
|
||||
StringName doc_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
|
||||
void set_extractable_translation(const Ref<Translation> &p_translation);
|
||||
StringName extractable_translate(const StringName &p_message, const StringName &p_context = "") const;
|
||||
StringName extractable_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
|
||||
|
||||
bool has_domain(const StringName &p_domain) const;
|
||||
Ref<TranslationDomain> get_or_add_domain(const StringName &p_domain);
|
||||
|
@ -5,6 +5,7 @@
|
||||
</brief_description>
|
||||
<description>
|
||||
[TranslationDomain] is a self-contained collection of [Translation] resources. Translations can be added to or removed from it.
|
||||
If you're working with the main translation domain, it is more convenient to use the wrap methods on [TranslationServer].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
@ -5,7 +5,7 @@
|
||||
</brief_description>
|
||||
<description>
|
||||
The translation server is the API backend that manages all language translations.
|
||||
Translations are stored in [TranslationDomain]s, which can be accessed by name. The most commonly used translation domain is the main translation domain, which always exists and can be accessed using an empty [StringName]. The translation server provides wrapper methods for accessing the master translation domain directly, without having to fetch the main translation domain first.
|
||||
Translations are stored in [TranslationDomain]s, which can be accessed by name. The most commonly used translation domain is the main translation domain. It always exists and can be accessed using an empty [StringName]. The translation server provides wrapper methods for accessing the main translation domain directly, without having to fetch the translation domain first. Custom translation domains are mainly for advanced usages like editor plugins. Names starting with [code]godot.[/code] are reserved for engine internals.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Internationalizing games">$DOCS_URL/tutorials/i18n/internationalizing_games.html</link>
|
||||
|
@ -6557,6 +6557,8 @@ EditorNode::EditorNode() {
|
||||
DEV_ASSERT(!singleton);
|
||||
singleton = this;
|
||||
|
||||
set_translation_domain("godot.editor");
|
||||
|
||||
Resource::_get_local_scene_func = _resource_get_edited_scene;
|
||||
|
||||
{
|
||||
|
@ -1210,6 +1210,8 @@ fail:
|
||||
|
||||
void EditorSettings::setup_language() {
|
||||
String lang = get("interface/editor/editor_language");
|
||||
TranslationServer::get_singleton()->set_locale(lang);
|
||||
|
||||
if (lang == "en") {
|
||||
return; // Default, nothing to do.
|
||||
}
|
||||
|
@ -54,6 +54,8 @@ Vector<String> get_editor_locales() {
|
||||
}
|
||||
|
||||
void load_editor_translations(const String &p_locale) {
|
||||
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain("godot.editor");
|
||||
|
||||
EditorTranslationList *etl = _editor_translations;
|
||||
while (etl->data) {
|
||||
if (etl->lang == p_locale) {
|
||||
@ -70,7 +72,7 @@ void load_editor_translations(const String &p_locale) {
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(etl->lang);
|
||||
TranslationServer::get_singleton()->set_tool_translation(tr);
|
||||
domain->add_translation(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -80,6 +82,8 @@ void load_editor_translations(const String &p_locale) {
|
||||
}
|
||||
|
||||
void load_property_translations(const String &p_locale) {
|
||||
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain("godot.properties");
|
||||
|
||||
PropertyTranslationList *etl = _property_translations;
|
||||
while (etl->data) {
|
||||
if (etl->lang == p_locale) {
|
||||
@ -96,7 +100,7 @@ void load_property_translations(const String &p_locale) {
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(etl->lang);
|
||||
TranslationServer::get_singleton()->set_property_translation(tr);
|
||||
domain->add_translation(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -106,6 +110,8 @@ void load_property_translations(const String &p_locale) {
|
||||
}
|
||||
|
||||
void load_doc_translations(const String &p_locale) {
|
||||
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain("godot.documentation");
|
||||
|
||||
DocTranslationList *dtl = _doc_translations;
|
||||
while (dtl->data) {
|
||||
if (dtl->lang == p_locale) {
|
||||
@ -122,7 +128,7 @@ void load_doc_translations(const String &p_locale) {
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(dtl->lang);
|
||||
TranslationServer::get_singleton()->set_doc_translation(tr);
|
||||
domain->add_translation(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -132,6 +138,8 @@ void load_doc_translations(const String &p_locale) {
|
||||
}
|
||||
|
||||
void load_extractable_translations(const String &p_locale) {
|
||||
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain("godot.editor");
|
||||
|
||||
ExtractableTranslationList *etl = _extractable_translations;
|
||||
while (etl->data) {
|
||||
if (etl->lang == p_locale) {
|
||||
@ -148,7 +156,7 @@ void load_extractable_translations(const String &p_locale) {
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(etl->lang);
|
||||
TranslationServer::get_singleton()->set_extractable_translation(tr);
|
||||
domain->add_translation(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -207,6 +207,10 @@ void EditorFileDialog::_update_theme_item_cache() {
|
||||
|
||||
void EditorFileDialog::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_POSTINITIALIZE: {
|
||||
set_translation_domain(SNAME("godot.editor"));
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_THEME_CHANGED:
|
||||
case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
|
||||
case NOTIFICATION_TRANSLATION_CHANGED: {
|
||||
|
@ -1081,6 +1081,8 @@ void ProjectManager::_titlebar_resized() {
|
||||
ProjectManager::ProjectManager() {
|
||||
singleton = this;
|
||||
|
||||
set_translation_domain("godot.editor");
|
||||
|
||||
// Turn off some servers we aren't going to be using in the Project Manager.
|
||||
NavigationServer3D::get_singleton()->set_active(false);
|
||||
PhysicsServer3D::get_singleton()->set_active(false);
|
||||
|
Loading…
Reference in New Issue
Block a user