Skip to content

Commit

Permalink
Add translation preview in editor
Browse files Browse the repository at this point in the history
  • Loading branch information
timothyqiu committed Sep 17, 2024
1 parent ac3b810 commit 3181ac3
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 9 deletions.
15 changes: 13 additions & 2 deletions core/string/translation_domain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ void TranslationDomain::clear() {
}

StringName TranslationDomain::translate(const StringName &p_message, const StringName &p_context) const {
const String &locale = TranslationServer::get_singleton()->get_locale();
const String &locale = locale_override.is_empty() ? TranslationServer::get_singleton()->get_locale() : locale_override;
StringName res = get_message_from_translations(locale, p_message, p_context);

const String &fallback = TranslationServer::get_singleton()->get_fallback_locale();
Expand All @@ -299,7 +299,7 @@ StringName TranslationDomain::translate(const StringName &p_message, const Strin
}

StringName TranslationDomain::translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
const String &locale = TranslationServer::get_singleton()->get_locale();
const String &locale = locale_override.is_empty() ? TranslationServer::get_singleton()->get_locale() : locale_override;
StringName res = get_message_from_translations(locale, p_message, p_message_plural, p_n, p_context);

const String &fallback = TranslationServer::get_singleton()->get_fallback_locale();
Expand All @@ -316,6 +316,15 @@ StringName TranslationDomain::translate_plural(const StringName &p_message, cons
return res;
}

String TranslationDomain::get_locale_override() const {
return locale_override;
}

void TranslationDomain::set_locale_override(const String &p_locale) {
String new_locale = p_locale.is_empty() ? p_locale : TranslationServer::get_singleton()->standardize_locale(p_locale);
locale_override = new_locale;
}

bool TranslationDomain::is_pseudolocalization_enabled() const {
return pseudolocalization.enabled;
}
Expand Down Expand Up @@ -417,6 +426,8 @@ void TranslationDomain::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &TranslationDomain::clear);
ClassDB::bind_method(D_METHOD("translate", "message", "context"), &TranslationDomain::translate, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("translate_plural", "message", "message_plural", "n", "context"), &TranslationDomain::translate_plural, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("get_locale_override"), &TranslationDomain::get_locale_override);
ClassDB::bind_method(D_METHOD("set_locale_override", "locale"), &TranslationDomain::set_locale_override);

ClassDB::bind_method(D_METHOD("is_pseudolocalization_enabled"), &TranslationDomain::is_pseudolocalization_enabled);
ClassDB::bind_method(D_METHOD("set_pseudolocalization_enabled", "enabled"), &TranslationDomain::set_pseudolocalization_enabled);
Expand Down
4 changes: 4 additions & 0 deletions core/string/translation_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class TranslationDomain : public RefCounted {
String suffix = "]";
};

String locale_override;
HashSet<Ref<Translation>> translations;
PseudolocalizationConfig pseudolocalization;

