Mi è capitato recentemente di dover realizzare un piccolo programmino in python che fosse internazionalizzato, ossia che comunicasse nella lingua dell’utente. Nel mio caso in italiano e in inglese.
Python viene distribuito già con un modulo pensato per risolvere questo problema e che è presente nel mondo della programmazione C e C++ dai primi anni ’90: gettext
.
GetText è presente nel mondo GNU da molto tempo e rappresenta una suite di programmi e API vastissime, che permettono la gestione ottimale delle traduzioni dei vari programmi. In questo breve articolo vedremo come utilizzare in modo minimale questo pacchetto.
Pyhton gettext module
Come detto, non serve installare nulla di aggiuntivo perchè python viene già fornito del modulo gettext
nella standard library e fornisce addirittura delle utility per processare i file.
Senza andare troppo nello specifico, gettext
funziona così:
- Inclusione e utilizzo delle API nel codice sorgente
- Estrazione dei testi da tradurre con
pygettext
in formato POT - Traduzione manuale nei file PO
- Compilazione in linguaggio macchina dei PO in MO
- Collocamento ordinato in una struttura del filesystem
Oltre a questo, ci sono vari strumenti per gestire ogni fase e, in particolar modo, fondere (merge) traduzioni precedenti con quelle nuove dovute allo sviluppo di nuovi componenti nei sorgenti. In questo articolo ci concentreremo solo sui cinque punti elencati.
Python API gettext
Per prima cosa, nei moduli che ci interessa tradurre, è necessario importare il modulo gettext
e inizializzarlo.
import gettext
try:
lang_default = gettext.translation('domain', 'locales')
lang_default.install()
_ = lang_default.gettext
except:
_ = gettext.gettext
print(_('This is a translatable string.'))
Utilizzare l’underscore come funzione gettext
è una prassi consolidata e permette di essere molto snelli nell’uso nel codice. Se si prova ad eseguire il codice si vedrà semplicemente la stringa stampata a video.
Estrarre il POT
La seconda fase consiste nell’estrarre un file di testo denominato POT (Portable Object Template) che conterrà lo schema generato in automatico di tutte le frasi da tradurre. La struttura interna è intuitiva:
: main.py:14 msgid "This is a translatable string." msgstr ""
In pratica si usa la stringa presente nel sorgente come identificativo e un’altra stringa che andrà a sostituirla. Quindi è possibile cambiare le frasi di default, solitamente in inglese, con altre frasi migliorate sempre in inglese, senza ricompilare il codice. Ma come si crea il file POT? Nelle librerie preinstallate di python si trova il programma pygettext
e su linux è un programma direttamente eseguibile
pygettext3.6 -d domain -o domain.pot main.py
Il programma è ovviamente pensato per elaborare codice python. Con le opzioni indicate si va a creare il file di output domain.pot per il dominio domain.
Tradurre il PO
I file PO (Portable Object) sono banalmente una copia del file POT in cui si riempiono i campi msgstr
con la traduzione di una lingua. Nel mio caso ho creato due file, uno per l’inglese e uno per l’italiano. La nomenclatura del file rimane la stessa, domain.po, sarà la sua collocazione a indicarne la lingua di riferimento. Lo vedremo tra qualche passaggio.
Il file PO, per piccoli script, può benissimo essere editato a mano, con un editor di testo qualsiasi. Il file può venire creato con l’utility msginit
per valorizzare in modo dettagliato anche le meta informazioni, ma il risultato è comunque un file PO di testo semplice. Esistono anche programmi appositi che leggono e modificano i file PO, pensati per i traduttori non programmatori e che aiutano nel lavoro, come poEdit.
Compilazione in file MO
Una volta completato il lavoro di traduzione, i file devono essere compilati per venire installati nel programma. Per farlo si usa il programma msgfmt
msgfmt -o domain.mo domain.po
In questo modo si creano i file MO (Machine Object) che saranno effettivamente usati dal modulo gettext
. Il nome del file è uguale per ogni lingua così da combaciare con la string ‘domain‘ presente il codice python. Ora creiamo la struttura dove piazzare questi file.
Struttura directory
Nel codice python di esempio uno dei parametri di traduzione è ‘locales‘. Esso identifica la cartella nella directory attuale nel quale cercare le traduzioni. Rimando alla documentazione ufficiale per impostare le directory di sistema o altro.
L’alberatura che andremo a creare è la seguente
locales ├── en │ └── LC_MESSAGES └── it └── LC_MESSAGES
I codici ‘en‘ e ‘it‘ vengono direttamente dall’ISO 639-1 ed è comunemente usata in informatica per indicare i vari linguaggi.
All’interno delle directory LC_MESSAGES andremo a collocare i file MO relativi alla lingua descritta dalla cartella parent. Da questo momento il programma può cambiare lingua. Per provarlo basta eseguire
LANGUAGE=it ; python3.6 main.py
Se tutto è stato fatto come si deve, vi apparirà il programma in italiano!