当我使用gettext用于模块级和类级变量时,我遇到了一些麻烦。
首先,在导入时我使用我的默认语言环境并安装它。之后,当我通过解析设置启动项目并使用gettext.translation.install
设置正确的语言环境时,我得到特定的语言环境。一切都运行良好,但在我的代码中,所有模块级和类级变量都保持使用默认语言环境进行转换,而不是正确。
例如,我有这样的项目:
├── 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的字符串对象或继承对象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_
我不确定这是一个很好的解决方案,但它确实有效。