國際化之MessageFormat與占位符


  如果一個字符串文本中包含了多個與國際化相關的數據,可以使用MessageFormat類對這些數據進行批量處理。

  例如:

  在201619的時候,一場台風導致了500間房屋的摧毀和1000000元人民幣的損失。

  在上面這句話中,包含了時間、數字和貨幣等多個與國家化相關的數據,已經用下划線標出,而我們可以使用MessageFormat對這句話中多個數據進行批量處理。

  要想使用MessageFormat進行批量處理,就要使用到占位符,用占位符替換上面的數據(不需要寫死的數據或者與國際化相關的數據)。占位符由花括號{}和在花括號中的數字組成,數字代表這是第幾個占位符,現在我們對上面的那個示例使用占位符:

  在{0}的時候,一場台風導致了{1}間房屋的摧毀和{2}元人民幣的損失。

   經過占位符修改的字符串文本也稱為模式字符串,如上面這句話,有了模式字符串后,我們需要一個對象數組來指定每個占位符對應的數據,在數組中的位置就對應着其相同位置的占位符。現在擁有了模式字符串和對象數組后,我們就可以使用MessageFormat對象的format方法,將數組中的數據一一對應到占位符上了。

  占位符由三種書寫格式:

  ① {index}:index為0~9之間的數字,對應對象數組中的位置。

  ② {index,formatType}:index為0~9之間的數字,formatType為參數的格式化類型

  ③  {index,formatType,formatStyle}:formatStyle為參數的格式化樣式。

有關占位符的使用稍后說明。

         注:在創建MessageFormat對象時可以直接將模式字符串以參數傳入構造器,也可以直接使用MessageFormat的靜態方法format(String pattern , Object …params)只執行一次。

 

例1:

1     String pattern = "在{0}的時候,一場台風導致了{1}間房屋的摧毀和{2}元人民幣的損失。";
2     Object[] params = {new Date(),500,1000000};
3     MessageFormat mf = new MessageFormat(pattern);
4     String content = mf.format(params);
5     System.out.println(content);
View Code

上述代碼等同於:

1     String pattern = "在{0}的時候,一場台風導致了{1}間房屋的摧毀和{2}元人民幣的損失。";
2     Object[] params = {new Date(),500,1000000};
3     String content = MessageFormat.format(pattern, params);
4     System.out.println(content);
View Code

輸出:

  

結果就是:在16-1-9 下午7:56的時候,一場台風導致了500間房屋的摧毀和1,000,000元人民幣的損失。

  可以看到在對應的占位符上,我們用對象數組中的內容替代了占位符。但是似乎和最開始我們規定的字符串文本有點不同?

 最開始我們規定的文本:

  在201619的時候,一場台風導致了500間房屋的摧毀和1,000,000元人民幣的損失。

例1占位符被替代后的文本:

  在16-1-9 下午7:56的時候,一場台風導致了500間房屋的摧毀和1,000,000元人民幣的損失。

 

  可以看到日期格式和貨幣格式跟我們規定的不同,而這一點可以想到前一篇博客我們學到的DateFormat和NumberFormat中可以指定日期/時間或貨幣的輸出格式。而這里我們要先了解下占位符:

  占位符有三種書寫格式:

  ① {index}:index為0~9之間的數字,對應對象數組中的位置。

  ② {index,formatType}:index為0~9之間的數字,formatType為參數的格式化類型

  ③ {index,formatType,formatStyle}:formatStyle為參數的格式化樣式,該樣式必須是格式化類型相匹配的合法模式,或表示合法模式的字符串。

  在Java的API關於MessageFormat中,已經定義了formatType和formatStyle能使用的參數有哪些:

  

  通過上圖我們就明白了formatType和formatStyle到底能使用哪些值,比如formatType如果我選了“date”,就代表該占位符是一個日期,那么可以指定formatStyle(使用占位符第三種書寫方式),也就是DateFormat的日期顯示格式;當然也可以不指定(使用占位符第二種書寫方式),那么該DateFormat就采用默認(MEDIUM)的日期顯示格式。如果formatType選擇為“number”也是一樣的道理。如果對DateFormat和NumberFormat不熟悉的可以看上一篇博客《國際化之DateFormat、NumberFormat》 。

