2025-02-17

Java編程語言是第一個設計成為全面支持國際化的語言。從一開始,它就具備瞭進行有效的國際化所必須的一個重要特征:使用Unicode來處理所有字符串。支持Unicode使得在Java編程語言中,編寫程序來操作多種語言的字符串變得異常方便。多數程序員認為進行國際哈需要做的事情就是支持Unicode並在用戶接口中對消息進行翻譯。然而在實際的開發中,國際化一個程序所需要做的絕不僅僅是提供Unicode支持,它還包括日期、時間、貨幣和數字等格式上的差異。
    1.    Locales:
    需要依賴國際化的兩個主要格式化類為NumberFormat和DateFormat,它們在通過工廠方法獲取其實現子類時,都會依賴參數Locale來決定最終被實例化的子類,見如下代碼:
1     public static void main(String[] args) {
2         Locale loc = new Locale("de","DE");
3         NumberFormat currFmt = NumberFormat.getCurrencyInstance(loc);
4         double amt = 123456.78;
5         String result = currFmt.format(amt);
6         System.out.println("The result = " + result);
7     }
8     /* 輸出結果如下:
9         The result = 123.456,78 ? */
    從結果可以看出原有的貨幣格式被轉換為德語的格式瞭。以上例子是從數字格式化為字符串,同樣還可以通過字符串轉換為數字,但是這要依賴parse方法,見如下代碼:
1     public static void main(String[] args) throws ParseException {
2         Locale loc = new Locale("de","DE");
3         NumberFormat fmt = NumberFormat.getNumberInstance(loc);
4         String amt = "123.456,78";
5         double result = fmt.parse(amt).doubleValue();
6         System.out.println("The result = " + result);
7     }
8     /* 輸出結果如下:   
9         The result = 123456.78    */
    在上面的代碼中都是通過直接給出ISO定義的語言和地區代碼縮寫的方式來構造Locale對象的,事實上Java中提供瞭一組預定義的Locale靜態對象來表示不同的語言和地區的Locale實例,如:
    Locale.CANADA
    Locale.CANADA_FRENCH
    Locale.CHINA
    Locale.FRANCE
    Locale.GERMANY
    Locale.ITALY
    Locale.JAPAN
    Locale.KOREA
    …
    以下的僅設定瞭語言而沒有設定位置:
    Locale.CHINESE
    Locale.ENGLISH
    Locale.FRENCH
    Locale.GERMAN
    Locale.ITALIAN
    …
    以下再給出幾個關於Locale的示例代碼:
 1     //設置缺省國際化Locale,註意:該操作隻是修改當前應用程序的
 2     //本地化,而不是修改當前操作系統的。
 3     public static void main(String[] args) {
 4         Locale.setDefault(Locale.FRANCE);
 5         DateFormat df = DateFormat.getInstance();
 6         NumberFormat nf = NumberFormat.getInstance();
 7         System.out.println(df.format(new Date()));
 8         System.out.println(nf.format(123.4567));
 9     }
10     /* 輸出結果如下:
11         26/08/11 23:28
12         123,457    */
13    
14     //獲取當前機器支持語言的列表
15     public static void main(String[] args) {
16         Locale[] locales = Locale.getAvailableLocales();
17         for (Locale loc : locales)
18             System.out.println(loc.getDisplayName());
19     }
    2.    數字格式:
 1     //將數組中的數字轉換為指定的美國本地化顯示格式
 2     public static void main(String[] args) {
 3         int data[] = { 100, 1000, 10000, 1000000 };
 4         NumberFormat nf = NumberFormat.getInstance(Locale.US);
 5         for (int i = 0; i < data.length; ++i) {
 6             System.out.println(data[i] + "\t" + nf.format(data[i]));
 7         }
 8     }
 9     //格式化BigDecimal   
