國際化(i18n)

國際化開發概述

軟件的國際化:軟件開發時,要使它能同時應對世界不一樣地區和國家的訪問,並針對不一樣地區和國家的訪問,提供相應的、符合來訪者閱讀習慣的頁面或數據。 
國際化(internationalization)又稱爲i18n(讀法爲i18n,聽說是由於internationalization(國際化)這個單詞從i到n之間有18個英文字母,i18n的名字由此而來)html

合格的國際化軟件

軟件實現國際化,需具有如下兩個特徵:java

  • 對於程序中固定使用的文本元素,例如菜單欄、導航條等使用的文本元素、或錯誤提示信息,狀態信息等,須要根據來訪者的地區和國家,選擇不一樣語言的文本爲之服務。
  • 對於程序動態產生的數據,例如(日期,貨幣等),軟件應能根據當前所在的國家或地區的文化習慣進行顯示。
固定文本元素的國際化

對於軟件中的菜單欄、導航條、錯誤提示信息,狀態信息等這些固定不變的文本信息,能夠把它們寫在一個properties文件中,並根據不一樣的國家編寫不一樣的properties文件。這一組properties文件稱之爲一個資源包。編程

建立資源包和資源文件

一個資源包中的每一個資源文件都必須擁有共同的基名。除了基名,每一個資源文件的名稱中還必須有標識其本地信息的附加部分。例如:一個資源包的基名是「MessageResource」,則與中文、英文環境相對應的資源文件名則爲: 「MessageResource_zh.properties」 「MessageResource_en.properties」 
這裏寫圖片描述 
每一個資源包都應有一個默認資源文件,這個文件不帶有標識本地信息的附加部分。若ResourceBundle對象在資源包中找不到與用戶匹配的資源文件,它將選擇該資源包中與用戶最相近的資源文件,若是再找不到,則使用默認資源文件。例如:MessageResource.properties。數組

資源文件的書寫格式

資源文件的內容一般採用」關鍵字=值」的形式,軟件根據關鍵字檢索值顯示在頁面上。一個資源包中的全部資源文件的關鍵字必須相同,值則爲相應國家的文字。而且資源文件中採用的是properties格式文件,因此文件中的全部字符都必須是ASCII字碼,屬性(properties)文件是不能保存中文的,對於像中文這樣的非ACSII字符,須先進行編碼。 
例如: 
國際化的中文環境的properties文件: 
這裏寫圖片描述 
國際化的英文環境的properties文件: 
這裏寫圖片描述 
java提供了一個native2ascII工具用於將中文字符進行編碼處理,native2ascII的用法以下所示: 
這裏寫圖片描述瀏覽器

編程實現固定文本的國際化

在JavaAPI中提供了一個ResourceBundle類用於描述一個資源包,而且 ResourceBundle類提供了相應的方法getBundle,這個方法能夠根據來訪者的國家地區自動獲取與之對應的資源文件予以顯示。 
ResourceBundle類提供了一個靜態方法getBundle,該方法用於裝載資源文件,並建立ResourceBundle實例:安全

Locale currentLocale = Locale.getDefault();
ResourceBundle myResources =ResourceBundle.getBundle(basename, currentLocale);
  • 1
  • 2
  • basename爲資源包基名(且必須爲完整路徑)。
  • 若是與該locale對象匹配的資源包子類找不到。通常狀況下,則選用默認資源文件予以顯示。

加載資源文件後, 程序就能夠調用ResourceBundle實例對象的getString方法獲取指定的資源信息名稱所對應的值。jsp

