Spring MVC 通過 MessageSource、LocaleResolver、LocaleChangeInterceptor 三大組件實現國際化。本文以 **SessionLocaleResolver** 為核心,演示基於 Session 的動態語言切換 (中文/英文/韓文),涵蓋前端標簽、後端代碼、配置文件、編碼處理全流程。
| 組件 | 角色 | 本文實現 |
|---|---|---|
MessageSource | 資源包加載與消息解析 | ReloadableResourceBundleMessageSource (熱重載) |
LocaleResolver | 決定當前請求 Locale | SessionLocaleResolver (Session 存儲,用戶級持久化) |
LocaleChangeInterceptor | 攔截請求參數切換 Locale | 參數名 language (如 ?language=zh_CN) |
src/main/resources/ ├── messages/ │ ├── messages.properties # 默認 (英文) │ ├── messages_zh_CN.properties # 中文 (需 Unicode 轉義) │ ├── messages_en_US.properties # 英文 │ └── messages_ko_KR.properties # 韓文 └── spring-mvc.xml # Spring MVC 配置
# messages_zh_CN.properties (native2ascii 轉義後) hello=\u4f60\u597d welcome=\u6b22\u8fce\u4f60 # messages_en_US.properties hello=Hello welcome=Welcome # messages_ko_KR.properties hello=\uc548\ub155\ud558\uc138\uc694 welcome=\ud658\uc601\ud569\ub2c8\ub2e4
關鍵:Properties 文件**必須為 ISO-8859-1 編碼**,中文/韓文等非 ASCII 字符**必須用 \uXXXX Unicode 轉義**,否則讀取亂碼。IDE 通常自動處理,命令行可用 native2ascii -encoding UTF-8 src.properties target.properties。
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:mvc="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 1. 資源包綁定器 (基礎名稱 messages/message,自動追加 _locale) -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages/message"/> <!-- 關鍵:到第一個下劃線前 -->
<property name="defaultEncoding" value="UTF-8"/>
<property name="useCodeAsDefaultMessage" value="true"/> <!-- 找不到 key 返回 key 本身 -->
<property name="cacheSeconds" value="60"/> <!-- 熱重載間隔,開發設 0 即時生效 -->
</bean>
<!-- 2. Session 級 Locale 解析器 -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="zh_CN"/> <!-- 默認中文 -->
</bean>
<!-- 3. 語言切換攔截器 -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language"/> <!-- URL 參數名 -->
</bean>
</mvc:interceptors>
<!-- 其他 MVC 配置... -->
</beans>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="spring" uri="https://www.springframework.org/tags" %>
<html>
<head><meta charset="UTF-8"/><title>i18n Demo</title></head>
<body>
<!-- 語言切換鏈接 -->
語言選擇:
<a href="?language=zh_CN">中文</a> |
<a href="?language=en_US">English</a> |
<a href="?language=ko_KR">한국어</a>
<br/><br/>
<!-- 1. 前端標簽國際化 (推薦) -->
前端標簽翻譯「你好」: <spring:message code="hello"/>
<br/>
<!-- 2. 後端注入模型國際化 -->
後端代碼翻譯「歡迎你」: ${welcome}
</body>
</html>
package com.ccg.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.RequestContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/view")
public ModelAndView view(HttpServletRequest request, HttpServletResponse response) {
// 1. 創建 RequestContext 綁定當前請求的 Locale 與 MessageSource
RequestContext rc = new RequestContext(request);
// 2. 獲取國際化消息 (key 為資源文件中的 key)
String welcomeMsg = rc.getMessage("welcome");
// 3. 返回視圖並攜帶模型數據
ModelAndView mv = new ModelAndView("test"); // 對應 test.jsp
mv.addObject("welcome", welcomeMsg);
return mv;
}
}
@Service
public class NotificationService {
@Autowired private MessageSource messageSource;
public String getWelcome(Locale locale) {
return messageSource.getMessage("welcome", null, locale);
}
}
| 語言參數 | 前端顯示「你好」 | 後端顯示「歡迎你」 |
|---|---|---|
?language=zh_CN | 你好 | 歡迎你 |
?language=en_US | Hello | Welcome |
?language=ko_KR | 안녕하세요 | 환영합니다 |
classpath:messages/message 對應 messages/message_zh_CN.properties,**不要寫後綴**,不要寫 messages/message_zh_CN。defaultEncoding="UTF-8" + 頁面 <meta charset="UTF-8"> + 資源文件 Unicode 轉義 = 零亂碼。SessionLocaleResolver:用戶登入後持久化偏好,**本文推薦**。CookieLocaleResolver:無需登入,瀏覽器級持久化 (需配置 Cookie 名/過期)。AcceptHeaderLocaleResolver:根據 Accept-Language 頭自動檢測,無用戶干預。FixedLocaleResolver:固定 Locale,測試用。paramName="language" 勿與業務參數同名,建議用 lang 或 locale。<span th:text="#{hello}"> 直接使用,無需額外配置。messageSource.getMessage("items.count", new Object[]{count}, locale) 配合 MessageFormat 處理 0/1/多 條件。Spring MVC i18n 核心三步:**配置 MessageSource 定位資源包 → 配置 LocaleResolver 存儲用戶偏好 → 配置 LocaleChangeInterceptor 響應切換請求**。前端用 <spring:message>,後端用 RequestContext.getMessage() 或 MessageSource.getMessage()。資源文件**必須 Unicode 轉義**,basename **精確到基礎名**。SessionLocaleResolver 適合登入系統,CookieLocaleResolver 適合公開站點。