gettext.md
1> **Источник:** https://python-all.ru/3.5/library/gettext.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 23.1. [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) – Многоязычные службы интернационализации89**Исходный код:** [Lib/gettext.py](https://python-all.ru/src/3.5/Lib/gettext.py)1011---1213Модуль [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) предоставляет службы интернационализации (I18N) и локализации (L10N) для модулей и приложений Python. Он поддерживает как API каталогов сообщений GNU `gettext`, так и API более высокого уровня, основанный на классах, который может лучше подходить для файлов Python. Описанный ниже интерфейс позволяет писать сообщения модуля и приложения на одном естественном языке и предоставлять каталог переведённых сообщений для работы на разных естественных языках.1415Также даются некоторые советы по локализации модулей и приложений Python.1617## 23.1.1. GNU **gettext** API1819Модуль [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) определяет следующий API, очень похожий на API GNU **gettext**. Использование этого API повлияет на перевод всего приложения глобально. Часто это желательно, если приложение одноязычное и выбор языка зависит от локали пользователя. Если требуется локализовать модуль Python или приложению нужно переключать языки на лету, вероятно, следует использовать API на основе классов.2021#### `gettext.bindtextdomain(domain, localedir=None)`2223Связывает *domain* с каталогом локали *localedir*. Если говорить точнее, [`gettext`](https://python-all.ru/3.5/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/3.5/library/gettext.html#id3)2627#### `gettext.bind_textdomain_codeset(domain, codeset=None)`2829Привязывает *domain* к *codeset*, изменяя кодировку байтовых строк, возвращаемых функциями [`lgettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.lgettext), [`ldgettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.ldgettext), [`lngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.lngettext) и [`ldngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.ldngettext). Если *codeset* опущен, возвращается текущая привязка.3031#### `gettext.textdomain(domain=None)`3233Изменяет или запрашивает текущий глобальный домен. Если *domain* равен `None`, возвращается текущий глобальный домен; в противном случае глобальный домен устанавливается в *domain*, который и возвращается.3435#### `gettext.gettext(message)`3637Возвращает локализованный перевод *message* на основе текущего глобального домена, языка и каталога локали. Эта функция обычно имеет псевдоним `_()` в локальном пространстве имён (см. примеры ниже).3839#### `gettext.dgettext(domain, message)`4041Как [`gettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.gettext), но ищет сообщение в указанном *domain*.4243#### `gettext.ngettext(singular, plural, n)`4445Как [`gettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.gettext), но учитывает формы множественного числа. Если перевод найден, применяет формулу множественного числа к *n* и возвращает результирующее сообщение (в некоторых языках более двух форм множественного числа). Если перевод не найден, возвращает *singular*, если *n* равно 1; в противном случае возвращает *plural*.4647Формула множественного числа берётся из заголовка каталога. Это выражение на C или Python со свободной переменной *n*; выражение вычисляет индекс формы множественного числа в каталоге. См. [документацию GNU gettext](https://python-all.ru/3.5/library/gettext.html) для точного синтаксиса, используемого в файлах `.po`, и формулы для различных языков.4849#### `gettext.dngettext(domain, singular, plural, n)`5051Как [`ngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.ngettext), но ищет сообщение в указанном *domain*.5253#### `gettext.lgettext(message)`5455#### `gettext.ldgettext(domain, message)`5657#### `gettext.lngettext(singular, plural, n)`5859#### `gettext.ldngettext(domain, singular, plural, n)`6061Эквивалентно соответствующим функциям без префикса `l` ([`gettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.gettext), [`dgettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.dgettext), [`ngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.ngettext) и [`dngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.dngettext)), но перевод возвращается в виде байтовой строки, закодированной в предпочтительной системной кодировке, если другая кодировка не была явно задана с помощью [`bind_textdomain_codeset()`](https://python-all.ru/3.5/library/gettext.html#gettext.bind_textdomain_codeset).6263> **Предупреждение**64>65> В Python 3 этих функций следует избегать, поскольку они возвращают закодированные байты. Гораздо лучше использовать альтернативы, возвращающие строки Unicode, так как большинство приложений на Python работают с человекочитаемым текстом в виде строк, а не байтов. Более того, при проблемах с кодировкой переведённых строк могут возникать непредвиденные исключения, связанные с Unicode. Есть вероятность, что функции `l*()` будут объявлены устаревшими в будущих версиях Python из-за присущих им проблем и ограничений.6667Обратите внимание, что GNU **gettext** также определяет метод `dcgettext()`, но он был признан бесполезным и на данный момент не реализован.6869Вот пример типичного использования этого API:7071```python72import gettext73gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')74gettext.textdomain('myapplication')75_ = gettext.gettext76# ...77print(_('This is a translatable string.'))78```7980## 23.1.2. API на основе классов8182API на основе классов модуля [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) предоставляет больше гибкости и удобства, чем GNU **gettext** API. Это рекомендуемый способ локализации приложений и модулей Python. [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) определяет класс «translations», который реализует разбор файлов формата GNU `.mo` и содержит методы для возврата строк. Экземпляры этого класса «translations» также могут устанавливать себя во встроенное пространство имён как функция `_()`.8384#### `gettext.find(domain, localedir=None, languages=None, all=False)`8586Эта функция реализует стандартный алгоритм поиска файлов `.mo`. Она принимает *домен*, такой же, как в [`textdomain()`](https://python-all.ru/3.5/library/gettext.html#gettext.textdomain). Необязательный параметр *localedir* – как в [`bindtextdomain()`](https://python-all.ru/3.5/library/gettext.html#gettext.bindtextdomain). Необязательный параметр *languages* – это список строк, где каждая строка – код языка.8788Если *localedir* не указан, используется системный каталог локали по умолчанию. [\[2\]](https://python-all.ru/3.5/library/gettext.html#id4) Если *languages* не указан, то проверяются следующие переменные окружения: `LANGUAGE`, `LC_ALL`, `LC_MESSAGES` и `LANG`. Для переменной *languages* используется первая из них, возвращающая непустое значение. Переменные окружения должны содержать разделённый двоеточиями список языков; он будет разбит по двоеточиям для получения ожидаемого списка кодов языков.8990[`find()`](https://python-all.ru/3.5/library/gettext.html#gettext.find) затем расширяет и нормализует языки, а затем перебирает их в поисках существующего файла, построенного из следующих компонентов:9192`localedir/language/LC_MESSAGES/domain.mo`9394Первое существующее имя файла возвращается [`find()`](https://python-all.ru/3.5/library/gettext.html#gettext.find). Если такого файла не найдено, возвращается `None`. Если указан *all*, возвращается список всех имён файлов в том порядке, в котором они встречаются в списке языков или в переменных окружения.9596#### `gettext.translation(domain, localedir=None, languages=None, class_=None, fallback=False, codeset=None)`9798Возвращает экземпляр `Translations` на основе *domain*, *localedir* и *languages*, которые сначала передаются в [`find()`](https://python-all.ru/3.5/library/gettext.html#gettext.find) для получения списка соответствующих путей к файлам `.mo`. Экземпляры с одинаковыми именами файлов `.mo` кэшируются. Фактически создаваемый класс – либо *class\_*, если он указан, иначе [`GNUTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.GNUTranslations). Конструктор класса должен принимать единственный аргумент [file object](https://python-all.ru/3.5/glossary.html#term-file-object). Если указан *codeset*, он изменит кодировку, используемую для кодирования переведённых строк в методах [`lgettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.lgettext) и [`lngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.lngettext).99100Если найдено несколько файлов, последующие файлы используются как запасные для предыдущих. Чтобы иметь возможность задать запасной вариант, [`copy.copy()`](https://python-all.ru/3.5/library/copy.html#copy.copy) используется для клонирования каждого объекта перевода из кэша; фактические данные экземпляра по-прежнему являются общими с кэшем.101102Если файл `.mo` не найден, эта функция вызывает [`OSError`](https://python-all.ru/3.5/library/exceptions.html#OSError), если *fallback* имеет значение false (по умолчанию), и возвращает экземпляр [`NullTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations), если *fallback* имеет значение true.103104Изменено в версии 3.3: [`IOError`](https://python-all.ru/3.5/library/exceptions.html#IOError) раньше вызывалось вместо [`OSError`](https://python-all.ru/3.5/library/exceptions.html#OSError).105106#### `gettext.install(domain, localedir=None, codeset=None, names=None)`107108Эта функция устанавливает функцию `_()` в пространство имён встроенных функций Python на основе *domain*, *localedir* и *codeset*, которые передаются в функцию [`translation()`](https://python-all.ru/3.5/library/gettext.html#gettext.translation).109110Описание параметра *names* см. в описании метода [`install()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.install) объекта перевода.111112Как показано ниже, строки в приложении, предназначенные для перевода, обычно помечаются обёртыванием их в вызов функции `_()`, например:113114```python115print(_('This string will be translated.'))116```117118Для удобства функцию `_()` устанавливают в пространство имён встроенных функций Python, чтобы она была легко доступна во всех модулях приложения.119120### 23.1.2.1. Класс [`NullTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations)121122Классы перевода – это то, что фактически реализует перевод строк сообщений исходного файла в переведённые строки сообщений. Базовый класс, используемый всеми классами перевода, – [`NullTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations); он предоставляет базовый интерфейс, который можно использовать для написания собственных специализированных классов перевода. Ниже приведены методы [`NullTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations):123124#### `class gettext.NullTranslations(fp=None)`125126Принимает необязательный [файловый объект](https://python-all.ru/3.5/glossary.html#term-file-object) *fp*, который игнорируется базовым классом. Инициализирует «защищённые» переменные экземпляра *\_info* и *\_charset*, которые устанавливаются производными классами, а также *\_fallback*, которая устанавливается через [`add_fallback()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.add_fallback). Затем вызывает `self._parse(fp)`, если *fp* не равен `None`.127128#### `_parse(fp)`129130В базовом классе этот метод не выполняет никаких действий; он принимает файловый объект *fp*, читает из файла данные и инициализирует свой каталог сообщений. Если формат файла каталога сообщений не поддерживается, следует переопределить этот метод для разбора такого формата.131132#### `add_fallback(fallback)`133134Добавляет *fallback* в качестве запасного объекта для текущего объекта перевода. Объект перевода должен обращаться к запасному объекту, если он не может предоставить перевод для данного сообщения.135136#### `gettext(message)`137138Если был установлен запасной объект, перенаправить [`gettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.gettext) к нему. В противном случае вернуть *message*. Переопределяется в производных классах.139140#### `ngettext(singular, plural, n)`141142Если был установлен запасной объект, перенаправить [`ngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.ngettext) к нему. В противном случае вернуть *singular*, если *n* равен 1; иначе вернуть *plural*. Переопределяется в производных классах.143144#### `lgettext(message)`145146#### `lngettext(singular, plural, n)`147148Эквивалентно [`gettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.gettext) и [`ngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.ngettext), но перевод возвращается в виде байтовой строки, закодированной в предпочтительной системной кодировке, если кодировка не была явно задана с помощью [`set_output_charset()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.set_output_charset). Переопределяется в производных классах.149150> **Предупреждение**151>152> Этих методов следует избегать в Python 3. См. предупреждение для функции [`lgettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.lgettext).153154#### `info()`155156Возвращает «защищённую» переменную `_info`.157158#### `charset()`159160Возвращает кодировку файла каталога сообщений.161162#### `output_charset()`163164Возвращает кодировку, используемую для возврата переведённых сообщений в [`lgettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.lgettext) и [`lngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.lngettext).165166#### `set_output_charset(charset)`167168Изменяет кодировку, используемую для возврата переведённых сообщений.169170#### `install(names=None)`171172Этот метод устанавливает [`gettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.gettext) во встроенное пространство имён, связывая его с `_`.173174Если указан параметр *names*, он должен быть последовательностью, содержащей имена функций, которые требуется установить в пространство имён builtins дополнительно к `_()`. Поддерживаемые имена: `'gettext'`, `'ngettext'`, `'lgettext'` и `'lngettext'`.175176Обратите внимание, что это лишь один из способов, хоть и самый удобный, сделать функцию `_()` доступной в приложении. Поскольку это влияет на всё приложение глобально, и в особенности на встроенное пространство имён, локализованные модули никогда не должны устанавливать `_()`. Вместо этого им следует использовать следующий код, чтобы сделать `_()` доступной в своём модуле:177178```python179import gettext180t = gettext.translation('mymodule', ...)181_ = t.gettext182```183184Это помещает `_()` только в глобальное пространство имён модуля и поэтому влияет только на вызовы внутри этого модуля.185186### 23.1.2.2. Класс [`GNUTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.GNUTranslations)187188Модуль [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) предоставляет один дополнительный класс, производный от [`NullTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations): [`GNUTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.GNUTranslations). Этот класс переопределяет `_parse()`, чтобы обеспечить чтение файлов `.mo` в формате GNU **gettext** как в формате big-endian, так и little-endian.189190[`GNUTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.GNUTranslations) извлекает необязательные метаданные из каталога переводов. Согласно соглашению GNU **gettext**, метаданные включаются как перевод пустой строки. Эти метаданные представлены в виде пар [**RFC 822**](https://python-all.ru/3.5/library/gettext.html)-style `key: value` и должны содержать ключ `Project-Id-Version`. Если найден ключ `Content-Type`, то свойство `charset` используется для инициализации «защищённой» переменной экземпляра `_charset`; по умолчанию `None`, если не найдено. Если указана кодировка, то все идентификаторы сообщений и строки сообщений, прочитанные из каталога, преобразуются в Unicode с использованием этой кодировки; в противном случае предполагается кодировка ASCII.191192Поскольку идентификаторы сообщений также читаются как строки Unicode, все методы `*gettext()` будут считать идентификаторы сообщений строками Unicode, а не байтовыми строками.193194Весь набор пар ключ/значение помещается в словарь и устанавливается как «защищённая» переменная экземпляра `_info`.195196Если магическое число файла `.mo` недействительно, основной номер версии неожиданный, или возникают другие проблемы при чтении файла, создание экземпляра класса [`GNUTranslations`](https://python-all.ru/3.5/library/gettext.html#gettext.GNUTranslations) может вызвать исключение [`OSError`](https://python-all.ru/3.5/library/exceptions.html#OSError).197198#### `class gettext.GNUTranslations`199200Следующие методы переопределены из реализации базового класса:201202#### `gettext(message)`203204Ищет идентификатор *message* в каталоге и возвращает соответствующую строку сообщения в виде строки Unicode. Если в каталоге нет записи для идентификатора *message* и задан резервный источник (fallback), поиск перенаправляется в метод [`gettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.gettext) резервного источника. В противном случае возвращается идентификатор *message*.205206#### `ngettext(singular, plural, n)`207208Выполняет поиск формы множественного числа по идентификатору сообщения. *singular* используется как идентификатор сообщения для поиска в каталоге, а *n* используется для определения того, какую форму множественного числа использовать. Возвращаемая строка сообщения является строкой Unicode.209210Если идентификатор сообщения не найден в каталоге и указан резервный источник, запрос перенаправляется в метод [`ngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.ngettext) резервного источника. В противном случае, когда *n* равно 1, возвращается *singular*, а в остальных случаях возвращается *plural*.211212Вот пример:213214```python215n = len(os.listdir('.'))216cat = GNUTranslations(somefile)217message = cat.ngettext(218 'There is %(num)d file in this directory',219 'There are %(num)d files in this directory',220 n) % {'num': n}221```222223#### `lgettext(message)`224225#### `lngettext(singular, plural, n)`226227Эквивалентно [`gettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.GNUTranslations.gettext) и [`ngettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.GNUTranslations.ngettext), но перевод возвращается в виде байтовой строки, закодированной в предпочтительной системной кодировке, если кодировка не была явно задана с помощью [`set_output_charset()`](https://python-all.ru/3.5/library/gettext.html#gettext.NullTranslations.set_output_charset).228229> **Предупреждение**230>231> Этих методов следует избегать в Python 3. См. предупреждение для функции [`lgettext()`](https://python-all.ru/3.5/library/gettext.html#gettext.lgettext).232233### 23.1.2.3. Поддержка каталогов сообщений Solaris234235Операционная система Solaris определяет собственный двоичный формат файлов `.mo`, но, поскольку документации по этому формату найти не удалось, он в настоящее время не поддерживается.236237### 23.1.2.4. Конструктор Catalog238239GNOME использует версию модуля [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) от James Henstridge, но эта версия имеет несколько другой API. Её задокументированное использование было таким:240241```python242import gettext243cat = gettext.Catalog(domain, localedir)244_ = cat.gettext245print(_('hello world'))246```247248Для совместимости с этим старым модулем функция `Catalog()` является псевдонимом функции [`translation()`](https://python-all.ru/3.5/library/gettext.html#gettext.translation), описанной выше.249250Одно различие между этим модулем и модулем Хенстриджа: его объекты каталога поддерживали доступ через API отображения (mapping API), но, по-видимому, эта возможность не используется и поэтому в настоящее время не поддерживается.251252## 23.1.3. Интернационализация программ и модулей253254Интернационализация (I18N) – это процесс, благодаря которому программа начинает работать с несколькими языками. Локализация (L10N) – это адаптация уже интернационализированной программы к местному языку и культурным особенностям. Чтобы добавить в программу на Python поддержку нескольких языков, нужно выполнить следующие шаги:2552561. подготовить программу или модуль, специально помечая переводимые строки2572. запустить набор инструментов над размеченными файлами для создания исходных каталогов сообщений2583. создание языковых переводов каталогов сообщений2594. использовать модуль [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) для корректного перевода строк сообщений260261Чтобы подготовить код к интернационализации, нужно просмотреть все строки в своих файлах. Любую строку, которую требуется перевести, следует пометить, обернув её в вызов `_('...')` – то есть в функцию `_()`. Например:262263```python264filename = 'mylog.txt'265message = _('writing a log message')266fp = open(filename, 'w')267fp.write(message)268fp.close()269```270271В этом примере строка `'writing a log message'` помечена как кандидат на перевод, а строки `'mylog.txt'` и `'w'` – нет.272273Существует несколько инструментов для извлечения строк, предназначенных для перевода. Исходная программа GNU **gettext** поддерживала только исходный код на C или C++, но её расширенная версия **xgettext** сканирует код на многих языках, включая Python, чтобы найти строки, помеченные как переводимые. [Babel](https://python-all.ru/3.5/library/gettext.html) – это библиотека интернационализации для Python, в состав которой входит скрипт `pybabel` для извлечения и компиляции каталогов сообщений. Программа Франсуа Пинара **xpot** делает то же самое и доступна как часть его [пакета po-utils](https://python-all.ru/3.5/library/gettext.html).274275(В Python также есть чисто питоновские версии этих программ: **pygettext.py** и **msgfmt.py**; некоторые дистрибутивы Python устанавливают их автоматически. **pygettext.py** похожа на **xgettext**, но понимает только исходный код Python и не умеет работать с другими языками вроде C или C++. **pygettext.py** поддерживает интерфейс командной строки, аналогичный **xgettext**; подробнее о его использовании – в выводе `pygettext.py --help`. **msgfmt.py** двоично совместима с GNU **msgfmt**. С этими двумя программами для интернационализации приложений на Python пакет GNU **gettext** может и не понадобиться.)276277**xgettext**, **pygettext** и похожие инструменты создают файлы `.po` – каталоги сообщений. Это структурированные, человекочитаемые файлы, содержащие каждую помеченную строку из исходного кода вместе с местом для переведённых версий этих строк.278279Копии этих файлов `.po` затем передаются переводчикам-людям, которые пишут переводы для каждого поддерживаемого естественного языка. Они возвращают готовые языковые версии в виде файла `<language-name>.po`, который компилируется в машинно-читаемый двоичный каталог `.mo` с помощью программы **msgfmt**. Файлы `.mo` используются модулем [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) для непосредственного перевода во время выполнения.280281То, как используется модуль [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) в коде, зависит от того, интернационализируется ли один модуль или всё приложение. В следующих двух разделах будет рассмотрен каждый случай.282283### 23.1.3.1. Локализация модуля284285Если вы локализуете свой модуль, нужно быть осторожным, чтобы не вносить глобальные изменения, например, во встроенное пространство имён. Не следует использовать GNU `gettext` API, а вместо этого – API на основе классов.286287Допустим, модуль называется «spam», а его файлы перевода `.mo` для разных естественных языков лежат в каталоге `/usr/share/locale` в формате GNU **gettext**. Вот что нужно поместить в начало модуля:288289```python290import gettext291t = gettext.translation('spam', '/usr/share/locale')292_ = t.gettext293```294295### 23.1.3.2. Локализация приложения296297Если вы локализуете приложение, можно установить функцию `_()` глобально во встроенное пространство имён, обычно в главном файле приложения. Тогда во всех файлах приложения можно будет использовать `_('...')` без явной установки в каждом из них.298299В простейшем случае нужно добавить в главный файл приложения следующий код:300301```python302import gettext303gettext.install('myapplication')304```305306Если требуется указать каталог с языковыми файлами, можно передать его в функцию [`install()`](https://python-all.ru/3.5/library/gettext.html#gettext.install):307308```python309import gettext310gettext.install('myapplication', '/usr/share/locale')311```312313### 23.1.3.3. Смена языка на лету314315Если программа должна одновременно поддерживать много языков, можно создать несколько экземпляров перевода и переключаться между ними явно:316317```python318import gettext319320lang1 = gettext.translation('myapplication', languages=['en'])321lang2 = gettext.translation('myapplication', languages=['fr'])322lang3 = gettext.translation('myapplication', languages=['de'])323324# начните с использования language1325lang1.install()326327# ... проходит время, пользователь выбирает language 2328lang2.install()329330# ... проходит ещё больше времени, пользователь выбирает language 3331lang3.install()332```333334### 23.1.3.4. Отложенные переводы335336В большинстве случаев строки переводятся там же, где и пишутся. Однако иногда нужно пометить строки для перевода, но отложить собственно перевод на потом. Классический пример:337338```python339animals = ['mollusk',340 'albatross',341 'rat',342 'penguin',343 'python', ]344# ...345for a in animals:346 print(a)347```348349Здесь требуется пометить строки в списке `animals` как переводимые, но на самом деле переводить их нужно только при выводе на печать.350351Вот один из способов справиться с этим:352353```python354def _(message): return message355356animals = [_('mollusk'),357 _('albatross'),358 _('rat'),359 _('penguin'),360 _('python'), ]361362del _363364# ...365for a in animals:366 print(_(a))367```368369Это работает, потому что фиктивное определение `_()` просто возвращает строку без изменений. И это фиктивное определение временно переопределяет любое определение `_()` во встроенном пространстве имён (до команды [`del`](https://python-all.ru/3.5/reference/simple_stmts.html#del)). Однако будьте осторожны, если во вложенном пространстве имён уже есть определение `_()`.370371Обратите внимание, что второе использование `_()` не будет определено программой **gettext** как переводимое, поскольку параметр не является строковым литералом.372373Другой способ – следующий пример:374375```python376def N_(message): return message377378animals = [N_('mollusk'),379 N_('albatross'),380 N_('rat'),381 N_('penguin'),382 N_('python'), ]383384# ...385for a in animals:386 print(_(a))387```388389В этом случае переводимые строки помечаются функцией `N_()`, которая не конфликтует ни с одним определением `_()`. Однако придётся научить программу извлечения сообщений искать строки, помеченные `N_()`. **xgettext**, **pygettext**, `pybabel extract` и **xpot** – все они поддерживают это через ключ командной строки `-k`. Выбор `N_()` здесь совершенно произволен; с тем же успехом можно было использовать `MarkThisStringForTranslation()`.390391## 23.1.4. Благодарности392393Следующие люди внесли код, отзывы, предложения по оформлению, предыдущие реализации и ценный опыт в создание этого модуля:394395- Peter Funk396- James Henstridge397- Juan David Ibáñez Palomar398- Marc-André Lemburg399- Martin von Löwis400- François Pinard401- Barry Warsaw402- Gustavo Niemeyer403404Сноски405406| [\[1\]](https://python-all.ru/3.5/library/gettext.html#id1) | Каталог локали по умолчанию зависит от системы; например, в RedHat Linux это `/usr/share/locale`, а в Solaris – `/usr/lib/locale`. Модуль [`gettext`](https://python-all.ru/3.5/library/gettext.html#module-gettext) не пытается поддерживать эти системно-зависимые значения по умолчанию; вместо этого его значение по умолчанию – `sys.prefix/share/locale`. По этой причине всегда лучше вызывать [`bindtextdomain()`](https://python-all.ru/3.5/library/gettext.html#gettext.bindtextdomain) с явным абсолютным путём в начале приложения. |407| --- | --- |408409| [\[2\]](https://python-all.ru/3.5/library/gettext.html#id2) | См. сноску для [`bindtextdomain()`](https://python-all.ru/3.5/library/gettext.html#gettext.bindtextdomain) выше. |410| --- | --- |411