标签:
应用程序的功能和代码设计考虑在不同地区运行的需要,其代码简化了不同本地版本的生产。开发这样的程序的过程,就称为国际化。今天,我们就开始学习java中国际化的代码实现。
Java国际化主要通过如下3个类完成
为实现程序的国际化,必须提供程序所需要的资源文件。资源文件的内容由key-value对组成。资源文件的命名可以有3种格式:
java se的国际化实现,项目结构如下:
首先定义属性文件,它的命名规则见上述。具体代码ResourceBundleTest.java如下
一、得到所有可用的Locale,结果太长就不列出了,一共156列
public static void getLocales() { Locale[] availableLocales = Locale.getAvailableLocales(); System.out.println(availableLocales.length); for (Locale locale : availableLocales) { System.out.println(locale.toString()); } }
二、 使用系统默认的Locale
public static void useDefaultLocale() { ResourceBundle resourceBundle = ResourceBundle.getBundle("locale.myres"); String string = resourceBundle.getString("name"); System.out.println(string); }
ResourceBundle.getBundle("locale.myres")与ResourceBundle.getBundle("locale.myres", Locale.getDefault())一样。
三、 使用自己指定的Locale
public static void useOwnLocale() { Locale locale = new Locale("zh", "CN"); ResourceBundle resourceBundle = ResourceBundle.getBundle("locale.myres", locale); String string = resourceBundle.getString("name"); System.out.println(string); }
四、 使用带占位符的消息
public static void getMessage() { ResourceBundle resourceBundle = ResourceBundle.getBundle("locale/myres"); String message = resourceBundle.getString("message"); System.out.println(MessageFormat.format(message, "huhx", "刘力")); }
myres_zh_CN.properties文件中有:
message=My name is {0}?, and I love you. --{1}
打印结果: My name is huhx?, and I love you. --刘力
五、 使用类文件代替资源文件
Java允许使用类文件来代替资源文件,即手动书写代码来实现国际化,
在locale包下增加myres_zh_CN.java类,内容如下:
package locale; import java.util.ListResourceBundle; public class myres_zh_CN extends ListResourceBundle { private final Object myData[][] = { { "message", "Hello, {0} and {1}" }, { "test", "test" } }; @Override protected Object[][] getContents() { return myData; } }
在Main中的测试使用代码:
public static void getMessage() { ResourceBundle resourceBundle = ResourceBundle.getBundle("locale.myres"); String message = resourceBundle.getString("message"); System.out.println(MessageFormat.format(message, "huhx", "刘力")); }
打印结果:Hello, huhx and 刘力
注意:如果系统同时存在资源文件、类文件,系统将以类文件为主,而不会调用资源文件。例如对于basename为myres的这一系列中文资源文件,系统搜索顺序如下
如果getBundle的参数是“locale/myres”,那么位于locale的对应类就不会去查找,只会去查找属性文件。只有“locale.myres”才会先查找类,再查找属性文件
六、我们看一下ResourceBundle的getString(key)方法的源码,实际上是调用getObject(key)方法
public final Object getObject(String key) { Object obj = handleGetObject(key); if (obj == null) { if (parent != null) { obj = parent.getObject(key); } if (obj == null) throw new MissingResourceException("Can‘t find resource for bundle " +this.getClass().getName() +", key "+key, this.getClass().getName(), key); } return obj; }
首先会调用handleGetObject方法,代码如下:
public final Object handleGetObject(String key) { // lazily load the lookup hashtable. if (lookup == null) { loadLookup(); } if (key == null) { throw new NullPointerException(); } return lookup.get(key); // this class ignores locales }
lookup是Map<String,Object>,声明为空。执行loadLookup()方法
private synchronized void loadLookup() { if (lookup != null) return; Object[][] contents = getContents(); HashMap<String,Object> temp = new HashMap<>(contents.length); for (int i = 0; i < contents.length; ++i) { // key must be non-null String, value must be non-null String key = (String) contents[i][0]; Object value = contents[i][1]; if (key == null || value == null) { throw new NullPointerException(); } temp.put(key, value); } lookup = temp; }
执行ListResourceBundle的getContens()方法,将返回的结果有规律的对应键值对存放在map中。
If ListResourceBundle or PropertyResourceBundle do not suit your needs, you can write your own ResourceBundle subclass. Your subclasses must override two methods: handleGetObject and getKeys().
标签:
原文地址:http://www.cnblogs.com/huhx/p/JavaResourceBunlde.html