在 Linux 环境下, 主流的软件翻译方法是通过工具抓取源代码中的需翻译字符串到外部文本文件, 形成一个字典, 翻译之后在运行期加载. 更专业一点就是, 从软件本身要能国际化 (internationalization, 一般简写为 i18n, 因为 i 和 n 之间有 18 个字符), 支持从源代码中提取字符串来翻译; 而翻译这个步骤则成为本地化 (localization, 简称 l10n).
要让软件具备国际化属性, 这必须程序员们亲自努力, 为需翻译字符串附加一些修饰. 如下面这个程序
int main(int argc, char* argv[])
{
if (1 == argc || 0 == strcmp("hello", argv[1]))
{
puts("Hello");
}
else
{
puts("World");
}
return 0;
}
要加上区分信息很简单, 比如
#define TRANSLATE_THIS(x) x
int main(int argc, char* argv[])
{
if (1 == argc || 0 == strcmp("hello", argv[1]))
{
puts(TRANSLATE_THIS("Hello"));
}
else
{
puts(TRANSLATE_THIS("World"));
}
return 0;
}
$ xgettext hello.c --keyword=TRANSLATE_THIS -o hello.po
那么 xgettext 将提取被宏
TRANSLATE_THIS
所包括的所有字符串到 hello.po 纯文本文件中.在 po 文件中, 每个被提取的字符串是一个 msgid, 而翻译则是接下来一行中的 msgstr, 现在所有的 msgstr 都空着, 在 po 文件中直接写入翻译结果并保存即可. 此外还要指定 po 文件头部有文件编码等信息.
翻译完成后, 在本地创建 locale 相关目录, 再使用 msgfmt 工具编译 po 文件为二进制文件, 并放入 locale 目录中
$ mkdir -p $LANG/LC_MESSAGES && msgfmt hello.po -o $LANG/LC_MESSAGES/hello.mo
这个目录的意义待会儿再解释.
使用纯文本编辑器盯着 po 文件翻译条目是很累很无趣的事情, 好在有许多工具可以选取. 比较流行的有 poEdit 和 Qt Linguist. 接下来继续讨论程序的事情.
到此为止, 程序本身还不具备本地化的能力, 因为宏
TRANSLATE_THIS
什么也没干, 程序本身的逻辑并没有变化, 也不知道如何导入翻译目标字符串替换原有字符串. 现在将宏定义换掉, 使用 locale 中的组件来完成本地化工作