String value =  myResources.getString(「key");
  • 1

範例:根據國家地區自動獲取與之對應的資源文件。ide

public class Demo1 {

    public static void main(String[] args) {

        // 根據資源包基名和語言環境加載對應的語言資源文件
        ResourceBundle bundler = ResourceBundle.getBundle("cn.itcast.resource.MessageResource",Locale.CANADA);

        String username = bundler.getString("username");
        String password = bundler.getString("password");

        System.out.println(username);
        System.out.println(password);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

運行結果: 
這裏寫圖片描述工具

在WEB應用中實現固定文本的國際化

以下所示:ui

<%@page import="java.util.Locale"%>
<%@page import="java.util.ResourceBundle"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>國際化的頁面</title>
</head>
<body>
    <a href="/day12/login.jsp?language=zh">中文(網頁)</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <a href="/day12/login.jsp?language=en">English(pages)</a>

    <%
        String language = request.getParameter("language");
        if(language == null || language.equals("")) {
            language = "zh";
        }   
        Locale locale = new Locale(language); // Locale表明當前語言地區和國家

        ResourceBundle bundle = ResourceBundle.getBundle("cn.itcast.resource.MessageResource",locale);
    %>
    <form action="">
        <%=bundle.getString("username") %><input type="text" name="username"><br/>
        <%=bundle.getString("password") %><input type="password" name="password"><br/>
        <input type="submit" value="<%=bundle.getString("submit") %>">
    </form>
</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
  • 26
  • 27
  • 28
  • 29
  • 30

運行結果: 
這裏寫圖片描述 
一樣一個頁面,在不一樣語言環境的瀏覽器下顯示出了不一樣的語言文字效果,這樣就實現了固定文本的國際化。

動態數據的國際化

數值,貨幣,時間,日期等數據因爲可能在程序運行時動態產生,因此沒法像文字同樣簡單地將它們從應用程序中分離出來,而是須要特殊處理。Java中提供瞭解決這些問題的API類(位於java.util包和java.text包中)

Locale類

Locale實例對象表明一個特定的地理、政治、文化區域。 
一個 Locale對象自己不會驗證它表明的語言和國家地區信息是否正確,只是向本地敏感的類提供國家地區信息,與國際化相關的格式化和解析任務由本地敏感的類去完成。(若JDK中的某個類在運行時須要根據Locale對象來調整其功能,這個類就稱爲本地敏感類)

DateFormat類(日期格式化)

DateFormat類能夠將一個日期/時間對象格式化爲表示某個國家地區的日期/時間字符串。 
DateFormat類除了可按國家地區格式化輸出日期外,它還定義了一些用於描述日期/時間的顯示模式的int型的常量,包括FULL, LONG, MEDIUM, DEFAULT, SHORT,實例化DateFormat對象時,可使用這些常量,控制日期/時間的顯示長度。 
例如,對於日期/時間「2005年9月15日下午4時41分20秒」,如設置了DateFormat的顯示模式,則日期/時間顯示樣式分別爲:

  • SHORT模式徹底是數字的,在中文環境下顯示爲「05-9-15 下午4:41」;在英文環境下爲「9/15/05 4:41 PM」。
  • MEDIUM模式比SHORT模式長些,在中文環境顯示爲「2005-9-15 16:41:20」;在英文環境下顯示爲「Sep 15, 2005 4:41:20 PM」。
  • LONG模式比MEDIUM模式更長一些,在中文環境下顯示爲「2005年9月15日 下午04時41分20秒」;在英文環境下顯示爲「September 15, 2005 4:41:20 PM CST」。
  • FULL模式指定日期/時間的完整格式,在中文環境下顯示爲「2005年9月15日 星期四 下午04時41分20秒 CST」;在英文環境下,這個日期/時間顯示爲「Thursday, September 15, 2005 4:41:20 PM CST」。

實例化DateFormat類

實例化DateFormat類有九種方式,如下三種爲帶參形式,下面列出的三種方式也能夠分別不帶參,或只帶顯示樣式的參數。

  • getDateInstance(int style, Locale aLocale):以指定的日期顯示模式和本地信息來得到DateFormat實例對象,該實例對象不處理時間值部分。
  • getTimeInstance(int style, Locale aLocale):以指定的時間顯示模式和本地信息來得到DateFormat實例對象,該實例對象不處理日期值部分。
  • getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale):以單獨指定的日期顯示模式、時間顯示模式和本地信息來得到DateFormat實例對象。

DateFormat對象的方法

  • format:將date對象格式化爲符合某個本地環境習慣的字符串。
  • parse:將字符串解析爲日期/時間對象。 
    注意:parse和format徹底相反,一個是把date時間轉化爲相應地區和國家的顯示樣式,一個是把相應地區的時間日期轉化成date對象,該方法在使用時,解析的時間或日期要符合指定的國家、地區格式,不然會拋異常。

DateFormat對象一般不是線程安全的,每一個線程都應該建立本身的 DateFormat實例對象。

DateFormat使用範例

使用DateFormat格式化輸出日期。

public class Demo2 {

    /*
     * 使用DateFormat格式化輸出日期
     */
    public static void main(String[] args) {

        Date date = new Date();

        // DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.CHINA); // 16-8-8
        // DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.CHINA); // 2016-8-8
        // DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.CHINA); // 2016年8月8日
        // DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, Locale.CHINA); // 2016年8月8日 星期一
        DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.CHINA); // 2016-8-8
        String str = df.format(date);
        System.out.println(str);

        df = DateFormat.getTimeInstance(DateFormat.LONG, Locale.CHINA);
        System.out.println(df.format(date));

        df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT, Locale.CHINA);
        System.out.println(df.format(date));

        // 獲得默認的DateFormat
        df = DateFormat.getInstance();
        System.out.println(df.format(date));
    }

}
  • 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

