Как использовать несколько файлов .mo одновременно для перевода gettext? - PullRequest
6 голосов
/ 15 января 2012

Короче говоря, могу ли я использовать в python много файлов .mo для одного и того же языка в одно и то же время?

В моем приложении на python мне нужно использовать gettext для I18N.Это приложение использует вид системы плагинов.Это означает, что вы можете скачать плагин и поместить его в соответствующий каталог, и он будет работать как любой другой пакет Python.Основное приложение хранит файл .mo, который он использует, скажем, ./locale/en/LC_MESSAGES/main.mo.И плагин № 1 имеет свой собственный .mo файл с именем plugin1.mo в том же каталоге.

Я бы использовал это для загрузки сообщений main.mo I18N:

gettext.install('main', './locale', unicode=False)

Как я могу установить и другие, чтобы все плагины были переведены так, как они должны быть?

Решения, о которых я думал:

Должен ли я gettext.install() в каждом пакетеПространство имен?Но это переопределит _(), определенный ранее, и испортит будущие переводы основного приложения.

Есть ли способ объединить два файла .mo в один (например, когда установлен новый плагин?))?

Во время выполнения я могу объединить их в один GNUTranslation объект?Или переопределить метод _() по умолчанию, который добавляется в глобальное пространство имен?Тогда, как бы я пошел с этим вариантом?Вместо _('Hello World') я бы использовал _('plugin1', 'Hello World in plug-in 1')

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

Ответы [ 2 ]

3 голосов
/ 13 января 2016

gettext.install() устанавливает неизменяемый единственный и только _ во встроенные модули (модуль __builtin__ или builtins в py3) - app-global.Таким образом, нет никакой гибкости.
Примечание. Порядок разрешения имен Python: locals> module-globals> builtins.

Так или иначе gettext.translation() (API на основе классов) или даже gettext.GNUTranslations() (например,для пользовательских схем .mo path) будет использоваться явно для одновременного использования нескольких переводов или смешанного стиля.

Некоторые параметры:

  • Через t = gettext.translation(...); _ = t.ugettextВы можете просто поместить отдельные переводы как _ в каждое глобальное пространство имен модуля - возможно, более автоматизированный способ в реальном мире.Просто, возможно, основной перевод все еще может войти во встроенные (через main_t.install()).

  • Если все или многие переводы в порядке, или то, что вам нужно, вы можете объединить несколько переводов по всему миру через t.install(); t.add_fallback(t_plugin1); t.add_fallback(t_plugin1);...; - и в противном случае сохранить глобальный подход приложения.

  • могут использоваться ключевые слова gettext, отличные от _, и могут передаваться через опцию xgettext -k other_keyword.Но мне не нравятся длинные и уникальные для модуля имена.
    (Тем не менее, лично я предпочитаю ключевое слово I, как правило, вместо _, и я также включаю схему оператора, например I % "some text" вместо _("some text") или I("some text"). Через I = t; t.__call__ = t.__mod__ = t.ugettext эффективно, плюс небольшой патч pygettext.py . Этот шаблон более приятен для ввода, выглядит более читабельным и Pythonic для меня, и избегает критического / уродливого столкновения имен _ в Python с интерактивным последним результатом-анафором (см. sys.displayhook) при использовании модулей gettext в интерактивных приглашениях Python. _ также «зарезервирован» как мой предпочтительный (локальный) заполнитель для неиспользуемых значений в выражениях, подобных_, _, x, y, z, _ = some_tuple.
    В конце концов gettext является довольно простым модулем и механизмом, и вещи легко настраиваются в Python.)

1 голос
/ 16 января 2012

Вы должны использовать разные домены для каждого плагина.Домен может быть именем пакета для предотвращения конфликтов.

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

Каждый плагин может предоставить свое собственное «undescore», легко связанное с доменом плагина:

from my.plugin import MessageFactory as _my_plugin

Обратите внимание, что подчеркивание - это всего лишь соглашение, поэтому инструменты извлечения могут найти i18n-включенные сообщения в программе.Сообщения плагинов должны быть отмечены подчеркиванием в соответствующих пакетах (вы помещаете их в отдельные пакеты, верно?).Во всех других местах вы можете называть эти фабрики другими именами и подчеркивать основной домен перевода программ.

Я менее уверен насчет .mo-файлов, но вы наверняка можете скомпилировать все свои.PO файлы в один файл .mo.Однако, если плагины написаны независимыми авторами, не желающими сотрудничать, могут возникать конфликты.

ОБНОВЛЕНИЕ:

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

Другими словами, плагины должны заботиться о своих переводах самостоятельно.Основное приложение может использовать функцию перевода, специфичную для плагина, как часть плагина API.Извлечение или ручное добавление строк в po / mo-файлы также не является проблемой для основного приложения: автор плагина может предоставить переводы.

...