Allow configuring which translation domain Object.tr uses

This commit is contained in:
Haoyu Qiu 2024-08-16 17:25:24 +08:00
parent 68d494e24e
commit c5d147b9b5
6 changed files with 94 additions and 2 deletions

View file

@ -1527,6 +1527,14 @@ void Object::initialize_class() {
initialized = true; initialized = true;
} }
StringName Object::get_translation_domain() const {
return _translation_domain;
}
void Object::set_translation_domain(const StringName &p_domain) {
_translation_domain = p_domain;
}
String Object::tr(const StringName &p_message, const StringName &p_context) const { String Object::tr(const StringName &p_message, const StringName &p_context) const {
if (!_can_translate || !TranslationServer::get_singleton()) { if (!_can_translate || !TranslationServer::get_singleton()) {
return p_message; return p_message;
@ -1541,7 +1549,8 @@ String Object::tr(const StringName &p_message, const StringName &p_context) cons
return TranslationServer::get_singleton()->tool_translate(p_message, p_context); return TranslationServer::get_singleton()->tool_translate(p_message, p_context);
} }
return TranslationServer::get_singleton()->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);
} }
String Object::tr_n(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const { String Object::tr_n(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
@ -1562,7 +1571,8 @@ String Object::tr_n(const StringName &p_message, const StringName &p_message_plu
return TranslationServer::get_singleton()->tool_translate_plural(p_message, p_message_plural, p_n, p_context); return TranslationServer::get_singleton()->tool_translate_plural(p_message, p_message_plural, p_n, p_context);
} }
return TranslationServer::get_singleton()->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);
} }
void Object::_clear_internal_resource_paths(const Variant &p_var) { void Object::_clear_internal_resource_paths(const Variant &p_var) {
@ -1714,6 +1724,8 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("can_translate_messages"), &Object::can_translate_messages); ClassDB::bind_method(D_METHOD("can_translate_messages"), &Object::can_translate_messages);
ClassDB::bind_method(D_METHOD("tr", "message", "context"), &Object::tr, DEFVAL(StringName())); ClassDB::bind_method(D_METHOD("tr", "message", "context"), &Object::tr, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("tr_n", "message", "plural_message", "n", "context"), &Object::tr_n, DEFVAL(StringName())); ClassDB::bind_method(D_METHOD("tr_n", "message", "plural_message", "n", "context"), &Object::tr_n, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("get_translation_domain"), &Object::get_translation_domain);
ClassDB::bind_method(D_METHOD("set_translation_domain", "domain"), &Object::set_translation_domain);
ClassDB::bind_method(D_METHOD("is_queued_for_deletion"), &Object::is_queued_for_deletion); ClassDB::bind_method(D_METHOD("is_queued_for_deletion"), &Object::is_queued_for_deletion);
ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free); ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free);

View file

