Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Localization using gettext (PO files)

In addition to importing translations in CSV format, Godot also supports loading translation files written in the GNU gettext format (text-based .po and compiled .mo since Godot 4.0).

备注

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

For the complete documentation, see GNU Gettext.

优势

  • gettext is a standard format, which can be edited using any text editor or GUI editors such as Poedit. This can be significant as it provides a lot of tools for translators, such as marking outdated strings, finding strings that haven't been translated etc.

  • gettext supports plurals and context.

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

  • Compared to CSV, gettext files work better with version control systems like Git, as each locale has its own messages file.

  • Multiline strings are more convenient to edit in gettext PO files compared to CSV files.

缺点

  • gettext PO files have a more complex format than CSV and can be harder to grasp for people new to software localization.

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

  • gettext PO files usually use English as the base language. Translators will use this base language to translate to other languages. You could still user other languages as the base language, but this is not common.

安装 gettext 工具

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

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

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

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

For a GUI tool you can get Poedit from its Official website. The basic version is open source and available under the MIT license.

创建 PO 模板

使用编辑器自动生成

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

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

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

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

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

请参阅下文了解如何添加面向翻译者的注释,以及如何从 GDScript 文件的 PO 模板中排除某些字符串。

然后就可以转到《从 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 文件或模板的有效性

It is possible to check whether a gettext file's syntax is valid.

If you open with Poeditor, it will display the appropriate warnings if there's some syntax errors. You can also verify by running the gettext command below:

msgfmt fr.po --check

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

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

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

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

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

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

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

msgunfmt fr.mo > fr.po

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

从 GDScript 文件中提取可本地化的字符串

内置的编辑器插件能够识别源代码中的多种模式,可以从 GDScript 文件中提取可本地化的字符串,包括但不限于以下内容:

  • tr()tr_n()atr()atr_n() 的调用;

  • textplaceholder_texttooltip_text 等属性赋值;

  • add_tab()add_item()set_tab_title() 等函数的调用;

  • FileDialog 的过滤器格式如 "*.png ; PNG 图像"

备注

参数和右操作数必须为字符串常量,否则插件无法对表达式求值,会将其忽略。

如果插件提取了不必要的字符串,你可以使用 NO_TRANSLATE 注释来忽略。你也可以使用 TRANSLATORS: 注释为翻译人员提供额外信息。这些注释必须放在与识别模式相同的行上,或者放在前一行。

$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?"))

Using context

The context parameter can be used to differentiate the situation where a translation is used, or to differentiate polysemic words (words with multiple meanings).

例如:

tr("Start", "Main Menu")
tr("End", "Main Menu")
tr("Shop", "Main Menu")
tr("Shop", "In Game")

Updating PO files

Some time or later, you'll add new content to our game, and there will be new strings that need to be translated. When this happens, you'll need to update the existing PO files to include the new strings.

First, generate a new POT file containing all the existing strings plus the newly added strings. After that, merge the existing PO files with the new POT file. There are two ways to do this:

  • Use a gettext editor, and it should have an option to update a PO file from a POT file.

  • Use the gettext msgmerge tool:

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

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

POT generation custom plugin

If you have any extra file format to deal with, you could write a custom plugin to parse and and extract the strings from the custom file. This custom plugin will extract the strings and write into the POT file when you hit Generate POT. To learn more about how to create the translation parser plugin, see EditorTranslationParserPlugin.