diff --git a/core/object/object.cpp b/core/object/object.cpp index a5f6f48b7f8..fd32c0a90ab 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -1650,6 +1650,19 @@ bool Object::_uses_signal_mutex() const { return true; } +String Object::_get_locale() const { + TranslationServer *ts = TranslationServer::get_singleton(); + const StringName domain_name = get_translation_domain(); + if (ts->has_domain(domain_name)) { + const Ref domain = ts->get_or_add_domain(domain_name); + const String &overridden = domain->get_locale_override(); + if (!overridden.is_empty()) { + return overridden; + } + } + return ts->get_locale(); +} + void Object::_set_bind(const StringName &p_set, const Variant &p_value) { set(p_set, p_value); } diff --git a/core/object/object.h b/core/object/object.h index c0e33457973..82cec498e1f 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -793,6 +793,9 @@ protected: virtual bool _uses_signal_mutex() const; + // Internal helper to get the current locale, taking into account the translation domain. + String _get_locale() const; + #ifdef TOOLS_ENABLED struct VirtualMethodTracker { void **method; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 2c5b21e8bba..c2dc503622d 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -453,6 +453,10 @@ void EditorNode::_update_from_settings() { String current_fallback_locale = GLOBAL_GET("internationalization/locale/fallback"); if (current_fallback_locale != TranslationServer::get_singleton()->get_fallback_locale()) { TranslationServer::get_singleton()->set_fallback_locale(current_fallback_locale); + Ref domain = TranslationServer::get_singleton()->get_main_domain(); + if (!domain->is_enabled()) { + domain->set_locale_override(current_fallback_locale); + } scene_root->propagate_notification(Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED); } @@ -4175,8 +4179,15 @@ void EditorNode::set_preview_locale(const String &p_locale) { // Texts set in the editor could be identifiers that should never be translated. // So we need to disable translation entirely. Ref main_domain = TranslationServer::get_singleton()->get_main_domain(); - main_domain->set_enabled(!p_locale.is_empty()); - main_domain->set_locale_override(p_locale); + if (p_locale.is_empty()) { + // Disable preview. Use the fallback locale. + main_domain->set_enabled(false); + main_domain->set_locale_override(TranslationServer::get_singleton()->get_fallback_locale()); + } else { + // Preview a specific locale. + main_domain->set_enabled(true); + main_domain->set_locale_override(p_locale); + } _translation_resources_changed(); } @@ -7574,7 +7585,10 @@ EditorNode::EditorNode() { ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &EditorNode::_update_from_settings)); GDExtensionManager::get_singleton()->connect("extensions_reloaded", callable_mp(this, &EditorNode::_gdextensions_reloaded)); - TranslationServer::get_singleton()->get_main_domain()->set_enabled(false); + Ref domain = TranslationServer::get_singleton()->get_main_domain(); + domain->set_enabled(false); + domain->set_locale_override(TranslationServer::get_singleton()->get_fallback_locale()); + // Load settings. if (!EditorSettings::get_singleton()) { EditorSettings::create(); diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 2b511bac9af..60ceba70a74 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -214,11 +214,8 @@ void Label3D::_notification(int p_what) { window->disconnect("size_changed", callable_mp(this, &Label3D::_font_changed)); } break; case NOTIFICATION_TRANSLATION_CHANGED: { - String new_text = atr(text); - if (new_text == xl_text) { - return; // Nothing new. - } - xl_text = new_text; + // Language update might change the appearance of some characters. + xl_text = atr(text); dirty_text = true; _queue_update(); } break; @@ -482,8 +479,9 @@ void Label3D::_shape() { TS->shaped_text_clear(text_rid); TS->shaped_text_set_direction(text_rid, text_direction); - String txt = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text; - TS->shaped_text_add_string(text_rid, txt, font->get_rids(), font_size, font->get_opentype_features(), language); + const String &lang = language.is_empty() ? _get_locale() : language; + String txt = uppercase ? TS->string_to_upper(xl_text, lang) : xl_text; + TS->shaped_text_add_string(text_rid, txt, font->get_rids(), font_size, font->get_opentype_features(), lang); TypedArray stt; if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) { diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 2fac6ee0537..6cce9115371 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -600,7 +600,8 @@ void Button::_shape(Ref p_paragraph, String p_text) const { } else { p_paragraph->set_direction((TextServer::Direction)text_direction); } - p_paragraph->add_string(p_text, font, font_size, language); + const String &lang = language.is_empty() ? _get_locale() : language; + p_paragraph->add_string(p_text, font, font_size, lang); p_paragraph->set_text_overrun_behavior(overrun_behavior); } diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 56d15231b4d..5c9a69b1e92 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -188,13 +188,14 @@ void CodeEdit::_notification(int p_what) { code_completion_line_ofs = CLAMP((code_completion_force_item_center < 0 ? code_completion_current_selected : code_completion_force_item_center) - lines / 2, 0, code_completion_options_count - lines); RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(code_completion_rect.position.x, code_completion_rect.position.y + (code_completion_current_selected - code_completion_line_ofs) * row_height), Size2(code_completion_rect.size.width, row_height)), theme_cache.code_completion_selected_color); + const String &lang = _get_locale(); for (int i = 0; i < lines; i++) { int l = code_completion_line_ofs + i; ERR_CONTINUE(l < 0 || l >= code_completion_options_count); Ref tl; tl.instantiate(); - tl->add_string(code_completion_options[l].display, theme_cache.font, theme_cache.font_size); + tl->add_string(code_completion_options[l].display, theme_cache.font, theme_cache.font_size, lang); int yofs = (row_height - tl->get_size().y) / 2; Point2 title_pos(code_completion_rect.position.x, code_completion_rect.position.y + i * row_height + yofs); @@ -1519,14 +1520,15 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 if (E) { text_rid = E->value; } else { + const String &lang = _get_locale(); String fc = String::num_int64(p_line + 1).lpad(line_number_digits, line_number_padding); if (is_localizing_numeral_system()) { - fc = TS->format_number(fc); + fc = TS->format_number(fc, lang); } text_rid = TS->create_shaped_text(); if (theme_cache.font.is_valid()) { - TS->shaped_text_add_string(text_rid, fc, theme_cache.font->get_rids(), theme_cache.font_size, theme_cache.font->get_opentype_features()); + TS->shaped_text_add_string(text_rid, fc, theme_cache.font->get_rids(), theme_cache.font_size, theme_cache.font->get_opentype_features(), lang); } line_number_text_cache.insert(p_line, text_rid); } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 0dc1664d82c..808faf13de6 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -35,7 +35,6 @@ #include "core/input/input_map.h" #include "core/os/os.h" #include "core/string/string_builder.h" -#include "core/string/translation_server.h" #include "scene/gui/scroll_container.h" #include "scene/main/canvas_layer.h" #include "scene/main/window.h" @@ -3516,12 +3515,9 @@ bool Control::is_layout_rtl() const { } else if (proj_root_layout_direction == 2) { data.is_rtl = true; } else if (proj_root_layout_direction == 3) { - String locale = OS::get_singleton()->get_locale(); - data.is_rtl = TS->is_locale_right_to_left(locale); + data.is_rtl = TS->is_locale_right_to_left(OS::get_singleton()->get_locale()); } else { - const Ref &t = TranslationServer::get_singleton()->get_translation_object(TranslationServer::get_singleton()->get_locale()); - String locale = t.is_valid() ? t->get_locale() : TranslationServer::get_singleton()->get_fallback_locale(); - data.is_rtl = TS->is_locale_right_to_left(locale); + data.is_rtl = TS->is_locale_right_to_left(_get_locale()); } return data.is_rtl; } @@ -3532,8 +3528,9 @@ bool Control::is_layout_rtl() const { return data.is_rtl; } #endif // TOOLS_ENABLED + const StringName domain_name = get_translation_domain(); Node *parent_node = get_parent(); - while (parent_node) { + while (parent_node && domain_name == parent_node->get_translation_domain()) { Control *parent_control = Object::cast_to(parent_node); if (parent_control) { data.is_rtl = parent_control->is_layout_rtl(); @@ -3556,22 +3553,19 @@ bool Control::is_layout_rtl() const { String locale = OS::get_singleton()->get_locale(); data.is_rtl = TS->is_locale_right_to_left(locale); } else { - String locale = TranslationServer::get_singleton()->get_tool_locale(); - data.is_rtl = TS->is_locale_right_to_left(locale); + data.is_rtl = TS->is_locale_right_to_left(_get_locale()); } } else if (data.layout_dir == LAYOUT_DIRECTION_APPLICATION_LOCALE) { if (GLOBAL_GET_CACHED(bool, "internationalization/rendering/force_right_to_left_layout_direction")) { data.is_rtl = true; } else { - String locale = TranslationServer::get_singleton()->get_tool_locale(); - data.is_rtl = TS->is_locale_right_to_left(locale); + data.is_rtl = TS->is_locale_right_to_left(_get_locale()); } } else if (data.layout_dir == LAYOUT_DIRECTION_SYSTEM_LOCALE) { if (GLOBAL_GET_CACHED(bool, "internationalization/rendering/force_right_to_left_layout_direction")) { - const_cast(this)->data.is_rtl = true; + data.is_rtl = true; } else { - String locale = OS::get_singleton()->get_locale(); - const_cast(this)->data.is_rtl = TS->is_locale_right_to_left(locale); + data.is_rtl = TS->is_locale_right_to_left(OS::get_singleton()->get_locale()); } } else { data.is_rtl = (data.layout_dir == LAYOUT_DIRECTION_RTL); diff --git a/scene/gui/foldable_container.cpp b/scene/gui/foldable_container.cpp index c93bab06faf..d64fc16d169 100644 --- a/scene/gui/foldable_container.cpp +++ b/scene/gui/foldable_container.cpp @@ -488,7 +488,8 @@ void FoldableContainer::_shape() { } text_buf->set_horizontal_alignment(_get_actual_alignment()); text_buf->set_text_overrun_behavior(overrun_behavior); - text_buf->add_string(atr(title), font, font_size, language); + const String &lang = language.is_empty() ? _get_locale() : language; + text_buf->add_string(atr(title), font, font_size, lang); } HorizontalAlignment FoldableContainer::_get_actual_alignment() const { diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 333ae07ab64..90b18d6e509 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -43,7 +43,8 @@ void ItemList::_shape_text(int p_idx) { } else { item.text_buf->set_direction((TextServer::Direction)item.text_direction); } - item.text_buf->add_string(item.xl_text, theme_cache.font, theme_cache.font_size, item.language); + const String &lang = item.language.is_empty() ? _get_locale() : item.language; + item.text_buf->add_string(item.xl_text, theme_cache.font, theme_cache.font_size, lang); if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) { item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_START_EDGE_SPACES | TextServer::BREAK_TRIM_END_EDGE_SPACES); } else { diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index cd97ee265b2..e946364ffa9 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -136,6 +136,8 @@ int Label::get_line_height(int p_line) const { } void Label::_shape() const { + const String &lang = language.is_empty() ? _get_locale() : language; + Ref style = theme_cache.normal_style; int width = (get_size().width - style->get_minimum_size().width); @@ -149,7 +151,7 @@ void Label::_shape() const { } paragraphs.clear(); - String txt = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text; + String txt = (uppercase) ? TS->string_to_upper(xl_text, lang) : xl_text; if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { txt = txt.substr(0, visible_chars); } @@ -183,7 +185,7 @@ void Label::_shape() const { ERR_FAIL_COND(font.is_null()); if (para.dirty) { - TS->shaped_text_add_string(para.text_rid, para.text, font->get_rids(), font_size, font->get_opentype_features(), language); + TS->shaped_text_add_string(para.text_rid, para.text, font->get_rids(), font_size, font->get_opentype_features(), lang); } else { int spans = TS->shaped_get_span_count(para.text_rid); for (int i = 0; i < spans; i++) { @@ -703,15 +705,14 @@ void Label::_notification(int p_what) { } break; case NOTIFICATION_TRANSLATION_CHANGED: { - String new_text = atr(text); - if (new_text == xl_text) { - return; // Nothing new. + const String new_text = atr(text); + if (new_text != xl_text) { + xl_text = new_text; + if (visible_ratio < 1) { + visible_chars = get_total_character_count() * visible_ratio; + } } - xl_text = new_text; - if (visible_ratio < 1) { - visible_chars = get_total_character_count() * visible_ratio; - } - text_dirty = true; + text_dirty = true; // Language update might change the appearance of some characters. queue_accessibility_update(); queue_redraw(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index f188ed693ca..9822086c78b 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -1201,11 +1201,8 @@ void LineEdit::_notification(int p_what) { DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_REPLACE_SELECTED_TEXT, callable_mp(this, &LineEdit::_accessibility_action_replace_selected)); DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SET_VALUE, callable_mp(this, &LineEdit::_accessibility_action_set_value)); DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SHOW_CONTEXT_MENU, callable_mp(this, &LineEdit::_accessibility_action_menu)); - if (!language.is_empty()) { - DisplayServer::get_singleton()->accessibility_update_set_language(ae, language); - } else { - DisplayServer::get_singleton()->accessibility_update_set_language(ae, TranslationServer::get_singleton()->get_tool_locale()); - } + const String &lang = language.is_empty() ? _get_locale() : language; + DisplayServer::get_singleton()->accessibility_update_set_language(ae, lang); bool rtl = is_layout_rtl(); Ref style = theme_cache.normal; @@ -2978,7 +2975,8 @@ void LineEdit::_shape() { } TS->shaped_text_set_preserve_control(text_rid, draw_control_chars); - TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, font->get_opentype_features(), language); + const String &lang = language.is_empty() ? _get_locale() : language; + TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, font->get_opentype_features(), lang); TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, t)); full_width = TS->shaped_text_get_size(text_rid).x; diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index f9ef144400c..83a3ca9b136 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -43,7 +43,8 @@ void LinkButton::_shape() { text_buf->set_direction((TextServer::Direction)text_direction); } TS->shaped_text_set_bidi_override(text_buf->get_rid(), structured_text_parser(st_parser, st_args, xl_text)); - text_buf->add_string(xl_text, font, font_size, language); + const String &lang = language.is_empty() ? _get_locale() : language; + text_buf->add_string(xl_text, font, font_size, lang); queue_accessibility_update(); } diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp index 9e149aff865..fe8208351e5 100644 --- a/scene/gui/menu_bar.cpp +++ b/scene/gui/menu_bar.cpp @@ -517,7 +517,8 @@ void MenuBar::shape(Menu &p_menu) { } else { p_menu.text_buf->set_direction((TextServer::Direction)text_direction); } - p_menu.text_buf->add_string(atr(p_menu.name), theme_cache.font, theme_cache.font_size, language); + const String &lang = language.is_empty() ? _get_locale() : language; + p_menu.text_buf->add_string(atr(p_menu.name), theme_cache.font, theme_cache.font_size, lang); } void MenuBar::_refresh_menu_names() { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index b51233df159..694b3015192 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1017,11 +1017,12 @@ void PopupMenu::_shape_item(int p_idx) const { } else { items.write[p_idx].text_buf->set_direction((TextServer::Direction)items[p_idx].text_direction); } - items.write[p_idx].text_buf->add_string(items.write[p_idx].xl_text, font, font_size, items[p_idx].language); + const String &lang = items[p_idx].language.is_empty() ? _get_locale() : items[p_idx].language; + items.write[p_idx].text_buf->add_string(items.write[p_idx].xl_text, font, font_size, lang); items.write[p_idx].accel_text_buf->clear(); items.write[p_idx].accel_text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); - items.write[p_idx].accel_text_buf->add_string(_get_accel_text(items.write[p_idx]), font, font_size); + items.write[p_idx].accel_text_buf->add_string(_get_accel_text(items.write[p_idx]), font, font_size, lang); items.write[p_idx].dirty = false; } } diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index f43ddd9cc70..37ae2b1abbc 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -167,7 +167,8 @@ void ProgressBar::_notification(int p_what) { String txt = itos(int(ratio * 100)); if (is_localizing_numeral_system()) { - txt = TS->format_number(txt) + TS->percent_sign(); + const String &lang = _get_locale(); + txt = TS->format_number(txt, lang) + TS->percent_sign(lang); } else { txt += String("%"); } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 233c6e54514..f3aa6b7bc24 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -3407,21 +3407,20 @@ TextServer::StructuredTextParser RichTextLabel::_find_stt(Item *p_item) { } String RichTextLabel::_find_language(Item *p_item) { - Item *item = p_item; - - while (item) { + String lang = language; + for (Item *item = p_item; item; item = item->parent) { if (item->type == ITEM_LANGUAGE) { ItemLanguage *p = static_cast(item); - return p->language; - } else if (item->type == ITEM_PARAGRAPH) { - ItemParagraph *p = static_cast(item); - return p->language; + lang = p->language; + break; + } + if (item->type == ITEM_PARAGRAPH) { + ItemParagraph *p = static_cast(item); + lang = p->language; + break; } - - item = item->parent; } - - return language; + return lang.is_empty() ? _get_locale() : lang; } Color RichTextLabel::_find_color(Item *p_item, const Color &p_default_color) { diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 429040563e3..8edca6e2003 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -88,7 +88,7 @@ void SpinBox::_update_text(bool p_only_update_if_value_changed) { double step = get_step(); String value = String::num(get_value(), Math::range_step_decimals(step)); if (is_localizing_numeral_system()) { - value = TS->format_number(value); + value = TS->format_number(value, _get_locale()); } if (p_only_update_if_value_changed && value == last_text_value) { @@ -137,8 +137,9 @@ void SpinBox::_text_submitted(const String &p_string) { Ref expr; expr.instantiate(); + const String &lang = _get_locale(); text = text.replace_char(';', ','); - text = TS->parse_number(text); + text = TS->parse_number(text, lang); // Ignore the prefix and suffix in the expression. text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix); @@ -147,7 +148,7 @@ void SpinBox::_text_submitted(const String &p_string) { if (err != OK) { // If the expression failed try without converting commas to dots - they might have been for parameter separation. text = p_string; - text = TS->parse_number(text); + text = TS->parse_number(text, lang); text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix); err = expr->parse(text); diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index 4c9c3f5ecef..31e6c669cf6 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -359,7 +359,8 @@ void TabBar::_shape(int p_tab) { tabs.write[p_tab].text_buf->set_direction((TextServer::Direction)tabs[p_tab].text_direction); } - tabs.write[p_tab].text_buf->add_string(atr(tabs[p_tab].text), theme_cache.font, theme_cache.font_size, tabs[p_tab].language); + const String &lang = tabs[p_tab].language.is_empty() ? _get_locale() : tabs[p_tab].language; + tabs.write[p_tab].text_buf->add_string(atr(tabs[p_tab].text), theme_cache.font, theme_cache.font_size, lang); } RID TabBar::get_tab_accessibility_element(int p_tab) const { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 2659d0b1755..cca2cb95b3a 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -39,7 +39,6 @@ #include "core/os/os.h" #include "core/string/alt_codes.h" #include "core/string/string_builder.h" -#include "core/string/translation_server.h" #include "scene/gui/label.h" #include "scene/main/window.h" #include "scene/theme/theme_db.h" @@ -866,7 +865,7 @@ void TextEdit::_notification(int p_what) { case NOTIFICATION_TRANSLATION_CHANGED: case NOTIFICATION_THEME_CHANGED: { if (is_inside_tree()) { - _update_caches(); + _update_caches(p_what == NOTIFICATION_TRANSLATION_CHANGED); _update_wrap_at_column(true); } } break; @@ -1444,7 +1443,7 @@ void TextEdit::_notification(int p_what) { Ref tl; tl.instantiate(); - tl->add_string(txt, theme_cache.font, theme_cache.font_size); + tl->add_string(txt, theme_cache.font, theme_cache.font_size, _get_locale()); int yofs = ofs_y + (row_height - tl->get_size().y) / 2; if (theme_cache.outline_size > 0 && theme_cache.outline_color.a > 0) { @@ -3357,7 +3356,8 @@ void TextEdit::_update_placeholder() { placeholder_data_buf->set_direction((TextServer::Direction)text_direction); } placeholder_data_buf->set_preserve_control(draw_control_chars); - placeholder_data_buf->add_string(placeholder_translated, theme_cache.font, theme_cache.font_size, language); + const String &lang = language.is_empty() ? _get_locale() : language; + placeholder_data_buf->add_string(placeholder_translated, theme_cache.font, theme_cache.font_size, lang); placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_translated); if (placeholder_bidi_override.is_empty()) { @@ -3403,7 +3403,7 @@ void TextEdit::_update_theme_item_cache() { } } -void TextEdit::_update_caches() { +void TextEdit::_update_caches(bool p_invalidate_all) { /* Text properties. */ TextServer::Direction dir; if (text_direction == Control::TEXT_DIRECTION_INHERITED) { @@ -3411,11 +3411,16 @@ void TextEdit::_update_caches() { } else { dir = (TextServer::Direction)text_direction; } - text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); + const String &lang = language.is_empty() ? _get_locale() : language; + text.set_direction_and_language(dir, lang); text.set_draw_control_chars(draw_control_chars); text.set_font(theme_cache.font); text.set_font_size(theme_cache.font_size); - text.invalidate_font(); + if (p_invalidate_all) { + text.invalidate_all(); + } else { + text.invalidate_font(); + } _update_placeholder(); /* Syntax highlighting. */ @@ -3740,8 +3745,9 @@ void TextEdit::set_text_direction(Control::TextDirection p_text_direction) { } else { dir = (TextServer::Direction)text_direction; } - text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); - text.invalidate_font(); + const String &lang = language.is_empty() ? _get_locale() : language; + text.set_direction_and_language(dir, lang); + text.invalidate_all(); _update_placeholder(); if (menu_dir) { @@ -3768,7 +3774,8 @@ void TextEdit::set_language(const String &p_language) { } else { dir = (TextServer::Direction)text_direction; } - text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); + const String &lang = language.is_empty() ? _get_locale() : language; + text.set_direction_and_language(dir, lang); text.invalidate_all(); _update_placeholder(); queue_accessibility_update(); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index a92dde1feb1..070e7549ebb 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -332,7 +332,7 @@ private: Array st_args; void _clear(); - void _update_caches(); + void _update_caches(bool p_invalidate_all = false); void _close_ime_window(); void _update_ime_window_position(); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 891ead7c328..3e46b0feb61 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2105,7 +2105,8 @@ void Tree::update_column(int p_col) { } columns.write[p_col].xl_title = atr(columns[p_col].title); - columns.write[p_col].text_buf->add_string(columns[p_col].xl_title, theme_cache.tb_font, theme_cache.tb_font_size, columns[p_col].language); + const String &lang = columns[p_col].language.is_empty() ? _get_locale() : columns[p_col].language; + columns.write[p_col].text_buf->add_string(columns[p_col].xl_title, theme_cache.tb_font, theme_cache.tb_font_size, lang); columns.write[p_col].cached_minimum_width_dirty = true; } @@ -2174,7 +2175,8 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) const { } else { font_size = theme_cache.font_size; } - p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].language); + const String &lang = p_item->cells[p_col].language.is_empty() ? _get_locale() : p_item->cells[p_col].language; + p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, lang); BitField break_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_TRIM_START_EDGE_SPACES | TextServer::BREAK_TRIM_END_EDGE_SPACES; switch (p_item->cells.write[p_col].autowrap_mode) { diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 5d1694973cf..990837dd15e 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -32,7 +32,6 @@ #include "core/config/project_settings.h" #include "core/debugger/engine_debugger.h" -#include "core/string/translation_server.h" #include "scene/gui/control.h" #include "scene/theme/theme_db.h" #include "scene/theme/theme_owner.h" @@ -2932,12 +2931,9 @@ bool Window::is_layout_rtl() const { } else if (proj_root_layout_direction == 2) { return true; } else if (proj_root_layout_direction == 3) { - String locale = OS::get_singleton()->get_locale(); - return TS->is_locale_right_to_left(locale); + return TS->is_locale_right_to_left(OS::get_singleton()->get_locale()); } else { - const Ref &t = TranslationServer::get_singleton()->get_translation_object(TranslationServer::get_singleton()->get_locale()); - String locale = t.is_valid() ? t->get_locale() : TranslationServer::get_singleton()->get_fallback_locale(); - return TS->is_locale_right_to_left(locale); + return TS->is_locale_right_to_left(_get_locale()); } } } @@ -2946,8 +2942,9 @@ bool Window::is_layout_rtl() const { return true; } #endif + const StringName domain_name = get_translation_domain(); Node *parent_node = get_parent(); - while (parent_node) { + while (parent_node && parent_node->get_translation_domain() == domain_name) { Control *parent_control = Object::cast_to(parent_node); if (parent_control) { return parent_control->is_layout_rtl(); @@ -2965,25 +2962,21 @@ bool Window::is_layout_rtl() const { } else if (root_layout_direction == 2) { return true; } else if (root_layout_direction == 3) { - String locale = OS::get_singleton()->get_locale(); - return TS->is_locale_right_to_left(locale); + return TS->is_locale_right_to_left(OS::get_singleton()->get_locale()); } else { - String locale = TranslationServer::get_singleton()->get_tool_locale(); - return TS->is_locale_right_to_left(locale); + return TS->is_locale_right_to_left(_get_locale()); } } else if (layout_dir == LAYOUT_DIRECTION_APPLICATION_LOCALE) { if (GLOBAL_GET_CACHED(bool, "internationalization/rendering/force_right_to_left_layout_direction")) { return true; } else { - String locale = TranslationServer::get_singleton()->get_tool_locale(); - return TS->is_locale_right_to_left(locale); + return TS->is_locale_right_to_left(_get_locale()); } } else if (layout_dir == LAYOUT_DIRECTION_SYSTEM_LOCALE) { if (GLOBAL_GET_CACHED(bool, "internationalization/rendering/force_right_to_left_layout_direction")) { return true; } else { - String locale = OS::get_singleton()->get_locale(); - return TS->is_locale_right_to_left(locale); + return TS->is_locale_right_to_left(OS::get_singleton()->get_locale()); } } else { return (layout_dir == LAYOUT_DIRECTION_RTL); diff --git a/scene/resources/3d/primitive_meshes.cpp b/scene/resources/3d/primitive_meshes.cpp index f5886a8719f..e597caf4e4c 100644 --- a/scene/resources/3d/primitive_meshes.cpp +++ b/scene/resources/3d/primitive_meshes.cpp @@ -3226,8 +3226,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { TS->shaped_text_clear(text_rid); TS->shaped_text_set_direction(text_rid, text_direction); - String txt = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text; - TS->shaped_text_add_string(text_rid, txt, font->get_rids(), font_size, font->get_opentype_features(), language); + const String &lang = language.is_empty() ? _get_locale() : language; + String txt = (uppercase) ? TS->string_to_upper(xl_text, lang) : xl_text; + TS->shaped_text_add_string(text_rid, txt, font->get_rids(), font_size, font->get_opentype_features(), lang); TypedArray stt; if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) { @@ -3685,11 +3686,8 @@ void TextMesh::_bind_methods() { void TextMesh::_notification(int p_what) { switch (p_what) { case MainLoop::NOTIFICATION_TRANSLATION_CHANGED: { - String new_text = tr(text); - if (new_text == xl_text) { - return; // Nothing new. - } - xl_text = new_text; + // Language update might change the appearance of some characters. + xl_text = tr(text); dirty_text = true; request_update(); } break;