官方文档:英文:http://www.postgresql.org/docs/9.2/static/charset.html
中文:http://58.58.27.50:8079/doc/html/9.3.1_zh/charset.html
pg中的本地化消息设置:http://blog.chinaunix.net/uid-20726500-id-4675473.html
linux下的locale设置: http://blog.chinaunix.net/uid-26760055-id-3222699.html
locale中文翻译成区域,其实这个单词包含的意义要宽泛很多。Locale是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。
操作系统的locale设置(以linux为例)
操作系统环境变量针对语言项设置有几个,经常设置的是这两个LANG和NLS_LANG。LANG是针对Linux系统的语言、地区、字符集的设置,对linux下的应用程序有效(包括postgresql),如date;NLS_LANG是针对Oracle语言、地区、字符集的设置,对oracle中的工具有效。
Linux系统中关于环境变量的LANG设置主要有下列项目:
[root@lyy bin]#export LANG='zh_CN.gb2312'
[root@lyy bin]#echo $LANG
zh_CN.gb2312
[root@lyy bin]# locale
LANG=zh_CN.gb2312
LC_CTYPE="zh_CN.gb2312"
LC_NUMERIC="zh_CN.gb2312"
LC_TIME="zh_CN.gb2312"
LC_COLLATE="zh_CN.gb2312"
LC_MONETARY="zh_CN.gb2312"
LC_MESSAGES="zh_CN.gb2312"
LC_PAPER="zh_CN.gb2312"
LC_NAME="zh_CN.gb2312"
LC_ADDRESS="zh_CN.gb2312"
LC_TELEPHONE="zh_CN.gb2312"
LC_MEASUREMENT="zh_CN.gb2312"
LC_IDENTIFICATION="zh_CN.gb2312"
LC_ALL=
这里LC_ALL没有设置,如果它设置了,上面所有的设置都无效的,系统会读取LC_ALL。
查看本地字符集:
[root@lyy bin]#locale -a
查看所有支持的字符集:
[root@lyy bin]#locale -m
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就是设定12大类的locale分类属性,即12个LC_*。除了这12个变量可以设定以外,为了简便起见,还有两个变量:LC_ALL和LANG。它们之间有一个优先级的关系:LC_ALL > LC_* >LANG。可以这么说,LC_ALL是最上级设定或者强制设定,而LANG是默认设定值。
1、如果你设定了LC_ALL=zh_CN.UTF-8,那么不管LC_*和LANG设定成什么值,它们都会被强制服从LC_ALL的设定,成为 zh_CN.UTF-8。
2、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*=en_US.UTF-8,并且没有设定LC_ALL的话,那么系统的locale设定以LC_*=en_US.UTF-8。
3、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*,和LC_ALL均未设定的话,系统会将LC_*设定成默认值,也就是LANG的值zh_CN.UTF-8。
4、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_CTYPE=en_US.UTF-8,其他的LC_*,和LC_ALL均未设定的话, 那么系统的locale设定将是:LC_CTYPE=en_US.UTF-8,其余的 LC_COLLATE,LC_MESSAGES等等均会采用默认值,也就是 LANG的值,也就是LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=zh_CN.UTF-8。
所以,locale是这样设定的:
1、如果你需要一个纯中文的系统的话,设定LC_ALL= zh_CN.XXXX,或者LANG=zh_CN.XXXX都可以,当然你可以两个都设定,但正如上面所讲,LC_ALL的值将覆盖所有其他的locale设定,不要作无用功。
2、如果你只想要一个可以输入中文的环境,而保持菜单、标题,系统信息等等为英文界面,那么只需要设定 LC_CTYPE=zh_CN.XXXX,LANG=en_US.XXXX就可以了。这样LC_CTYPE=zh_CN.XXXX,而LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=en_US.XXXX。
3、假如你高兴的话,可以把12个LC_*一一设定成你需要的值,打造一个古灵精怪的系统: LC_CTYPE=zh_CN.GBK/GBK(使用中文编码内码GBK字符集); LC_NUMERIC=en_GB.ISO-8859-1(使用大不列颠的数字系统) LC_MEASUREMEN=de_DE@euro.ISO-8859-15(德国的度量衡使用ISO-8859-15字符集) 罗马的地址书写方式,美国的纸张设定……。估计没人这么干吧。
4、假如你什么也不做的话,也就是LC_ALL,LANG和LC_*均不指定特定值的话,系统将采用POSIX作为lcoale,也就是C locale。
另外LANG和LANGUAGE有什么区别呢?
LANG - Specifies the default locale for all unset locale variables
LANGUAGE - Most programs use this for the language of its interface
LANGUAGE是设置应用程序的界面语言。而LANG是优先级很低的一个变量,它指定所有与locale有关的变量的默认值。
locale设置的含义:
zh_CN.UTF-8 表示语言为中文,地区为中国,编码为UTF-8 (操作系统语言是中文,初次设置可能需要重启)
en_US.UTF-8 表示语言为英文,地区为美国,编码为UTF-8 (操作系统语言是英文,初次设置可能需要重启)
环境变量的三个设置方法及其生命期
Linux下:echo $paraName = paraValue , 临时定义,只在该登陆操作内有效
在特定用户目录下的.bashrc(该文件是隐藏文件,用ls -al才能看到)文件中添加paraName=paraValue, 只对该用户登录时有效
在/etc/profile文件中添加paraName=paraValue, 对系统中所有用户都有效
(以上若在终端操作,则终端语言会接着就改变了)
2.pg中的locale属性设置
2.1. 区域支持
区域支持指的是应用中考虑字母、排序、数值格式化等与文化相关的问题。 PostgreSQL使用服务器操作系统提供的标准ISO C 和POSIX区域机制。 更多的信息请参考你的系统文档。
2.1.1. 概述
区域支持是在使用initdb创建一个数据库集群的时候自动初始化的。 缺省时,initdb将会按照它的执行环境的区域设置初始化数据库集群; 因此如果你的系统已经设置为你的数据库集群想要的区域,那么你就没有什么可干的了。 如果你想使用其它的区域(或者你还不知道你的系统设置的区域是什么), 那么你可以用--locale命令行选项告诉initdb你需要的区域究竟是哪个。 比如:
initdb --locale=sv_SE
Unix系统下的这个例子就把区域设置为说瑞典语(sv),并且在瑞典地区(SE)。 其它的可能性是en_US(美国英语)和fr_CA(加拿大法语)等等。 如果有多于一种的字符集可以用于同一个区域,那么声明看起来会像language_territory.codeset。 比如,fr_BE.UTF-8表示为在比利时(BE)地区使用的法语(fr),并且使用UTF-8字符集编码。
你的系统里有哪些可用的区域设置,它们的名字是什么, 这些信息都取决于你的操作系统提供商提供了什么以及你安装了什么东西。 在大多数系统上,命令locale -a将提供所有可用区域的一个列表。 Windows使用更详细的区域名称,比如German_Germany或者Swedish_Sweden.1252, 但是原则是一样的。
有时候,把几种区域规则混合起来也很有用,比如, 使用英语排序规则而用西班牙语消息。为了支持这些, 我们有一套区域子范畴用于控制区域规则的某一方面:
LC_COLLATE字符串排序顺序
LC_CTYPE字符分类(什么是字母?是否区分大小写?)
LC_MESSAGES消息的语言
LC_MONETARY货币金额的格式
LC_NUMERIC数值格式
LC_TIME日期和时间格式
这些范畴名转换成initdb选项的名字以覆盖某个特定范畴的区域选择。 比如,要把区域设置为加拿大法语,但使用美国的货币格式化规则, 可以使用initdb --locale=fr_CA --lc-monetary=en_US。
如果你想要你的系统表现得像没有区域支持一样,那么使用特殊的区域C或POSIX。一些区域范畴的值必须在创建数据库时固定下来。 您可以对不同的数据库使用不同的设置,但一旦创建一个数据库,你就再也不能更改它们了。 LC_COLLATE和LC_CTYPE就是这样的范畴。 它们影响索引的排序顺序,因此它们必需保持固定,否则在文本字段上的索引将会崩溃。 (但是你可以使用排序规则(collation)缓解这种限制,正如Section 22.2中讨论的)。 当运行initdb时确定这些范畴的缺省值, 这些值被用于创建新的数据库,除非在CREATE DATABASE命令中明确指定。
其它区域范畴可以在服务器启动的时候根据需要设置 服务器配置参数来改变(参阅Section 18.11.2获取细节)。 initdb选择的值实际上只是作为服务器启动时的缺省值写入 postgresql.conf配置文件。 如果你在postgresql.conf里面删除了这些设置, 那么服务器将会继承来自运行环境的设置。
请注意服务器的区域行为是由它看到的环境变量决定的, 而不受客户端的环境影响。 因此,我们要在启动服务器之前认真地设置好这些变量。 这样带来的一种情况是如果客户端和服务器设置成不同的区域, 那么消息可能以不同的语言呈现,这取决于消息的来源。
Note: 在我们谈到从执行环境继承区域的时候, 我们的意思是在大多数操作系统上的下列动作: 对于一个给定的区域范畴, 比如排序规则,按照下面的顺序评估这些环境变量, 直到找到一个已设置的:LC_ALL, LC_COLLATE (或者对应于相应范畴的其他变量), LANG。 如果这些环境变量一个都没有设置,那么区域缺省为C。
一些消息本地化库也使用环境变量LANGUAGE, 它覆盖所有其它用于设置语言信息的区域设置。 如果有问题,请参考你的操作系统文档, 特别是gettext的文档以获取更多信息。
要能够将消息翻译成用户选择的语言,编译时必需选择NLS选项(configure --enable-nls)。 其它区域支持是自动包含的。
22.1.2. 行为
区域设置特别影响下面的 SQL 特性:
1 查询中使用ORDER BY或者对文本数据的标准比较操作符进行排序
2 upper, lower和initcap函数模式匹配运算符(LIKE, SIMILAR TO, 以及POSIX-风格的正则表达式); 区域影响大小写不敏感的匹配和通过字符分类正则表达式的字符分类。
3 to_char函数族
4 使用LIKE子句的索引能力
PostgreSQL里使用非C或者POSIX区域的缺点是性能影响。 它降低了字符处理的速度并阻止了在LIKE类查询里面普通索引的使用。 因此,应该只有在你实际上需要的时候才使用它。
为了允许PostgreSQL在非C区域下的LIKE子句中使用索引, 有好几个自定义的操作符类可以用。 这些操作符类允许创建一个严格地比较每个字符的索引, 而忽略区域比较规则。请参考Section 11.9获取更多信息。 另外一个方法是使用C collation创建索引,正如Section 22.2 中讨论的。
22.1.3. 问题
如果经过上面解释后区域支持仍然不能运转, 那你就要检查一下操作系统的区域支持是否正确配置。 要检查某个区域是否安装并且正常运转, 你可以使用locale -a命令(如果你的系统提供了该命令)。
请检查核实PostgreSQL确实使用了你认为它该用的区域设置。 LC_COLLATE和LC_CTYPE的设置都是在数据库创建时决定的, 不能被改变除非创建新的数据库。其它的区域设置包括 LC_MESSAGES和LC_MONETARY都是由服务器的启动环境决定的, 但是可以在运行时修改。你可以用SHOW命令检查数据库正在使用的区域设置。
源码发布中的src/test/locale目录包含 PostgreSQL的区域支持测试套件。
那些通过解析错误消息文本处理服务器端错误的客户端应用很明显会有问题, 因为服务器信息可能会以不同的语言表示。我们建议这类应用的开发人员改用错误代码机制。
维护消息翻译表需要许多志愿者的坚持不懈的努力, 他们就是希望PostgreSQL以他们的语言说话的人。 如果你的语言消息目前还不可用或者没有完全翻译完成, 那么我们很欢迎你的协助。如果你想帮忙, 那么请参考Chapter 50或者向开发者邮递列表发邮件。
3.小总结
pg的语言一开始是根据OS的locale的。OS的locale设置是根据LC_ALL > LC_* > LANG 的优先级来设置的:如果定义了LC_ALL那么LC_*均与LC_ALL保持一致,LANG不起作用;如果LC_ALL和LC_*均未设置,那么设置LANG后,LC_ALL和LC_*将使用默认值LANG;
Linux下环境变量的三种设置方法及其生命期:
echo $paraName = paraValue , 临时定义,只在该登陆操作内有效
在特定用户目录下的.bashrc(该文件是隐藏文件,用ls -al才能看到)文件中添加paraName=paraValue, 只对该用户登录时有效
在/etc/profile文件中添加paraName=paraValue, 对系统中所有用户都有效
(以上若在终端操作,则终端语言会紧接着生效)
DB初始化后一部分local属性在初始化时确定了下来(LC_COLLATE和LC_CTYPE在数据库初始化后便不能再修改(server_encoding也不能修改,他们都能通过sql语句show出来)其他的可以在运行中修改),初始化完成后查看postgresql.conf中的locale相关参数,已指定的会体现出来,未指定的就是使用的默认值;如果想要数据库系统没有区域限制,那么使用特殊的区域C或POSIX来初始化。
pg的消息的语言是由lc_messages设置的。设置OS的locale为en_us.UTF8会使得psql的运行环境成为英文的;设置lc_messages='c'可以使得服务器的消息为英文,能保证各种中间件得到的消息不会成为乱码。
在pg中locale项的两种设置方式及其生命期
sql下set lc_messages='zh_CN.UTF-8'仅对该登陆起效,
要想使得配置永久生效,需要在/data/postgresql.conf总添加lc_messages='zh_CN.UTF-8',保存后,重启服务或者重载。
[lyy@linux bin]$ export LANG=zh.CN.UTF-8 --设置操作系统语言为中文
[lyy@linux bin]$ ./psql --登陆数据库之前语言是中文
口令:
psql(9.2.1)
输入“help”来获取帮助信息。
lyy=# show lc_messages;
lc_messages
------------------
C
(1行记录) --lc_messages值为C,登陆数据库后消息语言还是中文
lyy=# show server_encoding;
server_encoding
------------------
UTF-8
(1行记录)
lyy=# show client_encoding;
server_encoding
------------------
UTF-8
(1行记录)
lyy=# \q
[lyy@linux bin]$ export LANG=en_US.UTF-8 --设置操作系统语言为英文
[lyy@linux bin]$ ./psql
Password: --登陆数据库之前语言是英文
psql(9.2.1)
Type“help” for help.
lyy=# show lc_messages;
lc_messages
------------------
C
(1 row) --lc_messages值为C,登陆数据库后消息语言还是英文
lyy=# set lc_messages='zh_CN.UTF-8'; --lc_messages值修改为中文,数据库消息变为中文
SET
lyy=# dd;
错误: 与犯错误 在“DD”或附近
LINE 1:DD
常见乱码情况:JDBC中,消息都转为UTF8,但是连接错误容易出乱码,因为那时候客户端还不知道服务器的编码,不能进行编码转换,所以如果消息不是UTF8的就会乱,只有恰巧也是UTF8的才会不是乱码。