GNU gettext 是一套GNU下的国际化工具,几乎支持所有Linux下的计算机语言。在gettext的帮助下,可以轻松完成程序的国际化。
一、相关文件
- .pot
- po 的模版,可由xgettext生成
- .po
- 翻译的源,可由msginit + .pot生成
- .gmo
- 编译后的po,可由 msgfmt + .po 生成
- .mo
- 同上,只是gmo通常指的是未安装的mo,可由 install + .gmo 生成
二、相关工具
- xgettext
- 从源代码中提取需要翻译的字串,生成pot文件
- msginit
- 替换pot中的Entry信息,如译者,文件编码等
- msgmerge
- 合并现有的.po文件
- msgfmt
- 把.po文件生成.gmo或.mo文件
三、相关函数
- bindtextdomain(const char *domain, const char *dirname)
- 通过domain与dirname绑定mo文件的域
- textdomain (const char *domainname)
- 指定gettext所用的域
- gettext(const char *msgid):
- 由locale与textdomain指定的domain得到翻译后的字串
- ngettext(const char *msgid1, const char *msgid2, unsigned long int n):
- 通过n返回单数的msgid1 或 复数的msgid2
- dgettext(const char *domain, const char *msgid)
- 指定domain的gettext
- dngettext(const char *domain, const char *msgid, unsigned long int n);
- 指定domain的ngettext
- dcgettext(const char *domain, const char *msgid, int category):
- 指定domain与category的gettext
- dcngettext(const char *domain, const char *msgid1, const char *msgid2, unsigned long int n, int category):
- 指定domain与category的ngettext
gettext的dirname, locale domain, category, 在磁盘上的结构为
dirname/locale/category/domain.mo
如
/usr/share/locale/zh_CN/LC_MESSAGES/gettext_demo.mo
默认的category为LC_MESSAGES
四、实例
1. 新建文件 gettext_demo.c
#include <locale.h>
#include <libintl.h>
#include <stdio.h>
#define _(string) gettext(string)
const char *DOMAIN = "gettext_demo";
const char *DIRNAME = "languages";
int main(int argc, char **argv) {
/* 设置locale与系统一致 */
setlocale(LC_ALL, "");
/* 添加域 gettext_test 在目录 po */
bindtextdomain(DOMAIN, DIRNAME);
/* 设定默认域为 gettext_test */
textdomain(DOMAIN);
/* gettext(Hello World) */
puts(_("Hello"));
return 0;
}
2. 制作zh_CN.UTF-8的语言包
gettext_demo$ ls
gettext_demo.c
gettext_demo$ mkdir po
gettext_demo$ cd po
由xgettext生成pot
gettext_demo/po$ xgettext -k_ --package-name gettext_demo --package-version 0.1 ../*.c -o gettext_demo.pot
gettext_demo/po$ ls
gettext_demo.pot
由gettext_demo.pot生成zh_CN.po
gettext_demo/po$ msginit #因为我的系统locale为zh_CN.UTF-8,因此msginit自动生成针对zh_CN.UTF-8的po
gettext_demo/po$ ls
gettext_demo.pot zh_CN.po
修改po文件
#: ../gettext_demo.c:22
msgid "Hello"
msgstr ""
为
#: ../gettext_demo.c:22
msgid "Hello"
msgstr "你好"
由zh_CN.po生成zh_CN.mo
gettext_demo/po$ msgfmt zh_CN.po -o zh_CN.mo
gettext_demo/po$ ls
gettext_demo.pot zh_CN.mo zh_CN.po
复制zh_CN.mo到../languages/zh_CN/LC_MESSAGES/gettext_demo.mo
gettext_demo/po$ mkdir -p ../languages/zh_CN/LC_MESSAGES
gettext_demo/po$ cp zh_CN.mo ../languages/zh_CN/LC_MESSAGES/gettext_demo.mo
编译并测试
gettext_demo$ gcc gettext_demo.c -o gettext_demo
gettext_demo$ ls
gettext_demo gettext_demo.c languages po
gettext_demo$ ./gettext_demo
你好
测试英文环境
gettext_demo$ LC_ALL=en_US ./gettext_demo
Hello
如果尝试 LC_ALL=zh_CN.GBK ./gettext_demo 在UTF-8环下显示"乱码",因为显示的是GBK编码,gettext转换到相应的编码了。</pre>
当系统发生变化时,添加了新的语句,为此通过工具msgmerge进行和并
修改 gettext_demo.c
/* gettext(Hello World) */
puts(_("Hello"));
为
/* gettext(Hello World) */
puts(_("Hello"));
puts(_("World"));
gettext_demo/po$ xgettext -k_ --package-name gettext_demo --package-version 0.1 ../*.c -o gettext_demo.pot
gettext_demo/po$ msgmerge zh_CN.po gettext_demo.pot -o zh_CN.po
. 完成。
修改文件 zh_CN.po
#: ../gettext_demo.c:23
msgid "World"
msgstr "世界"
得新生成并复制zh_CN.mo到../languages/zh_CN/LC_MESSAGES/gettext_demo.mo
测试
gettext_demo$ ./gettext_demo
你好
世界
我按照您的方法实验过了,可是最后运行的时候不能出线中文字符。
系统是Ubuntu 10.04,安装了gettext包
locale使用zh_CN.utf8: export LANG=zh_CN.utf8
不知道是哪里出了问题,已经看过很多教程了,可是没有一个能成功的。
可否贴出源码?
就是复制程序代码,如何修改locale呢,我的修改方法正确么?
我默认的locale是en_US.utf8 LANGUAGE=en这个有关系么?
可能是你相应locale没有安装。
locale -a 查看
或者是LC_MESSAGES的locale不正确
gettext一般使用的是LC_MESSAGES,本文例子也是。
可以指定LC_MESSAGES = zh_CN.UTF-8
或者
LC_ALL = zh_CN.UTF-8
更多关于locale的信息可以参见我的另外一篇文章
http://www.jiangmiao.org/blog/1265.html
我用的 debian 6 locale使用zh_CN.utf8,测试下来 都没问题,就是最后再设置成英文LC_ALL=en_US时,并执行程序,还是显示中文 ,代码是你的测试源码
把xshell 的 编码由 gb2312 改成 默认的 utf-8 就好了