欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Locale

最编程 2024-01-04 14:33:00
...
Locale对象代表特定的地理,政治或文化区域。 需要Locale执行其任务的操作称为区域设置敏感,并使用Locale为用户定制信息。 例如,显示数字是区域设置敏感操作 - 应根据用户原生国家,地区或文化的习惯和惯例格式化数字。

Locale类实现了IETF BCP 47,它由RFC 4647 "Matching of Language Tags"RFC 5646 "Tags for Identifying Languages"组成,支持LDML(UTS#35,“Unicode语言环境数据标记语言”)BCP 47兼容的语言环境数据交换扩展。

Locale对象在逻辑上由下面描述的字段组成。

language
ISO 639 alpha-2或alpha-3语言代码,或注册语言子标签最多8个字母(用于将来的增强)。 当语言同时具有alpha-2代码和alpha-3代码时,必须使用alpha-2代码。 您可以在IANA语言子标签注册表中找到有效语言代码的完整列表(搜索“类型:语言”)。 语言字段不区分大小写,但Locale始终标准化为小写。
格式良好的语言值的格式为[a-zA-Z]{2,8} 请注意,这不是完整的BCP47语言生成,因为它不包括extlang。 由于现代三字母语言代码取代了它们,因此不需要它们。
例如:“en”(英文),“ja”(日文),“kok”(Konkani)
script
ISO 15924 alpha-4脚本代码。 您可以在IANA语言子标签注册表中找到有效脚本代码的完整列表(搜索“类型:脚本”)。 脚本字段不区分大小写,但Locale始终标准化为标题大小写(第一个字母为大写,其余字母为小写)。
格式良好的脚本值的格式为[a-zA-Z]{4}
示例:“Latn”(拉丁语),“Cyrl”(西里尔语)
country (region)
ISO 3166 alpha-2国家代码或UN M.49数字-3区号。 您可以在IANA语言子标签注册表中找到有效国家和地区代码的完整列表(搜索“类型:区域”)。 国家(地区)字段不区分大小写,但Locale始终标准化为大写。
格式良好的国家/地区值的格式为[a-zA-Z]{2} | [0-9]{3}
示例:“US”(美国),“FR”(法国),“029”(加勒比海)
variant
用于表示Locale的变体的任意值。 如果有两个或多个变量值,每个变量值都指示其自己的语义,则这些值应按重要性排序,最重要的是,首先用下划线('_')分隔。 变体字段区分大小写。
注意:IETF BCP 47对变体子标签设置了语法限制。 此外,BCP 47子标签严格用于表示定义语言或其方言的其他变体,这些变体未被语言,脚本和区域子标签的任何组合所涵盖。 您可以在IANA语言子标签注册表中找到有效变体代码的完整列表(搜索“类型:变体”)。

但是, Locale的变体字段历来用于任何类型的变体,而不仅仅是语言变体。 例如,Java SE运行时环境中可用的一些受支持的变体表示其他文化行为,例如日历类型或数字脚本。 在BCP 47中,这种不识别语言的信息由扩展子标签或私人使用子标签支持。

格式良好的变体值的形式为SUBTAG (('_'|'-') SUBTAG)* ,其中SUBTAG = [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8} (注意:BCP 47只使用连字符(' - ')作为分隔符,这样更宽松)。
示例:“polyton”(Polytonic Greek),“POSIX”
extensions
从单个字符键到字符串值的映射,指示除语言标识之外的扩展。 Locale的扩展实现了BCP 47扩展子标签和私有子标签的语义和语法。 扩展名不区分大小写,但Locale所有扩展键和值规范化为小写。 请注意,扩展名不能包含空值。
[0-9a-zA-Z]良好的键是[0-9a-zA-Z]中的单个字符。 格式良好的值的格式为SUBTAG ('-' SUBTAG)* ,其中键' SUBTAG = [0-9a-zA-Z]{1,8}和其他键SUBTAG = [0-9a-zA-Z]{2,8} (即'x'允许单字符子标签)。
示例:key =“u”/ value =“ca-japanese”(日历),key =“x”/ value =“java-1-7”
注意:虽然BCP 47要求在IANA语言子标签注册表中注册字段值,但Locale类不提供任何验证功能。 Builder仅检查单个字段是否满足语法要求(格式正确),但不验证值本身。 有关详细信息,请参见Locale.Builder

Unicode locale/language extension

UTS#35,“Unicode区域设置数据标记语言”定义了可选属性和关键字,以覆盖或优化与区域设置关联的默认行为。 关键字由一对键和类型表示。 例如,“nu-thai”表示应使用泰语本地数字(值:“泰语”)来格式化数字(键:“nu”)。

使用扩展键“u”( UNICODE_LOCALE_EXTENSION )将关键字映射到BCP 47扩展值。 上面的例子“nu-thai”成为“u-nu-thai”的延伸。

因此,当Locale对象包含Unicode语言环境属性和关键字时, getExtension(UNICODE_LOCALE_EXTENSION)将返回表示此信息的String,例如“nu-thai”。 Locale类还提供getUnicodeLocaleAttributes()getUnicodeLocaleKeys()getUnicodeLocaleType(java.lang.String) ,让你可以直接访问Unicode语言环境属性和关键/类型对。 当表示为字符串时,Unicode Locale Extension按字母顺序列出属性,后跟按键/类型序列,按键按字母顺序列出(定义类型时,包含键类型的子标签的顺序是固定的)

格式[0-9a-zA-Z]{2}区域设置键的格式为[0-9a-zA-Z]{2} 格式良好的区域设置类型具有"" | [0-9a-zA-Z]{3,8} ('-' [0-9a-zA-Z]{3,8})*形式(它可以是空的,或者长度为一系列子标签3-8个字母)。 格式良好的区域设置属性的格式为[0-9a-zA-Z]{3,8} (它是一个与区域设置类型子标签形式相同的单个子标签)。

Unicode语言环境扩展指定区分设置敏感服务中的可选行为。 尽管LDML规范定义了各种键和值,但Java Runtime Environment中的实际区域设置敏感服务实现可能不支持任何特定的Unicode语言环境属性或键/类型对。

创建区域设置

有几种不同的方法可以创建Locale对象。

生成器

使用Locale.Builder,您可以构造符合BCP 47语法的Locale对象。

构造函数

Locale类提供了三个构造函数:

     Locale(String language)
     Locale(String language, String country)
     Locale(String language, String country, String variant)
 
这些构造函数允许您使用语言,国家/地区和变体创建Locale对象,但不能指定脚本或扩展名。
工厂方法

方法forLanguageTag(java.lang.String)Locale良好的BCP 47语言标签创建Locale对象。

区域设置常量

Locale类提供了许多方便的常量,您可以使用这些Locale为常用语言环境创建Locale对象。 例如,以下内容为美国创建了一个Locale对象:

     Locale.US
 

Locale Matching

如果应用程序或系统已国际化并为多个区域设置提供本地化资源,则有时需要找到满足每个用户特定首选项的一个或多个区域设置(或语言标记)。 请注意,术语“语言标记”与此区域设置匹配文档中的“区域设置”可互换使用。

为了将用户的首选语言环境与一组语言标记进行匹配, RFC 4647 Matching of Language Tags定义了两种机制:过滤和查找。 过滤用于获取所有匹配的区域设置,而查找用于选择最佳匹配的区域设置。 匹配是不区分大小写的。 以下各节介绍了这些匹配机制。

用户的偏好称为语言优先级列表 ,并表示为语言范围列表。 语法上有两种语言范围:基本和扩展。 有关详细信息,请参见Locale.LanguageRange

过滤

过滤操作返回所有匹配的语言标记。 它在RFC 4647中定义如下:“在过滤中,每个语言范围代表最不具体的语言标记(即,子标记数量最少的语言标记),这是可接受的匹配。匹配集合中的所有语言标记标签的子标签数量等于或大于语言范围的数量。语言范围内的每个非通配符子标签都会出现在每个匹配的语言标签中。“

有两种类型的过滤:基本语言范围的过滤(称为“基本过滤”)和扩展语言范围的过滤(称为“扩展过滤”)。 它们可能会根据给定语言优先级列表中包含的语言范围返回不同的结果。 Locale.FilteringMode是一个参数,用于指定应如何进行过滤。

抬头

查找操作返回最佳匹配语言标记。 它在RFC 4647中定义如下:“与过滤相反,每个语言范围代表最可接受匹配的特定标记。根据用户的优先级找到的第一个匹配标记被认为是最接近的匹配,并且是项目回。”

例如,如果语言优先级列表由两个语言范围"zh-Hant-TW""en-US"组成, "zh-Hant-TW"优先顺序,查找方法逐步搜索下面的语言标记,以便找到最佳匹配语言标记。

    1. zh-Hant-TW
    2. zh-Hant
    3. zh
    4. en-US
    5. en
 
如果语言标记与上述语言范围完全匹配,则返回语言标记。

"*"是特殊语言范围,在查找时会被忽略。

如果有多个语言标签匹配作为子标记的结果'*'包括在语言范围内,所述第一匹配的语言标记由一个返回IteratorCollection语言标记的被视为最佳匹配之一。

使用Locale

创建Locale您可以查询它以获取有关自身的信息。 使用getCountry获取国家(或地区)代码,使用getLanguage获取语言代码。 您可以使用getDisplayCountry获取适合向用户显示的国家/地区名称。 同样,您可以使用getDisplayLanguage获取适合显示给用户的语言名称。 有趣的是, getDisplayXXX方法本身对语言环境敏感,有两个版本:一个使用默认的DISPLAY语言环境,另一个使用指定为参数的语言环境。

Java平台提供了许多执行区域设置敏感操作的类。 例如, NumberFormat类以区域设置敏感的方式格式化数字,货币和百分比。 NumberFormat这样的类有几种方便的方法来创建该类型的默认对象。 例如, NumberFormat类为创建默认的NumberFormat对象提供了以下三种便捷方法:

     NumberFormat.getInstance()
     NumberFormat.getCurrencyInstance()
     NumberFormat.getPercentInstance()
 
这些方法中的每一种都有两种变体; 一个具有明确的语言环境而另一个没有; 后者使用默认的FORMAT语言环境:
     NumberFormat.getInstance(myLocale)
     NumberFormat.getCurrencyInstance(myLocale)
     NumberFormat.getPercentInstance(myLocale)
 
Locale是用于识别您想要获得的对象类型( NumberFormat )的机制。 语言环境只是一种识别对象的机制, 而不是对象本身的容器。

兼容性

为了保持与现有用法的兼容性,Locale的构造函数在Java Runtime Environment 1.7版之前保留其行为。 toString方法也是如此。 因此,Locale对象可以继续按原样使用。 特别是,将toString的输出解析为语言,国家和变体字段的客户端可以继续这样做(尽管强烈建议不要这样做),尽管如果存在脚本或扩展,变体字段中将包含其他信息。

此外,BCP 47强加了语法限制,而不是Locale的构造函数强加的。 这意味着无法在不丢失信息的情况下进行某些Locales和BCP 47语言标记之间的转换。 因此, toLanguageTag不能表示其语言,国家或变体不符合BCP 47的语言环境的状态。

由于存在这些问题,建议客户端不要构建不符合要求的语言环境,而应使用forLanguageTagLocale.Builder API。 因此,希望完整语言环境的字符串表示的客户端可以始终依赖toLanguageTag

Special cases

出于兼容性原因,两个不符合要求的语言环境被视为特殊情况。 这些是ja_JP_JPth_TH_TH 这些在BCP 47中是不正确的,因为变体太短。 为了便于迁移到BCP 47,这些都在施工期间得到了特殊处理。 这两种情况(并且只有这些)导致构造函数生成扩展,所有其他值的行为与Java 7之前完全相同。

Java使用ja_JP_JP代表日本和日本帝国日历一起使用日语。 现在可以使用Unicode语言环境扩展来表示,通过指定Unicode语言环境键ca (用于“日历”)并键入japanese 当使用参数“ja”,“JP”,“JP”调用Locale构造函数时,会自动添加扩展名“u-ca-japanese”。

Java使用th_TH_TH来表示在泰国使用的泰语以及泰国数字。 现在,通过指定Unicode语言环境键nu (“number”)和值thai ,可以使用Unicode语言环境扩展来thai 当使用参数“th”,“TH”,“TH”调用Locale构造函数时,会自动添加扩展名“u-nu-thai”。

序列化

在序列化期间,writeObject将所有字段写入输出流,包括扩展。

在反序列化期间,readResolve添加扩展,如Special Cases中所述 ,仅针对th_TH_TH和ja_JP_JP这两种情况。

旧版语言代码

语言环境的构造一直变换的三个语言代码到其以前的,过时的形式: he映射到iwyi映射到ji ,并id映射到in 这种情况仍然如此,以免破坏向后兼容性。

1.7中添加的API映射旧语言代码和新语言代码,维护旧代码内部的Locale(以便getLanguagetoString反映旧代码),但使用BCP 47语言标记API中的新代码(以便toLanguageTag反映新的那一个)。 无论使用哪种代码或API来构造它们,这都会保留Locales之间的等价性。 Java的默认资源包查找机制也实现了此映射,因此可以使用任一约定命名资源,请参阅ResourceBundle.Control

三个字母的语言/国家(地区)代码

Locale构造函数总是指定语言和国家参数的长度是两个字符,尽管在实践中它们已经接受了任何长度。 该规范现已放宽,允许使用2到8个字符的语言代码和2到3个字符的国家(地区)代码,特别是IANA语言子标签注册表中指定的三字母语言代码和三位数区域代码。 为了兼容性,实现仍然没有强加长度约束。