Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python gettext:在()中指定区域设置_Python_Multithreading_Python 3.x_Internationalization_Gettext - Fatal编程技术网

python gettext:在()中指定区域设置

python gettext:在()中指定区域设置,python,multithreading,python-3.x,internationalization,gettext,Python,Multithreading,Python 3.x,Internationalization,Gettext,我正在寻找一种方法,在请求对gettext中的字符串进行翻译时,可以动态地设置语言。我会解释原因: 我有一个多线程bot,它在多个服务器上通过文本响应用户,因此需要用不同的语言进行响应。 gettext的说明是,要在运行时更改区域设置,应执行以下操作: import gettext # first, import gettext lang1 = gettext.translation('myapplication', languages=['en']) # Load every transla

我正在寻找一种方法,在请求对gettext中的字符串进行翻译时,可以动态地设置语言。我会解释原因:

我有一个多线程bot,它在多个服务器上通过文本响应用户,因此需要用不同的语言进行响应。 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()
但是,这不适用于我的情况,因为bot是多线程的:

假设以下两个代码段同时运行:

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 :'(

您可以看到消息有时被翻译成错误的语言环境。 但是,如果我能做一些类似于
(string),lang=“FR”)
的事情,问题就会消失

我是否错过了什么,或者我使用了错误的模块来完成任务。。。
我正在使用python3,下面的简单示例演示了如何为每个转换器使用单独的过程:

import gettext
import multiprocessing
import time

def translation_function(language):
    try:
        lang = gettext.translation('simple', localedir='locale', languages=[language])
        lang.install()
        while True:
            print(_("Running translator"), ": %s" % language)
            time.sleep(1.0)
    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    thread_list = list()
    try:
        for lang in ['en', 'fr', 'de']:
            t = multiprocessing.Process(target=translation_function, args=(lang,))
            t.daemon = True
            t.start()
            thread_list.append(t)
        while True:
            time.sleep(1.0)
    except KeyboardInterrupt:
        for t in thread_list:
            t.join()
输出如下所示:

Running translator : en Traducteur en cours d’exécution : fr Laufenden Übersetzer : de Running translator : en Traducteur en cours d’exécution : fr Laufenden Übersetzer : de 运行翻译:en 执行过程中的交易人:fr 劳芬登·贝尔塞策:德 运行翻译:en 执行过程中的交易人:fr 劳芬登·贝尔塞策:德
当我尝试使用线程时,我只得到了一个英文翻译。您可以在每个进程中创建单独的线程来处理连接。您可能不想为每个连接创建一个新进程。

我花了一点时间编写了一个脚本,该脚本使用了系统上所有可用的区域设置,并尝试在其中打印一条众所周知的消息。请注意,“所有区域设置”只包括编码更改,Python无论如何都会否定这些更改,而且很多翻译都是不完整的,所以请使用回退

显然,您还必须对
xgettext
(或等效项)的使用进行适当的更改,以使真正的代码能够识别翻译功能

#!/usr/bin/env python3

import gettext
import os

def all_languages():
    rv = []
    for lang in os.listdir(gettext._default_localedir):
        base = lang.split('_')[0].split('.')[0].split('@')[0]
        if 2 <= len(base) <= 3 and all(c.islower() for c in base):
            if base != 'all':
                rv.append(lang)
    rv.sort()
    rv.append('C.UTF-8')
    rv.append('C')
    return rv

class Domain:
    def __init__(self, domain):
        self._domain = domain
        self._translations = {}

    def _get_translation(self, lang):
        try:
            return self._translations[lang]
        except KeyError:
            # The fact that `fallback=True` is not the default is a serious design flaw.
            rv = self._translations[lang] = gettext.translation(self._domain, languages=[lang], fallback=True)
            return rv

    def get(self, lang, msg):
        return self._get_translation(lang).gettext(msg)

def print_messages(domain, msg):
    domain = Domain(domain)
    for lang in all_languages():
        print(lang, ':', domain.get(lang, msg))

def main():
    print_messages('libc', 'No such file or directory')

if __name__ == '__main__':
    main()
#/usr/bin/env蟒蛇3
导入gettext
导入操作系统
定义所有_语言():
rv=[]
对于os.listdir(gettext.\u default\u localedir)中的lang:
base=lang.split(''.')[0]。split('.')[0]。split('@')[0]

如果2以下示例直接使用
翻译
,如中所示,以允许使用线程:

import gettext
import threading
import time

def translation_function(quit_flag, language):
    lang = gettext.translation('simple', localedir='locale', languages=[language])
    while not quit_flag.is_set():
        print(lang.gettext("Running translator"), ": %s" % language)
        time.sleep(1.0)

if __name__ == '__main__':
    thread_list = list()
    quit_flag = threading.Event()
    try:
        for lang in ['en', 'fr', 'de']:
            t = threading.Thread(target=translation_function, args=(quit_flag, lang,))
            t.daemon = True
            t.start()
            thread_list.append(t)
        while True:
            time.sleep(1.0)
    except KeyboardInterrupt:
        quit_flag.set()
        for t in thread_list:
            t.join()
输出:

Running translator : en Traducteur en cours d’exécution : fr Laufenden Übersetzer : de Running translator : en Traducteur en cours d’exécution : fr Laufenden Übersetzer : de 运行翻译:en 执行过程中的交易人:fr 劳芬登·贝尔塞策:德 运行翻译:en 执行过程中的交易人:fr 劳芬登·贝尔塞策:德
如果我知道更多关于
gettext
,我会发布这个答案。我把我以前的答案留给那些真正想继续使用

的人。虽然上述解决方案似乎有效,但它们不能很好地使用传统的带有别名的
函数。但我想保留该函数,因为它用于从源代码中提取翻译字符串(请参阅或例如)

因为我的模块运行在多进程和多线程环境中,或者因为
\
将是一个共享资源而无法工作,并且如果多个线程安装不同的翻译,将受到竞争条件的约束

首先,我编写了一个简短的helper函数,它返回一个转换闭包:

然后,在使用翻译字符串的函数中,我将该翻译闭包分配给
\uu
,从而使其成为函数本地范围内所需的函数
),而不会污染全局共享命名空间:

def some_function(...):
    _ = get_translator()  # Pass whatever language is needed.

    log.info(_("A translated log message!"))

(将
get_translator()
函数包装到一个函数中以避免多次创建相同的闭包,需要额外的注意。)

也许我的问题措辞不好?我如何改进它?您没有提供足够的信息让某人轻松重现您的问题。我必须弄清楚如何使用
gettext
,并创建一个最小的翻译设置。理想情况下,您应该提供一个。只是不要使用
install
显然。。。直接对实例调用
gettext
。(不管怎么说,搞乱
内置的
都很讨厌)。谢谢!这是有用的。我使用了你的域类,它就像一个符咒。经过一些修改,我已经能够在函数中设置语言了!谢谢,这很有用:我现在更了解gettext模块了!请让我投票。我将继续使用@o11c解决方案,因为它可以更好地处理多线程!
import gettext

def get_translator(lang: str = "en"):
    trans = gettext.translation("foo", localedir="/path/to/locale", languages=(lang,))
    return trans.gettext
def some_function(...):
    _ = get_translator()  # Pass whatever language is needed.

    log.info(_("A translated log message!"))