Как стать автором
Обновить

Заблуждения программистов о тексте

Время на прочтение11 мин
Количество просмотров19K


Возжелавший прильнуть к жанру вестернов обратится либо к десятой строчке топ-250 лучших фильмов по версии IMDb, либо уже будет обладать знанием, что начинать нужно с «Хороший, плохой, злой». Там он увидит жадных потных мужчин, которые заканчивают фильм напряжённым мексиканским противостоянием. Жалкая охота за золотом конфедератов разворачивается на фоне кровавых битв Гражданской войны между «Севером» и «Югом». Таким зритель запомнит вестерны как жанр.

В реальности «Хороший» — это не классика, а яркий представитель поджанра ревизионистских вестернов, снят в Европе и наоборот, критикует американскую идеологию направления. В нём нет ничего общего с картинами, где герой встаёт на защиту правильного и справедливого общества от злодеев или кровожадных индейцев. В пятидесятых и шестидесятых классический вестерн сошёл на нет, но в коллективном сознании критика быстро заместила критикуемый объект. Когда Марти Макфлай жалуется на анахронизм наряда, он сравнивает себя с антигероями Клинта Иствуда, а не бравыми ковбоями в исполнении Джона Уэйна.

Иногда нашему восприятию требуются корректировки. Собственные заблуждения необходимо не забыть при проектировании информационных систем. Помнить нужно о многом: для времени, карт и почтовых адресов получаются длинные списки. Для текста неожиданностей мало.

Заблуждение 1. Любые символы, кроме управляющих, имеют предсказуемую ширину


В реальности ширина символов может отличаться даже в моноширных шрифтах.

В блоке символов Юникода U+FF00–FFEF «Полуширинные и полноширинные формы» находятся 52 символа хангыля, 55 катаканы, 66 общих и 52 символа полуширинной латиницы. В Юникоде этот блок выделили для совместимости с азиатскими стандартами, где символы либо полноширинные, либо полуширинные. Обычное слово «Cat» и полноширинное «Cat» отличаются.

Важно не забывать, что полноширинные символы латиницы — это не азиатское письмо. Создатель одного из ботов-переводчиков для Reddit этого не учёл. Бот натравился на чьё-то сообщение из полноширинных символов, а затем вошёл в бесконечный цикл, пытаясь перевести собственные ответы.

Полноширинные символы азиатского письма примерно в полтора раза шире даже в моноширных шрифтах. Для сравнения:

Cat
ネコ


Самая наглядная демонстрация непостоянства ширины — это символ . Это одна кодовая позиция U+FDFD, а не комбинация нескольких. Но даже в моноширном шрифте символ будет шириной в несколько обычных.



Заблуждение 2. Софт хорошо и однозначно интерпретирует все символы ASCII


Проблемы возникают с некоторыми управляющими символами в диапазоне от 0 по 31.

Символ горизонтальной табуляции U+0009 унаследован из ASCII, но в Юникоде не имеет заданной ширины. В CSS ширина табуляции U+0009 в пробелах U+0020 настраивается свойством tab-size.

Разные текстовые редакторы испытывают проблемы с символами перевода строки U+000A и возврата каретки U+000D.

Заблуждение 3. Для записи современного английского достаточно ASCII, для современных западноевропейских языков — ISO Latin-1


В ASCII нет “английских” кавычек. Несколько слов в английском пишутся с буквами, которых в обычном алфавите языка нет. Поскольку на клавиатуре эти символы отсутствуют, «façade», «naïve» и «piñata» постепенно всё сильнее проигрывают более простым вариантам «facade», «naive» и «pinata» в популярности. По крайней мере, в поисковой выдаче Google «красивых» написаний меньше.

Иногда эти типографские изыски несут смысловой оттенок. «Résumé» позволяет избегать путаницы с другими значениями слова «resume». Поэтому вообще-то нельзя сказать, что для английского достаточно символов ASCII.

В ISO Latin-1 (известная как ISO 8859-1) отсутствуют некоторые символы. Нет редкоиспользуемой французской лигатуры «œ», опциональным остаётся эсцет («ẞ») немецкого языка.

Заблуждение 4. Локализация под разные языки? Мне это ни к чему


Конечно, если это внутренняя корпоративная утилита для ограниченного числа пользователей, то разделять текст и код смысла мало.

Хорошо бы создать что-то один раз, а потом продавать по всему миру — игру, например. Рекомендации по локализации видеоигр обычно (статьи от октября 2017, мая 2022, августа 2022) выделяют 7–10 популярных мировых языков кроме английского: немецкий, французский, испанский (европейский вариант, но рекомендуется рассмотреть выделение отдельных версий для рынков Латинской Америки), бразильский вариант португальского, итальянский, русский, польский, китайский (упрощённый, чтобы попасть в аудиторию КНР, Сингапура и Малайзии), японский, корейский.

Выбор языков часто обосновывают числом носителей или логическими рассуждениями. К примеру, в Бразилии английский знают хуже, поэтому отсутствие локализации гарантирует низкий интерес к продукту. Более конкретные метрики — это средний среднедушевой доход в стране или же специальный индекс онлайн-расходов по языкам T-Index.


T-Index указывает, что если продукт переведён на английский, испанский и упрощённый китайский, то получены 50 % потенциала мировых продаж. Чтобы получить 90 %, нужно перевести продукт на 16 языков. Imminent

Если планов покорить мир нет, перевод всё равно не помешает. Один и тот же язык имеет вариации в разных странах, а в одной стране говорят на нескольких языках.

Наконец, если человек знает несколько языков, это не значит, что у него нет предпочтений. Скорее всего, комфортнее будет пользоваться продуктом на родном языке, а не английском.

Заблуждение 5. Перевод — это поменять несколько строчек


Поскольку цену за тысячу знаков обосновывать как-то приходится, бюро переводов с энтузиазмом докажут обратное. Но рассмотрим конкретные примеры.

Перевод — задача с несколькими правильными решениями. Один и тот же фрагмент текста можно перевести по-разному, и каждый из вариантов будет по-своему прав. Кстати, поэтому обсуждения переводов быстро скатываются в уровень вкусовщины и придирок к отдельным фразам. Конкретные определения адекватного перевода и уровни эквивалентности даются в хорошо известном слушателям одноимённого курса учебнике Вилена Наумовича Комиссарова «Теория перевода».

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

При переводе софта многие слова или фразы придётся шаблонизировать по специальным правилам и «вшить» в предложения. Заставить ожить это чудовище Франкенштейна непросто по нескольким причинам.

В русском языке при указании числа чего-либо количественные числительные сочетаются с существительным по-разному. Для чисел от 2 по 4 нужно существительное в единственном числе родительного падежа («3 вакансии»), для чисел от 5 до 9 нужны существительные во множественном числе родительного падежа («5 вакансий»). Эта особенность русского языка и схожие сюрпризы в других добавляют немало проблем.


Инструмент под названием «Матрица падежных форм», который используют для локализации в Badoo

Даже перевод одного предложения не так прост. В некоторых языках два, три, четыре и более грамматических родов. Если в языке несколько артиклей, то они тоже могут зависеть от рода: сравните испанские слова «la cocina» (кухня) и «el baño» (ванная).

В русском род субъекта становится ясным, если глагол действия в прошедшем времени. Если аккаунт нажал на красное сердечко, то пользователь пост «лайкнул» или «лайкнула»?

Переведённый текст станет надписями на кнопках и прочих элементах управления. Длина надписей будет заметно отличаться. «Поплывшие» элементы придётся отловить на этапе тестирования.

Заблуждение 6. У текста есть одно представление в Юникоде


Разные символы Юникода выглядят одинаково или полностью дублируют друг друга.

Если нужно поставить ударение над «е», то сгодится либо комбинация с символом акута U+0301, либо замена на символ со знаком ударения. При этом результат — «é» или «é» — выглядит одинаково.


Основная многоязычная плоскость Юникода покрывает все современные языки. Всего в стандарте 16 плоскостей, каждая из которых содержит до 65 536 символов. Некоторые из дублей находятся в других плоскостях. Drmccreedy

Греческий вопросительный знак ; визуально выглядит как обычная точка с запятой, но компилятор языков семейства C его не примет. Римская цифра выглядит почти как буква V, но символы римских цифр из Юникода не снискали популярности. Некоторые символы кириллицы во многих шрифтах совпадают или почти совпадают с буквами латиницы, что осложняет написание фильтров мата.

Заблуждение 7. Сортировка — это просто


Казалось бы, что может быть проще?

>>> words = ['cafeteria', 'caffeine', 'café']
>>> words.sort()
>>> words
['cafeteria', 'caffeine', 'café']

Получилось неправильно, поскольку Python сортирует по кодовым позициям символов, что для реального мира не работает. Правильный порядок: «café», «cafeteria», «caffeine».

Сортировка требует преобразований. К примеру, эсцет («ß») в немецком языке должен сортироваться так, будто это две буквы «ss».

Сортировка зависит от локали. Как нужно сортировать исландскую букву «æ»? Будет ли это правило из исландского языка работать для английского языка, где «æ» — это не буква, а лигатура?

Размер известного документа Unicode Collation Algorithm с описанием правил сортировки достигает почти 30 тысяч слов. Это длинное, тяжёлое в осмыслении руководство.

Для сортировки в Юникоде сначала проводят операцию case folding. Это как запись строчными буквами, но не всегда — стандарт приводит контрпример, что для языка чероки в результате case folding происходит запись заглавными. Лишь после этого возможно сравнение символов.

Заблуждение 8. Регистров два, их легко поменять


Преобразование из одного регистра в другой сложно и не подчиняется никаким правилам.

Преобразования символов в верхний или в нижний регистры зависит от локали. Буква «i» соответствует «I» в английском языке, но для турецкой и азербайджанской локали эквивалент — «İ».

Результат преобразования может зависеть от положения буквы в слове. Греческая «Σ» U+03A3 «GREEK CAPITAL LETTER SIGMA» преобразуется в «ς» U+03C2 «GREEK SMALL LETTER FINAL SIGMA», если стоит на конце слова, и в «σ» U+03C3 «GREEK SMALL LETTER SIGMA» в остальных случаях.

Преобразование не биективно и не транзитивно. В Юникоде есть как эсцет «ß», так и его заглавная форма «ẞ». Преобразование «ß» в верхний регистр выдаёт «SS», но «SS» при переводе в нижний регистр превращается в «ss».

Из пункта выше следует, что при смене регистра число символов и длина в байтах могут измениться.

Регистров символов в Юникоде три: верхний, нижний и titlecase, титульный. В титульном регистре каждое из слов пишется с заглавной буквы. При этом в зависимости от требований стилистики некоторые из слов (артикли, союзы, предлоги) всё равно будут начинаться со строчных. Пример символа титульного регистра — это диграф «Dz» по адресу U+01F2.

Понять регистр символа по внешнему виду возможно не всегда. Чем является символ U+1D34 «ᴴ»? Несмотря на то, что он называется «MODIFIER LETTER CAPITAL H» и выглядит как заглавная буква «H», этот символ обладает свойством «нижний регистр».

Согласно стандарту Юникода, регистр символа известен только в том случае, если он указан. У большинства символов Юникода регистра просто нет.

Заблуждение 9. Юникод — это чёрно-белые символы


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

Часть символов не предназначена для представления на экране вовсе. Это управляющие символы (перевод строки, удаление и так далее) и блок U+2800 по U+28FF, который содержит все 256 комбинаций восьмиточечного шрифта Брайля.

Заблуждение 10. В Юникоде нет символов разметки


Такими можно назвать символы принудительного выбора направления письма.


В выпуске «RTL» (right to left, справа налево) веб-комикса xkcd Черная шляпа, чтобы закончить надоедливую беседу, переключает режим отображения символов с помощью U+202E. Чтобы вернуть всё обратно, собеседнику нужно было воспользоваться символом U+202C.

Заблуждение 11. Отображаемый символ — это кодовая позиция (code point)


В полной мере опровергнуть это заблуждение может хотя бы корейское письмо хангыль. «각» — это три кодовых позиции «ᄀ», «ᅡ» и «ᆨ», идущие одна за другой. «ᄀᄀᄀ각ᆨᆨ» — это шесть кодовых позиций: три «ᄀ», один «각» и ещё два «ᆨ».

Многие эмодзи образованы «склеиванием», часто с участием знака нулевой ширины U+200C. Семья 👨‍👩‍👧‍👦 — это склейка мужчины, женщины, мальчика и девочки. Флаг 🇷🇺 — это стоящие рядом символы 🇷 и 🇺, в этом случае без «клея» U+200C.

На деле отображаемый символ может оказаться кластером из нескольких кодовых позиций. Операции редактирования (выбор символа, удаление, копирование/вырезание, вставка) будут применяться не к одной кодовой позиции, а ко всему символу.

Заблуждение 12. Юникод — неэффективный и переусложнённый стандарт, от которого идут все проблемы


Юникод ставит целью закодировать все современные и вышедшие из употребления языки. В нём есть как графика из PETSCII (добавлено в блоке наследия вычислительной техники), так и встретившийся единожды в славянской летописи символ «».

Развитие стандарта шло не по прямой, а блуждало, что можно отследить в нарушенных принципах построения. Многие символы дублируют друг друга, тысячи кодовых позиций расходуются на эмодзи.

Тем не менее баги возникали бы и без Юникода.

Даже если текст записан 26 символами английского алфавита и без каких-либо знаков пунктуации, апострофов и дефисов, в мире достаточно других проблем.

