背景
最近项目要做国际化,所以就简单调研了下国际化的实现,发现Spring Boot
本身就对国际化有支持,所以这里就对Spring Boot
的国际化做了一下简单的调研使用,发现还是挺好用的 这里补充下一个小知识,为什么国际化都叫i18
,因为国际化英文是internationalization
,在 i 和 n 之间有 18 个字母,所以叫i18n
maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
这里Spring Boot版本的2.6.8
创建国际化配置文件
-
messages.properties
user.name=default-name
-
messages_en.properties
user.name=xiaozou
-
messages_zh.properties
user.name=小奏

MessageSource
Spring Boot
负责国际化的核心接口是MessageSource
,我们来看看MessageSource
接口的方法
@Nullable
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
这里提供了getMessage
的三个重载方法,我们介绍下不同参数的作用
-
String code
: 待解析的字符串 -
Object[] args
: 待解析字符串的参数,可以基于 MessageFormat 解析带有 占位符 的字符串 -
String defaultMessage
: 读取不到 国际化 信息时返回的默认值 -
MessageSourceResolvable resolvable
: 函数式接口,对上面参数的封装 -
Locale locale
: 国际化定位
创建Controller测试
@RestController
@RequestMapping
public class TestController {
@Autowired
MessageSource messageSource;
@GetMapping("/international")
public String getInternationalPage() {
return messageSource.getMessage("user.name", null, LocaleContextHolder.getLocale());
}
}
这里我们在application.yaml
设置一下编码格式为UTF-8
防止乱码
spring:
messages:
encoding: UTF-8
这里我们通过设置不同的语言来获取user.name
的值 这里需要注意Spring 默认设置当前语言是通过请求头的Accept-Language
来配置当前的环境 ,然后语言与配置文件去做匹配 比如传入的语言是en
,就会使用messages_en.properties
,我们这里来简单测试一下
-
en -
zh 这里可以看到我们通过不同的
Accept-Language
获取到了不同的语言信息
自定义切换参数
实际我们有时候前端可能会通过自定义个参数传入语言环境,所以我们也可以自定义参数来设置语言环境,比如我们通过param
的lang
值来设置
这里我们需要添加配置
-
WebMvcConfig
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
// 设置默认环境
slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return slr;
}
}
这里我们设置默认的环境为zh
我们再重试试试传入参数
lang = en
试试可以看到成功了
参数校验国际化
我们在使用一些错误提示的使用希望也能够支持国际化,要实现该需求如何处理呢?
-
添加校验依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
-
添加校验国际化配置
@Bean
public Validator getValidator(MessageSource messageSource) {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource);
return bean;
}
注意该Validator
非Spring
的org.springframework.validation.Validator
不支持,不要导错包3. 全局异常处理
-
GlobalExceptionHandler
@RestControllerAdvice
@Configuration(proxyBeanMethods = false)
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(BindException.class)
public String exceptionHandle(Exception e) {
String message = e.getMessage();
return message.substring(message.lastIndexOf("default message") + 15);
}
}
-
编写校验类
@Data
public class User {
@NotEmpty(message = "{email.notempty}")
private String email;
}
注意这里的错误提示是读取我们的国际化配置文件
-
国际化配置添加错误提示key
-
messages_en.properties
email.notempty=Please provide valid email id.
-
messages_zh.properties
email.notempty=邮箱不能为空
-
测试 我们这里还是使用上面的controller改改
@GetMapping("/international")
public String getInternationalPage(@Valid User user) {
return messageSource.getMessage("user.name", null, LocaleContextHolder.getLocale());
}
测试效果
-
en
乱码问题
如果文件乱码需要如下可能需要设置idea file文件编码格式
这里设置为UTF-8
即可
总计
总的来说Spring 对国际化支持还是比较友好的,但是实际线上使用可能还是需要更多的二次开发
参考
-
spring-boot-internationalization
原文始发于微信公众号(小奏技术):国际化(i18)不知道怎么做?来看看利用Spring Boot如何优雅实现
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/29785.html