SE中的国际化
- java中支持多语言和本地化可以通过
MessageFormat
配合Locale
实现 ```java double price = 123.5;
//{}里的1,2指取参数数组的第?个值 //number指参数为数值型(为123.5保留了2位作用)。currency指是货币单位(为数值增加了$/¥)int number = 10;
Object[] arguments = { price, number };
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
- 其它更多语言……
- 默认语言,文件名必须为
- 多语言时,主Locale文件如果命名为
每个资源文件都有相同的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去找不同资源文件解析