使游戏国际化

前言

While indie or niche games usually do not need localization, games targeting a more massive market often require localization. Godot offers many tools to make this process more straightforward, so this tutorial is more like a collection of tips and tricks.

Localization is usually done by specific studios hired for the job. Despite the huge amount of software and file formats available for this, the most common way to do localization to this day is still with spreadsheets. The process of creating the spreadsheets and importing them is already covered in the 导入翻译 tutorial. If you haven’t read the Importing translations page before, we recommend you give it a read before reading this page.

备注

We will be using the official demo as an example; you can download it from the Asset Library.

配置导入的译文

翻译可以在更改时得到更新和重新导入,但仍必须添加到项目中。可通过项目 → 项目设置 → 本地化来完成:

../../_images/localization_dialog.png

上述对话框用于添加或删除项目范围内的翻译。

资源的本地化

根据当前语言,还可以指示 Godot 使用替代版本的资产(资源)。重定向选项卡可用于此。

**Remaps*分页可用于此目的:

../../_images/localization_remaps.png

Select the resource to be remapped then add some alternatives for each locale.

备注

DynamicFonts不支持资源重新对应系统。若要根据语言的脚本使用不同的字形,请改用DynamicFont回退系统,它允许你定义任意数量的回退字形。

DynamicFont回退系统的优点是,无论目前语言如何,它都可以工作,这使其非常适合文字语言可能与客户端语言不配对的多人聊天等情况。

将键转换为文本

一些控件,例如 ButtonLabel,如果它们的文本与一个翻译键值相匹配,将自动获取翻译内容。例如,如果一个标签的文本是“MAIN_SCREEN_GREETING1”并且该键值存在于当前的翻译中,那么该文本将被自动翻译。

这种自动翻译行为在某些情况下可能是不可取的。例如,当使用 Label 来显示玩家的名字时,如果玩家的名字与翻译键相匹配,你很可能不希望进行翻译。要禁用某个节点的自动翻译,请在检查器中禁用Localization > Auto Translate(本地化 > 自动翻译)。

在代码中, 可以使用 Object.tr() 函数. 这将只是在翻译中查找文本, 如果找到的话就进行转换:

  1. level.text = tr("LEVEL_5_NAME")
  2. status.text = tr("GAME_STATUS_%d" % status_index)

备注

如果更改语言后不显示任何文字,请尝试换一个字体。默认项目字体仅支持 Latin-1 字符集的子集,无法用于显示俄语、汉语等文字。

多语言字形的一个很好的资源是「Noto Fonts <https://www.google.com/get/noto/>」。如果你使用的是不太常见的语言,请确保下载正确的变体。

下载字体后,将TTF档案加载到DynamicFont资源中,并将其用作控制节点的自定义字体。为了获得更好的可重复使用性,请将新的主题资源关联到根控制节点,并将DynamicFont定义为主题中的预设字体。

Placeholders

若要在翻译的字符串中使用占位符,请使用 GDScript 格式字符串 或 C# 中的等效功能。这使得翻译者可以自由移动字符串中占位符的位置,使得翻译听起来更自然。为了允许翻译人员决定占位符出现的*顺序*,应尽可能使用搭配使用带命名的占位符和 String.format() 的函数:

  1. # The placeholder's locations can be changed, but not their order.
  2. # This will probably not suffice for some target languages.
  3. message.text = tr("%s picked up the %s") % ["Ogre", "Sword"]
  4. # The placeholder's locations and order can be changed.
  5. # Additionally, this form gives more context for translators to work with.
  6. message.text = tr("{character} picked up the {weapon}").format({character = "Ogre", weapon = "Sword"})

翻译上下文

如果你使用普通的英文所谓来源字符串(而不是类似于 LIKE_THIS 的消息代码),那么就有可能会遇到歧义的情况,同一个英文字符串可能需要在某些目标语言中翻译为不同的字符串。你可以通过指定可选的翻译上下文来消除歧义,即便原始字符串是相同的,也能够让目标语言能够使用不同的字符串:

  1. # "Close", as in an action (to close something).
  2. button.set_text(tr("Close", "Actions"))
  3. # "Close", as in a distance (opposite of "far").
  4. distance_label.set_text(tr("Close", "Distance"))

复数

很多语言会根据对象的单复数使用不同的字符串。但是把“是否为复数”的条件硬编码为“对象数量是否大于 1 ”并不是对所有语言都有效。

有些语言有两种以上的复数形式,不同的复数需要的对象数量也各不相同。Godot 提供了对复数的支持,目标地区可以自动进行处理。

复数应该只用于正整数(或零)的情况。负数和浮点数所代表的物理实体数量是单数还是复数一般无法明确区分。

  1. var num_apples = 5
  2. label.text = tr_n("There is %d apple", "There are %d apples", num_apples) % num_apples

如果有需要也可以和上下文组合使用:

  1. var num_jobs = 1
  2. label.text = tr_n("%d job", "%d jobs", num_jobs, "Task Manager") % num_jobs

备注

提供复数翻译仅支持 使用 gettext 进行本地化,不支持 CSV。

使控件的大小可调

不同语言的相同文本的长度差异很大。为此,请务必阅读教程 大小和锚点,因为动态调整控件大小可能有所帮助。Container 可能很有用,Label 的文本换行选项应该也能帮上忙。

若要检查你的UI是否可以容纳比原始字串更长的翻译,你可以在进阶项目设定中启用 pseudolocalization (伪本地化)。这将用更长的版本替换所有可本地化的字串,同时用带有重音的版本替换原始字串中的一些字元(同时仍然可读)。占位符保持原样,以便在启用伪本地化时它们继续工作。

