Linux: Localization

 24th February 2021 at 3:42pm

Linux 使用 locale 系统用来反映不同语言、文化中的习惯(时间格式、货币格式、数字格式等)及所使用的字符集(如 UTF-8)。

用户设置的 locale 会被一系列 glibc 函数读取及使用。设置好后体现为 LANGLC_* 这些环境变量;使用 locale 命令可以查看。不同的变量有不同的含义,比如:

  • LANG:其他变量没有定义时,默认使用这个
  • LC_NUMERIC:数值格式
  • LC_TIME:日期格式
  • LC_COLLATE:字符串排序方式,同时影响正则表达式匹配(比如某种 collate 定义了 A < a < B 时,[A-Z] 会包含 a, b 等,引起混乱)
  • LC_CTYPE:定义了终端(terminal)的编码,以及这种语言下哪些字符是字母、标点、空格等等,并定义了大小写规则(比如土尔其语 tr_TR 中,i 的大写是 İ
    • 如果你的终端使用的编码与 LC_CTYPE 定义的不一致,可能会有乱码。比如可以在 UTF8 终端下,设置 GB1312 的 LC_CTYPE,此时用 Vim 打开一个 UTF8 文件会乱码
  • LANGUAGE:一系列语言,用于翻译
  • LC_ALL:会覆盖除了 LANGUAGE 以外所有变量,用于调试

你还会看到这种 locale 名:C POSIX。它表示 ASCII 编码,并适用于 LC_COLLATE LC_CTYPE

最佳实践

根据这个写得非常好的 帖子,推荐的做法是:

  1. 设置 LANG 为你想要的 locale,比如 zh_CN.UTF8 或者 en_US.UTF8
  2. 显式设置 LC_COLLATELC_NUMERICC

操作

所有可用的 locale 被定义在 /etc/locale.gen 文件中。把想使用的 locale 取消注释,再运行 locale-gen 生成 locale 文件。

Note
需要 locale-gen 的原因是,全部语言的 locale 定义文件大约有 50MB 大,但用户往往只用其中一两个语言,所以 Linux 分发了 locale 定义文件的模板,再使用 locale-gen 生成实际的 locale 文件。

WSL

在 WSL2 中,使用 sudo update-locale LANG=en_US.UTF8 LC_NUMERIC=C LC_COLLATE=C 时两个 LC_* 变量无法生效。可能是因为 这个原因

参考