StaticMessageSource
ResourceBundleMessageSource
ReloadableResourceBundleMessageSource
使用及設定上3者都差不多, ReloadableResourceBundleMessageSource 的設定檔不需要放在 classpath 內, 且可以指定 cache, 故我選擇它實作.
實作環境Spring 3.1.0M1
在 spring 設定檔內設定如下:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename">
<value>/WEB-INF/i18n/messages</value>
</property>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds"><value>0</value></property>
</bean>
basename 指定訊息檔要放的位置及檔名.
本範例在 /WEB-INF/i18n/ 下會有 messages.properties, messages_en.properties, messages_zh_TW.properties ... 等各國語言的檔案.
messages.properties 內容為 Key=Value 型式的文字檔.
舉例來說:
messages_en_US.properties 的內容:
hello=Hello
messages_zh_TW.properties 的內容:
hello=哈囉
MessageSource會依 Http header 內的 Accept-Language 來判斷應選用那種語系.
如果該語系對應的檔案不存在, 預設會使用 messages.properties (注意, messages 為我在spring內的設定, 並非真的 spring 預設檔名).
如果 messages.properties 不存在, 則會拋出 exception.
在 jsp 內可使用 spring tag <s:message> 來取值 (記得要先宣告 <%@ taglib prefix="s" uri="http://www.springframework.org/tags"%>), 例
<s:message code="hello" text="hello" />
或是用 jstl tag <fmt:message> 來取值 (記得要先宣告 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> ), 例
<fmt:message key="hello" />
我個人比較喜歡用 spring tag, 因為有預設值可防止打錯字之類的低級錯誤.
spring:message 中帶參數的做法如下:
<s:message code="hello" text="hello {0}. {1}" argumentSeparator="|" arguments="Mr|Liu" />
詳請可參閱Spring文件message tag的說明.
如果在 jsp 中不用 spring tag 而想直接用 messageSource 的方式如下:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"
import="org.springframework.context.ApplicationContext"
import="org.springframework.web.context.support.WebApplicationContextUtils"
import="org.springframework.web.servlet.support.RequestContextUtils"
.
.
.
<%
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext( application.getContext(request.getContextPath())) ;
Locale locale = RequestContextUtils.getLocale(request) ;
out.println(ctx.getMessage("MESSAGE", null, "Message", locale)) ;
%>
import="org.springframework.context.ApplicationContext"
import="org.springframework.web.context.support.WebApplicationContextUtils"
import="org.springframework.web.servlet.support.RequestContextUtils"
.
.
.
<%
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext( application.getContext(request.getContextPath())) ;
Locale locale = RequestContextUtils.getLocale(request) ;
out.println(ctx.getMessage("MESSAGE", null, "Message", locale)) ;
%>
messages.properties 規定需為 iso-8859-1 編碼, 故若非英文語系的檔案, 需做特殊處理.
我的作法是, 編寫一個 messages_zh_TW.txt 的檔案, UTF-8 編碼 (不要有 BOM, 不然轉碼時第一行會出錯.)
然後以 jdk 附的 native2ascii 進行轉檔, 指令如下:
native2ascii -encoding utf8 messages_zh_TW.txt messages_zh_TW.properties
經此步驟轉出來的檔案才能派上用場.
如果要讓使用者可以自行選擇語系呢 ?
Spring 提供了 LocaleResolver 搭配 LocaleChangeInterceptor 進行這件事.
先在 spring 設定檔內設定如下:
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
</mvc:interceptors>
註: 除了 CookieLocaleResolver 還有 SessionLocaleResolver 可以用.
接著只要在網址後面加上參數 locale=zh_TW 或 locale=en_US ... 就可以變換不同語系了.
註: LocaleChangeInterceptor 有個參數 paramName 可用來指定參數名稱, 預設是 locale, 您也可以指定為 lang 或其它您喜歡的名稱.
最後, 想知道瀏覽器送出的 accept-language 為何, 可在 jsp 內以下列方式取得.
request.getHeader("Accept-Language") ;
在 Java 可以下列方式取得目前的 locale:
RequestContextUtils.getLocale(request)
最後的最後, locale 不論大寫或小寫, i18n 都可以正確判斷並發揮作用.
補充, 如果要指定 locale 的作法如下:
LocaleEditor localeEditor = new LocaleEditor();
localeEditor.setAsText("en_US"); // your locale string
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
localeResolver.setLocale(request, response, (Locale) localeEditor.getValue());
localeEditor.setAsText("en_US"); // your locale string
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
localeResolver.setLocale(request, response, (Locale) localeEditor.getValue());
沒有留言:
張貼留言