以前也接触过国际化相关的任务,被properties文件的内容给吓坏了 :那些丑陋的UNICODE编码,维护起来确实让人头痛!更重要的是:售后服务人员想现场更改一下,他们根本不知道文件内容是什么玩意!
所以,原来针对国际化的态度就是:能不做就不做,反正软件也没有打算卖到国外去!
现在不得不做国际化了(并不是因为产品要卖到国外,而是很多用户对同个事物的叫法不同),先上网查一查,看看有没有大侠提供了更好的解决方案。
但是很失望,还是老一套。不过倒是有了开发环境下的中文与UNICODE之间转换的ECLIPSE插件!
但是总觉得不是很爽:开发环境下可以,脱离了开发环境怎么办呢?比如售后又跑到客户那里去了,客户要求改动一下某个属性的叫法……UNICODE仍然很难理解!
于是开始琢磨着如何不再把中文转换为UNICODE编码……
其实无论什么框架和组件(Spring、WEBWORK等),JAVA的国际化都是借助ResourceBoundle类实现的。既然没有好的资料,就看一下ResourceBoundle的源文件吧,这一看,发现解决问题的途径了:
获取资源文件的入口,最终必定是通过如下的方式调用:ResourceBoundle.getBoundle(……),参数必须包含资源文件的名称。这个调用,最终执行到以下代码:return new PropertyResourceBundle(stream);……
看到了吧,最后返回的是PropertyResourceBundle,该类是基于Properties实现的,而Properties的开发者根本就没有考虑国际化问题:看看资源文件的加载方法 public synchronized void load(InputStream inStream)……终于明白了,原来问题还是Properties导致的呀!这个类真是让中国用户(应该不止中国用户吧,应该是除了英语系地区之外的地区用户)痛苦不堪。想想也真是,JAVA的内核都是基于UNICODE实现的,该方法的接口为什么不接受Reader呢???
其实事情并没有想象的那么坏,继续看代码后发现:ResourceBundle.getBoundle(……)首先试着将传入的资源参数作为一个ResouceBoundle的子类进行处理,如果不成功,再作为资源文件名进行加载……作者真是天才,还留了这么一手呢,找到解决问题的钥匙了!!
以下做个测试:
package test;
import java.util.Enumeration;
import java.util.ResourceBundle;
public class UnicodeResourceBoundle extends ResourceBundle {
public Enumeration<String> getKeys() {
return null;
}
protected Object handleGetObject(String key) {
System.out.println("key:" + key);
return "中文测试";
}
public static void main(String[] args) {
ResourceBundle rb = ResourceBundle.getBundle("test.UnicodeResourceBoundle");
System.out.println(rb.getString("test"));
}
}
运行后,控制台下打印内容:
key:test
中文测试
同志们,已经找到真正支持中文的国际化的钥匙!!!!
剩下的事情就是:
实现一个ResourceBoundle子类,由该类负责所有资源文件的管理,通过Reader输入流,正确的处理资源文件的内容……最后,ResourceBoundle.getResource("ResourceBoundle子类全限定名称")……世界清静了。还有一个问题:ResourceBoundle具有资源文件的文件名称和语言及地区、变量(Variable)的加载策略,这个策略我们也要自己实现了(这个不难,已经实现了)。
目前,已经在WEBWORK环境内实现,资源文件编写起来确实非常方便,webwork.properties添加以下配置:
webwork.custom.i18n.resources=test.UnicodeResourceBundle
好了,就先到这里吧,睡觉了!