应用程序的功能和代码设计考虑在不同地区运行的需要,其代码简化了不同本地版本的生产。开发这样的程序的过程,就称为国际化。今天,我们就开始学习java中国际化的代码实现。

Java国际化主要通过如下3个类完成

  • java.util.ResourceBundle:用于加载一个资源包
  • java.util.Locale:对应一个特定的国家/区域、语言环境。
  • java.text.MessageFormat:用于将消息格式化

为实现程序的国际化,必须提供程序所需要的资源文件。资源文件的内容由key-value对组成。资源文件的命名可以有3种格式:

  • basename_language_country.properties
  • basename_language.properties
  • basename_properties

java se中国际化的实现

java se的国际化实现,项目结构如下:

aaarticlea/png;base64,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" alt="" />

首先定义属性文件,它的命名规则见上述。具体代码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允许使用类文件来代替资源文件,即手动书写代码来实现国际化,

  • 该类要求继承于ListResourceBundle,并重写getContents方法该方法返回Object数组,该数组的每一个项都是key-value对。
  • 类的名字必须为basename_language_contry,这与属性文件的命名相似

在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的这一系列中文资源文件,系统搜索顺序如下

  1. myres_zh_CN.java
  2. myres_zh_CN.properties
  3. myres_zh.java
  4. myres_zh.properties
  5. myres.java
  6. myres.properties

如果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(). 

友情链接

最新文章

  1. BigDecimal类
  2. 自己用WordPress搭了个站点
  3. Hadoop 面试题 之Hive
  4. Hadoop学习笔记: MapReduce二次排序
  5. 图形用户界面(graphical user interface)
  6. LA_3263_That_Nice_Euler_Circuits_(欧拉定理+计算几何基础)
  7. 关于js的那些事儿
  8. node源码详解(六) —— 从server.listen 到事件循环
  9. Postman 使用详解
  10. Web安全之XSS Platform搭建及使用实践
  11. linux /proc目录
  12. 《nginx - 基本操作/配置》
  13. leetcode206
  14. ubuntu 14.04 安装pip
  15. 用微信小程序连接WordPress网站
  16. MySQL按照汉字拼音首字母排序
  17. Scrapyd发布爬虫的工具
  18. .net core An assembly specified in the application dependencied mainfest&lt;****.json&gt;was not found解决办法
  19. Kali-linux使用Wifite破解无线网络
  20. .Net Core配置与自动更新

热门文章

  1. kubernetes daahboard权限限制
  2. java中的方法——重载yu重写(转)
  3. javascript那些不应该忽视的细节
  4. arduino~snprintf
  5. Wordpress搭建社交型小游戏网站10大步骤
  6. Android Studion的Monitor中显示No Debuggable Application的解决方法
  7. 解决App can’t be opened because it is from an unidentified developer
  8. Python之多进程
  9. 远程桌面能连接到服务器,但PING不通
  10. java---EL与ONGL的区别