gettext 国际化使用总结
#gettext 是什么
gettext 是 GNU 的国际化与本地化 (i18n) 函数库。它常被用于编写多语言程序。
GNU gettext 支持 C、C++、Objective-C、Pascal/Object Pascal、sh 脚本、bash 脚本、Python、GNU CLISP,Emacs Lisp、ibrep、GNU Smalltalk、Java、GNU awk、wxWidgets(通过 wxLocale 类)、YCP(YaST2 语言)、Tcl、Perl、PHP、Pike、Ruby 以及 R。
具体来说,GNU gettext 是一组工具,其他软件包可以在其中生成国际化消息。这些工具包括:
- 一套关于如何编写程序以支持消息目录的约定: mo、po 和 pot 文件格式。
- 消息目录本身的目录和文件命名组织: locale 目录结构。
- 一个支持检索翻译消息的运行时库: gettext 库。
- 一些独立的程序,用于以各种方式处理可翻译字符串集或已翻译字符串: xgettext、msgmerge、msgfmt 等。
- 一个支持解析和创建包含翻译消息的文件的库。
- Emacs 的一个特殊模式,它有助于准备这些集合并使其保持最新。
#gettext i18n 使用流程
在源代码中绑定语言文件,并使用
gettext函数获取翻译后的字符串。例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main() {
// 设置当前环境的本地化信息
setlocale(LC_ALL, "");
// 将 domain 绑定到本地目录 LOCALEDIR
// gettext 将使用路径: LOCALEDIR/language/LC_MESSAGES/PACKAGE.mo 查找 .mo 文件
// 不以前缀 '/' 开头时,LOCALEDIR 被认为是相对路径
bindtextdomain(PACKAGE, LOCALEDIR);
// 设置当前使用的 domain
textdomain(PACKAGE);
printf(_("Hello, World!\n"));
}libintl.h头文件定义了gettext函数。宏_()用于标记需要翻译的字符串。libintl已经包含在 glibc 中,因此链接 glibc 时无需额外链接。使用
xgettext工具从源代码中提取标记的字符串,生成一个 POT (Portable Object Template) 文件:1
xgettext -k_ -o myprogram.pot myprogram.c
文件
myprogram.pot将包含所有需要翻译的字符串。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-11-09 13:06+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: myprogram.c:21
#, c-format
msgid "Hello, World!\n"
msgstr ""为需要翻译的目标语言创建/更新对应的 PO (Portable Object) 文件:
如果是第一次创建某个语言的 PO 文件,可以使用
msginit工具:1
msginit -l zh_CN -i myprogram.pot -o zh_CN.po
如果 PO 文件已经存在(已经有一部分翻译,程序中增加了新的条目),可以使用
msgmerge工具更新:1
msgmerge -U zh_CN.po myprogram.pot
翻译人员进行翻译,更新
LANG.po文件中的msgstr字段。1
2
3
4#: myprogram.c:21
#, c-format
msgid "Hello, World!\n"
msgstr "你好,世界!\n"使用
msgfmt工具将 PO 文件编译为供程序读取的 MO (Machine Object) 文件:1
msgfmt zh_CN.po -o zh_CN.mo
MO 文件是二进制格式,供程序在运行时使用。
将生成的 MO 文件安装到系统中,例如:
1
install -Dm644 zh_CN.mo ./zh_CN/LC_MESSAGES/myprogram.mo
运行程序时,设置正确的环境变量,即可切换到对应的语言:
1
2
3
4
5LANG=zh_CN.UTF-8 ./myprogram
你好,世界!
LANG=en ./myprogram
Hello, World!