根據數據的類型不同,國際化分為2類:靜態數據國際化和動態數據的國際化。
?
靜態數據,包括 “標題”、“用戶名”、“密碼”這樣的文字數據。
動態數據,包括日期、貨幣等可以動態生成的數據。
?
國際化涉及到java.util.Locale和java.util.ResourceBundle類。
?
java.util.Locale
A Locale object represents a specific geographical, political, or cultural region.
Locale對象代表了一定的地理、政治、文化區域。
?
java.util.ResourceBundle
Resource bundles contain locale-specific objects. When your program needs a locale-specific resource, a String for example, your program can load it from the resource bundle that is appropriate for the current user's locale. In this way, you can write program code that is largely independent of the user's locale isolating most, if not all, of the locale-specific information in resource bundles.?
ResouceBundle,由兩個單詞組成Resouce和Bundle,合在一起就是“資源包”的意思。ResouceBundle是包含不同區域(Locale)資源的集合,只要向ResouceBundle提供一個特定的Locale對象,ResouceBundle就會把相應的資源返回給你。
1、靜態數據國際化
?
靜態數據國際化的步驟:
(1).建立資源文件,存儲所有國家顯示的文本的字符串
????a)文件: .properties
????b)命名: ?基礎名_語言簡稱_國家簡稱.properties
????????例如:?msg_zh_CN.properties ? ? 存儲所有中文
????????????msg_en_US.properties ? ?存儲所有英文
(2).程序中獲取
????ResourceBundle類,可以讀取國際化的資源文件!
????Locale類,代表某一區域,用于決定使用哪一個國際化的資源。
?
1.1、Locale的API
static Locale getDefault()????得到JVM中默認的Locale對象
String getCountry()????? ? ?得到國家名稱的簡寫
String getDisplayCountry()????得到國家名稱的全稱
String getLanguage()????? ? 得到當前語言的簡寫
String getDisplayLanguage()????得到語言的全稱
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package ?com.rk.i18n.demo; import ?java.util.Locale; public ?class ?Demo01 { ???? public ?static ?void ?main(String[]?args) ???? { ???????? //本地化對象:Locale ???????? //?封裝語言、國家信息的對象,由java.util提供 //????? Locale?locale?=?Locale.CHINA; //????? Locale?locale?=?Locale.US; ???????? Locale?locale?=?Locale.getDefault(); ???????? String?country?=?locale.getCountry(); ???????? String?displayCountry?=?locale.getDisplayCountry(); ???????? String?language?=?locale.getLanguage(); ???????? String?displayLanguage?=?locale.getDisplayLanguage(); ???????? ????????? System.out.println(country);?????????? //????? CN??????? ???????? System.out.println(displayCountry);??? //???? 中國??????? ???????? System.out.println(language);????????? //?????? zh??????? ???????? System.out.println(displayLanguage);?? //????? 中文??????? ???? } } |
?
1.2、ResourceBundle的API
static ResourceBundle getBundle(String baseName,Locale locale) 獲取ResourceBundle實例
String getString(String key)????根據key獲取資源中的值
?
?
1.3、示例
?
(1)建立properties文件:msg_zh_CN.properties和msg_en_US.properties
msg_zh_CN.properties
1 2 | uname=\u59D3\u540D pwd=\u5BC6\u7801 |
?
msg_en_US.properties
1 2 | uname=User?Name pwd=Password |
(2)代碼獲取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package ?com.rk.i18n.demo; import ?java.util.Locale; import ?java.util.ResourceBundle; //?國際化?-?靜態數據 public ?class ?Demo02 { ???? public ?static ?void ?main(String[]?args) ???? { ???????? //?中文語言環境 ???????? Locale?locale?=?Locale.US; ???????? ????????? //?創建工具類對象ResourceBundle ???????? ResourceBundle?bundle?=?ResourceBundle.getBundle( "com.rk.i18n.demo.msg" ,?locale); ???????? ????????? //?根據key獲取配置文件中的值 ???????? String?uname?=?bundle.getString( "uname" ); ???????? String?pwd?=?bundle.getString( "pwd" ); ???????? ????????? //輸出 ???????? System.out.println(uname); ???????? System.out.println(pwd); ???? } } |
?
1.4、關于ResourceBundle的資源文件properties
文件命名:基礎名、語言簡稱
Resource bundles belong to families whose members share a common base name, but whose names also have additional components that identify their locales. For example, the base name of a family of resource bundles might be "MyResources". ?The family can then provide as many locale-specific members as needed, for example a German one named "MyResources_de".?
?
文件命名:國家簡稱
If there are different resources for different countries, you can make specializations: for example, "MyResources_de_CH" contains objects for the German language (de) in Switzerland (CH). If you want to only modify some of the resources in the specialization, you can do so.?
?
文件命名:默認的Resource Bundle
The family should have a default resource bundle which simply has the same name as its family - "MyResources" - and will be used as the bundle of last resort if a specific locale is not supported.
?
文件內容:屬于同一個family的resource bundle要包含相同的items內容。
Each resource bundle in a family contains the same items, but the items have been translated for the locale represented by that resource bundle. For example, both "MyResources" and "MyResources_de" may have a String that's used on a button for canceling operations. In "MyResources" the String may contain "Cancel" and in "MyResources_de" it may contain "Abbrechen".?
?
Java代碼:獲取Resource Bundle
When your program needs a locale-specific object, it loads the ResourceBundle class using the getBundle method:?
?
?ResourceBundle myResources = ResourceBundle.getBundle("MyResources", currentLocale);
?
?
2、動態數據國際化
動態國際化則主要涉及到數字、貨幣、百分比和日期
例如:
????中文:1987-09-19 ? ¥1000
????英文: Sep/09 1987 ?$100
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | package ?com.rk.i18n.demo; import ?java.text.DateFormat; import ?java.text.NumberFormat; import ?java.text.ParseException; import ?java.util.Date; import ?java.util.Locale; import ?org.junit.Test; public ?class ?Demo03 { ???? //?國際化?-?動態文本?-?0.?概述 ???? public ?void ?testI18N() ???? { ???????? //?國際化貨幣 ???????? NumberFormat.getCurrencyInstance(); ???????? //?國際化數字 ???????? NumberFormat.getNumberInstance(); ???????? //?國際化百分比 ???????? NumberFormat.getPercentInstance(); ???????? //?國際化日期 ???????? //?DateFormat.getDateTimeInstance(dateStyle,?timeStyle,?aLocale) ???? } ???? //?國際化?-?動態文本?-?1.?國際化貨幣 ???? @Test ???? public ?void ?testI18NCurrency() ???? { ???????? //?模擬語言環境 ???????? Locale?locale?=?Locale.CHINA; ???????? //?數據準備 ???????? double ?number?=? 100 ; ???????? //?工具類 ???????? NumberFormat?nf?=?NumberFormat.getCurrencyInstance(locale); ???????? //?國際化貨幣 ???????? String?str?=?nf.format(number); ???????? //?輸出 ???????? System.out.println(str); ???? } ???? ????? //面試題:??代碼計算:??$100?*?10?? ???? @Test ???? public ?void ?testCurrency()? throws ?ParseException ???? { ???????? String?str?=? "$100" ; ???????? int ?num?=? 10 ; ???????? ????????? //?1.?分析str值是哪一國家的貨幣 ???????? Locale?locale?=?Locale.US; ???????? ????????? //?2.?國際化工具類 ???????? NumberFormat?nf?=?NumberFormat.getCurrencyInstance(locale); ???????? ????????? //?3.?解析str ???????? Number?number?=?nf.parse(str); ???????? ????????? //4.進行計算 ???????? int ?value?=?number.intValue()?*?num; ???????? //5.格式化輸出 ???????? str?=?nf.format(value); ???????? System.out.println(str); ???? } ???? ????? //?國際化?-?動態文本?-?2.?國際化數值 ???? @Test ???? public ?void ?testI18NNumber() ???? { ???????? Locale?locale?=?Locale.CHINA; ???????? NumberFormat?nf?=?NumberFormat.getNumberInstance(locale); ???????? String?str?=?nf.format( 1000000000 ); ???????? System.out.println(str); ???? } ???? ????? //?國際化?-?動態文本?-?3.?國際化百分比 ???? @Test ???? public ?void ?testI18NPercent() ???? { ???????? Locale?locale?=?Locale.CHINA; ???????? NumberFormat?nf?=?NumberFormat.getPercentInstance(locale); ???????? String?str?=?nf.format( 0.325 ); ???????? System.out.println(str); ???? } ???? ????? //?國際化?-?動態文本?-?4.?國際化日期 ???? /* ????? *?日期 ????? *??? ??FULL???2015年3月4日?星期三 ????? *??? ??LONG???2015年3月4日 ????? *??? ??FULL???2015年3月4日?星期三 ????? *????MEDIUM?2015-3-4 ????? *????SHORT??15-3-4 ????? *???? ????? *?時間 ????? *??? ??FULL???下午04時31分59秒?CST ????? *??? ??LONG???下午04時32分37秒 ????? *????MEDIUM?16:33:00 ????? *????SHORT??下午4:33 ????? *???? ????? *? ????? */ ???? @Test ???? public ?void ?testI18NDate() ???? { ???????? int ?dateStyle?=?DateFormat.FULL; ???????? int ?timeStyle?=?DateFormat.FULL; ???????? Locale?locale?=?Locale.CHINA; ???????? DateFormat?df?=?DateFormat.getDateTimeInstance(dateStyle,?timeStyle,?locale); ???????? String?date?=?df.format( new ?Date()); ???????? System.out.println(date); ???? } ???? ????? //?面試2:?請將時間值:09-11-28?上午10時25分39秒?CST,反向解析成一個date對象。 ???? @Test ???? public ?void ?testDate()? throws ?ParseException ???? { ???????? String?str?=? "09-11-28?上午10時25分39秒?CST" ; ???????? ????????? int ?dateStyle?=?DateFormat.SHORT; ???????? int ?timeStyle?=?DateFormat.FULL; ???????? Locale?locale?=?Locale.CHINA; ???????? //?創建DateFormat工具類,國際化日期 ???????? DateFormat?df?=?DateFormat.getDateTimeInstance(dateStyle,?timeStyle,?locale); ???????? Date?date?=?df.parse(str); ???????? System.out.println(date); ???? } } |
?
?
?
3、JSP頁面國際化
?
數值,貨幣,時間,日期等數據由于可能在程序運行時動態產生,所以無法像文字一樣簡單地將它們從應用程序中分離出來,而是需要特殊處理,有的Java培訓機構講的不錯。Java 中提供了解決這些問題的 API 類(位于 java.util 包和 java.text 包中)
?
3.1、準備工作:建立properties資源
建立2個properties文件:message_en_US.properties和message_zh_CN.properties。
?
message_zh_CN.properties
1 2 3 4 | title=\u4F60\u597D\uFF0C\u8BF7\u767B\u5F55 uname=\u7528\u6237\u540D pwd=\u5BC6\u7801 submit=\u63D0\u4EA4 |
message_en_US.properties
1 2 3 4 | title=Plean?Log?In uname=User?Name pwd=Password submit=Submit\! |
?
3.2、使用JSP腳本進行國際化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <%@?page?language="java"?import="java.util.*"?pageEncoding="UTF-8"%> <!DOCTYPE?HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"> < html > ?? < head > ???? <% ???????? ResourceBundle?bundle?=?ResourceBundle.getBundle("com.rk.i18n.resource.message",?request.getLocale()); ???? %> ???? < title ><%=bundle.getString("title")?%></ title > ???? < meta ?http-equiv = "pragma" ?content = "no-cache" > ???? < meta ?http-equiv = "cache-control" ?content = "no-cache" > ???? < meta ?http-equiv = "expires" ?content = "0" >???? ?? </ head > ?? ??? < body > ???? < table ?border = "1" > ???????? < tr > ???????????? < td ><%=bundle.getString("uname")?%></ td > ???????????? < td >< input ?type = "text" ?name = "uname" /></ td > ???????? </ tr > ???????? < tr > ???????????? < td ><%=bundle.getString("pwd")?%></ td > ???????????? < td >< input ?type = "password" ?name = "pwd" /></ td > ???????? </ tr > ???????? < tr > ???????????? < td ></ td > ???????????? < td >< input ?type = "submit" ?value = "<%=bundle.getString(" submit")?%>"/></ td > ???????? </ tr >???? ???? </ table > ?? </ body > </ html > |
?
3.3、使用JSTL進行國際化
?
JSTL標簽:
????核心標簽庫
????國際化與格式化標簽庫
????數據庫標簽庫(沒用)
????函數庫
????<fmt:setLocale value=""/> ? ? ? ?設置本地化對象
????<fmt:setBundle basename=""/> ? ? 設置工具類
????<fmt:message></fmt:message> ? ? 顯示國際化文本
????格式化數值:<fmt:formatNumber pattern="#.##" value="100.99"></fmt:formatNumber>
????格式化日期:<fmt:formatDate pattern="yyyy-MM-dd" value="${date}"/>
?
需要注意的一點是:HttpServletRequest有一個方法是getLocale(),可以獲取當前request中的Locale信息,在EL表達式中可以使用${pageContext.request.locale}獲取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <%@?page?language="java"?import="java.util.*"?pageEncoding="UTF-8"%> <%--引入jstl國際化與格式化標簽庫?--%> <%@taglib?uri="http://java.sun.com/jsp/jstl/fmt"?prefix="fmt"%> <!DOCTYPE?HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"> < html > ?? < head > ???? <!--?一、設置本地化對象?--> ???? < fmt:setLocale ?value = "${pageContext.request.locale?}" /> ???? <!--?二、設置工具類?--> ???? < fmt:setBundle ?basename = "com.rk.i18n.resource.message" ?var = "msg" /> ???? < title >< fmt:message ?bundle = "${msg?}" ?key = "title" ></ fmt:message ></ title > ???? < meta ?http-equiv = "pragma" ?content = "no-cache" > ???? < meta ?http-equiv = "cache-control" ?content = "no-cache" > ???? < meta ?http-equiv = "expires" ?content = "0" >???? ?? </ head > ?? ??? < body > ???? < table ?border = "1" > ???????? < tr > ???????????? < td >< fmt:message ?bundle = "${msg?}" ?key = "uname" ></ fmt:message ></ td > ???????????? < td >< input ?type = "text" ?name = "uname" /></ td > ???????? </ tr > ???????? < tr > ???????????? < td >< fmt:message ?bundle = "${msg?}" ?key = "pwd" ></ fmt:message ></ td > ???????????? < td >< input ?type = "password" ?name = "pwd" /></ td > ???????? </ tr > ???????? < tr > ???????????? < td ></ td > ???????????? < td >< input ?type = "submit" ?value = "<fmt:message?bundle=" ${msg?}"? key = "submit" ></ fmt:message >"/></ td > ???????? </ tr >???? ???? </ table > ?? </ body > </ html > |
?
格式化數值和日期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <%@?page?language="java"?import="java.util.*"?pageEncoding="UTF-8"%> <%@taglib?uri="http://java.sun.com/jsp/jstl/fmt"?prefix="fmt"?%> <!DOCTYPE?HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"> < html > ?? < head > ???? < title >格式化</ title > ???? < meta ?http-equiv = "pragma" ?content = "no-cache" > ???? < meta ?http-equiv = "cache-control" ?content = "no-cache" > ???? < meta ?http-equiv = "expires" ?content = "0" >???? ?? < body > ?????? <!--? ?????????? 格式化金額? ?????????????? 格式:?0.00???保留2為小數,會自動補0 ??????????????????? #.##??保留2為小數,不自動補0 ?????? --> ???? < fmt:formatNumber ?pattern = "0.00" ?value = "100" ?></ fmt:formatNumber >?< br > ???? < fmt:formatNumber ?pattern = "#.##" ?value = "100" ?></ fmt:formatNumber >??< br > ???? < fmt:formatDate ?pattern = "yyyyMMdd" ?value="<%=new?Date()?%>"/>?< br > ???? <% ???????? request.setAttribute("date",?new?Date()); ???? %> ???? < fmt:formatDate ?pattern = "yyyy-MM-dd" ??value = "${date?}" />?< br > ?? </ body > </ html > |