2012-04-10 9 views
18

Con gettext è possibile utilizzare la directory locale predefinita dell'intero sistema oppure specificarne una utilizzando bindtextdomain. Questo è utile quando si esegue un programma direttamente dal sorgente quando i file di traduzione .mo compilati non sono disponibili nella posizione predefinita del sistema.Come associare un dominio di testo a una cartella locale per gettext in GTK3

In Python si dovrebbe fare questo:

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

dove /path/to/mo/folder contiene il familiare fr/LC_MESSAGES/nautilus-image-manipulator.mo struttura. Chiamate come questo:

print _("Delete this profile") 

restituire la stringa correttamente tradotto dai file .mo locali, vi ringrazio molto.

In GTK + 2/pygtk, esisteva gtk.glade.bindtextdomain, ma mi chiedo se non vi è alcun equivalente in GTK + 3/PyGObject.

Per darvi un esempio specifico, questo è il modo Nautilus Image Manipulator;s UI è stato creato dal suo file Glade:

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

parti dell'interfaccia utente che non sono costruita dal file di Glade (cioè impostato dal codice) mostrare correttamente tradotto, ma le stringhe del file Glade vengono comunque visualizzate in inglese.

Mi sembra che mi manca una chiamata a qualche tipo di builder.bind_text_domain('nautilus-image-manipulator', '/path/to/mo/folder') prima della chiamata a builder.set_translation_domain ... Qualche idea su come eseguire questo?

+0

Hai provato solo il solito 'gettext.bindtextdomain()'? – ptomato

risposta

12

In PyGtk è possibile utilizzare anche Gtk.Builder. Conseguentemente alla documentazione PyGTK Gtk.Builder:

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

Il dominio definizione utilizzata quando si traduce valori di proprietà che sono stati contrassegnati come traducibili in descrizioni delle interfacce. Se il dominio di traduzione è Nessuno, GtkBuilder utilizza gettext(), altrimenti dgettext(). Valore predefinito: Nessuno

Cioè, Gtk.Builder utilizza dgettext() da "Libreria C". Il problema è che il modulo gettext di Python, funzione bindtextdomain(), per qualche motivo a me sconosciuto, non imposta la "libreria C". L'opzione è utilizzare il modulo locale che espone anche quell'interfaccia. Dalla documentazione Python modulo locale:

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

Il modulo locale espone l'interfaccia Gettext della libreria C su sistemi che forniscono questa interfaccia. Consiste delle funzioni gettext(), dgettext(), dcgettext(), textdomain(), bindtextdomain() e bind_textdomain_codeset(). Sono simili alle stesse funzioni nel modulo gettext , ma utilizzano il formato binario della libreria C per i cataloghi del messaggio e gli algoritmi di ricerca della libreria C per individuare i cataloghi del messaggio .

Le applicazioni Python non dovrebbero in genere dover richiamare queste funzioni e utilizzare invece gettext. Una nota eccezione a questa regola sono applicazioni che collegano con le librerie addizionali C che internamente invocano gettext() o dcgettext(). Per queste applicazioni, è può essere necessario associare il dominio di testo, in modo che le librerie possono individuare correttamente i loro cataloghi dei messaggi.

Quale, è il caso corrente. Quello che un hack: S

Questo lo farà, archiviare 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 file di 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> 

Ricordarsi di creare il mo mo/LANG/LC_MESSAGES/myapp.mo basato su .po estratto con:

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

Che assomiglia:

enter image description here

Cordiali saluti

+0

Grazie, funziona bene. Ma mi chiedo quale sia la linea "locale.setlocale (locale.LC_ALL, '')" in realtà - la mia applicazione è tradotta anche quando la rimuovo ... Quella chiamata è effettivamente necessaria? – oliver

+0

ho aggiunto come suggerito qui: http://docs.python.org/2/library/locale.html#locale.setlocale "Questo imposta la localizzazione per tutte le categorie di impostazioni predefinite per l'utente (in genere specificato nel LANG variabile d'ambiente)." Questo potrebbe essere nei casi in cui si dispone di notte per qualche motivo LC_ * variabili diverse da LC_ALL suppongo, o, nel caso non ci sono variabili di locale, ma io non sono davvero sicuro. – Havok

+0

so che è vecchio, ma io sto affrontando ora ... Questo metodo sembra funzionare solo su Linux, dal momento che Windows non ha libreria C con gettext – Zvika

0

La soluzione per attivare traduzioni gettext in Gtk/Python sotto Windows è elib_intl.py E 'facile trovare il file con Google . Ciò consente la traduzione del testo nel codice e nel testo nell'interfaccia utente di Glade.

Ecco il codice utilizzato per il seguente ambiente:

Windows 7 Python 2.7 Gtk 3+ caricato da: pygi-AIO-3.10.2-win32_rev18-setup.exe

Dovrebbe funzionare in tutte le finestre e anche per Python 3. elib_intl.py può essere utilizzato con 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") 

Se si sta utilizzando Gtk 3, probabilmente visualizzato un errore: per la linea 447:

libintl = cdll.intl 

Questo errore indica: modulo non trovato. La ragione è che in GTK3, il nome della DLL è stato modificato. Non è più intl.dll. Nell'installazione Pygi descritta il nome è: libintl-8. È necessario sostituire la linea che provoques l'errore:

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

Si può trovare un esempio completo che lavora qui: pdfBooklet 2.4.0 (Attenzione: non ancora in linea quando scrivo)

grazie a Dieter Verfaillie che ha elib_intl scritto

0

Bene dopo la generosità non riuscendo così miseramente per attirare un mac os x risposta, ho dovuto fare la mia ricerca.Ecco il frammento di che uso:

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

Più tardi, quando si ha la Gtk.Builder, impostare il dominio:

builder.set_translation_domain('domain') 

questo funziona solo se di gettext biblioteca libintl è nel percorso della libreria, non riesca altrimenti con grazia. Affinché le transizioni funzionino, è necessario installare gettext come dipendenza.

Problemi correlati