使用DateFormat反向把一個字符串格式化成一個日期對象。

public class Demo3 {

    /*
     * 使用DateFormat反向把一個字符串格式化成一個日期對象
     */
    public static void main(String[] args) throws ParseException {

        String str = "2016年8月8日 星期一 下午5:57";

        DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT, Locale.CHINA);
        Date date = df.parse(str);
        System.out.println(date);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

運行結果爲:Mon Aug 08 17:57:00 CST 2016 
注意:把相應地區的時間日期轉化成date對象時,解析的時間或日期要符合指定的國家、地區格式,不然會拋異常。以下面所示的代碼就會拋異常:

public class Demo3 {

    /*
     * 使用DateFormat反向把一個字符串格式化成一個日期對象
     */
    public static void main(String[] args) throws ParseException {

        String str = "2016年8月8日 星期一 下午5:57";

        DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.CHINA);
        Date date = df.parse(str);
        System.out.println(date);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

會拋異常以下:

Exception in thread "main" java.text.ParseException: Unparseable date: "2016年8月8日 星期一 下午5:57"
  • 1

NumberFormat類(數字格式化)

NumberFormat類能夠將一個數值格式化爲符合某個國家地區習慣的數值字符串,也能夠將符合某個國家地區習慣的數值字符串解析爲對應的數值。 
NumberFormat類的方法:

  • format方法:將一個數值格式化爲符合某個國家地區習慣的數值字符串。
  • parse方法:將符合某個國家地區習慣的數值字符串解析爲對應的數值。

實例化NumberFormat類時,可使用locale對象做爲參數,也能夠不使用,下面列出的是使用參數的。

  • getNumberInstance(Locale locale):以參數locale對象所標識的本地信息來得到具備多種用途的NumberFormat實例對象。
  • getIntegerInstance(Locale locale):以參數locale對象所標識的本地信息來得到處理整數的NumberFormat實例對象。
  • getCurrencyInstance(Locale locale):以參數locale對象所標識的本地信息來得到處理貨幣的NumberFormat實例對象。
  • getPercentInstance(Locale locale):以參數locale對象所標識的本地信息來得到處理百分比數值的NumberFormat實例對象。

範例:

public class Demo4 {

