Make unaccent handle all diacritics known to Unicode, and expand ligatures correctly
Add Python script for buiding unaccent.rules from Unicode data. Don't backpatch because unaccent changes may require tsvector/index rebuild. Thomas Munro <thomas.munro@enterprisedb.com>
This commit is contained in:
parent
4aec49899e
commit
1bbd52cb9a
123
contrib/unaccent/generate_unaccent_rules.py
Normal file
123
contrib/unaccent/generate_unaccent_rules.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# This script builds unaccent.rules on standard output when given the
|
||||||
|
# contents of UnicodeData.txt[1] on standard input. Optionally includes
|
||||||
|
# ligature expansion, if --expand-ligatures is given on the command line.
|
||||||
|
#
|
||||||
|
# The approach is to use the Unicode decomposition data to identify
|
||||||
|
# precomposed codepoints that are equivalent to a ligature of several
|
||||||
|
# letters, or a base letter with any number of diacritical marks.
|
||||||
|
# There is also a small set of special cases for codepoints that we
|
||||||
|
# traditionally support even though Unicode doesn't consider them to
|
||||||
|
# be ligatures or letters with marks.
|
||||||
|
#
|
||||||
|
# [1] http://unicode.org/Public/7.0.0/ucd/UnicodeData.txt
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def print_record(codepoint, letter):
|
||||||
|
print (unichr(codepoint) + "\t" + letter).encode("UTF-8")
|
||||||
|
|
||||||
|
class Codepoint:
|
||||||
|
def __init__(self, id, general_category, combining_ids):
|
||||||
|
self.id = id
|
||||||
|
self.general_category = general_category
|
||||||
|
self.combining_ids = combining_ids
|
||||||
|
|
||||||
|
def is_plain_letter(codepoint):
|
||||||
|
"""Return true if codepoint represents a plain ASCII letter."""
|
||||||
|
return (codepoint.id >= ord('a') and codepoint.id <= ord('z')) or \
|
||||||
|
(codepoint.id >= ord('A') and codepoint.id <= ord('Z'))
|
||||||
|
|
||||||
|
def is_mark(codepoint):
|
||||||
|
"""Returns true for diacritical marks (combining codepoints)."""
|
||||||
|
return codepoint.general_category in ("Mn", "Me", "Mc")
|
||||||
|
|
||||||
|
def is_letter_with_marks(codepoint, table):
|
||||||
|
"""Returns true for plain letters combined with one or more marks."""
|
||||||
|
# See http://www.unicode.org/reports/tr44/tr44-14.html#General_Category_Values
|
||||||
|
return len(codepoint.combining_ids) > 1 and \
|
||||||
|
is_plain_letter(table[codepoint.combining_ids[0]]) and \
|
||||||
|
all(is_mark(table[i]) for i in codepoint.combining_ids[1:])
|
||||||
|
|
||||||
|
def is_letter(codepoint, table):
|
||||||
|
"""Return true for letter with or without diacritical marks."""
|
||||||
|
return is_plain_letter(codepoint) or is_letter_with_marks(codepoint, table)
|
||||||
|
|
||||||
|
def get_plain_letter(codepoint, table):
|
||||||
|
"""Return the base codepoint without marks."""
|
||||||
|
if is_letter_with_marks(codepoint, table):
|
||||||
|
return table[codepoint.combining_ids[0]]
|
||||||
|
elif is_plain_letter(codepoint):
|
||||||
|
return codepoint
|
||||||
|
else:
|
||||||
|
raise "mu"
|
||||||
|
|
||||||
|
def is_ligature(codepoint, table):
|
||||||
|
"""Return true for letters combined with letters."""
|
||||||
|
return all(is_letter(table[i], table) for i in codepoint.combining_ids)
|
||||||
|
|
||||||
|
def get_plain_letters(codepoint, table):
|
||||||
|
"""Return a list of plain letters from a ligature."""
|
||||||
|
assert(is_ligature(codepoint, table))
|
||||||
|
return [get_plain_letter(table[id], table) for id in codepoint.combining_ids]
|
||||||
|
|
||||||
|
def main(expand_ligatures):
|
||||||
|
# http://www.unicode.org/reports/tr44/tr44-14.html#Character_Decomposition_Mappings
|
||||||
|
decomposition_type_pattern = re.compile(" *<[^>]*> *")
|
||||||
|
|
||||||
|
table = {}
|
||||||
|
all = []
|
||||||
|
|
||||||
|
# read everything we need into memory
|
||||||
|
for line in sys.stdin.readlines():
|
||||||
|
fields = line.split(";")
|
||||||
|
if len(fields) > 5:
|
||||||
|
# http://www.unicode.org/reports/tr44/tr44-14.html#UnicodeData.txt
|
||||||
|
general_category = fields[2]
|
||||||
|
decomposition = fields[5]
|
||||||
|
decomposition = re.sub(decomposition_type_pattern, ' ', decomposition)
|
||||||
|
id = int(fields[0], 16)
|
||||||
|
combining_ids = [int(s, 16) for s in decomposition.split(" ") if s != ""]
|
||||||
|
codepoint = Codepoint(id, general_category, combining_ids)
|
||||||
|
table[id] = codepoint
|
||||||
|
all.append(codepoint)
|
||||||
|
|
||||||
|
# walk through all the codepoints looking for interesting mappings
|
||||||
|
for codepoint in all:
|
||||||
|
if codepoint.general_category.startswith('L') and \
|
||||||
|
len(codepoint.combining_ids) > 1:
|
||||||
|
if is_letter_with_marks(codepoint, table):
|
||||||
|
print_record(codepoint.id,
|
||||||
|
chr(get_plain_letter(codepoint, table).id))
|
||||||
|
elif expand_ligatures and is_ligature(codepoint, table):
|
||||||
|
print_record(codepoint.id,
|
||||||
|
"".join(unichr(combining_codepoint.id)
|
||||||
|
for combining_codepoint \
|
||||||
|
in get_plain_letters(codepoint, table)))
|
||||||
|
|
||||||
|
# some special cases
|
||||||
|
print_record(0x00d8, "O") # LATIN CAPITAL LETTER O WITH STROKE
|
||||||
|
print_record(0x00f8, "o") # LATIN SMALL LETTER O WITH STROKE
|
||||||
|
print_record(0x0110, "D") # LATIN CAPITAL LETTER D WITH STROKE
|
||||||
|
print_record(0x0111, "d") # LATIN SMALL LETTER D WITH STROKE
|
||||||
|
print_record(0x0131, "i") # LATIN SMALL LETTER DOTLESS I
|
||||||
|
print_record(0x0126, "H") # LATIN CAPITAL LETTER H WITH STROKE
|
||||||
|
print_record(0x0127, "h") # LATIN SMALL LETTER H WITH STROKE
|
||||||
|
print_record(0x0141, "L") # LATIN CAPITAL LETTER L WITH STROKE
|
||||||
|
print_record(0x0142, "l") # LATIN SMALL LETTER L WITH STROKE
|
||||||
|
print_record(0x0149, "'n") # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
|
||||||
|
print_record(0x0166, "T") # LATIN CAPITAL LETTER T WITH STROKE
|
||||||
|
print_record(0x0167, "t") # LATIN SMALL LETTER t WITH STROKE
|
||||||
|
print_record(0x0401, u"\u0415") # CYRILLIC CAPITAL LETTER IO
|
||||||
|
print_record(0x0451, u"\u0435") # CYRILLIC SMALL LETTER IO
|
||||||
|
if expand_ligatures:
|
||||||
|
print_record(0x00c6, "AE") # LATIN CAPITAL LETTER AE
|
||||||
|
print_record(0x00df, "ss") # LATIN SMALL LETTER SHARP S
|
||||||
|
print_record(0x00e6, "ae") # LATIN SMALL LETTER AE
|
||||||
|
print_record(0x0152, "OE") # LATIN CAPITAL LIGATURE OE
|
||||||
|
print_record(0x0153, "oe") # LATIN SMALL LIGATURE OE
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(len(sys.argv) == 2 and sys.argv[1] == "--expand-ligatures")
|
@ -4,22 +4,59 @@
|
|||||||
à A
|
à A
|
||||||
Ä A
|
Ä A
|
||||||
Å A
|
Å A
|
||||||
Æ A
|
Ç C
|
||||||
|
È E
|
||||||
|
É E
|
||||||
|
Ê E
|
||||||
|
Ë E
|
||||||
|
Ì I
|
||||||
|
Í I
|
||||||
|
Î I
|
||||||
|
Ï I
|
||||||
|
Ñ N
|
||||||
|
Ò O
|
||||||
|
Ó O
|
||||||
|
Ô O
|
||||||
|
Õ O
|
||||||
|
Ö O
|
||||||
|
Ù U
|
||||||
|
Ú U
|
||||||
|
Û U
|
||||||
|
Ü U
|
||||||
|
Ý Y
|
||||||
à a
|
à a
|
||||||
á a
|
á a
|
||||||
â a
|
â a
|
||||||
ã a
|
ã a
|
||||||
ä a
|
ä a
|
||||||
å a
|
å a
|
||||||
æ a
|
ç c
|
||||||
|
è e
|
||||||
|
é e
|
||||||
|
ê e
|
||||||
|
ë e
|
||||||
|
ì i
|
||||||
|
í i
|
||||||
|
î i
|
||||||
|
ï i
|
||||||
|
ñ n
|
||||||
|
ò o
|
||||||
|
ó o
|
||||||
|
ô o
|
||||||
|
õ o
|
||||||
|
ö o
|
||||||
|
ù u
|
||||||
|
ú u
|
||||||
|
û u
|
||||||
|
ü u
|
||||||
|
ý y
|
||||||
|
ÿ y
|
||||||
Ā A
|
Ā A
|
||||||
ā a
|
ā a
|
||||||
Ă A
|
Ă A
|
||||||
ă a
|
ă a
|
||||||
Ą A
|
Ą A
|
||||||
ą a
|
ą a
|
||||||
Ç C
|
|
||||||
ç c
|
|
||||||
Ć C
|
Ć C
|
||||||
ć c
|
ć c
|
||||||
Ĉ C
|
Ĉ C
|
||||||
@ -30,16 +67,6 @@
|
|||||||
č c
|
č c
|
||||||
Ď D
|
Ď D
|
||||||
ď d
|
ď d
|
||||||
Đ D
|
|
||||||
đ d
|
|
||||||
È E
|
|
||||||
É E
|
|
||||||
Ê E
|
|
||||||
Ë E
|
|
||||||
è e
|
|
||||||
é e
|
|
||||||
ê e
|
|
||||||
ë e
|
|
||||||
Ē E
|
Ē E
|
||||||
ē e
|
ē e
|
||||||
Ĕ E
|
Ĕ E
|
||||||
@ -60,17 +87,7 @@
|
|||||||
ģ g
|
ģ g
|
||||||
Ĥ H
|
Ĥ H
|
||||||
ĥ h
|
ĥ h
|
||||||
Ħ H
|
|
||||||
ħ h
|
|
||||||
Ĩ I
|
Ĩ I
|
||||||
Ì I
|
|
||||||
Í I
|
|
||||||
Î I
|
|
||||||
Ï I
|
|
||||||
ì i
|
|
||||||
í i
|
|
||||||
î i
|
|
||||||
ï i
|
|
||||||
ĩ i
|
ĩ i
|
||||||
Ī I
|
Ī I
|
||||||
ī i
|
ī i
|
||||||
@ -79,62 +96,36 @@
|
|||||||
Į I
|
Į I
|
||||||
į i
|
į i
|
||||||
İ I
|
İ I
|
||||||
ı i
|
IJ IJ
|
||||||
IJ I
|
ij ij
|
||||||
ij i
|
|
||||||
Ĵ J
|
Ĵ J
|
||||||
ĵ j
|
ĵ j
|
||||||
Ķ K
|
Ķ K
|
||||||
ķ k
|
ķ k
|
||||||
ĸ k
|
|
||||||
Ĺ L
|
Ĺ L
|
||||||
ĺ l
|
ĺ l
|
||||||
Ļ L
|
Ļ L
|
||||||
ļ l
|
ļ l
|
||||||
Ľ L
|
Ľ L
|
||||||
ľ l
|
ľ l
|
||||||
Ŀ L
|
|
||||||
ŀ l
|
|
||||||
Ł L
|
|
||||||
ł l
|
|
||||||
Ñ N
|
|
||||||
ñ n
|
|
||||||
Ń N
|
Ń N
|
||||||
ń n
|
ń n
|
||||||
Ņ N
|
Ņ N
|
||||||
ņ n
|
ņ n
|
||||||
Ň N
|
Ň N
|
||||||
ň n
|
ň n
|
||||||
ʼn n
|
|
||||||
Ŋ N
|
|
||||||
ŋ n
|
|
||||||
Ò O
|
|
||||||
Ó O
|
|
||||||
Ô O
|
|
||||||
Õ O
|
|
||||||
Ö O
|
|
||||||
ò o
|
|
||||||
ó o
|
|
||||||
ô o
|
|
||||||
õ o
|
|
||||||
ö o
|
|
||||||
Ō O
|
Ō O
|
||||||
ō o
|
ō o
|
||||||
Ŏ O
|
Ŏ O
|
||||||
ŏ o
|
ŏ o
|
||||||
Ő O
|
Ő O
|
||||||
ő o
|
ő o
|
||||||
Œ E
|
|
||||||
œ e
|
|
||||||
Ø O
|
|
||||||
ø o
|
|
||||||
Ŕ R
|
Ŕ R
|
||||||
ŕ r
|
ŕ r
|
||||||
Ŗ R
|
Ŗ R
|
||||||
ŗ r
|
ŗ r
|
||||||
Ř R
|
Ř R
|
||||||
ř r
|
ř r
|
||||||
ß S
|
|
||||||
Ś S
|
Ś S
|
||||||
ś s
|
ś s
|
||||||
Ŝ S
|
Ŝ S
|
||||||
@ -147,16 +138,6 @@
|
|||||||
ţ t
|
ţ t
|
||||||
Ť T
|
Ť T
|
||||||
ť t
|
ť t
|
||||||
Ŧ T
|
|
||||||
ŧ t
|
|
||||||
Ù U
|
|
||||||
Ú U
|
|
||||||
Û U
|
|
||||||
Ü U
|
|
||||||
ù u
|
|
||||||
ú u
|
|
||||||
û u
|
|
||||||
ü u
|
|
||||||
Ũ U
|
Ũ U
|
||||||
ũ u
|
ũ u
|
||||||
Ū U
|
Ū U
|
||||||
@ -171,9 +152,6 @@
|
|||||||
ų u
|
ų u
|
||||||
Ŵ W
|
Ŵ W
|
||||||
ŵ w
|
ŵ w
|
||||||
Ý Y
|
|
||||||
ý y
|
|
||||||
ÿ y
|
|
||||||
Ŷ Y
|
Ŷ Y
|
||||||
ŷ y
|
ŷ y
|
||||||
Ÿ Y
|
Ÿ Y
|
||||||
@ -183,5 +161,253 @@
|
|||||||
ż z
|
ż z
|
||||||
Ž Z
|
Ž Z
|
||||||
ž z
|
ž z
|
||||||
ё е
|
Ơ O
|
||||||
|
ơ o
|
||||||
|
Ư U
|
||||||
|
ư u
|
||||||
|
DŽ DZ
|
||||||
|
Dž Dz
|
||||||
|
dž dz
|
||||||
|
LJ LJ
|
||||||
|
Lj Lj
|
||||||
|
lj lj
|
||||||
|
NJ NJ
|
||||||
|
Nj Nj
|
||||||
|
nj nj
|
||||||
|
Ǎ A
|
||||||
|
ǎ a
|
||||||
|
Ǐ I
|
||||||
|
ǐ i
|
||||||
|
Ǒ O
|
||||||
|
ǒ o
|
||||||
|
Ǔ U
|
||||||
|
ǔ u
|
||||||
|
Ǧ G
|
||||||
|
ǧ g
|
||||||
|
Ǩ K
|
||||||
|
ǩ k
|
||||||
|
Ǫ O
|
||||||
|
ǫ o
|
||||||
|
ǰ j
|
||||||
|
DZ DZ
|
||||||
|
Dz Dz
|
||||||
|
dz dz
|
||||||
|
Ǵ G
|
||||||
|
ǵ g
|
||||||
|
Ǹ N
|
||||||
|
ǹ n
|
||||||
|
Ȁ A
|
||||||
|
ȁ a
|
||||||
|
Ȃ A
|
||||||
|
ȃ a
|
||||||
|
Ȅ E
|
||||||
|
ȅ e
|
||||||
|
Ȇ E
|
||||||
|
ȇ e
|
||||||
|
Ȉ I
|
||||||
|
ȉ i
|
||||||
|
Ȋ I
|
||||||
|
ȋ i
|
||||||
|
Ȍ O
|
||||||
|
ȍ o
|
||||||
|
Ȏ O
|
||||||
|
ȏ o
|
||||||
|
Ȑ R
|
||||||
|
ȑ r
|
||||||
|
Ȓ R
|
||||||
|
ȓ r
|
||||||
|
Ȕ U
|
||||||
|
ȕ u
|
||||||
|
Ȗ U
|
||||||
|
ȗ u
|
||||||
|
Ș S
|
||||||
|
ș s
|
||||||
|
Ț T
|
||||||
|
ț t
|
||||||
|
Ȟ H
|
||||||
|
ȟ h
|
||||||
|
Ȧ A
|
||||||
|
ȧ a
|
||||||
|
Ȩ E
|
||||||
|
ȩ e
|
||||||
|
Ȯ O
|
||||||
|
ȯ o
|
||||||
|
Ȳ Y
|
||||||
|
ȳ y
|
||||||
|
Ḁ A
|
||||||
|
ḁ a
|
||||||
|
Ḃ B
|
||||||
|
ḃ b
|
||||||
|
Ḅ B
|
||||||
|
ḅ b
|
||||||
|
Ḇ B
|
||||||
|
ḇ b
|
||||||
|
Ḋ D
|
||||||
|
ḋ d
|
||||||
|
Ḍ D
|
||||||
|
ḍ d
|
||||||
|
Ḏ D
|
||||||
|
ḏ d
|
||||||
|
Ḑ D
|
||||||
|
ḑ d
|
||||||
|
Ḓ D
|
||||||
|
ḓ d
|
||||||
|
Ḙ E
|
||||||
|
ḙ e
|
||||||
|
Ḛ E
|
||||||
|
ḛ e
|
||||||
|
Ḟ F
|
||||||
|
ḟ f
|
||||||
|
Ḡ G
|
||||||
|
ḡ g
|
||||||
|
Ḣ H
|
||||||
|
ḣ h
|
||||||
|
Ḥ H
|
||||||
|
ḥ h
|
||||||
|
Ḧ H
|
||||||
|
ḧ h
|
||||||
|
Ḩ H
|
||||||
|
ḩ h
|
||||||
|
Ḫ H
|
||||||
|
ḫ h
|
||||||
|
Ḭ I
|
||||||
|
ḭ i
|
||||||
|
Ḱ K
|
||||||
|
ḱ k
|
||||||
|
Ḳ K
|
||||||
|
ḳ k
|
||||||
|
Ḵ K
|
||||||
|
ḵ k
|
||||||
|
Ḷ L
|
||||||
|
ḷ l
|
||||||
|
Ḻ L
|
||||||
|
ḻ l
|
||||||
|
Ḽ L
|
||||||
|
ḽ l
|
||||||
|
Ḿ M
|
||||||
|
ḿ m
|
||||||
|
Ṁ M
|
||||||
|
ṁ m
|
||||||
|
Ṃ M
|
||||||
|
ṃ m
|
||||||
|
Ṅ N
|
||||||
|
ṅ n
|
||||||
|
Ṇ N
|
||||||
|
ṇ n
|
||||||
|
Ṉ N
|
||||||
|
ṉ n
|
||||||
|
Ṋ N
|
||||||
|
ṋ n
|
||||||
|
Ṕ P
|
||||||
|
ṕ p
|
||||||
|
Ṗ P
|
||||||
|
ṗ p
|
||||||
|
Ṙ R
|
||||||
|
ṙ r
|
||||||
|
Ṛ R
|
||||||
|
ṛ r
|
||||||
|
Ṟ R
|
||||||
|
ṟ r
|
||||||
|
Ṡ S
|
||||||
|
ṡ s
|
||||||
|
Ṣ S
|
||||||
|
ṣ s
|
||||||
|
Ṫ T
|
||||||
|
ṫ t
|
||||||
|
Ṭ T
|
||||||
|
ṭ t
|
||||||
|
Ṯ T
|
||||||
|
ṯ t
|
||||||
|
Ṱ T
|
||||||
|
ṱ t
|
||||||
|
Ṳ U
|
||||||
|
ṳ u
|
||||||
|
Ṵ U
|
||||||
|
ṵ u
|
||||||
|
Ṷ U
|
||||||
|
ṷ u
|
||||||
|
Ṽ V
|
||||||
|
ṽ v
|
||||||
|
Ṿ V
|
||||||
|
ṿ v
|
||||||
|
Ẁ W
|
||||||
|
ẁ w
|
||||||
|
Ẃ W
|
||||||
|
ẃ w
|
||||||
|
Ẅ W
|
||||||
|
ẅ w
|
||||||
|
Ẇ W
|
||||||
|
ẇ w
|
||||||
|
Ẉ W
|
||||||
|
ẉ w
|
||||||
|
Ẋ X
|
||||||
|
ẋ x
|
||||||
|
Ẍ X
|
||||||
|
ẍ x
|
||||||
|
Ẏ Y
|
||||||
|
ẏ y
|
||||||
|
Ẑ Z
|
||||||
|
ẑ z
|
||||||
|
Ẓ Z
|
||||||
|
ẓ z
|
||||||
|
Ẕ Z
|
||||||
|
ẕ z
|
||||||
|
ẖ h
|
||||||
|
ẗ t
|
||||||
|
ẘ w
|
||||||
|
ẙ y
|
||||||
|
Ạ A
|
||||||
|
ạ a
|
||||||
|
Ả A
|
||||||
|
ả a
|
||||||
|
Ẹ E
|
||||||
|
ẹ e
|
||||||
|
Ẻ E
|
||||||
|
ẻ e
|
||||||
|
Ẽ E
|
||||||
|
ẽ e
|
||||||
|
Ỉ I
|
||||||
|
ỉ i
|
||||||
|
Ị I
|
||||||
|
ị i
|
||||||
|
Ọ O
|
||||||
|
ọ o
|
||||||
|
Ỏ O
|
||||||
|
ỏ o
|
||||||
|
Ụ U
|
||||||
|
ụ u
|
||||||
|
Ủ U
|
||||||
|
ủ u
|
||||||
|
Ỳ Y
|
||||||
|
ỳ y
|
||||||
|
Ỵ Y
|
||||||
|
ỵ y
|
||||||
|
Ỷ Y
|
||||||
|
ỷ y
|
||||||
|
Ỹ Y
|
||||||
|
ỹ y
|
||||||
|
ff ff
|
||||||
|
fi fi
|
||||||
|
fl fl
|
||||||
|
ffi ffi
|
||||||
|
ffl ffl
|
||||||
|
st st
|
||||||
|
Ø O
|
||||||
|
ø o
|
||||||
|
Đ D
|
||||||
|
đ d
|
||||||
|
ı i
|
||||||
|
Ħ H
|
||||||
|
ħ h
|
||||||
|
Ł L
|
||||||
|
ł l
|
||||||
|
ʼn 'n
|
||||||
|
Ŧ T
|
||||||
|
ŧ t
|
||||||
Ё Е
|
Ё Е
|
||||||
|
ё е
|
||||||
|
Æ AE
|
||||||
|
ß ss
|
||||||
|
æ ae
|
||||||
|
Œ OE
|
||||||
|
œ oe
|
||||||
|
Loading…
x
Reference in New Issue
Block a user