@ -665,6 +665,8 @@ private:
Object(bool p_reference); Object(bool p_reference);
protected: protected:
StringName _translation_domain;
_FORCE_INLINE_ bool _instance_binding_reference(bool p_reference) { _FORCE_INLINE_ bool _instance_binding_reference(bool p_reference) {
bool can_die = true; bool can_die = true;
if (_instance_bindings) { if (_instance_bindings) {
@ -954,6 +956,9 @@ public:
_FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate = p_enable; } _FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate = p_enable; }
_FORCE_INLINE_ bool can_translate_messages() const { return _can_translate; } _FORCE_INLINE_ bool can_translate_messages() const { return _can_translate; }
virtual StringName get_translation_domain() const;
virtual void set_translation_domain(const StringName &p_domain);
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
void editor_set_section_unfold(const String &p_section, bool p_unfolded); void editor_set_section_unfold(const String &p_section, bool p_unfolded);

View file

@ -973,6 +973,13 @@
Similar to [method call_thread_safe], but for setting properties. Similar to [method call_thread_safe], but for setting properties.
</description> </description>
</method> </method>
<method name="set_translation_domain_inherited">
<return type="void" />
<description>
Makes this node inherit the translation domain from its parent node. If this node has no parent, the main translation domain will be used.
This is the default behavior for all nodes. Calling [method Object.set_translation_domain] disables this behavior.
</description>
</method>
<method name="update_configuration_warnings"> <method name="update_configuration_warnings">
<return type="void" /> <return type="void" />
<description> <description>

View file

@ -818,6 +818,12 @@
[b]Note:[/b] Due of the implementation, each [Dictionary] is formatted very similarly to the returned values of [method get_method_list]. [b]Note:[/b] Due of the implementation, each [Dictionary] is formatted very similarly to the returned values of [method get_method_list].
</description> </description>
</method> </method>
<method name="get_translation_domain" qualifiers="const">
<return type="StringName" />
<description>
Returns the name of the translation domain used by [method tr] and [method tr_n]. See also [TranslationServer].
</description>
</method>
<method name="has_meta" qualifiers="const"> <method name="has_meta" qualifiers="const">
<return type="bool" /> <return type="bool" />
<param index="0" name="name" type="StringName" /> <param index="0" name="name" type="StringName" />
@ -1070,6 +1076,13 @@
If a script already exists, its instance is detached, and its property values and state are lost. Built-in property values are still kept. If a script already exists, its instance is detached, and its property values and state are lost. Built-in property values are still kept.
</description> </description>
</method> </method>
<method name="set_translation_domain">
<return type="void" />
<param index="0" name="domain" type="StringName" />
<description>
Sets the name of the translation domain used by [method tr] and [method tr_n]. See also [TranslationServer].
</description>
</method>
<method name="to_string"> <method name="to_string">
<return type="String" /> <return type="String" />
<description> <description>

View file

@ -111,6 +111,7 @@ void Node::_notification(int p_notification) {
data.auto_translate_mode = AUTO_TRANSLATE_MODE_ALWAYS; data.auto_translate_mode = AUTO_TRANSLATE_MODE_ALWAYS;
} }
data.is_auto_translate_dirty = true; data.is_auto_translate_dirty = true;
data.is_translation_domain_dirty = true;
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
// Don't translate UI elements when they're being edited. // Don't translate UI elements when they're being edited.
@ -1320,6 +1321,51 @@ bool Node::can_auto_translate() const {
return data.is_auto_translating; return data.is_auto_translating;
} }
StringName Node::get_translation_domain() const {
ERR_READ_THREAD_GUARD_V(StringName());
if (data.is_translation_domain_inherited && data.is_translation_domain_dirty) {
const_cast<Node *>(this)->_translation_domain = data.parent ? data.parent->get_translation_domain() : StringName();
data.is_translation_domain_dirty = false;
}
return _translation_domain;
}
void Node::set_translation_domain(const StringName &p_domain) {
ERR_THREAD_GUARD
if (!data.is_translation_domain_inherited && _translation_domain == p_domain) {
return;
}
_translation_domain = p_domain;
data.is_translation_domain_inherited = false;
data.is_translation_domain_dirty = false;
_propagate_translation_domain_dirty();
}
void Node::set_translation_domain_inherited() {
ERR_THREAD_GUARD
if (data.is_translation_domain_inherited) {
return;
}
data.is_translation_domain_inherited = true;
data.is_translation_domain_dirty = true;
_propagate_translation_domain_dirty();
}
void Node::_propagate_translation_domain_dirty() {
for (KeyValue<StringName, Node *> &K : data.children) {
Node *child = K.value;
if (child->data.is_translation_domain_inherited) {
child->data.is_translation_domain_dirty = true;
child->_propagate_translation_domain_dirty();
}
}
notification(NOTIFICATION_TRANSLATION_CHANGED);
}
StringName Node::get_name() const { StringName Node::get_name() const {
return data.name; return data.name;
} }
@ -3610,6 +3656,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_translate_mode", "mode"), &Node::set_auto_translate_mode); ClassDB::bind_method(D_METHOD("set_auto_translate_mode", "mode"), &Node::set_auto_translate_mode);
ClassDB::bind_method(D_METHOD("get_auto_translate_mode"), &Node::get_auto_translate_mode); ClassDB::bind_method(D_METHOD("get_auto_translate_mode"), &Node::get_auto_translate_mode);
ClassDB::bind_method(D_METHOD("set_translation_domain_inherited"), &Node::set_translation_domain_inherited);
ClassDB::bind_method(D_METHOD("get_window"), &Node::get_window); ClassDB::bind_method(D_METHOD("get_window"), &Node::get_window);
ClassDB::bind_method(D_METHOD("get_last_exclusive_window"), &Node::get_last_exclusive_window); ClassDB::bind_method(D_METHOD("get_last_exclusive_window"), &Node::get_last_exclusive_window);

View file

@ -255,6 +255,9 @@ private:
mutable bool is_auto_translating = true; mutable bool is_auto_translating = true;
mutable bool is_auto_translate_dirty = true; mutable bool is_auto_translate_dirty = true;
mutable bool is_translation_domain_inherited = true;
mutable bool is_translation_domain_dirty = true;
mutable NodePath *path_cache = nullptr; mutable NodePath *path_cache = nullptr;
} data; } data;
@ -281,6 +284,7 @@ private:
void _propagate_physics_interpolation_reset_requested(bool p_requested); void _propagate_physics_interpolation_reset_requested(bool p_requested);
void _propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification); void _propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification);
void _propagate_groups_dirty(); void _propagate_groups_dirty();
void _propagate_translation_domain_dirty();
Array _get_node_and_resource(const NodePath &p_path); Array _get_node_and_resource(const NodePath &p_path);
void _duplicate_properties(const Node *p_root, const Node *p_original, Node *p_copy, int p_flags) const; void _duplicate_properties(const Node *p_root, const Node *p_original, Node *p_copy, int p_flags) const;
@ -735,6 +739,10 @@ public:
AutoTranslateMode get_auto_translate_mode() const; AutoTranslateMode get_auto_translate_mode() const;
bool can_auto_translate() const; bool can_auto_translate() const;
virtual StringName get_translation_domain() const override;
virtual void set_translation_domain(const StringName &p_domain) override;
void set_translation_domain_inherited();
_FORCE_INLINE_ String atr(const String p_message, const StringName p_context = "") const { return can_auto_translate() ? tr(p_message, p_context) : p_message; } _FORCE_INLINE_ String atr(const String p_message, const StringName p_context = "") const { return can_auto_translate() ? tr(p_message, p_context) : p_message; }
_FORCE_INLINE_ String atr_n(const String p_message, const StringName &p_message_plural, int p_n, const StringName p_context = "") const { return can_auto_translate() ? tr_n(p_message, p_message_plural, p_n, p_context) : p_message; } _FORCE_INLINE_ String atr_n(const String p_message, const StringName &p_message_plural, int p_n, const StringName p_context = "") const { return can_auto_translate() ? tr_n(p_message, p_message_plural, p_n, p_context) : p_message; }