文档

Java™ 教程
隐藏目录
语言标记过滤和查找
指南: 国际化
课程: 设置区域设置

语言标记过滤和查找

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对象的列表。它们的签名如下:

在这两个方法中,第一个参数指定了用户的语言优先级列表,如前一节所述。

第二个参数指定要进行匹配的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方法。

方法签名如下:

示例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);
    }
} 

此示例返回最佳匹配用户语言优先级列表的单个对象。


上一页: 识别可用的区域设置
下一页: 区域设置的范围