РЕДАКТИРОВАТЬ 12/12/2018:
После некоторой работы я мог бы создать конкретный пакет на основе того, что приведено ниже в этом ответе.Его можно использовать из других проектов для автоматической компиляции po-файлов во время сборки с помощью волшебства setuptools enty_points.Теперь он доступен на GitHUB (https://github.com/s-ball/mo_installer) и распространяется на PyPI (https://pypi.org/project/mo_installer)
). Исследования, которые я проводил до того, как задать вопрос, дали мне достаточно подсказок, чтобы найти возможное решение.
Теперь я могу сказать, что возможно включить mo-файл для конкретной платформы в колесо - к сожалению, в моем текущем решении колесо не указывает, что оно зависит от платформы. Но это же решение позволяет создать источник.дистрибутив, который строит файл mo на целевой платформе.
Теперь для подробностей:
инструменты, необходимые для компиляции файла mo на целевой:
Большинство решений, выбранных из Google или SO, основаны либо на Babel, либо на программе GNU gettext * 1019. * Но инструменты cPython включают в себя чистый Python-модуль msgfmt.py
, которого здесь достаточно. К сожалению, этот инструмент часто не устанавливается по умолчанию вмногие Linux / Unix-подобные. Мое решение просто включает в себя копию этого модуля (простой файл 7k) для версии 3.7.1. Он выглядит как очень стабильный код(несколько изменений за последние годы), и он должен работать для любого Python> = 3.3
интеграция с setuptools
Волшебство setuptools заключается в том, что одна и та же подкоманда build внутреннеиспользуется для сборки бинарного колеса, для установки с помощью pip из исходного пакета или для непосредственной установки с python setup.py install
из копии (git clone) полного исходного пакета.Поэтому я предоставляю build
подкласс в setup.py
, который генерирует файлы .mo с их полным путем перед вызовом метода суперкласса.Я также использую файл MANIFEST.in
, чтобы вывести список файлов, которые должны быть скопированы в исходном дистрибутиве, и аргумент установки package_data
, чтобы вывести список того, что должно быть в бинарном пакете или папке установки
использование во время выполнения
При условии, что иерархия mo, устанавливаемая в известном пакете, os.dirname(__file__)
, вызываемая из модуля этого пакета, дает его родительскую папку
Код (при условии, что файл msgfmt.py
скопирован в папку tools_i18n
, а файлы po находятся в папке src
):
в setup.py
...
sys.path.append(os.path.join(os.path.dirname(__file__), "tools_i18n"))
import msgfmt
from distutils.command.build import build as _build
class Builder(_build):
def run(self):
# po files in src folder are named domain_lang.po
po = re.compile(r"(.*)_(.*).po")
for file in os.listdir("src"):
m = po.match(file)
if m:
# create the LANG/LC_MESSAGES subdir of "locale"
path = os.path.join(self.build_lib, NAME, "locale",
m.group(2), "LC_MESSAGES")
os.makedirs(path, exist_ok=True)
# use msgfmt.py to compile the po file
msgfmt.make(os.path.join("src", file),
os.path.join(path, m.group(1) + ".mo"))
_build.run(self)
setup(
name=NAME,
...
package_data = { "": [..., "locale/*/*/*.mo"]}, # ensure .mo file are copied
cmdclass = {"build": Builder},
)
InMANIFEST.in
:
...
include src/*
include tools_i18n/*
Чтобы использовать переводы во время выполнения:
locpath = os.path.dirname(__file__)
lang = locale.getdefaultlocale()[0] # to get platform default language, or whatever...
tr = gettext.translation("argparse", os.path.join(locpath, "locale"),
[lang], fallback=True)
Полный проект с использованием этого метода доступен по адресу https://github.com/s-ball/i18nparse
И последнее, но не менее важное: после более глубокого чтения gettext doc GNU я могу сказать, что gettext может обрабатывать mo-файлы независимо от их порядкового номера:
MO-файлов любогоEndianness может использоваться на любой платформе.Когда MO-файл имеет порядковый номер, отличный от порядкового номера платформы, 32-разрядные числа из MO-файла меняются местами во время выполнения.Влияние на производительность незначительно.