JAVA 国际化基础知识(二)
輸入法
實際上,以上所有討論都涉及操作或顯示數據。然而,必須以某種方式輸入數據。對于最終用戶,最常用的是鍵盤。但是,如果鍵盤不支持某種語言輸入所需的字符,您該怎么辦呢?
輸入法(Input method)是允許數據輸入的軟件組件的一個技術術語。Java 平臺既允許使用主機 OS 輸入法也允許使用基于 Java 語言的輸入法。如果您需要實現輸入法,您可以使用輸入法框架(Input Method Framework)。您可以在 JDK 文檔中?Internationalization?一節中的?Input Method Framework?(可以從參考資料中訪問該文檔)中找到輸入法客戶機 API(Input Method Client API)及輸入法引擎 SPI(Input Method Engine SPI)的規范、參考和教程
Unicode 與 Java 字符
Java 字符與 char 數據類型
Java 程序員的一個最知名的抱怨是“我只看到程序輸出是問號(或方塊),我的數據是怎么被破壞的呢?”通常,作為 Java 開發人員,您應該理解實際發生了什么以及這一表面問題后面的原因,而這種知識在處理國際化問題時尤為重要。
Java 語言規范(Java Language Specification)將?char?定義為原始的、數值型和整型的類型。此外,char?是唯一的無符號(unsigned)數字類型,它允許一些有趣的(或討厭的,這取決于您的觀點)竅門。char?在另一方面也十分特殊,因為將它們送到諸如顯示器或打印機的輸出設備時,會將其值從字符映射或字體映射成字形。然而,從根本上來說,char?是數值類型,支持所有整數運算。因此?Unicode支持?注釋道:可以使用字母或 Unicode 轉義符設置?char。因為?char?是數值型,所以您也可以使用八進制、十進制或十六進制表示法甚至反轉位來賦值。
假設出現上述情況并假定沒有程序錯誤,上面問題的答案是:字符映射或字體不支持該字符,顯示問號或方塊來作為替代。該?char?本身的值仍然有效。但是,這樣您就不能可視地驗證數據;您不得不核對數值。下面的示例顯示了這一行為。
這幅圖像顯示了日本象形文字中的“Go”或 5,以 Unicode 表示為‘\u4E94’。該字符導致在下面的?charExample?程序中顯示成問號和方塊:
import javax.swing.*; ? public class charExample { ? public static void main( String[] args ) ? { ??? boolean bFirst = true;??? ????char aChar[] = { ???????????????????? 'A',???? // character ????????????????????? 65,???? // decimal ????????????????????? 0x41,?? // hex ????????????????????? 0101,?? // octal ???????????????????? '\u0041' // Unicode escape ?????????????????? }; ? ??? char myChar = 256; ??? ????for( int i = 0; i < aChar.length; i++ ) ??? { ????? System.out.print( aChar[i]++ + " " ); ????? if( i == (aChar.length - 1) ) ????? { ??????? System.out.println( "\n---------" ); ??????? if( bFirst ) ??????? { ????????? i = -1; ????????? bFirst = !bFirst;????????? ????????} ????? } ??? } // end for ??? // the result of adding two chars is an int ??? System.out.println( "aChar[0] + aChar[1] equals: " + ????????????????????????(aChar[0] + aChar[1]) ); ??? System.out.println( "myChar at 256: " + myChar ); ??? System.out.println( "myChar at 20116 or \\u4E94: " + ???????????????????????( myChar = 20116 ) ); ??? // show integer value of the char ??? System.out.println( "myChar numeric value: " + ????????????????????(int)myChar ); ? ??? JFrame jf = new JFrame(); ????? JOptionPane.showMessageDialog( jf, ??????? "myChar at 20116 or \\u4E94: " + ????????( myChar = 20116 ) + ????????"\nmyChar numeric value: " + ????????(int)myChar, ????????"charExample", JOptionPane.ERROR_MESSAGE); ? ??? jf.dispose(); ??? System.exit(0); ? ? } // end main ? }? // End class charExample首先,程序用字母“A”的各種表示法初始化一個?char?數組,并將一個?char?變量設置成 256(‘\u0100’)。程序在一個循環中打印兩次數組的值。打印之后遞增每個元素的值(char?是數值型,記得嗎?)。接下來,將頭兩個元素加到一起,然后打印其結果(int)。然后,打印?char?變量,首先用其初始值,然后用值 20116 或‘\u4E94’,它是 5 的日本象形文字“Go”。如預期的那樣在使用代碼頁 cp1252 的 Windows NT 上,會在顯示器上將這兩個值打印成問號。根據您的系統使用的代碼頁,顯示可能略微有些不同。要核查其值,接下來將變量作為?int?打印。最后,JOptionPane?顯示其值,對于不受支持的?char‘\u4E94’,它顯示一個方塊。
下面是?charExample?的輸出:
A A A A A --------- B B B B B --------- aChar[0] + aChar[1] equals: 134 myChar at 256: ? myChar at 20116 or \u4E94: ? myChar numeric value: 20116JOptionPane?顯示:
字體、字體特性及 Lucida 字體
Java 平臺既識別邏輯字體也識別物理字體。
邏輯字體是那些被映射到主機系統字體的字體。比如人們熟悉的 Serif、Sans-serif、Monospaced、Dialog 以及 DialogInput 字體。還有四種邏輯字體樣式:普通、粗體、斜體及粗斜體。使用一個位于 JRE/lib 目錄下的font.properties 文件來實現主機字體到邏輯字體的映射。盡管細節因系統而異,但是缺省 font.properties 文件通常設置成英語環境,雖然JDK 也有一個本地化日語版本可用。還提供了另外的font.properties 文件;JDK 1.3.1 Windows 版包含阿拉伯語、希伯來語、日語、韓國語、俄語、泰國語字體文件以及中文的幾種版本的字體文件。就象命名約定一樣,搜索適當的 font.properties 同用于?ResourceBundle?的方法類似(但不全相同)。如果特定于語言的 font.properties 文件同您的系統的語言環境相匹配,并且安裝了期望的字體(通常隨 OS 的那一版本一起提供),那么就會對該語言進行自動映射。否則,就使用缺省的(通常是英語)文件映射。
如果您安裝了適當的字體并且在調用 Java 應用程序時傳入了相應的語言及國家或地區代碼,那么也會進行自動映射。如果期望的 font.properties 文件存在,那么這種行為對開發非常有用。也可以將最初的缺省 font.properties 文件拷貝到別的地方,然后將特定文件重命名為“font.properties”,通過這樣來將該語言/字體有效地設置成缺省情況。雖然對于開發人員來說很容易,但這顯然不是最終用戶非得做的事情。
如果您必須親自定制或創建一個新的font.properties 文件,那就完全是另一回事,而且更難??梢栽贘DK 文檔?Internationalization?一節中的?Font Properties?中找到處理 font.properties 文件的指示信息。
物理字體是我們始終在使用的正常字體?;贏SCII 和 ISO 8859-1 的字體不會有問題。然而,一旦超出這一范圍,主機平臺顯然必須理解它們,并且必須對它們進行 Unicode 編碼以使之能夠用于您的 Java程序。找到這些字體不象以前那么難了。例如,Windows MS MinchoTrueType 字體(主要是日語)是 Unicode 編碼的,可以以標準方式立即投入使用。當在系統上裝入了適當的物理字體時,您可以讓用戶選擇他們想要的字體并保存他們的首選項,或者將該字體設置成整個軟件包的標準字體,而不用進入 font.properties 文件。
Java 2 SDK 還提供三種物理字體系列:Lucida Sans、Lucida Bright 和 Lucida Sans Typewriter。每一系列都含有四種字體 ― 分別用于普通、斜體、粗體以及粗斜體樣式 ― 總計 12 種字體。雖然關于這些字體的確切功能的信息極為稀少,但 Lucida Sans 字體處理大多數歐洲和中東語言。不包括亞洲語言。由于該字體隨 JDK 一起提供,因此教程中的所有圖形應用程序示例都使用Lucida Sans 字體。更多信息,請參閱 JDK 文檔?Internationalization?一節中的?Physical Fonts?(可以從參考資料訪問)。
提供本地化的資源
創建語言環境
提供任何類型的本地化資源時,您應該做的第一件事情是創建一個適當的語言環境(參閱語言環境)。雖然有一個包含平臺/瀏覽器變體的構造器,但通常您將使用
| Locale l = new Locale(String language, String country); |
其中,language?是由 ISO-639 定義的小寫、兩字母代碼,country?是一個由 ISO-3166 定義的大寫、兩字母代碼。
下面是用于特定于德國的德語語言環境:
| Locale l = new Locale( "de", "DE"); |
?
Locale?有一個返回受支持的語言環境數組的?static getAvailableLocales()?方法。實際上,所有與語言環境相關的 Java 2 Platform API 都有一個?getAvailableLocales()?方法,您可以期望它返回一致的值。其它有用的方法是?static getDefault(),它返回缺省的語言環境,以及?getDisplayName()?和?getDisplayName(Locale inLocale)?方法,它們分別用缺省或所請求的語言環境語言來返回適于顯示的名稱。您也可以獲取國家或地區以及語言的代碼和名稱。這些方法允許沒有特定語言知識的程序員為最終用戶提供讀、選擇以及返回本地化的語言環境信息的能力。
使用資源束
ResourceBundle?包含鍵/值結合。鍵總是?String,而值總是?PropertyResourceBundle?中的?String,但可以是?ListResourceBundle?中的任何對象或定制子類。如果沒有找到請求的資源,那么?ResourceBundle?訪問方法會拋出一個MissingResourceException。
參閱本地化的資源以獲得更多常規信息。本教程將集中于?PropertyResourceBundle,因為它們適合于大多數情形,并且易于生成和修改而無須編寫任何新代碼。
ResourceBundle.getBundle(StringbaseName)?和?ResourceBundle.getBundle(StringbaseName, Locale locale)?提供一種內置的搜索機制,當這些束的結構恰當時,這種機制工作得非常好。正常的搜索從 base_language_country_variant 到 base_language_country,再到base_language,最后到 base。注:如果請求一個特定的、非缺省的語言環境,并且同資源一起存在一個缺省的語言環境束,那么搜索將會停在那兒而不是繼續搜索到基礎束。我們的示例程序(參閱?PropertyResourceBundle代碼示例)支持英語、法語、德語和俄語并使用?PropertyResourceBundle。支持的 .properties 文件被命名為:
·????????ByTheNumbersrb.properties
·????????ByTheNumbersrb_de.properties
·????????ByTheNumbersrb_en.properties
·????????ByTheNumbersrb_fr.properties
·????????ByTheNumbersrb_ru.properties
所有文件都含有全部所需資源。英語用作缺省值,ByTheNumbersrb.properties和 ByTheNumbersrb_en.properties 是相同的。這種做法略微有些偏離傳統認知,即:對于基礎缺省語言,不需要專門命名的 .properties 文件,因此我們不需要ByTheNumbersrb_en.properties。然而,當一段特定信息使用非缺省語言環境時,這種設置卻是必需的,我們的示例程序就是這種情形。假定一個英語語言環境將被用來在一臺法語為缺省語言環境機器上顯示某項。如果 _fr 束中存在相同的鍵,_en 搜索失敗時,將會選擇該值。這完全不是所請求的或所期待的那樣。如果在程序的任意一次給定運行中只使用一種語言環境,那么專門命名的副本就不是必需的。但無論如何,在任何情況下這種做法都不需要新的代碼并且起作用。
如果我們需要更特定的語言環境支持,例如奧地利語、瑞士語和德語(分別是 _de_AT、_de_CH 和 _de_DE),那么只將國家或地區細節置于以適當的國家或地區命名的特性文件(例如,myprops_de_CH.properties)中,而將更一般的元素置于 _de 束級別,這樣做會很有意義。在那種情形下,需要其它元素時,將總能找到 _de 束。
您也應該為束實現幾種命名約定。我們的示例使用這種通用格式:Object.getClass().getName() + "rb"。主要規則是:對于 .properties 文件,不要只使用類名稱作為其基礎名稱。忽視該規則在有些平臺上照樣能行,但在其它一些平臺上您會大吃一驚。記入文檔的準則是:如果類和具有相同名稱的 .properties 文件同時存在,那么被選中和裝入的將是類。就是這樣。這一行為的一個好結果是:使用適當命名的束,您可以在?ListResourceBundle?和PropertyResourceBundle?之間轉換,而不用更改代碼;只要將期望的類型移到類路徑即可。
您可能會發現讓不同的信息類型具有多個?ResourceBundle?更加合適。它們可以為許多不同的程序提供資源。特定的前綴或后綴約定對于避免類名沖突仍然有用。
使用 PropertyResourceBundle
PropertyResourceBundle?的語義同其父束?ResourceBundle?的語義相同。不同之處在于數據存儲的位置。PropertyResourceBundle?由符合?Properties?約定的 .properties 文件支持。下面是創建文件所要知道的內容:
·????????文件被格式化為 ISO8859-1 編碼的基本文本,因此您可以使用任何編輯器來創建和編輯文件。
·????????以 # 開頭的行是注釋。
·????????每個資源以?key=value?的形式被設置成鍵/值對。
·????????文件擴展名必須是.properties。名稱必須遵守下列格式,其中?language?由 ISO-639 定義,country?由 ISO-3166 定義(參閱創建語言環境):
1.?????? baseName.properties
2.?????? baseName_language.properties
3.?????? baseName_language_country.properties
4.?????? baseName_language_country_variant.properties
下面是ByTheNumbersrb_en.properties 的一個示例項:
| 1=One: |
下面是ByTheNumbersrb_ru.properties 的一個示例項:
| 1=\u041E\u0434\u0438\u043D: |
上面兩個示例中的冒號實際上是值的一部分而不是所需的項。注:一旦我們超越了 ISO 8859-1 而進入其它 Unicode 范圍,我們必須使用 Java Unicode 轉義。您可以使用 JDKnative2ascii 工具來從不同編碼進行轉換。
Property ResourceBundle 代碼示例
顯示在右側的?ByTheNumbers?示例使用俄語語言環境 ― ru_RU。
ByTheNumbers.java(參閱?ByTheNumbers.java:PropertyResourceBundle 示例)以幾種不同的語言顯示數字 0 到 10 的名稱。進入時,將缺省的語言環境同支持的語言環境(英語、法語、德語和俄語)相比較。如果缺省語言環境與其中的某一種不匹配,那么就將英語選做缺省,將基礎?ResourceBundle?用于資源;否則,使用缺省語言環境?ResourceBundle。通過使用缺省語言環境獲得支持的語言的語言環境顯示名稱(Locale Display Name),并將其裝入?JComboBox。用戶可以鍵入適當名稱的號碼然后按 OK。程序驗證這些輸入項并顯示祝賀消息或重試消息。我們提供一個按鈕以隨機順序顯示號碼名稱。用戶可以從?JComboBox?選擇任何語言,并且字段初始將以數值順序顯示選中的語言。程序使用 Lucida Sans 字體,因此可以正確地顯示所有受支持的語言。遺憾的是,我們的翻譯還沒有返回我們對標題翻譯的請求,因此“title=Key in numbers to match the words:”鍵/值對僅僅出現在基礎名稱文件中,它給了我們一個機會,讓我們明白不位于層次結構較低位置的鍵可以在祖先文件中找到。
要運行該程序,使用下列任意一條命令:
l?? java ByTheNumbers?// 如果支持缺省語言環境,就使用它,否則,就使用英語。
l?? java -Duser.language=de -Duser.region=DE ByTheNumbers?// 德語
l?? java -Duser.language=en -Duser.region=US ByTheNumbers?// 英語
l?? java -Duser.language=fr -Duser.region=FR ByTheNumbers?// 法語
l?? java -Duser.language=ru -Duser.region=RU ByTheNumbers?// 俄語
下面顯示了五個 .properties 文件中的兩個:
ByTheNumbersrb.properties?(與 ByTheNumbersrb_en.properties相同)
| # Default properties in English 0=Zero: 1=One: 2=Two: 3=Three: 4=Four: 5=Five: 6=Six: 7=Seven: 8=Eight: 9=Nine: 10=Ten: random=Random title=Key in numbers to match the words: |
ByTheNumbersrb_ru.properties
| # Default properties in Russian 0=\u041D\u0443\u043B\u044C: 1=\u041E\u0434\u0438\u043D: 2=\u0414\u0432\u0430: 3=\u0422\u0440\u0438: 4=\u0427\u0435\u0442\u044B\u0440\u0435: 5=\u041F\u044F\u0442\u044C: 6=\u0428\u0435\u0441\u0442\u044C: 7=\u0441\u0435\u043C\u044C: 8=\u0412\u043E\u0441\u0435\u043C\u044C: 9=\u0414\u0435\u0432\u044F\u0442\u044C: 10=\u0414\u0435\u0441\u044F\u0442\u044C: random=\u041D\u0430\u0443\u0433\u0430\u0434 |
Property ResourceBundle 代碼示例:I18N 詳細信息
讓我們看一看同 I18N 有關的代碼部分。首先,建立支持的語言環境和?ResourceBundle?基礎名稱。
| ? Locale[]?? alSupported = { ??????????????? Locale.US, ??????????????? Locale.FRANCE, ??????????????? Locale.GERMANY, ??????????????? new Locale( "ru", "RU" ) ?????????????????????????? }; ... ? ? String sRBName = getClass().getName() + "rb"; |
?
接下來,使用與 OK 按鈕的字體相同的樣式和大小創建 Lucida Sans 字體,然后獲得缺省語言環境語言所支持的語言的顯示名稱(Display Names)。此外,對缺省語言環境進行比較以確定是否支持它。如果不支持,英語數字將是首先被顯示的集合。
| ??? Font fJB = jbOK.getFont(); ??? fLucida = new Font("Lucida Sans", ??????????????????????? fJB.getStyle(), ??????????????????????? fJB.getSize() ); ? ??? ... ? ??? asDNames = new String[ alSupported.length ]; ??? Locale lDefault = Locale.getDefault(); ??? for( i = 0; i < alSupported.length; i++ ) ??? { ????? asDNames[i] = ???????? alSupported[i].getDisplayName(); ? ????? if( iSelIndex == 0 && ????????? lDefault.equals( alSupported[i] ) ) ????? { iSelIndex = i; } ??? } // end for |
?
接下來,在一個循環中創建?JLabel?和?JTextField?并將它們裝入數組。設置每個?JLabel?的?Font?和?Name。一旦構建了數組,就調用?loadFromResourceBundle()?來設置每個?JLabel?的文本值。接下來設置本地化jbRandom 按鈕和標題文本。請注意,這兩個組件的屬性只設置了一次,這是典型程序中所有組件的正常情況,在那里,語言環境在給定的運行期間不會改變。
| ????? jlTemp.setFont( fLucida ); ????? jlTemp.setName( i +? "" ); // set Name ????? ... ??? loadFromResourceBundle(); // get localized labels ????? ... ??? jbRandom.setFont( fLucida ); ??? jbRandom.setText( rb.getString( "random" ) ); ????? ... ??? jlTemp = new JLabel( rb.getString( "title" ) ); ??? jlTemp.setFont( fLucida ); |
?
下面是?loadFromResourceBundle()?方法,它使用選中的語言環境訪問適當的?ResourceBundle。使用?JLabel.Name?屬性作為?getString(String key)?的鍵來設置?JLabel?的文本。如果沒有找到特別的資源,就顯示一個錯誤對話框。從JComboBox?選擇語言時,也會調用這一方法。
| ? public void loadFromResourceBundle() ? { ??? try ??? { // get the PropertyResourceBundle ????? rb = ResourceBundle.getBundle( ????????????? sRBName, ????????????? alSupported[iSelIndex] ); ????? // get data associated with keys ????? for( int i = 0; i < sfiSIZE; i++ ) ????? { ??????? aiOrder[i] = i; ??????? ajl[i].setText( rb.getString( ajl[i].getName() ) ); ????? } ????? bRandomize = false; ??? } // end try ??? catch( MissingResourceException mre ) ??? { ????? JOptionPane.showMessageDialog( this, ??????? "ResourceBundle problem;\n" + ??????? "Specific error: " + mre.getMessage(), ??????? "", JOptionPane.ERROR_MESSAGE); ??? } ? } // end loadFromResourceBundle |
?
同樣,有關完整的程序清單及所有.properties 文件的內容,請參閱?ByTheNumbers.java:PropertyResourceBundle 示例。
使用日期、數字和貨幣
日期、數字和貨幣
對于任何那些從未出過國,或從未接觸過日期、數字和貨幣的“外國”用法的人來說,格式化和解析日期、數字和貨幣顯得很簡單。畢竟,所有人都能理解 lundi 1 avril 2002 或至少 4.1.02 的月和日部分,對嗎?雖然我們極少有人能實際以 150,75??購買 32 1500,7 項東西,但我們能夠很容易地理解以歐元表示的價格有多少項。或者可能不是這樣。這些示例看起來可能不典型,但他們確實發生了,并且表示了為什么非本國人在理解本國的日期、數字和貨幣格式方面經常會有問題。
結果是,全世界使用的日期有各種各樣的順序和符號。數字和貨幣也是如此。此外,貨幣符號可能不止一個字符,它可能出現在值的前面或后面,和值之間有或沒有空格。在大多數編程語言中,您幾乎總是靠自己來處理這些情形。但 Java API 卻能夠處理每個受支持語言環境的所有的不同格式。而且,通過使用?DateFormatSymbols?和?DecimalFormatSymbols?類,您可以獲得諸如這樣的信息:本地化的長短月日名稱、十進制與貨幣分隔符以及貨幣與百分比符號。
API 文檔鼓勵您為 I18N 應用程序使用抽象父類?DateFormat?和?NumberFormat?的?getInstance()?和?getXXXInstance()?方法。從 1.3(和 1.4)參考實現起,分別返回?SimpleDateFormat?和?DecimalFormat?的實例。兩個類都有缺省的模式與符號用于格式化和解析,并且還允許定制。
下面幾頁中的示例程序都使用缺省模式來幫助您理解它們是怎樣工作的。您將看到:由于 API 設計的緣故,三個示例中的代碼都非常相似。從最終用戶的觀點,它們也非常相似:以本機語言環境提供一個輸入域。當用戶按下 OK 按鈕時,就在表示用戶選擇的語言環境和標準解析的“原始”值的單獨域中顯示值。這三個示例都將處理由 JDKAPI 支持的所有語言環境。Lucida Sans 字體用于所有顯示?!癟oggle Display Names”按鈕將語言環境名稱的顯示從用戶的本機語言切換為特定語言環境的本機語言。當字體中沒有用于本地化顯示名稱的第一個字符的字形時,“ - font can't display.”就被附加到下拉框中的語言環境名稱上。程序仍然會工作,但在那種情況下,您可能會看到輸出的某些部分是您熟悉的方框或問號。
使用下面的命令調用程序:
| java AppName |
?
由于支持所有 API 語言環境,您也可以使用下列命令調用它們
| java -Duser.language=lc -Duser.region=cc AppName |
?
其?lc?是 API 支持的語言環境的 ISO-639 語言代碼,cc?是 API 支持的語言環境的 ISO-3166 國家或地區代碼,以使輸入格式化成該語言環境的樣式。
注:由于要訪問整個語言環境顯示名稱集,這些應用程序將比正常情況要花費更長的時間來啟動。
日期格式化示例
這個?JIBDateGUI?示例使用德語作為缺省語言環境 ― de_DE。
JIBDateGUI(參閱?JIBDateGUI.java:DateFormat 示例)允許用戶以其本地的格式輸入日期。輸入時確定本地語言環境,并且該語言環境顯示在 OK 按鈕的旁邊。當用戶按下 OK 時,則解析輸入數字并以選中的語言環境顯示該數字。還以 ISO 格式對該值進行單獨解析和顯示??赡苁褂脜怠癴ull”、“long”、“medium”或“short”調用程序。如果沒有發送參數或者發送了這四個參數之外的其它參數,那么就使用“short”。這些值對應于DateFormat.FULL、DateFormat.LONG、DateFormat.MEDIUM?和?DateFormat.SHORT,并且被用來以選中的樣式創建?DateFormats。
程序通過定義缺省和選中的?DateFormats?和?locales?開始。java.sql.Date?被初始化成顯示標準 ISO 日期值的當前日期(注:沒有為該示例對日期進行標準化),然后定義 Lucida 字體、缺省語言環境、支持的語言環境的數組以及本機和本地化的語言環境顯示名稱。
| ? DateFormat dfLocal, ???????????? dfSelected; ? ? java.sql.Date jsqlDate = new java.sql.Date( ???? System.currentTimeMillis() ); ? ? Font fLucida; ? ... ? Locale???? lDefault = Locale.getDefault(); ? Locale[]?? alSupported; ? ? String[]?? asDNames, ???????????? asLDNames; |
?
在構造器中,創建了 Lucida Sans 字體并將其賦給顯示域。捕獲請求的樣式并創建缺省?DateFormat。接下來,同時以缺省和本地化格式收集所有可用的顯示名稱。由?Font.canDisplay()?檢查每個本地化顯示名稱的第一個字符;如果返回 false,那么“ - font can'tdisplay.”就被附加到該名稱后面。如果 Java API 支持缺省語言環境,那么相應的顯示名稱就會被選中;否則就選中第零行。此外,使用?java.sql.Date?的值設置和格式化輸入域。DateFormat.setLenient(false)?被應用到缺省?DateFormat?并且獲取缺省顯示名稱以供顯示。
| ??? Font fJCB = jbToggle.getFont(); ??? fLucida = new Font("Lucida Sans", ??????????????????????? fJCB.getStyle(), ??????????? ????????????fJCB.getSize() ); ? ??? iFormat = argiFormat; ??? dfLocal = DateFormat.getDateInstance( ???? iFormat ); ??? ??? alSupported = Locale.getAvailableLocales(); ??? asDNames = new String[ alSupported.length ]; ??? asLDNames = new String[ alSupported.length ]; ??? for( int i = 0; i < alSupported.length; i++ ) ??? { ????? asDNames[i] = ???????? alSupported[i].getDisplayName(); ? ????? s1 = ???????? alSupported[i].getDisplayName( alSupported[i] ); ????? if( fLucida.canDisplay( s1.charAt( 0 ) ) ) ????? { asLDNames[i] = s1; } ????? else ????? { asLDNames[i] = s1 + " - font can't display."; } ? ????? if( iSelIndex == 0 && ????????? lDefault.equals( alSupported[i] ) ) ????? { iSelIndex = i; } ??? } // end for ??? ... ??? jtI.setText( dfLocal.format( jsqlDate ) ); ??? ... ??? dfLocal.setLenient( false ); ??? ... ??? JLabel jlTemp = new JLabel("Default = " + ??????????? lDefault.getDisplayName() ); ??? jlTemp.setFont( fLucida ); |
?
在?ActionListener(actionPerformed()?方法)中為顯示名稱?JComboBox(jcb)處理所有其它 I18N 功能:根據選擇項,創建新的?DateFormat?并清空顯示域。如果在下一節中出現了任何錯誤,對話框將顯示?ParseException?消息。代碼試圖從輸入解析?java.util.Date?并使用缺省?DateFormat?對其重新進行格式化以供輸出。接下來,格式化選中的?DateFormat?的顯示。最后,解析該值并用它來創建?java.sql.Date,java.sql.Date?被用來顯示 ISO 值。
| ??? if( oSource == jcb ) ??? { ????? dfSelected = DateFormat.getDateInstance( ???????? iFormat, ???????? alSupported[ jcb.getSelectedIndex() ] ); ??? }? // end if jcb, continue on ??? ??? jtD.setText( "" ); ??? jtP.setText( "" ); ??? ??? try ??? { ????? java.util.Date d = dfLocal.parse( ???????? jtI.getText() ); ????? jtI.setText( dfLocal.format( d ) ); ????? jtI.setCaretPosition(0); ????? jtD.setText( dfSelected.format( d ) ); ????? jtD.setCaretPosition(0); ????? d = dfSelected.parse( jtD.getText() ); ????? // get new java.sql.Date ???? ?jsqlDate = new java.sql.Date( d.getTime() ); ????? ????? jtP.setText( jsqlDate.toString() ); ??? } ??? catch( ParseException pe ) ??? { ????? JOptionPane.showMessageDialog( this, ????? pe.getMessage(), "", JOptionPane.ERROR_MESSAGE); ??? } |
?
同樣,JIBDateGUI.java:DateFormat 示例上列出了完整的程序。
總結
以上是生活随笔為你收集整理的JAVA 国际化基础知识(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LC-3 指令集注释规范
- 下一篇: py3+requests+urllib+