2006年7月16日星期日

gettext的用法

gettext是GNU世界里用来实现i18n的标准方式,下面用一个小例子来演示它的用法。
源文件gettext_demo.c
#include

#include
#include

int main()
{
// 设置程序的locale
setlocale(LC_ALL, "");
// 为你的程序选择一个domain
textdomain("gettext_demo");
// 为这个domain绑定一个目录,就用当前目录吧
bindtextdomain("gettext_demo", ".");
// 指定输出所用的编码,通常你不需要用它
bind_textdomain_codeset("gettext_demo", "UTF-8");

// 来,跟大家say hello一下
printf(gettext("Hello\n"));
return 1;
}

编译执行之:
$gcc gettext_demo.c
$./a.out
Hello

好像没什么变化,别急,让我们看看底层发生了什么!
$strace ./a.out
....(略去无关输出)
open("/workspace/learn/gettext/./zh_CN.UTF/LC_MESSAGES/gettext_demo.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/workspace/learn/gettext/./zh_CN/LC_MESSAGES/gettext_demo.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/workspace/learn/gettext/./zh.gb2312/LC_MESSAGES/gettext_demo.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/workspace/learn/gettext/./zh/LC_MESSAGES/gettext_demo.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
....(略去无关输出)

看起来,程序在试图找到一个叫gettext_demo.mo的文件。这个文件里保存了"Hello"在当前locale下应该被翻译成什么的信息。下面让我们来生成这个文件。
$xgettext gettext_demo.c // 从源文件里获取要翻译的字符串,得到一个叫message.po的文件
打开这个文件看看,稍微有点脑子的人就知道是怎么回事。你当然可以用vi之类的编辑器来编辑,不过还有专门的工具像poedit,kbabel,推荐使用这些工具,把msgid "Hello\n"对应的msgstr设成"你好\n"就算翻译完了。然后执行:
$msgfmt message.po
这样你得到一个message.mo的文件(po是potable object的意思,mo是machine object的意思),这个东东就是上面程序在找的gettext_demo.mo。下一步把message.mo放到合适的位置就行了。
$mkdir -p zh_CN.UTF/LC_MESSAGES
$mv message.mo zh_CN.UTF/LC_MESSAGES/gettext_demo.mo
再执行./a.out,程序就会输出“你好”了。

课外习题:
1. 研究一下bind_textdomain_codeset的用处

没有评论: