如何在GTK3下将文本域绑定到gettext的本地文件夹

Emi*_*ien 20 python translation gettext pygobject gtk3

随着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')
Run Code Online (Sandbox Code Playgroud)

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

print _("Delete this profile")
Run Code Online (Sandbox Code Playgroud)

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

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

为了给你一个具体的例子,这是Nautilus Image Manipulator的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
Run Code Online (Sandbox Code Playgroud)

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

在我看来,在打电话builder.bind_text_domain('nautilus-image-manipulator', '/path/to/mo/folder')之前我错过了某种呼叫builder.set_translation_domain......任何想法如何执行此操作?

Hav*_*vok 13

在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

语言环境模块在提供此接口的系统上公开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()
Run Code Online (Sandbox Code Playgroud)

我的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>
Run Code Online (Sandbox Code Playgroud)

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

xgettext --keyword=translatable --sort-output -o en.po test.glade
Run Code Online (Sandbox Code Playgroud)

它看起来像什么:

在此输入图像描述

亲切的问候