    public static void main(String[] args) throws ParseException {

        int price = 18; // $18 ¥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 nf = NumberFormat.getCurrencyInstance(Locale.FRANCE); // 18,00 €
        System.out.println(nf.format(price));

        String s = "18,00 €";
        nf = NumberFormat.getCurrencyInstance(Locale.FRANCE);
        System.out.println(nf.parse(s).doubleValue()); // 18.0

        double d = 0.1;
        nf = NumberFormat.getPercentInstance();
        System.out.println(nf.format(d)); // 10%

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

MessageFormat(動態文本)

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

At 12:30 pm on jul 3,1998, a hurricance destroyed 99 houses and caused $1000000 of damage.

以上字符串中包含了時間、數字、貨幣等多個與國際化相關的數據,對於這種字符串,可使用MessageFormat類對其國際化相關的數據進行批量處理。 
MessageFormat類如何進行批量處理呢?

  1. MessageFormat類容許開發人員用佔位符替換掉字符串中的敏感數據(即國際化相關的數據)。
  2. MessageFormat類在格式化輸出包含佔位符的文本時,messageFormat類能夠接收一個參數數組,以替換文本中的每個佔位符。

模式字符串與佔位符

例如:

At 12:30 pm on jul 3,1998, a hurricance destroyed 99 houses and caused $1000000 of damage.

該語句對應的模式字符串即爲:

At {0} on {1},a destroyed {2} houses and caused {3} of damage.

字符串中的{0}、{1}、{2}、{3}就是佔位符。

格式化模式字符串

At 12:30 pm on jul 3,1998, a hurricance destroyed 99 houses and caused $1000000 of damage.

該語句對應的模式字符串還可編寫爲:

On {0}, a hurricance destroyed {1} houses and caused {2} of damage.

如今來格式化以上模式字符串。

  1. 實例化MessageFormat對象,並裝載相應的模式字符串。
  2. 使用format(object obj[])格式化輸出模式字符串,參數數組中指定佔位符相應的替換對象。

範例:

public class Demo5 {

    public static void main(String[] args) {
        // 模式字符串
        String pattern = "On {0}, a hurricance destroyed {1} houses and caused {2} of damage.";
        // 實例化MessageFormat對象,並裝載相應的模式字符串
        MessageFormat format = new MessageFormat(pattern, Locale.CHINA);
        Object[] params = {new Date(), 99, 1000000};
        // 格式化模式字符串,參數數組中指定佔位符相應的替換對象
        String message = format.format(params);
        System.out.println(message);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

運行結果:On 16-8-18 上午9:01, a hurricance destroyed 99 houses and caused 1,000,000 of damage. 
還能夠將模式字符串編寫在資源文件中,以下: 
這裏寫圖片描述 
代碼以下:

public class Demo6 {
    public static void main(String[] args) {
        ResourceBundle bundle = ResourceBundle.getBundle("cn.itcast.resource.MessageResource", Locale.CHINA);
        String pattern = bundle.getString("message");

        MessageFormat format = new MessageFormat(pattern, Locale.CHINA);
        Object[] params = {new Date(), 99, 100000000};
        String message = format.format(params);
        System.out.println(message);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

運行結果爲:在16-8-18 上午9:16,一場大風摧毀了99所房子,致使了100,000,000錢的損失!!!

佔位符的三種書寫方式

佔位符有三種方式書寫方式:

  • {argumentIndex}:0-9之間的數字,表示要格式化對象數據在參數數組中的索引號。
  • {argumentIndex,formatType}:參數的格式化類型。
  • {argumentIndex,formatType,FormatStyle}:格式化的樣式,它的值必須是與格式化類型相匹配的合法模式、或表示合法模式的字符串。

範例:

public class Demo6 {
    public static void main(String[] args) {

        String pattern = "At {0, time, short} on {0, date}, a destroyed {1} houses and caused {2, number, currency} of damage.";
        MessageFormat format = new MessageFormat(pattern, Locale.US);
        Object[] params = {new Date(), 99, 100000000};
        String message = format.format(params);
        System.out.println(message);

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

運行結果爲:At 9:06 AM on Aug 18, 2016, a destroyed 99 houses and caused $100,000,000.00 of damage. 以上就是JavaWeb開發中國際化的總結內容。

相關文章
相關標籤/搜索