PostgreSQL程序(服务器和客户端) 可以用你喜爱的语言发出信息 -- 只要那些信息被翻译过.创建和维护翻译过的信息集需要那些熟悉 自己的语言并且希望为PostgreSQL做一些事情的人. 实际上要干这 件事你完全不必是个程序员.本章讲的就是如何帮助PostgreSQL 做这件事.
我们不会评判你的语言能力 -- 本章是有关软件工具的. 理论上,你只需要一个文本编辑器.但这种情况只存在于 你不想看看自己翻译的信息的情况下,这种情况很难发生吧. 在你配置你的源程序的时候,记住要使用 --enable-nls 选项.这样也会检查 libintl 库和 msgfmt 程序,它们是所有最终用户都需要的东西.要试验你的工作, 遵照安装指导中相应的部分就可以了.
如果你想开始一个新的翻译工作或者想做信息表融合工作(下面描述), 那么你就还分别需要有 GNU 兼容的 xgettext 和 msgmerge. 稍后我们将试着安排它,这样,如果你使用的是一个打包的源码发布, 那么你就不再需要xgettext.(从 CVS 里下源码的话, 你还是需要的.)我们现在推荐 GNU gettext 0.10.36 或者更高.
你的局部的 gettext 实现应该和它自身的文档在一起发布. 其中有一些可能和下面的内容重复,但如果要知道额外的 细节,你应该看看它们.
信息原文(英语)和它们的(可能)翻译过的等价物都放在 信息表里,每个程序一个(不过相关的程序 可以共享一个信息表)以及每种目标语言一个. 信息表有两种文件格式∶第一种是 "PO"(Portable Object) 文件 (可移植对象),它是纯文本文件,带一些翻译者编辑的特殊语法. 第二种是 "MO"(Machine Objece) 文件(意思是机器对象), 它是从相应的 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(模糊).翻译者然后就可以核实这些, 然后删除这个模糊标志.请注意模式信息是最终用户不可见的. 另外一个标志是 c-format,它表示该信息 是一个 printf风格的格式模版. 这就意味着翻译也应该是一个格式化字串,带有相同数目和相同 类型的占位符.我们有用于核实这些的工具,它们生成 c 格式(c-format)标志 的键.
好,那我们怎么创建一个"空白"的信息表呢? 首先,进入包含你想翻译信息的程序所在的目录.如果那里有 一个文件叫 nls.mk,那么这个程序就 已经准备好翻译了.
如果目录里已经有一些 .po 文件了, 那么就是有人已经做了一些翻译工作了.这些文件是用 language.po 命名的,这里的 language 是 ISO639-1 规定的两字母语言代码(小写),比如, fr.po 指的是法语.如果每种语言需要多过 一种的翻译,那么这些文件也可以叫做 language_region.po 这里的 region 是 ISO3166-1 规定的两字母国家代码(大写),比如, pt_BR.po 指的是巴西葡萄牙语.如果你找到了 你想要的语言文件,那么你就可以在那个文件上干活.
如果你需要开始一个新的翻译工作,那么首先运行下面的命令
gmake init-po
这样将创建一个文件 progname.pot (用 .pot 和"生产中"使用的 PO 文件区分开.T代表"template"。)把这个文件拷贝成 language.po 然后编辑它.要让程序知道有新语言可以用,还要编辑文件 nls.mk,增加该语言(或者语言和国家) 代码到类似下面这样的行∶
AVAIL_LANGUAGES := de fr
(当然可能还有其它国家.)
随着下层的程序或者库的改变,程序员可能修改或者增加信息. 这个时候,你不必从头再来.只需要运行下面的命令
gmake update-po
它将创建一个新的空信息表文件(你开始时用的 pot 文件)并且会把它 和现有的 PO 文件融合起来.如果融合算法不能确定某条具体的信息 是否融合正确,那么它就会象上面解释那样把它定义为 "fuzzy(模糊)".如果有些事情真是出错了,那么旧的 PO 文件 就会保存为带 .po.old 扩展的.
PO 文件可以用普通的文本编辑器编辑.翻译者应该只修改那些 在 msgstr 指示符后面的双引号中间的内容,也可以增加评注和 修改模糊(fuzzy)标志.Emacs 有一个用于 PO 的模式,我觉得相当好用.
我们不需要把 PO 文件完全填满.如果有些字串没有翻译(或者是一个 空白的翻译),那么软件会自动使用原始的字串.也就是说提交一个 未完成的翻译包括再源码树中并不是一个问题;那样可以留下让其它 人继续你的工作的空间.不果,我们鼓励你在完成一次融合之后 首先消除模糊的条目.要知道模糊的条目是不会被安装的;它们 只起到表示可能是正确翻译的引用的作用.
下面是一些编辑翻译信息的时候要记住的事情∶
确保如果原始信息是以换行结尾的话,翻译信息也如此.类似的情况 适用于 tab 等.
如果最初的字串是 printf 格式的字串,那么翻译串也必须如此. 翻译串还要有同样的格式声明词,并且顺序相同. 有时候语言的自然规则会让这么做几乎不可能或者及其难看. 这时候你可以用下面的格式∶
msgstr "Die Datei %2$s hat %1$u Zeichen."
这样,第一个占位符实际上使用列表里的第二个参数. digits$ 应该跟在 % 后面并且在其它格式操作符之前. (这个特性实际上存在于 printf 家族函数中. 你可能从来没有听说过它,因为除了信息国际化以外它没有什么用处.
如果原始的字串包含语言错误,那么请报告它(或者再程序源文件中 直接修补它),然后按照正常翻译.正确的字串可能跟在程序源文件更新的时候 融合进来.如果最初的字串与事实不符,那么请报告它(或者自己修补它) 但是不要翻译它.相反,你可以在 PO 文件中用注解给该字串做个标记.
维护风格和原始字串的语气.特别是那些不成句子的信息( cannot open file %s)可能不应该以大写字符开头 (如果你的语言区分大小写的话)或者用句号结束(如果你的语言里有 符号标志).
如果你不知道一条消息是什么意思,或者它很含糊, 那么在开发者邮递列表上询问.因为可能说英语的最终用户 也可能不明白它或者觉得它不好理解,所以我们最好改善这些信息.