@[TOC]
一、国际化
1、概述
国际化(internationalization)是设计和制造领域适应不同区域要求的产品的一种方式。它要求从产品中抽离所有地域语言,国家/地区和文化相关的元素。换言之,应用程序的功能和代码设计考虑在不同地区运行的需要,其代码简化了不同本地版本的生产。开发这样的程序的过程,就称为国际化。
2、Spring国际化
二、springboot简单使用国际化
1、定义MessageSource
java
/**
* 国际化相关
* @return
*/
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages/message");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
2、定义message配置文件
bash
# message_en.properties
test=meiguo
test2=meiguo{0}
# message_zh.properties
test=中国
3、测试
java
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
String message = applicationContext.getMessage("test", null, new Locale("zh"));
System.out.println(message); // 中国
String message2 = applicationContext.getMessage("test", null, new Locale("en"));
System.out.println(message2); // meiguo
String message3 = applicationContext.getMessage("test2", new String[]{"content"}, new Locale("en"));
System.out.println(message3); // meiguocontent
}
我们发现,按照不同地区,根据配置文件获取到了不同的配置。
三、根据请求的地区获取信息
1、定义message配置文件
bash
# message_en_US.properties
Success={0}success
Test=myTest
# message_zh_CN.properties
Success={0}成message功
Test=我的test内容
2、定义配置类
java
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
@Configuration
public class I18nConfig {
/**
* 国际化相关
*/
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages/message");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
3、基础模板工具
java
import org.springframework.context.NoSuchMessageException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.support.RequestContextUtils;
import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public interface I18nTemplateBase {
String defaultMessage();
String name();
/**
* 解析国际化模板
*/
default String resolve(HttpServletRequest request, Object... args) {
// 先解析参数
List<Object> argResolveList = new ArrayList<>();
if (args != null) {
for (Object arg : args) {
if (arg instanceof I18nTemplateBase) {
I18nTemplateBase i18nTemplateBase = (I18nTemplateBase) arg;
try {
argResolveList.add(resolveTemplate(request, i18nTemplateBase.name()));
} catch (NoSuchMessageException e) {
argResolveList.add(i18nTemplateBase.defaultMessage());
}
}
}
}
// 再解析最终的
String resolveResult;
try {
resolveResult = resolveTemplate(request, name(), argResolveList.toArray());
} catch (NoSuchMessageException e) {
// 拿不到模板用默认模板
resolveResult = MessageFormat.format(defaultMessage(), args);
}
return resolveResult;
}
/**
* 根据key解析国际化模板
*/
default String resolveTemplate(HttpServletRequest request, String code, Object... args) {
Locale locale = RequestContextUtils.getLocale(request);
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
if (context != null) {
return context.getMessage(String.valueOf(code), args, locale);
} else {
throw new NoSuchMessageException("WebApplicationContext not available");
}
}
}
4、消息模板定义枚举
java
/**
* 标准国际化消息模板
*/
public enum I18nTemplate implements I18nTemplateBase {
Success("{0}成功"),
Error("{0}失败"),
Data("{0}"),
// TODO - 定义更多消息模板
Test("测试结果"),
;
private final String defaultMessage;
I18nTemplate(String defaultMessage) {
this.defaultMessage = defaultMessage;
}
public String defaultMessage() {
return defaultMessage;
}
}
5、测试一下
java
@GetMapping("/test1")
public String test1(HttpServletRequest request) {
// 模板定制 + 参数定制
String resolve1 = I18nTemplate.Success.resolve(request, I18nTemplate.Test);
System.out.println(resolve1);
// 模板定制 + 参数手输
String resolve2 = I18nTemplate.Error.resolve(request, "手写的参数");
System.out.println(resolve2);
// 模板参数都手输
String resolve3 = I18nTemplate.Data.resolve(request, "手写的参数");
System.out.println(resolve3);
return "success";
}
bash
请求头:Accept-Language=en-US
结果:
myTestsuccess
手写的参数失败
手写的参数
bash
请求头:Accept-Language=zh-CN
结果:
我的test内容成message功
手写的参数失败
手写的参数
可以实现模板消息、默认消息等。
6、总结
我们可以通过Spring的国际化,将每一个国家的语言模板都定义在配置文件中,这样就可以动态的解决数据返回的语言问题了。
真正生产环境还会将消息再进一步封装,配合httpcode码、返回的数据、请求成功状态、消息等等统一进行封装返回。此处就不进行详细分享了。