Библиотека сайта rus-linux.net
Проблемы локализации в RedHat 5.2 (GNU libc 2.0.7).
Когда мне принесли CD c новой версией RedHat Linux 5.2 (Apollo), я, скажем так, слегка волновался. Наконец, то, думал я, появится версия Linux в которой проблемы локализации если не исчезнут, то хотя бы сойдут на уровень косметических недочетов.
Как бы не так!
Итак, "из чего же" сделан RedHat 5.2 ? Во-первых, это libc6 (glibc2) дистрибутив. На библиотеку glibc RPM рапортует как glibc-2.0.7-29 . На самом деле, официально такой библиотеки нет, последняя на ftp://ftp.gnu.org - glibc-2.0.6 . То, что входит в состав RedHat 5.2 - это snap glibc-2.0.7-981012 с огромным количеством патчей от RedHat. Также, в дистрибутив входит libc5 (libc-5.3.12-28) для совместимости со старым binary софтом.
Одна из RedHat-овских правок добавляет поддержку руского языка в KOI8-R. Но давайте вспомним теорию
По новому стандарту (POSIX.2 приложение E (?)) значения локализации записываются в форме:
language_TERRITORY.Codeset
или формально:
language[_TERRITORY[.Codeset[@modyfier]]]
T.e. допустимы короткие именования значений locale, которые часто оформляются как aliases (псевдонимы) полного наименования. Hапример "C" --> "POSIX" --> "en_US".
Стандарт ISO 639 описывает "language names", ISO 3166 - "territory names".
По стандарту, language для Росии будет "ru", а TERRITORY - "RU". Значение TERRITORY "SU" больше не существует.
С кодировками все
более менее понятно. За период "темных
времен" их расплодилось предостаточно :
IBM866
KOI8-R
ISO8859-5
Windows-1251
X-mac-cyrillic и еще несколько совсем редких.
Однако, это не страшно. В настоящее время их размножение остановилось (или найдется чудак ?), все они зарегистрованы в IANA (кроме mac-cyrillic), все они могут выступать как Charset в MIME, и таблицы перекодировок одной в другую давно известны. Пусть живут. (См. Charset и его имя).
Итак, RedHat 5.2. Включаю локализацию :
$ export LANG=ru_RU
Проверяю утилитой locale :
$ locale mon ощрпЮО;дурЮпшО;?пЮБ;°ъЮушО;?пы;ёНщО;ёНшО;°рсЦАБп;аущБОяЮО;?зБОяЮО;?чОяЮО;?узпяЮО $
OOSP ! Зачем мне ISO8859-5 ??? Проверим, что у нас есть на выбор :
$ locale -a ... ru ru_RU ru_SU russian ...
Включаю :
$ export LANG=ru_SU $ locale mon Января;Февраля;Март;Апреля;Май;Июня;Июля;Августа;Сентября;Октября;Ноября;Декабря $
Прекрасно. За исключением несуществующей страны SU. Но раз в стандарте написано [.CODESET] , попробую явно задать CODESET.
$ export LANG=ru_RU.KOI8-R
Проверяем :
$ locale mon ощрпЮО;дурЮпшО;?пЮБ;°ъЮушО;?пы;ёНщО;ёНшО;°рсЦАБп;аущБОяЮО;?зБОяЮО;?чОяЮО;?узпяЮО $
Но может быть данного CODESET нету ? Нет, есть :
$ locale -m ... CP1251 ISO-8859-5 KOI8-R ...
Проблема оказалась даже хуже, чем я предполагал. Библиотека glibc2 (в базовой поставке) принципиально не воспринимает параметр CODESET. Естественно, это оказывает разрушающее воздействие также на систему NLS (кодировка сообщений). А праметр CODESET просто игнорируется.
Именно для обхода этой "нефункциональности" и была введена несуществующая страна _SU и новое значение локализации ru_SU. Сначала в виде "заплатки" от RedHat, а потом и в alpha версии glibc 2.1
Итак, отныне (как решил за нас RedHat):
ru_RU | ISO8859-5 |
ru_SU | KOI8-R |
Нестандартных решений прибыло ! На этот раз от GNU и RedHat !
Дополнение на 21 Feb 1999
Но предположим, что мы неплохо разбираемся в POSIX locale и хотим сами установить новое значение локализации :
$ localedef -c -i ru_RU -f KOI8-R ru_RU.KOI8-R Computing table size for character classes might take a while... done Computing table size for collation information might take a while... done $
Проверяем :
$ locale -a ... ru ru_RU ru_RU.koi8r ru_SU russian ...
Опять не легче, поскольку наш горячо любимый KOI8-R (описанный в стандарте RFC-1489) превратился в жалкий koi8r ! А почему ? Да потому что Ulrich Drepper добавил в localedef такое :
/* Normalize codeset name. There is no standard for the codeset names. Normalization allows the user to use any of the common names. */ static const char * normalize_codeset (codeset, name_len) const char *codeset; size_t name_len; { |
Непонятно, почему Ulrich считает, что нет стандарта на CODESET. Достаточно зайти на http://www.isi.edu/in-notes/iana/assignments/character-sets и получть список всех CHARSET, зарегистрированных в IANA, даже с Alias:... (См. Charset и его имя)
Что с этим делать ?
Самое простое решение : скомпилировать locale и переименовать каталог :
$ localedef -c -i ru_RU -f KOI8-R ru_RU.KOI8-R Computing table size for character classes might take a while... done Computing table size for collation information might take a while... done $ $ cd /usr/share/locale $ mv ru_RU.koi8r ru_RU.KOI8-R
поскольку создает-то localedef все правильно. После этого проставить LANG=ru_RU.KOI8-R и радоваться жизни.
Можно также поправить /usr/share/locale/locale.alias, но этот метод несколько хуже.
На мой вопрос Ulrich-у, что мол так плохо, я получил ответ : "glibc 2.2 will have support for all the automatic character set conversions." Это при том, что сейчас glibc 2.1 alpha. Не любят нас буржуи...
Однако, не везде все так плохо. Вот другой пример (свежепоставленная система) :
$ ls -l /usr/share/locale ... lrwxrwxrwx 1 root bin 11 Aug 30 21:14 ru -> ru_RU.ISO_8859-5 lrwxrwxrwx 1 root bin 11 Aug 30 21:14 ru_RU -> ru_RU.ISO_8859-5 lrwxrwxrwx 1 root bin 11 Aug 30 21:14 ru_SU -> ru_RU.KOI8-R lrwxrwxrwx 1 root bin 11 Aug 30 21:14 ru_SU.ISO_8859-5 -> ru_RU.ISO_8859-5 lrwxrwxrwx 1 root bin 12 Aug 30 21:14 ru_SU.KOI8-R -> ru_RU.KOI8-R lrwxrwxrwx 1 root bin 11 Aug 30 21:14 ru_SU.CP866 -> ru_RU.CP866 ... drwxr-xr-x 2 bin bin 512 Aug 30 21:14 ru_RU.CP866 drwxr-xr-x 2 bin bin 512 Aug 30 21:14 ru_RU.ISO_8859-5 drwxr-xr-x 2 bin bin 512 Aug 30 21:14 ru_RU.KOI8-R ... $
Как видите, есть поддержка ru --> ru_RU --> ru_RU.ISO_8859-5 и пресловутого ru_SU --> ru_RU.KOI8-R (все сделано на symlinks). Но к сожалению, это не Linux...
Дополнение на 3 марта 1999.
Новые глюки. На этот раз в обычном ls. Не сортирует имена файлов.
Читаем man ls :
...
This manual page documents the GNU version of ls. dir and
vdir are versions of ls with different default output for-
mats. These programs list each given file or directory
name. Directory contents are sorted alphabetically. For
ls, files are by default listed in columns, sorted verti-
cally, if the standard output is a terminal; otherwise
they are listed one per line. For dir, files are by
default listed in columns, sorted vertically. For vdir,
files are by default listed in long format.
...
Проверим ?
$ locale LANG=ru_RU.KOI8-R LC_CTYPE="ru_RU.KOI8-R" LC_NUMERIC="ru_RU.KOI8-R" LC_TIME="ru_RU.KOI8-R" LC_COLLATE="ru_RU.KOI8-R" LC_MONETARY="ru_RU,KOI8-R" LC_MESSAGES="ru_RU.KOI8-R" LC_ALL= $
Установленная locale - самодельная : изготовлена через localedef, а потом mv.
$ ls -l /usr/share/locale/ru_RU.KOI8-R total 45 -rw-rw-r-- 1 root root 29370 Мар 2 19:02 LC_COLLATE -rw-r--r-- 1 root root 10424 Мар 2 16:05 LC_CTYPE drwxrwxr-x 2 root root 1024 Мар 2 19:03 LC_MESSAGES -rw-rw-r-- 1 root root 95 Мар 2 19:02 LC_MONETARY -rw-rw-r-- 1 root root 27 Мар 2 19:02 LC_NUMERIC -rw-rw-r-- 1 root root 492 Мар 2 19:02 LC_TIME $
LC_COLLATE есть. Обратите внимание -- даты русские, то есть LC_NUMERIC работает. Консоль русифицирована в KOI8-R.
$ ls -l total 1 -rw-rw-r-- 1 alec alec 0 Мар 3 19:02 Anna -rw-rw-r-- 1 alec alec 0 Мар 3 19:03 Bravo -rw-rw-r-- 1 alec alec 0 Мар 3 19:03 Center -rw-rw-r-- 1 alec alec 0 Мар 3 19:07 Zero -rw-rw-r-- 1 alec alec 0 Мар 3 19:03 anna -rw-rw-r-- 1 alec alec 0 Мар 3 19:03 bravo -rw-rw-r-- 1 alec alec 0 Мар 3 19:03 center -rw-rw-r-- 1 alec alec 0 Мар 3 19:07 zero -rw-rw-r-- 1 alec alec 0 Мар 3 19:10 юлия -rw-rw-r-- 1 alec alec 0 Мар 3 19:03 анна -rw-rw-r-- 1 alec alec 0 Мар 3 19:04 борис -rw-rw-r-- 1 alec alec 0 Мар 3 19:06 центр -rw-rw-r-- 1 alec alec 0 Мар 3 19:05 виктор -rw-rw-r-- 1 alec alec 0 Мар 3 19:10 Юлия -rw-rw-r-- 1 alec alec 0 Мар 3 19:02 Анна -rw-rw-r-- 1 alec alec 0 Мар 3 19:04 Борис -rw-rw-r-- 1 alec alec 0 Мар 3 19:06 Центр -rw-rw-r-- 1 alec alec 0 Мар 3 19:05 Виктор $
Все плохо. Сортировка юабцЮАБЦ -- это сортировка по кодам в KOI8-R. Данный ls из RedHat 5.2 (Linux/GNU). Попробуем на другой системе : старенькая FreeBSD 2.2.5 пойдет ? Русификация консоли в KOI8-R. Утилиты locale там все еще нет. Однако сортировка в ls работает :
$ uname -sr FreeBSD 2.2.5-RELEASE $ $ echo $LANG ru_RU.KOI8-R $ $ ls -l total 0 -rw-r--r-- 1 root wheel 0 мар 2 23:01 Анна -rw-r--r-- 1 root wheel 0 мар 2 23:01 Борис -rw-r--r-- 1 root wheel 0 мар 2 23:01 Виктор -rw-r--r-- 1 root wheel 0 мар 2 23:02 Центр -rw-r--r-- 1 root wheel 0 мар 2 23:02 Юлия -rw-r--r-- 1 root wheel 0 мар 2 23:01 анна -rw-r--r-- 1 root wheel 0 мар 2 23:01 борис -rw-r--r-- 1 root wheel 0 мар 2 23:01 виктор -rw-r--r-- 1 root wheel 0 мар 2 23:02 центр -rw-r--r-- 1 root wheel 0 мар 2 23:02 юлия $
Подкрутить надо что-то в консерватории, однако...
Locale "AS IT IS" Локализация "Как она есть" - введение в POSIX locale.
Большой Журналистский Секрет. Что говорить про Linux.
Еще один борец со стандартами : KSI Linux.
Комментарии к предыдущей заметке (в конце).
День славянской письменности. Вообще-то, это юмор...
--
-=AV=-