gettext软件包提供给程序员、翻译人员,甚至用户,一套完整的工具和文档来帮助生成多语言消息。
由于gettext库采用GPL,无法在商用软件中使用,不过仍可以使用gettext工具包来进行代码中的字符串处理。
代码中的字符串ID和前置注释
gettext可以处理类似以下格式的字符串ID相关代码:
// STR_ACCOUNT_LOGIN=尊敬的%s,您登录游戏的时间:%s 登录城市:%s。
_snprintf(szInfo, sizeof(szInfo) - 1, g_objStrMgr.GetStr("STR_ACCOUNT_LOGIN"), ...
批处理文件示例
使用以下批处理文件提取示例代码中的字符串ID及前置注释:
::Requires GnuWin32 touch, xgettext, msginit, iconv, sed
CD /D "%0\.." 1>NUL 2>&1
DEL client.po gb18030.po msgid.po msgstr.po msgstr.txt 1>NUL 2>&1
touch client.po
FOR %%X IN (3DRole\Network\*.cpp, 3DRole\*.cpp, BaseCode\*.cpp, MyShell\*.cpp) DO (
xgettext --from-code GB18030 -d client -j -c -kGetStr -s %%X
)
REM msginit --locale=zh_CN --no-wrap -i client.po
iconv -c -f utf-8 -t gb18030 client.po > gb18030.po
sed -l 0 -n -e "/^msgid \"\(.*\)\"/ s//\1/p" gb18030.po | uniq > msgid.po
sed -l 0 -n -e "/^#\. / { /^#\. ~/ d; p }" gb18030.po | uniq > msgstr.po
sed -l 0 -n -e "/^#\. / s///p" msgstr.po > msgstr.txt
在实际项目使用时,需要替换”FOR %%X IN (…)”括号内的源代码文件名匹配规则和xgettext命令的-k参数。
client.po和gb18030.po
使用xgettext提取并在client.po和gb18030.po中保存的信息:
#. STR_ACCOUNT_LOGIN=尊敬的%s,您登录游戏的时间:%s 登录城市:%s。
#: MyShell\DlgAccountLoginAlert.cpp:175
msgid "STR_ACCOUNT_LOGIN"
msgstr ""
当多个文件引用了同一个字符串ID,或者同一文件多处引用了同一个字符串ID,以”#: “开头的行(或多行)包含了所有引用文件及行号。例如:
#. STR_ACCOUNT_LOGIN_DIFF=与本次登录不同。
#: MyShell\DlgAccountLoginAlert.cpp:171 MyShell\DlgAccountLoginAlert.cpp:176
msgid "STR_ACCOUNT_LOGIN_DIFF"
msgstr ""
msgid.po
包含gb18030.po中msgid开头的行中引号内的字符串ID:
STR_ACCOUNT_LOGIN
msgstr.po
包含gb18030.po中的前置注释行:
#. STR_ACCOUNT_LOGIN=尊敬的%s,您登录游戏的时间:%s 登录城市:%s。
msgstr.txt
删除了msgstr.po中的前置”#. “:
STR_ACCOUNT_LOGIN=尊敬的%s,您登录游戏的时间:%s 登录城市:%s。
批处理文件说明
使用gettext工具包提取代码中的字符串配置,基本原理和步骤如下:
- 使用xgettext,通过指定参数”-kGetStr”将代码中的GetStr(“字符串ID”)中的”字符串ID”及前置注释行提取到client.po文件;
- 使用iconv将client.po(UTF8编码)转换为gb18030.po(GB18030编码),因为sed在中文命令提示符窗口环境处理UTF8编码的文件会出错,所以先将文件转换为GB18030编码;
- 使用sed将gb18030.po中的字符串ID提取到msgid.po,用于后期字符串ID配置项的检查;
- 使用sed将gb18030.po中的代码注释提取到msgstr.po和msgstr.txt。其中msgstr.po保留了gb18030.po原始行的格式,方便文件比较;msgstr.txt是去掉”#. “的,如果代码注释编写符合规范,稍作修改即可作为正式资源发布。
优点
- msgid.po文件直接从代码导出,与程序版本同步,避免了人工处理字符串ID可能出现错漏、重复和多余的情况;
- 如果代码中字符串ID的前置注释符合一定规则,就可以直接从代码导出msgstr.txt,后期制作只要将它同msgid.po进行比对和翻译。