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);
    }
}

 

 

猜你喜欢

转载自slnddd.iteye.com/blog/2346933