Archive:Development/Tutorials/Localization/i18n Build Systems (zh CN)
摘要
现在您的程序能够本地化了,我们接下来考虑怎样把这个重要的机能合并到您程序的Cmake系统中去。 首先我们“理论”上解释用于安装.po文件时解压缩信息字符串所需要的步骤。然后我们来看怎么实现这些步骤(#Theory: The xgettext toolchain)。如果您的程序书用KDE的subversion开发的,很多步骤是自动完成的(参见 #handling i18n in KDE's subversion repository)。 如果不是,请参见 #handling i18n in third party applications 部分。
理论: xgettext 工具
翻译需要以下步骤:
- 提取出要翻译的字符串
- 将新翻译的字串和已有的翻译合并在一起
- 将翻译编译进消息目录
- 安装消息目录
- 在程序中使用消息目录
提取字符串
本步骤中,需要收集您代码中所有标记为 i18n()/ki18n()/etc. 的字串到一个临时翻译文件 (.pot) 文件中。 有些待翻译字串在.ui, .rc, or .kcfg 文件中. 此外也要把每日一帖搜集到.pot文件中.
这个步骤是由 xgettext, extractrc, 和 preparetips 这些程序分别完成的。有些情况下,您也会用到 extractattr.
合并翻译结果
一般来讲,一次改动只需要更改少部分的可翻译字串:有些要移除,有些要添加,有些要替换,有些要改变在代码中的位置。这些改变需要在翻译中得到体现。但显然每次(更新)都重做所有的翻译是一件耗力的工作,把原有的翻译和那些改变的东西合并在一起会更好。这时需要 msgmerge 工具。
编译翻译结果
为了更快查找信息,需要编译.po文件成所谓的 "消息目录" (.mo / .gmo)。这可由 msgfmt 工具完成.
安装消息目录
编译好的信息目录需和程序一起安装。在KDE系统中,标准的消息目录的路径是 $KDEDIR/share/locale/xx/LC_MESSAGES/。
使用消息目录
最后,当程序能够运行,程序会载入消息目录来查找和显示翻译的字串。 在大多数情形,对KDE程序而言,这是由KLocale 类自动完成的。
一些特殊的情形,比如说插件,请参看 #Runtime Loading Of Catalogs.
在KDE的 subversion库中处理
如果您使用KDE subversion库做开发,上述大部分的步骤都是自动完成的。此时,您只需要提供一个Messages.sh脚本。我们下面会提到这个脚本。
此外,如果您的根目录和.pot文件重名,当您对代码打包时,svn2dist脚本会自动包含.po文件
当然,进行这一步骤所做的详细幕后信息会被提供。
编辑 Messages.sh 脚本
通常地,准备和安装一个KDE subversion 库程序的翻译只需要提供“信息”。包括了需要翻译的代码, ui文件和提示。就此而言,您只要写一小段 Messages.sh 代码,并把他放置到您的代码中就好了。下面是一个带注释的例子:
- !bin/sh
- invoke the extractrc script on all .ui, .rc, and .kcfg files in the sources
- the results are stored in a pseudo .cpp file to be picked up by xgettext.
$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp
- if your application contains tips-of-the-day, call preparetips as well.
$PREPARETIPS > tips.cpp
- call xgettext on all source files. If your sources have other filename
- extensions besides .cc, .cpp, and .h, just add them in the find call.
$XGETTEXT `find . -name \*.cc -o -name \*.cpp -o -name \*.h` -o $podir/APPNAME.pot
可以发现,这段脚本实际上只含有三行代码,而且这三段并不都是必要的。$XGETTEXT, $PREPARETIPS, $EXTRACTRC 和 $podir 环境变量是预先定义好的,不需要考虑。您只需要将 "APPNAME" 替换成您的程序的名字 (参见 #Naming .pot Files 描述了例外的情形)。
请确定您的Messages.sh 脚本概括了所有需要的信息。如有疑问,请查看其它KDE subversion库中程序的示例,或者,询问。
幕后的故事
每隔一段时间, KDE 服务器会运行extract-messages.sh (又称为scripty) 脚本。这个脚本会使用适当的参数调用库中所有的Messages.sh。 提取所得的信息胡储存在一个l10n模块的一个临时文件夹的临时的 (.pot) 文件。参见 What Is Scripty。
KDE翻译组会翻译这些信息将其并放在相应语言的文件夹中。这些文件夹会由模块细分。例如,德语翻译会被放置在l10n/de/messages/kdebase/konqueror.po中.
当l10n模块构建完成, 相应的.po文件会被编译成二进制形式的.mo文件以供更快的查询和显示。.mo files 在 $KDEDIR/share/locale/xx/LC_MESSAGES/中,其中 xx 是个两字符的 ISO 639 相对于该语言的编码。这被称为消息目录。
运行时 i18n(...) 函数会使用您代码中原有的字串,并查询用户桌面所使用的语言,从而查询消息目录并替换成用户相应的语言。 如果消息目录缺失,或者指定的字串没有找到,i18n(...) 会使用您程序中原有的字串。
您项目中的.desktop文档会被单独处理。makemessages提取字串,比如说将,desktop文件中的名字和注释放置在临时文件夹一个名为desktop_mmmm.pot的文件中,其中 mmmm 是模块的名字。翻译者完成翻译了文档,要将翻译的文本插入回到.desktop文件中。提取的字串列在l10n/scripts/apply.cc中. Here's the code that checks for them:
if (checkTag("Name", in, argc, argv, newFile))
continue;
if (checkTag("Comment", in, argc, argv, newFile))
continue;
if (checkTag("Language", in, argc, argv, newFile))
continue;
if (checkTag("Keywords", in, argc, argv, newFile))
continue;
if (checkTag("About", in, argc, argv, newFile))
continue;
if (checkTag("Description", in, argc, argv, newFile))
continue;
if (checkTag("GenericName", in, argc, argv, newFile))
continue;
if (checkTag("Query", in, argc, argv, newFile))
continue;
if (checkTag("ExtraNames", in, argc, argv, newFile))
continue;