第 9 章 本地语言支持
9.1. 给翻译者 #
PostgreSQL 程序(服务器和客户端)可以用你喜欢的语言发出消息——前提是消息已被翻译。创建和维护翻译的消息集需要语言说得好并想为 PostgreSQL 做贡献的人的帮助。做这件事你完全不必是程序员。本节说明如何提供帮助。
9.1.1. 要求
我们不会评判你的语言能力——本节讲的是软件工具。理论上,你只需要一个文本编辑器。但这只在你不想试用翻译的消息这种不太可能的情况下成立。配置源代码树时,请务必使用 --enable-nls 选项。这还会检查 libintl 库和
msgfmt 程序,所有最终用户反正都需要它们。要试用你的工作成果,请按安装说明中适用的部分操作。
如果想开始一项新的翻译工作或想做消息目录合并(后文描述),你分别需要 GNU 兼容实现中的程序 xgettext 和
msgmerge。以后我们会尽力安排成使用打包的源码发行版时不需要
xgettext。(从 CVS 获取则仍需要它。)目前推荐
GNU gettext 0.10.36 或更新版本。
你本地的 gettext 实现应该自带文档。其中有些内容可能与下文重复,但要了解更多细节,你应当去查阅那些文档。
9.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 标志来检查的。
9.1.3. 创建和维护消息目录
好,那么如何创建一个“空白”消息目录呢?首先,进入包含你想翻译其消息的程序的目录。如果存在文件
nls.mk,说明该程序已经为翻译做好了准备。
如果已经有一些 .po 文件,那么就说明已经有人做过部分翻译工作。这些文件命名为 ,其中 language.polanguage 是
ISO 639-1 两字母语言代码(小写),例如法语对应 fr.po。如果某种语言确实需要进行多套翻译工作,这些文件也可以命名为
,其中 language_region.poregion 是
ISO 3166-1 两字母国家代码(大写),例如巴西葡萄牙语对应
pt_BR.po。如果你找到了自己想要的语言,就可以直接开始编辑那个文件。
如果你需要启动一项新的翻译工作,先运行命令
gmake init-po
这会创建文件
。(用 progname.pot.pot 来与“正在使用中”的
PO 文件区分。T 代表什么?我也不知道。)把这个文件复制为
并编辑它。为了让别人知道新语言已可用,还要编辑文件 language.ponls.mk,把语言(或语言和国家)代码加到形如下面的行中:
AVAIL_LANGUAGES := de fr
(当然也可以是其他语言。)
随着底层程序或库的变化,程序员可能会更改或添加消息。这种情况下不必从头开始,只需运行命令:
gmake update-po
该命令会创建一个新的空白消息目录文件(即你最初使用的 pot 文件),并把它与现有的 PO 文件合并。如果合并算法对某个消息没有把握,就会如上所述把它标记为“模糊”。万一哪里真的出了问题,旧的 PO 文件会以.po.old扩展名保存。
9.1.4. 编辑 PO 文件
PO 文件可以用普通文本编辑器编辑。翻译者只应修改 msgstr 指令后引号之间的内容、添加注释,以及调整 fuzzy 标志。Emacs 里(不出意外地)有一个 PO 模式,相当有用。
PO 文件不必完全填满。如果没有可用译文(或译文为空),软件会自动回退到原始字符串。把不完整的翻译提交到源码树中也没有问题;这样别人就有机会接手你的工作。不过,完成一次合并之后,建议优先清除 fuzzy 条目。记住,fuzzy 条目不会被安装;它们只用来作为可能正确译文的参考。
编辑译文时需要记住下面几点:
务必确保如果原文以换行结束,译文也同样以换行结束。制表符等也是如此。
如果原文是 printf 格式串,译文也需要是。译文还需要以相同的顺序包含相同的格式说明符。有时语言自身的规则会让这一点变得不可能,或者至少很别扭。这种情况下可以使用这种格式:
msgstr "Die Datei %2$s hat %1$u Zeichen."
这样一来,第一个占位符实际上会使用参数列表中的第二个参数。
必须紧跟在 % 后面,并位于其他任何格式修饰符之前。(这个特性确实存在于digits$printf函数族中。你以前可能没听说过它,因为在消息国际化之外它几乎没有用武之地。)如果原始字符串包含语言错误,就报告它(或者你自己在程序源代码中修正它),然后照常翻译。等程序源代码更新之后,修正过的字符串就可以被合并进来。如果原始字符串包含事实性错误,就报告它(或者你自己修正它),并且不要翻译它。相反,你可以在 PO 文件里为该字符串加上一条注释。
保持原字符串的风格和语气。具体来说,不是完整句子的消息(
cannot open file %s)也许不应以大写字母开头(如果你的语言区分大小写),也不应以句点结尾(如果你的语言使用标点符号)。如果你不知道某条消息是什么意思,或者它有歧义,就到开发者邮件列表里提问。很可能说英语的终端用户也同样看不懂它,或者会觉得它有歧义,因此最好直接改进那条消息。