首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

浅析 Linux 的国际化与本地化机制(1)

浅析 Linux 的国际化与本地化机制(1)

什么是国际化和本地化不同的国家和地区因文化的差异,在日期、时间以及货币符号等表示方式上都不完全相同,最为明显的就是语言。有时在编写软件给用户使用时,开发者、维护者以及最终用户可能分别来自不同的区域,而要求他们均使用同一种语言显然是不明知的,因此当一个程序或者软件编写给全世界人使用时,通常分为两个部分:国际化 (internationalization,即缩写为 i18n,这是由于在这个单词的头尾之间包含了 18 个字母 ) 和本地化 (localization,缩写为 l10n)。
NLSNLS 即是 Native Language Support。Linux 为解决各文件系统文件名多语言的问题而引入了对 NLS 的支持,我们可在内核编译配置中找到相关选项。

国际化,指的是一个程序或软件可给特定的人群使用而无须修改或重新编译源代码。在 ISO C 中,国际化的工作依赖于 locales。程序开发者可使用多样的方式来国际化他们的程序,但是 GNU gettext 已成为了其中的一种标准。
本地化,指的是一个程序或软件在支持国际化的基础上,给定程序特定区域的语言信息使其在信息的输入输出等处理上适应特定区域人群的使用。这里允许程序所使用的一些语言环境变量在程序执行时动态配置。
简单的说,国际化是开发者的任务,是一个一般化的过程;而本地化则是翻译者所做的事情,是一个具体的过程。国际化的运作为本地化工作提供了可能。对于国际化与本地化,有时我们也称为 NLS。Glibc (GNU C library) 作为 Linux 的 C 标准库为 Linux 处理国际化与本地化提供了基础,如图 1 所示,Linux 上的程序处理依赖于 glibc。
图 1. glibc 在 Linux 上的基础作用使用和设定系统 locale对用户而言,用来控制语言或区域环境生效的功能就叫做 locale。locale 是 glibc 的一个重要组成部分,也是 Linux 国际化和本地化工作的一个重要基础。locale 通过设置一系列的环境变量来满足用户对国际化和本地化的需求。通过 locale 命令,我们不仅可查看到语言环境的当前设置,还可查看当前 locale 可用的名称和字符集。
清单 1. 系统当前 locale 环境变量值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ locale
LANG=en_US.UTF-8                    # 未设置任何 LC_xxx 变量时所使用的默认值
LC_CTYPE=zh_CN.UTF-8                # 指定使用某区域的字符分类及处理方式
LC_NUMERIC="en_US.UTF-8"            # 指定使用某区域的非货币的数字格式
LC_TIME="en_US.UTF-8"               # 指定使用某区域的日期和时间格式
LC_COLLATE="en_US.UTF-8"            # 指定使用某区域的排序规则
LC_MONETARY="en_US.UTF-8"           # 指定使用某区域的货币格式
LC_MESSAGES="en_US.UTF-8"           # 指定使用某区域的响应与信息的格式
LC_PAPER="en_US.UTF-8"              # 指定使用某区域的纸张大小
LC_NAME="en_US.UTF-8"               # 指定使用某区域的姓名书写方式
LC_ADDRESS="en_US.UTF-8"            # 指定使用某区域的地址格式和位置信息
LC_TELEPHONE="en_US.UTF-8"          # 指定使用某区域的电话号码格式
LC_MEASUREMENT="en_US.UTF-8"        # 指定使用某区域的度量衡规则
LC_IDENTIFICATION="en_US.UTF-8"     # 对 locale 自身信息的概述
LC_ALL=                             # 用来覆盖掉所有其他 LC_xxx 变量的值




除 中所示的,另有用于指定 locale 可用名称目录的变量 LOCPATH,默认使用的路径是 /usr/lib/locale/。另外,当一个程序找寻 locale 环境变量值时,它会依以下优先顺序使用变量。
清单 2. locale 相关变量使用时的优先顺序
1
2
3
4
[1] LANGUAGE
[2] LC_ALL
[3] LC_xxx
[4] LANG




