Если вы начнёте изучать стандарт 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.”
Комментарии (34)
wmlab
07.11.2024 11:48Помню один из своих тасков на проекте в Польше (HR приложение) - написание функции, которая переводит юникодную строку fullname со всей этой диакриктикой и умляутами в однобитную кодировку для упрощения индексации и поиска. Сама задача простая, но пришлось долго составлять таблицу соответствий. Странно, что на такую распространенную проблему не нашлось готовой библиотечной функции.
bogolt
07.11.2024 11:48Гуглите по слову "Unidecode" вот например на питоне https://pypi.org/project/Unidecode/
NeoCode
07.11.2024 11:48А не проще ли было привести венгерский алфавит в соответствие Здравому Смыслу, а не вводить в Юникод всякую хрень? Если букву можно записать двумя буквами то это две буквы.
А вообще где можно почитать о всяких странностях Юникода, не закапываясь в стандарт? И не приходило ли кому в голову сделать "работу над ошибками" в виде альтернативной таблицы символов (да, здесь должна быть картинка про 17 конкурирующих стандартов - но с другой стороны ведь объективно там всякой фигни накопилось немало).
Goron_Dekar
07.11.2024 11:48שָׁלוֹם, בּוֹקֶר טוֹב!
(Восклицательный знак должен стоять слева, но редактор Хабра не справился с Ивритом)
NeoCode
07.11.2024 11:48Насколько я знаю, китайские и японские тексты исторически записываются сверху вниз, столбцами. А Юникод это не учел, непорядок! Надо ввести еще код смены направления с горизонтального на вертикальное:)
LaserPro
07.11.2024 11:48Если записывать звуки несколькими буквами то и получается хрень. Две, три, четыре(привет немецкому) буквы для одного звука. А всё потому что говорим мы звуками а пишем буквами. И для европейских языков очень распространён латинский алфавит, который со своим жалким набором букв не подходит ни одному более-менее популярному языку (нет он не достаточен ни для английского, ни для итальянского). Вот и приходится изображать звуки разными комбинация, умляютами, и просто дополнительными буквами. И при этом люди не хотят переходить на какой-то общий искусственный язык.
NeoCode
07.11.2024 11:48Не понял при чем тут звуки. Во многих языках очень нетривиальные правила чтения слов, но при чем здесь Юникод? Претензия к тому, что составители венгерского алфавита зачем-то в алфавит (который есть набор букв, атомарных символов) ввели буквосочетания, а комитет Юникода это бездумно повторил. Если в языке есть устойчивое буквосочетание, это не значит что его нужно рассматривать как отдельную букву. В английском после Q обязательно идет U, но вводить букву QU никому в голову не пришло.
salnicoff
07.11.2024 11:48В английском после Q обязательно идет U, но вводить букву QU никому в голову не пришло.
Потому что есть sheqel, tzaddiq и еще много других слов, пришедших в английский из других языков.
theonevolodya
07.11.2024 11:48Цадик и шекель? Но они разве через q пишутся в английском?
salnicoff
07.11.2024 11:48Как один из вариантов. То, что пришло из латыни — c QU, а из идиша и французского — с Q. Потом начали менять на K для особо одаренных.
LaserPro
07.11.2024 11:48Вся система речи, письменности, грамматики это дремучее легаси с тысячами лет истории. Никаким новым "более лучшим и правильным" Юникодом это не исправить, всё равно будет костыль для легаси. Я за рефкторинг вместо костылей))
Goron_Dekar
07.11.2024 11:48Что? Чего вы говорите?
[вдумайтесь о разнице звуков и написания этого вопроса и того, сколько звуков записано каким количеством букв]
Vytian
07.11.2024 11:48Потому что большинство населения мира считает фонетическое письмо глупым пережитком родоплеменного устройства общества.
Потому что писать символы -- это не то же самое, что говорить, хуже того, местами это дополнительные, если не противоречащие задачи. Не только в матане или химии, всё программирование об этом.
LaserPro
07.11.2024 11:48Я уверен что большинство населения мира вообще не задумывается о таких вещах и принимает языки, письменность и алфавит как данность, что-то незыблемое и об изменении чего даже думать кощунство.
perfect_genius
07.11.2024 11:48писать символы -- это не то же самое, что говорить
А как же белорусский?
CaptainFlint
07.11.2024 11:48А не проще ли было привести венгерский алфавит в соответствие Здравому Смыслу, а не вводить в Юникод всякую хрень? Если букву можно записать двумя буквами то это две буквы.
В статье же сказано: чтобы обеспечить однозначность конвертации алфавитов. Про венгерский я не знаю, а, скажем, в сербском есть буквы Њ (мягкая Н), обычная Н, и Ј (соответствующая русскому Й). В латинице эти буквы записываются как NJ, N, J. Поэтому возникает неоднозначность при переводе латиницы в кириллицу, как трактовать этот NJ: как одну букву Њ или как НЈ. И да, есть слова, где такое буквосочетание присутствует. Использование единого юникодного символа для диграфа NJ позволяет различить эти ситуации.
По-хорошему, конечно, разработчики алфавита должны были сразу использовать неповторяющиеся буквы, скажем, ввести Ñ. Но имеем что имеем. А стандарт Юникод не диктует языкам, что они должны стать ёжиками, он лишь фиксирует существующие нормы. Хотя, конечно, на практике этими диграфами вряд ли кто-то пользуется; их даже на клавиатурах нет, насколько я знаю…
Format-X22
07.11.2024 11:48Как на счет русской буквы Ы? И если английская W ещё как минимум соединена визуально, то Ы уже нет. Для нас кажется нонсенсом разделить Ы на части, думаю для них dz также.
kenomimi
07.11.2024 11:48У нас нет буквы I в алфавите, она только в украинском есть. Потому Ы вроде как норм, дублирования в русском алфавите не происходит...
CaptainFlint
07.11.2024 11:48В казахском языке кириллический алфавит, в котором есть и Ь, и Ы, и І.
artptr86
07.11.2024 11:48В белорусском языке тоже есть Ь, Ы, I, а ещё можно упомянуть диграфы ДЖ и ДЗ, которые иногда считают отдельными буквами.
bt2901
07.11.2024 11:48А почему бы нам тогда не вспомнить историю буквы У, которая до Петра Первого обозначалась как диграф "оу" (Юникод сохранил следы этой традиции в символах Ꙋꙋᲈ и Ѹѹ), хотя "у" в отдельности нигде не встречалась? Почему бı нам не упростить эти странıе символı-лигатурı?
Шутка, если что.
youngmysteriouslight
07.11.2024 11:48Диграфную историю «оv» мы можем наблюдать в начертаниях «y» (от второй части) и в диграфе «ю» = «iov» (от первой части).
Кстати, «v» встречалась отдельно вплоть до начала XX в печатных гражданских (и тем более церковных) текстах (а в быту всё более заменялась на фонетические эквиваленты) в словах «мvро», «сvнодъ», «Моvсей» и прочих заимствованиях.
Шутка, если что.
А зря. Бездумно тащить легаси с видом, что так и должно быть, тоже не полезно.
perfect_genius
07.11.2024 11:48не приходило ли кому в голову сделать "работу над ошибками" в виде альтернативной таблицы символов
Каждый раз на Хабре в статьях про странности Юникода. И я так спрашивал.
Ещё кто-то предлагал дельную (на мой взгляд) идею: можно всё нужное поместить в 2 байта. А как же десятки тысяч иероглифов? А они состоят из общих элементов и поэтому их можно делать составными.
Но это уже надо бы спросить китайских программистов как будет работаться с таким вариантом.
TimReset
07.11.2024 11:48если ввести строку поиска «mad», то она не будет соответствовать «madzag» (что означает «верёвка»), потому что «dz» в «madzag» — это отдельная буква, а не «d», за которой следует «z»
Если кто-то решил перепроверить - нет, тут две отдельные буквы. Но в таблицах - да, один символ. :-)
ris58h
07.11.2024 11:48Хотел проверить везде ли автор не поленился и использовал dz в тексте (спойлер: не везде), но наткнулся на забавную особенность поиска по тексту в Chrome: при поиске по диаграфу dz он, в том числе, находит буквосочетания dz. В Firefox такого нет - поиск работает строго.
Kandimus
Я не знаю никого кто использует диграф dz, все пишут две буквы. А многие сербы вообще не заморачиваются и вместо букв "c", "ć", "č" пишут "с". Такая же ситуация и с остальными буквами, где есть диакритические символы.
perfect_genius
А как dz вводится с клавиатуры? Если это сложнее, чем буквы по отдельности, то причина тогда понятна.
Kandimus
Я даже не знаю как ввести этот символ, так как на сербской клавиатуре нет такой клавиши