【譯】使用Java Locale進行國際化


前言

在開發軟件應用程序時,我們經常強調尊重用戶語言和地理區域的重要性和價值。允許用戶用他們自己的語言與軟件交流可能會大大促進軟件的銷售。在Java 語言環境中, Locale則用來闡明國際化過程。

什么是Locale

java.util.LocaleJava Locale的實現類。要為應用程序定義區域設置(語言、國家和變體),您將使用 Locale 對象,它只是一個標識符。真正的本地化是由區域敏感類完成的。您從對區域設置敏感的類創建的對象可以自定義如何格式化和向用戶呈現數據。這些類通過 Locale 對象來感知應用程序中使用的語言環境.NumberFormat 類就是一個很好的例子。比如,對於法國,NumberFormat 表示為 302 400,德國為 302 .400, 美國則是302,400

Java標准API中, 常見的區域敏感類有:

  • NumberFormat
  • DateFormat
  • DecimalFormat

創建Java Locale對象

現在讓我們深入研究代碼。有四種方法可以創建 Locale 對象。

  • Locale 構造函數
  • Locale.Builder
  • Locale.forLanguageTag工廠方法
  • Locale常量

使用Locale構造函數

有三個可用於創建 Locale 對象的構造函數。

  • Locale(String language): 僅用語言來創建語言環境對象:Locale locale = new Locale("en");
  • Locale(String language, String country): 使用語言和國家來創建語言環境對象: Locale locale = new Locale("en", "US");
  • Locale(String language, String country, String variant): 使用所有三個組件——語言、國家和變體——來創建語言環境對象: Locale locale = new Locale("en", "US", "SiliconValley");

這是使用Locale 構造函數的完整示例:

Locale deLocale = new Locale("de", "De");
Locale usLocale = new Locale("en", "US");
Locale zhLocale = new Locale("zh", "CN");
long number = 123456789L;
NumberFormat denf = NumberFormat.getInstance(deLocale);
NumberFormat usnf = NumberFormat.getInstance(usLocale);
NumberFormat zhnf = NumberFormat.getInstance(zhLocale);
System.out.println(denf.format(number));
System.out.println(usnf.format(number));
System.out.println(zhnf.format(number));

Date now = new Date();
DateFormat usdf = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, usLocale);
DateFormat dedf = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, deLocale);
DateFormat zhdf = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, zhLocale);
System.out.println(usdf.format(now));
System.out.println(dedf.format(now));
System.out.println(zhdf.format(now));

在輸出中,可以看到德語,美國英語和中國如何顯示數字和日期:

123.456.789
123,456,789
123,456,789
December 12, 2021 1:02:53 PM CST
12. Dezember 2021 13:02:53 CST
2021年12月12日 下午01時02分53秒

使用Locale.Builder類

您還可以使用 Locale.Builder 類來創建 Locale 對象。這個類只有一個構造函數,不帶任何參數。您必須使用一系列 setter 方法來指定languagecountryvariant

Locale locale = new Locale.Builder().setLanguage("de").setRegion("CA").build();

使用Locale.forLanguageTag工廠方法

IETF BCP 47 是定義語言標簽以識別區域設置的標准,Java SE 7 包符合它。您可以使用 IETF BCP 47 標准語言標簽通過 Locale.forLanguageTag 工廠方法創建區域設置對象

Locale aLocale = Locale.forLanguageTag("en-US");
Locale bLocale = Locale.forLanguageTag("de-Germany");

稍后我們將介紹語言標簽;下面的代碼向您展示了如何使用 Locale.forLanguageTag 工廠方法來創建Locale對象。

Locale usLocale = Locale.forLanguageTag("en-US");
Locale deLocale = Locale.forLanguageTag("de-Germany");
Locale zhLocale = Locale.forLanguageTag("zh-CN");
long number = 123456789L;
NumberFormat denf = NumberFormat.getInstance(deLocale);
NumberFormat usnf = NumberFormat.getInstance(usLocale);
NumberFormat zhnf = NumberFormat.getInstance(zhLocale);
System.out.println(denf.format(number));
System.out.println(usnf.format(number));
System.out.println(zhnf.format(number));

輸出將是:

123.456.789
123,456,789
123,456,789

使用Locale常量

