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())
{