Next Previous Contents

## 9. Локализация и Интернационализация

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

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

Следовательно, возникает потребность в стандартизации. И стандарт есть.

Все связанное с вышеперечисленными проблемами разделено в соответствии c двумя базисными концепциями: localization и internationalization. Под локализацией мы имеем в виду создание программ, способных обрабатывать различные языковые соглашения для различных стран. Позвольте привести пример. Формат даты выданный в Соединенных Штатах - имеет вид ММ/ДД/ГГ. Однако в России, наиболее популярный формат - ДД.ММ.ГГ. Другие проблемы включают в себя представление времени, форматы числа и представления валюты. Кроме этого, один из наиболее важных аспектов локализации - это определение соответствующих классов символов, то есть определение: какие символы в наборе символов являются "кирпичиками" языка (буквами) и как они упорядочиваются. С другой стороны, локализация не работает со шрифтами.

Интернационализация (или i18n для краткости), как предполагается, решает проблемы, связанные со способностью программы, взаимодействуют с пользователем на его родном языке.

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

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

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

## 9.1 Locale

Одно из основных понятий локализации - locale. Под locale подразумевается набор соглашений, специфических для отдельно взятого языка в отдельно взятой стране. В общем случае говорить, что locale определяется только страной неправильно. Например, в Канаде могут быть определены два locale- язык Канада / Английский и язык Канада / Французский. Более того, язык Канада / Английский - не является эквивалентом языку Великобритания / Английский или Американский / Английский, точно так же Канада / Французский язык - не эквивалент языку Франция / Французский или языку Швейцария / Французский.

### Locale с точки зрения пользователя

Каждая locale - это специальная база данных, определяющая по крайней мере следующие правила и соглашения:

1. Классификация символов и преобразований
2. Представление валюты
3. Представление чисел (то есть. Десятичные символы)
4. Формат даты / времени

В RedHat Linux (как вероятно и во многих других дистрибутивах Linux), имеются фактически две базы данных locale: одна для библиотеки C (`libc`), а другая для X библиотек. В идеальном случае должна иметься только одна база данных locale для всего.

Чтобы изменить значение locale по умолчанию, обычно достаточно установить системную переменную `LANG`. Например, как это делается в `sh`:

    LANG=ru_SU
    export LANG

Вы можете проверить действие этой команды сразу же, если запустите команду `date`. Результатом должен быть вывод дня, недели и месяца на русском языке.

RedHat 5.x определяет KOI8-R locale как `ru_SU`, по этой причине я и использую его. Более очевидное название `ru_RU` используется для locale основанного на `iso-8859-5` кодировки.

Иногда, вы можете захотеть изменить только один аспект locale без изменения других. Например, вы можете захотеть (Бог знает почему) пользоваться с `ru_SU` locale, но печатаемые числа должны будут соответствовать стандарту POSIX один. В подобных случаях, имеется набор системных переменных, которые Вы можете задать чтобы сконфигурировать соответствующие части locale. Например в нашем случае это бы выглядело так:

    LANG=ru_SU
    LC_NUMERIC=POSIX
    export LANG LC_NUMERIC

Подробнее , см. `locale(7)`.

Теперь давайте держаться поближе к специфике Linux. К сожалению, в Linux `libc` версии 5.3.12, входящей в дистрибутив RedHat 4.1 отсутствует русская locale. В данном случае ее надо скачать из Interneta (я, однако, не знаю точного адреса).

Чтобы проверить, для каких языков у вас есть locale, выполните '`locale -a`'. Это выведет список всех locale из баз данных доступных libc.

Что касается библиотек `X`, то они имеют свою собственную базу данных locale. В версии которую я использую (`XFree86 3.3`), уже имеется российская база данных locale. Я не уверен есть ли она в предыдущей версии. В любом случае, вы можете проверить это, изучив директорию `/usr/lib/X11/locale/` (в большинстве систем). В моем случае, уже есть подкаталоги, именованные `koi8-r` и даже `iso8859-5`..

### Locale зависимое программирование

