此文是 【Spring 容器详解】-> 【ApplicationContext 做了哪些企业化的增强?】的支节点。
Spring国际化支持是Spring框架提供的重要功能,允许应用程序根据用户的语言和地区偏好来显示不同的文本内容。这对于开发多语言应用程序至关重要。
0.核心概念 及 整体流程
- 国际化(i18n):Internationalization的缩写,指应用程序能够适应不同语言和地区
- 本地化(L10n):Localization的缩写,指为特定地区定制应用程序
- Locale:表示语言和地区的组合,如zh_CN(简体中文)、en_US(美式英语)

一、完整配置及使用示例
1. Spring Boot配置
java
@Configuration
public class I18nConfig implements WebMvcConfigurer {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(3600);
return messageSource;
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return resolver;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang");
return interceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
2. application.properties配置
properties
# 国际化配置
spring.messages.basename=messages
spring.messages.encoding=UTF-8
spring.messages.cache-duration=3600
spring.messages.fallback-to-system-locale=false
3. 消息文件命名规则
消息文件应按照以下规则命名:
messages.properties
- 默认语言messages_zh_CN.properties
- 简体中文messages_en_US.properties
- 美式英语messages_ja_JP.properties
- 日语
4. 消息文件示例
messages.properties (默认)
properties
welcome.message=Welcome to our application
user.login=Login
user.register=Register
error.notfound=Resource not found
messages_zh_CN.properties (简体中文)
properties
welcome.message=欢迎使用我们的应用程序
user.login=登录
user.register=注册
error.notfound=资源未找到
messages_en_US.properties (美式英语)
properties
welcome.message=Welcome to our application
user.login=Login
user.register=Register
error.notfound=Resource not found
5. 在Controller中使用
java
@RestController
public class UserController {
@Autowired
private MessageSource messageSource;
@GetMapping("/welcome")
public String welcome(Locale locale) {
return messageSource.getMessage("welcome.message", null, locale);
}
@GetMapping("/user/login")
public String login(Locale locale) {
return messageSource.getMessage("user.login", null, locale);
}
@GetMapping("/error/404")
public String notFound(Locale locale) {
return messageSource.getMessage("error.notfound", null, locale);
}
}
6. 在Service中使用
java
@Service
public class UserService {
@Autowired
private MessageSource messageSource;
public String getWelcomeMessage(Locale locale) {
return messageSource.getMessage("welcome.message", null, locale);
}
public String getErrorMessage(String errorCode, Object[] args, Locale locale) {
return messageSource.getMessage(errorCode, args, locale);
}
}
7. 在JSP/Thymeleaf中使用
JSP示例:
jsp
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<title><spring:message code="welcome.title"/></title>
</head>
<body>
<h1><spring:message code="welcome.message"/></h1>
<a href="?lang=zh_CN">中文</a>
<a href="?lang=en_US">English</a>
</body>
</html>
Thymeleaf示例:
html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{welcome.title}">Welcome</title>
</head>
<body>
<h1 th:text="#{welcome.message}">Welcome</h1>
<a href="?lang=zh_CN">中文</a>
<a href="?lang=en_US">English</a>
</body>
</html>
二、配置信息中相关接口解释
1. 定义MessageSource接口获取国际化消息的方法
MessageSource是Spring i18n的核心接口,定义了获取国际化消息的方法:
java
public interface MessageSource {
String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
主要实现类:
ResourceBundleMessageSource
基于Java ResourceBundle的实现,适用于大多数场景:
java
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
ReloadableResourceBundleMessageSource
支持热重载的实现,适用于开发环境:
java
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(3600); // 缓存1小时
return messageSource;
}
2. 使用LocaleResolver解析用户的语言偏好
使用LocaleResolver可以基于不同的方案进行解析,分别是,基于Session、基于Cookie、基于HTTP Accept-Language头。这三种都可以。
SessionLocaleResolver
基于Session的Locale解析器:
java
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return resolver;
}
CookieLocaleResolver
基于Cookie的Locale解析器:
java
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver resolver = new CookieLocaleResolver();
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
resolver.setCookieName("locale");
resolver.setCookieMaxAge(3600 * 24 * 365); // 1年
return resolver;
}
AcceptHeaderLocaleResolver
基于HTTP Accept-Language头的解析器:
java
@Bean
public LocaleResolver localeResolver() {
AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return resolver;
}
3. 配置拦截器LocaleChangeInterceptor用于动态切换语言
java
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang");
return interceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
三、高级特性
1. 参数化消息
消息文件支持参数化:
properties
# messages.properties
greeting.message=Hello {0}, welcome to {1}!
# messages_zh_CN.properties
greeting.message=你好 {0},欢迎来到 {1}!
使用示例:
java
String message = messageSource.getMessage("greeting.message",
new Object[]{"张三", "我们的网站"}, locale);
2. 嵌套消息
支持消息的嵌套引用:
properties
# messages.properties
app.name=My Application
welcome.message=Welcome to {app.name}
# messages_zh_CN.properties
app.name=我的应用程序
welcome.message=欢迎使用 {app.name}
3. 默认消息
当找不到消息时,可以提供默认值:
java
String message = messageSource.getMessage("unknown.key",
null, "默认消息", locale);
4. 单元测试
java
@SpringBootTest
class I18nTest {
@Autowired
private MessageSource messageSource;
@Test
void testChineseMessage() {
String message = messageSource.getMessage("welcome.message",
null, Locale.SIMPLIFIED_CHINESE);
assertEquals("欢迎使用我们的应用程序", message);
}
@Test
void testEnglishMessage() {
String message = messageSource.getMessage("welcome.message",
null, Locale.US);
assertEquals("Welcome to our application", message);
}
}
总结
Spring的国际化支持提供了完整的多语言解决方案,通过合理配置和使用,可以轻松实现应用程序的国际化需求。关键点包括:
- 正确配置MessageSource和LocaleResolver
- 合理组织消息文件
- 在代码中正确使用国际化功能
- 注意性能优化和错误处理
- 遵循最佳实践