這可能是創建 Locale 對象的最簡單方法。為方便起見,Java為某些語言和國家/地區預定義了常量。例如:Japan 是日本的國家表示,而 Japanese 是日語的表示。您只需要使用一個常量來創建這種類型的語言環境。以下代碼是如何使用區域設置常量的示例。

Locale deLocale = Locale.GERMANY;
Locale usLocale = Locale.US;
Locale zhLocale = Locale.CHINA;
long number = 123456789L;
NumberFormat denf = NumberFormat.getInstance(deLocale);
NumberFormat usnf = NumberFormat.getInstance(usLocale);
NumberFormat zhnf = NumberFormat.getInstance(zhLocale);
System.out.println( denf.format(number) );
System.out.println( usnf.format(number) );
System.out.println( zhnf.format(number) );

這段代碼基本上和前面的例子做了同樣的事情,唯一的區別是它如何創建 Locale 對象。輸出是:

123.456.789
123,456,789
123,456,789

Java Locale代碼小結

您可能已經注意到,我們在使用 Locale 構造函數和 Locale.Builder 方法創建對象時使用了代碼。有一個可用的 Java 語言代碼和國家/地區代碼列表。可用代碼的完整列表將使本文不必要地冗長。

您在這里看到的是對更常見的概述:

語言代碼:

  • English – en
  • German – de
  • French – fr
  • Russian –ru
  • Japanese – ja
  • Chinese – zh
  • Arabic – ar

同一種語言可以在多個國家使用。語言的使用方式可能因國家/地區而異。例如,在美國使用的英語與在英國使用的英語不同。這就是為什么在您的 Locale 對象中指定國家/地區很重要的原因。該國家/地區使用唯一的國家/地區代碼指定......

國家代碼:

  • United States – US
  • Germany – DE
  • France – FR
  • United Kingdom – UK
  • Canada – CA

Java Locale語言標簽

語言標簽是具有特殊格式的字符串,用於提供有關特定語言環境的信息。它可以像英語使用en表示一樣簡單,也可以像使用zh-cmn-Hans-CN表示中國一樣復雜,分別用於中文、普通話、簡體文字。

Locale.forLanguageTag(LanguageTag) 使用語言標簽來創建 Locale 對象。

Locale locale = Locale.forLanguageTag("en-US");

此代碼僅使用en-US語言標簽創建 Locale 對象。

語言范圍

語言范圍是一組共享某些屬性的語言標簽。例如,es-*可用於識別任何地區的西班牙語。

   Locale locale = Locale.forLanguageTag("en-GB");
   Locale.LanguageRange r1= new Locale.LanguageRange("es-*",1);
   Locale.LanguageRange r2= new Locale.LanguageRange("de-DE",0.5);
   Locale.LanguageRange r3= new Locale.LanguageRange("en-GB*",0);  

上例中使用的Locale.LanguageRange 構造函數有兩個參數。

第一個參數是語言范圍,第二個參數是權重。通常,這個權重用於表達用戶的偏好。在此示例中,我們創建了從最高用戶偏好到最低用戶偏好的三個范圍。

創建優先級列表

您可以使用一組語言范圍創建優先級列表。

Locale locale = Locale.forLanguageTag("en-GB");
String rangeString = "en-US;q=1.0,en-GB;q=0.5,de-DE;q=0.0";
List<Locale.LanguageRange> rangeList = Locale.LanguageRange.parse(rangeString);

rangeString 是具有一組語言環境及其權重的有效字符串。然后我們使用Locale.LanguageRange 類中的 parse() 方法解析它以創建語言優先級列表。

使用優先級列表過濾標簽

在前面的示例中,我們創建了一個語言優先級列表。在語言標簽過濾過程中,我們將一組語言標簽與優先級列表進行匹配。

String ranges = "en-US;q=1.0,en-GB;q=0.5,de-DE;q=0.0";
List<Locale.LanguageRange> languageRanges = Locale.LanguageRange.parse(ranges);

Collection<Locale> localesList = new ArrayList<>();
localesList.add(Locale.forLanguageTag("en-GB"));
localesList.add(Locale.forLanguageTag("en-US"));
localesList.add(Locale.forLanguageTag("ja-*"));
localesList.add(Locale.forLanguageTag("fe-FE"));

