пятница, 26 ноября 2010 г.

Когда изменение регистра не обратимо в .NET

Это перевод When casing does not need to roundtrip in .NET. Автор: Майкл Каплан.

Несколько дней назад я напомнил читателям, что у каждого символа есть своя история. И тогда я говорил о U+03c2 a.k.a. GREEK SMALL LETTER FINAL SIGMA.

В тёмном, далёком прошлом я также говорил о значении термина "лингвистического изменения регистра" в Windows. Но я ни разу не сказал, когда и где эта настройка используется в .NET Framework (я вот думаю: а это кто-то заметил?).

Некоторое время назад я также говорил о проблемах одностороннего проецирования регистра для грузинского.

Но это не просто путешествие назад в прошлое...

Недавно у меня была e-mail переписка с Jeff Cooperstein, архитектором отделения разработчиков. Он работал над кучей этих вопросов и он заметил кое-что странное, когда он попытался сделать операцию с регистром в .NET:
Почему с InvariantCulture только Final Sigma не обратима (не считая грузинского):

ς (0x03C2) ToUpper -> Σ (0x03A3) ToLower -> σ (0x03C3)

С локалью же по-умолчанию находится намного больше таких примеров:

Dz (0x01F2) ToLower -> dz (0x01F3) ToUpper -> DZ (0x01F1)
ΐ (0x0390) ToUpper -> Ϊ (0x03AA) ToLower -> ϊ (0x03CA)
ϕ (0x03D5) ToUpper -> Φ (0x03A6) ToLower -> φ (0x03C6)
ϖ (0x03D6) ToUpper -> Π (0x03A0) ToLower -> π (0x03C0)

Однако в InvariantCulture их нет, остаётся только ς.
Напоминает ли вам что-то этот второй список? В самом деле, это тот же самый список, получаемый при так называемой лингвистической сортировке и флаге LCMAP_LINGUISTIC_CASING в LCMapString. Jeff заметил, что .NET Framework всегда использует эти дополнительные проецирования (что, конечно же, работает отлично для турецких культур). В случае же инвариантной культуры (это я про CultureInfo.InvariantCulture), эти дополнительные преобразования не используются.

Так что насчёт GREEK SMALL LETTER FINAL SIGMA?

Jeff был прав: сигма - это единственное одностороннее проецирование в таблицах по-умолчанию в Windows и .NET Framework. И если вы посмотрите на ключи сортировки для этих трёх символов:
U+03c3  0F 13 01 01    01 01 00
U+0c32  0F 13 01 01 0A 01 01 00
U+03a3  0F 13 01 01 12 01 01 00
Если вы проигнорируете веса регистра (отмечены выше РОЗОВЫМ), то они все будут идентичны. Так что с точки зрения файловой системы Windows, реестра, переменных окружения и любых других аналогичных вещей: всё это - один и тот же символ.

Хотя я не волнуюсь.

Тогда почему я считаю, что случай с грузинским является ужасным багом, который надо исправить, а этот случай с греческим - это нормально?

Ну, грузинские символы хуцури не очень-то понимаемы большинством пользователей, а вот final sigma довольно известна. Кроме того, греческий имеет двустороннее проецирование, даже хотя оно не позволяет делать взаимно-однозначное соответствие. Добавьте к этому то, что значение текста не теряется, если вы используете SMALL LETTER SIGMA вместо SMALL FINAL SIGMA - так что тут нет лингвистической потери смысла. И вишенка на кусочке пирога: приведение к верхнему регистру для греческого всегда работает отлично - а именно эту операцию делает файловая система и аналогичный код!

Отдельный вопрос - почему Windows и .NET Framework недостаточно умны, чтобы опознать эту ситуацию и выставить правильную форму символа в зависимости от его положения в слове. Сейчас я просто скажу, что сначала нам надо бы исправить "нехорошести" в начале слов, прежде чем браться за их окончания!

This post brought to you by "ς" and "σ" (U+03c2 and U+03c3, a.k.a. GREEK SMALL LETTER FINAL SIGMA и GREEK SMALL LETTER SIGMA)

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

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

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

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

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

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

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