运行 pg 数据库后,查询支持的 locale,只有如下项目:
缺少对 zh_CN 的支持,需要排查问题。
locale -a 的输出信息表明存在 zh_CN 的 locale 支持
输出信息表明数据库的 locale 被设定为 en_US.UTF-8
The database cluster will be initialized with locale "zh_CN.UTF-8". initdb: error: locale "zh_CN.UTF-8" requires unsupported encoding "GBK" Encoding "GBK" is not allowed as a server-side encoding. Rerun initdb with a different locale selection.
使用 initdb: error: locale “zh_CN.UTF-8” requires unsupported encoding “GBK” 检索互联网,没有找到可用的信息。
The database cluster will be initialized with locale "zh_CN.UTF-8". The default database encoding has accordingly been set to "UTF8". initdb: could not find suitable text search configuration for locale "zh_CN.UTF-8" The default text search configuration will be set to "simple".
在我的 debian10 系统中,执行 sudo dpkg-reconfigure locales,选择如下项目生成 locale:
en_US.UTF-8 zh_CN.GB2312 zh_CN.GB18030 zh_CN.GBK zh_CN.UTF-8
生成之后拷贝设备上的 /lib/locale/locale-archive 文件到异常环境中的相同目录中,然后重试,问题得到解决。
替换 /lib/locale/locale-archive 是我过去在解决一个终端中文乱码时搞过的内容,但是并不清楚 locale 是怎么使用这个文件的,通过查看 locale 的 manual 内容,发现可以指定一个 -v 参数获取一些额外的信息。
异常环境中执行 locale -a -v 信息,获取到的 zh_CN.utf8 locale 相关信息摘录如下:
locale: zh_CN.utf8 archive: /usr/lib/locale/locale-archive ------------------------------------------------------------------------------- title | Chinese locale for Peoples Republic of China email | bug-glibc-locales@gnu.org language | Chinese territory | P.R. of China revision | 0.1 date | 2000-07-25 codeset | GBK
正常环境中执行 locale -a -v 信息,获取到的 zh_CN.utf8 locale 相关信息摘录如下:
locale: zh_CN.utf8 archive: /usr/lib/locale/locale-archive ------------------------------------------------------------------------------- title | Chinese locale for Peoples Republic of China email | bug-glibc-locales@gnu.org language | Chinese territory | China revision | 0.1 date | 2000-07-25 codeset | UTF-8
对比发现,正常环境中 zh_CN.utf8 locale 的 codeset 为 UTF-8,异常环境中 zh_CN.utf8 locale 的 codeset 为 GBK,联系 initdb: error: locale “zh_CN.UTF-8” requires unsupported encoding “GBK” 报错信息,不难确定是异常环境中的 zh_CN.utf8 locale 的 codeset 为 GBK,而 PG 不支持 GBK 导致无法配置问题。
在 linux 中可以 locale-gen 来重新生成 locale,locale-gen 是一个 shell 脚本。locale-gen 最终通过调用 localedef 程序来生成相关的文件,这些生成的文件用于 c 库 setlocale,localeconv 等 locale 相关函数。
localedef 生成的内容有两种保存形式,一种是保存在 /usr/lib/locale/locale-archive 文件中,一种是保存在 /lib/locale 中以 locale 文件命令的子目录中。
保存在子目录中的一个示例如下:
root@debian:/tmp # ls -lh /lib/locale/C.UTF-8/ total 1.7M -rw-r--r-- 1 root root 131 May 1 2019 LC_ADDRESS -rw-r--r-- 1 root root 1.5M May 1 2019 LC_COLLATE -rw-r--r-- 1 root root 197K May 1 2019 LC_CTYPE -rw-r--r-- 1 root root 252 May 1 2019 LC_IDENTIFICATION -rw-r--r-- 1 root root 23 May 1 2019 LC_MEASUREMENT drwxr-xr-x 2 root root 4.0K Feb 1 2021 LC_MESSAGES -rw-r--r-- 1 root root 270 May 1 2019 LC_MONETARY -rw-r--r-- 1 root root 62 May 1 2019 LC_NAME -rw-r--r-- 1 root root 50 May 1 2019 LC_NUMERIC -rw-r--r-- 1 root root 34 May 1 2019 LC_PAPER -rw-r--r-- 1 root root 47 May 1 2019 LC_TELEPHONE -rw-r--r-- 1 root root 3.3K May 1 2019 LC_TIME
localedef 使用到的下面两个关键文件名称与功能如下:
/usr/share/i18n/charmaps Usual default character map path. /usr/share/i18n/locales Usual default path for locale definition files.
charmaps 中保存 gzip 压缩过的语言编码集,locales 中保存组成一个独立 locale 完整条目的规则信息,包含如下几个项目:
category "i18n:2012";LC_IDENTIFICATION category "i18n:2012";LC_CTYPE category "i18n:2012";LC_COLLATE category "i18n:2012";LC_TIME category "i18n:2012";LC_NUMERIC category "i18n:2012";LC_MONETARY category "i18n:2012";LC_MESSAGES category "i18n:2012";LC_PAPER category "i18n:2012";LC_NAME category "i18n:2012";LC_ADDRESS category "i18n:2012";LC_TELEPHONE category "i18n:2012";LC_MEASUREMENT
生成一个 locale 的主要过程是 localedef 将系统 /usr/share/i18n/locales 目录中不同语系的规则使用 /usr/share/i18n/charmaps 中的指定编码生成每个 LC_XXX 列表的内容。
http://t.zoukankan.com/songyuejie-p-3925371.html
https://www.postgresql.org/docs/current/locale.html