使用 gettext 进行本地化

除了 CSV 格式的导入翻译之外,Godot 还支持加载以 GNU gettext 格式编写的翻译文件(基于文本的 .po,自 Godot 4.0 起还支持编译后的 .mo)。

备注

有关 gettext 的介绍,请查看快速 Gettext 教程。它是针对 C 项目编写的,但其中许多建议也适用于 Godot(xgettext除外)。

优势

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

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

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

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

缺点

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

  • 维护本地化文件的人员必须在其系统上安装 gettext 工具。但是,由于 Godot 支持使用基于文本的消息文件(.po),翻译人员无需安装 gettext 工具即可测试他们的工作。

安装 gettext 工具

命令行 gettext 工具是执行维护操作(例如更新消息文件)所必需的。因此,强烈建议安装它们。

  • Windows:该页面下载安装程序。任何架构和二进制类型(共享或静态)均可;如有疑问,请选择 64 位静态安装程序。

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

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

创建 PO 模板

使用编辑器自动生成

自 Godot 4.0 以来,编辑器可以从指定的场景和 GDScript 文件中自动生成 PO 模板。如果在脚本中使用,此 POT 生成还支持翻译上下文和复数形式,使用 tr()tr_n() 方法的可选的第二个实参。

打开项目设置的本地化 > POT 生成选项卡,然后使用添加... 按钮指定项目中包含可本地化字符串的场景和脚本的路径:

在项目设置的“本地化 > POT 生成”选项卡中创建 PO 模板

在项目设置的本地化 > POT 生成选项卡中创建 PO 模板

添加至少一个场景或脚本后,点击右上角的生成 POT,然后指定输出文件的路径。该文件可以放在项目目录中的任何位置,但建议将其保存在子目录如 locale中,因为每个区域都将在其自己的文件中定义。

See below for how to add comments for translators or exclude some strings from being added to the PO template for GDScript files.

然后,你可以转到《从 PO 模板创建消息文件》。

备注

请记住,在对可本地化的字符串进行任何更改或新增新场景或脚本后重新生成 PO 模板。否则,新添加的字符串将不可本地化,并且翻译人员将无法更新过时字符串的翻译。

手动创建

如果该自动生成的方法不能满足你的需求,你可以在文本编辑器中手动创建 PO 模板。该文件可以放在项目目录中的任何位置,但建议将其保存在子目录中,因为每个区域设置都将在其自己的文件中定义。

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

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

# Example of a regular string.
msgid "Hello world!"
msgstr ""

# Example of a string with pluralization.
msgid "There is %d apple."
msgid_plural "There are %d apples."
msgstr[0] ""
msgstr[1] ""

# Example of a string with a translation context.
msgctxt "Actions"
msgid "Close"
msgstr ""

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

警告

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

从 PO 模板创建消息文件

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

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

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

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

在 Godot 中加载消息文件

如果要将消息文件注册为项目的翻译,请打开项目设置,然后进入本地化选项卡。在翻译中单击添加...,然后在文件对话框中选择该 .po 或者 .mo 文件。区域设置将从消息文件的 "Language: <code>\n" 属性中推断出来。

备注

关于在 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”注释。该注释表示翻译应更新以匹配新的源字符串,因为翻译在更新之前很可能是不准确的。

在翻译更新并删除“fuzzy”注释之前,Godot 不会读取带有“fuzzy”注释的字符串。

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

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

msgfmt fr.po --check

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

使用二进制 MO 文件(仅适用于大型项目)

大型项目会有成千上万的字符串要翻译,相比于基于文本的 PO 文件,使用(编译为)二进制的 MO 消息文件可能更加划算。二进制 MO 文件比对应的 PO 文件更小、读起来更快。

可以使用以下命令生成 MO 文件:

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

如果该 PO 文件有效,该命令将在 PO 文件旁边创建一个 fr.mo 文件。该 MO 文件然后可以按照上述方法在 Godot 中加载。

原始 PO 文件应保留在版本控制中,以便你将来更新翻译。如果你丢失了原始 PO 文件,并希望将 MO 文件反编译为基于文本的 PO 文件,你可以这样做:

msgunfmt fr.mo > fr.po

反编译出的文件不包含注释和模糊字符串,因为它们一开始就没有编译进 MO 文件里。

Extracting localizable strings from GDScript files

The built-in editor plugin recognizes a variety of patterns in source code to extract localizable strings from GDScript files, including but not limited to the following:

  • tr(), tr_n(), atr(), and atr_n() calls;

  • assigning properties text, placeholder_text, and tooltip_text;

  • add_tab(), add_item(), set_tab_title(), and other calls;

  • FileDialog filters like "*.png ; PNG Images".

备注

The argument or right operand must be a constant string, otherwise the plugin will not be able to evaluate the expression and will ignore it.

If the plugin extracts unnecessary strings, you can ignore them with the NO_TRANSLATE comment. You can also provide additional information for translators using the TRANSLATORS: comment. These comments must be placed either on the same line as the recognized pattern or precede it.

$CharacterName.text = "???" # NO_TRANSLATE

# NO_TRANSLATE: Language name.
$TabContainer.set_tab_title(0, "Python")

item.text = "Tool" # TRANSLATORS: Up to 10 characters.

# TRANSLATORS: This is a reference to Lewis Carroll's poem "Jabberwocky",
# make sure to keep this as it is important to the plot.
say(tr("He took his vorpal sword in hand. The end?"))