受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

Chapter 53. 本地语言支持

53.1. 给翻译者 #

PostgreSQL 程序(服务器和客户端)可以用你所偏好的语言发出消息 — 前提是这些消息已经被翻译。创建和维护翻译后的消息集,需要那些精通自己语言并愿意为 PostgreSQL 项目作出贡献的人的帮助。做这件事完全不必是程序员。 本节说明如何提供帮助。

53.1.1. 要求 #

我们不会评判你的语言能力 — 本节讨论的是软件工具。理论上,你只需要一个文本编辑器。 但这只有在你不打算试用自己翻译的消息时才成立,而这种情况不太可能发生。 配置你的源代码树时,请务必使用 --enable-nls 选项。 这还会检查 libintl 库和 msgfmt 程序,而终端用户无论如何也需要它们。要试用你的工作成果,请遵循安装说明中适用的部分。

如果你想开始一项新的翻译工作,或者想执行一次消息目录合并(后文会描述), 则分别需要 GNU 兼容实现的 xgettextmsgmerge 程序。今后我们会尽量做到:如果你使用打包的源码发布版, 就不需要 xgettext 了。(如果从 Git 工作,你仍然需要它。) 目前推荐使用 GNU Gettext 0.10.36 或更高版本。

你本地的 gettext 实现应该自带文档。其中有些内容可能与下文重复, 但要了解更多细节,你应当去查阅那些文档。

53.1.2. 概念 #

原始(英语)消息及其(可能存在的)译文对应项,以成对形式保存在 消息目录中;每个程序以及每种目标语言各有一份消息目录 (尽管相关程序可以共享同一个消息目录)。消息目录有两种文件格式:第一种是 PO 文件(Portable Object,可移植对象),它是带有特殊语法的纯文本文件,由翻译者编辑。 第二种是 MO 文件(Machine Object,机器对象),它是根据相应的 PO 文件生成的二进制文件, 在国际化后的程序运行时使用。翻译者不需要处理 MO 文件;事实上几乎没有人需要。

消息目录文件的扩展名,毫不意外地是 .po.mo。基本名则视情况而定,要么是其所对应的程序名, 要么是该文件所对应的语言。这多少有些令人困惑。例子包括 psql.po (psql 的 PO 文件)或 fr.mo(法语的 MO 文件)。

PO 文件的格式示例如下:

# comment

msgid "original string"
msgstr "translated string"

msgid "more original"
msgstr "another translated"
"string can be broken up like this"

...

msgid 行是从程序源代码中提取出来的。(并非一定如此,但这是最常见的做法。) msgstr 行起初为空,由翻译者填入有意义的字符串。字符串可以包含 C 风格的转义字符, 也可以像上例那样跨多行延续。(下一行必须从行首开始。)

# 字符引入注释。如果 # 字符后面紧跟空白,那么这就是由翻译者维护的注释。 也可能存在自动注释,即 # 后紧跟非空白字符的注释。这些注释由各种处理 PO 文件的工具维护, 目的是帮助翻译者。

#. automatic comment
#: filename.c:1023
#, flags, flags

#. 风格的注释是从使用该消息的源文件中提取出来的。程序员可能已经为翻译者插入了信息, 例如期望的对齐方式。#: 注释指出该消息在源代码中使用的精确位置。 翻译者不必查看程序源代码,但如果对正确译法有疑问,也可以去看。#, 注释包含以某种方式描述该消息的标志。 目前有两种标志:如果某条消息可能因程序源代码的更改而过期,则会设置 fuzzy。 翻译者随后可以核实这一点,并在可能时移除 fuzzy 标志。注意,fuzzy 消息不会提供给终端用户。 另一个标志是 c-format,它表示该消息是一个 printf 风格的格式模板。这意味着译文也应该是一个格式字符串, 并具有相同数量和类型的占位符。有一些工具会据此验证格式字符串,它们就是根据 c-format 标志来检查的。

53.1.3. 创建和维护消息目录 #

