2023年6月13日
原文链接:http://peter.eisentraut.org/blog/2023/06/13/overview-of-icu-collation-settings-part-2
作者:Peter Eisentraut(彼得·艾森特劳特)
在一篇最近的文章中,我介绍了ICU的参数化排序定制设置。在今天的文章中,我将描述另一种主要的排序定制选项:使用语言环境标识符中的键选择的替代排序类型co
。
了解可用的排序类型及其功能的最佳方式是查看源代码,而ICU的源代码即来自CLDR项目。让我们从CLDR中的键定义开始。(在本文中,所有的URL都是针对特定的CLDR版本,这是我撰写本文时的最新版本,因为如下所述,这些内容会随着时间而变化。)
还有一项有趣的内容是在相关标准UTS #35中定义的部分:http://unicode.org/reports/tr35/#UnicodeCollationIdentifier
作为提醒,在将这些选项用于可以传递给PostgreSQL(或其他ICU应用程序)的语言环境字符串时,语法可能类似于(新)或(旧).de-u-co-phonebk``de@collation=phonebook
现在让我们逐个解释这些选项的作用。我在下面给出一些示例,但其中许多示例适用于我不太熟悉的字符,因此我将避免在这些示例中给出具体的例子。
描述:拉丁字母使用拼音排序,CJK字符(用于中文)使用big5字符集排序
这种排序类型仅出现在zh
(中文)排序中。拼音是汉字的罗马拼音系统。Big5是一种用于中文的Unicode之前的字符编码。因此,这是为了与特定的Unicode之前的约定兼容而提供的排序方式。
参考gb2312以了解类似的概念。
描述:用于兼容性的之前版本排序方式
这种排序类型仅出现在ar
(阿拉伯语)排序中。
这是不言自明的:标准排序方式进行了调整,而之前的版本可作为“compat”类型使用。
描述:词典风格排序(例如在僧伽罗语中)
这种排序类型仅出现在si
(僧伽罗语)排序中。它相对于僧伽罗语的标准排序方式进行了一些微小的修改。
描述:二进制码点顺序(用于印地语)(已弃用)
该排序类型以前出现在(印地语)排序中,但在2012年被移除。hi
(PostgreSQL注:要获得二进制码点顺序,可以使用C
或ucs_basic
排序。)
描述:默认的Unicode排序元素表顺序
该排序类型当前在CLDR的任何排序中不存在。DUCET是实际的Unicode标准,而CLDR是实现如ICU的数据文件集。CLDR稍微修改(“tailored”)自DUCET。此排序类型的目的是允许用户选择一个未经修饰的纯标准排序。在2012年的CLDR中曾短暂存在,但很快发现它无法完全工作并且难以维护。ducet
描述:表情符号字符的推荐排序
这个排序类型出现在根排序中。
有一个单独的标准UTS #51用于对表情符号字符进行排序,这个排序类型实现了该标准。例如,在输入选择器中展示表情符号字符时,可以使用这个排序类型。
示例:
select chr(x) from generate_series(x'1F634'::int, x'1F644'::int) as _(x)
order by chr(x);
chr
-----
create collation c1 (provider = icu, locale = 'und-u-co-emoji');
select chr(x) from generate_series(x'1F634'::int, x'1F644'::int) as _(x)
order by chr(x) collate c1;
chr
-----
你可以在这里看到,默认排序将表情符号字符以相当随机的顺序排列。而表情符号排序将它们分组(笑脸,猫)并且组内有一致的顺序(开心,中性,伤心)。详情请参阅UTS #51。
描述:“欧洲排序规则”
此排序类型出现在根排序中,并且在de
(德语)排序中有一个“国家增量”。
欧洲排序规则是一种用于对拉丁文、希腊文、西里尔文、格鲁吉亚文和亚美尼亚文字符进行排序的标准(EN 13710),即在欧洲使用的语言中使用的字符。但是,你知道,UCA也可以做到这一点。根据这一历史,似乎这是在等同的Unicode标准完全被接受之前就开始开发的,我认为现在这已经基本过时了。
描述:“拼音排序(用于拉丁文),gb2312han字符集排序(用于CJK字符,即中文)”
此排序类型仅出现在zh
(中文)排序中。拼音是一种用于汉字的罗马化系统。GB 2312是一种用于汉字的(也称为EUC-CN的)预Unicode字符编码。因此,这是为了与特定的预Unicode约定兼容而提供的排序方式。
另请参见big5han以获取类似的想法。
描述:“电话簿风格排序(例如德语)”
此排序类型仅出现在de
(德语)和de_AT
(奥地利德语)排序中。
德国标准DIN 5007指定了字符字符串的排序。它包含两个部分:一个通用部分和一个用于排序名称列表的部分。第一部分实际上与Unicode根排序相同,第二部分通常称为电话簿排序,但实际上适用于任何人名列表。
在CLDR中,对于排序,该排序类型添加了以下规则:de
&AE<<ä<<<Ä
&OE<<ö<<<Ö
&UE<<ü<<<Ü
对于ä
,此排序类型在后面加入了一个次要差异,并随后加入了一个三级差异,以此类推对于其他元音字母。
对于de_AT
,该排序类型添加了以下规则:
&a<ä<<<Ä
&o<ö<<<Ö
&u<ü<<<Ü
&ss<ß<<<ẞ
这表示该字母在字母“a”之后作为单独的字母进行排序(主要差异),以此类推。
示例:
create collation german (provider = icu, locale = 'de');
create collation german_phonebook (provider = icu,
locale = 'de-u-co-phonebk');
create collation austrian_phonebook (provider = icu,
locale = 'de-AT-u-co-phonebk');
select *
from (values ('Göbel'), ('Goethe'), ('Goldmann'), ('Göthe'), ('Götz')) _(x)
order by x collate german;
x
-----------
Göbel
Goethe
Goldmann
Göthe
Götz
(这与根排序相同。)
select *
from (values ('Göbel'), ('Goethe'), ('Goldmann'), ('Göthe'), ('Götz')) _(x)
order by x collate german_phonebook;
x
-----------
Göbel
Goethe
Göthe
Götz
Goldmann
select *
from (values ('Göbel'), ('Goethe'), ('Goldmann'), ('Göthe'), ('Götz')) _(x)
order by x collate austrian_phonebook;
x
-----------
Goethe
Goldmann
Göbel
Göthe
Götz
请参考https://de.wikipedia.org/wiki/Alphabetische_Sortierung#Deutsche_Sprache,了解更多关于德语中各种排序变体的详细信息。
描述:按照发音进行排序(基于发音的排序)
这个排序类型只出现在ln
(林加拉语)排序中。我对此没有实际的了解,但很明显,这个排序类型修改了一些字母和字母组的顺序,使其更符合发音。
描述:拼音排序(用于拉丁字母和CJK字符(中文中使用))
这个排序类型只出现在zh
(中文)排序中。拼音是一种用于表示汉字发音的罗马字转写系统。因此,这个排序类型基本上按照拉丁字母的类似排序方式来对中文字符进行排序。
描述:改革后的排序(如瑞典语)
这个排序类型目前没有出现在任何排序中。它之前出现在sv
(瑞典语)排序中。在2022年7月,瑞典语的“reformed”排序被改名为“standard”,而之前的标准排序被改为“traditional”。
改革后(现在的标准)类型和传统(之前的标准)类型之间唯一的区别是改革后类型省略了以下规则:
&v<<
也就是说,将 w/W 排在 v/V 的第二级变体之后。
另请参阅trad
。
“一种用于字符串搜索的特殊排序类型”
该排序类型出现在根排序和许多语言特定的排序中(但据我所知,大多数,如果不是全部,语言特定文件中的出现只是导入了来自根排序的搜索规则,然后应用语言特定的标准规则。似乎没有太多语言特定的搜索规则,但我没有详尽地检查过)。
根据UTS #35的描述:
一种专门用于字符串搜索的特殊排序类型,它不用于确定两个字符串的相对顺序,而仅用于确定它们在指定的强度下是否应被视为等效,使用适用于语言的字符串搜索匹配规则。与语言的普通排序器相比,这种排序器可能添加或删除主要等效性,可能使其他字符可忽略或更改次要等效性,并且可能修改缩写以允许在其中进行匹配,具体取决于所需的行为。例如,在捷克语中,普通排序中的‘a’和‘á’之间的区别是次要的,但在搜索中是主要的;搜索‘a’不应匹配‘á’,反之亦然。通常,搜索排序器的强度设置为PRIMARY或SECONDARY(如果使用[UCA]中描述的“非对称”搜索,则应为SECONDARY)。根排序中的搜索排序器提供了适用于大多数语言的匹配规则(与根排序行为不同);可以提供特定语言的搜索排序器,以根据需要覆盖给定语言的匹配规则。
有趣的是,引用的捷克语示例在CLDR中已经被移除。它在2016年被删除。给出的理由是:
这个变化部分原因是捷克用户已经习惯了谷歌在捷克语中的搜索方式;由于网络搜索是最常见的搜索行为,它会对其他搜索行为产生期望。
所以就是这样。
根排序中的大多数搜索规则涉及阿拉伯语和韩语等非拉丁字母表,对此我了解甚少,所以不会深入研究。
我能解读的一个规则是
# root search rules for Symbols
&'='<'≠'
这意味着将不等号排在等号之后,两者之间有一个主要差别。
这些字符的默认排序权重为:
003D ; [*06A2.0020.0002] # EQUALS SIGN
2260 ; [*06A2.0020.0002][.0000.002F.0002] # NOT EQUAL TO
这将把不等号当作等号的一种“重音”(次要差别)来处理。这在排序时可能是合理的,但在搜索时可能会产生奇怪的结果。
如果你使用主要排序强度创建一个排序规则,你的搜索结果会是这样的:
create collation c1 (provider = icu,
locale = 'und-u-co-standard-ks-level1',
deterministic = false);
select * from (values (u&'x\003Dy'), (u&'x\2260y')) _(x)
where x collate c1 = 'x=y';
x
-----
x=y
x≠y
这可能是不可取的。如果你使用搜索排序规则,你会得到更好的结果:
create collation c2 (provider = icu,
locale = 'und-u-co-search-ks-level1',
deterministic = false);
select * from (values (u&'x\003Dy'), (u&'x\2260y')) _(x)
where x collate c2 = 'x=y';
x
-----
x=y
(PostgreSQL备注:在这里需要使用deterministic = false
属性进行排序。)
描述:用于韩语初始辅音搜索的特殊排序类型。
该排序类型仅出现在ko
(韩语)排序中。
描述:每种语言的默认排序顺序。
这是默认值。因此,指定一个排序类型,例如en-u-co-standard
等效于直接写入en
。
描述:拉丁字母的拼音排序,汉字的笔画顺序(用于中文)。
该排序类型仅出现在zh
(中文)排序中。
描述:传统风格的排序(例如西班牙语)。
此排序类型出现在排序bn
(孟加拉语)、es
(西班牙语)、fi
(芬兰语)、kn
(卡纳达语)、sa
(梵语)和vi
(越南语)中。
例如,西班牙语的“传统”排序具有以下附加规则:
&C
这将将ch
和ll
作为单独的字母(主要差异)按照字母顺序排序。西班牙语语言学院已经删除了这一规则。但它仍然在CLDR/ICU中提供,供那些需要的人使用。
类似地,在其他语言中,一些传统规则随着时间的推移而被删除,以使语言规则更适应计算机时代(我猜测)。另请参见reformed
,当新规则还没有准备好
成为标准规则时,以及compat
相关概念。
描述:拉丁字母的拼音排序,CJK(中日韩)字符的部首-笔画顺序(用于中文)。
该排序类型出现在ja
(日语)、ko
(韩语)和zh
(中文)排序中。
Unihan 是指Unicode中用于日语、韩语和中文字符的汉字统一表意文字。
描述:拉丁字母的拼音排序,注音顺序用于注音符号和CJK(中日韩)字符(用于中文)。
该排序类型仅出现在zh
(中文)排序中。注音是中文的一个音译和书写系统。
从本讨论中可以看出,这些替代排序类型有各种各样的原因。其中一些是为了与先前的惯例或其他标准兼容,一些是短暂的实验,一些是针对单个语言的需求,还有一些是特别针对中文语言的。实际上,所有这些排序类型只是一组打包在名称下的排序自定义规则。如果您的需求超出了这个范围,您也可以自己编写规则,PostgreSQL从16版本开始将支持这一点。