gettext是GNU世界里用来实现i18n的标准方式,下面用一个小例子来演示它的用法。 源文件gettext_demo.c #include <libintl.h> #include <locale.h> #include <libintl.h> 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的用处
错误集中: "msgfmt: messages.po: warning: Charset "CHARSET" is not a portable encoding name. Message conversion to user's charset might not work. "
解决方法:把message.po里面的CHARSET换成UTF-8或其他编码格式
有时候hello不会被翻译为"你好"有可能是你的xxx.mo的路径不对.在strace ./a.out的时候你看一下最后的信息,看一下程序会调用哪个路径的.mo去翻译,根据错误去改变.mo的路径,就正确了!