好,那么该如何创建一个 空白 消息目录呢?首先,进入包含你想翻译其消息的程序的目录。 如果那里有一个 nls.mk 文件,就说明这个程序已经为翻译做好准备了。

如果已经有一些 .po 文件,那么就说明已经有人做过部分翻译工作。 这些文件命名为 language.po, 其中 languageISO 639-1 两字母语言代码(小写),例如法语对应 fr.po。 如果某种语言确实需要进行多套翻译工作,这些文件也可以命名为 language_region.po, 其中 regionISO 3166-1 两字母国家代码(大写),例如巴西葡萄牙语对应 pt_BR.po。如果你找到了自己想要的语言,就可以直接开始编辑那个文件。

如果你需要开始一项新的翻译工作,先运行以下命令:

make init-po

这会创建一个 progname.pot 文件。 (.pot 用来与已经 投入使用 的 PO 文件区分开来; T 代表 template。) 把这个文件复制为 language.po 并进行编辑。 为了让系统知道新语言已经可用,还要编辑 po/LINGUAS 文件, 在已经列出的语言旁边添加该语言(或语言加国家)代码,例如:

de fr

(当然也可能有其他语言。)

随着底层程序或库发生变化,程序员可能会修改或增加消息。这种情况下你不需要从头开始。 相反,请运行以下命令:

make update-po

它会创建一个新的空白消息目录文件(也就是你最初使用的那个 pot 文件), 并将它与现有的 PO 文件合并。如果合并算法对某条消息拿不准, 就会像上文所述那样把它标记为 fuzzy。新的 PO 文件会以 .po.new 作为扩展名保存。

53.1.4. 编辑 PO 文件 #

PO 文件可以用普通文本编辑器编辑。也有一些专门的 PO 文件编辑器, 可以借助翻译专用功能帮助完成这一过程。Emacs 里(不出意外地)有一个 PO 模式, 相当有用。

翻译者只应修改 msgstr 指令后引号之间的内容、添加注释,以及调整 fuzzy 标志。

PO 文件不必完全填满。如果没有可用译文(或译文为空),软件会自动回退到原始字符串。 把不完整的翻译提交到源码树中也没有问题;这样别人就有机会接手你的工作。不过, 完成一次合并之后,建议优先清除 fuzzy 条目。记住,fuzzy 条目不会被安装; 它们只用来作为可能正确译文的参考。

编辑译文时要记住以下几点:

  • 务必确保如果原文以换行结束,译文也同样以换行结束。制表符等也是如此。

  • 如果原文是一个 printf 格式字符串,译文也必须如此。 译文还需要按相同顺序保留相同的格式说明符。有时语言自身的规则会让这一点变得不可能, 或者至少很别扭。在这种情况下,你可以像下面这样修改格式说明符:

    msgstr "Die Datei %2$s hat %1$u Zeichen."
    

    这样一来,第一个占位符实际上会使用参数列表中的第二个参数。 digits$ 必须紧跟在 % 后面, 位于其他任何格式修饰符之前。(这个特性确实存在于 printf 函数族中。你以前可能没听说过它,因为在消息国际化之外,它几乎没有用武之地。)

  • 如果原始字符串包含语言错误,就报告它(或者你自己在程序源代码中修正它), 然后照常翻译。等程序源代码更新之后,修正过的字符串就可以被合并进来。 如果原始字符串包含事实性错误,就报告它(或者你自己修正它),并且不要翻译它。 相反,你可以在 PO 文件里为该字符串加上一条注释。

  • 保持原始字符串的风格和语气。特别是,那些不是完整句子的消息 (cannot open file %s)通常不应以大写字母开头 (如果你的语言区分大小写),也不应以句号结尾(如果你的语言使用标点符号)。 阅读 Section 52.3 可能会有帮助。

  • 如果你不知道某条消息是什么意思,或者它有歧义,就到开发者邮件列表里提问。 很可能说英语的终端用户也同样看不懂它,或者会觉得它有歧义,因此最好直接改进那条消息。

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。