Если вы начнёте изучать стандарт 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.”

Комментарии (6)


  1. Kandimus
    07.11.2024 11:48

    Я не знаю никого кто использует диграф dz, все пишут две буквы. А многие сербы вообще не заморачиваются и вместо букв "c", "ć", "č" пишут "с". Такая же ситуация и с остальными буквами, где есть диакритические символы.


  1. wmlab
    07.11.2024 11:48

    Помню один из своих тасков на проекте в Польше (HR приложение) - написание функции, которая переводит юникодную строку fullname со всей этой диакриктикой и умляутами в однобитную кодировку для упрощения индексации и поиска. Сама задача простая, но пришлось долго составлять таблицу соответствий. Странно, что на такую распространенную проблему не нашлось готовой библиотечной функции.


  1. NeoCode
    07.11.2024 11:48

    А не проще ли было привести венгерский алфавит в соответствие Здравому Смыслу, а не вводить в Юникод всякую хрень? Если букву можно записать двумя буквами то это две буквы.

    А вообще где можно почитать о всяких странностях Юникода, не закапываясь в стандарт? И не приходило ли кому в голову сделать "работу над ошибками" в виде альтернативной таблицы символов (да, здесь должна быть картинка про 17 конкурирующих стандартов - но с другой стороны ведь объективно там всякой фигни накопилось немало).


    1. Goron_Dekar
      07.11.2024 11:48

      שָׁלוֹם, בּוֹקֶר טוֹב!

      (Восклицательный знак должен стоять слева, но редактор Хабра не справился с Ивритом)


    1. LaserPro
      07.11.2024 11:48

      Если записывать звуки несколькими буквами то и получается хрень. Две, три, четыре(привет немецкому) буквы для одного звука. А всё потому что говорим мы звуками а пишем буквами. И для европейских языков очень распространён латинский алфавит, который со своим жалким набором букв не подходит ни одному более-менее популярному языку (нет он не достаточен ни для английского, ни для итальянского). Вот и приходится изображать звуки разными комбинация, умляютами, и просто дополнительными буквами. И при этом люди не хотят переходить на какой-то общий искусственный язык.


    1. CaptainFlint
      07.11.2024 11:48

      А не проще ли было привести венгерский алфавит в соответствие Здравому Смыслу, а не вводить в Юникод всякую хрень? Если букву можно записать двумя буквами то это две буквы.

      В статье же сказано: чтобы обеспечить однозначность конвертации алфавитов. Про венгерский я не знаю, а, скажем, в сербском есть буквы Њ (мягкая Н), обычная Н, и Ј (соответствующая русскому Й). В латинице эти буквы записываются как NJ, N, J. Поэтому возникает неоднозначность при переводе латиницы в кириллицу, как трактовать этот NJ: как одну букву Њ или как НЈ. И да, есть слова, где такое буквосочетание присутствует. Использование единого юникодного символа для диграфа NJ позволяет различить эти ситуации.

      По-хорошему, конечно, разработчики алфавита должны были сразу использовать неповторяющиеся буквы, скажем, ввести Ñ. Но имеем что имеем. А стандарт Юникод не диктует языкам, что они должны стать ёжиками, он лишь фиксирует существующие нормы. Хотя, конечно, на практике этими диграфами вряд ли кто-то пользуется; их даже на клавиатурах нет, насколько я знаю…