Skip to content

Commit

Permalink
Merge pull request #295 from endlessm/blockdef-translations
Browse files Browse the repository at this point in the history
Translation infrastructure
  • Loading branch information
wjt authored Nov 4, 2024
2 parents 7834706 + 6d149f0 commit 1e94e46
Show file tree
Hide file tree
Showing 54 changed files with 33,721 additions and 11 deletions.
64 changes: 64 additions & 0 deletions addons/block_code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,70 @@ Lean into animations! Godot's animations functionality goes beyond just simple a

Please share feedback in the [Godot Forum Block Coding thread](https://forum.godotengine.org/t/block-coding-high-level-block-based-visual-programming/68941).

## Localization

The plugin supports translations through Godot's [gettext][godot-gettext]
support. We welcome contributions to make the plugin work better in your
language! However, please note that translations in the Godot editor **will
only work with Godot 4.4 or newer**.

The gettext PO files are located in the `addons/block_code/locale` directory.
See the Godot [documentation][godot-gettext] for instructions on working with
PO files.

[godot-gettext]: https://docs.godotengine.org/en/stable/tutorials/i18n/localization_using_gettext.html

For developers, a few things need to be done to keep the translatable strings
up to date.

* If files are added or removed, the list of translatable files needs to be
updated. This can be done by using the **Add** dialog in the [POT
Generation][pot-generation] tab. Or you can use the **Project → Tools →
Update BlockCode translated files** menu item in the editor.

* If translatable strings have changed, the POT file needs to be updated. This
can be done by using the **Generate POT** dialog in the [POT
Generation][pot-generation] tab. Or you can use the **Project → Tools →
Regenerate BlockCode POT file** menu item in the editor.

* If the POT file has changed, the PO message files need to be updated. This
can be done using the gettext `msgmerge` tool in the
`addons/block_code/locale` directory:
```
for po in *.po; do
msgmerge --update --backup=none "$po" godot_block_coding.pot
done
```

[pot-generation]: https://docs.godotengine.org/en/stable/tutorials/i18n/localization_using_gettext.html#automatic-generation-using-the-editor

Strings added in scene files or block definition resources will usually be
extracted for localization and translated in the editor automatically. Strings
in scripts need more consideration.

* `Object`s or `Node`s that are not descendents of the Block Coding panel need
to have their translation domain set with the `set_block_translation_domain`
helper function. This should usually be done in the object's `_init` method
to make sure the translation domain is set before that object or any of its
descendents (which inherit the translation domain by default) try to use
localized strings.

* Usually [`tr`][object-tr] and [`tr_n`][object-tr-n] (or [`atr`][node-atr] and
[`atr_n`][node-atr-n] for `Node`s) should be used to mark translatable
strings. These will eventually call the domain's
[`translate`][domain-translate] or
[`translate_plural`][domain-translate-plural] methods, but the `tr` methods
respect translation settings on the object instances. The only time the
`translate` methods should be called directly is within a static context when
an object instance isn't available.

[object-tr]: https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-tr
[object-tr-n]: https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-tr-n
[node-atr]: https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-atr
[node-atr-n]: https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-atr-n
[domain-translate]: https://docs.godotengine.org/en/latest/classes/class_translationdomain.html#class-translationdomain-method-translate
[domain-translate-plural]: https://docs.godotengine.org/en/latest/classes/class_translationdomain.html#class-translationdomain-method-translate-plural

## Development

### pre-commit
Expand Down
6 changes: 6 additions & 0 deletions addons/block_code/block_code_node/block_code.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
class_name BlockCode
extends Node

const TxUtils := preload("res://addons/block_code/translation/utils.gd")

@export var block_script: BlockScriptSerialization = null


func _init():
TxUtils.set_block_translation_domain(self)


func _ready():
if Engine.is_editor_hint():
return
Expand Down
18 changes: 18 additions & 0 deletions addons/block_code/block_code_plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ extends EditorPlugin
const MainPanelScene := preload("res://addons/block_code/ui/main_panel.tscn")
const MainPanel = preload("res://addons/block_code/ui/main_panel.gd")
const Types = preload("res://addons/block_code/types/types.gd")
const TxUtils := preload("res://addons/block_code/translation/utils.gd")
const ScriptWindow := preload("res://addons/block_code/ui/script_window/script_window.tscn")

static var main_panel: MainPanel
Expand All @@ -12,6 +13,9 @@ static var block_code_button: Button
const BlockInspectorPlugin := preload("res://addons/block_code/inspector_plugin/block_script_inspector.gd")
var block_inspector_plugin: BlockInspectorPlugin

const BlockTranslationParserPlugin := preload("res://addons/block_code/translation/parser.gd")
var _tx_parser_plugin: BlockTranslationParserPlugin

var editor_inspector: EditorInspector

var _selected_block_code: BlockCode
Expand All @@ -29,6 +33,11 @@ const DISABLED_CLASSES := [
]


func _init():
TxUtils.load_translations()
TxUtils.set_block_translation_domain(self)


func _enter_tree():
Types.init_cast_graph()

Expand All @@ -41,6 +50,14 @@ func _enter_tree():
block_inspector_plugin = BlockInspectorPlugin.new()
add_inspector_plugin(block_inspector_plugin)

if not _tx_parser_plugin:
_tx_parser_plugin = BlockTranslationParserPlugin.new()
add_translation_parser_plugin(_tx_parser_plugin)

# Custom Project->Tools menu items.
add_tool_menu_item(tr("Regenerate %s POT file") % "BlockCode", TxUtils.regenerate_pot_file)
add_tool_menu_item(tr("Update %s translated files") % "BlockCode", TxUtils.update_pot_files)

# Remove unwanted class nodes from create node
old_feature_profile = EditorInterface.get_current_feature_profile()

Expand Down Expand Up @@ -69,6 +86,7 @@ func script_window_requested(script: String):


func _exit_tree():
remove_translation_parser_plugin(_tx_parser_plugin)
remove_inspector_plugin(block_inspector_plugin)

if block_code_button:
Expand Down
7 changes: 6 additions & 1 deletion addons/block_code/inspector_plugin/block_script_inspector.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
extends EditorInspectorPlugin

const BlockCodePlugin = preload("res://addons/block_code/block_code_plugin.gd")
const TxUtils := preload("res://addons/block_code/translation/utils.gd")


func _init():
TxUtils.set_block_translation_domain(self)


func _can_handle(object):
Expand All @@ -11,7 +16,7 @@ func _parse_begin(object):
var block_code := object as BlockCode

var button := Button.new()
button.text = "Open Block Script"
button.text = tr("Open Block Script")
button.pressed.connect(func(): BlockCodePlugin.main_panel.switch_block_code_node(block_code))

var container := MarginContainer.new()
Expand Down
Loading

0 comments on commit 1e94e46

Please sign in to comment.