суббота, 17 апреля 2010 г.

Они спрашивают меня: "почему мой корейский текст выводится в случайном порядке?"

Это перевод They ask me "why is my Korean text in random order?" Автор: Майкл Каплан.

Я получаю похожие вопросы постоянно: люди интересуются, не знаю ли я, почему, скажем, корейский текст показывается в случайном порядке. Они вполне ожидают такое поведение, если они не указывают корейский LCID ($0412 или 1042), но если они задают его - то они ожидают текст в некотором правильном порядке, а по факту получается что-то не то.

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

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

Мой второй большой вопрос: как они задают порядок. Тут ответ разнится - если они являются программистами, то они обычно вызывают что-то вроде LCMapString или CompareString (или другую функцию, чья работа сводится к их вызову), в противном случае, если это приложение (Access, Excel или что там ещё), тогда они не знают функцию (но обычно я могу узнать, что делает приложение). Или они работают с управляемым кодом и используют классы CompareInfo или SortKey. Проблема же обычно состоит в том, что они указывают флаг NORM_IGNORENONSPACE (или его аналог CompareOptions.IgnoreNonSpace в управляемом коде). И в этом-то и есть причина проблемы...

Видите ли, современные корейские алфавиты (хангыл и ханчча) не имеют обозначения для не пробельных символов (типа диакритических знаков ˆˇˉ˘˙˚˛˜˝, которые вы можете видеть в латинице), поэтому эта часть "пространства весов сопоставления" вместо этого используется для символов ханчча, которые обычно имеют ту же самую фонетическую транскрипцию в хангыле. И если вы говорите API или методу игнорировать этот вес, то вы, фактически, просите его рассматривать (например) такие иероглифы как 渴, 噶 и 鶡 как случайно сортированные вместе не детерминированным образом, поскольку API сообщит, что это одна и та же строка. Та же вещь случится с буквами с диакритическими знаками в латинице - установка флага приведёт (к примеру) к тому, что символы A, Ā, Ă, Ą, À, Á, Â, Ã, Ä и Å будут считаться одинаковыми и испортят результат сортировки.

Ага, нам виден свет в конце туннеля - порядок, на самом деле, не так уж случаен, как они думали. На самом деле, им просто не нужно было указывать флаг!

Но тогда они задают вопрос: "что такого особенного в корейском языке?". Ответ: ничего особенного.

Имена для флагов NORM_IGNORENONSPACE/NORM_IGNORECASE (или IgnoreNonSpace/IgnoreCase) весьма обманчивы, поскольку их названия ссылаются на диакритические знаки латиницы и регистр соответственно, когда нужно указать разницу весов между 'A' и 'Ă' как вторичного отличия и между 'A' и 'a' как третичного. На самом деле, есть несметное число языков, которым тоже нужно выражать вторичные и третичные различия, так что они просто используют эти типы весов. Указание этих флагов может повредить аккуратности/точности тайского, хинди, тамильскому, арабскому, телугу, ивриту и многим другим.

И последний вопрос: "но я произвожу поиск и мне нужно указывать эти флаги для латиницы/кириллицы/греческого. Как мне заставить работать сортировку правильно, без нахождения неверных совпадений?". Ответ весьма прост: производить поиск с указанием флагов, но проводить сортировку без них.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.