• java基础---->java中国际化的实现


      应用程序的功能和代码设计考虑在不同地区运行的需要,其代码简化了不同本地版本的生产。开发这样的程序的过程,就称为国际化。今天,我们就开始学习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的国际化实现,项目结构如下:

    首先定义属性文件,它的命名规则见上述。具体代码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(). 

    友情链接

  • 相关阅读:
    壁纸网站收藏
    LaTeX公式学习
    最简单的音乐播放器,实现播放器基本功能
    计算机视觉领域的牛人博客、研究机构、博客
    视频压缩编码和音频压缩编码的基本原理
    MPEG-4 压缩编码标准
    视频编码标准简介
    视频压缩编码的基本原理
    数字视频原理
    视频压缩编码综述
  • 原文地址:https://www.cnblogs.com/huhx/p/JavaResourceBunlde.html
Copyright © 2020-2023  润新知