Spring boot 实现国际化
Spring目前提供了两个MessageSource
的实现:ResourceBundleMessageSource
和StaticMessageSource
。它们都继承NestingMessageSource
以便能够处理嵌套的消息。StaticMessageSource
很少被使用,但能以编程的方式向消息源添加消息。ResourceBundleMessageSource
会用得更多一些,为此提供了一下示例:
1:添加配置类
import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
//WebMvcConfigurerAdapter
@Configuration
public class I18nConfig extends WebMvcConfigurerAdapter {
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return slr;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
2:添加资源文件
默认读取路径在resources下:
可在application.properties中添加属性设置 :
#i18n configuation
spring.messages.basename=i18n/messages
效果如下图:
messages.properties是默认访问资源
3:网页切换语言
于url上拼接属性 如下
?lang=en_US
该属性会存于cookie中,网页跳转将继续使用该语言:
Cookie:JSESSIONID=9EFE46F94D0F89A9E7FBD1073631DEC5; hudson_auto_refresh=false; ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE=d3A3NzE5MTAwMTI6MTQ4MjczNzMxNjkxMjpkZDQ2MzM2NTc3ZmM3ZjU1Y2UzYjk2YWU2NjkwNjlmMjNmMjQwMDhhZmRlOGQxOWQ0YzRjOTM4ZTAwNzYwZmM5; jenkins-timestamper-offset=-28800000; org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=en_US
最后一行即为存于cookie中的 语言属性
4:controller层中语言属性
LocaleContextHolder.getLocale()
可获取Locale类
可用如下代码进行语言判断:
LocaleContextHolder.getLocale().equals(Locale.US)
如有意见 请于评论指出 谢谢~
相关文章:
58. Spring Boot国际化(i18n)【从零开始学Spring Boot】
使用自定义的MessageSource实现对properties的复用
spring通过ResourceBundleMessageSource实现国际化
实现国际化:
一:消息无参
lang_zh.properties内容,name=\u5F20\u4E09
lang_en.properties内容,name=zhangsan
注意:配置文件的命名需要带上语言种类的即:文件名_语言种类.properties,并且不同语言的相同消息的文件名应该一样,例如ang_zh.properties和lang_en.properties就表示中文和英语
语言种类不知道该怎么写的可以在程序中输出,System.out.println(Locale.CHINESE);即可
接着我们就是在spring配置文件中配置:
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>config/properties/lang</value>
</list>
</property>
</bean>
这里需要注意几点:
①在basenames中输入的相对路径
②文件不需要文件类型比如:我的语言文件是lang_zh.properties和lang_en.properties在这里我就只需要输入lang
③大家也看到了,不同语言的文件不需要全部都导入,只需要写文件名即可,看我的配置就知道了
最后就是应用了,
在程序中我们需要得到spring中配置的这个bean,可以通过注入,也可以通过beanUtil获取,我的代码如下:
Java代码
MessageSource ms = (MessageSource) BeanUtil.getBeanByName("configProperties") ;
System.out.println(ms.getMessage("name",new Object[]{} , Locale.CHINESE)); //张三
System.out.println(ms.getMessage("name",new Object[]{} , Locale.ENGLISH)); //zhangsan
在这里的ms.getMessage中有两个三个方法,我只研究了三个参数的和四个参数的getMessage(String arg0, Object[] arg1, Locale arg2) 这里, 第一个参数是文件中的字段名,第二个参数是文件中占位符的参数(后面讲),第三个参数是语言种类,可以通过Locale.种类获取
getMessage(String arg0, Object[] arg1, String arg2, Locale arg3)这里第一个参数是文件中的字段名,第二个参数是文件中占位符的参数(后面讲),第三个参数是默认值,第四个参数是语言种类,可以通过Locale.种类获取
这里需要注意的是,如果没有占位符也可以用null
二:消息中带参数
那么我需要在文件中带入占位符,如我吧语言文件中的内容改为:
lang_zh.properties内容,name=\u5F20\u4E09 {0}
lang_en.properties内容,name=zhangsan{0}
MessageSource ms = (MessageSource) BeanUtil.getBeanByName("configProperties") ;
System.out.println(ms.getMessage("name",new Object[]{} , Locale.CHINESE)); //张三
System.out.println(ms.getMessage("name",new Object[]{"年龄:20"} , Locale.CHINESE)); //张三年龄20
System.out.println(ms.getMessage("name",new Object[]{} , Locale.ENGLISH)); //zhangsan
System.out.println(ms.getMessage("name",new Object[]{"age:20"} , Locale.ENGLISH)); //zhangsanage20
如果你的文件中的消息有占位符,同时又有单引号就需要注意了,有占位符的时候,单引号需要转义,只需要在单引号前再加一个单引号就可以了,
例如:
name='dengwei'{0}
我就需要写成:name=''dengwei‘’{0}记得是两个单引号,而不是双引号
更多信息:占位符和信息格式化:
实现品牌内容:
而在我们的项目中有这样一个需求。假设现在项目中有三个properties文件。
其中aami和apia是我们项目需要支持的两个品牌。当一个用户登陆我们的web项目时,会自动将其当前所使用的品牌信息存到session中。而如果是aami用户的话,前端jsp页面显示的message读取的顺序是这样的:如果在aami.properties文件中没找到的话,就在default.properties文件中找。对于apia用户,则先在apia.properties中找,然后查找default.properties。
举个例子,如果default.properties中有一个键值对helloWorld.label = Welcome
。那么在jsp上使用时会显示Welcome。但是对于ammi来说需要用同样的键hello.world.label
但是显示Welcome to AAMI
。
这样可以最大程度的复用default.properties中的数据,同时又可以根据自身品牌定义一些自身的数据在自身品牌的properties文件中。
ResourceBundleMessageSource中有一个parentMessageSource
属性,如果在当前MessageSource中找不到code的值,会在parentMessageSource
中查找。一个简单的配置如下。
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="parentMessageSource">
<bean class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>default</value>
</property>
</bean>
</property>
<property name="basenames">
<list>
<value>aami</value>
</list>
</property>
</bean>
如果给给定一个code,程序会先在aami.properties文件中查找,如果未找到,则会在default中查找。 这似乎能满足我们的要求。其实不行。假如我们现在将apia品牌也加入,如果想让程序根据当前用户的品牌来选择适合的properties做成首选,当前这个功能是不满足的。我们需要自定义一个继承自ResourceBundleMessageSource
的类来实现。