最精简有效的 glibc locales 设定


By EricHsu


- begin.200412211044


经过昨天一天实验, 把 glibc 重装了 4 次, 得出如下获得最精简 glibc locales 设置的方法 (下面是步骤, 没耐心了解其原因的朋友直接照做就可以, 有兴趣问个为什么的, 我会在步骤后面给出详细解释. 另, 条件所限, 仅针对简体中文用户):


一. 步骤



  1. 确保 emerge glibc 时, useflags 中有 userlocales

  2. 要让 glibc 在 emerge 时仅生成我们所需的 locales, 那么必须设置 userlocales useflag:

Code:


# echo "sys-libs/glibc userlocales" >> /etc/portage/package.use



emerge -pv glibc 时应看到:

Quote:


[ebuild R ] sys-libs/glibc-2.3.4.20041102 -build -debug -erandom-hardened -multilib +nls -nomalloccheck +nptl +nptlonly -pic +userlocales 0 kB



编辑 /etc/locales.build, 仅设置如下 5 行, 其余一律注释掉:

Code:


en_US/ISO-8859-1


en_US.UTF-8/UTF-8


zh_CN/GB18030


zh_CN.GB2312/GB2312


zh_CN.UTF-8/UTF-8



安装 glibc

Code:


# emerge --oneshot glibc



设置系统的 LC_ALL 为 zh_CN
编辑 /etc/env.d/99local, 如果没有这个文件就自己创建, 添加一行:

Code:


LC_ALL=zh_CN



然后运行:

Code:


# env-update



注销, 重新登录, GB18030 字符集里的中文字都应该能正常显示, 测试:

  • 创建一个文件名包含这两个字 (攞, 離) 的空文件, 应能正常显示:

Code:


$ touch 攞離.txt


$ ls -l


-rwxrwx---  1 root users       0 12月 21 11:04 攞離.txt



在网页中的 flash 里右键, flash 的菜单选项中的中文应正常显示


让仅支持 gb2312/utf8 的程序正常工作

  • 仅支持 gb2312 的 bittornado

Code:


$ echo $LC_ALL


zh_CN


$ btdownloadgui.py


段错误


$ LC_ALL=zh_CN.gb2312 btdownloadgui.py


(正常运作)



仅支持 utf8 的 gxmame

Code:


$ echo $LC_ALL


zh_CN


$ gxmame


(大量错误输出:


(gxmame.original:7583): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()


且界面所有中文变成空白)


$ LC_ALL=zh_CN.utf8 gxmame


(正常运作)








二. 解释


  1. 只有在 useflags 中设置了 userlocales 后, /etc/locales.build 这个文件才会起作用, 否则, emerge glibc 默认将生成所有 locales
  2. /etc/locales.build 的解释:

Quote:


# 必不可少的英文支持


en_US/ISO-8859-1


en_US.UTF-8/UTF-8


# LC_ALL=zh_CN, 则系统将使用 zh_CN 下的所有字符信息/内容, 因此我们使用 GB18030 码表 (charmap) 以最大限度覆盖所有中文字符


zh_CN/GB18030


# 为有些仅支持 gb2312 的程序提供选择


zh_CN.GB2312/GB2312


# 为有些仅支持 utf8 的程序提供选择


zh_CN.UTF-8/UTF-8



对于 /etc/locales.build 的格式 (每一行为 <locale>/<charmap>) 有时会让人迷惑, 比如会看到 de_DE@euro/ISO-8859-15 这样的, 又会看到 en_US.UTF-8/UTF-8... 我当时就一直不理解为什么会有个 "@" 符号? 什么时候该用 "."? 其实很简单,

  • 在 /usr/share/i18n/locale 目录中, 就有一个 de_DE@euro 的文件, 所以这个 locale 就等于 de_DE@euro, "@" 符号与格式无关!
  • 至于 ".", 这个不好解释, 可以理解为有生成 "子 locale" 的意思, 唯一要保证的是, "." 后的内容必须是 /usr/share/i18n/charmaps 中存在的 charmap. 例如 /usr/share/i18n/charmap 中有 GB18030.gz, GB2312.gz, GBK.gz, 那么我们就可以 zh_CN.GB18030/GB18030, zh_CN.GB2312/GB2312, zh_CN.GBK/GBK


经过实验发现, 每个 locale 项会在 /usr/lib/locale 下生成一个同名的目录, 例如, 如上配置, 我们将在 /usr/lib/locale 下得到如下目录:

Code:


eric@gentux ~ $  ls /usr/lib/locale/


en_US  en_US.utf8  ru_RU  zh_CN  zh_CN.gb2312  zh_CN.utf8



(注, ru_RU 里面的内容为空, 我删掉过, 但是 emerge glibc 时又会生成, 忽略之)
每个目录恰好与 /etc/locales.build 中的 locales 一一对应.
为何要设置 LC_ALL=zh_CN?
其实最新的一些程序大都支持 locales 如 zh_CN.GBK, zh_CN.GB18030, zh_CN.UTF-8, 但是, 有些程序还是仅支持到 GB2312, 它们在 GBK, GB18030, UTF-8 下会运作不正常. 例如, 浏览器的 flash 插件的仅在 LC_ALL=zh_CN 的情况下, 其右键菜单才能正常显示中文, 在 LC_ALL=zh_CN.GBK 下, 右键菜单空白. 总之, 通过 LC_ALL=zh_CN 设置系统的 locale 为 zh_CN 将最大限度让新老程序的中文都运作正常. 而又因为 /usr/lib/locale/zh_CN 下的 LC_* 文件的内容都是使用 /usr/share/i18n/charmaps 里的 GB18030.gz 这一目前最全 (?) 的中文码表来生成的, 因此, 这又让所有程序覆盖了最全 (?) 的中文字符, 系统将可以正常处理 GB18030 字符集范围以内的所有中文字符 (当然, 还是有限制, 有些生僻的中文字符还是显示成方块, 那是因为字体文件本身的限制造成的, 如果我没记错的话, simsun 仅支持到 GBK 字符集, 不过已经绝对够用了. 如果还非要显示所有字符, 那就设法找个支持 GB18030 字符集的字体吧, 好像有个 simsun-18030).



