代码之家  ›  专栏  ›  技术社区  ›  Serge Ballesta

是否有一种可移植的方法来提供PyPI上分发的包的本地化?

  •  2
  • Serge Ballesta  · 技术社区  · 7 年前

    背景:

    another question 我的。

    我想提供包的本地化版本。在Python文档之后,我用pygettext提取了一个.pot文件,在一个.po文件中准备了一个翻译,在一个.mo文件中编译了它。

    在那之前一切都很好,我的包显示了翻译的信息。

    但我的最终目标是让它在PyPI上可用。所以我做了一些研究,发现:

    问题:

    汇编

    1 回复  |  直到 5 年前
        1
  •  2
  •   Community Mohan Dere    5 年前

    经过一些工作,我可以根据下面的答案构建一个特定的包。通过setuptools enty_points的魔力,它可以从其他项目中用于在构建时自动编译po文件。它现在在GitHUB上可用( https://github.com/s-ball/mo_installer )并在PyPI上分发( https://pypi.org/project/mo_installer )


    我在提出这个问题之前所做的研究给了我足够的提示,让我找到了一个可能的解决方案。

    我现在可以说,可以在控制盘中包含特定于平台的mo文件-不幸的是,在我当前的解决方案中,控制盘没有显示它是特定于平台的。但同样的解决方案允许构建源发行版,在目标平台上构建mo文件。

    详情如下:

    1. 在目标上编译mo文件所需的工具:

      从谷歌那里挑选出来的大多数解决方案要么依赖于Babel,要么依赖于GNU gettext msgfmt msgfmt.py 这就够了。不幸的是,在许多类似Linux/Unix的系统中,默认情况下通常不会安装此工具。我的解决方案只包括3.7.1版本的模块副本(仅7k文件)。它看起来是一个非常稳定的代码(近年来几乎没有变化),应该适用于任何Python>=3.3

    2. setuptools集成

      setuptools的神奇之处在于,同一个build子命令在内部用于构建二进制控制盘、从源程序包使用pip安装或直接使用pip安装 python setup.py install build 子类 setup.py MANIFEST.in 文件,列出应在源发行版和 package_data

    3. 运行时使用

      如果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},
        )
    

    在里面 舱单

    ...
    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文件都可以在任何平台上使用。如果MO文件的尾数不是平台尾数,则运行时会交换MO文件中的32位数字。性能影响可以忽略不计。