Pages

Saturday, 25 January 2020

修改linux系统的locale,解决中文乱码问题


在你的电脑和服务器的~/.bashrc(或者如果你用其他shell如zsh的话就是~/.zshrc)里都添加以下语句:
export LC_ALL=zh_CN.UTF-8
添加后退出当前窗口并重新登录(因为重新登录才会重新加载~/.bashrc或~/.zshrc),然后你可以用以下命令查看配置,都是zh_CN.UTF-8即可:
locale

细心的童鞋会发现我线上的LANG=en_US.UTF-8而不是LANG=zh_CN.UTF-8,这时只需要在~/.bashrc或~/.zshrc中再添加以下语句,然后重新登录即可:
export LANG=zh_CN.UTF-8
事实上locale命令输出的设置项我们都可以在~/.bashrc或~/.zshrc中用export的方式重新设置。

到底什么是locale?
locale这个单词中文翻译成地区或者地域,其实这个单词包含的意义要宽泛很多。Locale是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。

locale把按照所涉及到的文化传统的各个方面分成12个大类,这12个大类分别是:
1. 语言符号及其分类 (LC_CTYPE)
2. 数字(LC_NUMERIC)
3. 比较和排序习惯(LC_COLLATE)
4. 时间显示格式(LC_TIME)
5. 货币单位(LC_MONETARY)
6. 信息主要是提示信息,错误信息, 状态信息, 标题, 标签, 按钮和菜单等(LC_MESSAGES)
7. 姓名书写方式(LC_NAME)
8. 地址书写方式(LC_ADDRESS)
9. 电话号码书写方式(LC_TELEPHONE)
10. 度量衡表达方式 (LC_MEASUREMENT)
11. 默认纸张尺寸大小(LC_PAPER)
12. 对locale自身包含信息的概述 (LC_IDENTIFICATION)。

怎样设置locale?
1、以前的locale设置是在/etc/sysconfig/i18n文件中,i18n是internationalization的意思,这个单词是国际化的意思,因为单词太长,为了方便,只写第一个字母和最后一个字母,中间18个字母直接用数字18代替,表示这里有18个字母省略了。
2、CentOS7的locale设置是在/etc/locale.conf,至于从什么时候开始变成这个配置文件我就不太清楚,总之就是这两个位置中的其中一个。

所以如果CentOS7设置locale,应该要在/etc/locale.conf配置文件中设置,但由于该配置文件设置后需要重启服务器,所以一般会在.bashrc中用export的方式添加(或者你是其他shell,比如zsh的话,就是在.zshrc中添加),因为这可以覆盖/etc/locale.conf中的设置。

如果你需要一个纯中文的系统的话,如果是添加在/etc/locale.conf,可以这样写:
LC_ALL="zh_CN.UTF-8"
LANG="zh_CN.UTF-8"

如果是添加在~/.bashrc或~/.zshrc则要在它们的前面加一个export(其它设置同理):
export LC_ALL="zh_CN.UTF-8"
export LANG="zh_CN.UTF-8"

注意,LC_ALL会设置除LANG之外的11个分类,LANG需要单独设置,比如我只设置了LC_ALL,未设置LANG,则我的locale值是这样的:
除LANG之外的所有分类都被设置为zh_CN.UTF-8了,这样的结果是,所有习惯都用中国的习惯,但语言还是用英文,有些想学习英文的童鞋,就适合用这种。

由于LC_ALL会覆盖除LANG以外的所有值,所以,假如你设置了LC_ALL,那么就无需设置其他了LC_*了,因为没必要。

但必须注意,不能只设置LANG而不设置LC_*,比如我只在~/.bashrc中添加:
LANG="zh_CN.UTF-8"

那么使用的时候就会报错,比如我用man vim查看一下vim的手册,退出的时候就报这个错:
man: can't set the locale; make sure $LC_* and $LANG are correct
但奇怪的是,这个错误只会出现在往~/.bashrc或~/.zshrc中添加,如果是往配置文件/etc/locale.conf中只添加LANG="en_US.UTF-8"则没有任何问题。

此外,设置的时候,等号右边的值最好加上双引号,因为我看/etc/locale.conf文件中默认也是添加了的,当然我也试了如果不添加双引号,也一样生效,不会报错。

有意思的是,假设你这样设置:
export LANG="zh_CN.UTF-8"
export LC_CTYPE="zh_CN.UTF8"

那么几乎相当于设置LC_ALL(即把除LANG外的其他选项的值都设置了):
这样设置只是比用LC_ALL设置少一个LC_ALL的值,但由于LC_ALL本身是没什么作用的,它的作用就是设置除自己和LANG以外的那10个变量,既然这里那10个变量已经被LC_CTYPE设置,那么LC_ALL就无需设置了。

值得注意的是,上面的例子如果去掉LANG设置,只写成这样:
export LC_CTYPE="zh_CN.UTF8"
那么它只会设置它自己(即LC_CTYPE),而不会设置其他的.

以上例子测试环境为:CentOS Linux release 7.1