國際化 ,英文叫 internationalization 單詞太長 ,又被簡稱為 i18n(取頭取尾中間有18個字母)不經大聲呼喊 ,這都行 !接著看什麼是國際化 , 國際化是指讓產品或是程式在無需做出改變的情況下就能夠適應不同語言和地區的需要 。同樣是打招呼在中國你會說 “ 你好 ” ,在美國你會說 “ Hello ” ,你看 ,你已經是 i18n 了 。
在 Java 中實現國際化主要是藉助一個工具類 ResourceBundle ,核心的思想就是 ,對不同的語言環境提供一個不同的資源檔 。所以說先來看看資源檔怎麼定義的 。
定義相應的資源檔 ,我們將資源檔放在一個資源套件(就是平常的一個包)中 ,一個資源套件中每個資源檔必須擁有共同的基名 。除了基名 ,每個檔案的名稱中還必須有標識其本地資訊的附加部分 ,例如 :一個資源套件的基名是 “ message ” ,則與中文(中國)、英文(美國)環境相對應的資源檔名分別為 :
message_zh_CN.properties
message_en_US.properties
這裡需要注意的是 ,資源檔通常採用索引值對的形式 ,並且資源檔中採用的是 properties 格式檔案 ,所以檔案中的所有字元都必須是 ascll 碼 ,不能儲存為中文的 ,Java 中提供 了 native2ascll 工具用於將中文轉化為 ascll 碼 。所以在編寫 properties 檔案的時候寫的是中文 ,一斷行符號就自動被編碼了 。
下面就是具體的編碼了 ,在 Java API 中提供了一個 ResourceBundle 類用於描述一個資源套件 ,並且 ResourceBundle 類提供了相應的靜態方法 getBundle ,這個方法可以根據來訪者的國家地區自動綁定對應的資源檔 。
import java.util.Locale;import java.util.ResourceBundle;public class I18n{ public static void test() { // 設定定製的語言國家代碼 Locale locale1 = new Locale("en_US"); Locale locale2 = Locale.getDefault(); // 獲得資源檔 ResourceBundle rb = ResourceBundle.getBundle("message.i18n.message", locale2); // 獲得相應的key值 String greeting = rb.getString("greeting"); String userInfo = rb.getString("name"); System.out.println(greeting); System.out.println(userInfo); } public static void main(String[] args) { test(); }}//你好//餘6路
以上就是一些固定文本的國際化 ,固定文本包括菜單名 ,導航條 ,系統提示資訊等 ,都是我們手工配置在 properties 檔案中的 ,但有些資料 ,比方說 ,數值 ,貨幣 ,時間 ,日期等由於可能在程式運行時動態產生 ,所以無法像文字一樣簡單地將它們從應用程式中分離出來 ,而需要特殊處理 。Java 提供瞭解決這些問題的 API 。
簡單的說一下 Locale 這個類 ,英語介紹是這樣的
A Locale object represents a specific geographical , political , or cultural region . An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user .
翻譯過來就是說 Locate 對象代表特定的地理 ,政治或文化地區 。需要 Locate 設定執行任務的操作稱為敏感地區( 包含 Locate 的類就是敏感地區 ) ,使用 Locate 為使用者定製資訊 。
關於日期的國際化我們使用工具類 DateFormat ,看一下該類的結構圖 。
DateFormat 有很多不同的構造器 ,而且在構造器中還可以指定不同的時間顯示模式 ,我就不一一示範了 ,下面給出範例程式碼 。
public class DateFormatTest { public static void main(String[] args) throws ParseException { Date date = new Date(); DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.CHINA); String str = df.format(date); System.out.println(str); // 2018-8-6 df = DateFormat.getTimeInstance(DateFormat.LONG, Locale.CHINA); System.out.println(df.format(date)); // 下午07時58分26秒 df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT, Locale.CHINA); System.out.println(df.format(date)); // 2018年8月6日 星期一 下午7:58 // 得到預設的DateFormat df = DateFormat.getInstance(); System.out.println(df.format(date)); // 18-8-6 下午7:58 // 使用DateFormat反向把一個字串格式化成一個日期對象 String dateString = "2018年8月6日 星期一 下午7:58"; DateFormat df2 = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT, Locale.CHINA); Date date2 = df2.parse(dateString); // 這裡可能會有異常,字串的格式和 DateFormat 設定的格式不一致時就會報錯。 System.out.println(date2); // Mon Aug 06 19:58:00 CST 2018 }}
動態文本國際化使用工具類 MessageFormat ,MessageFormat 允許開發人員用預留位置替換掉字串中的敏感性資料( 即國際化相關的資料 )字串中的 {0} {1} {2} {3} 就是預留位置 。
public class MessageFormatTest { public static void main(String[] args) { /* 測試資料 greeting=Welcome name=YJK age=18 pattern={0},{1},your age is {2}. */ ResourceBundle rb = ResourceBundle.getBundle("message.i18n.message_en_US",Locale.US); String greeting = rb.getString("greeting"); String name = rb.getString("name"); String age = rb.getString("age"); // 得到模式字串 String pattern = rb.getString("message"); // 執行個體化MessageFormat對象,並裝載相應的模式字串 MessageFormat format = new MessageFormat(pattern); // format 方法需要一個 Object 的數組。 Object[] params = {greeting, name, age}; // 格式化模式字串,參數數組中指定預留位置相應的替換對象 String string = format.format(params); System.out.println(string); }}//Welcome,YJK,your age is 18.
NumberFormat 類可以將一個數值格式化為符合某個國家地區習慣的數值字串 ,也可以將符合某個國家地區習慣的數值字串解析為對應的數值 。 對應的方法分別是 format 和 parse 。
public class NumberFormatTest { public static void main(String[] args) throws ParseException{ int price = 18; // NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.CHINA); // ¥18.00 // NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US); // $18.00 // NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.JAPAN); // ¥18 // 獲得處理貨幣的 NumberFormat 執行個體對象 NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.FRANCE); // 18,00 € System.out.println(nf.format(price)); String s = "18,00 €"; nf = NumberFormat.getCurrencyInstance(Locale.FRANCE); // 以法國的貨幣來解析 18,00 € 得到的結果是 18.0 System.out.println(nf.parse(s).doubleValue()); double d = 0.1; // 獲得處理整數的NumberFormat執行個體對象。 nf = NumberFormat.getIntegerInstance(); // 0 // 獲得處理百分比數值的 NumberFormat 執行個體對象 nf = NumberFormat.getPercentInstance(); System.out.println(nf.format(d)); // 10% }}