【译】使用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 日。


God, Grant me the SERENITY, to accept the things I cannot change, COURAGE to change the things I can, and the WISDOM to know the difference.
原文地址:https://www.cnblogs.com/yw0219/p/15680439.html