diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 39cb9b382be2..044562d225b5 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -96,6 +96,12 @@ Returns the edited (current) scene's root [Node]. + + + + Returns the language currently used for the editor interface. + + diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 82e8f01cf72d..56bec120b273 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -880,7 +880,7 @@ During a drag-and-drop, this is how long to wait over a UI element before it triggers a reaction (e.g. a section unfolds to show nested items). - The language to use for the editor interface. + The language to use for the editor interface. If set to [b]Auto[/b], the language is automatically determined based on the system locale. See also [method EditorInterface.get_editor_language]. Translations are provided by the community. If you spot a mistake, [url=https://contributing.godotengine.org/en/latest/documentation/translation/index.html]contribute to editor translations on Weblate![/url] diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp index ca530bedea6b..79cd296aa825 100644 --- a/editor/editor_interface.cpp +++ b/editor/editor_interface.cpp @@ -442,6 +442,10 @@ float EditorInterface::get_editor_scale() const { return EDSCALE; } +String EditorInterface::get_editor_language() const { + return EditorSettings::get_singleton()->get_language(); +} + bool EditorInterface::is_node_3d_snap_enabled() const { return Node3DEditor::get_singleton()->is_snap_enabled(); } @@ -846,6 +850,7 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("is_multi_window_enabled"), &EditorInterface::is_multi_window_enabled); ClassDB::bind_method(D_METHOD("get_editor_scale"), &EditorInterface::get_editor_scale); + ClassDB::bind_method(D_METHOD("get_editor_language"), &EditorInterface::get_editor_language); ClassDB::bind_method(D_METHOD("is_node_3d_snap_enabled"), &EditorInterface::is_node_3d_snap_enabled); ClassDB::bind_method(D_METHOD("get_node_3d_translate_snap"), &EditorInterface::get_node_3d_translate_snap); diff --git a/editor/editor_interface.h b/editor/editor_interface.h index 8f84650fe58f..76936855c219 100644 --- a/editor/editor_interface.h +++ b/editor/editor_interface.h @@ -131,6 +131,7 @@ class EditorInterface : public Object { bool is_multi_window_enabled() const; float get_editor_scale() const; + String get_editor_language() const; bool is_node_3d_snap_enabled() const; real_t get_node_3d_translate_snap() const; diff --git a/editor/inspector/editor_property_name_processor.cpp b/editor/inspector/editor_property_name_processor.cpp index 7dcede74d7f4..efb37be116b6 100644 --- a/editor/inspector/editor_property_name_processor.cpp +++ b/editor/inspector/editor_property_name_processor.cpp @@ -59,7 +59,7 @@ EditorPropertyNameProcessor::Style EditorPropertyNameProcessor::get_tooltip_styl } bool EditorPropertyNameProcessor::is_localization_available() { - return EditorSettings::get_singleton() && EDITOR_GET("interface/editor/editor_language") != "en"; + return EditorSettings::get_singleton() && EditorSettings::get_singleton()->get_language() != "en"; } String EditorPropertyNameProcessor::_capitalize_name(const String &p_name) const { diff --git a/editor/settings/editor_settings.cpp b/editor/settings/editor_settings.cpp index d666a02057c2..a92d024f3ee7 100644 --- a/editor/settings/editor_settings.cpp +++ b/editor/settings/editor_settings.cpp @@ -363,6 +363,28 @@ void EditorSettings::_set_initialized() { initialized = true; } +static LocalVector _get_skipped_locales() { + // Skip locales if Text server lack required features. + LocalVector locales_to_skip; + if (!TS->has_feature(TextServer::FEATURE_BIDI_LAYOUT) || !TS->has_feature(TextServer::FEATURE_SHAPING)) { + locales_to_skip.push_back("ar"); // Arabic. + locales_to_skip.push_back("fa"); // Persian. + locales_to_skip.push_back("ur"); // Urdu. + } + if (!TS->has_feature(TextServer::FEATURE_BIDI_LAYOUT)) { + locales_to_skip.push_back("he"); // Hebrew. + } + if (!TS->has_feature(TextServer::FEATURE_SHAPING)) { + locales_to_skip.push_back("bn"); // Bengali. + locales_to_skip.push_back("hi"); // Hindi. + locales_to_skip.push_back("ml"); // Malayalam. + locales_to_skip.push_back("si"); // Sinhala. + locales_to_skip.push_back("ta"); // Tamil. + locales_to_skip.push_back("te"); // Telugu. + } + return locales_to_skip; +} + void EditorSettings::_load_defaults(Ref p_extra_config) { _THREAD_SAFE_METHOD_ // Sets up the editor setting with a default value and hint PropertyInfo. @@ -381,36 +403,18 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { /* Languages */ { - String lang_hint = ";en/[en] English"; - String host_lang = OS::get_singleton()->get_locale(); - - // Skip locales if Text server lack required features. - Vector locales_to_skip; - if (!TS->has_feature(TextServer::FEATURE_BIDI_LAYOUT) || !TS->has_feature(TextServer::FEATURE_SHAPING)) { - locales_to_skip.push_back("ar"); // Arabic - locales_to_skip.push_back("fa"); // Persian - locales_to_skip.push_back("ur"); // Urdu - } - if (!TS->has_feature(TextServer::FEATURE_BIDI_LAYOUT)) { - locales_to_skip.push_back("he"); // Hebrew - } - if (!TS->has_feature(TextServer::FEATURE_SHAPING)) { - locales_to_skip.push_back("bn"); // Bengali - locales_to_skip.push_back("hi"); // Hindi - locales_to_skip.push_back("ml"); // Malayalam - locales_to_skip.push_back("si"); // Sinhala - locales_to_skip.push_back("ta"); // Tamil - locales_to_skip.push_back("te"); // Telugu - } + String lang_hint; + const String host_lang = OS::get_singleton()->get_locale(); + // Skip locales which we can't render properly. + const LocalVector locales_to_skip = _get_skipped_locales(); if (!locales_to_skip.is_empty()) { WARN_PRINT("Some locales are not properly supported by selected Text Server and are disabled."); } - String best; + String best = "en"; int best_score = 0; for (const String &locale : get_editor_locales()) { - // Skip locales which we can't render properly (see above comment). // Test against language code without regional variants (e.g. ur_PK). String lang_code = locale.get_slicec('_', 0); if (locales_to_skip.has(lang_code)) { @@ -427,11 +431,9 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { best_score = score; } } - if (best_score == 0) { - best = "en"; - } + lang_hint = vformat(";auto/Auto (%s);en/[en] English", TranslationServer::get_singleton()->get_locale_name(best)) + lang_hint; - EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_ENUM, "interface/editor/editor_language", best, lang_hint, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED | PROPERTY_USAGE_EDITOR_BASIC_SETTING); + EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_ENUM, "interface/editor/editor_language", "auto", lang_hint, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED | PROPERTY_USAGE_EDITOR_BASIC_SETTING); } // Asset library @@ -1329,7 +1331,7 @@ void EditorSettings::create() { } void EditorSettings::setup_language(bool p_initial_setup) { - String lang = _EDITOR_GET("interface/editor/editor_language"); + String lang = get_language(); if (p_initial_setup) { String lang_ov = Main::get_locale_override(); if (!lang_ov.is_empty()) { @@ -1851,6 +1853,37 @@ float EditorSettings::get_auto_display_scale() { #endif // defined(MACOS_ENABLED) || defined(ANDROID_ENABLED) } +String EditorSettings::get_language() const { + const String language = has_setting("interface/editor/editor_language") ? get("interface/editor/editor_language") : "auto"; + if (language != "auto") { + return language; + } + + if (auto_language.is_empty()) { + // Skip locales which we can't render properly. + const LocalVector locales_to_skip = _get_skipped_locales(); + const String host_lang = OS::get_singleton()->get_locale(); + + String best = "en"; + int best_score = 0; + for (const String &locale : get_editor_locales()) { + // Test against language code without regional variants (e.g. ur_PK). + String lang_code = locale.get_slicec('_', 0); + if (locales_to_skip.has(lang_code)) { + continue; + } + + int score = TranslationServer::get_singleton()->compare_locales(host_lang, locale); + if (score > 0 && score >= best_score) { + best = locale; + best_score = score; + } + } + auto_language = best; + } + return auto_language; +} + // Shortcuts void EditorSettings::_add_shortcut_default(const String &p_name, const Ref &p_shortcut) { diff --git a/editor/settings/editor_settings.h b/editor/settings/editor_settings.h index 2059b9e31c99..df65c26719e3 100644 --- a/editor/settings/editor_settings.h +++ b/editor/settings/editor_settings.h @@ -89,6 +89,7 @@ class EditorSettings : public Resource { static Ref singleton; HashSet changed_settings; + mutable String auto_language; mutable Ref project_metadata; HashMap hints; @@ -186,6 +187,7 @@ class EditorSettings : public Resource { Vector get_script_templates(const String &p_extension, const String &p_custom_path = String()); String get_editor_layouts_config() const; static float get_auto_display_scale(); + String get_language() const; void _add_shortcut_default(const String &p_name, const Ref &p_shortcut); void add_shortcut(const String &p_name, const Ref &p_shortcut); diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs index 5ae4dfa076d6..3428962a810b 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs @@ -41,7 +41,7 @@ private static Process LaunchBuild(BuildInfo buildInfo, Action? stdOutH startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"] - = ((string)editorSettings.GetSetting("interface/editor/editor_language")).Replace('_', '-'); + = ((string)EditorInterface.Singleton.GetEditorLanguage()).Replace('_', '-'); if (OperatingSystem.IsWindows()) { @@ -111,7 +111,7 @@ private static Process LaunchPublish(BuildInfo buildInfo, Action? stdOu startInfo.RedirectStandardError = true; startInfo.UseShellExecute = false; startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"] - = ((string)editorSettings.GetSetting("interface/editor/editor_language")).Replace('_', '-'); + = ((string)EditorInterface.Singleton.GetEditorLanguage()).Replace('_', '-'); if (OperatingSystem.IsWindows()) {