23

gettext您可以使用默认的系统范围的语言环境目录,也可以使用bindtextdomain. 当编译的 .mo 翻译文件在系统的默认位置不可用时,这在直接从源代码运行程序时很有用。

在 Python 中,你会这样做:

import gettext
from gettext import gettext as _
gettext.bindtextdomain('nautilus-image-manipulator', '/path/to/mo/folder')
gettext.textdomain('nautilus-image-manipulator')

其中/path/to/mo/folder包含熟悉的fr/LC_MESSAGES/nautilus-image-manipulator.mo结构。像这样调用:

print _("Delete this profile")

从本地 .mo 文件中返回正确翻译的字符串,非常感谢。

在 GTK+2/pygtk 中,存在gtk.glade.bindtextdomain,但我想知道在 GTK+3/PyGObject 中是否有任何等价物。

举一个具体的例子,这是Nautilus Image Manipulator;s UI是如何从它的 Glade 文件创建的:

from gi.repository import Gtk
builder = Gtk.Builder()
builder.set_translation_domain('nautilus-image-manipulator')
builder.add_from_file(ui_filename)
return builder

不是从 Glade 文件构建的部分 UI(即从代码设置)显示正确翻译,但 Glade 文件中的字符串仍以英文显示。

在我看来,我在调用builder.bind_text_domain('nautilus-image-manipulator', '/path/to/mo/folder')之前错过了对某种类型的调用builder.set_translation_domain...知道如何执行此操作吗?

4

3 回答 3

15

在 PyGtk 中,您也可以使用 Gtk.Builder。根据 PyGtk Gtk.Builder 文档:

http://developer.gnome.org/pygtk/stable/class-gtkbuilder.html#properties-gtkbuilder

翻译在接口描述中标记为可翻译的属性值时使用的翻译域。如果翻译域为 None,GtkBuilder 使用 gettext(),否则使用 dgettext()。默认值:无

也就是说,Gtk.Builder 使用“C 库”中的 dgettext()。问题是 Python 的 gettext 模块函数bindtextdomain()出于某种我不知道的原因,没有设置“C 库”。选项是使用也公开该接口的语言环境模块。从 Python 语言环境模块文档:

http://docs.python.org/library/locale#access-to-message-catalogs

locale 模块在提供此接口的系统上公开 C 库的 gettext 接口。它由函数 gettext()、dgettext()、dcgettext()、textdomain()、bindtextdomain() 和 bind_textdomain_codeset() 组成。这些与 gettext 模块中的相同函数类似,但使用 C 库的二进制格式用于消息目录,并使用 C 库的搜索算法来定位消息目录。

Python 应用程序通常不需要调用这些函数,而是应该使用 gettext。此规则的一个已知例外是与其他 C 库链接的应用程序,这些库在内部调用 gettext() 或 dcgettext()。对于这些应用程序,可能需要绑定文本域,以便库可以正确定位其消息目录。

这是当前的情况。什么黑客:S

这将做到这一点,文件test.py

from gi.repository import Gtk
from os.path import abspath, dirname, join, realpath
import gettext
import locale

APP = 'myapp'
WHERE_AM_I = abspath(dirname(realpath(__file__)))
LOCALE_DIR = join(WHERE_AM_I, 'mo')

locale.setlocale(locale.LC_ALL, '')
locale.bindtextdomain(APP, LOCALE_DIR)
gettext.bindtextdomain(APP, LOCALE_DIR)
gettext.textdomain(APP)
_ = gettext.gettext

print('Using locale directory: {}'.format(LOCALE_DIR))

class MyApp(object):

    def __init__(self):
        # Build GUI
        self.builder = Gtk.Builder()
        self.glade_file = join(WHERE_AM_I, 'test.glade')
        self.builder.set_translation_domain(APP)
        self.builder.add_from_file(self.glade_file)

        print(_('File'))
        print(_('Edit'))
        print(_('Find'))
        print(_('View'))
        print(_('Document'))

        # Get objects
        go = self.builder.get_object
        self.window = go('window')

        # Connect signals
        self.builder.connect_signals(self)

        # Everything is ready
        self.window.show()

    def main_quit(self, widget):
        Gtk.main_quit()

if __name__ == '__main__':
    gui = MyApp()
    Gtk.main()

我的 Glade 文件test.glade

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <object class="GtkWindow" id="window">
    <property name="can_focus">False</property>
    <property name="window_position">center-always</property>
    <property name="default_width">400</property>
    <signal name="destroy" handler="main_quit" swapped="no"/>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkLabel" id="label1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">File</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label2">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">Edit</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label3">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">Find</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label4">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">View</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">3</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label5">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">Document</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">4</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

记得在mo/LANG/LC_MESSAGES/myapp.mo中创建基于 .po 提取的 mo:

xgettext --keyword=translatable --sort-output -o en.po test.glade

它看起来像什么:

在此处输入图像描述

亲切的问候

于 2012-05-10T19:17:18.117 回答
1

Windows下在Gtk/python中激活gettext翻译的解决方案是elib_intl.py,用google很容易找到这个文件。这允许翻译代码中的文本和 glade UI 中的文本。

以下是用于以下环境的代码:

Windows 7 Python 2.7 Gtk 3+ 由 pygi-aio-3.10.2-win32_rev18-setup.exe 加载

它应该适用于任何窗口,也适用于 Python 3。 elib_intl.py 可以与 pyGtk (Gtk 2) 一起使用。

from gi.repository import Gtk, Gdk
import cairo

import locale       #for multilanguage support
import gettext
import elib_intl
elib_intl.install("pdfbooklet", "share/locale")

如果你使用 Gtk 3,你可能会收到一个错误:对于第 447 行:

libintl = cdll.intl

此错误表示:找不到模块。原因是在 Gtk3 中,dll 的名称已更改。它不再是 intl.dll。在所描述的 Pygi 安装中,名称是:libintl-8。您必须将引发错误的行替换为:

libintl = cdll.LoadLibrary("libintl-8.dll")

你可以在这里找到一个完整的工作示例: pdfBooklet 2.4.0 (警告:我写的时候还没有排队)

感谢编写 elib_intl 的节食者 Verfaillie

于 2015-08-23T18:59:29.077 回答
1

好吧,在赏金如此悲惨地未能吸引 mac os x 答案之后,我不得不自己做研究。这是我使用的片段:

import locale, ctypes, sys, os
import gettext

# setup textdomain and install _() for strings from python
gettext.install('domain', '/path/to/locale/dir')

try:
    if hasattr(locale, 'bindtextdomain'):
        libintl = locale
    elif os.name == 'nt':
        libintl = ctypes.cdll.LoadLibrary('libintl-8.dll')
    elif sys.platform == 'darwin':
        libintl = ctypes.cdll.LoadLibrary('libintl.dylib')

    # setup the textdomain in gettext so Gtk3 can find it
    libintl.bindtextdomain('domain', '/path/to/locale/dir')

except (OSError, AttributeError):
    # disable translations altogether for consistency
    gettext.install('')

稍后,当您拥有 Gtk.Builder 时,设置域:

builder.set_translation_domain('domain')

这仅在 gettext 的库libintl位于库路径中时才有效,否则会正常失败。为了使翻译工作,您需要安装 gettext 作为依赖项。

于 2017-03-03T11:01:40.617 回答