您的位置:首页 > 运维架构 > Linux

linux 乱码 及解决方法 locale 可以利用iconv -l 来查看linux系统都支持哪种编码格式

2006-05-25 15:14 1046 查看

引用的网址:

http://www.syxin.com/2006/03/localelocale.html

http://www.linuxfans.org/nuke/modules.php?name=Forums&file=viewtopic&p=4647771

对于计算机来说就是你要是用哪一种字符集,你就必须告诉你的linux系统,locale就是某一个地域内的人们的语言习惯和文化传统和生活习惯。一个地区的locale就是根据这几大类的习惯定义的,这些locale定义文件放在/usr/share/i18n/locales目录下面,所有的字符集都放在/usr/share/i18n/charmaps,所有的字符集也都是用Unicode编号索引的。

怎样去自定义locale
在gentoo生成locale还是很容易的,首先要在USE里面加入userlocales支持,然后编辑locales.build文件,这个文件用来指示glibc生成locale文件。
很多人不明白每一个条目是什么意思。 其实根据上面的说明现在应该很明确了。

File: /etc/locales.build
en_US/ISO-8859-1
en_US.UTF-8/UTF-8

zh_CN/GB18030
zh_CN.GBK/GBK
zh_CN.GB2312/GB2312
zh_CN.UTF-8/UTF-8

上面是我的locales.build文件,依次的说明是这样的:

en_US/ISO-8859-1:生成名为en_US的locale,采用ISO-8859-1字符集,并且把这个locale作为英文_美国locale类的默认值,其实它和en_US.ISO-8859-1/ISO-8859-1没有任何区别。

en_US.UTF-8/UTF-8:生成名为en_US.UTF-8的locale,采用UTF-8字符集。

zh_CN/GB18030:生成名为zh_CN的locale,采用GB18030字符集,并且把这个locale作为中文_中国locale类的默认值,其实它和zh_CN.GB18030/GB18030没有任何区别。

zh_CN.GBK/GBK:生成名为zh_CN.GBK的locale,采用GBK字符集。
zh_CN.GB2312/GB2312:生成名为zh_CN.GB2312的locale,采用GB2312字符集。
zh_CN.UTF-8/UTF-8:生成名为zh_CN.UTF-8的locale,采用UTF-8字符集。

关于默认locale,默认locale可以简写成en_US或者zh_CN的形式,只是为了表达简单而已没有特别的意义。

Gentoo在locale定义的时候掩盖了一些东西,也就是locale的生成工具:localedef。
在编译完glibc之后你可以用这个localedef 再补充一些locale,就会更加理解locale了。具体的可以看 localedef 的manpage。

$localedef -f 字符集 -i locale定义文件 生成的locale的名称
例如
$localedef -f UTF-8 -i zh_CN zh_CN.UTF-8

上面的定义方法和在locales.build中设定zh_CN.UTF-8/UTF-8的结果是一样一样的。

一. 步骤

确保 emerge glibc 时, useflags 中有 userlocales
要让 glibc 在 emerge 时仅生成我们所需的 locales, 那么必须设置 userlocales useflag:

代码:
# echo "sys-libs/glibc userlocales" >> /etc/portage/package.use
emerge -pv glibc 时应看到:

引用:
[ebuild R ] sys-libs/glibc-2.3.4.20041102 -build -debug -erandom -hardened -multilib +nls -nomalloccheck +nptl +nptlonly -pic +userlocales 0 kB
代码:
en_US/ISO-8859-1
en_US.UTF-8/UTF-8
zh_CN/GB18030
zh_CN.GB2312/GB2312
zh_CN.UTF-8/UTF-8
代码:
# emerge --oneshot glibc
代码:
LC_ALL=zh_CN
然后运行:

代码:
# env-update
代码:
$ touch ??.txt
$ ls -l
-rwxrwx--- 1 root users 0 12月 21 11:04 ??.txt
代码:
$ echo $LC_ALL
zh_CN
$ btdownloadgui.py
段错误
$ LC_ALL=zh_CN.gb2312 btdownloadgui.py
(正常运作)
代码:
$ 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
(正常运作)
代码:
# 必不可少的英文支持
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 下得到如下目录:

代码:
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 时又会生成, 忽略之)
[/blue]
每个目录恰好与 /etc/locales.build 中的 locales 一一对应.

而又为 /usr/lib/locale/zh_CN 下的 LC_* 文件的内容都是使用 /usr/share/i18n/charmaps 里的 GB18030.gz 这一目前最全 (?) 的中文码表来生成的, 因此, 这又让所有程序覆盖了最全 (?) 的中文字符, 系统将可以正常处理 GB18030 字符集范围以内的所有中文字符 (当然, 还是有限制, 有些生僻的中文字符还是显示成方块, 那是因为字体文件本身的限制造成的, 如果我没记错的话, simsun 仅支持到 GBK 字符集, 不过已经绝对够用了. 如果还非要显示所有字符, 那就设法找个支持 GB18030 字符集的字体吧, 好像有个 simsun-18030).

代码:
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 完才发现-_-#

代码:
zh_CN
代码:
C
en_US
en_US.utf8
POSIX
zh_CN
zh_CN.utf8
代码:
en_US en_US.utf8 ru_RU zh_CN zh_CN.utf8
代码:
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
代码:
zh_CN
代码:
C
en_US
en_US.utf8
POSIX
zh_CN
zh_CN.gb18030
zh_CN.gbk
zh_CN.utf8
代码:
en_US en_US.utf8 ru_RU zh_CN zh_CN.gb18030 zh_CN.gbk zh_CN.utf8
代码:
en_US/ISO-8859-1
en_US.UTF-8/UTF-8
zh_CN/GB18030
zh_CN.UTF-8/UTF-8
代码:
zh_CN
代码:
C
en_US
en_US.utf8
POSIX
zh_CN
zh_CN.utf8
代码:
en_US en_US.utf8 ru_RU zh_CN zh_CN.utf8
代码:
en_US/ISO-8859-1
en_US.UTF-8/UTF-8
zh_CN/GB18030
zh_CN.GB2312/GB2312
zh_CN.UTF-8/UTF-8
代码:
zh_CN
代码:
C
en_US
en_US.utf8
POSIX
zh_CN
zh_CN.gb2312
zh_CN.utf8
代码:
en_US en_US.utf8 ru_RU zh_CN zh_CN.gb2312 zh_CN.utf8
编辑 /etc/locales.build, 仅设置如下 5 行, 其余一律注释掉:

安装 glibc

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

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

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

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

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

仅支持 gb2312 的 bittornado

仅支持 utf8 的 gxmame

二. 解释

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

/etc/locales.build 的解释:

为何要设置 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 下, 右键菜单空白. [color=blue]总之, 通过 LC_ALL=zh_CN 设置系统的 locale 为 zh_CN 将最大限度让新老程序的中文都运作正常.

三. 实验记录

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

第一次:

/etc/locales.build

echo $LC_ALL

locale -a

ls /usr/lib/locale

问题:

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

第二次:

/etc/locales.build

echo $LC_ALL

locale -a

ls /usr/lib/locale

问题:

在 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

echo $LC_ALL

locale -a

ls /usr/lib/locale

问题:

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

第四次:

/etc/locales.build

echo $LC_ALL

locale -a

ls /usr/lib/locale

问题: 迄今暂无![/code]

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

[color=blue]系统支持目前最全的中文字符集 GB18030

由于 LC_ALL=zh_CN, 因此新老程序对中文的支持同样完美

仅支持 gb2312 (bittornado) 或 utf8 (gxmame) 的程序都有符合它们需要的 locale 以供选择
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