解决LC_CTYPE: cannot change locale (UTF-8)及vim中文乱码问题

解决LC_CTYPE: cannot change locale (UTF-8)及vim中文乱码问题

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去设置服务器的:
image

另外一个Mac常用的终端叫“iTerm2”,也是有相应的位置设置这个:
image

另一种可能就是,你客户端没勾选,但是在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文件中,i18ninternationalization的意思,这个单词是国际化的意思,因为单词太长,为了方便,只写第一个字母和最后一个字母,中间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值是这样的:

Xnip2019-01-22_14-19-47.jpg

如上图所示,除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

Xnip2019-01-22_14-30-08.jpg

但奇怪的是,这个错误只会出现在往~/.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外的其他选项的值都设置了):

Xnip2019-01-22_14-37-58.jpg

如上图,这样设置只是比用LC_ALL设置少一个LC_ALL的值,但由于LC_ALL本身是没什么作用的,它的作用就是设置除自己和LANG以外的那10个变量,既然这里那10个变量已经被LC_CTYPE设置,那么LC_ALL就无需设置了。

值得注意的是,上面的例子如果去掉LANG设置,只写成这样:

export LC_CTYPE="zh_CN.UTF8"

那么它只会设置它自己(即LC_CTYPE),而不会设置其他的:

Xnip2019-01-22_14-42-56.jpg

以上例子测试环境为:CentOS Linux release 7.1.1503 (Core)

打赏
订阅评论
提醒
guest

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x

扫码在手机查看
iPhone请用自带相机扫
安卓用UC/QQ浏览器扫

解决LC_CTYPE: cannot change locale (UTF-8)及vim中文乱码问题