List<Locale> filteredSet = Locale.filter(languageRanges,localesList);
for(Locale locale : filteredSet){
    System.out.println(locale.toString());
}

輸出為:

en_US
en_GB

Locale范圍

Java 中使用語言環境最重要的方面之一是它的范圍。您不必在一個程序中使用相同的語言環境。實際上,您可以為應用程序中使用的每個區域設置敏感對象指定不同的區域設置。

一個有趣的案例是分布式應用程序的開發。假設您的應用程序收到來自不同國家/地區的請求。您如何決定應用程序的語言環境?您在這里可以做的是使用單獨的線程來處理請求並為每個線程分配一個語言環境。

檢索Locale信息

Locale 對象提供了許多方法來獲取有關正在使用的語言環境的信息。讓我們來了解其中的一些。

獲取語言環境

getLanguage()getISO3Language() 方法可用於檢索區域設置的語言。這里, getLanguage() 返回一個 ISO2 字母,而 getISO3Language() 返回一個 ISO3 字母。

Locale locale = Locale.GERMAN;
System.out.println("Locale:" + locale);
System.out.println("ISO 2: " + locale.getLanguage());
System.out.println("ISO 3: " + locale.getISO3Language());

輸出為:

Locale: de
ISO 2: de
ISO 3: deu

首先,我使用 Locale 常量創建了一個 locale 對象。然后,我對該對象調用了 getLanguage() 方法。它返回德語的 ISO2 代碼 de。接下來,我調用 locale.getISO3Language()。它返回了德語的 ISO3 代碼 deu

獲取國家信息

getCountry()getISO3Country() 可用於檢索區域設置的語言。這里, getCountry() 返回 ISO2 字母,而 getISO3Country() 返回 ISO3 字母。

Locale locale = Locale.GERMANY;
System.out.println("Locale: " + locale);
System.out.println("ISO 2 letter: " + locale.getCountry());
System.out.println("ISO 3 letter: " + locale.getISO3Country());

輸出:

Locale: de_DE
ISO 2 letter: DE
ISO 3 letter: DEU

如果您檢查上述示例中的輸出,則這些短格式標簽不適合用戶。 Java Local 對象提供了以更具可讀性的方式返回上述詳細信息的方法。

獲取顯示語言

getDisplayLanguage 方法用於以更常見的方式獲取語言。有兩個覆蓋的 getDisplayLanguage 方法。

如果您使用空參數方法,它將返回默認語言環境中的值。如果您將目標語言環境作為參數傳遞,則此方法將從目標語言環境返回值。

   Locale locale = Locale.GERMANY;
   String defaultLanguage = locale.getDisplayLanguage();
   String targetLanguage = locale.getDisplayLanguage(locale);
   System.out.println(defaultLanguage);
   System.out.println(targetLanguage);

輸出:

German
Deutsch

在第一種情況下,您沒有向 getDisplayLanguage 方法傳遞任何參數。因此,區域設置值(德語)顯示在默認區域設置中,即 en_US。接下來,我將目標語言環境歸因於 getDisplayLanguage 方法。因此顯示 Deutsch

獲取顯示國家

getDisplayCountry 方法將返回以可讀形式調用的語言環境。 getDisplayCountry 方法的工作方式與 getDisplayLanguage 方法類似。

Locale locale = Locale.GERMANY;
String defaultCountry = locale.getDisplayCountry();
String targetCountry = locale.getDisplayCountry(locale);
System.out.println(defaultCountry);
System.out.println(targetCountry);

輸出將與前面的示例非常相似,只是這次將顯示國家/地區。

獲取顯示名稱

getDisplayName 方法可用於獲取調用它的完整區域設置名稱。它的工作原理類似於前兩種方法:

Locale locale = Locale.GERMANY;
String defaultCountry = locale.getDisplayName();
String targetCountry = locale.getDisplayName(locale);
System.out.println(defaultCountry);
System.out.println(targetCountry);

輸出:

German (Germany)
Deutsch (Deutschland)

總結

如果您對本文感到滿意,您可能還想要更進一步了解如何國際化 JSP 應用程序如何國際化 Spring 啟動應用程序

斯蒂芬撰寫。最后更新於 2020 年 8 月 27 日。


免責聲明!

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



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