С locale программа не должна знать о различных символьных преобразованиях и правилах сравнения, описанных выше. Вместо этого, они используют специальный API, который действует по правилам, определенным locale. Кроме того, нет необходимости для программы, пользоваться только одной locale для соблюдения всех правил- возможно пользоваться другими правилами, описанных в других locale (хотя такой метод не очень хорош).

Из man `setlocale(3)`:

> Программа может быть сделана переносимой для всех locale, вызывая `setlocale(LC_ALL, "" )` после инициализации программы, используя значения, возвращенные из `localeconv()` запрос для locale - зависимой информации и используя `strcoll()` или `strxfrm()` для сравнения строк.

Довольно легко определить четыре уровня программной локализации:

1. Чисто 8ми битное программное обеспечение. То есть программа вызывает `setlocale()`. Она не делает каких-либо предположений относительно 8-ого бита каждого символа, использует пользовательские функции из `ctype.h` и ограничения из `limits.h`, и заботится относительно `signed/unsigned` результата. Очень важно, чтобы программа не делала каких-либо предположений относительно характера набора символов и их упорядочения. То есть следует воздержаться от следующих конструкций при программировании:

           if (c >= 'A' && c <= 'Z') {
               ...

   Взамен во всех таких случаях должны использоваться, макрокоманды из locale зависимого файла заголовка `ctype.h`.
2. Форматы, методы сортировки, размеры листа бумаги. Программа использует `strcoll()` и `strxfrm()` вместо `strcmp()` для строк, использует `time()`, `localtime()`, и `strftime()` для работы со временем, и в заключение, использует `localeconv()` для правильного представления чисел и валюты.
3. Видимый текст складывается в каталоги сообщений/. Программа должна локализовать весь видимый текст в специальных каталогах сообщений. Они содержат соответствия строк на английском и их переводы на другие языки. Выбор сообщений соответствующих языку окружения выполнен так, что полностью прозрачен и для программы и для пользователя. Чтобы использовать эти средства, программа должна вызвать `gettext()` (Sun/POSIX стандарт), или `catgets()` (X/Open стандарт). Подробнее см. раздел i18n .
4. EUC/Unicode поддержка. На этом уровне, программа не использует тип `char`. Взамен это она использует `wchar_t`, который определяет объекты, достаточно большие, чтобы содержать символы Unicode. ANSI C определяет этот тип данных и соответствующий API.

Для выяснения подробностей, смотрите например ( Voropay1 ) или ( SingleUnix ).

## 9.2 интернационализация

В то время как локализация описывает, как адаптировать программу к иностранному окружению, интернационализация (или i18n для краткости) детализирует способы общения программы с не-англоговорящим пользователем.

Прежде, это делалось с помощью создания абстракций сообщений, для вывода их из кода программы. Теперь, такой механизм (более или менее) стандартизирован. И, конечно, есть его free реализации!

Проект GNU наконец стал на путь создания интернационализированных прикладных программ. Ulrich Drepper (`drepper@ipd.info.uni-karlsruhe.de`) разработал пакет `gettext`. Этот пакет лежит во всех GNU архивах, например в prep.ai.mit.edu. Он позволяет вам разрабатывать программы в направлении, двигаясь в котором вы можете легко заставить их поддерживать большее количество языков. Я и не предполагаю описывать методы программирования, еще и потому, что `gettext` пакет поставляется с превосходным руководством.

Просьба о сотрудничестве: Если вы хотите изучить `gettext` пакет и сделать свой вклад в проект GNU или просто сделать вклад без всякого изучения, то вы можете сделать это! GNU становится международным, так что все утилиты делаются locale зависимыми. Проблема состоит в том, чтобы переводить сообщения от Английского языка на Русского (и другие языки, конечно если захотите). В общем, что следует сделать: вы должны получить специальный `.po` файл, состоящий из Английских сообщений для неких утилит, и связать каждое сообщение с его эквивалентом на русском. В конечном счете, это заставит говорить систему Русский, если пользователь захочет этого! Для для подробностей войдите в контакт с Ulrich Drepper ( drepper@ipd.info.uni-karlsruhe.de).

Next Previous Contents