修改 /var/lib/locales/supported.d/local 文件(使用 locale -a 命令查看系统中所有已配置的 locale)
转自:http://zyxhome.org/wp/cc-prog-lang/c-stdlib-setlocale-usage-note/
http://www.west263.com/info/html/caozuoxitong/FreeBSD/20090513/126191.html
C 和 C++ 的标准库分别有自己的 locale 操作方法,C 标准库的 locale 设定函数是 setlocale(),而 C++ 标准库有 locale 类和流对象的 imbue() 方法。这篇是我自己的 setlocale() 使用总结。
Linux的glibc中的setlocale()
具体参考:man 3 setlocale
头文件与声明如下:
1 |
#include <locale.h> |
2 |
char * setlocale ( int category, const char * locale); |
说明:
category:为locale分类,表达一种locale的领域方面,通常有下面这些预定义常量:LC_ALL、LC_COLLATE、LC_CTYPE、LC_MESSAGES、LC_MONETARY、LC_NUMERIC、LC_TIME,其中 LC_ALL 表示所有其它locale分类的并集。
locale:为期望设定的locale名称字符串,在Linux/Unix环境下,通常以下面格式表示locale名称:language[_territory][.codeset][@modifier],language 为 ISO 639 中规定的语言代码,territory 为 ISO 3166 中规定的国家/地区代码,codeset 为字符集名称。
在Linux下,可以使用 locale -a 命令查看系统中所有已配置的 locale。用不带选项的 locale 命令查看当前 Shell 中活动的 locale。用 locale -m 命令查看locale系统支持的所有可用的字符集编码。
和locale相关的包叫做:locales,locale系统支持的所有可用locale在文件:/usr/share/i18n/SUPPORTED 中列出。
在Debian下,可用 dpkg-reconfigure locales 命令重新配置 locale,也可以手工修改 /etc/locale.gen 文件,然后运行 locale-gen 命令。
在Ubuntu下,修改 /var/lib/locales/supported.d/local 文件,配置新的 locale,然后运行 locale-gen 命令。
我在我用的fedora14的linux虚拟机中执行locale 返回如下:
[hehongji@localhost ~]$ locale
LANG=zh_CN.utf8
LC_CTYPE="zh_CN.utf8"
LC_NUMERIC="zh_CN.utf8"
LC_TIME="zh_CN.utf8"
LC_COLLATE="zh_CN.utf8"
LC_MONETARY="zh_CN.utf8"
LC_MESSAGES="zh_CN.utf8"
LC_PAPER="zh_CN.utf8"
LC_NAME="zh_CN.utf8"
LC_ADDRESS="zh_CN.utf8"
LC_TELEPHONE="zh_CN.utf8"
LC_MEASUREMENT="zh_CN.utf8"
LC_IDENTIFICATION="zh_CN.utf8"
LC_ALL=
当 locale 为 NULL 时,函数只做取回当前 locale 操作,通过返回值传出,并不改变当前 locale。
当 locale 为 "" 时,根据环境的设置来设定 locale,检测顺序是:环境变量 LC_ALL,每个单独的locale分类LC_*,最后是 LANG 变量。为了使程序可以根据环境来改变活动 locale,一般都在程序的初始化阶段加入下面代码:setlocale(LC_ALL, "")。
当C语言程序初始化时(刚进入到 main() 时),locale 被初始化为默认的 C locale,其采用的字符编码是所有本地 ANSI 字符集编码的公共部分,是用来书写C语言源程序的最小字符集(所以才起locale名叫:C)。
当用 setlocale() 设置活动 locale 时,如果成功,会返回当前活动 locale 的全名称;如果失败,会返回 NULL。
locale 是一组 C 程式语言处理自然语言(文字)的程式介面, 也可以简单的说,locale 就是一组地区性语言的资讯。由国家语言和各地习俗影响所决定的惯例,或代表一个地理区域的定义所组成,这些惯例包含文字、日期、数字、货币格式和排序等等。这代表着 locale 可让程式的输出可以直接反应地方区域性的文化。
C 语言的 locale 定义,分为下列各大类:
LC_ALL 指定所有的 Locale
LC_CTYPE 字元定义 (包含字元分类与转换规则)
LANG 语言显示
LC_MESSAGES 讯息显示
LC_TIME 时间格式
LC_NUMERIC 数字格式
LC_MONETARY 货币格式
LC_COLLATE 字母顺序与特殊字元比较
其中与一般使用者息息相关的,是字元定义 (LC_CTYPE) 与语言显示 (LANG)。LC_CTYPE 直接关系到某些字元或内码在目前的 locale 下是否可列印?要如何转换字码?对应到哪一个字?.... 等等。LANG 则关系到软体的讯息输出是不是符合地域性,例如 :我们需要的是中文。而一个真正完整支援 locale 系统, 是当使用者在 shell prompt 下,直接设好环境变数後,则马上就能切换到那个语言了。当 LC_MESSAGES、LC_TIME、LC_NUMERIC、 LC_MONETARY 等没有设定的时候,会直接取用 LANG 的环境设定值。
设定 Locale 的字元定义为台湾地区的 utf-8 繁体中文码定义, 有了正确的 locale 的定义後,使得任何地区的语文,只要在加入适当的 locale data 之後,C Library 就能正确地处理软体显示讯息, 而我们使用的中文当然也不例外,而目前常用的中文 locale data 就是 zh_TW.utf-8,代表的就是中文语系(zh)台湾地区(TW) 使用utf-8编码系统(utf-8)。
其中与一般使用者息息相关的,是字元定义 (LC_CTYPE) 与语言显示 (LANG)。LC_CTYPE 直接关系到某些字元或内码在目前的 locale 下是否可列印?要如何转换字码?对应到哪一个字?.... 等等。LANG 则关系到软体的讯息输出是不是符合地域性,例如 :我们需要的是中文。而一个真正完整支援 locale 系统, 是当使用者在 shell prompt 下,直接设好环境变数後,则马上就能切换到那个语言了。当 LC_MESSAGES、LC_TIME、LC_NUMERIC、 LC_MONETARY 等没有设定的时候,会直接取用 LANG 的环境设定值。
设定 Locale 的字元定义为台湾地区的 utf-8 繁体中文码定义, 有了正确的 locale 的定义後,使得任何地区的语文,只要在加入适当的 locale data 之後,C Library 就能正确地处理软体显示讯息, 而我们使用的中文当然也不例外,而目前常用的中文 locale data 就是 zh_TW.utf-8,代表的就是中文语系(zh)台湾地区(TW) 使用utf-8编码系统(utf-8)。
locale 命名规则:语言_地区名.字元编码名称
当一个程式启动时,系统会预设给它一个初始 locale,称为 POSIX 或 C locale。在此 locale 下,程式的表现会与传统的 C 语言中一样, 使用英文做讯息输出,只能处理英文等 ASCII 码等等。如果该程式有支援 I18N,也就是说它有按照 I18N 的标准来写,则它在启动後就会马上呼叫系统函式来改变它的 locale, 如此它就摇身一变,变成可以处理该 locale 所代表的地区语文了。
zh_TW.utf-8 是目前台湾内广泛使用的 locale, zh 是华语(Chinese),1998 年 ISO639 里面以两个英文字母来代表语言编码, 这个缩写据笔者所知没有任何含义,而 TW 代表的就是台湾(Taiwan) 地区的缩写,最後的 utf-8 则是编码方式。
locale 设定档在编译後, 则是储存在 /usr/share/locale/ 目录下, 以 zh_TW.utf-8 locale 为例,该目录中就包含了 LC_COLLATE、LC_CTYPE、 LC_TIME。
而 LC_MESSAGES 则是储存在 /usr/local/share/locale/zh_TW/LC_MESSAGES/ 或是/usr/X11R6/share/locale/zh_TW.utf-8/ 底下。由於 LC_MESSAGES 类别掌管的是程式讯息输出所用的语言,而且不同程式间的讯息都不会一样,因此它不能像其他类别一样,只提供单一一个资料档即可。相反的,在这里所采取的方式是由各应用程式自行提供它们的讯息资料档, 并统一放在各 locale 的 LC_MESSAGES 的目录下。例如 mutt 程式,其讯息的部分除了英文以外,可能还同时提供了繁体中文、简体中文、 日文、法文等翻译,因此,在以上这些语文所代表的 locale 中, 其底下的 LC_MESSAGES 目录中都会有一份属於 mutt 程式的讯息资料档。 换句话说,在 I18N 架构下,程式讯息部分是与程式分离的, 如此才能分别对各 locale 做 ``区域化'' (即翻译成各地区的语言)。 如此,当 mutt 在执行时,系统会根据目前它的 LC_MESSAGES locale 设定去找找看有没有它的讯息资料档存在,有的话就以该语言做讯息输出, 否则的话则以 C locale 的方式 (即英文) 来输出讯息。
zh_CN.GB2312到底是在说什么?
Locale 是软件在运行时的语言环境, 它包括语言(Language), 地域 (Territory) 和字符集(Codeset)。一个locale的书写格式为: 语言[_地域[.字符集]]. 所以说呢,locale总是和一定的字符集相联系的。下面举几个例子:
1、我说中文,身处中华人民共和国,使用国标2312字符集来表达字符。
zh_CN.GB2312=中文_中华人民共和国+国标2312字符集。
2、我说中文,身处中华人民共和国,使用国标18030字符集来表达字符。
zh_CN.GB18030=中文_中华人民共和国+国标18030字符集。
3、我说中文,身处中华人民共和国台湾省,使用国标Big5字符集来表达字符。
zh_TW.BIG5=中文_台湾.大五码字符集
4、我说英文,身处大不列颠,使用ISO-8859-1字符集来表达字符。
en_GB.ISO-8859-1=英文_大不列颠.ISO-8859-1字符集
5、我说德语,身处德国,使用UTF-8字符集,习惯了欧洲风格。
de_DE.UTF-8@euro=德语_德国.UTF-8字符集@按照欧洲习惯加以修正
注意不是de_DE@euro.UTF-8,所以完全的locale表达方式是
[语言[_地域][.字符集] [@修正值]
生成的locale放在/usr/lib/locale/目录中,并且每个locale都对应一个文件夹,也就是说创建了de_DE@euro.UTF-8 locale之后,就生成/usr/lib/locale/de_DE@euro.UTF-8/目录,里面是具体的每个locale的内容。
什么是字符集?
字符集就是字符,尤其是非英语字符在系统内的编码方式,也就是通常所说的内码,所有的字符集都放在 /usr/share/i18n/charmaps,所有的字符集也都是用Unicode编号索引的。Unicode用统一的编号来索引目前已知的全部的符号。而字符集则是这些符号的编码方式,或者说是在网络传输,计算机内部通信的时候,对于不同字符的表达方式,Unicode是一个静态的概念,字符集是一个动态的概念,是每一个字符传递或传输的具体形式。就像Unicode编号U59D0是代表姐姐的“姐”字,但是具体的这个字是用两个字节表示,三个字节,还是四个字节表示,是字符集的问题。例如:UTF-8字符集就是目前流行的对字符的编码方式,UTF-8用一个字节表示常用的拉丁字母,用两个字节表示常用的符号,包括常用的中文字符,用三个表示不常用的字符,用四个字节表示其他的古灵精怪的字符。而GB2312字符集就是用两个字节表示所有的字符。需要提到一点的是Unicode除了用编号索引全部字符以外,本身是用四个字节存储全部字符,这一点在谈到挂载windows分区的时候是非常重要的一个概念。所以说你也可以把Unicode看作是一种字符集(我不知道它和UTF-32的关系,反正UTF-32就是用四个字节表示所有的字符的),但是这样表述符号是非常浪费资源的,因为在计算机世界绝大部分时候用到的是一个字节就可以搞定的26个字母而已。所以才会有UTF-8,UTF-16等等,要不然大同世界多好,省了这许多麻烦.
通常这几个函数一起用,用于编写本地化程序。
setlocale
bindtextdomain
textdomain
gettext
http://blog.sina.com.cn/s/blog_70f157930101jlz2.html