本Java教程适用于JDK 8。本页面描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
请参阅Java语言变更,了解Java SE 9及后续版本中更新的语言特性摘要。
请参阅JDK发布说明,了解所有JDK版本的新功能、增强功能和已删除或弃用选项的信息。
Java编程语言提供了国际化支持,包括语言标签、语言标签过滤和语言标签查找。这些功能由IETF BCP 47规定,其中包括RFC 5646 "标识语言的标签"和RFC 4647 "匹配语言标签"。本教程描述了JDK中提供的支持。
语言标签是一种特殊格式的字符串,提供有关特定语言的信息。语言标签可以是简单的(例如"en"表示英语),也可以是复杂的(例如"zh-cmn-Hans-CN"表示中国使用的中文、普通话、简化字体),还可以是介于两者之间的(例如"sr-Latn"表示使用拉丁字母的塞尔维亚语)。语言标签由用连字符分隔的"子标签"组成;这个术语在API文档中使用。
java.util.Locale
类提供对语言标签的支持。一个Locale
对象包含多个字段:语言(例如"en"表示英语或"ja"表示日语)、脚本(例如"Latn"表示拉丁字母或"Cyrl"表示西里尔字母)、国家(例如"US"表示美国或"FR"表示法国)、变体(指示区域特定的语言变体)和扩展(提供了一个由单字符键和String
值组成的映射,表示除了语言标识之外的扩展)。要从语言标签String
创建Locale
对象,请调用Locale.forLanguageTag(String)
,并将语言标签作为唯一参数传递进去。这样做会创建并返回一个新的Locale
对象,供应用程序使用。
示例1:
package languagetagdemo; import java.util.Locale; public class LanguageTagDemo { public static void main(String[] args) { Locale l = Locale.forLanguageTag("en-US"); } }
请注意,Locale API只要求您的语言标签在语法上正确。它不执行任何额外的验证(例如,检查标签是否在IANA语言子标记注册表中注册)。
语言范围(由类java.util.Locale.LanguageRange
表示)标识具有特定属性的语言标签集合。语言范围分为基本范围和扩展范围,并且与语言标签类似,由用连字符分隔的子标签组成。基本语言范围的示例包括"en"(英语)、"ja-JP"(日语,日本)和"*"(一个特殊的语言范围,匹配任何语言标签)。扩展语言范围的示例包括"*-CH"(任何语言,瑞士)、"es-*"(西班牙语,任何地区)和"zh-Hant-*"(繁体中文,任何地区)。
有关"ranges"参数所需格式的详细信息,请参阅此方法的API规范。
示例3:
package languagetagdemo; import java.util.Locale; import java.util.List; public class LanguageTagDemo { public static void main(String[] args) { // 创建Locale Locale l = Locale.forLanguageTag("en-US"); // 创建语言优先级列表 String ranges = "en-US;q=1.0,en-GB;q=0.5,fr-FR;q=0.0"; List<Locale.LanguageRange> languageRanges = Locale.LanguageRange.parse(ranges) } }
示例3创建了与示例2相同的三个语言范围,但将它们存储在一个String
对象中,并传递给parse(String)
方法。返回的List
对象是语言优先级列表。
语言标签过滤是将一组语言标签与用户的语言优先级列表进行匹配的过程。过滤的结果将是所有匹配结果的完整列表。Locale
类定义了两个过滤方法,它们返回一个Locale
对象的列表。它们的签名如下:
public static List<Locale> filter (List<Locale.LanguageRange> priorityList, Collection<Locale> locales)
public static List<Locale> filter (List<Locale.LanguageRange> priorityList, Collection<Locale> locales, Locale.FilteringMode mode)
在这两个方法中,第一个参数指定了用户的语言优先级列表,如前一节所述。
第二个参数指定要进行匹配的Locale
对象的Collection
。匹配本身将根据RFC 4647指定的规则进行。
第三个参数(如果提供)指定要使用的"过滤模式"。Locale.FilteringMode
枚举提供了许多不同的值可供选择,例如AUTOSELECT_FILTERING
(用于基本语言范围过滤)或EXTENDED_FILTERING
(用于扩展语言范围过滤)。
示例4提供了语言标签过滤的演示。
示例4:
package languagetagdemo; import java.util.Locale; import java.util.Collection; import java.util.List; import java.util.ArrayList; public class LanguageTagDemo { public static void main(String[] args) { // 创建一个要过滤的Locale对象的集合 Collection<Locale> locales = new ArrayList<>(); locales.add(Locale.forLanguageTag("en-GB")); locales.add(Locale.forLanguageTag("ja")); locales.add(Locale.forLanguageTag("zh-cmn-Hans-CN")); locales.add(Locale.forLanguageTag("en-US")); // 用语言优先级列表表达用户的偏好 String ranges = "en-US;q=1.0,en-GB;q=0.5,fr-FR;q=0.0"; List<Locale.LanguageRange> languageRanges = Locale.LanguageRange.parse(ranges); // 现在过滤Locale对象,返回任何匹配结果 List<Locale> results = Locale.filter(languageRanges,locales); // 打印出匹配结果 for(Locale l : results){ System.out.println(l.toString()); } } }
这个程序的输出结果是:
en_US
en_GB
返回的列表根据用户语言优先级列表中指定的权重进行排序。
Locale
类还定义了用于将语言标签作为String
对象进行过滤的filterTags
方法。
方法签名如下:
public static List<String> filterTags (List<Locale.LanguageRange> priorityList, Collection<String> tags)
public static List<String> filterTags (List<Locale.LanguageRange> priorityList, Collection<String> tags, Locale.FilteringMode mode)
示例5提供了与示例4相同的搜索,但使用了String
对象而不是Locale
对象。
示例5:
package languagetagdemo; import java.util.Locale; import java.util.Collection; import java.util.List; import java.util.ArrayList; public class LanguageTagDemo { public static void main(String[] args) { // 创建一个String对象的集合进行匹配 Collection<String> tags = new ArrayList<>(); tags.add("en-GB"); tags.add("ja"); tags.add("zh-cmn-Hans-CN"); tags.add("en-US"); // 用语言优先级列表表示用户的偏好 String ranges = "en-US;q=1.0,en-GB;q=0.5,fr-FR;q=0.0"; List<Locale.LanguageRange> languageRanges = Locale.LanguageRange.parse(ranges); // 现在搜索最佳匹配的语言环境 List<String> results = Locale.filterTags(languageRanges,tags); // 打印出匹配结果 for(String s : results){ System.out.println(s); } } }
与之前一样,搜索将匹配并返回"en-US"和"en-GB"(按顺序)。
与语言标签过滤相反,语言标签查找是将语言范围与语言标签集合进行匹配,并返回最佳匹配范围的语言标签的过程。RFC4647指出:"查找从可用标签列表中产生与用户偏好最佳匹配的单个结果,因此它在需要单个项的情况下很有用(并且只能返回一个项)。例如,如果一个进程要将可读的错误消息插入到协议头中,它可能会根据用户的语言优先级列表选择文本。由于进程只能返回一个项,它被迫选择一个项并返回某个项,即使没有任何内容的语言标签与用户提供的语言优先级列表匹配。"
示例6:
package languagetagdemo; import java.util.Locale; import java.util.Collection; import java.util.List; import java.util.ArrayList; public class LanguageTagDemo { public static void main(String[] args) { // 创建一个Locale对象的集合进行搜索 Collection<Locale> locales = new ArrayList<>(); locales.add(Locale.forLanguageTag("en-GB")); locales.add(Locale.forLanguageTag("ja")); locales.add(Locale.forLanguageTag("zh-cmn-Hans-CN")); locales.add(Locale.forLanguageTag("en-US")); // 使用语言优先级列表来表示用户的偏好 String ranges = "en-US;q=1.0,en-GB;q=0.5,fr-FR;q=0.0"; List<Locale.LanguageRange> languageRanges = Locale.LanguageRange.parse(ranges); // 找到最佳匹配,并返回一个结果 Locale result = Locale.lookup(languageRanges,locales); System.out.println(result.toString()); } }
与过滤示例相比,示例6中的查找演示返回了一个最佳匹配的对象(在这种情况下是en-US
)。为了完整起见,示例7展示了如何使用String
对象执行相同的查找。
示例7:
package languagetagdemo; import java.util.Locale; import java.util.Collection; import java.util.List; import java.util.ArrayList; public class LanguageTagDemo { public static void main(String[] args) { // 创建一个String对象的集合进行匹配 Collection<String> tags = new ArrayList<>(); tags.add("en-GB"); tags.add("ja"); tags.add("zh-cmn-Hans-CN"); tags.add("en-US"); // 使用语言优先级列表来表示用户的偏好 String ranges = "en-US;q=1.0,en-GB;q=0.5,fr-FR;q=0.0"; List<Locale.LanguageRange> languageRanges = Locale.LanguageRange.parse(ranges); // 找到最佳匹配,并返回一个结果 String result = Locale.lookupTag(languageRanges, tags); System.out.println(result); } }
此示例返回最佳匹配用户语言优先级列表的单个对象。