使用GetText本地化编程
介绍
GetText 是 GNU 的一个项目,GetText 主页有最丰富的信息。下面大致翻 译一下 GetText 主页的介绍 :
“通常,程序及其文档信息都是用英语语言写的,程序运行时同用户交 互的信息也是英语。这是一个事实,不仅仅 GNU 的软件是这样,其他大 部分私有软件或自由软件也是这样。一方面,对于来自所有国家的开 发者、维护者和用户来说,相互沟通中使用一种通用的语言非常的方便。另一方面,相对于母语来说大多数人并不适应使用英语,而且他 们的日常工作都是尽可能的使用他们自己的母语。多数人都会喜欢他 们的计算机屏幕显示的英语更少,显示的母语更多。"
" GNU 的 'gettext' 是 GNU 翻译项目的一个重要步骤,我们依赖于它 来作很多其他的步骤。这个软件包给程序员、翻译者,或者用户提供 了一套集成工具和文档。详细地说,GNU gettext 提供了一套工具, 能让其他 GNU 软件创建多语言信息。…"
gettext 的工作流程是这样的:比如我们写一个 C 程序,通常 printf 等输 出信息都是 English 的。如果我们在程序中加入 gettext 支持,在需要交 互的字符串上用 gettext 函数,程序运行是就可以先调用 gettext 函数处 理字符串,替换当前的字符串了。注意是运行时替换。
例子
#include <stdio.h> #include <locale.h> #include <libintl.h> /*使用gettext通常使用类似下面的一个带函数的宏定义 *你完全可以不用,直接使用 gettext(字符串) */ #define _(S) gettext(S) /*PACKAGE是本程序最终的名字(运行时输入的命令)*/ #define PACKAGE "jian_gettext" int main(int argc, char **argv) { /* 下面三个参数都是使用gettext时候需要使用的 * setlocale * bindtextdomain * textdomain */ setlocale(LC_ALL,""); bindtextdomain(PACKAGE, "locale"); textdomain(PACKAGE); printf(_("Hello,GetText!\n")); return 0; }
使用 gettext 的流程
- 头文件包含:
#include <locale.h> #include <libintl.h>
- 定义宏定义(完全是为了方便,而且几乎所有程序都这样)
#define _(S) gettext(S)
- 设置 locale 和 mo 文件将要存放的路径,关联程序
setlocale(LC_ALL,""); bindtextdomain(PACKAGE, "locale"); textdomain(PACKAGE);
- 制作 po 文件(示例程序是:jian_gettext.c)
xgettext -a jian_gettext.c -o jian_gettext.po --from-code=utf-8
- 修改生成的 jian_gettext.po 文件,将下面行中的 CHARSET 换成 UTF-8
"Content-Type: text/plain; charset=CHARSET\n"
再翻译其中的 string(其他的 string 不要改):
#: jian_gettext.c:14 #, c-format msgid "Hello,GetText!\n" msgstr "你好,GetText!\n"
- 生成 mo 文件,
msgfmt jian_gettext.po -o jian_gettext.mo
- 创建存放 mo 文件的目录,(例子使用./locale)
mkdir -pv locale/zh_CN/LC_MESSAGES/ cp -v jian_gettext.mo locale/zh_CN/LC_MESSAGES/
- 运行程序,你的程序应该是这样编译好的:
gcc -Wall -o jian_gettext jian_gettext.c
如果没有错误,上面的程序运行结果如下:
# ./jian_gettext 你好,GetText!
细节
setlocale()
setlocale(LC_ALL,"") 的意思是使用环境变量(系统当前的值)
xgettext
- -k 参数 可以只搜索某些字符串,没有用的信息省略。
xgettext jian_gettext.c -k_ -o jian_gettext.po
- -l 参数 可以针对某一语言生成 po 文件,中文为例:
msginit -l zh_CN -i jian_gettext.po
上面命令会生成 zh_CN.po 文件,可由此修改生成 mo 文件
多文件的 PO
一个开源项目中,通常有很多源文件,我们都需要翻译其中的字符串。通常步骤 如下:
进入 PO 目录执行(一定要是 PO 目录):
intltool-update -m
得到一个文件列表告诉我应该把它们加入 POTFILES.in 文件.
跳到 PO 目录的父目录,使用新的 POTFILES.in 生成 POT 文件::
xgettext -a -f po/POTFILES.in -o po/xxx.pot
我使用的一个示例:
xgettext -k_ -f po/POTFILES.in -o po/mutter-moblin.pot --from-code="utf-8" intltool-update —pot # 生成 pot 文件 intltool-update —maintain
创建 po 文件
创建并进入/po 目录,创建 POTFILES.in,内容为你需要提取源码中有需要翻译的 字符串的源文件列表,每行一个文件,然后执行 intltool-update —pot
产生 pot 文件,如果将来你在维护代码中代码有变化或者在 POTFILES.in 中新增了源文件, 可用 intltool-update —maintain 更新。
有了 pot 文件,现在需要产生各种语言的 po 文件,如 msginit —locale=zh_CN
产生 中文 po 文件,如将来源文件有变化可以 intltool-update zh_CN
更新 zh_CN.po,接 下来翻译的工作就是你自己来做了。
要生成特定语言的 mo 文件,需要维护 configure.ac 中的 ALL_LINGUAS,以空格分隔 就可以了