1 采用 GNU gettext提供多语言支持
原理就是: 当你在输出的字符串前加上 gettext
函数时,系统会去对应的文件(.mo文件)中找该字符串是否存在翻译,如果存在就显示翻译后的字符串,如果没有对应翻译项就直接显示。
- 一个小例程,用于演示:
cat >hello.cpp <<EOF
// hello.cpp
#include <libintl.h>
#include <locale.h>
#include <iostream>
int main (){
setlocale(LC_ALL, "");
bindtextdomain("hello", ".");
textdomain( "hello"); // 这里设置.mo的文件名字为: hello.mo
std::cout << gettext("hello, world!") << std::endl; // 输出的字符串,用于被替换的
}
EOF
- 编译上述文件:
g++ -o hello hello.cpp
- 找出源代码中所有需要转换的字符串,并生成 .pot 文件。(Extracted text from C++ source file (portable object template))
// -d, --default-domain=名称 使用<名称.po>输出(而不是 messages.po)
// -o, --output=文件 将输出写入指定文件
// -kWORD, --keyword=WORD 查找 WORD 作为一个额外的关键字(如果字符串用额外的关键字标出了,例如: _("Hello world!\n"),则关键字为 _ )
// 如果关键字不是 gettext 则需要显式加上 -k 选项
xgettext --package-name hello --package-version 1.2 --default-domain hello --output hello.pot hello.cpp
// 可以简化为:
xgettext -kXXX -o hello.pot XXX.cpp
- 将 .pot 文件转换成 .po 文件,并编辑。注:可以不通过源文件生成的.po文件直接自己一条一条添加,这个.po文件可以跨系统,用于生成.mo文件。(Modified text for Chinese with translations added)
-
// --no-translator 表示:假定 PO 文件是自动生成的,不然会让你输入电子邮件地址,以反馈翻译问题 msginit --no-translator --locale zh_CN.UTF-8 --output-file hello_chinese.po --input hello.pot 简化版:msginit -l zh_CN.UTF-8 -i hello.pot -o hello.po // 编辑 hello_chinese.po 文件,并添加替换中文翻译字符串 #: hello.cpp:9 msgid "hello, world!" msgstr "你好,世界!"
- 将 .po 文件转化为 .mo 文件,该文件即为我们最后需要使用的文件。(Binary translated text for Chinese used at run-time)
mkdir -p zh_CN.UTF-8/LC_MESSAGES
msgfmt --check --verbose --output-file ./zh_CN.UTF-8/LC_MESSAGES/hello.mo hello_chinese.po
- 设置环境变量,运行程序即可:
export LANG=zh_CN.UTF-8 # locale 查看系统变量
export LANGUAGE=zh_CN.UTF-8 # 该环境变量决定了你去哪个文件夹中找 .mo 文件
./hello
2 关于格式化字符串(即在 .po 文件中匹配数字等):
C/gettext:
snprintf(msg,sizeof(msg),gettext("This is the message to %1$s about %2$s"),who,what);
C++/gettext:
using boost::format;
std::ostringstream ss;
ss << format(gettext("This is the message to %1% about %2%")) % who % what;
C++ using boost.locale:
using boost::locale::format;
using boost::locale::translate;
std::ostringstream ss;
ss << format(translate("This is the message to {1} about {2}")) % who % what;