10     public static void main(String[] args) {
11         StringBuffer buffer = new StringBuffer();
12         Locale it = Locale.ITALY;
13         Locale.setDefault(it);
14         BigDecimal rate = new BigDecimal(".03250000");
15         BigDecimal months = new BigDecimal("12");
16         BigDecimal monthlyRate = rate.pide(months, BigDecimal.ROUND_HALF_DOWN);
17         NumberFormat pf = new DecimalFormat("#,##0.00000%");
18         buffer.append("Annual rate : " + pf.format(rate.doubleValue()) + "\n");
19         buffer.append("Monthly rate: " + pf.format(monthlyRate.doubleValue()) + "\n");
20         BigDecimal balance = new BigDecimal("10000.0000");
21         NumberFormat nf = NumberFormat.getCurrencyInstance();
22         for (int i = 0; i < 12; i++) {
23             BigDecimal interest = balance.multiply(monthlyRate);
24             balance = balance.add(interest);
25             buffer.append("Balance : " + nf.format(balance.doubleValue()) + "\n");
26         }
27         System.out.println(buffer.toString());
28     }   
29     //格式化數字格式中主要的3中表示方式:數字、貨幣和百分比
30     public class MyTest {
31         static public void displayNumber(Locale currentLocale) {
32             Integer quantity = new Integer(123456);
33             Double amount = new Double(345987.246);
34             NumberFormat numberFormatter;
35             String quantityOut;
36             String amountOut;
37             numberFormatter = NumberFormat.getNumberInstance(currentLocale);
38             quantityOut = numberFormatter.format(quantity);
39             amountOut = numberFormatter.format(amount);
40             System.out.println(quantityOut + "   " + currentLocale.toString());
41             System.out.println(amountOut + "   " + currentLocale.toString());
42         }
43    
44         static public void displayCurrency(Locale currentLocale) {
45             Double currency = new Double(9876543.21);
46             NumberFormat currencyFormatter;
47             String currencyOut;
48             currencyFormatter = NumberFormat.getCurrencyInstance(currentLocale);
49             currencyOut = currencyFormatter.format(currency);
50             System.out.println(currencyOut + "   " + currentLocale.toString());
51         }
52    
53         static public void displayPercent(Locale currentLocale) {
54             Double percent = new Double(0.75);
55             NumberFormat percentFormatter;
56             String percentOut;
57             percentFormatter = NumberFormat.getPercentInstance(currentLocale);
58             percentOut = percentFormatter.format(percent);
59             System.out.println(percentOut + "   " + currentLocale.toString());
60         }
61    
62         public static void main(String[] args) {
63             Locale[] locales = { new Locale("fr", "FR"),
64                     new Locale("de", "DE"),
65                     new Locale("en", "US") };
66             for (int i = 0; i < locales.length; i++) {
67                 System.out.println();
68                 displayNumber(locales[i]);
69                 displayCurrency(locales[i]);
70                 displayPercent(locales[i]);
71             }
72         }
73     }
    3.    日歷格式:
 1     //從不同的locale獲取每周中的哪一天為周的第一天,並顯示
 2     //不同locale針對星期的顯示名稱。
 3     public static void main(String[] args) {
 4         Locale usersLocale = Locale.getDefault();
 5
 6         DateFormatSymbols dfs = new DateFormatSymbols(usersLocale);
 7         String weekdays[] = dfs.getWeekdays();
 8         Calendar cal = Calendar.getInstance(usersLocale);
 9         //獲取不同地區定義的哪一天是每周的第一天
10         int firstDayOfWeek = cal.getFirstDayOfWeek();
11         int dayOfWeek;
12         //根據不同的每周第一天,遍歷並顯示不同地區針對星期的名稱。
13         for (dayOfWeek = firstDayOfWeek; dayOfWeek < weekdays.length; dayOfWeek++)
14             System.out.println(weekdays[dayOfWeek]);
15
16         for (dayOfWeek = 0; dayOfWeek < firstDayOfWeek; dayOfWeek++)
17             System.out.println(weekdays[dayOfWeek]);
18     }
19     //比較日本時區時間和本地時區時間
20     public static void main(String[] args) {
21         Calendar local = Calendar.getInstance();
22         Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));
23         japanCal.setTimeInMillis(local.getTimeInMillis());
24         int jpHour = japanCal.get(Calendar.HOUR); // 3
25         int jpMinutes = japanCal.get(Calendar.MINUTE); // 0
26         int jpSeconds = japanCal.get(Calendar.SECOND); // 0
27         System.out.println("Japan's time is Hour = " + jpHour + "\tMinutes = "
28                 + jpMinutes + "\tSeconds = " + jpSeconds);
29         int localHour = local.get(Calendar.HOUR); // 3
30         int localMinutes = local.get(Calendar.MINUTE); // 0
31         int localSeconds = local.get(Calendar.SECOND); // 0
32         System.out.println("Local's time is Hour = " + localHour + "\tMinutes = "
33                 + localMinutes + "\tSeconds = " + localSeconds);
34     }
    4.    日期格式:
 1     //定義指定的日期格式化格式,再根據locale的不同,打印出不同的日期名稱。
 2     public static void main(String[] args) {
 3         Locale locale = Locale.ENGLISH;
 4         //SimpleDateFormat對象的構造函數中,如果沒有顯示的傳入locale對象,
 5         //該對象在解析和格式化的過程中將使用缺省的本地化對象。
 6         DateFormat formatter = new SimpleDateFormat("E, dd MMM yyyy", locale);
 7         DateFormat formatter2 = new SimpleDateFormat("HH:mm:ss zzzz", locale);
 8         System.out.println("Result = " + formatter.format(new Date()));
 9         System.out.println("Result2 = " + formatter2.format(new Date()));
10         //定義指定格式的日期格式化對象,在結合Locale對象去格式化當前時間。
11         Date date = new Date();
12         String s = DateFormat.getTimeInstance(DateFormat.SHORT, locale).format(date);
13         System.out.println(s);
14        
15         //使用缺省的本地化locale格式化日期和數字,這裡DateFormat和NumberFormat工廠方法
16         //將會根據不同的locale來實例化不同的DateFormat和NumberFormat的實現類,然而這些
17         //邏輯對使用者是完全透明的。
18         DateFormat df = DateFormat.getInstance();
19         NumberFormat nf = NumberFormat.getInstance();
20         System.out.println(df.format(new Date()));
21         System.out.println(nf.format(123.4567));       
22     }
23     //根據不同的時間Pattern、日期Pattern、日期時間Pattern,連同不同的Locale參數來
24     //構造出DateFormat的實現子類,在格式化指定的日期對象。
25     public class MyTest {
26         static public void displayDate(Locale currentLocale) {
27             DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT,
28                     currentLocale);
29             Date today = new Date();
30             String dateOut = dateFormatter.format(today);
31             System.out.println(dateOut + "   " + currentLocale.toString());
32         }
33    
34         static public void showBothStyles(Locale currentLocale) {
35             int[] styles = { DateFormat.DEFAULT, DateFormat.SHORT,
36                     DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL };
37             System.out.println("Locale: " + currentLocale.toString());
38             Date today = new Date();
39             for (int k = 0; k < styles.length; k++) {
40                 DateFormat formatter = DateFormat.getDateTimeInstance(styles[k], styles[k],
41                         currentLocale);
42                 String result = formatter.format(today);
43                 System.out.println(result);
44             }
45         }
46    
47         static public void showDateStyles(Locale currentLocale) {
48             Date today = new Date();
49             int[] styles = { DateFormat.DEFAULT, DateFormat.SHORT,
50                     DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL };
51             System.out.println("Locale: " + currentLocale.toString());
52             for (int k = 0; k < styles.length; k++) {
53                 DateFormat formatter = DateFormat.getDateInstance(styles[k], currentLocale);
54                 String result = formatter.format(today);
55                 System.out.println(result);
56             }
57         }
58    
59         static public void showTimeStyles(Locale currentLocale) {
60             Date today = new Date();
61             int[] styles = { DateFormat.DEFAULT, DateFormat.SHORT,
62                     DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL };
63             System.out.println("Locale: " + currentLocale.toString());
64             for (int k = 0; k < styles.length; k++) {
65                 DateFormat formatter = DateFormat.getTimeInstance(styles[k], currentLocale);
66                 String result = formatter.format(today);
67                 System.out.println(result);
68             }
69         }
70    
71         static public void main(String[] args) {
72             Locale[] locales = { Locale.CHINA,new Locale("en", "US") };
73             for (int i = 0; i < locales.length; i++)
74                 displayDate(locales[i]);
75             showDateStyles(new Locale("en", "US"));
76             showDateStyles(Locale.CHINA);
77             showTimeStyles(new Locale("en", "US"));
78             showTimeStyles(Locale.CHINA);
79             showBothStyles(new Locale("en", "US"));
80             showBothStyles(Locale.CHINA);
81         }
82     }
    5.    字符排序:
    大多數程序員都知道如何使用String類中的compareTo方法對字符串進行比較。但是由於大小寫字符的ASCII值之間的差異,既小寫字符總是大於大寫字符,因此很多時候排序的結果並非程序員所真正希望得到的。然而有些時候,排序的問題不僅僅被大小寫的問題所困擾,使用不同的本地化(Locale)對象,得到的排序規則往往也是不同的,比如在有些語言中存在重音符,其值更是大於小寫字符,基於這樣的排序結果也就失去的排序的真正意義。在Java中提供瞭Collator對象(Comparator的實現類),因此在當需要對字符串進行排序時,可以使用該類的工廠方法針對不同的Locale生成一個Collator的子類,之後在傳給如Collections.sort這樣的排序方法來完成實際的排序,如下例:
 1     static public void main(String[] args) {
 2         List<String> fruits = new ArrayList<String>();
 3         fruits.add("A");
 4         fruits.add("é");
 5         fruits.add("C");
 6         fruits.add("D");
 7         fruits.add("A");
 8         Collator collator = Collator.getInstance(Locale.US);
 9         Collections.sort(fruits, collator);
10         for (int i = 0; i < fruits.size(); i++) {
11             String fruit = fruits.get(i);
12             System.out.println("Fruit = " + fruit);
13         }
14     }
15     /*    結果如下:
16         Fruit = A
17         Fruit = A
18         Fruit = C
19         Fruit = D
20         Fruit = é
21     */
    在Collator中提供瞭不同的排序強度,字符間的差別主要區分為PRIMARY、SECONDARY和TERTIARY三種,PRIMARY差別將主要關註字符間的主要差異,如A和Z之間就是主要的差異,而é和"É"(法語)之間的差別為SECONDARY,最後"A"和"a"之間的差異為TERTIARY。由此看出,排序強度越高,其區分字符間的差異性就越差,見下例:
 1     static public void main(String[] args) {
 2         String s1 = "é";
 3         String s2 = "É";
 4
 5         Collator frCollator = Collator.getInstance(Locale.FRANCE);
 6         System.out.println("The current strength is PRIMARY.");
 7         frCollator.setStrength(Collator.PRIMARY);
 8         if (frCollator.compare(s1, s2) == 0)
 9             System.out.println("s1 = s2");
10         System.out.println("The current strength is SECONDARY.");
11         frCollator.setStrength(Collator.SECONDARY);
12         if (frCollator.compare(s1, s2) == 0)
13             System.out.println("s1 = s2");
14         System.out.println("The current strength is TERTIARY.");
15         frCollator.setStrength(Collator.TERTIARY);
16         if (frCollator.compare(s1, s2) == 0)
17             System.out.println("s1 = s2");
18     }
19     /*    輸出結果如下:
20         The current strength is PRIMARY.
21         s1 = s2
22         The current strength is SECONDARY.
23         s1 = s2
24         The current strength is TERTIARY.   
25     */
    從輸出結果中可以看出,當排序強度將為TERTIARY時,這兩個字符將被視為不同的字符瞭。
    6.    消息格式化:
 1     //這裡演示瞭MessageFormat的最基本用法:
 2     // {0,time}: 0表示第0個占位符,time表示該占位符的格式為時間,如不指定style,按缺省格式顯示。
 3     // {1,number}: 1表示第1個占位符,number表示該占位符為數字。
 4     static public void main(String[] args) {
 5         String pattern = "The time is {0,time} and your lucky number is {1,number}.";
 6         MessageFormat format = new MessageFormat(pattern);
 7         Object objects[] = {new Date(),new Integer((int)(Math.random() * 1000))};
 8         String formattedOutput = format.format(objects);
 9         System.out.println(formattedOutput);
10
11         pattern = "The datetime is {0} and your lucky number is {1}.";
12         format = new MessageFormat(pattern);
13         //指定Locale
14         format.setLocale(Locale.US);
15         formattedOutput = format.format(objects);
16         System.out.println(formattedOutput);
17         format.setLocale(Locale.CHINA);
18         formattedOutput = format.format(objects);
19         System.out.println(formattedOutput);
20     }
21     /*    輸出結果如下:
22         The time is 10:47:47 and your lucky number is 97.
23         The datetime is 8/28/11 10:47 AM and your lucky number is 97.
24         The datetime is 11-8-28 上午10:47 and your lucky number is 97.
25     */
    Java針對Message中占位符的type,不僅提供瞭常規的number、time和date,還提供瞭choice格式,見如下例句:
    String pattern = "On {2,date,long},{0} destroyed {1} houses and caused {3,number,currency} of damage";
    註意占位符{1},盡管沒有明確標註,仍然可以推測出它是number類型的。這裡存在的主要問題是{1}後面的houses是復數格式,因此如果參數設置為1,則不符合英文的語法1 houses。再有就是如果參數設置為0,則更加奇怪"0 houses"。根據英文的語法規則,我們期待的格式是如果數量>=2,顯示n houses,如果等於1,顯示1 house,如果<=0,顯示no house。如何完成這個功能呢?這裡我們可以利用Java中給占位符提供的另外一種type: choice。其語法規則如下:
    一個選擇格式是由一個序列對組成,每一個對包括一個下限和一個格式字符串,下限和格式字符串由一個#符號分隔,對與對之間由符號|分隔。如:
    {1,choice,0#no house|1#one house|2#{1} houses}
     如果不使用選擇格式,又希望實現剛剛說到的邏輯,就需要手工進行數量的判斷,再根據數量的不同定義不同的pattern,如果使用選擇格式,代碼將會更加清晰明確,如:
    String pattern = "On {2,date,long},{0} destroyed {1,choice,0#no house|1#one house|2#{1} houses} houses and caused {3,number,currency} of damage";
     7.    字符集:
     在進行byte和char之間的轉換時,不同編碼方式的字符集提供瞭不同的編碼(encode)和解碼(decode)規則,見如下代碼:
 1     public class MyTest {
 2         public static void print(ByteBuffer bb) {
 3             while (bb.hasRemaining())
 4                 System.out.print(bb.get() + " ");
 5             System.out.println();
 6             bb.rewind();
 7         }
 8    
 9         public static void main(String[] args) {
10             ByteBuffer bb = ByteBuffer.wrap(new byte[] { 0, 0, 0, 0, 0, 0, 0,
11                     (byte) 'a' });
12             System.out.println("Initial Byte Buffer");
13             print(bb);
14             //提供瞭幾種常用的字符集
15             Charset[] csets = { Charset.forName("UTF-16LE"),
16                     Charset.forName("UTF-16BE"), Charset.forName("UTF-8"),
17                     Charset.forName("US-ASCII"), Charset.forName("ISO-8859-1") };
18             for (int i = 0; i < csets.length; i++) {
19                 System.out.println(csets[i].name() + ":");
20                 //編碼顯示
21                 print(csets[i].encode(bb.asCharBuffer()));
22                 //解碼用於下一次迭代
23                 csets[i].decode(bb);
24                 bb.rewind();
25             }
26         }
27     }
28     //根據指定的字符集,將數據在CharBuffer和ByteBuffer之間做轉換(編碼和解碼)
29     public static void main(String[] args) throws CharacterCodingException {
30         //由於有中文的存在,因此這裡需要是用UTF-8的字符集,如果使用其他
31         //的西方字符集會導致encode拋出異常。
32         Charset charset = Charset.forName("UTF-8");
33         // An engine that can transform a sequence of bytes in a specific
34         // charset into a sequence of sixteen-bit Unicode characters.
35         // from byte to unicode
36         CharsetDecoder decoder = charset.newDecoder();
37         // An engine that can transform a sequence of sixteen-bit Unicode
38         // characters into a sequence of bytes in a specific charset.
39         // from unicode to byte
40         CharsetEncoder encoder = charset.newEncoder();
41         ByteBuffer bbuf = ByteBuffer.allocate(1024);
42         CharBuffer cbuf = CharBuffer.allocate(1024);
43         String tmp = "HelloWorld123你好";
44         cbuf.put(tmp);
45         cbuf.flip();
46         //或者直接給CharBuffer賦值,如:
47         //cbuf = CharBuffer.wrap("HelloWorld123你好");
48         //該語句相當於上面3條語句的功能。
49        
50         //註:在encode內部已經調用瞭bbuf.flip(),如果外部重復調用,會導致後面的
51         //decode返回空值。
52         bbuf = encoder.encode(cbuf);
53         byte[] buf = bbuf.array();
54         String s = new String(buf,charset);
55         System.out.println("ByteBuffer = " + s);
56         //註:在decode內部已經調用瞭cbuf.flip(),如果外部重復調用,會導致後面
57         //打印空值。
58         cbuf = decoder.decode(bbuf);
59         System.out.println("CharBuffer = " + cbuf.toString());
60     }
    8.    資源包:
    經常會遇到這樣的情形,我們應用程序中的大量字符串信息需要被翻譯成各種不同的語言,如英文、德文等。我們常用的方式是自定義包含各種不同語言信息的文件,並通過文件名來標識其所屬的語種。我們的應用程序在根據當前不同的locale來選擇不同的語言資源文件。在Windows的MFC中,是通過一種被稱為字符表的資源來存儲這些信息的。在Java中,JDK同樣提供瞭其自身的支持–資源包。
    和我們想象的一樣,JDK也是通過將不同語言的字符串信息存放在不同的資源文件中,同時也定義瞭語言資源文件的文件命名規則:包名_語言_國傢,如MyProgramStrings_de_DE。如果locale = new Locale("de","DE");該資源文件將會被加載。既然Java已經為我們提供瞭這樣的方法,我們還是應該充分的利用這一規則。事實上,和我們預想的非常相似,該資源文件也是以鍵值對的方式存儲資源信息的,如下面的德文和英文資源文件:
    File: MessageBundle_en_US.properties
    planet = Mars
    template = At {2,time,short} on {2,date,long}, we detected {1,number,integer} spaceships on the planet {0}.
   
    File: MessageBundle_de_DE.properties
    planet = Mars
    template = Um {2,time,short} am {2,date,long} haben wir {1,number,integer} Raumschiffe auf dem Planeten Mars entdeckt.
    將以上兩個文件copy到工程的bin目錄下,再執行下面的示例代碼:
 1     public class MyTest {
 2         static void displayMessage(Locale currentLocale) {
 3             System.out.println("currentLocale = " + currentLocale.toString());
 4             //getBundle的第一個參數是資源文件的前綴,後綴則根據Locale來定義。
 5             ResourceBundle messages = ResourceBundle.getBundle("MessageBundle",currentLocale);
 6             Object[] messageArguments = { messages.getString("planet"),
 7                     new Integer(7), new Date() };
 8             MessageFormat formatter = new MessageFormat("");
 9             formatter.setLocale(currentLocale);
10             formatter.applyPattern(messages.getString("template"));
11             String output = formatter.format(messageArguments);
12             System.out.println(output);
13         }
14    
15         public static void main(String[] args) {
16             displayMessage(new Locale("en", "US"));
17             displayMessage(new Locale("de", "DE"));
18         }
19     }   
20     /*    輸出結果如下:
21         currentLocale = en_US
22         At 9:27 PM on August 29, 2011, we detected 7 spaceships on the planet Mars.
23         currentLocale = de_DE
24         Um 21:27 am 29. August 2011 haben wir 7 Raumschiffe auf dem Planeten Mars entdeckt.
25     */   
     以下示例結合瞭ChoiceFormat和ResourceBundle,資源文件內容如下:
    File: ChoiceBundle_en_US.properties
    noFiles = are no files
    oneFile = is one file
    multipleFiles = are {2} files
    pattern = There {0} on {1}.
   
    File: ChoiceBundle_fr_FR.properties
    noFiles = n' y a pas des fichiers
    oneFile = y a un fichier
    multipleFiles = y a {2} fichiers
    pattern = Il {0} sur {1}.
    見代碼如下:
 1     public class MyTest {
 2         static void displayMessages(Locale currentLocale) {
 3             System.out.println("currentLocale = " + currentLocale.toString());
 4             //1. 根據Locale的不同,獲取不同的資源文件
 5             ResourceBundle bundle = ResourceBundle.getBundle("ChoiceBundle",currentLocale);
 6             MessageFormat messageForm = new MessageFormat("");
 7             //2. 給MessageFormat對象設定locale,便於資源文件的定位。
 8             messageForm.setLocale(currentLocale);
 9             //3. 設定ChoiceFormat下限部分
10             double[] fileLimits = { 0, 1, 2 };
11             //4. 從資源文件中讀取指定的key/value,之後再初始化ChoiceFormat的選擇部分。
12             String[] fileStrings = { bundle.getString("noFiles"),
13                     bundle.getString("oneFile"), bundle.getString("multipleFiles") };
14             ChoiceFormat choiceForm = new ChoiceFormat(fileLimits, fileStrings);
15             //5. 根據資源文件中“pattern”鍵值對來定義MessageFormat的pattern部分。
16             String pattern = bundle.getString("pattern");
17             //6. 定義MessageFormat.pattern的格式信息。
18             Format[] formats = { choiceForm, null, NumberFormat.getInstance() };
19             messageForm.applyPattern(pattern);
20             messageForm.setFormats(formats);
21             //7. 定義和formats對應的格式參數。
22             Object[] messageArguments = { null, "XDisk", null };
23             for (int numFiles = 0; numFiles < 4; numFiles++) {
24                 //8. 重新設定格式參數中第0個和第2個參數的值,該值為被ChoiceFormat利用,
25                 //並根據該參數值的不同選擇不同的Choice字符串來替換。
26                 messageArguments[0] = new Integer(numFiles);
27                 messageArguments[2] = new Integer(numFiles);
28                 //9. 開始格式化瞭。
29                 String result = messageForm.format(messageArguments);
30                 System.out.println(result);
31             }
32         }
33    
34         public static void main(String[] args) {
35             displayMessages(new Locale("en", "US"));
36             displayMessages(new Locale("fr", "FR"));
37         }
38     }
39     /*    輸出結果如下:
40         currentLocale = en_US
41         There are no files on XDisk.
42         There is one file on XDisk.
43         There are 2 files on XDisk.
44         There are 3 files on XDisk.
45         currentLocale = fr_FR
46         Il n' y a pas des fichiers sur XDisk.
47         Il y a un fichier sur XDisk.
48         Il y a 2 fichiers sur XDisk.
49         Il y a 3 fichiers sur XDisk.
50     */
    Java不僅提供瞭資源包文件的方式來包含不同語言的資源信息,還提供瞭資源包類的方式,其命名規則和資源包的規則一致,隻是擴展名由".properties"替換為".java",其內容也從鍵值對的配置文件改為java的代碼文件。資源包中定義的類必須是擴展自ResourceBundle類,使用方式和資源包配置文件的方式完全一致。見下面的示例代碼:
 1     //File: SimpleResourceBundle.java
 2     public class SimpleResourceBundle extends ResourceBundle {
 3         @Override
 4         protected Object handleGetObject(String key) {
 5             if (key.equals("AMMessage"))
 6                 return "早上好";
 7             if (key.equals("PMMessage"))
 8                 return "晚上好";
 9             return null;
10         }
11         @Override
12         public Enumeration getKeys() {
13             StringTokenizer keyTokenizer = new StringTokenizer(keys);
14             return keyTokenizer;
15         }
16         private String keys = "AMMessage PMMessage";
17     }
18     //File: SimpleResourceBundle_en_US.java
19     public class SimpleResourceBundle_en_US extends ResourceBundle {
20         @Override
21         protected Object handleGetObject(String key) {
22             if (key.equals("AMMessage"))
23                 return "Good morning";
24             if (key.equals("PMMessage"))
25                 return "Good evening";
26             return null;
27         }
28         @Override
29         public Enumeration getKeys() {
30             StringTokenizer keyTokenizer = new StringTokenizer(keys);
31             return keyTokenizer;
32         }
33         private String keys = "AMMessage PMMessage";
34     }
35    
36     //調用類代碼如下:
37     public static void main(String[] args) {
38         try {
39             //由於使用缺省的locale,因此在定義資源包類的文件時,可以不包含locale相關的後綴。
40             ResourceBundle rb = ResourceBundle.getBundle("SimpleResourceBundle");
41             System.out.println(rb.getString("AMMessage"));
42             System.out.println(rb.getString("PMMessage"));
43             //由於給ResourceBundle的工廠方法傳入瞭Locale參數,因此會獲取US的資源包綁定類。
44             ResourceBundle rb_US = ResourceBundle.getBundle("SimpleResourceBundle",Locale.US);
45             System.out.println(rb_US.getString("AMMessage"));
46             System.out.println(rb_US.getString("PMMessage"));
47         } catch (MissingResourceException mre) {
48             mre.printStackTrace();
49         }
50     }
51     /*    輸出結果如下:
52         早上好
53         晚上好
54         Good morning
55         Good evening
56     */
    在Java中還提供瞭另外一種更為方便的資源包綁定類的實現方式,既直接擴展ListResourceBundle類,ListResourceBundle讓你把所有資源都放到一個對象數組並提供查詢功能,見如下代碼:
 1     //File: SimpleResourceBundle_de_DE.java
 2     public class SimpleResourceBundle_de_DE extends ListResourceBundle {
 3         public Object[][] getContents() {
 4             return contents;
 5         }
 6    
 7         private static final Object[][] contents = {
 8             {"backgroundColor",Color.black},
 9             {"defaultPaperSize",new double[]{210,297}}
10         };
11     }
12     //File: SimpleResourceBundle_en_US.java
13     public class SimpleResourceBundle_en_US extends ListResourceBundle {
14         public Object[][] getContents() {
15             return contents;
16         }
17    
18         private static final Object[][] contents = {
19             {"backgroundColor",Color.blue},
20             {"defaultPaperSize",new double[]{216,279}}
21         };
22     }
23     //主程序文件
24     public static void main(String[] args) {
25         try {
26             ResourceBundle rb = ResourceBundle.getBundle("SimpleResourceBundle",Locale.GERMANY);
27             Color bg = (Color)rb.getObject("backgroundColor");
28             double[] paperSize = (double[])rb.getObject("defaultPaperSize");
29             System.out.println("Germany Color is " + bg);
30             System.out.println("Germany paperSize is x = " + paperSize[0] + "\ty = " + paperSize[1]);
31             ResourceBundle rb_US = ResourceBundle.getBundle("SimpleResourceBundle",Locale.US);
32             bg = (Color)rb_US.getObject("backgroundColor");
33             paperSize = (double[])rb_US.getObject("defaultPaperSize");
34             System.out.println("US Color is " + bg);
35             System.out.println("US paperSize is x = " + paperSize[0] + "\ty = " + paperSize[1]);
36         } catch (MissingResourceException mre) {
37             mre.printStackTrace();
38         }
39     }
40     /*    輸出結果如下:
41         Germany Color is java.awt.Color[r=0,g=0,b=0]
42         Germany paperSize is x = 210.0    y = 297.0
43         US Color is java.awt.Color[r=0,g=0,b=255]
44         US paperSize is x = 216.0    y = 279.0
45     */   

 作者“Stephen_Liu”
 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *