有没有一种可移植的方法来提供在 PyPI 上分发的包的本地化?
Is there a portable way to provide localization of a package distributed on PyPI?
上下文:
这是对我的 的跟进。
我想提供包的本地化版本。按照 Python 文档,我用 pygettext 提取了一个 .pot 文件,在 .po 文件中准备了一个翻译,将其编译为一个 .mo 文件。
一切都很好,我的包裹显示翻译后的消息。
但我的最终目标是让它在 PyPI 上可用。所以我做了一些研究,发现:
setuptools documentation: 对本地化只字未提...
-
它解释了格式取决于生成文件的平台的字节顺序。我的理解是只有po文件是可移植的...
What is the correct way to include localisation in python packages?
答案完全相关并且谈到了 setuptools/babel 集成但是:
- 该集成只允许构建 mo 文件并且不涉及它们的分发
- 作者描述了他们如何使用它,没有参考跨系统的可移植性
一种有趣的方式,即使它需要目标平台上的 babel 模块。没那么重,但比我自己的包重很多……事实上,发行版只包含 po 文件,它们是在安装时用 babel 编译的。
问题:
有没有办法构建包含已编译 mo 文件的特定平台轮子?
如果不是,我将不得不在目标上要求 babel 并尝试在安装时通过 mo 编译找到我的方式。
编辑 2018 年 7 月 12 日:
经过一些工作,我可以根据此答案中的以下内容构建特定的包。它可以从其他项目中使用,通过 setuptools enty_points 的魔力在构建时自动编译 po 文件。现在可以在 GitHUB (https://github.com/s-ball/mo_installer) and distributed on PyPI (https://pypi.org/project/mo_installer)
我在问这个问题之前所做的研究给了我足够的提示来找到可能的解决方案。
我现在可以说,可以在转盘中包含特定于平台的 mo 文件 - 不幸的是,在我当前的解决方案中,转盘没有表明它是特定于平台的。但同样的解决方案允许构建一个在目标平台上构建 mo 文件的源分发。
现在了解详情:
在目标上编译mo文件需要的工具:
大多数从 Google 或 SO 中选择的解决方案依赖于 Babel 或 GNU gettext msgfmt
程序。但是 cPython 工具包括一个纯粹的 Python 模块 msgfmt.py
在这里就足够了。不幸的是,这个工具在许多 Linux/Unix-like 中通常没有默认安装。我的解决方案仅包含 3.7.1 版本的该模块的副本(仅 7k 文件)。它看起来像一个非常稳定的代码(近年来几乎没有变化)并且它应该适用于任何 Python >= 3.3
setuptools 集成
setuptools 的神奇之处在于,相同的构建子命令在内部用于构建二进制轮,使用源包中的 pip 安装或直接使用副本中的 python setup.py install
安装(git 克隆)的完整源代码包。所以我在 setup.py
中提供了一个 build
子类,它在调用超类方法之前生成带有完整路径的 .mo 文件。我还使用 MANIFEST.in
文件列出应在源代码分发中复制的文件,并使用 package_data
设置参数列出二进制包或安装文件夹中应包含的内容
运行 时间使用
如果 mo 层次结构要安装在 knows 包下,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},
)
在MANIFEST.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
获得
最后但同样重要的是,在更深入地阅读 GNU gettext doc 之后,我可以说 gettext 可以处理 mo 文件,无论它们的字节顺序如何:
MO files of any endianness can be used on any platform. When a MO file has an endianness other than the platform’s one, the 32-bit numbers from the MO file are swapped at runtime. The performance impact is negligible.
上下文:
这是对我的
我想提供包的本地化版本。按照 Python 文档,我用 pygettext 提取了一个 .pot 文件,在 .po 文件中准备了一个翻译,将其编译为一个 .mo 文件。
一切都很好,我的包裹显示翻译后的消息。
但我的最终目标是让它在 PyPI 上可用。所以我做了一些研究,发现:
setuptools documentation: 对本地化只字未提...
-
它解释了格式取决于生成文件的平台的字节顺序。我的理解是只有po文件是可移植的...
What is the correct way to include localisation in python packages?
答案完全相关并且谈到了 setuptools/babel 集成但是:
- 该集成只允许构建 mo 文件并且不涉及它们的分发
- 作者描述了他们如何使用它,没有参考跨系统的可移植性
一种有趣的方式,即使它需要目标平台上的 babel 模块。没那么重,但比我自己的包重很多……事实上,发行版只包含 po 文件,它们是在安装时用 babel 编译的。
问题:
有没有办法构建包含已编译 mo 文件的特定平台轮子?
如果不是,我将不得不在目标上要求 babel 并尝试在安装时通过 mo 编译找到我的方式。
编辑 2018 年 7 月 12 日:
经过一些工作,我可以根据此答案中的以下内容构建特定的包。它可以从其他项目中使用,通过 setuptools enty_points 的魔力在构建时自动编译 po 文件。现在可以在 GitHUB (https://github.com/s-ball/mo_installer) and distributed on PyPI (https://pypi.org/project/mo_installer)
我在问这个问题之前所做的研究给了我足够的提示来找到可能的解决方案。
我现在可以说,可以在转盘中包含特定于平台的 mo 文件 - 不幸的是,在我当前的解决方案中,转盘没有表明它是特定于平台的。但同样的解决方案允许构建一个在目标平台上构建 mo 文件的源分发。
现在了解详情:
在目标上编译mo文件需要的工具:
大多数从 Google 或 SO 中选择的解决方案依赖于 Babel 或 GNU gettext
msgfmt
程序。但是 cPython 工具包括一个纯粹的 Python 模块msgfmt.py
在这里就足够了。不幸的是,这个工具在许多 Linux/Unix-like 中通常没有默认安装。我的解决方案仅包含 3.7.1 版本的该模块的副本(仅 7k 文件)。它看起来像一个非常稳定的代码(近年来几乎没有变化)并且它应该适用于任何 Python >= 3.3setuptools 集成
setuptools 的神奇之处在于,相同的构建子命令在内部用于构建二进制轮,使用源包中的 pip 安装或直接使用副本中的
python setup.py install
安装(git 克隆)的完整源代码包。所以我在setup.py
中提供了一个build
子类,它在调用超类方法之前生成带有完整路径的 .mo 文件。我还使用MANIFEST.in
文件列出应在源代码分发中复制的文件,并使用package_data
设置参数列出二进制包或安装文件夹中应包含的内容运行 时间使用
如果 mo 层次结构要安装在 knows 包下,
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},
)
在MANIFEST.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
获得最后但同样重要的是,在更深入地阅读 GNU gettext doc 之后,我可以说 gettext 可以处理 mo 文件,无论它们的字节顺序如何:
MO files of any endianness can be used on any platform. When a MO file has an endianness other than the platform’s one, the 32-bit numbers from the MO file are swapped at runtime. The performance impact is negligible.