Если вы начнёте изучать стандарт Unicode, то, к своему удивлению, можете обнаружить некоторые символы, имеющие различия в регистре, при этом они сами по себе ни в верхнем, ни в нижнем регистре.

У-у-у-у, загадочно и пугающе.

Иными словами, это символ c, обладающий следующими свойствами:

  • toUpper(c) ≠ toLower(c), однако

  • c ≠ toUpper(c) и c ≠ toLower(c).

Поздравляю, вы обнаружили таинственный третий регистр: Title case.

Некоторые символы Unicode занимают одну кодовую точку, но представляют объединённые вместе два графических символа. Например, символ Unicode dz (U+01F1 LATIN SMALL LETTER DZ) выглядит как два символа Unicode, расположенных рядом друг с другом: dz (U+0064 LATIN SMALL LETTER D, за которым следует U+007A LATIN SMALL LETTER Z).

Эти диграфы — символы алфавитов некоторых языков, в частности венгерского. В таких языках диграф считается отдельной буквой алфавита. Например, вот первые десять букв венгерского алфавита¹

a

á

b

c

cs

d

dz

dzs

e

é

Эти диграфы (и один триграф) имеют три формы.

Форма

Результат

Верхний регистр

DZ

Title case

Dz

Нижний регистр

dz

В кодировку Unicode включено четыре диграфа.

Верхний регистр

Title case

Нижний регистр

DŽ

Dž

dž

LJ

Lj

lj

NJ

Nj

nj

DZ

Dz

dz

Но постойте, если у нас есть кодовая точка Unicode для диграфа dz, почему нет точки для диграфа cs или триграфа dzs? Что особенного в dz?

Эти диграфы обязаны своим существованием в Unicode не венгерскому, а сербохорватскому языку. Сербохорватский записывается и латиницей (хорватской), и кириллицей (сербской), и эти диграфы позволяют выполнять взаимно однозначную транслитерацию между ними¹.

Это ещё одна ситуация, в которой мир оказывается сложнее, чем мы думали. Вы думали, что поняли верхний и нижний регистр, но есть ещё один регистр между ними, о котором вы не знали.

Дополнение: то, что dz считается в венгерском одной буквой, означает, что если ввести строку поиска «mad», то она не будет соответствовать «madzag» (что означает «верёвка»), потому что «dz» в «madzag» — это отдельная буква, а не «d», за которой следует «z», аналогично тому, что «lav» не будет соответств��вать слову «law» просто потому, что первая часть буквы «w» выглядит как «v». Ещё один неожиданный результат, если вы ошибочно используете литеральный поиск подстрок вместо учитывающего локаль. В следующий раз мы рассмотрим поиск подстрок с учётом локалей.

¹ Я узнал эту информацию из Unicode Standard, Version 15.0, Глава 7: “Europe I”, Section 7.1: “Latin”, подраздел “Latin Extended-B: U+0180-U+024F”, подподраздел “Croatian Digraphs Matching Serbian Cyrillic Letters.”