简介
springboot 默认支持了国际化, 自动注入 MessageSource 到容器中, 通过 getMessage 方法可以读取 messages.properties 中的数据.
前置准备
jdk: 1.8
springboot: 2.3.2.RELEASE
简单使用
MessageSource
读取国际化的 bean, springboot 默认已配置,可直接注入使用。
@Resource
private MessageSource messageSource;
资源文件
存放国际化翻译的文件,使用 spring.messages.basename 指定读取的资源文件名,默认值 messages, 通过 _语言标识 来对应不同语言。
下面是测试使用的资源文件:
默认 messages.properties
test=测试
noUser=用户[{0}]不存在。
common=通用
简体中文(中国大陆) messages_zh_CN.properties
test=测试
noUser=用户[{0}]不存在。
繁体中文(中国台湾) messages_zh_TW.properties
test=測試
noUser=用戶[{0}]不存在。
英语(美国) messages_en_US.properties
test=test
noUser=user [{0}] not exists.
使用
无占位符
// 结果: test
messageSource.getMessage("test", null, new Locale("en", "US"));
有占位符
// 结果: 用户[张三]不存在。
messageSource.getMessage("noUser", new Object[]{"张三"}, new Locale("zh", "CN"));
读取默认文件
// 结果: 通用
messageSource.getMessage("common", null, new Locale("en", "US"));
默认值
// 结果: 默认值
messageSource.getMessage("apple", null, "默认值", new Locale("en", "US"));
web环境下使用
web环境下一般是用户自己手动指定的语言环境(下文使用 Locale 代替),我们可以通过用户的请求参数自动来获取 Locale. 省去每次手动选择 Locale 这个步骤
LocaleResolver
LocaleResolver 接口的作用是通过 resolveLocale 方法解析 request 请求获取用户的 Locale、然后存放到 LocaleContextHolder 中,LocaleContextHolder是使用 ThreadLocal 保存 Locale的,所以不同请求之间不会发生冲突。
下面的例子中的 ParamLocaleResolver 是用来通过解析 url 链接上的 lang 字段来作为 Locale, 可以自行扩展,使用 header、cookie 等方式获取
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
@Configuration
public class I18nConfig {
@Bean
public LocaleResolver localeResolver(){
return new ParamLocaleResolver();
}
/**
* 读取请求参数的国际化解析器
*/
private static class ParamLocaleResolver implements LocaleResolver {
/**
* 国际化的请求参数
*/
private static final String PARAM = "lang";
@Override
public Locale resolveLocale(HttpServletRequest request) {
String l = request.getParameter(PARAM);
Locale locale = Locale.getDefault();
if(!StringUtils.isEmpty(l)){
String[] split = l.split("_");
if(split.length != 2){
throw new RuntimeException("语言格式错误");
}
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
}
I18nUtils
国际化工具类,只是用来简化 MessageSource 的操作,用 MessageSource 效果一样。
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Locale;
@Component
public class I18nUtils {
@Resource
private MessageSource messageSource;
/**
* 读取无参, 无默认值的
* @param code
* @return
*/
public String getMessage(String code){
return messageSource.getMessage(code, null, LocaleContextHolder.getLocale());
}
/**
* 读取无参, 无默认值的, 手动指定语言
* @param code
* @return
*/
public String getMessage(String code, Locale locale){
return messageSource.getMessage(code, null, locale);
}
/**
* 读取无参, 有默认值的
* @param code
* @return
*/
public String getMessage(String code, String defaultValue){
return messageSource.getMessage(code, null, defaultValue, LocaleContextHolder.getLocale());
}
/**
* 读取无参, 有默认值的, 手动指定语言
* @param code
* @return
*/
public String getMessage(String code, String defaultValue, Locale locale){
return messageSource.getMessage(code, null, defaultValue, locale);
}
/**
* 读取有参, 无默认值的
* @param code
* @return
*/
public String getMessage(String code, Object[] args){
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
/**
* 读取有参, 无默认值的, 手动指定语言
* @param code
* @return
*/
public String getMessage(String code, Object[] args, Locale locale){
return messageSource.getMessage(code, args, locale);
}
/**
* 读取有参,有默认值的
* @param code
* @return
*/
public String getMessage(String code, Object[] args, String defaultValue){
return messageSource.getMessage(code, args, defaultValue, LocaleContextHolder.getLocale());
}
/**
* 读取有参,有默认值的, 手动指定语言
* @param code
* @return
*/
public String getMessage(String code, Object[] args, String defaultValue, Locale locale){
return messageSource.getMessage(code, args, defaultValue, locale);
}
}
使用
注入工具类
@Resource
private I18nUtils i18nUtils;
无占位符
// 结果: test
i18nUtils.getMessage("test");
有占位符
// 结果: 用户[张三]不存在。
i18nUtils.getMessage("noUser", new Object[]{"张三"});
读取默认文件
// 结果: 通用
i18nUtils.getMessage("common");
默认值
// 结果: 默认值
i18nUtils.getMessage("apple", "默认值");
参考链接
baeldung: https://www.baeldung.com/spring-boot-internationalization