在resources文件下新建i18n文件,并新建国际化资源文件。如图:
点击新增Resource Bundle文件。
我们在Resource bundle base name处填写国际化文件的名称,笔者此处填“messages”。并点击中间偏右的“+”号,新增国际化语言,此处新增两个语言“zh_CN”,“en_US”。
点击ok保存,看到这样的文件结构,就表示创建成功了:
分别在两个文件中添加
zh_CN:
A00001=你好,世界
A00002=你好,JAVA
en_US:
A00001=Hello World
A00002=Hello JAVA
spring:
messages:
basename: i18n/messages
注意:此处的basename填的messages是填Resource bundle base name时填的值。
MyLocaleResolver:
/**
* @Description: 自定义LocaleResolver
* @author Felix.Du
* @Date: 2022/3/30 21:25
*/
@Configuration
public class MyLocaleResolver implements LocaleResolver {
@Autowired
private HttpServletRequest request;
public Locale getLocal() {
return resolveLocale(request);
}
/**
* 从HttpServletRequest中获取Locale
*
* @param httpServletRequest httpServletRequest
* @return 语言Local
*/
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
//获取请求中的语言参数
String language = httpServletRequest.getParameter("lang");
//如果没有就使用默认的(根据主机的语言环境生成一个 Locale
Locale locale = Locale.getDefault();
//如果请求的链接中携带了 国际化的参数
if (!StringUtils.isEmpty(language)){
//zh_CN
String[] s = language.split(Constant.CONNECTOR);
//国家,地区
locale = new Locale(s[0], s[1]);
}
return locale;
}
/**
* 用于实现Locale的切换。比如SessionLocaleResolver获取Locale的方式是从session中读取,但如果
* 用户想要切换其展示的样式(由英文切换为中文),那么这里的setLocale()方法就提供了这样一种可能
*
* @param request HttpServletRequest
* @param httpServletResponse HttpServletResponse
* @param locale locale
*/
@Override
public void setLocale(@NonNull HttpServletRequest request, @Nullable HttpServletResponse httpServletResponse, @Nullable Locale locale) {
}
}
添加i18n工具类,I18nUtil:
@Slf4j
@Component
public class I18nUtil {
@Value("${spring.messages.basename}")
private String basename;
private final MyLocaleResolver resolver;
private static MyLocaleResolver customLocaleResolver;
private static String path;
public I18nUtil(MyLocaleResolver resolver) {
this.resolver = resolver;
}
@PostConstruct
public void init() {
setBasename(basename);
setCustomLocaleResolver(resolver);
}
/**
* 获取 国际化后内容信息
*
* @param code 国际化key
* @return 国际化后内容信息
*/
public static String getMessage(String code) {
Locale locale = customLocaleResolver.getLocal();
return getMessage(code, null, code, locale);
}
/**
* 获取指定语言中的国际化信息,如果没有则走英文
*
* @param code 国际化 key
* @param lang 语言参数
* @return 国际化后内容信息
*/
public static String getMessage(String code, String lang) {
Locale locale;
if (StringUtils.isEmpty(lang)) {
locale = Locale.US;
} else {
try {
var split = lang.split("-");
locale = new Locale(split[0], split[1]);
} catch (Exception e) {
locale = Locale.US;
}
}
return getMessage(code, null, code, locale);
}
/**
* 获取站内信指定语言 目前只支持 中文与英文两类 默认英文
*
* @param code 国际化 key
* @param lang 语言参数
* @return 国际化后内容信息
*/
public static String getStationLetterMessage(String code, String lang) {
Locale locale = Objects.equals(lang, I18nConstant.ZH_CN) ? Locale.SIMPLIFIED_CHINESE : Locale.US;
return getMessage(code, null, code, locale);
}
public static String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.toString());
messageSource.setBasename(path);
String content;
try {
content = messageSource.getMessage(code, args, locale);
} catch (Exception e) {
log.error("国际化参数获取失败===>{},{}", e.getMessage(), e);
content = defaultMessage;
}
return content;
}
public static void setBasename(String basename) {
I18nUtil.path = basename;
}
public static void setCustomLocaleResolver(MyLocaleResolver resolver) {
I18nUtil.customLocaleResolver = resolver;
}
}
FirstUserController:
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@Slf4j
public class FirstUserController {
private final HttpServletRequest request;
@GetMapping("/i18n")
public String i18n() {
String message1 = I18nUtil.getMessage("A00001", request.getHeader("lang"));
String message2 = I18nUtil.getMessage("A00002", request.getHeader("lang"));
return message1 + message2;
}
}
因为此处截取的是请求头的lang参数,那么我们在请求的时候添加一个lang参数。
注意:此处lang传的值是zh-CN、en-US并非zh_CN、en_US,因为在MyLocaleResolver中解析参数是通过分隔符“-”解析的,而并不是“”。当然你也可以传zh_CN、en_US,只需要在MyLocaleResolver类的resolveLocale方法将解析符号换为“”即可。