-
-
Notifications
You must be signed in to change notification settings - Fork 21k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add translation domain #95787
Add translation domain #95787
Conversation
I'm confused on how to add translations for plugins. E.g. I have a plugin with custom strings that need to be translated, but it also has a file dialog. When I set a domain for the plugin, the dialog will lose translations. I have to either set a domain for every node, or modify an existing domain. The first option sounds rather cumbersome, the latter has the conflict problem this PR tries to fix. Also, for whatever reason, when adding translation to |
<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]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am to assume it works like this
Returns the name of the translation domain used by [method tr] and [method tr_n]. See also [TranslationServer]. | |
Returns the name of the translation domain used by [method tr] and [method tr_n], as registered on the [TranslationServer]. See also [TranslationDomain]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this creates an ambiguity: what is registered on the TranslationServer?
- "which translation domain this object uses" is registered
- It's not registered on the translation server.
- "the name of a translation domain" is registered
- It's technically not required that a translation domain with the specified name exists.
@KoBeWi I made a sample dock panel plugin to demonstrate the usage: test-4.zip The plugin has I only partially translated |
It would be more convenient if editor translation was a fallback. |
Plugins should use Currently, all plugin translations fall back to editor translations. It's also technically not hard to add fallback domain support for a
|
Unfortunately EditorFileDialog is not easily available. Most people don't even know that you can use it. Though I guess it's a separate issue. |
editor/gui/editor_file_dialog.cpp
Outdated
@@ -206,6 +206,10 @@ void EditorFileDialog::_update_theme_item_cache() { | |||
|
|||
void EditorFileDialog::_notification(int p_what) { | |||
switch (p_what) { | |||
case NOTIFICATION_POSTINITIALIZE: { | |||
set_translation_domain("godot.editor"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it's not in the constructor?
EDIT:
Also you could use SNAME for nodes that have multiple instances.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was in the constructor, but then I got this warning:
WARNING: Attempting to access theme items too early in EditorFileDialog; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's weird, because it's unrelated to theme. Also you set it in the constructor in ProjectManager.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EditorFileDialog
updates its icons in NOTIFICATION_TRANSLATION_CHANGED
, maybe some icons have language dependent variants (?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They don't, looks like a bug. It handles 3 notifications at once. Translation change should only call invalidate()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_update_icons()
is indeed locale-dependent. A change in language potentially changes the return value of is_layout_rtl()
:
godot/editor/gui/editor_file_dialog.cpp
Lines 1422 to 1431 in 5ebfc8a
void EditorFileDialog::_update_icons() { | |
// Update icons. | |
mode_thumbnails->set_icon(theme_cache.mode_thumbnails); | |
mode_list->set_icon(theme_cache.mode_list); | |
if (is_layout_rtl()) { | |
dir_prev->set_icon(theme_cache.forward_folder); | |
dir_next->set_icon(theme_cache.back_folder); | |
} else { |
Yeah, maybe icon update could be moved to invalidate()
too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But that's what NOTIFICATION_LAYOUT_DIRECTION_CHANGED
is for. Unless RTL can change based on locale and don't send the notification?
In any case, changing language without restarting the editor is generally not supported, so this is pretty much irrelevant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the implementation, NOTIFICATION_LAYOUT_DIRECTION_CHANGED
is only emitted when the control changes between inherit-parent
, locale-dependent
, LTR
, and RTL
. It's not used when locale changes.
How editor plugins use this feature: 1. Pick a unique translation domain name. 2. `_enter_tree()`: load translations into that translation domain. 3. Call `set_translation_domain()` for its root UI node. 4. `_exit_tree()`: remove that translation domain. Plugins can also set the translation domain to `godot.editor` for nested nodes that should use editor translations. `EditorFileDialog` automatically does this.
134eaff
to
818acb4
Compare
case NOTIFICATION_POSTINITIALIZE: { | ||
set_translation_domain(SNAME("godot.editor")); | ||
} break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably do the same for EditorSpinSlider
?
I didn't check if it has translatable strings but I assume maybe some tooltips at least.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EditorSpinSlider
currently does not use auto translation. Text translations, including tooltip translations, are done via TTR
macros (always use the godot.editor
domain).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read through the proposals and the PR discussion, it makes sense to me.
I haven't checked the implementation in depth nor tested but overall the exposed API seems pretty good.
Thanks! Great work 🎉 |
EditorInterface
. #82158This PR is separated into 3 commits to make it easier to review.
1. Add
TranslationDomain
l10n features like
add_translation()
andtranslate()
are all moved fromTranslationServer
into the newTranslationDomain
class.Users can add/remove custom translation domains with
get_or_add_domain()
/remove_domain()
. It's "get or add" because getting a nullTranslationDomain
is practically never desired.Existing
TranslationServer
methods are kept as wrappers around the main translation domain.2. Allow configuring which translation domain
Object.tr()
usesThis adds
{get,set}_translation_domain()
virtual methods onObject
. It's by default a simple getter/setter, only affects latertr()
calls on that object.For a
Node
, its translation domain is inherited from the parent node by default. Onceset_translation_domain()
is called, the node's translation domain is fixed (callingset_translation_domain_inherited()
makes it parent-dependent again).3. Make editor use translation domains
The components from Weblate are all translation domains now:
godot.editor
,godot.properties
, andgodot.documentation
. Note that tool translations and extractable translations are loaded into the samegodot.editor
domain.EditorNode
andProjectManager
are set to use thegodot.editor
translation domain. Nodes in the current edited scene don't do translation, so translation domains do not matter.Nodes like
EditorFileDialog
should automatically fix their translation domain togodot.editor
so they have the right translation when used by plugins.How editor plugins do l10n
com.example.my-plugin-name
._enter_tree()
: load translations into that translation domain.set_translation_domain("com.example.my-plugin-name")
on its root UI node._exit_tree()
: remove that translation domain.Sample dock panel plugin to demonstrate the usage: test-4.zip