语言标记过滤和查找

Java 编程语言包含对语言标签,语言标签过滤和语言标签查找的国际化支持。这些功能由IETF BCP 47指定,其中IETF BCP 47包含RFC 5646“用于识别语言的标签”RFC 4647“语言标签的匹配”。。本类描述了如何在 JDK 中提供此支持。

什么是语言标签?

语言标签是特殊格式的字符串,可提供有关特定语言的信息。语言标签可能很简单(例如在英语中为“ en”),或者很复杂(例如在中国使用的中文,中文,简体字为“ zh-cmn-Hans-CN”),或介于两者之间(如“ sr-Latn”,用于使用拉丁 Literals 写成的塞尔维亚语)。语言标签由连字符分隔的“子标签”组成;该术语在 API 文档中使用。

java.util.Locale类提供对语言标记的支持。 Locale包含几个不同的字段:语言(例如,英语的“ en”或日语的“ ja”),脚本(例如拉丁语的“ Latn”或西里尔字母的“ Cyrl”),国家/地区(例如“ US”美国或“ FR”(法国)),变体(表示语言环境的某种变体)和 extensions(提供单个字符键到String值的 Map,表示除语言标识之外的 extensions)。要从语言标签String创建Locale对象,请调用Locale.forLanguageTag(String),并将语言标签作为唯一参数传入。这样做会创建并返回一个新的Locale对象供您的应用程序使用。

Example 1:

package languagetagdemo;

import java.util.Locale;

public class LanguageTagDemo {
     public static void main(String[] args) {
         Locale l = Locale.forLanguageTag("en-US");
     }
}

请注意,区域设置 API 仅要求您的语言标签的语法格式正确。它不会执行任何额外的验证(例如检查标签是否已在 IANA 语言子标签注册表中注册)。

什么是语言范围?

语言范围(由类java.util.Locale.LanguageRange表示)标识共享特定属性的语言标签集。语言范围分为基本的或扩展的,并且与语言标签类似,因为它们由连字符分隔的子标签组成。基本语言范围的示例包括“ en”(英语),“ ja-JP”(日语,日本)和“ ”(与任何语言标签匹配的特殊语言范围)。扩展语言范围的示例包括“ * -CH”(任何语言,瑞士),“ es-”(西班牙语,任何区域)和“ zh-Hant-*”(繁体中文,任何区域)。

此外,语言范围可以存储在语言优先级列表中,这使用户能够在加权列表中确定其语言偏好的优先级。语言优先级列表是通过将LanguageRange个对象放入java.util.List来表示的,然后可以将它们传递给接受_5 个对象的List个的Locale个方法。

创建语言范围

Locale.LanguageRange类为创建语言范围提供了两种不同的构造函数:

  • public Locale.LanguageRange(String range)

  • public Locale.LanguageRange(String range, double weight)

它们之间的唯一区别是第二种版本允许指定权重;如果将范围放入“语言优先级列表”,则将考虑此权重。

Locale.LanguageRange还指定了一些可与这些构造函数一起使用的常量:

  • public static final double MAX_WEIGHT

  • public static final double MIN_WEIGHT

MAX_WEIGHT常量的值为 1.0,表示它非常适合用户。 MIN_WEIGHT常数的值为 0.0,表示不是。

Example 2:

package languagetagdemo;

import java.util.Locale;

public class LanguageTagDemo {

     public static void main(String[] args) {
         // Create Locale
         Locale l = Locale.forLanguageTag("en-US");

         // Define Some LanguageRange Objects
         Locale.LanguageRange range1 = new Locale.LanguageRange("en-US",Locale.LanguageRange.MAX_WEIGHT);
         Locale.LanguageRange range2 = new Locale.LanguageRange("en-GB*",0.5);
         Locale.LanguageRange range3 = new Locale.LanguageRange("fr-FR",Locale.LanguageRange.MIN_WEIGHT);
     }
}

示例 2 创建了三种语言范围:英语(美国),英语(英国)和法语(法国)。对这些范围进行加权,以从最优选到最不喜欢的 Sequences 表达用户的偏好。

创建语言优先级列表

