我不生产代码
我只是代码的搬运工

springboot配置国际化支持多语言

1. 默认国际化实现

1.1 添加多语言文件

spring boot 默认实现了国际化多语言配置,打开文件  org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration 可以看到,默认的多语言文件放到目录 messages 中,可以通过配置 spring.messages.basename 修改多语言文件存放目录,修改默认配置:

spring:
  messages:
    basename: i18n.messages

    新建多语言配置文件放到目录 resources/i18n 中:

messages.properties(默认的多语言文件)
messages_zh_CN.properties(中文语言文件)
messages_en_US.properties(英文语言文件)

    messages.propertiesmessages_zh_CN.properties 中添加如下内容:

login.name=登录

   messages_en_US.properties 中添加如下内容:

login.name=Login

 1.2 添加控制器

package com.sviping.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @Autowired
    MessageSource messageSource;

    @RequestMapping("/test")
    public String test(){
        String message = null;
        try {
            message = messageSource.getMessage("login.name", null, LocaleContextHolder.getLocale());
        } catch (NoSuchMessageException e) {
            message = "";
            System.out.println(e.getMessage());
        }
        return message;
    }
}

1.3 测试

浏览器中访问地址 localhost:8080/test 可以看到会返回 登录,修改浏览器的默认语言为英文后,刷新浏览器,会返回 Login,此时配置的默认国际会多语言完成。

2. 自定义国际化实现

上面 spring boot 默认的多语言不够灵活,不能方便的切换语言。通过查看类 org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver 可以发现,spring boot 是根据 header 中 Accept-Language 来切换不同的语言,并且该类型实现了接口 org.springframework.web.servlet.LocaleResolver,所以我们要自己实现多语言切换,也需要实现该接口。这里通过采用类似 AcceptHeaderLocaleResolver 要用不同 Accept-Language 来切换不同语言。 

2.1 自定义拦截器

通过添加 url 参数来灵活的修改 Accept-Language ,spring boot 中类 org.springframework.web.servlet.i18n.LocaleChangeInterceptor 已经实现了此功能。该类会将接收到的参数放到 cookie 中, cookie 默认名字为 locale ,同时会添加名为 CookieLocaleResolver.class.getName() + ".LOCALE"request 属性,值为 url 参数生成的 Locale 对象,所以我们只需求添加一个拦截器调用即可。

2.2 修改多语言默认实现

文件 org.springframework.boot.autoconfigure.web.servle.WebMvcAutoConfiguration 中方法 localeResolver 为默认多语言的默认实现方式

@Override
@Bean
@ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME)
public LocaleResolver localeResolver() {
	if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
		return new FixedLocaleResolver(this.webProperties.getLocale());
	}
	AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
	localeResolver.setDefaultLocale(this.webProperties.getLocale());
	return localeResolver;
}

通过注解 ConditionalOnMissingBean 可以发现,当 DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME  bean 不存在,即 localeResolver bean 不存在,该方法才生效,所以只需要添加 localeResolver bean 就可以自己实现多语言。为了能够实现不用每次都添加 url 参数,所以可以将 url 参数的值保存在 cookie 中,当没有 url 参数时,从 cookie 中取值即可,spring boot 已经通过类 org.springframework.web.servlet.i18n.CookieLocaleResolver 实现了此功能 ,并且该类实现了 org.springframework.web.servlet.LocaleResolver 接口,所以我们只需要添加 localeResolver bean 并实例化 CookieLocaleResolver 即可。 CookieLocaleResolver  通过下面两种方式获取 Locale 对象:

  1. 从  request 对象的 CookieLocaleResolver.class.getName() + ".LOCALE" 属性获取,此种方式对应有 url 参数的请求

  2. 从名为 locale(默认值) 的 cookie 中获取,此种方式对应没有 url 参数的请求

2.3 完整代码

新建类 MyMvcConfig 并实现接口 WebMvcConfigurer

package com.sviping.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Bean
    public LocaleResolver localeResolver(){
        CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
        cookieLocaleResolver.setCookieName("locale");//LocaleChangeInterceptor 默认会获取url参数 locale
        return cookieLocaleResolver;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //多语言
        registry.addInterceptor(new LocaleChangeInterceptor()).addPathPatterns("/**");
    }
}

2.4 测试

在浏览器中输入 localhost:8080/test?locale=en_US 后,即可切换成英文,去掉 locale 参数后,仍为英文,将参数的值改为 zh_CN 后,返回结果变为中文,到此,实现了多语言的自定义切换。

本文章为本站原创,如转载请注明文章出处:https://www.sviping.com/archives/46

分享到:
上一篇: Springboot 2.6.3 整合 Swagger3 下一篇: springboot 用FastJson2 替代默认的 jackjson
12