在全球化的今天,如今比過去更須要編寫能夠在不一樣語言國家和地區部署的應用程序。在這方面,須要瞭解兩個術語:css
Java謹記國家互的需求,爲字符和字符串提供了Unicode支持。所以,用Java編寫國際化的應用程序是一件很容易的事情。國際化應用程序的具體方式取決於有多少靜態數據須要以不一樣的語言顯示出來。這裏有兩種方法:html
本篇博客首先解釋什麼是語言區域,接着講解國際化應用程序技術,最後介紹一個Spring MVC範例。java
每個Locale對象都表明了一個特定的地理、政治和文化地區。在操做 Date, Calendar等表示日期/時間的對象時,常常會用到;由於不一樣的區域,時間表示方式都不一樣。一個Locale對象包含3個主要參數:language、country和variant:web
Locale的構造函數共有3個:spring
public Locale(String language) public Locale(String language, String country) public Locale(String language, String country, String variant)
參數language是一個有效的ISO語言碼。下表顯示了ISO 639語言碼範例:apache
代碼 | 語言 |
de | 德語 |
el | 希臘語 |
en | 英語 |
es | 西班牙語 |
fr | 法語 |
hi | 印地語 |
it | 意大利語 |
ja | 日語 |
nl | 荷蘭語 |
pt | 葡萄牙語 |
ru | 俄語 |
zh | 漢語 |
參數country是一個有效的ISO國家碼,由兩個字母組成,ISO 3166中指定爲大寫字母。下表展現了ISO 3166國家碼範例:數組
國家 | 代碼 |
澳大利亞 | AU |
巴西 | BR |
加拿大 | CA |
中國 | CN |
埃及 | EG |
法國 | FR |
德語 | DE |
印度 | IN |
墨西哥 | MX |
瑞士 | CH |
英國 | GB |
美國 | US |
Locale類支持很是多的國家和地區。咱們能夠經過如下方法,查看Locale支持的所有區域:瀏覽器
Locale[] ls = Locale.getAvailableLocales(); System.out.print("All Locales: "); for(Locale locale:ls) { System.out.printf(locale+", "); }
輸出結果以下:spring-mvc
All Locales: , ar_AE, ar_JO, ar_SY, hr_HR, fr_BE, es_PA, mt_MT, es_VE, bg, zh_TW, it, ko, uk, lv, da_DK, es_PR, vi_VN, en_US, sr_ME, sv_SE, es_BO, en_SG, ar_BH, pt, ar_SA, sk, ar_YE, hi_IN, ga, en_MT, fi_FI, et, sv, cs, sr_BA_#Latn, el, uk_UA, hu, fr_CH, in, es_AR, ar_EG, ja_JP_JP_#u-ca-japanese, es_SV, pt_BR, be, is_IS, cs_CZ, es, pl_PL, tr, ca_ES, sr_CS, ms_MY, hr, lt, es_ES, es_CO, bg_BG, sq, fr, ja, sr_BA, is, es_PY, de, es_EC, es_US, ar_SD, en, ro_RO, en_PH, ca, ar_TN, sr_ME_#Latn, es_GT, sl, ko_KR, el_CY, es_MX, ru_RU, es_HN, zh_HK, no_NO_NY, hu_HU, th_TH, ar_IQ, es_CL, fi, ar_MA, ga_IE, mk, tr_TR, et_EE, ar_QA, sr__#Latn, pt_PT, fr_LU, ar_OM, th, sq_AL, es_DO, es_CU, ar, ru, en_NZ, sr_RS, de_CH, es_UY, ms, el_GR, iw_IL, en_ZA, th_TH_TH_#u-nu-thai, hi, fr_FR, de_AT, nl, no_NO, en_AU, vi, nl_NL, fr_CA, lv_LV, de_LU, es_CR, ar_KW, sr, ar_LY, mt, it_CH, da, de_DE, ar_DZ, sk_SK, lt_LT, it_IT, en_IE, zh_SG, ro, en_CA, nl_BE, no, pl, zh_CN, ja_JP, de_GR, sr_RS_#Latn, iw, en_IN, ar_LB, es_NI, zh, mk_MK, be_BY, sl_SI, es_PE, in_ID, en_GB,
下面選擇其中的一個進行說明,如何利用它們來建立Locale對象:例如,輸出「ja_JP」。其中,ja表明「語言」,這裏指日語;「JP」表明國家,這裏指日本。tomcat
咱們能夠經過以下方法,建立一個表示中國所用漢語的Locale對象,能夠像下面這樣編寫:
Locale local = new Locale("zh", "CN");
此外,Locale類提供了static final域(編譯期常量),用來返回特定國家或語言的語言區域:
public static final Locale CANADA public static final Locale CANADA_FRENCH public static final Locale CHINA public static final Locale CHINESE public static final Locale ENGLISH public static final Locale FRANCE public static final Locale FRENCH public static final Locale GERMAN public static final Locale GERMANY public static final Locale ITALIAN public static final Locale ITALY public static final Locale JAPAN public static final Locale JAPANESE public static final Locale KOREA public static final Locale KOREAN public static final Locale PRC public static final Locale ROOT public static final Locale SIMPLIFIED_CHINESE public static final Locale TAIWAN public static final Locale TRADITIONAL_CHINESE public static final Locale UK
所以,也能夠經過調用其static於來構造Locale對象,下面的Locale對象是對應 「中國(簡體中文)」的
Locale locale = Locale.SIMPLIFIED_CHINESE
此外,靜態的getDefault()方法會返回用戶計算機的語言區域:
Locale locale = Locale.getDefault()
下面經過示例演示在Date中使用Locale的。參考代碼以下(LocaleTest.java):
import java.util.Locale; import java.util.Date;import java.text.DateFormat; /** * Locale 的測試程序 */ public class LocaleTest { public static void main(String[] args) { // 2種不一樣的Locale的建立方法 testDiffDateLocales(); // 顯示全部的Locales testAllLocales(); } /** * 2種不一樣的Locale的建立方法 */ private static void testDiffDateLocales() { // date爲2013-09-19 14:22:30 Date date = new Date(113, 8, 19, 14, 22, 30); System.out.println(date); // 建立「簡體中文」的Locale Locale localeCN = Locale.SIMPLIFIED_CHINESE; // 建立「英文/美國」的Locale Locale localeUS = new Locale("en", "US"); // 獲取「簡體中文」對應的date字符串 String cn = DateFormat.getDateInstance(DateFormat.MEDIUM, localeCN).format(date); // 獲取「英文/美國」對應的date字符串 String us = DateFormat.getDateInstance(DateFormat.MEDIUM, localeUS).format(date); System.out.printf("cn=%s\nus=%s\n", cn, us); } /** * 顯示全部的Locales */ private static void testAllLocales() { Locale[] ls = Locale.getAvailableLocales(); System.out.print("All Locales: "); for(Locale locale:ls) { System.out.printf(locale+", "); } System.out.println(); } }
輸出以下:
Thu Sep 19 14:22:30 CST 2013 cn=2013-9-19 us=Sep 19, 2013 All Locales: , ar_AE, ar_JO, ar_SY, hr_HR, fr_BE, es_PA, mt_MT, es_VE, bg, zh_TW, it, ko, uk, lv, da_DK, es_PR, vi_VN, en_US, sr_ME, sv_SE, es_BO, en_SG, ar_BH, pt, ar_SA, sk, ar_YE, hi_IN, ga, en_MT, fi_FI, et, sv, cs, sr_BA_#Latn, el, uk_UA, hu, fr_CH, in, es_AR, ar_EG, ja_JP_JP_#u-ca-japanese, es_SV, pt_BR, be, is_IS, cs_CZ, es, pl_PL, tr, ca_ES, sr_CS, ms_MY, hr, lt, es_ES, es_CO, bg_BG, sq, fr, ja, sr_BA, is, es_PY, de, es_EC, es_US, ar_SD, en, ro_RO, en_PH, ca, ar_TN, sr_ME_#Latn, es_GT, sl, ko_KR, el_CY, es_MX, ru_RU, es_HN, zh_HK, no_NO_NY, hu_HU, th_TH, ar_IQ, es_CL, fi, ar_MA, ga_IE, mk, tr_TR, et_EE, ar_QA, sr__#Latn, pt_PT, fr_LU, ar_OM, th, sq_AL, es_DO, es_CU, ar, ru, en_NZ, sr_RS, de_CH, es_UY, ms, el_GR, iw_IL, en_ZA, th_TH_TH_#u-nu-thai, hi, fr_FR, de_AT, nl, no_NO, en_AU, vi, nl_NL, fr_CA, lv_LV, de_LU, es_CR, ar_KW, sr, ar_LY, mt, it_CH, da, de_DE, ar_DZ, sk_SK, lt_LT, it_IT, en_IE, zh_SG, ro, en_CA, nl_BE, no, pl, zh_CN, ja_JP, de_GR, sr_RS_#Latn, iw, en_IN, ar_LB, es_NI, zh, mk_MK, be_BY, sl_SI, es_PE, in_ID, en_GB,
國際化和本地化應用程序時,須要具有如下條件:
下面詳細介紹這兩個步驟,並進行簡單的示範。
國際化的應用程序是將每個語言區域的文本元素都單獨保存在一個獨立的屬性文件中。每一個文件中都包含key/value對,而且每一個key都惟一標示一個特定語言區域的對象。key始終是字符串,value則能夠是字符串,也能夠是其餘任意類型的對象。例如,爲了支持英語、德語、以及漢語,就要有3個屬性文件,它們都有相同的key。
如下是英語版的屬性文件。注意:它有greetings和farewell兩個key:
greetings=Hello
farewell=Goodbye
德語版的屬性文件以下:
greetings=Hallo
farewell=Auf Wiedersehen
漢語版的屬性文件以下:
greetings=\u4f60\u597d
farewell=\u518d\u89c1
若是你是中文用戶,你可使用任何中文文本編輯器並寫入漢字字符。完成後,將文件轉換成Unicode。
如今,要學習java.util.ResourceBundle類。它能使你輕鬆的選擇和讀取特定於用戶語言區域的屬性,以及查找值。ResourceBundle是一個抽象類,可是它提供了靜態的getBundle()方法,返回一個具體子類的實例。
ResourceBoundle有一個基準名,它能夠是任意名稱。可是,爲了讓ResourceBundle正確的選擇屬性文件,這個文件名中最好必須包含基準名ResourceBundle,後面再接下劃線、語言碼,還能夠選擇再加一條下劃線和國家碼。屬性文件名的格式以下所示:
basename_lanuageCode_countryCode
例如,假設基準名爲MyResources,而且定義瞭如下3個語言區域:
那麼就會獲得下面這3個屬性文件:
如前所述。ResourceBundle是一個抽象類。儘管如此,仍是能夠經過調用它的靜態getBundle()方法來獲取一個ResourceBundle實例。它的重載簽名以下:
public static final ResourceBundle getBundle(String baseName) public static final ResourceBundle getBundle(String baseName,Locale locale)
例如:
ResourceBundle rb = ResourceBundle .getBundle("MyResources",Locale.US);
這樣就會加載ResourceBundle在相應屬性文件中的值。
若是沒有找到合適的屬性文件,ResourceBundle對象就會返回到默認的屬性文件。默認屬性文件的名稱爲基準名加一個擴展名properties。在這個例子中,默認文件就是MyResource.properties。若是沒有找到默認文件,將拋出java.util.MissingResourceException。
隨後,讀取值,利用ResourceBundle類的getString()方法傳入一個key。
public String getString(String key)
若是沒有找到指定key的入口,就會拋出出java.util.MissingResourceException。
在Spring MVC中,不直接使用ResourceBundle,而是利用messageSource bean告訴Spring MVC要將屬性文件保存在哪裏。例如,下面的messageSource bean讀取了兩個屬性文件:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames" > <list> <value>/WEB-INF/resource/messages</value> <value>/WEB-INF/resource/labels</value> </list> </property> </bean>
上面的bean定義中用了ReloadableResourceBundleMessageSource 類做爲的實現類。另外一個實現類是ResourceBundleMessageSource,可是它是不能從新加載的,這意味着,若是在任意屬性文件中修改了某一個屬性key或者value,而且正在使用ResourceBundleMessageSource,那麼要使修改生效,就必須先重啓JVM。
這兩個實現之間的另外一個區別是:使用ReloadableResourceBundleMessageSource時,是在應用程序目錄下搜索這些屬性文件,而使用ResourceBundleMessageSource時,屬性文件則必須放在類路徑下,即/WEB-INF/class目錄下。
還要注意,若是隻有一組屬性文件,則能夠用basename屬性替代basenames,像下面這樣:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="/WEB-INF/resource/messages" /> </bean>
爲用戶選擇語言區域時,最經常使用的方法或許是讀取用戶瀏覽器的accept-language標題值。accept-language標題值提供了關於偏好哪一種語言的信息。
選擇語言區域的其它方法還包括讀取某個session屬性或者cookie。
在Spring MVC中選擇語言區域,可使用語言區域解析器bean。它有幾個實現:
全部這些實現都是org.springframework.web.server.i18n包的組成部分。AccpetHeaderLocaleResolver或許是其中最容易使用的一個。若是選擇使用這個語言區域解析器,Spring MVC將會讀取瀏覽器的accept-language標題,來肯定瀏覽器要接受哪一個語言區域。若是瀏覽器的某個語言區域與Spring MVC應用程序支持的某個語言區域匹配,就會使用這個語言區域。若是沒有找到匹配的語言區域,則使用默認的語言區域。
下面是使用AccpetHeaderLocaleResolver的localeResovler bean定義:
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"> </bean>
在Spring MVC中顯示本地化消息最容易方法是使用Spring的message標籤。爲了使用這個標籤,要在使用該標籤的全部JSP頁面最前面聲明以下一個taglib指令:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
message標籤的屬性見下表,全部這些屬性都是可選的:
屬性 | 描述 |
arguments | 該標籤的參數寫成一個有界的字符串、一個對象數組或者單個對象 |
argumentSeparator | 用來分割該標籤參數的字符 |
code | 獲取消息的key |
htmlEscape | 接受true或者false,表示被渲染文本是都應該進行HTML轉義 |
javaScriptEscape | 接受true或者false,表示被渲染文本是都應該進行JavaScript轉義 |
message | MessageSourceResolvable參數 |
scope | 保存var屬性中定義的變量的範圍 |
text | 若是code屬性不存在,或者指定碼沒法獲取消息,所顯示的默認文本 |
var | 用於保存消息的有界變量 |
下面咱們將會建立一個i18n應用程序,該應用展現了用localeResovler bean將JSP頁面中的消息本地化的方法。
i18n應用程序目錄結構以下圖:
package domain; import java.io.Serializable; import java.math.BigDecimal; public class Product implements Serializable { private static final long serialVersionUID = 78L; private String name; private String description; private BigDecimal price; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } }
該應用包含一個名爲ProductValidator的驗證器:
package validator; import java.math.BigDecimal; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import domain.Product; public class ProductValidator implements Validator { @Override public boolean supports(Class<?> klass) { //支持Product類? return Product.class.isAssignableFrom(klass); } //將目標對象target的錯誤註冊到errors對象中 @Override public void validate(Object target, Errors errors) { Product product = (Product) target; //若是目標對象的name屬性爲null,或者爲""字符串,則將錯誤註冊到errors對象 ValidationUtils.rejectIfEmpty(errors, "name", "productname.required"); BigDecimal price = product.getPrice(); //若是價格爲負數 則將錯誤註冊到errors對象中 if (price != null && price.compareTo(BigDecimal.ZERO) < 0) { errors.rejectValue("price", "price.negative"); } } }
ProductValidator驗證器是一個很是簡單的驗證器。它的validate()方法會檢驗Product是否有名稱,而且價格是否不爲負數。
在Controller類中經過實例化validator類,可使用Spring驗證器:
package controller; import javax.validation.Valid; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import validator.ProductValidator; import domain.Product; @Controller public class ProductController { private static final Log logger = LogFactory.getLog(ProductController.class); @RequestMapping(value="/add-product") public String inputProduct(Model model) { model.addAttribute("product", new Product()); return "ProductForm"; } @RequestMapping(value="/save-product") public String saveProduct(@ModelAttribute Product product, BindingResult bindingResult, Model model) { //建立一個ProductValidator,並調用其validate()方法校驗Product對象,並將驗證錯誤填入bindingResult中。 ProductValidator productValidator = new ProductValidator(); productValidator.validate(product, bindingResult); if (bindingResult.hasErrors()) { FieldError fieldError = bindingResult.getFieldError(); logger.debug("Code:" + fieldError.getCode() + ", field:" + fieldError.getField()); return "ProductForm"; } // save product here //model.addAttribute("product", product); return "ProductDetails"; } }
ProductController類的saveProduct()方法,有三個參數:
注意:BindingResult接口是Errors接口的子類,在請求處理方法的簽名中使用了BindingResult參數,就是告訴Spring關於表單對象數據校驗的錯誤將由咱們本身來處理,不然Spring會直接拋出異常。
該方法建立一個ProductValidator,並調用其validate()方法校驗Product對象,並將驗證錯誤填入bindingResult中。
ProductValidator productValidator = new ProductValidator(); productValidator.validate(product, bindingResult);
爲了檢驗該驗證器是否生成錯誤消息,須要在BindingResult中調用hasErrors()方法:
if (bindingResult.hasErrors()) { FieldError fieldError = bindingResult.getFieldError(); logger.debug("Code:" + fieldError.getCode() + ", field:" + fieldError.getField()); return "ProductForm"; }
若是存在表單綁定錯誤或者是輸入驗證錯誤,將會打印出錯誤相關的字段,並重定位到ProductForm.jsp頁面。
若是表單輸入的數據均合法,則會重定位到ProductDetails.jsp頁面。
i18n應用包含2個視圖文件:
ProductForm.jsp:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <title><spring:message code="page.productform.title"/></title> <style type="text/css">@import url("<c:url value="/css/main.css"/>");</style> </head> <body> <div id="global"> Current Locale : ${pageContext.response.locale} <br/> accept-language header: ${header["accept-language"]} <form:form modelAttribute="product" action="save-product" method="post"> <fieldset> <legend><spring:message code="form.name"/></legend> <p> <label for="name"><spring:message code="label.productName" text="default text" />:</label> <form:input id="name" path="name" cssErrorClass="error"/> <form:errors path="name" cssClass="error"/> </p> <p> <label for="description"><spring:message code="label.description"/>: </label> <form:input id="description" path="description"/> </p> <p> <label for="price"><spring:message code="label.price" text="default text" />: </label> <form:input id="price" path="price" cssErrorClass="error"/> <form:errors path="price" cssClass="error"/> </p> <p id="buttons"> <input id="reset" type="reset" tabindex="4" value="<spring:message code="button.reset"/>"> <input id="submit" type="submit" tabindex="5" value="<spring:message code="button.submit"/>"> </p> </fieldset> </form:form> </div> </body> </html>
爲了實現本地化,JSP頁面中的每一段文本都使用了message標籤代替html中的label標籤,如:
<label for="name"><spring:message code="label.productName" text="default text" />:</label>
同時爲了調試,當前的語言區域和accept-language標題顯示在頁面的最前面:
Current Locale : ${pageContext.response.locale} <br/> accept-language header: ${header["accept-language"]}
ProductDetails.jsp:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <title>Save Product</title> <style type="text/css">@import url("<c:url value="/css/main.css"/>");</style> </head> <body> <div id="global"> <h4>The product has been saved.</h4> <p> <h5>Details:</h5> Product Name: ${product.name}<br/> Description: ${product.description}<br/> Price: $${product.price} </p> </div> </body> </html>
main.css:
#global { text-align: left; border: 1px solid #dedede; background: #efefef; width: 560px; padding: 20px; margin: 100px auto; } form { font:100% verdana; min-width: 500px; max-width: 600px; width: 560px; } form fieldset { border-color: #bdbebf; border-width: 3px; margin: 0; } legend { font-size: 1.3em; } form label { width: 250px; display: block; float: left; text-align: right; padding: 2px; } #buttons { text-align: right; } #errors, li { color: red; } .error { color: red; font-size: 9pt; }
部署描述符(web.xml文件):
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/springmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
下面給出springmvc-config.xml文件的全部內容:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="controller" /> <mvc:annotation-driven/> <mvc:resources mapping="/css/**" location="/css/" /> <mvc:resources mapping="/*.html" location="/" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames" > <list> <value>/WEB-INF/resource/messages</value> <value>/WEB-INF/resource/labels</value> </list> </property> </bean> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"> </bean> </beans>
這裏用到了messageSource bean和localeResolver bean:
Spring MVC經過讀取瀏覽器的accept-language標題,來肯定瀏覽器接受哪一個語言區域,而後再結合基準名查找該語言區域對應的屬性文件,若是有,則使用語言區域。若是沒有,則使用默認的語言區域。
該應用支持en、fr、zh三種語言區域,此外,還有一個默認的語言區域(和en語言區域同樣),所以屬性文件有四種版本。爲了實現本地化,JSP頁面中的每一段文本都使用了message標籤代替。具體能夠查看ProductForm.jsp文件。
將屬性文件分爲兩類:
messages_en.properties(英語):
productname.required=Please enter a name
price.negative=Invalid price
messages_fr.properties(法語):
productname.required=S'il vous pla�t entrer un nom de produit
price.negative=Valeur invalide
messages_zh.properties(漢語):
productname.required=\u4EA7\u54C1\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
price.negative=\u5546\u54C1\u4EF7\u683C\u4E0D\u80FD\u4E3A\u8D1F\u6570
messages.properties(默認):
productname.required.product.name=Please enter a name
price.negative=Invalid price
labels_en.properties(英語):
label.productName=Product Name
label.description=Description
label.price=Price
button.reset=Reset
button.submit=Add Product
form.name=Product Form
page.productform.title=New Product
labels_fr.properties(法語):
label.productName=Nom du Produit
label.description=Description
label.price=Prix
button.reset=Réinitialiser
button.submit=Ajouter Produit
form.name=Formulaire de Produit
page.productform.title=Formulaire
labels_zh.properties(漢語):
label.productName=\u4EA7\u54C1\u540D\u79F0
label.description=\u63CF\u8FF0
label.price=\u4EF7\u683C
button.reset=\u91CD\u7F6E
button.submit=\u589E\u52A0\u4EA7\u54C1
form.name=\u4EA7\u54C1\u8868\u5355
page.productform.title=\u65B0\u589E\u4EA7\u54C1
labels.properties(默認):
label.productName=Product Name
label.description=Description
label.price=Price
button.reset=Reset
button.submit=Add Product
form.name=Product Form
page.productform.title=New Product
爲了測試應用程序,要修改瀏覽器的accept-language標籤。
對於Chrome瀏覽器,打開」設置「頁面,點擊「顯示高級設置」,點擊「語言和輸入設置」,添加並移動語言到列表的頂部。
將應用程序部署到tomcat服務器,訪問如下URL:
http://localhost:8008/i18n/add-product
你會看到Product的中文版:
修改accept-language標籤,將英語移動到列表的頂部,再次刷新頁面:
修改accept-language標籤,將法語移動到列表的頂部,再次刷新頁面:
注意:該應用的全部文件都採用UTF-8編碼。
參考文章
[2]java中的編碼問題
[3]Spring MVC學習指南