[国际化Python项目,使用PyGTK3和Glade

问题描述 投票:1回答:1

我正在开发Python程序,使用PyGTK3和Glade作为UI。我想国际化UI,而不是根据系统中的语言环境,而是通过程序中“已安装”的语言进行国际化,并且我希望能够“即时”更改UI语言,例如,通过选择一个菜单中的语言。我在Windows 10上,运行Python 3.4。

我做了很多研究,尝试了很多事情,并取得了一些进展。我能够为Windows程序包安装一个gettext程序(链接?),但是显然它很小。 xgettext确实从我的Python源代码中提取了_(“ strings”)。但是,如果我尝试使用xgettext -L Glade(每https://askubuntu.com/questions/218432/how-extract-strings-from-a-ui-file-glade-with-gettext),则无法说该版本是在没有外籍人员的情况下构建的。而且,似乎还无法使用intltool的各种样式。没问题。根据本页上描述的intltool-extract(http://www.learningpython.com/2006/12/03/translating-your-pythonpygtk-application)的输出,我知道我可以手动从.glade文件中提取可翻译字符串,并将其放入C .h格式的文件中:

char *s = N_("_File");

然后,我可以在我的xgettext命令中添加.h文件和-kN_,以从Python源代码和.glade UI文件中获取带有字符串的.pot文件。我还可以编写一个Python脚本,该脚本从.glade源文件中提取各种字符串,并将它们与空字符串成对添加到.pot文件中。据我了解,这些只是将适当的字符串放入.pot文件中的技术,因此可以对其进行翻译,但看来我也可以手动创建.pot文件…

一旦有了包含要翻译的字符串的.pot文件,那么我就可以使用msginit命令创建.po文件:

msginit --input=test.pot --locale=fr_FR     (this creates a file fr.po)

然后,我手动翻译(或让某人翻译)每个.po文本文件中的所有字符串,完成后,我创建.mo文件并将其放入适当的目录结构中(所有都是以下子目录的子目录) \ po):

msgfmt --output-file=fr_FR\LC_MESSAGES\test.mo fr.po

到目前为止一切顺利。

在我的Python代码中,为了启用翻译,我提出了以下最少的代码:

import gettext
APP_NAME = "test"
locale_path = os.path.realpath('.\po')
langs = ['fr_FR', 'en_US']
lang = gettext.translation(APP_NAME, locale_path, languages=langs, fallback = True)
_ = lang.gettext
builder = Gtk.Builder()
builder.set_translation_domain(APP_NAME)
builder.add_from_file("test.glade")
builder.connect_signals(Handler())

这对于翻译Python代码中的字符串非常有用,但是没有Glade接口被翻译。这是我的基本问题。

使用Glade XML手动设置文本我找到了以下页面:翻译python gtk构建器文件(http://martens.me/programming/translating-python-gtk-builder-files.html),它解释了如何创建Gtk.Builder的派生类,该类将扫描.glade文件的XML并手动调用set _ {}(在我的上下文中,每个参数的_(child.text)都应为set_label,set_text或set_title),以便进行翻译。我对他的代码做了一些更改,因为在扫描XML之前没有将对象加载到Builder中,所以我在解析树之前先加载了.glade文件,如下所示:

class GtkBuilder(Gtk.Builder):

    def __init__(self, glade_file, APP_NAME):
        super().__init__()
        self.set_translation_domain(APP_NAME)
        self.add_from_file(glade_file)

        tree = ET.parse(glade_file)
        root = tree.getroot()
        self.recursive_xml_translate(root)

然后翻译发生得更远(使用_(child.text)触发翻译):

    # translate property value
    if child.tag == 'property' and parent_id and child.attrib.get('name'):
        name = child.attrib.get('name')
        obj = self.get_object(parent_id)
        func = getattr(obj, 'set_{}'.format(name), func_not_found)
        func(_(child.text))

在我的代码中,我使用而不是上面显示的4条构建器行:

builder = GtkBuilder("PrimerPrep.glade", APP_NAME)
builder.connect_signals(Handler())

这似乎可行,但似乎是一种令人费解的方法,可以到达我想去的地方。

其他尝试翻译Glade界面的方法我还读过问题所在,即Glade接口是使用C代码呈现的,因此_()的覆盖不会转换Glade字符串。所以我尝试了这段代码的变体:

try:
    import ctypes
    libintl = ctypes.cdll.LoadLibrary('libintl-8.dll')
    libintl.bindtextdomain(APP_NAME, locale_path)
    libintl.bind_textdomain_codeset(APP_NAME, 'UTF-8')
except:
    print('Error loading translations into Glade file.')

我也尝试过设置环境变量:

os.environ['LANG'] = 'fr_FR'

我使用了不同的语言环境选项,包括此处描述的内容:How to bind a text domain to a local folder for gettext under GTK3),但是由于我的语言环境模块没有bindtextdomain对象,因此没有任何成果。而且我不想实际设置计算机区域设置。例如。我的计算机上没有法语语言环境,但是我希望能够将程序UI更改为法语。如果我尝试将语言环境设置为未安装的语言环境,则会出现错误。

这些选项似乎都无法转换Glade界面。

gettext应该可以做得更好?从23.1.3.3的gettext文档(https://docs.python.org/3.5/library/gettext.html)看来,这应该不难:

lang1 = gettext.translation('myapplication', languages=['en'])
lang2 = gettext.translation('myapplication', languages=['fr'])
# start by using language1
lang1.install()
# ... time goes by, user selects language 2
lang2.install()

我已经尝试过将这些事情进行各种组合,但是它们似乎都不影响Glade接口(可能是上面提到的C语言问题)。

获取UI进行更新因此,上述复杂的解决方案在某种程度上是唯一可行的。但是即使那样,我也只能在程序启动时设置语言环境才能生效。程序运行时更改UI语言的过程是什么?手动将_()例程更改为新的翻译语言后,我尝试再次运行builder.recursive_xml_translate()例程,但这似乎并未更新接口。我找不到类似Gtk.Builder.refresh()方法的东西。关于如何更新UI语言的任何建议?

结论因此,我发现了一种复杂的翻译Glade界面的方法,因此,我似乎可以做出足够的努力(如果我能找到一种动态更新它的方法)。但是必须有一个更简单的方法!请告诉我,我只是想念一些小事情,这些事情会使我的生活更加轻松...

python-3.x gtk3 glade
1个回答
0
投票

我发现将林间空地文件加载到字符串中并使用以下命令替换该字符串中的翻译很有用:

© www.soinside.com 2019 - 2024. All rights reserved.