python - GTK3下如何将文本域绑定(bind)到本地文件夹以获取gettext

标签 python translation gettext gtk3 pygobject

使用 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.set_translation_domain...知道如何执行此操作吗?

最佳答案

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

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

The translation domain used when translating property values that have been marked as translatable in interface descriptions. If the translation domain is None, GtkBuilder uses gettext(), otherwise dgettext(). Default value: None

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

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

The locale module exposes the C library’s gettext interface on systems that provide this interface. It consists of the functions gettext(), dgettext(), dcgettext(), textdomain(), bindtextdomain(), and bind_textdomain_codeset(). These are similar to the same functions in the gettext module, but use the C library’s binary format for message catalogs, and the C library’s search algorithms for locating message catalogs.

Python applications should normally find no need to invoke these functions, and should use gettext instead. A known exception to this rule are applications that link with additional C libraries which internally invoke gettext() or dcgettext(). For these applications, it may be necessary to bind the text domain, so that the libraries can properly locate their message catalogs.

这是当前的情况。真是个黑客: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

它的样子:

enter image description here

亲切的问候

关于python - GTK3下如何将文本域绑定(bind)到本地文件夹以获取gettext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10094335/

相关文章:

php - 模块翻译不是翻译

python - 用翻译交换主要代码语言

java - ActionListener 如何将处理结果发送回 JTextArea

django - 在 Django 字段的定义中使用 `ugettext`

python - Pandas Series.ne 运算符针对同一系列的两个切片返回意外结果

python - 如何获取包含与索引对应的特定值的列列表作为 Pandas 数据框中的新列?

python - 使用 pyodbc 从 SQL Server 中提取的数据行是 "unhashable type"

Django 翻译 block 未翻译

Django 翻译模板标签字符串参数

python - 如何从文件在 Python 中创建字典,其中值是一个列表