Spring Boot :國際化實戰(zhàn),一鍵切換多語言
前言
在企業(yè)級應(yīng)用開發(fā)中,多語言支持(國際化/Internationalization,簡稱i18n)是提升產(chǎn)品全球化競爭力的關(guān)鍵功能。
核心原理:Spring 國際化組件鏈
Spring Boot內(nèi)置了完整的國際化支持,核心依賴三個組件的協(xié)同工作:
MessageSource:消息源組件,負(fù)責(zé)加載不同語言的資源文件(如中文.properties、英文.properties)LocaleResolver:語言環(huán)境解析器,用于存儲用戶當(dāng)前選擇的語言(如Session存儲、Cookie存儲)LocaleChangeInterceptor:語言切換攔截器,攔截請求中的語言參數(shù)(如?lang=en_US),動態(tài)切換Locale
整個流程可概括為:
用戶請求(帶lang參數(shù))→ 攔截器解析語言 → 解析器存儲Locale → 消息源按Locale返回文本實現(xiàn)
Step 1:準(zhǔn)備國際化資源文件
中文配置(messages_zh_CN.properties)
# 系統(tǒng)提示(sys模塊)
sys.welcome=歡迎使用XX管理系統(tǒng)
sys.login.success=登錄成功,3秒后跳轉(zhuǎn)首頁
sys.login.fail=賬號或密碼錯誤,請重新輸入
# 按鈕文本(btn模塊)
btn.submit=提交
btn.cancel=取消
btn.reset=重置
# 表單提示(form模塊)
form.username=用戶名
form.password=密碼
form.remember=記住我英文配置(messages_en_US.properties)
# System tips (sys module)
sys.welcome=Welcome to XX Management System
sys.login.success=Login successful, redirecting to homepage in 3 seconds
sys.login.fail=Invalid username or password, please try again
# Button text (btn module)
btn.submit=Submit
btn.cancel=Cancel
btn.reset=Reset
# Form tips (form module)
form.username=Username
form.password=Password
form.remember=Remember Me默認(rèn)配置(messages.properties)
# 默認(rèn)語言:中文
sys.welcome=歡迎使用XX管理系統(tǒng)
sys.login.success=登錄成功,3秒后跳轉(zhuǎn)首頁
# 其余key與messages_zh_CN.properties一致Step 2:配置 Spring 國際化組件
配置 LocaleResolver 與攔截器
@Configuration
public class I18nConfig implements WebMvcConfigurer {
/**
* 1. 配置LocaleResolver:存儲用戶語言環(huán)境
* 選擇SessionLocaleResolver(基于Session存儲),適合后端渲染場景
* 若為前后端分離,可改用CookieLocaleResolver(基于Cookie存儲)
*/
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver resolver = new SessionLocaleResolver();
// 設(shè)置默認(rèn)語言為中文(Locale.SIMPLIFIED_CHINESE對應(yīng)zh_CN)
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return resolver;
}
/**
* 2. 配置LocaleChangeInterceptor:攔截語言切換請求
* 指定語言參數(shù)名為"lang",前端通過?lang=zh_CN或?lang=en_US切換語言
*/
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang"); // 語言參數(shù)名,可自定義(如"language")
return interceptor;
}
/**
* 3. 注冊攔截器:讓攔截器生效
* 若需排除某些路徑(如靜態(tài)資源),可通過addPathPatterns和excludePathPatterns配置
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor())
.addPathPatterns("/**") // 攔截所有請求
.excludePathPatterns("/static/**", "/favicon.ico"); // 排除靜態(tài)資源
}
}配置 MessageSource(解決亂碼 + 指定資源路徑)
spring:
# 國際化消息源配置
messages:
basename: i18n/messages # 資源文件基礎(chǔ)路徑(classpath:i18n/下的messages前綴文件)
encoding: UTF-8 # 編碼格式,解決中文亂碼
use-code-as-default-message: true # 找不到消息時,用key作為默認(rèn)值(避免報錯)
cache-duration: 3600s # 資源文件緩存時間(生產(chǎn)環(huán)境建議設(shè)置,開發(fā)環(huán)境可設(shè)為0禁用緩存)可選:配置 CookieLocaleResolver(前后端分離場景)
若項目為前后端分離(前端用Vue/React,后端提供API),SessionLocaleResolver會因跨域?qū)е?/span>Locale丟失,此時需改用CookieLocaleResolver:
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver resolver = new CookieLocaleResolver();
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
resolver.setCookieName("language"); // Cookie名稱,前端可讀取該Cookie判斷當(dāng)前語言
resolver.setCookieMaxAge(30 * 24 * 60 * 60); // Cookie有效期:30天
return resolver;
}Step 3:替換硬編碼文本(核心改動)
@RestController
@RequestMapping("/api/auth")
public class AuthController {
// 注入MessageSource(Spring自動配置,無需額外配置)
private final MessageSource messageSource;
// 構(gòu)造器注入
public AuthController(MessageSource messageSource) {
this.messageSource = messageSource;
}
@PostMapping("/login")
public Result login(@RequestBody LoginDTO dto) {
if (checkLogin(dto)) {
// 通過key獲取對應(yīng)語言文本:sys.login.success
String successMsg = messageSource.getMessage(
"sys.login.success", // 消息key
null, // 占位符參數(shù)(無則傳null)
LocaleContextHolder.getLocale() // 當(dāng)前語言環(huán)境
);
return Result.success(successMsg);
} else {
String failMsg = messageSource.getMessage(
"sys.login.fail",
null,
LocaleContextHolder.getLocale()
);
return Result.error(failMsg);
}
}
}帶占位符的文本處理:
# 中文配置:帶占位符
sys.welcome.user=歡迎您,{0}!
# 英文配置:帶占位符
sys.welcome.user=Welcome, {0}!// 傳遞參數(shù):{0}對應(yīng)"張三"
String welcomeMsg = messageSource.getMessage(
"sys.welcome.user",
new Object[]{"張三"}, // 占位符參數(shù)數(shù)組
LocaleContextHolder.getLocale()
);
// 中文環(huán)境返回:"歡迎您,張三!";英文環(huán)境返回:"Welcome, 張三!"

























