Подтвердить что ты не робот

Как связать текстовый домен с локальной папкой для gettext под 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')

где /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 пользовательский интерфейс создается из файла 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 (т.е. из кода), отображаются правильно переведенными, но строки из файла Glade все еще отображаются на английском языке.

Мне кажется, что я пропускаю вызов какого-то builder.bind_text_domain('nautilus-image-manipulator', '/path/to/mo/folder') перед вызовом builder.set_translation_domain... Любая идея, как это сделать?

4b9b3361

Ответ 1

В PyGtk вы также можете использовать Gtk.Builder. В соответствии с документацией PyGtk Gtk.Builder:

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

Область перевода, используемая при переводе значений свойств, которые имеют помечены как переводимые в описаниях интерфейсов. Если домен перевода - None, GtkBuilder использует gettext(), иначе dgettext(). Значение по умолчанию: None

То есть, Gtk.Builder использует dgettext() из библиотеки "C". Проблема в том, что Python gettext module, функция bindtextdomain(), по какой-то неизвестной мне причине, не устанавливает "библиотеку C". Опция заключается в использовании модуля locale, который также предоставляет этот интерфейс. Из документации модуля языка Python:

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

Модуль locale предоставляет интерфейс gettext C библиотеки для систем которые обеспечивают этот интерфейс. Он состоит из функций 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
import gettext
import locale

APP = 'myapp'
WHERE_AM_I = abspath(dirname(__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()

Файл My 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 в mo/LANG/LC_MESSAGES/myapp.mo на основе .po, извлеченного с помощью

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

Как выглядит:

enter image description here

С уважением

Ответ 2

Решение активировать gettext-переводы в Gtk/python под Windows - elib_intl.py Файл с Google легко найти. Это позволяет преобразовать текст в код и текст в пользовательский интерфейс поляризации.

Вот код, используемый для следующей среды:

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 (Предупреждение: еще не в строке, когда я пишу)

благодаря диете Verfaillie, который написал elib_intl

Ответ 3

Ну, после того, как щедрость, так неудачно, чтобы привлечь ответ 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 как зависимость.