Python、gettext:如何为模块级和 class 级变量获取正确的语言环境?

Python, gettext: How to get right locale for module- and class-level variables?

当我将 gettext 用于模块级和 class 级变量时,我遇到了一些麻烦。

首先,在导入时我使用我的默认语言环境并安装它。 之后,当我通过解析设置并使用 gettext.translation.install 来设置正确的语言环境来启动我的项目时,我会获得特定的语言环境。一切正常,但在我的代码中,所有模块级和 class 级变量都使用默认语言环境进行翻译,不正确。

例如我有这样的项目:

├── foo.py
├── i18t
│   └── __init__.py
├── __init__.py
└── run.py

i18t/__init__.py 包含:

import gettext
from os import path

SUPPORTED_LANGUAGES = ('en', 'fr')
DEFAULT_LANGUAGE = SUPPORTED_LANGUAGES[0]

locale_path = path.abspath(path.join(path.dirname(__file__), 'locale'))

TRANSLATIONS = {
    lang: gettext.translation(
        'domain',
        locale_path,
        languages=[lang]
    ) for lang in SUPPORTED_LANGUAGES
}


def install_language(language):
    lang = TRANSLATIONS.get(language)
    if lang is None:
        lang = TRANSLATIONS[DEFAULT_LANGUAGE]
    lang.install()

__init__.py:

from i18n import DEFAULT_LANGUAGE, install_language

install_language(DEFAULT_LANGUAGE)

foo.py:

foo = _('Bar')

run.py:

from i18t import install_language
import foo


def main():
    ...
    read config and get right locale
    ...
    install_language(right_locale)
    bar = _('Bazz')
    print(foo.foo)
    print(bar)

我执行 run.py 并使用默认语言环境翻译 foo.foo 并使用正确的语言环境翻译 bar。 我知道 foo.foo 运行 _(gettext) 在我导入模块时只有一次,但我需要获得正确的翻译字符串。 哪种方法更好?

这种情况的问题是希望对在导入时仅评估一次的字符串使用 运行 时间函数 gettext。我认为最好不要这样做。

但我通过使用像 speaklater package or inherit object UserSting 中的类似字符串的对象解决了这个问题,并制作了您自己的 gettext 函数:

from collections import UserString


class RuntimeTranslatedString(UserString):

    def __init__(self, message):
        self._data = message

    @property
    def data(self):
        return _(self._data)


def N_(message):
    return RuntimeTranslatedString(message)

在您的代码中,您可以像 _(gettext):

这样使用它
from .i18n import N_

foo = N_('Bar')

不要忘记将它添加到您的 extract_message 命令中。在我的 setup.cfg 中它看起来像:

[extract_messages]
output_file = my-package/i18n/locale/translation.pot
keywords = _ N_

我不确定这是不是好的解决方案,但它确实有效。