總結:

  formatType如果使用“date”,那么就是采用DateFormat類的getDateInstance方法獲取只關於日期的DateFormat類實例對象,根據formatStyle來獲取日期輸出格式。

  formatType如果使用“time”,那么就是采用DateFormat類的getTimeInstance方法獲取只關於時間的DateFormat類實例對象,根據formatStyle來獲取時間輸出格式。

  formatType如果使用“number”,如果也指定了formatStyle為“currency”,那么就是調用了NumberFormat的getCurrencyInstance方法獲取有關於貨幣格式的NumberFormat類對象。

  當然通過上圖還可以獲得很多對象,還有其他類型的格式轉換器類,比如SimpleDateFormat等等,具體根據上圖和實際情況滿足需求即可。

 

例2:

1     String pattern = "在{0,date,long}的時候,一場台風導致了{1}間房屋的摧毀和{2,number,currency}元人民幣的損失。";
2     Object[] params = {new Date(),500,1000000};
3         
4     String content = MessageFormat.format(pattern, params);
5     System.out.println(content);
View Code

輸出:

  

結果就是:在2016年1月9日的時候,一場台風導致了500間房屋的摧毀和¥1,000,000.00元人民幣的損失。

  可以看到這就跟我們的最開始定義的字符串文本相同了。

  占位符在框架中是經常被使用到的,當然占位符一般不會在程序代碼中被使用,而是在資源文件properties被使用,這是想Struts2這樣的框架經常被使用到的,結合前兩篇的《國際化之ResourceBundle》,如果模式字符串在properties中使用,那么我們需要通過ResourceBundle通過資源文件的基名獲取對象,並使用getString方法獲取模式字符串,最后只要使用MessageFormat像上面一樣處理就行了。

 

例3:

  在工程中用一個包來封裝一組資源包,該組資源包中默認的資源配置文件基名為“MessageResource”,同時配有中文和英文兩個資源配置文件,如下圖所示:

  

在默認的資源文件“MessageResource.properties”中定義的內容如下:

  

在中文資源文件“MessageResource_zh.properties”中定義的內容如下:

  

  英文資源文件和默認資源文件中的內容是一樣的,這里就不再貼出。

  因為我們將資源文件放在包中,所以基名應該包括包名,這一點在博文《《國際化之ResourceBundle》中已經說明。

 

在程序中代碼如下:

1     ResourceBundle bundle = ResourceBundle.getBundle("com.fjdingsd.resource.MessageResource",Locale.CHINA);
2     String pattern = bundle.getString("message");  //獲取模式字符串
3     Object[] params = {new Date(),500,10000000};
4         
5     String content = MessageFormat.format(pattern, params);
6     System.out.println(content);
View Code

輸出:在16-1-9 下午8:59的時候,一場台風導致了500間房屋的摧毀和10,000,000元人民幣的損失。

注意:⑴ 這里占位符對應的地方格式並不友好,這是因為占位符沒有使用特定的格式,參見例2。

   ⑵ 在ResourceBundle獲取對象中使用到了Locale是以中國的形式,因此最后輸出的是中文,如果想以美國作為Locale,那么將會輸出英文:

修改代碼為:

1     ResourceBundle bundle = ResourceBundle.getBundle("com.fjdingsd.resource.MessageResource",Locale.US);
2     String pattern = bundle.getString("message"); //獲取模式字符串
3     Object[] params = {new Date(),500,10000000};
4         
5     String content = MessageFormat.format(pattern, params);
6     System.out.println(content);
View Code

輸出:On 16-1-9 下午9:03, a typhoon destory 500 houses and caused 10,000,000 of damage.

  看上去似乎很正確,但是在這些英文中出現了中文,而且是在占位符對應的地方,說明我們還未將MessageFormat對象的代表的語言國家環境修改,最終代碼如下:

1     ResourceBundle bundle = ResourceBundle.getBundle("com.fjdingsd.resource.MessageResource",Locale.US);
2     String pattern = bundle.getString("message");  //獲取模式字符串
3     Object[] params = {new Date(),500,10000000};
4         
5     MessageFormat mf = new MessageFormat(pattern, Locale.US);
6     String content = mf.format(params);
7     System.out.println(content);
View Code

輸出:On 1/9/16 9:07 PM, a typhoon destory 500 houses and caused 10,000,000 of damage.

 

 

 

       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM