解决LC_CTYPE: cannot change locale (UTF-8)及vim中文乱码问题
Table of Contents
vim中文编码问题
方式一:添加vim配置
在~/.vimrc
里添加以下设置即可:
"解决vim中文乱码问题
set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936
set termencoding=utf-8
set encoding=utf-8
方式二:修改系统locale
参见:怎样设置locale。
LC_CTYPE: cannot change locale (UTF-8)问题
错误发生原因
登录Linux服务器的时候,可能遇到这样的错误:
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
出现这个错误的原因是ssh终端会把本locale信息发送给服务器,服务器会去设置客户端发送过来的这些locale,如果客户端的locale在服务器上没有,那就会报对应错误。
比如我是Mac,Mac自带的ssh终端叫“终端.app”(英文叫“Terminal.app”),它的“Advanced”里有一个设置,叫Set locale environment variables on startup
, 如果勾选了,就会自动根据本地的locale去设置服务器的:
另外一个Mac常用的终端叫“iTerm2”,也是有相应的位置设置这个:
另一种可能就是,你客户端没勾选,但是在ssh配置文件~/.ssh/config
里设置了这行
SendEnv LANG LC_*
设置了这行也是用于发送本地locale参数到服务器的,理论上来说,就算客户端没勾,这里设置了应该也会发送的,但实际测试如果客户端没有勾,有这行也没用,客户端勾了,没这么也会发送,所以这个设置的意义好像不大。
有人可能会问,既然勾选了会报这个错误,那不勾选不就行了吗?——答案确实是这样,不勾选就不会报错,但客户端却默认勾选了,说明最好还是设置一下,因为跟你系统语言不一样,很有造成乱码,或者有些你看不习惯的格式。
什么是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?
不同系统的设置方式可能不同,我这里只说CentOS的。
1、CentOS7以下的locale设置是在/etc/sysconfig/i18n
文件中,i18n
是internationalization
的意思,这个单词是国际化的意思,因为单词太长,为了方便,只写第一个字母和最后一个字母,中间18个字母直接用数字18代替,表示这里有18个字母省略了。
2、CentOS7以上的locale设置是在/etc/locale.conf
,但它不需要自己直接修改,而是有命令可以用
localectl set-locale LANG=en_US.utf8
但实际上该命令就是直接把set-locale
后面的参数覆盖写入到/etc/locale.conf
文件中,所以实际使用的时候要同时设置多个(空格隔开即可):
localectl set-locale LANG=en_US.utf8 LC_CTYPE=en_US.utf8
注意:用localectl
设置是无法设置LC_ALL
的,因为LC_ALL
其实就是除LANG
外的其它属性,所以这个命令还不如不用。
而且由于该方式需要重启服务器才会生效,所以一般会在.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.1503 (Core)