例如,当启用伪本地化时,字串「Hello world,this is %s!」将变为「[Ĥéłłôŵôŕłd́, ŧh̀íš íš %s!]」。

虽然第一眼看上去很奇怪,但是伪本地化的好处有很多:

  • 它可以让你快速发现不可本地化的字串,这样你就可以检查它们并使它们可本地化(如果这样做有意义的话)。

  • 它可以让你检查无法容纳长字串的UI元素。许多语言的翻译都会比原始文字长得多,因此确保你的UI能够容纳比平常更长的字串非常重要。

  • 它可以让你检查你的字形是否包含支持各种语言所需的所有字元。然而,由于伪本地化的目标是保持原始字串的可读性,因此它并不是检查字形是否支持CJK(中文、日文、韩文)或从右到左语言的有效测试。

项目设定可让你调整伪本地化行为,以便你可以根据需要停用其部分内容。

TranslationServer

Godot 有一个进行底层翻译管理的服务器,名为 TranslationServer。可以在运行时添加或删除翻译;当前语言也可以在运行时更改。

双向文本和 UI 镜像

阿拉伯语和希伯来语是从右到左书写的(除了混合的数字和拉丁单字),这些语言的使用者界面也应该是镜像的。在某些语言中,字形的形状会根据周围的字元而变化。

对双向书写系统和UI镜像的支持是透明的,你通常不需要更改任何内容或了解特定书写系统。

对于 RTL(从右至左)语言,Godot 会自动对 UI 进行以下调整:

  • 镜像左右锚点和边距。

  • 交换文本的左对齐和右对齐。

  • 镜像容器中子控件的水平顺序以及 Tree/ItemList 控件中项目的水平顺序。

  • 控件内部元素使用镜像顺序(例如 OptionButton 的下拉按钮、单选框的位置、列表框列的顺序、Tree 项目的图标和连接线的位置等),某些镜像的控件会使用单独的主题样式。

  • 坐标系不会镜像,非 UI 节点(精灵等)不受影响。

可以使用下列控件属性来复写文字和控件布局方向:

  • text_direction,设定基本文字方向。当设定为“auto”时,方向取决于根据Unicode双向算法的文字中的第一个强方向字符,

  • “语言”,覆盖目前项目区域设定。

  • ``structured_text_bidi_override``属性和`_structured_text_parser``回调,可以对结构化文本进行特殊处理。

  • “layout_direction”,覆盖控制镜像。

../../_images/ui_mirror.png

参见

You can see how right-to-left typesetting works in action using the BiDI and Font Features demo project.

在导出后的项目中添加分词迭代器数据

有些语言书写没有空格,单词和换行需要的不仅仅是字符序列的规则。Godot包括ICU规则和基于字典的中断迭代器数据,但默认情况下,导出的项目中不包括这些数据。要将其包括在内,请转到 Project → Project Settings → Localization → Text Server Data**(**项目→ 项目设置→ 本地化→ 文本服务器数据),然后单击**Install support data…**(安装支持数据…)。中断迭代器数据大约有4 MB大。

../../_images/icu_data.png

结构化文本 BiDi 覆盖

Unicode BiDi算法设计用于处理自然文字,它无法处理具有更高层级顺序的文字,例如档案名称、URI、电子邮件地址、正规表示式或原始代码。

../../_images/bidi_override.png

例如,所显示的目录结构的路径将显示不正确(顶部「LineEdit」控件)。「档案」型别结构化文字会复写将文字分割成段,然后将BiDi算法单独套用到每个段,以正确显示任何语言的目录名称并保留文件夹的正确顺序(底部「LineEdit」控件)。

自定义回调提供了一种覆盖其他型别结构化文字的BiDi的方法。

数字的本地化

专为数位输入或输出设计的控件(例如ProgressBar、SpinBox)将自动使用本地化编号系统,对于其他控件 TextServer.format_number(string,language) 可用于转换西阿拉伯数字(0 ..9)到本地化编号系统并:ref:TextServer.parse_number(string,language)<class_TextServer_method_parse_number> 将其转换回来。

图标和图像的本地化

带有左右指向箭头的图标可能需要在阿拉伯语和希伯来语语言环境中颠倒过来,以防它们指示移动或方向(例如后退/前进按钮)。否则,它们可以保持不变。

测试翻译

你可能会想要在发布前测试项目的翻译。Godot 为此提供了两种方法。

First, in the Project Settings, under Internationalization > Locale (with advanced settings enabled), there is a Test property. Set this property to the locale code of the language you want to test. Godot will run the project with that locale when the project is run (either from the editor or when exported).

../../_images/locale_test.webp

请记住,因为这是一个项目设置,设为非空时会在版本控制中显示。因此,将修改提交到版本控制之前,应该将其设回空值。

Translations can also be tested when running Godot from the command line. For example, to test a game in French, the following argument can be supplied:

  1. godot --language fr

翻译项目名称

The project name becomes the app name when exporting to different operating systems and platforms. To specify the project name in more than one language go to Project > Project Settings> Application > Config. From here click on the button that says Localizable String (Size 0). Now there should be a button below that which says Add Translation. Click on that and it will take you to a page where you can choose the language (and country if needed) for your project name translation. After doing that you can now type in the localized name.

../../_images/localized_name.webp

如果你不确定要使用的语言代码,请参阅区域代码列表