其中 LC_ALL 并不是一个环境变量,它仅是一个可被函数 setlocale (setlocale 的函数原型及其参数 category 的可用值均被定义在头文件 locale.h 中 ) 调用的宏,它的值可覆盖所有其他的 locale 设定 ( 如果 LC_ALL 的值存在的话,即非空 ) 。LANG 用于正常指定使用某区域环境值,而 LANGUAGE 则用于指定个人对语言环境值的主次偏好。通常我们会在设定 LANG 后,并通过 LC_xxx 加以修正。
LANGUAGE="en_US:en"
LANG="en_US.UTF-8"
LC_CTYPE="zh_CN.UTF-8"
您可将以上内容添加至 /etc/profile 或 /etc/environment 等系统初始文件中,以保证系统在启动后立即使用您所期望的语言环境。值得注意的是,若 locale 被设定为 "C",那么 LANGUAGE 的值将被忽视。因此我们必须为 LANG ( 或 LC_ALL) 设置有效的 locale 名称,而非 "C"。
清单 3. 当前系统可用的 locale 名称
1
2
3
4
5
6
7
$ locale – a
C
en_AU.utf8
...
POSIX
zh_CN.utf8
...




在 中我们看到了两个特别的 locale 名称,C 和 POSIX。当前,POSIX 仅是 C 的一个别名。除 C 和 POSIX 之外,locale 的名称并未标准化。同时,中可用名称的输出已依 LC_COLLATE 所指定的排序规则进行了排序。另外,我们看到 locale 的名称存在一个命名的格式。
language[_territory[.codeset]][@modifier]
其中 language 是 ISO 639-1 标准中定义的语言代码,territory 是 ISO 3166-1 标准中定义的国家和地区代码,codeset 是字符集的名称 ( 如 UTF-8 等 ),而 modifier 则是某些 locale 变体的修正符。若期望使用的 locale 名称未在以上的列表中,那么我们可使用 glibc 提供的命令 localedef 进行添加 ( 见 ,命令 localedef 会在相关路径生成必要的数据文件 )。
清单 4. 通过命令 localedef 添加 fi_FI.UTF-8
1
2
[1] localedef -f UTF-8 -i fi_FI fi_FI.UTF-8
[2] localedef -f UTF-8 -i fi_FI ./fi_FI




方式 1 将在默认路径上生成一个 locale-archive 文件,而方式 2 则在指定路径产生一个目录,该目录中将包含 locale 相关的数据。另外,命令 localedef 还提供了 --no-archive 选项,该选项可使方式 1 生成的也是一个目录,而非 locale-archive 文件。下面我们通过设置 LC_ALL 和 LC_TIME 的值来了解该 locale 环境变量对时间和日期格式的影响,从而更好的理解 locale 环境变量在系统上的基础作用 ( 见 ,另外我们需在运行前确定该 locale 名称是有效的 )。
清单 5. locale 环境变量对系统命令的影响
1
2
3
4
5
6
7
8
9
10
11
12
13
$ LC_ALL=en_US.UTF-8 date
Thu Nov  5 14:13:36 CST 2009

$ LC_TIME=fi_FI.UTF-8 date
to 5.11.2009 14.13.44 +0800

$ LC_ALL=zh_CN.UTF-8  locale  -ck  LC_TIME
LC_TIME
abday="日 ; 一 ; 二 ; 三 ; 四 ; 五 ; 六"
...
...
date_fmt="%Y 年 %m 月 %d 日 %A %H:%M:%S %Z"
time-codeset="UTF-8"




在这里另要指出的是,由 GNU coreutils 提供的 date 命令在实现时加入了以下内容,而这正是 date 命令实现国际化与本地化的关键 ( 见清单 6)。
清单 6. date 命令的源码片断
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
返回列表