Monday, August 18, 2008

关于i18n与l10n,gettext,locale

今天稍微研究了一下gettext,发觉涉及到的东西很多,有点乱,稍微总结一下。

1.概念与介绍
i18n=internationlization的缩写,代表国际化
i10n=localization的缩写,代表本地化
gettext是用于实现i18n和i10n的一个工具
locale翻译成区域或区域设置,是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。 [2]
这个用户环境可以按照所涉及到的文化传统的各个方面分成几个大类,通常包括用户所使用的语言符号及其分类(LC_CTYPE),数字 (LC_NUMERIC),比较和排序习惯(LC_COLLATE),时间显示格式(LC_TIME),货币单位(LC_MONETARY),信息主要是 提示信息,错误信息, 状态信息, 标题, 标签, 按钮和菜单等(LC_MESSAGES),姓名书写方式(LC_NAME),地址书写方式(LC_ADDRESS),电话号码书写方式 (LC_TELEPHONE),度量衡表达方式(LC_MEASUREMENT),默认纸张尺寸大小(LC_PAPER)和locale对自身包含信息的 概述(LC_IDENTIFICATION)。 [2]

编写软件时,要使软件能国际化,则必须考虑到其在不同区域,能符合当地的习惯显示正确的字符串,数字格式等。
但是如何解决这个翻译的问题?最笨的方法显然是hardcode,以C程序为例,
printf("hello world")
每次要翻译成不同语言都把字符串"hello world"改变,再重新编译一次,这显然非常不方便。

聪明一点,可以使用一个宏代替字符串,每次更改一系列的宏。

而现在普遍使用的方法基于一个"映射表"式的方法。程序的字符串能根据运行时,动态地从对应的翻译文件中取得正确的字符串进行显示。
比如gettext,又比如windows下win32程序的字符串映射表。

下面着重介绍gettext。

2.gettext实现i18n与l10n
以下总结自参考资料[1].
主要的流程为:
  1. 编写应用程序,包含以下头文件:libintl.h,locale.h
  2. 使用setlocale设置程序的locale为当前用户的locale
  3. 使用bindtextdomain指定一个域名(domain)的对应文件所在的基目录(一般为/usr/share/local/<xxx>,<xxx>为zh_CN等)
  4. 使用textdomain设置当前应用程序的域名(一般与3中的域名对应)
  5. 使用gettext("...")包含printf("...")中的字符串,即printf(gettext("..."));
  6. 使用xgettext从源文件中抽取字符串,生成pot文件(portable object template)
  7. 使用msginit从pot文件生成指定语言的po文件(portable object)
  8. 使用msgfmt从po文件生成mo文件(machine object)
  9. 复制生成的po文件到3中指定基目录中与po的区域对应的目录
  10. 程序运行时,能根据区域设置(LC_ALL,LANG等)来输出字符串。
3.locale
说道locale,我虽然看了不少文章,还是模模糊糊的,还是要靠以后积累了。
参考资料[2]是一篇非常好的文章。

参考资料:
[1] A tutorial on Native Language Support using GNU gettext, http://oriya.sarovar.org/docs/gettext/memo.html
[2] 关于locale的设定,为什么要设定locale, http://forum.ubuntu.org.cn/viewtopic.php?t=18273

No comments: