使用 gettext 进行本地化

In addition to 导入翻译 in CSV format, Godot also supports loading translation files written in the GNU gettext format (text-based .po and compiled .mo since Godot 3.5).

备注

有关 gettext 的介绍,请查看 A Quick Gettext Tutorial。它是针对 C 项目编写的,但是很多建议也适用于 Godot(除了 xgettext)。

优势

  • gettext 是一种标准格式,可以使用任何文本编辑器或图形用户界面编辑器(如 Poedit)进行编辑。

  • TransifexWeblate 等翻译平台也支持 gettext,让人们可以更方便地进行本地化协作。

  • 与 CSV 相比,gettext 更适合 Git 这样的版本控制系统,因为每个语言环境都有自己的消息文件。

  • 与 CSV 文件相比,在 gettext 文件中编辑多行字符串更方便。

缺点

  • gettext 是一种比 CSV 更复杂的格式,对于刚接触软件本地化的人来说可能更难理解。

  • People who maintain localization files will have to install gettext tools on their system. However, as Godot supports using text-based message files (.po), translators can test their work without having to install gettext tools.

注意事项

  • 由于 Godot 在幕后使用自己的 PO 文件解析器(这比参考 GNU gettext 实现有更多限制),因此不支持诸如复数之类的一些特性。

安装 gettext 工具

需要命令行 gettext 工具来执行维护操作,如更新消息文件。因此,强烈建议您安装它们。

  • Windows:该页面下载安装程序。任何体系结构和二进制类型(共享或静态)都可以;如果不确定,请选择 64 位静态安装程序。

  • macOS:使用 Homebrewbrew install gettext 命令来安装 gettext,或使用 MacPortssudo port install gettext 命令来安装。

  • Linux:在大多数发行版上,请使用发行版的包管理器安装 gettext 包。

手动创建 PO 模板(POT)

Godot目前不支持使用 xgettext 提取源字符串, 因此必须手动创建 .pot 文件. 该文件可以放在项目目录中的任何位置, 但建议将其放在子目录中, 因为每个语言环境都将在其自己的文件中定义.

在工程目录下创建名为 locale 的目录. 在该目录下, 保存一个名为 messages.pot 的文件, 内容如下:

# Don't remove the two lines below, they're required for gettext to work correctly.
msgid ""
msgstr ""

msgid "Hello world!"
msgstr ""

gettext 中的消息由 msgidmsgstr 对组成。msgid 为源字符串(一般为英文),msgstr 为翻译后的字符串。

PO 模板文件(.pot)中的 msgstr 值应始终为空。本地化会在生成的 .po 文件中进行。

使用 pybabel 创建 PO 模板(POT)

Python 工具 pybabel 支持 Godot,可用于从场景文件和脚本自动创建和更新 POT 文件。

安装 Babelbabel-godot 后, 例如使用pip:

pip3 install babel babel-godot

编写一个映射文件(例如 Babelrc),指明 pybabel 需要处理哪些文件(请注意,我们将 GDScript 作为 Python 处理,这通常就足够了):

[python: **.gd]
encoding = utf-8

[godot_scene: **.tscn]
encoding = utf-8

然后,您可以运行 pybabel,如下所示:

pybabel extract -F babelrc -k text -k LineEdit/placeholder_text -k tr -o godot-l10n.pot .

使用 -k 选项指定需要提取的内容。在这种情况下,将翻译 tr() 的参数,以及名为“text”的属性(Control 节点常用)和 LineEdit 的 placeholder_text 属性。

从 PO 模板创建消息文件

msginit 命令用于将 PO 模板转换为消息文件。例如,要创建法语本地化文件,请在 locale 目录中使用以下命令:

msginit --no-translator --input=messages.pot --locale=fr

上面的命令会在 PO 模板所在的目录下创建一个名为 fr.po 的文件。

或者,您可以使用 Poedit 以图形方式完成此操作,或者通过将 POT 文件上传到您选择的 Web 平台。

在 Godot 中加载消息文件

To register a messages file as a translation in a project, open the Project Settings, then go to the Localization tab. In Translations, click Add… then choose the .po or .mo file in the file dialog. The locale will be inferred from the "Language: <code>\n" property in the messages file.

备注

关于在 Godot 中导入和测试翻译的更多信息,请参阅 使游戏国际化

按照 PO 模板更新消息文件

更新 PO 模板后,您必须更新消息文件以使其包含新字符串,同时删除已经在 PO 模板中不复存在的字符串。这可以使用 msgmerge 工具自动完成:

# The order matters: specify the message file *then* the PO template!
msgmerge --update --backup=none fr.po messages.pot

如果你想保留原始消息文件的备份,在本例中会保存为 fr.po~ ,请删除 --backup=none 参数。

备注

运行 msgmerge 后,如果源语言修改了某个字符串,那么在 .po 文件中就会在这个字符串之前加入“fuzzy”注释。这个注释表示的是翻译应当针对新字符串进行更新,因为现有翻译非常可能是不精确的。

Godot 不会读取带有“fuzzy”注释的字符串,需要更新翻译并移除“fuzzy”注释才行。

检查 PO 文件或模板的有效性

可以通过运行以下命令来检查 gettext 文件的语法是否有效:

msgfmt fr.po --check

如果有语法错误或警告,他们将显示在控制台。否则,msgfmt 不会输出任何东西。

Using binary MO files (useful for large projects only)

For large projects with several thousands of strings to translate or more, it can be worth it to use binary (compiled) MO message files instead of text-based PO files. Binary MO files are smaller and faster to read than the equivalent PO files.

You can generate a MO file with the command below:

msgfmt fr.po --no-hash -o fr.mo

If the PO file is valid, this command will create a fr.mo file besides the PO file. This MO file can then be loaded in Godot as described below.

The original PO file should be kept in version control so you can update your translation in the future. In case you lose the original PO file and wish to decompile a MO file into a text-based PO file, you can do so with:

msgunfmt fr.mo > fr.po

The decompiled file will not include comments or fuzzy strings, as these are never compiled in the MO file in the first place.