• 国际化的实现i18n--错误码国际化以及在springboot项目中使用


    国际化 ,英文叫 internationalization 单词太长 ,又被简称为 i18n(取头取尾中间有18个字母);

    主要涉及3个类: Locale用来设置定制的语言和国家代码 

           ResourceBundle 用来加载国际化资源文件

           MessageFormat 用来格式化占位符

    //先看结构:

    在创建国际化资源文件时,如我在resources文件下建了一个i18n文件夹,下放了3个资源文件,idea自动会生成一个Resource Bundle 'messages'文件夹,这个文件夹不是真实存在的,打开项目所在文件夹后,找不到它的;如图:

    资源文件的命名格式:前缀+"_"+"语言代码"+地区代码+".properites";(

    Locale[] locales = Locale.getAvailableLocales();//获取世界可用的语言地区表示

    )

    如上图所示,我定义了3个资源文件夹,其中一个没有语言代码和地区代码的那个是默认资源,也就是要找的资源文件都不存在时,就会去那里找;

    查找顺序,如果你指定Locale locale=new Locale("en_US"),那它就会找到messages_en_US.properties,如果你写错了一个单词Locale locale=new Locale("en_USAA");找不到的话,它就会找本地的语言(

    Locale locale2 = Locale.getDefault(); //获取默认语言地区

    ),如我们在中国就会找本地的中国语言包messages_zh_CN.properties,如果没有本地的语言包messages_zh_CN.properties,就会去messages.properties这里找

    资源文件的内容格式为:key=value,其中value值可以含有占位符,格式{数字},例如" 你的订单号{0}的订单,金额{1}元";

    key和value值在properties文件中都不用加双引号

    注意:

    资源文件中的所有字符都必须是 ascll 码 ,不能保存为中文的 ,Java 中提供 了 native2ascll 工具用于将中文转化为 ascll 码 。所以在编写 properties 文件的时候写的是中文 ,一回车就自动被编码了 。

    在idea工具中,可以设置显示为中文:

    后端做国际化用得比较多的情况是错误码国际化:具体代码如下:

     @Test
        public void test2(){
            Locale locale1 = new Locale("en_US");
            Locale locale2 = Locale.getDefault(); //获取默认语言地区
            System.out.println(locale2.getCountry()); //CN
            System.out.println(locale2.getDisplayCountry()); //中国
            System.out.println(locale2.getDisplayLanguage()); //中文
            System.out.println(locale2.getDisplayName()); //中文(中国)
            System.out.println(locale2.getDisplayLanguage(locale1)); //以某种语言显示语言,这里是Chinese
            System.out.println(locale2.getLanguage()); //zh 语言代表符
            System.out.println(locale2.toLanguageTag()); //语言标签 格式语言-国家 这里是zh-CN
            //Locale自定义了很多语言跟国家常量 如中国 和中文,德国和德文
            Locale china = Locale.CHINA; // zh-Cn
            Locale chinese = Locale.CHINESE; //ZH
            System.out.println(china.toLanguageTag()); //ZH-CN
            System.out.println(chinese.toLanguageTag()); //ZH
            Locale german = Locale.GERMAN; //de
            Locale germany = Locale.GERMANY; //de-DE
            System.out.println(german.toLanguageTag());//de
            System.out.println(germany.toLanguageTag());//de-DE
            Locale[] locales = Locale.getAvailableLocales();//获取世界可用的地区
            for (Locale locale : locales) {
                System.out.println(locale.toLanguageTag());
            }
            ResourceBundle resourceBundle = ResourceBundle.getBundle("i18n/messages",locale2); //这里的baseName也可以表示成i18n.messages形式,messages是虚拟的包名
    
            String s = resourceBundle.getString("103014"); //我在资源文件存了:103014=订单号为{0}的订单已经支付
            MessageFormat messageFormat = new MessageFormat(s);
            String format = messageFormat.format(new String[]{"100002222"});
            System.out.println(format);//输出值(订单号为{100002222}的订单已经支付)
    
    
        }
    
    //稍微封装:
     private String getErrorMessage(String language,String errorCode,String ...params){
            Locale locale=null;
            if(StringUtils.isEmpty(language)){
                locale=new Locale("zh_CN");
            }
    
            locale=new Locale(language);
            ResourceBundle bundle = ResourceBundle.getBundle("i18n/messages",locale);
            String msg = bundle.getString(errorCode);
            if(StringUtils.isEmpty(msg)){
                return null;
            }
            MessageFormat messageFormat = new MessageFormat(msg);
            String format = messageFormat.format(params);
            return format;
    
        }
      @Test
        public void testI18n() throws IOException {
       
          //key=value 103032=Order No.{0} and No.{1} has not been linked
            System.out.println(getErrorMessage("en_US", "103032", "dddd", "vvvvvv"));
    
        }//输出为Order No.dddd and No.vvvvvv has not been linked



    补充:注意下面的区别:下划线和横线用在不同方法,建议使用

    Locale locale = new Locale("en_US");

    Locale locale2 =Locale.forLanguageTag("en-US"); //推荐使用这种方式
     

     //springboot项目中使用国际化,非常简单:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class JestTest {
        @Autowired
        private MessageSource messageSource;
    
        @Test
        public void testI18n() throws IOException {
    
            Locale locale2 = Locale.forLanguageTag("en-US");
    
            Object[] arr = {"dddd", "vvvvvv"};
            //key=value    103032=Order No.{0} and No.{1} has not been linked
            System.out.println(messageSource.getMessage("103032", arr, locale2));
            //输出结果:Order No.dddd and No.vvvvvv has not been linked
    
        }
    
    }
    需要在application.yml中配置:
    messages:
    always-use-message-format: false # Whether to always apply the MessageFormat rules, parsing even messages without arguments.
    basename: i18n/messages # Comma-separated list of basenames (essentially a fully-qualified classpath location), each following the ResourceBundle convention with relaxed support for slash based locations.
    cache-duration: # Loaded resource bundle files cache duration. When not set, bundles are cached forever. If a duration suffix is not specified, seconds will be used.
    encoding: UTF-8 # Message bundles encoding.
    fallback-to-system-locale: true # Whether to fall back to the system Locale if no files for a specific Locale have been found.
    use-code-as-default-message: false # Whether to use the message code as the default message instead of throwing a "NoSuchMessageException". Recommended during development only.
    如果报这个:org.springframework.context.NoSuchMessageException: No message found under code '103032' for locale 'en_us'
    非常有可能是上面的messages在application.yml的位置没配置对,messages要配置在spring的下一级,如图所示:

     

     错误配置如下:

                              

    
    
    
  • 相关阅读:
    L391 弦理论
    L390 Business meeting English
    L389 ABDDC
    L388 Five Ways to Manage Travel Sickness
    L386 DACBD
    Spring 中拦截器与过滤器的区别
    Hibernate中,left join、inner join以及left join fetch区别(转)
    java读取配置文件的几种方法
    Struts1和Struts2的区别和对比(完整版)
    面试题之String str = new String("abc"); 创建了几个对象
  • 原文地址:https://www.cnblogs.com/yangxiaohui227/p/11180640.html
Copyright © 2020-2023  润新知