三. 实验记录


实验前, glibc 是安装系统是装的, 当时没有设置 userlocales 这一 useflags, 因此 glibc 安装过程中生成了所有的 locales.



  1. 第一次:


  • /etc/locales.build

Code:


en_US/ISO-8859-1


en_US.UTF-8/UTF-8


zh_CN/GB2312


zh_CN/GBK


zh_CN/GB18030


zh_CN.UTF8/UTF-8



注意, 上面有两个错误:

  • 不能同时写 zh_CN/GB2312, zh_CN/GBK, zh_CN/GB18030, 这会让 glibc 往 /usr/lib/locale/zh_CN 目录里逐个生成 GB2312, GBK, GB18030 的 LC_* 文件, 结果是: 最终只剩 GB18030 - GBK 覆盖了 GB2312, 接着 GB18030 覆盖了 GBK.
  • 应该是 zh_CN.UTF-8 而非 zh_CN.UTF8, emerge 完才发现-_-#


echo $LC_ALL

Code:


zh_CN



locale -a

Code:


C


en_US


en_US.utf8


POSIX


zh_CN


zh_CN.utf8



ls /usr/lib/locale

Code:


en_US  en_US.utf8  ru_RU  zh_CN  zh_CN.utf8



问题:

  • bittornado 默认 LC_ALL 下段错误, export LC_ALL=zh_CN.GB2312 后再运行, 则提示 GB2312 不是系统支持的 locale (因为之前的那个互相覆盖... locale -a 中可以看出系统中只有 GB18030 和 UTF-8 ), 自动 fallback 回 C locale, 含中文信息的 torrent 显示乱码.




第二次:

  • /etc/locales.build

Code:


en_US/ISO-8859-1


en_US.UTF-8/UTF-8


zh_CN/GB2312


zh_CN.GBK/GBK


zh_CN.GB18030/GB18030


zh_CN.UTF-8/UTF-8



echo $LC_ALL

Code:


zh_CN



locale -a

Code:


C


en_US


en_US.utf8


POSIX


zh_CN


zh_CN.gb18030


zh_CN.gbk


zh_CN.utf8



ls /usr/lib/locale

Code:


en_US  en_US.utf8  ru_RU  zh_CN  zh_CN.gb18030  zh_CN.gbk  zh_CN.utf8



问题:

  • 在 LC_ALL=zh_CN 的情况下, 含这两个字 (攞, 離) 的文件名显示为 \224{... 这样的乱码. 这是因为 /usr/lib/locale/zh_CN 下的 LC_* 文件内容仅以 GB2312 码表生成, 因此无法覆盖超过 GB2312 字符集的字符.
  • 在设置 LC_ALL=zh_CN.GBK 之后, 上述二字显示正常, 说明 GBK 字符集覆盖了这些字. 但是这时在浏览器中, flash 右键, 菜单为空白, 所有中文在 GBK 下都无法正常显示.
  • 在设置 LC_ALL=zh_CN.UTF8 之后, 上述二字显示正常, 说明 GB18030 字符集覆盖了这些字. 但是这时在浏览器中, flash 右键, 菜单成为英文.




第三次:

  • /etc/locales.build

Code:


en_US/ISO-8859-1


en_US.UTF-8/UTF-8


zh_CN/GB18030


zh_CN.UTF-8/UTF-8



echo $LC_ALL

Code:


zh_CN



locale -a

Code:


C


en_US


en_US.utf8


POSIX


zh_CN


zh_CN.utf8



ls /usr/lib/locale

Code:


en_US  en_US.utf8  ru_RU  zh_CN  zh_CN.utf8



问题:

  • 由于 zh_CN 下的 LC_* 是用 GB18030 生成的, 在把系统 LC_ALL 设置为 zh_CN 之后, 同时获得了最大限度覆盖所有中文字符以及让新老程序尽可能支持中文的好处 (如 flash 右键菜单显示正常). 可是这时 bittornado 会出现如第一次时的情况, 段错误, 以及自动 fallback 回 C locale 以致中文乱码的问题. 主要因为系统中没有 zh_CN.GB2312 的 locale 可以给它使用.




第四次:

  • /etc/locales.build

Code:


en_US/ISO-8859-1


en_US.UTF-8/UTF-8


zh_CN/GB18030


zh_CN.GB2312/GB2312


zh_CN.UTF-8/UTF-8



echo $LC_ALL

Code:


zh_CN



locale -a

Code:


C


en_US


en_US.utf8


POSIX


zh_CN


zh_CN.gb2312


zh_CN.utf8



ls /usr/lib/locale

Code:


en_US  en_US.utf8  ru_RU  zh_CN  zh_CN.gb2312  zh_CN.utf8



问题: 迄今暂无! 小结: 在第三次实验的基础上, 为 /etc/locales.build 中添加了一行 zh_CN.GB2312/GB2312 之后, 系统的 locale 获得迄今最精简最完美的结果:

  • 系统支持目前最全的中文字符集 GB18030
  • 由于 LC_ALL=zh_CN, 因此新老程序对中文的支持同样完美
  • 仅支持 gb2312 (bittornado) 或 utf8 (gxmame) 的程序都有符合它们需要的 locale 以供选择