Документация Python неофициальный перевод

gettext.md

493 строк · 47.1 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/2.7/library/gettext.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 22.1. [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) – Многоязычные службы интернационализации89**Исходный код:** [Lib/gettext.py](https://python-all.ru/src/2.7/Lib/gettext.py)1011---1213Модуль [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) предоставляет службы интернационализации (I18N) и локализации (L10N) для модулей и приложений Python. Он поддерживает как API каталогов сообщений GNU `gettext`, так и API более высокого уровня, основанный на классах, который может лучше подходить для файлов Python. Описанный ниже интерфейс позволяет писать сообщения модуля и приложения на одном естественном языке и предоставлять каталог переведённых сообщений для работы на разных естественных языках.1415Также даются некоторые советы по локализации модулей и приложений Python.1617## 22.1.1. GNU **gettext** API1819Модуль [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) определяет следующий API, очень похожий на API GNU **gettext**. Использование этого API повлияет на перевод всего приложения глобально. Часто это желательно, если приложение одноязычное и выбор языка зависит от локали пользователя. Если требуется локализовать модуль Python или приложению нужно переключать языки на лету, вероятно, следует использовать API на основе классов.2021#### `gettext.bindtextdomain(domain[, localedir])`2223Связывает *domain* с каталогом локали *localedir*. Если говорить точнее, [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) будет искать двоичные файлы `.mo` для заданного домена по пути (в Unix): `localedir/language/LC_MESSAGES/domain.mo`, где *languages* ищется в переменных окружения `LANGUAGE`, `LC_ALL`, `LC_MESSAGES` и `LANG` соответственно.2425Если *localedir* опущен или равен `None`, то возвращается текущая привязка для *domain*. [1](https://python-all.ru/2.7/library/gettext.html#id6)2627#### `gettext.bind_textdomain_codeset(domain[, codeset])`2829Привязывает *domain* к *codeset*, изменяя кодировку строк, возвращаемых семейством функций [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext). Если *codeset* опущен, возвращается текущая привязка.3031Новое в версии 2.4.3233#### `gettext.textdomain([domain])`3435Изменяет или запрашивает текущий глобальный домен. Если *domain* равен `None`, возвращается текущий глобальный домен; в противном случае глобальный домен устанавливается в *domain*, который и возвращается.3637#### `gettext.gettext(message)`3839Возвращает локализованный перевод *message* на основе текущего глобального домена, языка и каталога локали. Эта функция обычно имеет псевдоним `_()` в локальном пространстве имён (см. примеры ниже).4041#### `gettext.lgettext(message)`4243Эквивалентно [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext), но перевод возвращается в предпочтительной системной кодировке, если никакая другая кодировка не была явно задана с помощью [`bind_textdomain_codeset()`](https://python-all.ru/2.7/library/gettext.html#gettext.bind_textdomain_codeset).4445Новое в версии 2.4.4647#### `gettext.dgettext(domain, message)`4849Как [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext), но ищет сообщение в указанном *domain*.5051#### `gettext.ldgettext(domain, message)`5253Эквивалентно [`dgettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.dgettext), но перевод возвращается в предпочтительной системной кодировке, если никакая другая кодировка не была явно задана с помощью [`bind_textdomain_codeset()`](https://python-all.ru/2.7/library/gettext.html#gettext.bind_textdomain_codeset).5455Новое в версии 2.4.5657#### `gettext.ngettext(singular, plural, n)`5859Как [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext), но учитывает формы множественного числа. Если перевод найден, применяет формулу множественного числа к *n* и возвращает результирующее сообщение (в некоторых языках более двух форм множественного числа). Если перевод не найден, возвращает *singular*, если *n* равно 1; в противном случае возвращает *plural*.6061Формула множественного числа берётся из заголовка каталога. Это выражение на C или Python, использующее свободную переменную *n*; выражение вычисляет индекс формы множественного числа в каталоге. Обратитесь к документации GNU gettext для получения точного синтаксиса, используемого в файлах `.po`, и формул для множества языков.6263Новое в версии 2.3.6465#### `gettext.lngettext(singular, plural, n)`6667Эквивалентно [`ngettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.ngettext), но перевод возвращается в предпочтительной системной кодировке, если никакая другая кодировка не была явно задана с помощью [`bind_textdomain_codeset()`](https://python-all.ru/2.7/library/gettext.html#gettext.bind_textdomain_codeset).6869Новое в версии 2.4.7071#### `gettext.dngettext(domain, singular, plural, n)`7273Как [`ngettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.ngettext), но ищет сообщение в указанном *domain*.7475Новое в версии 2.3.7677#### `gettext.ldngettext(domain, singular, plural, n)`7879Эквивалентно [`dngettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.dngettext), но перевод возвращается в предпочтительной системной кодировке, если никакая другая кодировка не была явно задана с помощью [`bind_textdomain_codeset()`](https://python-all.ru/2.7/library/gettext.html#gettext.bind_textdomain_codeset).8081Новое в версии 2.4.8283Обратите внимание, что GNU **gettext** также определяет метод `dcgettext()`, но он был признан бесполезным и на данный момент не реализован.8485Вот пример типичного использования этого API:8687```python88import gettext89gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')90gettext.textdomain('myapplication')91_ = gettext.gettext92# ...93print _('This is a translatable string.')94```9596## 22.1.2. API на основе классов9798API на основе классов модуля [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) обеспечивает большую гибкость и удобство по сравнению с GNU **gettext** API. Это рекомендуемый способ локализации приложений и модулей Python. `gettext` определяет класс «translations», который реализует разбор файлов в формате GNU `.mo` и имеет методы для возврата как стандартных 8-битных строк, так и строк Unicode. Экземпляры этого класса «translations» также могут устанавливать себя во встроенное пространство имён как функцию `_()`.99100#### `gettext.find(domain[, localedir[, languages[, all]]])`101102Эта функция реализует стандартный алгоритм поиска файлов `.mo`. Она принимает *домен*, такой же, как в [`textdomain()`](https://python-all.ru/2.7/library/gettext.html#gettext.textdomain). Необязательный параметр *localedir* – как в [`bindtextdomain()`](https://python-all.ru/2.7/library/gettext.html#gettext.bindtextdomain). Необязательный параметр *languages* – это список строк, где каждая строка – код языка.103104Если *localedir* не указан, используется системный каталог локали по умолчанию. [2](https://python-all.ru/2.7/library/gettext.html#id7) Если *languages* не указан, то проверяются следующие переменные окружения: `LANGUAGE`, `LC_ALL`, `LC_MESSAGES` и `LANG`. Для переменной *languages* используется первая из них, возвращающая непустое значение. Переменные окружения должны содержать разделённый двоеточиями список языков; он будет разбит по двоеточиям для получения ожидаемого списка кодов языков.105106[`find()`](https://python-all.ru/2.7/library/gettext.html#gettext.find) затем расширяет и нормализует языки, а затем перебирает их в поисках существующего файла, построенного из следующих компонентов:107108`localedir/language/LC_MESSAGES/domain.mo`109110Первое существующее имя файла возвращается [`find()`](https://python-all.ru/2.7/library/gettext.html#gettext.find). Если такого файла не найдено, возвращается `None`. Если указан *all*, возвращается список всех имён файлов в том порядке, в котором они встречаются в списке языков или в переменных окружения.111112#### `gettext.translation(domain[, localedir[, languages[, class_[, fallback[, codeset]]]]])`113114Возвращает экземпляр `Translations` на основе *domain*, *localedir* и *languages*, которые сначала передаются в [`find()`](https://python-all.ru/2.7/library/gettext.html#gettext.find) для получения списка соответствующих путей к файлам `.mo`. Экземпляры с одинаковыми именами файлов `.mo` кэшируются. Фактически создаваемый класс – это либо *class\_*, если он указан, либо `GNUTranslations`. Конструктор класса должен принимать один аргумент – объект файла. Если указан *codeset*, он изменит кодировку, используемую для кодирования переведённых строк.115116Если найдено несколько файлов, последующие файлы используются как запасные для предыдущих. Чтобы иметь возможность задать запасной вариант, [`copy.copy()`](https://python-all.ru/2.7/library/copy.html#copy.copy) используется для клонирования каждого объекта перевода из кэша; фактические данные экземпляра по-прежнему являются общими с кэшем.117118Если файл `.mo` не найден, эта функция вызывает [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError), если *fallback* имеет значение false (по умолчанию), и возвращает экземпляр [`NullTranslations`](https://python-all.ru/2.7/library/gettext.html#gettext.NullTranslations), если *fallback* имеет значение true.119120Изменено в версии 2.4: Добавлен параметр *codeset*.121122#### `gettext.install(domain[, localedir[, unicode[, codeset[, names]]]])`123124Эта функция устанавливает функцию `_()` во встроенное пространство имён Python на основе *domain*, *localedir* и *codeset*, которые передаются функции [`translation()`](https://python-all.ru/2.7/library/gettext.html#gettext.translation). Флаг *unicode* передаётся методу [`install()`](https://python-all.ru/2.7/library/gettext.html#gettext.NullTranslations.install) конечного объекта перевода.125126Описание параметра *names* см. в описании метода [`install()`](https://python-all.ru/2.7/library/gettext.html#gettext.NullTranslations.install) объекта перевода.127128Как показано ниже, строки в приложении, предназначенные для перевода, обычно помечаются обёртыванием их в вызов функции `_()`, например:129130```python131print _('This string will be translated.')132```133134Для удобства функцию `_()` устанавливают в пространство имён встроенных функций Python, чтобы она была легко доступна во всех модулях приложения.135136Изменено в версии 2.4: Добавлен параметр *codeset*.137138Изменено в версии 2.5: Добавлен параметр *names*.139140### 22.1.2.1. Класс [`NullTranslations`](https://python-all.ru/2.7/library/gettext.html#gettext.NullTranslations)141142Классы перевода – это то, что фактически реализует перевод строк сообщений исходного файла в переведённые строки сообщений. Базовый класс, используемый всеми классами перевода, – [`NullTranslations`](https://python-all.ru/2.7/library/gettext.html#gettext.NullTranslations); он предоставляет базовый интерфейс, который можно использовать для написания собственных специализированных классов перевода. Ниже приведены методы `NullTranslations`:143144#### `class gettext.NullTranslations([fp])`145146Принимает необязательный объект файла *fp*, который игнорируется базовым классом. Инициализирует «защищённые» переменные экземпляра *\_info* и *\_charset*, которые устанавливаются производными классами, а также *\_fallback*, который устанавливается через [`add_fallback()`](https://python-all.ru/2.7/library/gettext.html#gettext.NullTranslations.add_fallback). Затем вызывает `self._parse(fp)`, если *fp* не равен `None`.147148#### `_parse(fp)`149150В базовом классе этот метод не выполняет никаких действий; он принимает файловый объект *fp*, читает из файла данные и инициализирует свой каталог сообщений. Если формат файла каталога сообщений не поддерживается, следует переопределить этот метод для разбора такого формата.151152#### `add_fallback(fallback)`153154Добавляет *fallback* в качестве резервного объекта для текущего объекта перевода. Объект перевода должен обращаться к резервному, если не может предоставить перевод для заданного сообщения.155156#### `gettext(message)`157158Если резервный объект установлен, перенаправляет `gettext()` резервному объекту. В противном случае возвращает переведённое сообщение. Переопределяется в производных классах.159160#### `lgettext(message)`161162Если резервный объект установлен, перенаправляет `lgettext()` резервному объекту. В противном случае возвращает переведённое сообщение. Переопределяется в производных классах.163164Новое в версии 2.4.165166#### `ugettext(message)`167168Если резервный объект установлен, перенаправляет `ugettext()` резервному объекту. В противном случае возвращает переведённое сообщение в виде строки Unicode. Переопределяется в производных классах.169170#### `ngettext(singular, plural, n)`171172Если резервный объект установлен, перенаправляет `ngettext()` резервному объекту. В противном случае возвращает переведённое сообщение. Переопределяется в производных классах.173174Новое в версии 2.3.175176#### `lngettext(singular, plural, n)`177178Если резервный объект установлен, перенаправляет `lngettext()` резервному объекту. В противном случае возвращает переведённое сообщение. Переопределяется в производных классах.179180Новое в версии 2.4.181182#### `ungettext(singular, plural, n)`183184Если задан резервный вариант, перенаправить `ungettext()` в него. В противном случае возвращать переведённое сообщение как строку Unicode. Переопределяется в производных классах.185186Новое в версии 2.3.187188#### `info()`189190Возвращает «защищённую» переменную `_info`.191192#### `charset()`193194Возвращает «защищённую» переменную `_charset`.195196#### `output_charset()`197198Возвращает «защищённую» переменную `_output_charset`, определяющую кодировку, используемую для возврата переведённых сообщений.199200Новое в версии 2.4.201202#### `set_output_charset(charset)`203204Изменяет «защищённую» переменную `_output_charset`, определяющую кодировку, используемую для возврата переведённых сообщений.205206Новое в версии 2.4.207208#### `install([unicode[, names]])`209210Если флаг *unicode* равен false, этот метод устанавливает `self.gettext()` во встроенное пространство имён, связывая его с `_`. Если *unicode* равен true, он связывает `self.ugettext()`. По умолчанию *unicode* равен false.211212Если задан параметр *names*, он должен быть последовательностью, содержащей имена функций, которые требуется установить во встроенное пространство имён в дополнение к `_()`. Поддерживаемые имена: `'gettext'` (привязывается к `self.gettext()` или `self.ugettext()` в зависимости от флага *unicode*), `'ngettext'` (привязывается к `self.ngettext()` или `self.ungettext()` в зависимости от флага *unicode*), `'lgettext'` и `'lngettext'`.213214Обратите внимание, что это лишь один из способов, хоть и самый удобный, сделать функцию `_()` доступной в приложении. Поскольку это влияет на всё приложение глобально, и в особенности на встроенное пространство имён, локализованные модули никогда не должны устанавливать `_()`. Вместо этого им следует использовать следующий код, чтобы сделать `_()` доступной в своём модуле:215216```python217import gettext218t = gettext.translation('mymodule', ...)219_ = t.gettext220```221222Это помещает `_()` только в глобальное пространство имён модуля и поэтому влияет только на вызовы внутри этого модуля.223224Изменено в версии 2.5: Добавлен параметр *names*.225226### 22.1.2.2. Класс `GNUTranslations`227228Модуль [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) предоставляет один дополнительный класс, производный от [`NullTranslations`](https://python-all.ru/2.7/library/gettext.html#gettext.NullTranslations): `GNUTranslations`. Этот класс переопределяет `_parse()` для чтения `.mo`-файлов формата GNU **gettext** как в формате big-endian, так и little-endian. Он также преобразует как идентификаторы сообщений, так и строки сообщений в Unicode.229230`GNUTranslations` извлекает необязательные метаданные из каталога переводов. В GNU **gettext** принято включать метаданные как перевод пустой строки. Эти метаданные представлены в стиле [**RFC 822**](https://python-all.ru/2.7/library/gettext.html) пар `key: value` и должны содержать ключ `Project-Id-Version`. Если найден ключ `Content-Type`, то свойство `charset` используется для инициализации «защищённой» переменной экземпляра `_charset`, по умолчанию `None`, если не найдено. Если указана кодировка charset, то все идентификаторы сообщений и строки сообщений, читаемые из каталога, преобразуются в Unicode с использованием этой кодировки. Метод `ugettext()` всегда возвращает строку Unicode, а метод [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext) возвращает закодированную 8-битную строку. Для аргументов идентификаторов сообщений обоих методов допустимы как строки Unicode, так и 8-битные строки, содержащие только символы US-ASCII. Обратите внимание, что версии методов, работающие с Unicode (т.е. `ugettext()` и `ungettext()`), являются рекомендуемым интерфейсом для интернационализированных программ на Python.231232Весь набор пар ключ/значение помещается в словарь и устанавливается как «защищённая» переменная экземпляра `_info`.233234Если магическое число файла `.mo` недействительно или при чтении файла возникают другие проблемы, создание экземпляра класса `GNUTranslations` может вызвать [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError).235236Следующие методы переопределены из реализации базового класса:237238#### `GNUTranslations.gettext(message)`239240Ищет идентификатор *сообщения* в каталоге и возвращает соответствующую строку сообщения в виде 8-битной строки, закодированной с использованием кодировки charset каталога, если она известна. Если в каталоге нет записи для идентификатора *сообщения* и задан резервный вариант, поиск перенаправляется в метод [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext) резервного варианта. В противном случае возвращается идентификатор *сообщения*.241242#### `GNUTranslations.lgettext(message)`243244Эквивалентно [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext), но перевод возвращается в предпочтительной системной кодировке, если другая кодировка не была явно задана с помощью `set_output_charset()`.245246Новое в версии 2.4.247248#### `GNUTranslations.ugettext(message)`249250Ищет идентификатор *сообщения* в каталоге и возвращает соответствующую строку сообщения в виде строки Unicode. Если в каталоге нет записи для идентификатора *сообщения* и задан резервный вариант, поиск перенаправляется в метод [`ugettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.GNUTranslations.ugettext) резервного варианта. В противном случае возвращается идентификатор *сообщения*.251252#### `GNUTranslations.ngettext(singular, plural, n)`253254Выполняет поиск по множественным формам для идентификатора сообщения. *singular* используется как идентификатор сообщения для поиска в каталоге, а *n* используется для определения, какую множественную форму использовать. Возвращаемая строка сообщения представляет собой 8-битную строку, закодированную с использованием кодировки charset каталога, если она известна.255256Если идентификатор сообщения не найден в каталоге и указан резервный вариант, запрос перенаправляется в метод [`ngettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.ngettext) резервного варианта. В противном случае, если *n* равно 1, возвращается *singular*, а во всех остальных случаях возвращается *plural*.257258Новое в версии 2.3.259260#### `GNUTranslations.lngettext(singular, plural, n)`261262Эквивалентно [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext), но перевод возвращается в предпочтительной системной кодировке, если другая кодировка не была явно задана с помощью `set_output_charset()`.263264Новое в версии 2.4.265266#### `GNUTranslations.ungettext(singular, plural, n)`267268Выполняет поиск формы множественного числа по идентификатору сообщения. *singular* используется как идентификатор сообщения для поиска в каталоге, а *n* используется для определения того, какую форму множественного числа использовать. Возвращаемая строка сообщения является строкой Unicode.269270Если идентификатор сообщения не найден в каталоге и указан резервный вариант, запрос перенаправляется в метод [`ungettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.GNUTranslations.ungettext) резервного варианта. В противном случае, если *n* равно 1, возвращается *singular*, а во всех остальных случаях возвращается *plural*.271272Вот пример:273274```python275n = len(os.listdir('.'))276cat = GNUTranslations(somefile)277message = cat.ungettext(278    'There is %(num)d file in this directory',279    'There are %(num)d files in this directory',280    n) % {'num': n}281```282283Новое в версии 2.3.284285### 22.1.2.3. Поддержка каталогов сообщений Solaris286287Операционная система Solaris определяет собственный двоичный формат файлов `.mo`, но, поскольку документации по этому формату найти не удалось, он в настоящее время не поддерживается.288289### 22.1.2.4. Конструктор Catalog290291GNOME использует версию модуля [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) от James Henstridge, но эта версия имеет несколько другой API. Её задокументированное использование было таким:292293```python294import gettext295cat = gettext.Catalog(domain, localedir)296_ = cat.gettext297print _('hello world')298```299300Для совместимости с этим старым модулем функция `Catalog()` является псевдонимом функции [`translation()`](https://python-all.ru/2.7/library/gettext.html#gettext.translation), описанной выше.301302Одно различие между этим модулем и модулем Хенстриджа: его объекты каталога поддерживали доступ через API отображения (mapping API), но, по-видимому, эта возможность не используется и поэтому в настоящее время не поддерживается.303304## 22.1.3. Интернационализация программ и модулей305306Интернационализация (I18N) – это процесс, благодаря которому программа начинает работать с несколькими языками. Локализация (L10N) – это адаптация уже интернационализированной программы к местному языку и культурным особенностям. Чтобы добавить в программу на Python поддержку нескольких языков, нужно выполнить следующие шаги:3073081. подготовить программу или модуль, специально помечая переводимые строки3092. запустить набор инструментов над размеченными файлами для создания исходных каталогов сообщений3103. создание языковых переводов каталогов сообщений3114. использовать модуль [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) для корректного перевода строк сообщений312313Чтобы подготовить код к интернационализации, нужно просмотреть все строки в своих файлах. Любую строку, которую требуется перевести, следует пометить, обернув её в вызов `_('...')` – то есть в функцию `_()`. Например:314315```python316filename = 'mylog.txt'317message = _('writing a log message')318fp = open(filename, 'w')319fp.write(message)320fp.close()321```322323В этом примере строка `'writing a log message'` помечена как кандидат на перевод, а строки `'mylog.txt'` и `'w'` – нет.324325Дистрибутив Python включает два инструмента, которые помогут создать каталоги сообщений после подготовки исходного кода. Они могут быть доступны или не доступны в бинарном дистрибутиве, но их можно найти в дистрибутиве исходных кодов, в каталоге `Tools/i18n`.326327Программа **pygettext** [3](https://python-all.ru/2.7/library/gettext.html#id8) сканирует весь исходный код Python в поиске строк, помеченных ранее как переводимые. Она похожа на программу GNU **gettext**, за исключением того, что понимает все тонкости исходного кода Python, но ничего не знает об исходном коде C или C++. GNU `gettext` не нужна, если вы также не собираетесь переводить код C (например, модули расширения C).328329**pygettext** создаёт текстовые человекочитаемые файлы каталогов сообщений в стиле Uniforum – `.pot`, по сути структурированные человекочитаемые файлы, содержащие каждую помеченную строку в исходном коде вместе с заполнителем для строк перевода. **pygettext** – это скрипт командной строки, поддерживающий интерфейс командной строки, похожий на **xgettext**; для подробностей об его использовании выполните:330331```python332pygettext.py --help333```334335Копии этих файлов `.pot` затем передаются переводчикам, которые создают версии для каждого поддерживаемого естественного языка. Они возвращают заполненные языковые версии в виде файла `.po`. С помощью программы **msgfmt.py** [4](https://python-all.ru/2.7/library/gettext.html#id9) (в каталоге `Tools/i18n`) вы берёте файлы `.po` от переводчиков и создаёте машиночитаемые двоичные файлы каталогов `.mo`. Файлы `.mo` используются модулем [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) для фактической обработки перевода во время выполнения.336337То, как используется модуль [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) в коде, зависит от того, интернационализируется ли один модуль или всё приложение. В следующих двух разделах будет рассмотрен каждый случай.338339### 22.1.3.1. Локализация вашего модуля340341Если вы локализуете свой модуль, нужно быть осторожным, чтобы не вносить глобальные изменения, например, во встроенное пространство имён. Не следует использовать GNU `gettext` API, а вместо этого – API на основе классов.342343Допустим, модуль называется «spam», а его файлы перевода `.mo` для разных естественных языков лежат в каталоге `/usr/share/locale` в формате GNU **gettext**. Вот что нужно поместить в начало модуля:344345```python346import gettext347t = gettext.translation('spam', '/usr/share/locale')348_ = t.lgettext349```350351Если переводчики предоставляют строки Unicode в своих файлах `.po`, вместо этого следует сделать:352353```python354import gettext355t = gettext.translation('spam', '/usr/share/locale')356_ = t.ugettext357```358359### 22.1.3.2. Локализация вашего приложения360361Если вы локализуете приложение, можно установить функцию `_()` глобально во встроенное пространство имён, обычно в главном файле приложения. Тогда во всех файлах приложения можно будет использовать `_('...')` без явной установки в каждом из них.362363В простейшем случае нужно добавить в главный файл приложения следующий код:364365```python366import gettext367gettext.install('myapplication')368```369370Если требуется задать каталог локали или флаг *unicode*, можно передать их в функцию [`install()`](https://python-all.ru/2.7/library/gettext.html#gettext.install):371372```python373import gettext374gettext.install('myapplication', '/usr/share/locale', unicode=1)375```376377### 22.1.3.3. Смена языка на лету378379Если программа должна одновременно поддерживать много языков, можно создать несколько экземпляров перевода и переключаться между ними явно:380381```python382import gettext383384lang1 = gettext.translation('myapplication', languages=['en'])385lang2 = gettext.translation('myapplication', languages=['fr'])386lang3 = gettext.translation('myapplication', languages=['de'])387388# начните с использования language1389lang1.install()390391# ... проходит время, пользователь выбирает language 2392lang2.install()393394# ... проходит ещё больше времени, пользователь выбирает language 3395lang3.install()396```397398### 22.1.3.4. Отложенные переводы399400В большинстве случаев строки переводятся там же, где и пишутся. Однако иногда нужно пометить строки для перевода, но отложить собственно перевод на потом. Классический пример:401402```python403animals = ['mollusk',404           'albatross',405           'rat',406           'penguin',407           'python', ]408# ...409for a in animals:410    print a411```412413Здесь требуется пометить строки в списке `animals` как переводимые, но на самом деле переводить их нужно только при выводе на печать.414415Вот один из способов справиться с этим:416417```python418def _(message): return message419420animals = [_('mollusk'),421           _('albatross'),422           _('rat'),423           _('penguin'),424           _('python'), ]425426del _427428# ...429for a in animals:430    print _(a)431```432433Это работает, потому что фиктивное определение `_()` просто возвращает строку без изменений. И это фиктивное определение временно переопределяет любое определение `_()` во встроенном пространстве имён (до команды [`del`](https://python-all.ru/2.7/reference/simple_stmts.html#del)). Однако будьте осторожны, если во вложенном пространстве имён уже есть определение `_()`.434435Обратите внимание, что второе использование `_()` не будет распознано программой **pygettext** как переводимое, поскольку это не строка.436437Другой способ – следующий пример:438439```python440def N_(message): return message441442animals = [N_('mollusk'),443           N_('albatross'),444           N_('rat'),445           N_('penguin'),446           N_('python'), ]447448# ...449for a in animals:450    print _(a)451```452453В этом случае переводимые строки помечаются функцией `N_()`, [5](https://python-all.ru/2.7/library/gettext.html#id10), которая не конфликтует ни с каким определением `_()`. Однако потребуется обучить программу извлечения сообщений искать переводимые строки, помеченные `N_()`. **pygettext** и **xpot** обе поддерживают это с помощью параметров командной строки.454455### 22.1.3.5. [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext) и [`lgettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.lgettext)456457В Python 2.4 было введено семейство функций [`lgettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.lgettext). Их цель – предоставить альтернативу, более совместимую с текущей реализацией GNU gettext. В отличие от [`gettext()`](https://python-all.ru/2.7/library/gettext.html#module-gettext), которая возвращает строки, закодированные с использованием той же кодировки, что и в файле перевода, [`lgettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.lgettext) будет возвращать строки, закодированные в предпочтительной системной кодировке, возвращаемой [`locale.getpreferredencoding()`](https://python-all.ru/2.7/library/locale.html#locale.getpreferredencoding). Также обратите внимание, что Python 2.4 вводит новые функции для явного выбора кодировки, используемой в переведённых строках. Если кодировка задана явно, даже [`lgettext()`](https://python-all.ru/2.7/library/gettext.html#gettext.lgettext) будет возвращать переведённые строки в запрошенной кодировке, как и следовало ожидать в реализации GNU gettext.458459## 22.1.4. Благодарности460461Следующие люди внесли код, отзывы, предложения по оформлению, предыдущие реализации и ценный опыт в создание этого модуля:462463- Peter Funk464- James Henstridge465- Juan David Ibáñez Palomar466- Marc-André Lemburg467- Martin von Löwis468- François Pinard469- Barry Warsaw470- Gustavo Niemeyer471472Сноски473474**[1](https://python-all.ru/2.7/library/gettext.html#id1)**475476Каталог локали по умолчанию зависит от системы; например, в RedHat Linux это `/usr/share/locale`, а в Solaris – `/usr/lib/locale`. Модуль [`gettext`](https://python-all.ru/2.7/library/gettext.html#module-gettext) не пытается поддерживать эти системно-зависимые значения по умолчанию; вместо этого его значение по умолчанию – `sys.prefix/share/locale`. По этой причине всегда лучше вызывать [`bindtextdomain()`](https://python-all.ru/2.7/library/gettext.html#gettext.bindtextdomain) с явным абсолютным путём в начале приложения.477478**[2](https://python-all.ru/2.7/library/gettext.html#id2)**479480См. сноску для [`bindtextdomain()`](https://python-all.ru/2.7/library/gettext.html#gettext.bindtextdomain) выше.481482**[3](https://python-all.ru/2.7/library/gettext.html#id3)**483484Франсуа Пинар написал программу под названием **xpot**, которая выполняет аналогичную задачу. Она доступна как часть его [пакета po-utils](https://python-all.ru/2.7/library/gettext.html).485486**[4](https://python-all.ru/2.7/library/gettext.html#id4)**487488**msgfmt.py** двоично совместим с GNU **msgfmt**, за исключением того, что предоставляет более простую реализацию на чистом Python. С помощью этого и **pygettext.py** обычно не требуется устанавливать пакет GNU **gettext** для интернационализации приложений Python.489490**[5](https://python-all.ru/2.7/library/gettext.html#id5)**491492Выбор `N_()` здесь абсолютно произволен; с тем же успехом это мог быть `MarkThisStringForTranslation()`.493