栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

后端项目集成i18n国际化多语言支持

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

后端项目集成i18n国际化多语言支持

框架:springboot 2.3.3
项目交付以后本来后端响应的消息统一响应的是code没有附带消息,消息前端通过code进行匹配多种语言,然后前端三哥突然打算让我直接返回对应的语言信息,好吧,只能临时更改了

恰巧前一天琢磨了一下@RestControllerAdvice的用法,今天恰巧排上了用场,在求助了万能的群友后知道了i18n这个包,记录一下,省的以后再用到处找

依赖

    org.webjars.bower
    jquery-i18n-properties
    1.2.7

配置类

有了依赖以后我们创建一个配置类,具体功能在里面解释

@Configuration
public class LocaleConfig {

	
	@Bean
	public SessionLocaleResolver localeResolver() {
		SessionLocaleResolver localeResolver = new SessionLocaleResolver();
		// 这里配置了在没有指定语言的默认情况下匹配的语言种类,你也可以追进去看看每个语言的tag是什么
		// tag就是你语言的代号,下面lang值对应的参数,这是一个全局变量。
		localeResolver.setDefaultLocale(Locale.ENGLISH);
		return localeResolver;
	}

	
	@Bean
	public WebMvcConfigurer localeInterceptor() {
		return new WebMvcConfigurer() {
			@Override
			public void addInterceptors(InterceptorRegistry registry) {
				LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
				// 这里指定一个从前端form-data或者url参数获取语言tag的key值,比如这里是lang
				// 前端就需要传参?lang=zh_CN。zh是语言tag,对应全局变量中的语言,CN是国家代号,这里似乎没用上最好还是设置上吧
				localeInterceptor.setParamName("lang");
				registry.addInterceptor(localeInterceptor);
			}
		};
	}
}
配置语言包


yml配置文件添加内容

spring:
  messages:
    #指定了语言包所在位置
    basename: language.message
    cache-duration: 3600
    encoding: UTF-8

首先创建一个首要语言包message.properties,不需要什么内容,可以为空,后续我们通过拓展包对语种进行归类
然后我们分别创建其他语言的语言包,注意格式message****
语言包内容[同一个语义对应的同一个key]

使用
@GetMapping("/info")
public Result getInfo(){
    User user = new User();
    return new Result<>(true,CodeEnum.SUCCESS.getCode(),
            messageSource.getMessage(
                    "success", // 这里是语言包中properties对应的key值
                    null,// 占位参数,一般不设置
                    LocaleContextHolder.getLocale() // 区域选择,这里选择了当前语言环境,也就是根据前端参数设置的语言
            ),user);
}
解决当前问题

当前情况是我已经全部统一通过Result返回了,并且只返回了code并没有msg,我现在在Result里新增一个成员属性msg

现在我们返回的结果就是

{
	flag:true
	code:20
	msg:null
	data:object
}

我们创建一个接口层增强器@RestControllerAdvice统一处理响应[也可以在拦截器中处理]

@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Autowired
    private ObjectMapper objectMapper; // 用来向前端直接写出Json
    @Autowired
    private MessageSource messageSource;// 语言转换对象
    @Autowired
    private HttpServletResponse response;// 响应对象

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }


    
    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        int status = response.getStatus();
        // 这里为了避免出现失败的时候依然封装为成功
        if (status!=200)
            return Result.fail(status,null);
        if (o instanceof String) {
            // 如果是字符串就以Json写出
            return objectMapper.writevalueAsString(Result.success("成功", o));
        }
        if (o instanceof Result){
            // 如果是结果实体,就调用下面的方法取出code作为key匹配消息进行填充msg
            return languageFormat(o);
        }
        // 如果都不符合证明返回的是其他实体。我们将他封装进data进行响应
        return Result.success("成功", o);
    }

    
   public Object languageFormat(Object o){
       // 由于调用方法前使用了instanceof确定了具体类型,我们这里可以直接强转
       Result result = (Result) o;
       // 强转以后取出code
       String key = result.getCode().toString();
       // 设置msg,用code作为key获取参数
       result.setMsg(messageSource.getMessage(key,null, LocaleContextHolder.getLocale()));
       return result;
   }
}
 

前端请求以及响应


注意这里的param必须和你的配置文件后缀一致

如果不想统一响应可以去除最后的那段,如果加了那个:当匹配不上的时候就包装起来响应,那我们不处理的话就只是检测到是Result就取出code并匹配填入

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号