在Grails项目中,实现国际化,遇到了中文乱码的问题,几经学习问题解决了。本着打破砂锅的精神,又折腾到凌晨2点,初步研究了一下字符编码等知识。
====基础====
---ANSI---
字符编码:
ASCII = 英文字母编码
GB2312 = ASCII + 简体编码(对ASCII的中文扩展)
Big5 = ASCII + 繁体编码
(还有针对日语、韩语等字符编码)
以上统称为ANSI,也就是操作系统的默认编码
---Unicode---
Unicode:万国码,任何字符都是2个字节
UTF-8:Unicode的“英文”压缩形式,经过一定算法的转换,英文只用1个字节,汉字用3个字节。所以适合英文为主的网站。
UTF-16:不压缩,任何字符都是2个字节,看似适合中文为主的网站,但仔细想想HTML语言又包含大量英文,所以还是用GB2312比较合适(英文1字节、中文2字节)。
注:UTF主要是互联网兴起后,需要考虑传输效率才出现的。
---测试---
用记事本输入“严严”,另存为的时候选择不同的编码,在用UE查看16进制
|
文件头 |
内容 |
ANSI |
无 |
D1 CF D1 CF |
Unicode |
FF FE |
25 4E 25 4E |
Unicode-B |
FE FF |
4E 25 4E 25 |
UTF-8 |
EF BB BF |
E4 B8 A5 E4 B8 A5 |
超级混淆:这里的Unicode(保存格式)其实意思是UTF-16-Little-Endian(小尾、逆序),而Unicode-B和Unicode(原始编码)在编码上是一致的。
Mac中使用大尾格式,Windows或Linux使用小尾格式。
---文件头---
如果没有文件头,操作系统就会以默认的ANSI进行解码。
UTF-8的文件头,其实就是Unicode-B的文件头进行UTF-8算法得来的:FEFF --> EFBBBF。所以UTF-8也是顺序的。
====JAVA====
Java因为其跨平台的需求,在内部运算中,涉及到的所有字符串都会被转化为unicode来进行运算。
所以代码都以UTF-8来存放,就最不容易出现乱码问题。
---native2ascii---
JDK提供了将“字符”转化为“unicode编码”的工具
txt文件保存的内容“严严”
C:\Users\Calvin\Desktop\test1>native2ascii ANSI.txt ANSI.ascii.txt
\u4e25\u4e25
连文件头也编码了。。。是不是有点多余。。
C:\Users\Calvin\Desktop\test1>native2ascii -encoding utf-8 utf8.txt utf8.ascii.txt
\ufeff\u4e25\u4e25
乱码:因为utf8.txt是utf-8格式的,而没有指定-encoding参数,就会以系统默认的ANSI去解析,就出现错误
C:\Users\Calvin\Desktop\test1>native2ascii utf8.txt utf8.ascii2.txt
\u9518\u5938\u5f17\u6d93\ufffd
====Grails i18n====
1. 字典:位于grails-app/i18n下,默认会创建好几种语言的属性文件,我们只需要保留messages.properties和messages_zh_CN.properties即可
2. 使用:gsp页面中,<g:message code="company.name"/>
3. 自动识别:默认是以浏览器的设置进行语言的识别
4. 手动选择:
<div class="right">
<g:link url="${request.requestURI}?lang=en_US">English</g:link>
| <g:link url="${request.requestURI}?lang=zh_CN">中文</g:link>
</div>
中文乱码问题
1. 检查发现messages_zh_CN.properties是GBK编码的,所以会被读成乱码
2. 解决办法,仍然是GBK编码,但是将中文转化为unicode
company.name=\u516c\u53f8
但这样编辑起来很痛苦
3. 也可以将properites文件保存为UTF-8格式
company.name=公司
这样即方便编辑,又不会有乱码
注:但保存为UTF-16是不行的,网上都说properites文件只能用unicode保存中文,我推测是Grails做了类似工作来兼容UTF-8的格式。
Properties prop=new Properties();
prop.load(new InputStreamReader(Client.class.getClassLoader().getResourceAsStream("config.properties"), "UTF-8"));
参考
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html