На собственном опыте это проверил Амр Эладави. Ему всего лишь повезло обладать именем, которое в записи латиницей (Amr) содержит комбинацию символов, похожую на суффикс «Mr.» (мистер, господин). Амр с удивлением обнаруживал, что при бронировании авиабилета его имя было указано либо как A, либо как AMRMR

Источник ошибок — стандарты телетайпа, которые остаются в ходу. В своё время авиаоператоры и железнодорожные компании в числе первых вводили инновационные информационные системы, которые затем обновляли слабо. За век форматы разрослись в махровый клубок унаследованных систем, поскольку жизнь ставила проблемы и преподносила идеи.

К примеру, если у пассажира нога в гипсе, то ему придётся купить отдельные места для своей нижней конечности. Документ ирландского лоукостера Ryanair (текст сохранился только в виде копии на стороннем сайте) описывает этот процесс. Купить можно до двух дополнительных мест. Первое покупается на пассажира по фамилии «LEGSEAT ONE» и имени «EXTRA», если нужно ещё одно — «LEGSEAT TWO» и «EXTRA». Какой караул случится, если на одном борту полетят два и более тяжело загипсованных, документ Ryanair умалчивает. Эти места ведь нужно не только учесть в списке, но и рассадить в специальном порядке — пересадить ногу в соседний ряд без хирургической пилы невозможно.

Легаси авиалиний не только устарело и содержит много неприятных особенностей. Также тяжело со стандартизацией. В качестве де-факто стандартов закрепились документы от SITA, но участники индустрии придерживаются их в меру своих умений и предпочтений, иногда опуская неудобные фрагменты, отлавливая ошибки парсинга или вводя свои.

Вероятно, имя Амра записывают продукты компаний Sabre или Amadeus. На странице 33 документа Amadeus Quick Reference Guide описано, как правильно передавать элемент имени:

NM1SMITH/JOHN MR

Значения полей:

  • NM: команда «Name», имя.
  • 1: количество пассажиров (один).
  • SMITH: фамилия.
  • JOHN: имя.
  • MR: название лица, то есть форма обращения.

В результате имя Амра передаётся строкой вида NM1ELADAWY/AMR. Системы распарсят это как NM, 1, ELADAWY, A, MR. Часть агентств добавляет пробел после имени (NM1ELADAWY/AMR MR), что исключает неправильное толкование.

Описанный выше случай — это не что-то редкое. Это арабское имя популярно: только в англоязычной «Википедии» 28 различных Амров, в основном египтян. Также Mr. — не единственный суффикс: человеку Oleksandr иногда «присваивается» учёная степень с заменой имени на Dr. Oleksan.


Скриншот штрафов из выступления Джозефа Тартаро на DEF CON 27 и его презентации

В США номерные знаки обычно состоят из псевдослучайной комбинации чисел и символов, но отделы транспортных средств за плату выдают знаки с любым кодом (не без премодерации). Хакер Джозеф Тартаро в 2016 году выбирал для себя что-нибудь в тему инфобеза. Он рассматривал SEGFAULT и VOID, но остановил выбор на NULL.

Проблемы начались уже в следующем году: при продлении регистрации форма на сайте отказалась принимать NULL как номерной знак. Джозеф вышел из положения и в тот раз продлил регистрацию по иному идентификатору, а не номерному знаку. Затем на Тартаро посыпались штрафы: под NULL попадали любые записи без номерного знака, постепенно накрутившись до $12 049. Штрафы всё же аннулировали, поскольку некоторые датировались 2014 годом, а в большинстве мест из описаний Тартаро просто не бывал.

Как видно, глупые ситуации случаются даже без Юникода.



Миллиарды людей с необычным для нас письмом ни в чём себе не отказывают. Они создают музыку, переписываются в чатах и заказывают товары с доставкой. Дашборд автомобиля должен не показать квадратики вместо тэгов MP3, смартфон — не входить в бутлуп от арабских символов, служба доставки — не упасть в обморок от необычного названия компании-получателя.

В жизни у информационных систем не всегда получается обработать не только сложные фрагменты текста, но и строку из латиницы, содержащую имя. Происходит это на ровном месте, без специфики комбинаций Юникода или коварства триграфов в C.

А без имени прожить никто не может. Даже у Человека без имени в каждой из частей «долларовой трилогии» есть клички.



По материалам блогов Маттиаса Вейсмана Тиаса, Eevee, Бена Фредериксона, Джеймс Беннтта, Маниша Горегаокара и Бена Хэмилла, Wired и ответа на Stack Exchange.
Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
Всего голосов 96: ↑96 и ↓0+96
Комментарии51

Публикации

Истории

Ближайшие события