SpringBoot thymeleaf 多语言显示
在日常开发中,如果涉及到网站需要多语言显示的话,那么利用Spring Boot要怎么做呢?又涉及到了哪些内容呢,下面是我开发中用的的一些记录。仅供参考。
我这边需要的语言有,假定需要的语言有:中文zh,英文en
使用到的主要技术有:SpringBoot,Thymeleaf,
关键的类:CookieLocaleResolver,LocaleChangeInterceptor,WebMvcConfigurerAdapter的addInterceptors
另外很多内容都是参照: http://412887952-qq-com.iteye.com/blog/2312274
这个关于SpringBoot讲解的很全面了。
1、首先我们先定义国际化资源文件,spring boot默认就支持国际化的,而且不需要你过多的做什么配置,只需要在resources/下定义国际化配置文件即可
如果想修改文件的位置,可以在application.properties中定义
spring.messages.basename=message/messages
那么messages_en.properties,messages_zh.properties 就可以放到resources/message文件夹下了
上面链接的博客中是使用
@Configuration public class WebConfiguration extends WebMvcConfigurerAdapter { @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("message/messages"); messageSource.setDefaultEncoding("UTF-8"); return messageSource; } }
@Autowired protected MessageSource messageSource; String msg = messageSource.getMessage("welcome", null,locale);
这种形式,然后put到前台,但是这种如果前台全是静态的页面,都通过put形式未免太麻烦了。有没有什么其他方式呢?
thymeleaf支持#{welcome}形式读取message信息。
那么就可以使用LocaleChangeInterceptor 拦截器,来拦截语言的变化,然后CookieLocaleResolver设置cookie,前段也自然就跟着变化了。
@Configuration public class WebConfiguration extends WebMvcConfigurerAdapter { @Bean public LocaleChangeInterceptor localeChangeInterceptor() { LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); lci.setParamName("lang"); return lci; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(localeChangeInterceptor()); } }
这样,就可以捕获浏览器地址栏lang参数的变化了
http://localhost:8080/index?lang=zh
http://localhost:8080/index?lang=en
通过查看拦截器的源码可以看到:
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException { String newLocale = request.getParameter(getParamName()); if (newLocale != null) { if (checkHttpMethod(request.getMethod())) { LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); if (localeResolver == null) { throw new IllegalStateException( "No LocaleResolver found: not in a DispatcherServlet request?"); } try { localeResolver.setLocale(request, response, parseLocaleValue(newLocale)); } catch (IllegalArgumentException ex) { if (isIgnoreInvalidLocale()) { logger.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage()); } else { throw ex; } } } } // Proceed in any case. return true; }
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); 这句如果没有特意指定localeResolver 的话,在执行过程中会报错:
java.lang.UnsupportedOperationException:
Cannot change HTTP accept header - use a different locale resolution strategy
...AcceptHeaderLocaleResolver.setLocale(AcceptHeaderLocaleResolver.java:45)
原因是:
In Spring MVC application, if you do not configure the Spring’s LocaleResolver, it will use the default AcceptHeaderLocaleResolver, which does not allow to change the locale. To solve it, try declare a SessionLocaleResolver bean in the Spring bean configuration file, it should be suits in most cases.
<beans ...
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
</list>
</property>
</bean>
</beans>
咱们使用的是SpringBoot,所以可以通过注解@Bean的形式注入一个localeResolver
@Configuration public class WebConfiguration extends WebMvcConfigurerAdapter { @Bean public LocaleChangeInterceptor localeChangeInterceptor() { LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); lci.setParamName("lang"); return lci; } @Bean public LocaleResolver localeResolver() { CookieLocaleResolver cl = new CookieLocaleResolver(); cl.setCookieName("language"); return cl; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(localeChangeInterceptor()); } }
此处用的是Cookie记录,所以注入Cookie,当然也可以Session什么的,自己随意。
通过以上,就可以通过在浏览器lang的切换,然后页面显示不同配置的语言了。
但是现在开发中语言设置一般遵循restful的风格,即访问地址为:
http://localhost:8080/en/
http://localhost:8080/zh/
这种形式,这样LocaleChangeInterceptorgetParameter就获取不到lang了。
所以就需要自己重新写一个拦截器,只需要继承LocaleChangeInterceptor,然后覆写preHandle即可。
@Component public class LanguageInterceptor extends LocaleChangeInterceptor { @Autowired private LocaleResolver localeResolver; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException { //获取 @pathvariable 的参数 /{lang} Map map = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); String lang = MapUtils.getString(map, "lang", ""); Locale l = new Locale(lang); localeResolver.setLocale(request, response, l); } }
只要在localeResolver中设置了Locale,那么就是按照Locale的语言进行显示了。
然后修改addInterceptors
@Configuration public class WebConfiguration extends WebMvcConfigurerAdapter { @Autowired private LanguageInterceptor languageInterceptor; @Bean public LocaleResolver localeResolver() { CookieLocaleResolver cl = new CookieLocaleResolver(); cl.setCookieName("language"); return cl; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(languageInterceptor); } }
推荐阅读
-
三、SpringBoot整合Thymeleaf视图
-
springboot+mybatis日志显示SQL的最简单方法
-
SpringBoot+SpringSecurity+Thymeleaf认证失败返回错误信息踩坑记录
-
springboot~thymeleaf页面布局的步骤
-
【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限
-
Thymeleaf+SpringBoot+SpringDataJPA实现的中小医院信息管理系统
-
SpringBoot 之Thymeleaf模板.
-
springboot2 设置输入ip或者localhost+端口号显示首页
-
SpringBoot整合Thymeleaf快速入门(附详细教程)
-
springboot+thymeleaf前后端联调笔记