您可以使用LanguageRange.parse(String)方法从语言范围列表中创建语言优先级列表。此方法接受逗号分隔的语言范围列表,对给定范围内的每种语言范围执行语法检查,然后返回新创建的“语言优先级列表”。

有关所需的“范围”参数格式的详细信息,请参阅此方法的 API 规范。

Example 3:

package languagetagdemo;

import java.util.Locale;

import java.util.List;

public class LanguageTagDemo {

    public static void main(String[] args) {

        // Create Locale

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

        // Create a Language Priority List

        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)方法。返回的LanguageRange个对象中的List是语言优先级列表。

过滤语言标签

语言标签过滤是将一组语言标签与用户的“语言优先级列表”进行匹配的过程。过滤的结果将是所有匹配结果的完整列表。 Locale类定义了两个过滤器方法,这些方法返回Locale对象的列表。它们的签名如下:

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

第二个参数指定要匹配的Collection个(共Locale个)对象。匹配本身将根据 RFC 4647 指定的规则进行。

第三个参数(如果提供)指定要使用的“过滤 Pattern”。 Locale.FilteringMode枚举提供许多不同的值供您选择,例如AUTOSELECT_FILTERING(用于基本语言范围过滤)或EXTENDED_FILTERING(用于扩展语言范围过滤)。

示例 4 提供了语言标签过滤的演示。

Example 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) {

        // Create a collection of Locale objects to filter
        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"));

        // Express the user's preferences with a Language Priority List
        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);

        // Now filter the Locale objects, returning any matches
        List<Locale> results = Locale.filter(languageRanges,locales);

        // Print out the matches
        for(Locale l : results){
        System.out.println(l.toString());
        }
    }
}

该程序的输出为:

en_US
en_GB

该返回的列表是根据用户的“语言优先级列表”中指定的权重排序的。

Locale类还定义了filterTags个用于将语言标签过滤为String个对象的方法。

方法签名如下:

示例 5 提供与示例 4 相同的搜索,但是使用String个对象而不是Locale个对象。

Example 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) {

        // Create a collection of String objects to match against
        Collection<String> tags = new ArrayList<>();
        tags.add("en-GB");
        tags.add("ja");
        tags.add("zh-cmn-Hans-CN");
        tags.add("en-US");

        // Express user's preferences with a Language Priority List
        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);

        // Now search the locales for the best match
        List<String> results = Locale.filterTags(languageRanges,tags);

        // Print out the matches
        for(String s : results){
            System.out.println(s);
        }
    }
}

与以前一样,搜索将匹配并返回“ en-US”和“ en-GB”(按该 Sequences)。

执行语言标签查询

与语言标签过滤相比,语言标签查找是将语言范围与语言标签集进行匹配并返回最匹配该范围的一种语言标签的过程。 RFC4647 指出:“查阅会产生与可用标签列表中的用户首选项最匹配的单个结果,因此在需要单个项目(并且只能返回单个项目)的情况下很有用。例如,如果某个过程将易读的错误消息插入到协议 Headers 中,则它可能会根据用户的语言优先级列表来选择文本,因为该过程只能返回一个项目,所以它被迫选择一个项目,然后即使内容的语言标签均与用户提供的语言优先级列表都不匹配,它也必须返回某些项目。”

Example 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) {

        // Create a collection of Locale objects to search
        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"));

        // Express the user's preferences with a Language Priority List
        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);

        // Find the BEST match, and return just one result
        Locale result = Locale.lookup(languageRanges,locales);
        System.out.println(result.toString());
    }
}

与过滤示例相反,示例 6 中的查找演示返回一个最匹配的对象(在这种情况下为en-US)。为了完整起见,示例 7 显示了如何使用String对象执行相同的查找。

Example 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) {
        // Create a collection of String objects to match against
        Collection<String> tags = new ArrayList<>();
        tags.add("en-GB");
        tags.add("ja");
        tags.add("zh-cmn-Hans-CN");
        tags.add("en-US");

        // Express user's preferences with a Language Priority List
        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);

        // Find the BEST match, and return just one result
        String result = Locale.lookupTag(languageRanges, tags);
        System.out.println(result);
    }
}

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