2012-04-10 4 views
18

Mit können Sie entweder das systemweite Standardgebietsschemaverzeichnis verwenden oder eines davon mithilfe von bindtextdomain angeben. Dies ist nützlich, wenn ein Programm direkt von der Quelle ausgeführt wird, wenn die kompilierten .mo-Übersetzungsdateien nicht im Standardspeicherort des Systems verfügbar sind.So binden Sie eine Textdomäne unter GTK3 für gettext an

In Python Sie würden dies tun:

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

wo /path/to/mo/folder die bekannte fr/LC_MESSAGES/nautilus-image-manipulator.mo Struktur enthält. Anrufe wie folgt aus:

print _("Delete this profile") 

Rückkehr der richtig übersetzt Zeichenfolge von den lokalen .mo Dateien, ich danke Ihnen sehr.

In GTK + 2/pygtk gab es gtk.glade.bindtextdomain, aber ich frage mich, ob es gleichwertige in GTK + 3/PyGObject gibt.

Ihnen ein konkretes Beispiel zu geben, ist dies, wie Nautilus Image Manipulator;s UI aus seiner Glade Datei erstellt:

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

Teile der Benutzeroberfläche, die von der Glade-Datei nicht erstellt werden (dh von Code festgelegt) angezeigt richtig übersetzt, aber die Strings aus der Glade-Datei erscheinen immer noch auf Englisch.

Es scheint mir, dass ich einen Anruf zu einer Art von builder.bind_text_domain('nautilus-image-manipulator', '/path/to/mo/folder') vor dem Anruf zu builder.set_translation_domain verpasst ... Irgendeine Idee, wie man das durchführt?

+0

Haben Sie nur die übliche 'gettext.bindtextdomain()' ausprobiert? – ptomato

Antwort

12

In PyGtk können Sie auch Gtk.Builder verwenden. Entsprechend zu der PyGtk Gtk.Builder Dokumentation:

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

Die verwendete Übersetzung Domain, wenn Eigenschaftswerte übersetzen, die haben als übersetzbar Beschreibungen in Schnittstelle markiert. Wenn die Übersetzungsdomäne None ist, verwendet GtkBuilder gettext(), andernfalls dgettext(). Standardwert: Keine

Das heißt, Gtk.Builder verwendet dgettext() aus "C-Bibliothek". Das Problem ist, dass Pythons Gettext-Modul, Funktion bindtextdomain() aus irgendeinem mir unbekannten Grund die "C-Bibliothek" nicht setzt. Die Option besteht darin, das Gebietsschema Modul zu verwenden, das diese Schnittstelle ebenfalls verfügbar macht. Aus der Python locale Modul Dokumentation:

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

Der locale-Modul macht die C-Bibliothek der gettext-Schnittstelle auf Systeme , die diese Schnittstelle zur Verfügung stellen. Es besteht aus den Funktionen gettext(), dgettext(), dcgettext(), textdomain(), bindtextdomain() und bind_textdomain_codeset(). Diese ähneln den gleichen Funktionen in dem Gettext-Modul, aber verwenden das Binärformat der C-Bibliothek für Nachrichtenkataloge und die Suchalgorithmen der C-Bibliothek zum Lokalisieren von Nachrichtenkatalogen .

Python-Anwendungen sollten normalerweise keine Notwendigkeit finden, diese Funktionen aufzurufen, und sollten stattdessen Gettext verwenden. Eine bekannte Ausnahme zu dieser Regel sind Anwendungen, die mit zusätzlichen C-Bibliotheken verknüpfen, die intern gettext() oder dcgettext() aufrufen. Für diese Anwendungen kann es notwendig sein, die Textdomäne zu binden, damit die Bibliotheken ihre Nachrichtenkataloge richtig lokalisieren können.

Welche, ist der aktuelle Fall. Was für ein Hack: S

Dies wird es tun, test.py Datei:

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() 

Meine Glade Datei 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> 

Erinnern Sie sich das mo in erstellen mo/LANG/LC_MESSAGES/myapp.mo basierend auf .po extrahiert mit:

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

Wie es aussieht:

enter image description here

Art

Bezug
+0

Danke, das funktioniert gut. Aber ich frage mich, was die Zeile "locale.setlocale (locale.LC_ALL, '')" tatsächlich tut - meine Anwendung wird übersetzt, auch wenn ich sie entferne ... Ist dieser Aufruf tatsächlich notwendig? – oliver

+0

Ich habe es wie hier vorgeschlagen hinzugefügt: http://docs.python.org/2/library/locale.html#locale.setlocale "Dies legt das Gebietsschema für alle Kategorien auf die Benutzereinstellung (in der Regel in der LANG angegeben Umgebungsvariable)." Dies könnte in Fällen, in denen Sie aus irgendeinem Grund Nacht haben LC_ * Variablen anders als LC_ALL Ich nehme an, oder in dem Fall gibt es keine Gebietsschema Variablen, aber ich bin mir nicht wirklich sicher. – Havok

+0

Ich weiß, es ist alt, aber ich bin es jetzt konfrontiert ... Diese Methode scheint nur auf Linux zu funktionieren, da Windows keine C-Bibliothek mit gettext – Zvika

0

Die Lösung gettext Übersetzungen in Gtk/Python unter Windows zu aktivieren ist elib_intl.py Es ist einfach, die Datei mit Google zu finden . Dies ermöglicht die Übersetzung von Text im Code und Text in einer Benutzeroberfläche.

Hier ist der Code für die folgende Umgebung verwendet:

Windows 7 Python 2.7 Gtk 3+ geladen von: pYGI-AIO-3.10.2-win32_rev18-setup.exe

Es sollte funktionieren in jedem Fenster und auch für Python 3. elib_intl.py kann mit pyGtk (Gtk 2) verwendet werden.

from gi.repository import Gtk, Gdk 
import cairo 

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

Wenn Sie Gtk 3 verwenden, werden Sie wahrscheinlich eine Fehlermeldung: für Zeile 447:

libintl = cdll.intl 

Dieser Fehler zeigt: Modul nicht gefunden. Der Grund ist, dass in Gtk3 der Name der DLL geändert wurde. Es ist nicht mehr intl.dll. In der beschriebenen Pygi-Installation lautet der Name: libintl-8. Sie müssen die Zeile ersetzen, die den Fehler provoques von:

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

Sie können hier ein komplettes Arbeitsbeispiel finden: pdfBooklet 2.4.0 (Achtung: Nur noch nicht in Linie, wenn ich schreibe)

dank dieter Verfaillie wer geschrieben elib_intl

0

Gut nachdem die Bounty so miserabel versagte, um eine Mac OS X Antwort anzuziehen, musste ich meine eigenen Nachforschungen anstellen.Hier ist das Snippet ich benutze:

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('') 

Später, wenn Sie die Gtk.Builder haben, setzen Sie die Domain:

builder.set_translation_domain('domain') 

Dies funktioniert nur, wenn gettext Bibliothek libintl im Bibliothekspfad ist, sonst fehlschlagen anmutig. Damit Transaltions funktionieren, müssen Sie gettext als Abhängigkeit installieren.

Verwandte Themen