LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 5658|回复: 9

LANGUAGE, LC_ALL, LC_MESSAGES, LANG

[复制链接]
发表于 2005-12-31 21:03:00 | 显示全部楼层 |阅读模式
关于这几个环境变量
一般认为它们的作用是用来指定程序用户界面语言
而且这几个环境变量的优先级是从左到右依次降低的

大概的这么理解一下,也没什么太大问题
不过其实是不很准确的
它们是否起作用还和程序调用某些函数的方式有关
主要有这么一些函数:setlocale(), textdomain()/bindtextdomain(), gettext()/dgettext()/dcgettext()

详情如下:

Wait a sec, 如果对如何写国际化的程序尚不了解的话,还是先看看这个
http://xcin.linux.org.tw/i18n/pc2000/p5/index.html

首先,这几个环境变量并不能自动控制库函数(比如gettext)所使用的locale。也就是说设置了这些环境变量,程序的界面语言可能没有变化,虽然这样的软件应该很少。所有的c语言程序默认的locale都是"C"。 setlocale可以改变库函数所用的locale。如果希望利用这些环境变量来设定库函数所使用的locale或者某个locale的 category,一定要用""作为setlocale的第二个参数来调用setlocale()。绝大多数软件都会这样做:
    setlocale(LC_ALL, "");
