这几年,上司重视的产品和系统,不知道是否注意到了国际化已经成为标准装备。 最让我生气的是,项目刚开始的时候,大家都没有说。 到了向上司做简报的时候,或者突然来了。 上司说:“本公司的目标是进军全世界。 今后我们所有的系统都必须支持两种语言和三种语言等”,程序员又开启了心中MMB的加班模式。 但是,国际化实际上听起来很大,并不像大家想象的那样复杂。 然后,根据properties配置文件,查看无需对原始代码进行过多更改的方法,从而实现上司的国际化Dream。
01什么是国际化
可以手动或自动根据语言环境的变化更改页面内容和提示信息。 目前市场上出现的是页面上有语言切换图标(不是谷歌浏览器的翻译功能)。 另外,大部分系统主要实现页面上静态数据的国际化(如菜单、提示、标签等),没有动态数据和业务数据。 由于很多业务系统都是私有化引进,通过数据隔离可以避免中英文的混乱
02国际化三部曲
语言的保存和切换
获取国际化数据
批量处理结果
03具体实现
语言的保存和切换
首先实现本地解析器和本地交换中心
@Slf4j
@Configuration
公共级i18配置单元swebmvcconfigurer {
@Bean
publiclocaleresolverlocaleresolver {
cookielocaleresolverlocaleresolver=newcookielocaleresolver (;
本地解决方案. set默认本地(本地.中国);
返回本地解析器;
}
@Bean
publiclocalechangeinterceptorlocalechangeinterceptor {
localechangeinterceptorlocalechangeinterceptor=newlocalechangeinterceptor (;
localechangeinterceptor.set param名称(' lang );
返回本地交换中心;
}
@Override
公共卫生中心(互联存储器) {
registry.add介面卡(本机交换介面卡();
}
}
LocaleResolver用于存储语言,此处将语言信息存储在Cookie中,因此使用现成的实现CookieLocaleResolver,如果需要将语言存储在会话中,则使用SessionLocaleResolver
LocaleChangeInterceptor是切换语言的中心。 如果请求中有lang参数,语言将根据其值切换。 通过实现WebMvcConfigurer的addInterceptors方法,将拦截器放入拦截器链中
实现后,我们在测试下:
@ rest控制器
@ request映射(/语言) ) ) )。
publicclasslanguagecontrollerextendsbasecontroller {
@ API操作(“切换语言”
@ post mapping (/变更) ) )。
publicapiresultstringchangelanguage @请求参数(名称=' lang ' ) API参数)名称=' lang ',值='语言',请求参数
由于已通过LocaleChangeInterceptor进行切换,因此无需在此处进行处理
返回获取语言(;
}
@ApiOperation ('取得现在的语言) ) ) ) ) ) ) ) ) ) ) ) ) )。
@获取映射
publicapiresultstringgetlanguage (
locale locale=localecontextholder.get locale (;
>return ApiResult.success(locale.toString());
}
}
调用切换语言的接口:curl -X POST "http://localhost:8080/language/change?lang=en_US"
可以在Cookie中看到语言信息:
调用获得当前语言接口:curl -X GET "http://localhost:8080/language" -H "accept: */*"
可以获取返回结果:
{
"code": 200,
"data": "en_US",
"message": "成功"
}
②获取国际化数据
要想获取国际化数据,首先需要添加国际化文件。默认的文件名为messages*.properties,也可以通过配置spring.messages.basename=messages修改文件名,存放的文件路径为:/resources/i18n/,如下:
在文件中以键值对的形式存储数据
✬默认数据:messages.properties
success=API调用成功
fail=API调用失败
✬英文数据:messages_en_US.properties
success=success
fail=fail
✬中文数据:messages_en_US.properties
success=API调用成功
fail=API调用失败
国际化数据有了,语言有了,那如何获取到当前语言的数据?这里使用ResourceBundleMessageSource来解析国际化文件,如下:
@Slf4j
@Configuration
public class I18nConfig{
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("i18n/messages");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
需要获取数据时,直接注入进行使用:
@RestController
@RequestMapping("/message")
public class MessageController {
@Autowired
private MessageSource messageSource;
@ApiOperation("成功")
@GetMapping("/success")
public ApiResult<String> success() {
// 获取当前语言
Locale locale = LocaleContextHolder.getLocale();
// 根据Code值和语言,获取国际化数据
String message = messageSource.getMessage(ResultCode.SUCCESS.getMessage(), null, locale);
return new ApiResult<>(ResultCode.SUCCESS.getCode(), null, message);
}
@ApiOperation("失败")
@GetMapping("/fail")
public ApiResult<String> failure() {
Locale locale = LocaleContextHolder.getLocale();
String message = messageSource.getMessage(ResultCode.FAIL.getMessage(), null, locale);
return new ApiResult<>(ResultCode.SUCCESS.getCode(), null, message);
}
}
➯LocaleContextHolder.getLocale(); 获取当前语言
➯messageSource.getMessage(); 获取国际化数据
这里用到ResultCode:
@Getter
@AllArgsConstructor
public enum ResultCode {
SUCCESS(200, "success"),
FAIL(500, "fail");
private Integer code;
private String message;
}
③统一处理返回结果
通过注解@ControllerAdvice和实现ResponseBodyAdvice接口, 数据返回前都调用beforeBodyWrite方法,在这里我们将code值转换成国际化数据如下:
@ControllerAdvice
public class ApiResultAdvice implements ResponseBodyAdvice<ApiResult> {
@Autowired
private MessageSource messageSource;
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return returnType.getParameterType().isAssignableFrom(ApiResult.class);
}
@Override
public ApiResult beforeBodyWrite(ApiResult body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
Locale locale = LocaleContextHolder.getLocale();
String message = messageSource.getMessage(body.getMessage(), null, locale);
body.setMessage(message);
return body;
}
}
在这里统一处理之后,就不需要在Controller进行处理
调用切换语言的接口:curl -X POST "http://localhost:8080/language/change?lang=en_US"
返回结果如下:
{
"code": 200,
"data": "en_US",
"message": "success"
}
以上我们就实现了国际化,并且不需要对以前的代码进行多大的改动,只需要将原来的提示信息等数据换成Code值,然后将Code值在国际化文件里配置即可,是不是炒鸡easy
花有重开日,人无再少年 → 我是花少#更新不断,下期继续#走过路过记得留下关注和点赞!!!