美文网首页Java基础
Java国际化——ResourceBundle基本使用

Java国际化——ResourceBundle基本使用

作者: 采药僧 | 来源:发表于2019-08-15 11:36 被阅读0次

    背景:企业项目中,往往面对国际的。针对不同地区语言,ResourceBundle主要用来处理本地化资源和国际化资源的问题,向用户展示合理的界面显示。

    ResourceBundle

    官方解释:一堆有着相同前缀名称但有着不同语言后缀名称的属性文件的集合,且至少包含2个有着相似前缀名称的属性文件。
    用途:从适合当前用户语言环境的资源包,一适应不同语言环境,后期提示语均在配置文件中,修改便捷。

    配合Locale使用:查询Java所支持的国家和语言,方便查询强制化Local属性。

    package study;
    
    import java.util.Locale;
    import java.util.ResourceBundle;
    
    public class Test {
        public static void main(String[] args) {
            Locale[] localeList = Locale.getAvailableLocales();
            //遍历数组的每个元素,依次获取所支持的国家和语言
            for (int i = 0; i < localeList.length ; i++ )
            {
                System.out.println(localeList[i].getCountry()+ "( "+localeList[i].getDisplayCountry() +")   "
                        +localeList[i].getLanguage()+"("+localeList[i].getDisplayLanguage()+")");
    
            }
    }
    
    
    加载顺序

    优先级:本地化资源(默认)>加载系统默认>加载默认的资源文件。
    不存在:java.util.MissingResourceException。

    本地资源构建:新建myconfig.properties相关文件
    myconfig.properties:local=default
    myconfig_zh_CN.properties:local=zh_CN
    myconfig_en_US.properties:local=en_US

    package study;
    import java.util.Locale;
    import java.util.ResourceBundle;
    public class Test {
        public static void main(String[] args) {
            //取得系统默认的国家/语言环境
            System.out.println("=================");
            //获取本地语言地区属性
            System.out.println("default:"+Locale.getDefault());
            //加载默认src下,但是不能读取其他文件加载,本class在src.study下,所以需要加前缀。
            ResourceBundle resourceBundle0 = ResourceBundle.getBundle("study.myconfig");
            System.out.println(resourceBundle0.getString("local"));
            System.out.println("=================");
            //中文测试
            Locale locale1 = new Locale("zh", "CN");
            ResourceBundle resourceBundle1 = ResourceBundle.getBundle("study.myconfig",locale1);
            System.out.println(resourceBundle1.getString("local"));
            System.out.println("=================");
            //英文测试
            Locale locale2 = new Locale("en", "US");
            ResourceBundle resourceBundle2 = ResourceBundle.getBundle("study.myconfig",locale2);
            System.out.println(resourceBundle2.getString("local"));
            System.out.println("=================");
             //德文测试,但不存在该语言的Properties
            Locale locale3 = new Locale("de", "GR");
            ResourceBundle resourceBundle3 = ResourceBundle.getBundle("study.myconfig",locale3);
            System.out.println(resourceBundle3.getString("local"));
    }
    
        
    
    测试结果: 配置文件都存在.png

    顺序:对于中国用户:中国>默认。英国用户:英国>默认。 德国:中国>默认(德国不存在,但是不是直接走默认,而是先走中国,中国是本地化资源!!!)
    特别:
    1.属性key-value,若上级资源中没有key,则去下级资源中寻找。
    2.优先走本地化资源文件。若不存在,则走不带后缀文件,本地化资源文件不等于默认不带后缀的配置文件。

    删除myconfig_zh_CN.properties:

    本地资源不存在.png

    顺序:对于中国用户:默认。英国用户:英国>默认。 德国:默认(德国不存在,但是不是直接走默认,而是先走中国,中国是本地化资源!!!)

    其他注意:
    报错:Can't find bundle for base name myconfig, locale xx_XX。查找文件路径是否正确。

    • 直接配置,src下读取,但是内部文件夹,需要前缀读取。
    • src路径下的文件在编译后会放到WEB-INF/clases路径下(默认的classpath)
    • 直接放到WEB-INF下的话,是不在classpath下的

    编码:

    底层读取Properties文件是根据字节流的形式,防止中文乱码,建议配置文件存在中文等,使用Unicode字符集进行配置。
    源码片段:

     else if (format.equals("java.properties")) {
                    final String resourceName = toResourceName0(bundleName, "properties");
                    if (resourceName == null) {
                        return bundle;
                    }
                    final ClassLoader classLoader = loader;
                    final boolean reloadFlag = reload;
                    InputStream stream = null;
                    try {
                        stream = AccessController.doPrivileged(
                            new PrivilegedExceptionAction<InputStream>() {
                                public InputStream run() throws IOException {
                                    InputStream is = null;
                                    if (reloadFlag) {
                                        URL url = classLoader.getResource(resourceName);
                                        if (url != null) {
                                            URLConnection connection = url.openConnection();
                                            if (connection != null) {
                                                // Disable caches to get fresh data for
                                                // reloading.
                                                connection.setUseCaches(false);
                                                is = connection.getInputStream();
                                            }
                                        }
                                    } else {
                                        is = classLoader.getResourceAsStream(resourceName);
                                    }
                                    return is;
                                }
                            });
                    } catch (PrivilegedActionException e) {
                        throw (IOException) e.getException();
                    }
                   
    

    经验

    1.可以通过只配置myconfig.properties来全局变量,不配置其他语言文件。
    2.企业项目中,配合PropertyUtils,设置map.properties,不打包,当国际化各个配置文件找不到相应提示,提供一个类别管理的报错。
    3.编码问题请使用Unicode字符集输入,可以使用在线转码工具也可以配合java自带的native2ascii.exe
    4.配合NumberFormat ,DateFormat进行String处理

    补充

    Properties补充:
    https://www.cnblogs.com/alfredinchange/p/5384760.html
    ResourceBundle运行会自行将配置文件打包,也可以根据情况自己配合idea打包:https://segmentfault.com/a/1190000016496715
    Spring相关:https://blog.csdn.net/u010882791/article/details/83756717

    相关文章

      网友评论

        本文标题:Java国际化——ResourceBundle基本使用

        本文链接:https://www.haomeiwen.com/subject/fqowjctx.html