SE中的国际化

  • java中支持多语言和本地化可以通过MessageFormat配合Locale实现 ```java double price = 123.5;
    1. int number = 10;
    2. Object[] arguments = { price, number };
    //{}里的1,2指取参数数组的第?个值 //number指参数为数值型(为123.5保留了2位作用)。currency指是货币单位(为数值增加了$/¥)
      MessageFormat mfUS = new MessageFormat("Pay {0,number,currency} for {1} books.", Locale.US);
      System.out.println(mfUS.format(arguments));
      MessageFormat mfZH = new MessageFormat("{1}本书一共{0,number,currency}。", Locale.CHINA);
      System.out.println(mfZH.format(arguments));
    

//结果 Pay $123.50 for 10 books. 10本书一共¥123.50。

<a name="gKb4E"></a>
# Web中的国际化

- 实现国际化的步骤:
   - 首先拿到地区
   - 获取语言资源文件
<a name="hWJKj"></a>
## 获取用户的地区(Locale)

- locale是表示一个国家或地区的日期、时间、数字、货币等格式。意为**本地化**。Locale由语言_国家的字母缩写构成,例如,zh_CN表示中文+中国,en_US表示英文+美国。语言使用小写,国家使用大写。
   - 别跟时区搞混了,时区只是时间值转换计算的,有时也用于时间格式

1. HTTP规范规定了浏览器会在请求中携带`Accept-Language`头,用来指示用户浏览器设定的语言顺序.如`Accept-Language: zh-CN,zh;q=0.8,en;q=0.2`  
   1. 这里表示优先简体中文,其次中文,最后英文。q表示权重,即优先级。**mvc框架通过解析这个头部获得Locale,大多数框架解析只返回权重最高的框架**
   1. Spring MVC通过`LocaleResolver`来自动从`HttpServletRequest`中获取`Locale`。有多种`LocaleResolver`的实现类,其中最常用的是`CookieLocaleResolver`
      1. `CookieLocaleResolver`获取`Locale`的规则是:**首先从**`**HttpServletRequest**`**中找一个特定的Cookie(用户选择语言时就增加该Cookie),如果没有,就从HTTP头获取;如果还没有,就返回默认的Locale。**    
      1. **当用户第一次访问网站时,CookieLocaleResolver只能从HTTP头获取Locale,即使用浏览器的默认语言(**LocaleResolver**也可以配置默认地区,**LocaleResolver**的默认>前端)。通常网站也允许用户自己选择语言,此时,CookieLocaleResolver就会把用户选择的语言存放到Cookie中,下一次访问时,就会读取cookie中用户选择的locale**
```java
  @Bean
    CookieLocaleResolver createLocaleResolver() {
       CookieLocaleResolver clr = new CookieLocaleResolver();
        clr.setDefaultLocale(Locale.ENGLISH);   //设置默认地区
        clr.setDefaultTimeZone(TimeZone.getDefault()); //设置默认时区
        clr.setCookieName("language");   //设置存储locale地区数据的cookie名称
        clr.setCookieMaxAge(3600);   //单位为秒,设置cookie的时效
        return clr;
    }

Locale资源文件创建

  • web中国际化不再是跟se中一样在代码里使用不同locale去渲染模板字符串,而是将locale资源存储到外部。
    • 多语言时,主Locale文件如果命名为messages,那么资源文件必须按如下方式命名并放入classpath中
    • locale资源文件命名有固定规则:基准名称+后面再接下划线、语言码,还可以选择加一条下划线和国家码如下面
      • 默认语言,文件名必须为messages.properties
      • 简体中文,Locale是zh_CN,文件名必须为messages_zh_CN.properties
      • 日文,Locale是ja_JP,文件名必须为messages_ja_JP.properties
      • 其它更多语言……
  • 每个资源文件都有相同的Key(即要渲染的内容),如下面2个文件,language.select,home等就是他们相同的键,web根据不同locale,相同的键去不同的资源文件里找渲染值

    language.select=Language
    home=Home
    signin=Sign In
    copyright=Copyright©{0,number,#}
    
    language.select=语言
    home=首页
    signin=登录
    copyright=版权所有©{0,number,#}
    

    创建MessageSource

  • MessageSource是spring提供的一个国际化帮助的实例。它自动读取所有的.properties文件,并提供一个统一接口来实现“翻译”:

    @Bean("i18n")  //国际化的英文缩写为i18n
    MessageSource createMessageSource() {
      var messageSource = new ResourceBundleMessageSource();
      // 指定文件是UTF-8编码:
      messageSource.setDefaultEncoding("UTF-8");
      // 指定主资源文件名:
      messageSource.setBasename("messages");
      return messageSource;
    }
    
    //传入要渲染的键值,Object[]参数,loacle
    String text = messageSource.getMessage("signin", null, locale);
    

    实现多语言

  • 廖雪峰那个多语言是themlef版本的,个人感觉其实掌握了过滤器/拦截器和MessageSource,LocaleResolver后,自己实现多语言国际化也很简单,无非就是读取到Locale后通过MessageSource获取不同内容

    spring boot中的国际化

  • springboot中就是简化了下配置。我们可以直接使用配置文件配置替代bean配置,springboot自动配置一个默认的MessageSource并寻找配置的资源路径下的资源文件

    配置

    pring.messages.basename=i18n.xx   #配置路径与资源文件名,如i18n是存放locale资源的目录,文件名是xx.properties,xx_zh_CN.properties,xx_....properties
    

    其他

    其他的就没什么好讲的,也都是一个道理,根据得到的locale去找不同资源文件解析