当请求翻译 gettext 中的字符串时,我正在寻找一种即时设置语言的方法。我会解释原因:
我有一个多线程机器人,它在多台服务器上通过文本回复用户,因此需要用不同的语言回复。 documentation gettext 声明,要在运行时更改语言环境,您应该执行以下操作:
import gettext # first, import gettext
lang1 = gettext.translation('myapplication', languages=['en']) # Load every translations
lang2 = gettext.translation('myapplication', languages=['fr'])
lang3 = gettext.translation('myapplication', languages=['de'])
# start by using language1
lang1.install()
# ... time goes by, user selects language 2
lang2.install()
# ... more time goes by, user selects language 3
lang3.install()
但是,这不适用于我的情况,因为机器人是多线程的:
假设以下 2 个片段同时运行:
import time
import gettext
lang1 = gettext.translation('myapplication', languages=['fr'])
lang1.install()
message(_("Loading a dummy task")) # This should be in french, and it will
time.sleep(10)
message(_("Finished loading")) # This should be in french too, but it wont :'(
和
import time
import gettext
lang = gettext.translation('myapplication', languages=['en'])
time.sleep(3) # Not requested on the same time
lang.install()
message(_("Loading a dummy task")) # This should be in english, and it will
time.sleep(10)
message(_("Finished loading")) # This should be in english too, and it will
您可以看到消息有时会翻译成错误的语言环境。
但是,如果我可以做类似 _("string", lang="FR")
的事情,问题就会消失!
我是不是漏掉了什么,或者我使用了错误的模块来完成任务... 我正在使用 python3
最佳答案
虽然上述解决方案似乎有效,但它们不能很好地与别名为 gettext() 的常规 _()
函数一起使用.但我想保留该功能,因为它用于从源中提取翻译字符串(参见 docs 或例如 this blog)。
因为我的模块运行在多进程多线程环境下,using the application’s built-in namespace或 a module’s global namespace不会工作,因为如果多个线程安装不同的翻译,_()
将是一个共享资源并受制于竞争条件。
因此,首先我编写了一个返回翻译闭包的简短辅助函数:
import gettext
def get_translator(lang: str = "en"):
trans = gettext.translation("foo", localedir="/path/to/locale", languages=(lang,))
return trans.gettext
然后,在使用翻译字符串的函数中,我将该翻译闭包分配给 _
,从而使其成为我的本地范围内所需的函数 _()
在不污染全局共享 namespace 的情况下运行:
def some_function(...):
_ = get_translator() # Pass whatever language is needed.
log.info(_("A translated log message!"))
(将 get_translator()
函数包装到 memoizing cache 中以避免多次创建相同闭包的额外加分项。)
关于 python gettext : specify locale in _(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37998300/