在Java 8中引入Locale.lookup()
,基于RFC 4647,允许用户根据Locale
的优先级列表找到LocaleRange
列表的最佳匹配。现在我不明白这种方法的每个角落情况。以下公开了一个我希望得到解释的具体案例:
// Create a collection of Locale objects to search
Collection<Locale> locales = new ArrayList<>();
locales.add(Locale.forLanguageTag("en-GB"));
locales.add(Locale.forLanguageTag("en"));
// Express the user's preferences with a Language Priority List
String ranges = "en-US;q=1.0,en-GB;q=1.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());
这会打印en
,我会直观地预期en-GB
。
请注意:
"en-GB;q=1.0,en-US;q=1.0"
范围(GB和US已撤消),则会打印en-GB
,"en-US;q=0.9,en-GB;q=1.0"
(GB的优先级高于美国),则会打印en-GB
。有人可以解释这种行为背后的理由吗?
答案 0 :(得分:8)
如果您提供具有相同优先级的语言备选方案,则列表顺序将变得非常重要。当您检查已解析的"en-US;q=1.0,en-GB;q=1.0"
列表时,这一点就变得很明显了。它包含两个条目,代表"en-US;q=1.0"
,后跟"en-GB;q=1.0"
请参阅https://www.ietf.org/rfc/rfc4647.txt
3.4。查找
查找用于选择最匹配的单一语言标记 给定请求的语言优先级列表。表演时 查找,语言优先级列表中的每个语言范围 根据优先顺序反过来考虑。 ... 根据发现的第一个匹配标签 用户的优先级被认为是最接近的匹配并且是项目 回。例如,如果语言范围是“de-ch”,则查找 操作可以使用标签“de”或“de-CH”生成内容,但从不 带有“de-CH-1996”标签的内容。如果没有语言标签匹配 请求,返回“默认”值。
...
在查找方案中,语言范围逐渐被截断 从最后到匹配的语言标签。 ...
最后一句描述了第一段中已经通过示例说明的内容,即de-CH
的语言范围可能与de-CH
或de
匹配。将对列表中的每个项目执行此回退查找,并在找到匹配项的第一个项目处停止。
换句话说,指定"en-US;q=1.0,en-GB;q=1.0"
就像指定"en-US,en,en-GB,en"
。
也许您想要的是过滤,请参阅
3.3。过滤
过滤用于选择与a匹配的语言标记集 给定语言优先级列表。 ...
在过滤中,每种语言范围代表最不具体 语言标记(即最少数量的语言标记 子标签)这是一个可以接受的匹配。
因此,给出原始的可选区域设置列表
List<Locale> filtered = Locale.filter(
Locale.LanguageRange.parse("en-US;q=1.0,en-GB;q=1.0"), locales);
System.out.println("filtered: "+filtered);
生成[en_GB]
。
,而
Collection<Locale> locales = Arrays.asList(Locale.forLanguageTag("en"),
Locale.forLanguageTag("en-GB"), Locale.forLanguageTag("en-US"));
List<Locale> filtered = Locale.filter(
Locale.LanguageRange.parse("en-US;q=1.0,en-GB;q=1.0"), locales);
System.out.println("filtered: "+filtered);
生成[en_US, en_GB]
(请注意优先顺序和缺少en
后备)。因此,根据上下文,您可能首先尝试从筛选列表中进行选择,并且只有在筛选列表为空时才使用 lookup 。
至少,Java实现的行为符合规范。如您所述,更改优先级或更改顺序(当优先级相等时),根据规范更改结果。
答案 1 :(得分:4)
获得此结果的步骤如下:
en-US
匹配en-GB
吗? →没有en-US
匹配en
吗? →没有en-US
截断为en
en
匹配en-GB
吗? →没有en
匹配en
吗? →是,找到匹配的标签,将其返回根据RFC 4647:
运作<强> 3.4。查找强>
...
根据用户的优先级找到的第一个匹配标记被认为是最接近的匹配,并且是返回的项目。
...
在查找方案中,语言范围从结尾逐步截断,直到找到匹配的语言标记。
查找算法的核心是在sun.util.locale.LocaleMatcher#lookupTag
中实现的。您可以查看source code
答案 2 :(得分:3)
生成SUM(Cast((replace(replace(replace (p.[Total Sales], '$', ''), '(','-'), ')','')) as money)) - SUM(Cast((replace(replace(replace (p.[Total Cost], '$', ''), '(','-'), ')','')) as money)) / SUM(Cast((replace(replace(replace (p.[Total Sales], '$', ''), '(','-'), ')','')) as money)) as new_bal
的给定范围的解析:
Language Priority List
优先级列表为"en-US;q=1.0,en-GB;q=1.0"
]
[en-us;=1.0,en-gb;=1.0
优先级列表为"en-GB;q=1.0,en-US;q=1.0"
]
[en-gb;=1.0,en-us;=1.0
优先级列表为"en-US;q=0.9,en-GB;q=1.0"
]
然后查找方法遵循此优先级列表,直到找到匹配的区域设置(根据RFC 4647 ):
[en-gb;=1.0,en-us;=0.9
,算法首先使用en-us;=1.0,en-gb;=1.0
,其中最匹配的区域设置为en-us;=1.0
en
,算法首先使用en-gb;=1.0,en-us;=1.0
,其中最匹配的区域设置为en-gb;=1.0
en-GB
,算法首先使用en-gb;=1.0,en-us;=0.9
,其中最匹配的区域设置为en-gb;=1.0