我确实使用 GNU gettext 及其基于类的 API,因此将
_()
安装在 Python builtins
命名空间中。我想在全局范围内暂时禁用翻译。
我试图通过用局部函数定义对其进行着色来以某种方式“屏蔽”
_()
。但我得到了这些错误:
No problem.
Traceback (most recent call last):
File "/home/user/ownCloud/_transfer/./z.py", line 27, in <module>
.format(foobar(True), foobar(False)))
File "/home/user/ownCloud/_transfer/./z.py", line 19, in foobar
return _('Hello')
UnboundLocalError: local variable '_' referenced before assignment
这是MWE
#!/usr/bin/env python3
import gettext
translation = gettext.translation(
domain='iso_639',
languages=['de'],
localedir='/usr/share/locale'
)
translation.install() # installs _() in "buildins" namespace
# Keep in mind: The object "translation" is not avialble in the original
# productive code because it is instanciated elsewhere.
def foobar(translate):
if not translate:
# I try to mask the global _() builtins-function
def _(txt):
return txt
return _('Hello')
if __name__ == '__main__':
# To ilustrate that _() is part of "builtins" namespace
print(_('No problem.'))
print('The translated string "{}" is originally "{}".'
.format(foobar(True), foobar(False)))
在我原来的高效代码中,我尝试以两种方式显示一个大的多行字符串:未翻译和已翻译。但我不想在这样的代码中重复该字符串。
original = 'Hello'
translated = _('Hello')
据我所知,GNU gettext 实用程序确实需要第二行来确定哪些字符串是可翻译的,并且应该放入
po
/pot
文件中。因此,我不能这样做,因为 gettext utils 不知道 original
是什么。
original = 'Hello'
translated = _(original)
也许我尝试的方式不对。或者,我可以这样表述我的问题:如何以原始源(未翻译)形式显示一个字符串,并逐个站点地翻译该字符串,而不在 python 源代码中复制该字符串?
这应该有效:
def N_(msgid):
return msgid
original = N_(msgid)
translated = _(msgid)
您只需配置消息提取器即可提取函数的参数
N_
。
如果您使用 GNU gettext 附带的
xgettext
提取消息,则必须使用 --keyword=N_
明确添加该关键字(这有点烦人,因为它是大多数语言的默认关键字,但不是 Python)。如果您使用 PyBabel,它是默认关键字,请参阅https://babel.pocoo.org/en/latest/cmdline.html#extract。
如果代码没有意义,这里有一个更深入的解释:所有 gettext 翻译函数(
gettext()
,ngettext()
,pgettext()
,_()
,...)都有双重目的:运行时,它们提供相关消息的翻译。在“消息提取时”,它们将字符串标记为可翻译。函数 N_()
通常只是标记字符串,但实际上并不在运行时检索翻译。
但是为什么提取器不会被
_(msgid)
触发呢?因为提取器只提取字符串文字,但从不提取变量。在运行时,_()
/gettext()
和朋友的参数是(静态)消息目录的查找键,它显然必须是常量。
注意:我不是 Python 专家,因此不知道您是否必须自己定义无操作函数
N_()
还是默认情况下可用。你自己就会发现的。