Spring Boot 国际化(i18n)实现指南
在当今全球化的互联网时代,开发能够适应不同语言和地区用户的应用程序变得至关重要。Spring Boot 作为一款流行的 Java 开发框架,提供了强大且易于使用的国际化(Internationalization,简称 i18n)支持,帮助开发者轻松构建多语言应用。本文将深入探讨如何在 Spring Boot 项目中实现国际化功能。
一、什么是国际化(i18n)
国际化是指设计和开发应用程序时,使其能够适应不同语言、地区和文化习惯的过程。通过国际化,应用可以根据用户的语言偏好动态切换文本内容,包括界面标签、提示信息、错误消息等,同时还能处理不同地区的日期、时间、数字、货币等格式差异,为全球用户提供一致且友好的体验。例如,一款面向全球用户的电商应用,需要根据用户所在地区显示不同语言的商品描述、价格格式以及促销信息。
二、Spring Boot 国际化实现步骤
(一)创建资源文件
资源文件用于存储不同语言的文本信息。在 Spring Boot 项目中,通常在 src/main/resources
目录下创建一系列以 messages
为基础名,后跟语言代码和区域代码的属性文件。常见的语言代码如 zh
(中文)、en
(英文),区域代码如 CN
(中国)、US
(美国)。
- 默认资源文件:
messages.properties
作为默认资源文件,用于未匹配到特定语言时的兜底显示。例如:
welcome=Welcome to our application
- 特定语言资源文件:
messages_zh_CN.properties
用于中文(中国)环境,内容如下:
welcome=欢迎使用我们的应用
- `messages_en_US.properties` 用于美式英语环境,内容可以和默认文件相同或有所不同,以适应特定地区的语言习惯:
welcome=Welcome to our app
资源文件中的每一行都是一个键值对,键(如 welcome
)用于在代码中引用该文本,值则是对应语言的具体内容。
注意,这里要将项目配置文件的编码方式改成UTF-8,否则会出现乱码
(二)配置 MessageSource
MessageSource
是 Spring 框架中处理国际化消息的核心接口,负责加载和管理资源文件。在 Spring Boot 项目中,有多种方式配置 MessageSource
。
- Java 配置方式:创建一个配置类,例如
I18nConfig.java
:
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
@Configuration
public class I18nConfig {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
// 设置资源文件的基础名称,不包含语言和区域后缀
messageSource.setBasenames("classpath:messages");
// 设置编码格式
messageSource.setDefaultEncoding("UTF-8");
// 设置缓存时间(毫秒),-1 表示不缓存,每次都重新加载
messageSource.setCacheSeconds(-1);
return messageSource;
}
}
这里使用了 ReloadableResourceBundleMessageSource
,它支持从类路径加载资源文件,并且可以配置热重载(通过设置 cacheSeconds
为较短时间或 -1),方便开发过程中修改资源文件后即时生效。
2. application.properties 配置方式:在 application.properties
文件中添加以下配置:
spring.messages.basename=classpath:messages
spring.messages.encoding=UTF-8
spring.messages.cache - seconds=-1
这种方式相对简洁,Spring Boot 会根据这些配置自动创建并配置 MessageSource
。
(三)在代码中使用 MessageSource
- 在控制器中获取国际化消息:通过注入
MessageSource
,调用getMessage
方法获取对应语言的文本。以下是一个简单的控制器示例:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class I18nController {
@Autowired
private MessageSource messageSource;
@GetMapping("/welcome")
public String welcome() {
// 获取当前用户的区域设置
Locale locale = LocaleContextHolder.getLocale();
// 使用国际化
String welcome = messageSource.getMessage("welcome", new Object[]{}, locale);
return welcome;
}
}
在上述代码中,LocaleContextHolder.getLocale()
用于获取当前请求的区域设置,它会根据请求头中的 Accept - Language
字段(由浏览器自动发送)确定用户的语言偏好。messageSource.getMessage
方法根据区域设置查找对应的资源文件,返回相应的文本。如果资源文件中定义了占位符(如 welcome=Welcome to {0}
),可以在第二个参数中传入替换值(这里为空数组 new Object[]{}
)。
2. 在服务层或其他组件中使用:同样可以在服务层或其他需要国际化支持的组件中注入 MessageSource
并使用。例如:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Autowired
private MessageSource messageSource;
public String getInternationalizedMessage(String key) {
Locale locale = LocaleContextHolder.getLocale();
return messageSource.getMessage(key, new Object[]{}, locale);
}
}
这样在业务逻辑中也能方便地获取国际化消息。
(四)在视图中使用国际化信息(以 Thymeleaf 为例)
如果使用 Thymeleaf 作为视图模板引擎,在 HTML 页面中使用国际化非常方便。
- 通过
th:text
属性:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{page.title}">默认标题</title>
</head>
<body>
<h1 th:text="#{welcome('Spring Boot')}">欢迎</h1>
</body>
</html>
th:text="#{...}"
是 Thymeleaf 中引用国际化消息的语法。#{page.title}
会从资源文件中查找 page.title
对应的键值,并根据当前语言环境显示相应文本。#{welcome('Spring Boot')}
中,welcome
是资源文件中的键,('Spring Boot')
是传递给消息的参数,用于替换资源文件中 {0}
这样的占位符。
2. 内联表达式方式:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>[[#{page.title}]]</title>
</head>
<body>
<h1>[[#{welcome('Spring Boot')}]]</h1>
</body>
</html>
[[...]]
是 Thymeleaf 的内联表达式语法,[[#{welcome('Spring Boot')}]]
与 th:text="#{welcome('Spring Boot')}"
功能相同,只是写法更简洁,适用于在标签体内直接嵌入动态内容。
三、高级应用与拓展
(一)动态切换语言
除了根据浏览器请求头中的 Accept - Language
自动切换语言外,还可以提供给用户手动切换语言的功能。
- 通过请求参数切换:在控制器中接收一个表示语言的参数(如
lang
),然后设置当前会话的区域。例如:
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Locale;
@RestController
public class LanguageSwitchController {
@GetMapping("/setLanguage")
public String setLanguage(@RequestParam String lang) {
Locale locale = new Locale(lang);
LocaleContextHolder.setLocale(locale);
return "Language set to " + lang;
}
}
用户访问 http://your - app/setLanguage?lang=zh
即可将语言切换为中文,访问 http://your - app/setLanguage?lang=en
切换为英文。
2. 通过 Cookie 或 Session 切换:实现自定义的 LocaleResolver
,将用户选择的语言存储在 Cookie 或 Session 中,下次访问时自动应用。例如,自定义一个基于 Session 的 LocaleResolver
:
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Locale;
@Configuration
public class CustomLocaleResolverConfig {
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
// 设置默认语言
localeResolver.setDefaultLocale(Locale.US);
return localeResolver;
}
}
然后在控制器中通过修改 SessionLocaleResolver
来切换语言:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
@RestController
public class CustomLanguageSwitchController {
@Autowired
private LocaleResolver localeResolver;
@GetMapping("/customSetLanguage")
public String customSetLanguage(@RequestParam String lang, HttpServletRequest request, HttpServletResponse response) {
Locale locale = new Locale(lang);
localeResolver.setLocale(request, response, locale);
return "Custom Language set to " + lang;
}
}
这种方式更灵活,适合需要长期记住用户语言选择的场景。
(二)处理日期、数字和货币的本地化
Spring 不仅支持文本的国际化,还能处理不同地区的日期、数字和货币格式。
- 日期格式化:通过配置
DateFormat
实现。在配置类中添加如下配置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
@Configuration
public class DateFormatConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
DateFormat dateFormat = new SimpleDateFormat("yyyy - MM - dd");
registry.addFormatterForFieldType(Date.class, new org.springframework.format.datetime.DateFormatter(dateFormat));
}
}
这样在视图中显示 Date
类型数据时,会根据用户的区域设置动态调整日期格式(如中式 “yyyy - MM - dd” 或美式 “MM/dd/yyyy”)。
2. 货币格式化:配置 NumberFormat
来格式化货币金额。例如:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.text.NumberFormat;
import java.util.Currency;
import java.util.Locale;
@Configuration
public class CurrencyFormatConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
currencyFormat.setCurrency(Currency.getInstance(Locale.getDefault()));
registry.addFormatterForFieldType(Double.class, new org.springframework.format.number.NumberFormatter(currencyFormat));
}
}
在显示货币金额时,会根据用户区域自动使用对应货币符号和格式(如¥、$)。
四、总结
通过上述步骤,我们可以在 Spring Boot 项目中轻松实现国际化功能,为全球用户提供多语言支持。从创建资源文件、配置 MessageSource
,到在代码和视图中使用国际化消息,再到实现动态语言切换以及处理日期、数字和货币的本地化,Spring Boot 提供了一套完整且强大的解决方案。在实际开发中,应根据项目需求合理选择和配置这些功能,不断优化用户体验,使应用程序能够更好地适应全球化市场。