[color="Red"]如果不调用setlocale(),或者使用其他自己指定的合法locale字符串(比如“zh_CN.utf8")作为第二个参数调用setlocale,那么这些环境变量就一点用都没有。所以如果你正确设定了环境变量,但还是不起作用的话,不排除软件本身有问题。

其次,程序界面语言的字符串存于mo文件中。gettext被用来从mo文件中得到这些字符串。mo文件的绝对路径是这样的         DIR_NAME/LOCALE/LC_CATEGORY/DOMAIN_NAME.mo
gettext 需要依次确定这个路径的各个部分,才能找到正确的mo文件。其中LOCALE部分正是和语言相关的。要确定它,gettext将按照LANGUAGE, LC_ALL, LC_MESSAGES, LANG的顺序挨个检查这些环境变量[color="Red"](注意,可以这样理解,实际不是这样,可以看这个连接
http://spaces.msn.com/members/zhllg/Blog/cns!1pZICR9vxlDKAQZ1A4wqfIbw!824.entry
而且这里有个前提,就是程序的locale一定不能为“C”,也就是说一定要事先调用setlocale()),直到找到一个已经被设置的为止,并用它的值代替上面路径中的LOCALE。其余几个部分,DIR_NAME一般是 “/usr/share/locale”,也可以由bindtextdomain()的第二个参数指定;LC_CATEGORY的值对于gettext ()来说默认是“LC_MESSAGES”,也可以由dcgettext()的第三个参数决定;DOMAIN_NAME初始值是”message“,可以通过textdomain()或者bindtextdomain()的第一个参数指定,一般是程序名。

再次,LANGUAGE是glibc的扩展,其他的libc貌似是没有的,它可以是几个值,彼此之间用冒号分开,比如:zh_CN:zh:en_US:en

举个例子,一个典型的mo文件的路径是
/usr/share/locale/zh_CN/LC_MESSAGES/coreutils.mo
顾名思议,ls,cp,mv等程序的中文错误提示信息就来自这个文件

以上过程是决定程序输出语言的来源(mo文件),如果找不到,自然就是英文

还有一个重要的相关环境变量/locale category 是LC_CTYPE
LC_CTYPE决定用什么字符集打印出mo里的字符。要注意的是,同一种语言,不管用什么字符集,一个程序都只需要一个mo。比如LC_CTYPE=zh_CN.gbk,程序按gbk字符集输出字符,如果LC_CTYPE=zh_CN.utf8,程序按utf8字符集输出字符

最后一点,其实这些信息`info libc`里都有
GNU的这些软件的info确实是好东西
不过说实话不是很user friendly
是reference,而不是tutorial
看起来会比较乏味
Anyway,既然搞这个,还是得会用它
发表于 2006-1-1 08:46:41 | 显示全部楼层
顶,这些东西还是要搞明白的
thx
回复 支持 反对

使用道具 举报

发表于 2006-1-1 22:44:00 | 显示全部楼层
不错不错!顶一下
回复 支持 反对

使用道具 举报

发表于 2006-1-3 11:30:06 | 显示全部楼层
顶一下!
在"wcout没法显示中文"回贴中引用了一下大哥论述.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-1-3 11:52:22 | 显示全部楼层
It's my honor
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-1-6 23:10:17 | 显示全部楼层
刚更新了一下
回复 支持 反对

使用道具 举报

发表于 2009-9-26 10:34:09 | 显示全部楼层
顺便说下,觉得 info libc 不爽的,可以到 gnu glibc 官方看不分页的 html 版本,方便搜索:
http://www.gnu.org/software/libc/manual/html_mono/libc.html
http://www.gnu.org/software/libc/manual/

PS: 早几年看过的帖子,到昨天才真正理解 LANGUAGE 变量作用,发现自己真有懒惰的潜质,感谢版主帮助清除先入之见。
回复 支持 反对

使用道具 举报

发表于 2010-4-28 21:56:34 | 显示全部楼层
info libc
8.2.1.6 User influence on `gettext'
...
The LOCALE component is computed based on the category used.  Just
like for the `setlocale' function here comes the user selection into
the play.  Some environment variables are examined in a fixed order and
the first environment variable set determines the return value of the
lookup process.  In detail, for the category `LC_xxx' the following
variables in this order are examined:

`LANGUAGE'

`LC_ALL'

`LC_xxx'

`LANG'
...


刚刚确认一个反例。
  1. $ unset LANGUAGE LANG LC_ALL
  2. $ set | grep -e LANG -e LC_ | grep -v _=
  3. $
  4. $ LANGUAGE=en:zh_CN LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 date; LANGUAGE=en:zh_CN LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 ls noexist
  5. 2010年 04月 28日 星期三 21:51:11 CST
  6. ls: 无法访问 noexist: 没有那个文件或目录
  7. $
  8. $ LANGUAGE=zh_CN:en LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 date; LANGUAGE=zh_CN:en LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 ls noexist
  9. Wed Apr 28 21:51:17 CST 2010
  10. ls: 无法访问 noexist: 没有那个文件或目录
  11. $  
  12. $ LANGUAGE=en LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 date; LANGUAGE=en LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 ls noexist
  13. 2010年 04月 28日 星期三 21:51:34 CST
  14. ls: cannot access noexist: No such file or directory
  15. $
  16. $ LANGUAGE=zh_CN LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 date; LANGUAGE=zh_CN LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 ls noexist
  17. Wed Apr 28 21:51:39 CST 2010
  18. ls: 无法访问 noexist: 没有那个文件或目录
  19. $
复制代码

date ls 均源自 coreutils 软件包,date.c ls.c 国际化部分处理看起来没问题,gettext glibc 中应该有一无关痛痒 bug。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-4-28 23:23:48 | 显示全部楼层
关于你说的反例,到底是不是“反例”,我觉得有两个问题要事先确认一下

1. date命令不能作为例子,因为LANGUAGE影响的是LC_MESSAGES,也就是程序中本来就有的字符串,用strings可以看到的字符串,以及它们的翻译。date的输出结果明显不在此列

2.请确认你是否有 /usr/share/locale/en/LC_MESSAGES/coreutils.mo
回复 支持 反对

使用道具 举报

发表于 2010-4-28 23:45:22 | 显示全部楼层
多谢指点。

1.
  1. $ LANGUAGE=en LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 date noexist
  2. date: invalid date `noexist'
  3. $ LANGUAGE=zh_CN LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 date noexist
  4. date: 无效的日期 “noexist”
  5. $
复制代码
stings date 确实看不到 Wed Apr 之类的字符串。

2.
  1. $ find /usr/share/locale/ -name '*coreutils*' | grep -e en
  2. $ find /usr/share/locale/ -name '*coreutils*' | grep -e zh
  3. /usr/share/locale/zh_CN/LC_TIME/coreutils.mo
  4. /usr/share/locale/zh_CN/LC_MESSAGES/coreutils.mo
  5. /usr/share/locale/zh_TW/LC_TIME/coreutils.mo
  6. /usr/share/locale/zh_TW/LC_MESSAGES/coreutils.mo
  7. $
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表