Интернационализация II

Спецсеминар "Разработка свободного ПО": http://uucode.com/oss2004/. 12-я лекция, 27 ноября 2004.

Представление букв

Unicode -- это не кодировка, это "реестр" символов. Иногда слоэно различить "одинаковые" и "разные" буквы. Буквам сопоставлены "магические числа".

Например, "ё" (русская йо):

Поиск символов, преобразование различных представлений: http://www.zvon.org/other/charSearch/PHP/search.php

По-быстрому получить "магический" код символа:

$ echo -n 'ё' | iconv -f koi8-r -t ucs2 | od -t x2
0000000 0451

Кодировки unicode

Важно: unicode -- это не кодировка. Это абстрактное описание. International standard ISO/IEC 10646.

Яva: U+042f U+0076 U+0061

А теперь про кодировки.

"Яva": 04 2f 00 76 00 61
"Яva": 2f 04 76 00 61 00

Делают и так, и так. "FE FF" -- BOM -- Unicode Byte Order Mark. UCS-2/UTF-16, два варианта из-за BOM

Unicode не всем понравился: слишком большой расход памяти. Особенно в UCS-4.

utf8

September 2, 1992, Pike и Thompson придумали за обедом utf8, а затем реализовали её, и система plan9 стала всюду использовать utf8.

UTF-8 (8-bit Unicode Transformation Format). RFC 3629.

Таблица перевода:

000000-00007F:  0xxxxxxx
000080-0007FF:  110xxxxx 10xxxxxx
000800-00FFFF:  1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF:  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Пример:

Я:   0x042f: 10000101111 -> 10000.101111 -> 11010000 10101111 -> D0 AF
va:  76 61
Яva: D0 AF 76 61

А ещё бывают UTF-16 и UTF-7. А ещё у Явы (и, наверное, не только) своё представление об UTF-8.

Очевидные свойства:

Плюсы:

Минусы:

Зачёт: продемонстрировать на примере "Яva" как буква "Я" кодируется разными последовательностями.

Указание кодировки

Важно. Не бывает такого понятия как "просто текст"! Строка без знания кодировки бессмысленна.

Способы задания кодировки:

В некоторых случаях кодировку не указать: zip-архивы, mp3 tags. И тогда всё плохо.

Транспортная кодировка:

Unicode внутри языков

C/C++:

Java/C#/Python/etc -- внутри utf8. Но не без проблем.

Когда "тест"!="тест" (первое введено пользователем в web-формочку, второе -- в исходный код программы). Указание кодировки при компиляции программы или использование unicode-escapes. Второе лучше и надёжнее.

Локаль

Кодировка -- это хорошо, но правильные программы должны учитывать "культуру". Пример локали:

ru_RU.koi8-r

Обычно задаётся переменной окружения "LC_ALL". Есть и другие переменные для тонкой настройки, их список -- в любой книжке про unix. По умолчанию "C" или "POSIX".

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

LC_NUMERIC стоит всегда держать в "C" или "POSIX". О проблемах говорили в прошлый раз.

Про LC_COLLATE. Почему нельзя использовать "наивные" сортировки.

В некоторых ОС локаль не меняется.

Проблема DOS'овского чёрного окна. А нём используется oem-кодировка (например, cp866). Поэтому "type file.txt" выводит нечитаемый текст. В принципе, кодировку можно поменять, но тогда "призовая игра":

"cmd.com ..."
vs
"cmd.com ... | more.

Взаимодействие 8-bit и unicode

От этого пока никуда не деться.

Проблема: делаем "print(str)", "str" содержит "u:", а выходная кодировка "koi8-r". Что случится?

Это не лечится. Надо внимательно работать с кодировками reader'ов, writer'ов и stream'ов, и знать что в какой кодировке находится. Проще всего входящие данные сразу преобразовывать в unicode.

Важно: При отладке unicode-действий нельзя использовать для отладки просто print. Ведь при этом происходит преобразование, и на выходе получается неправда. Правильный способ -- написать и использовать функцию "asciify", которая символы [^A-Za-z0-9] преобразует в коды типа "У".

gettext

Про него уже говорили. Код пишется примерно так:

print(_("Hello, World!"))

Специальная программа вытаскивает строки, тексты переводятся на другие языки (po-файлы), результаты компилируются (mo-файлы). Есть GUI.

gettext есть для почти всех языков программирования, в том числе и для php.

Можно использовать не только для текста, но и для других данных.

В .NET есть что-то подобное.

Разное

В названии unicode-шрифтов обычно присутствует "iso-10446-1".

Если вывести мусор на терминал, то иногда можно что-нибудь исполнить.

В MSDN есть хорошая книжка про l10n и i18n. Рекомендую.

Флаги на сайтах надо использовать аккуратно (например, что использовать для английского языка?). Более тяжёлый случай: http://www.linux.org.ru/view-message.jsp?msgid=665958&page=0 "Флажки запрещены по соображениям политкорректности".