Expand Down Expand Up @@ -80,6 +81,9 @@ class TranslationDomain : public RefCounted {
StringName translate(const StringName &p_message, const StringName &p_context) const;
StringName translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const;

String get_locale_override() const;
void set_locale_override(const String &p_locale);

bool is_pseudolocalization_enabled() const;
void set_pseudolocalization_enabled(bool p_enabled);
bool is_pseudolocalization_accents_enabled() const;
Expand Down
1 change: 1 addition & 0 deletions core/string/translation_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class TranslationServer : public Object {
public:
_FORCE_INLINE_ static TranslationServer *get_singleton() { return singleton; }

Ref<TranslationDomain> get_main_domain() const { return main_domain; }
Ref<TranslationDomain> get_editor_domain() const { return editor_domain; }

void set_enabled(bool p_enabled) { enabled = p_enabled; }
Expand Down
16 changes: 16 additions & 0 deletions doc/classes/TranslationDomain.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<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].
Because translation domain is intended to be advanced usage, modifications to it do not emit [constant MainLoop.NOTIFICATION_TRANSLATION_CHANGED] on the scene tree automatically. See the description of methods and properties below for details.
</description>
<tutorials>
</tutorials>
Expand All @@ -23,6 +24,12 @@
Removes all translations.
</description>
</method>
<method name="get_locale_override" qualifiers="const">
<return type="String" />
<description>
Returns the locale override of the domain. Returns an empty string if locale override is disabled.
</description>
</method>
<method name="get_translation_object" qualifiers="const">
<return type="Translation" />
<param index="0" name="locale" type="String" />
Expand All @@ -44,6 +51,15 @@
Removes the given translation.
</description>
</method>
<method name="set_locale_override">
<return type="void" />
<param index="0" name="locale" type="String" />
<description>
Sets the locale override of the domain.
If [param locale] is an empty string, locale override is disabled. Otherwise, [param locale] will be standardized to match known locales (e.g. [code]en-US[/code] would be matched to [code]en_US[/code]).
[b]Note: [/b] Updating this property does not automatically update texts in the scene tree. Please propagate the [constant MainLoop.NOTIFICATION_TRANSLATION_CHANGED] signal manually.
</description>
</method>
<method name="translate" qualifiers="const">
<return type="StringName" />
<param index="0" name="message" type="StringName" />
Expand Down
23 changes: 23 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,10 @@ void EditorNode::_update_from_settings() {

ResourceImporterTexture::get_singleton()->update_imports();

TranslationServer::get_singleton()->clear();
TranslationServer::get_singleton()->load_translations();
scene_root->propagate_notification(NOTIFICATION_TRANSLATION_CHANGED);

#ifdef DEBUG_ENABLED
NavigationServer3D::get_singleton()->set_debug_navigation_edge_connection_color(GLOBAL_GET("debug/shapes/navigation/edge_connection_color"));
NavigationServer3D::get_singleton()->set_debug_navigation_geometry_edge_color(GLOBAL_GET("debug/shapes/navigation/geometry_edge_color"));
Expand Down Expand Up @@ -3673,6 +3677,21 @@ void EditorNode::set_edited_scene_root(Node *p_scene, bool p_auto_add) {
}
}

String EditorNode::get_preview_locale() const {
const String override = TranslationServer::get_singleton()->get_main_domain()->get_locale_override();
// Override should always be non-empty, but just in case.
return override.is_empty() ? TranslationServer::get_singleton()->get_locale() : override;
}

void EditorNode::set_preview_locale(const String &p_locale) {
Ref<TranslationDomain> main_domain = TranslationServer::get_singleton()->get_main_domain();
if (main_domain->get_locale_override() == p_locale) {
return;
}
TranslationServer::get_singleton()->get_main_domain()->set_locale_override(p_locale);
scene_root->propagate_notification(NOTIFICATION_TRANSLATION_CHANGED);
}

Dictionary EditorNode::_get_main_scene_state() {
Dictionary state;
state["scene_tree_offset"] = SceneTreeDock::get_singleton()->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_value();
Expand Down Expand Up @@ -6459,6 +6478,9 @@ void EditorNode::_bind_methods() {

ClassDB::bind_method("set_edited_scene", &EditorNode::set_edited_scene);

ClassDB::bind_method("get_preview_locale", &EditorNode::get_preview_locale);
ClassDB::bind_method(D_METHOD("set_preview_locale", "locale"), &EditorNode::set_preview_locale);

ClassDB::bind_method("stop_child_process", &EditorNode::stop_child_process);

ADD_SIGNAL(MethodInfo("request_help_search"));
Expand Down Expand Up @@ -6996,6 +7018,7 @@ EditorNode::EditorNode() {
editor_main_screen->set_v_size_flags(Control::SIZE_EXPAND_FILL);

scene_root = memnew(SubViewport);
scene_root->set_translation_domain(StringName());
scene_root->set_embedding_subwindows(true);
scene_root->set_disable_3d(true);
scene_root->set_disable_input(true);
Expand Down
3 changes: 3 additions & 0 deletions editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,9 @@ class EditorNode : public Node {
void set_edited_scene_root(Node *p_scene, bool p_auto_add);
Node *get_edited_scene() { return editor_data.get_edited_scene_root(); }

String get_preview_locale() const;
void set_preview_locale(const String &p_locale);

void fix_dependencies(const String &p_for_file);
int new_scene();
Error load_scene(const String &p_scene, bool p_ignore_broken_deps = false, bool p_set_inherited = false, bool p_clear_errors = true, bool p_force_open_imported = false, bool p_silent_change_tab = false);
Expand Down
3 changes: 3 additions & 0 deletions editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,9 @@ void EditorSettings::setup_language() {
String lang = get("interface/editor/editor_language");
TranslationServer::get_singleton()->set_locale(lang);

// Used by edited scene.
TranslationServer::get_singleton()->get_main_domain()->set_locale_override("en");

if (lang == "en") {
return; // Default, nothing to do.
}
Expand Down
38 changes: 38 additions & 0 deletions editor/plugins/canvas_item_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/os/keyboard.h"
#include "core/string/translation_server.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_main_screen.h"
#include "editor/editor_node.h"
Expand Down Expand Up @@ -63,6 +64,7 @@
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/style_box_texture.h"
#include "scene/scene_string_names.h"

#define RULER_WIDTH (15 * EDSCALE)
#define DRAG_THRESHOLD (8 * EDSCALE)
Expand Down Expand Up @@ -1062,6 +1064,36 @@ void CanvasItemEditor::_switch_theme_preview(int p_mode) {
EditorNode::get_singleton()->update_preview_themes(theme_preview);
}

void CanvasItemEditor::_prepare_translation_menu() {
translation_menu->clear();
translation_menu->add_radio_check_item(TTR("None"));
translation_menu->set_item_metadata(-1, "en");

Vector<String> locales = TranslationServer::get_singleton()->get_loaded_locales();

const String current_preview_locale = EditorNode::get_singleton()->get_preview_locale();
if (!locales.is_empty()) {
translation_menu->add_separator();
}
bool using_default = true;
for (const String &locale : locales) {
translation_menu->add_radio_check_item(locale);
translation_menu->set_item_metadata(-1, locale);
if (locale == current_preview_locale) {
translation_menu->set_item_checked(-1, true);
using_default = false;
}
}
if (using_default) {
translation_menu->set_item_checked(0, true);
}
}

void CanvasItemEditor::_switch_translation_preview(int p_translation) {
view_menu->get_popup()->hide();
EditorNode::get_singleton()->set_preview_locale(translation_menu->get_item_metadata(p_translation));
}

bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
Ref<InputEventMouseButton> b = p_event;
Expand Down Expand Up @@ -5582,6 +5614,12 @@ CanvasItemEditor::CanvasItemEditor() {
theme_menu->set_item_checked(i, i == theme_preview);
}

translation_menu = memnew(PopupMenu);
translation_menu->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
translation_menu->connect("about_to_popup", callable_mp(this, &CanvasItemEditor::_prepare_translation_menu));
translation_menu->connect("index_pressed", callable_mp(this, &CanvasItemEditor::_switch_translation_preview));
p->add_submenu_node_item(TTR("Preview Translation"), translation_menu);

main_menu_hbox->add_child(memnew(VSeparator));

// Contextual toolbars.
Expand Down
4 changes: 4 additions & 0 deletions editor/plugins/canvas_item_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ class CanvasItemEditor : public VBoxContainer {
MenuButton *view_menu = nullptr;
PopupMenu *grid_menu = nullptr;
PopupMenu *theme_menu = nullptr;
PopupMenu *translation_menu = nullptr;
PopupMenu *gizmos_menu = nullptr;
HBoxContainer *animation_hb = nullptr;
MenuButton *animation_menu = nullptr;
Expand Down Expand Up @@ -432,6 +433,9 @@ class CanvasItemEditor : public VBoxContainer {
ThemePreviewMode theme_preview = THEME_PREVIEW_PROJECT;
void _switch_theme_preview(int p_mode);

void _prepare_translation_menu();
void _switch_translation_preview(int p_translation);

List<CanvasItem *> _get_edited_canvas_items(bool p_retrieve_locked = false, bool p_remove_canvas_item_if_parent_in_selection = true, bool *r_has_locked_items = nullptr) const;
Rect2 _get_encompassing_rect_from_list(const List<CanvasItem *> &p_list);
void _expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D(), bool include_locked_nodes = true);
Expand Down
7 changes: 0 additions & 7 deletions scene/main/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,6 @@ void Node::_notification(int p_notification) {
data.is_auto_translate_dirty = true;
data.is_translation_domain_dirty = true;

#ifdef TOOLS_ENABLED
// Don't translate UI elements when they're being edited.
if (is_part_of_edited_scene()) {
set_message_translation(false);
}
#endif

if (data.auto_translate_mode != AUTO_TRANSLATE_MODE_DISABLED) {
notification(NOTIFICATION_TRANSLATION_CHANGED);
}
Expand Down

0 comments on commit 3181ac3

Please sign in to comment.