Come tradurre un’applicazione Pylons

Applicazioni web in PythonUno degli ultimi passaggi nello sviluppo di un’applicazione web è la traduzione e localizzazione in altre lingue, anche se per motivi tecnici sarebbe meglio progettare l’applicazione fin da subito per essere facilmente traducibile, anziché modificarla a progetto terminato.

Vediamo come rendere traducibile un’applicazione pylons.

Il modulo i18n

Il framework pylons mette a disposizione il modulo i18n per aiutarci nella traduzione dell’applicazione (i18n è un’abbreviazione che si può interpretare come “internationalization“, con la cifra 18 che rappresenta le 18 lettere omesse).

In questo modulo sono presenti diverse funzioni utili, ma quella che useremo nel 99% dei casi è ugettext(), o la sua forma abbreviata _().

Questo metodo “marca” una stringa come testo da tradurre e restituisce una stringa unicode (gettext() è la sua controparte non-unicode).

Il primo passo è importare le funzioni del modulo:

[code gutter=”false” language=”python”]
from pylons.i18n.translation import *
[/code]

e l’uso è altrettanto semplice:

[code gutter=”false” language=”python”]
def index(self):
return _(“Traduci questo!”)
[/code]

Ovviamente da qualche parte sul nostro sito ci sarà la possibilità di scegliere la lingua e nel codice dovremo usare la funzione set_lang() per impostarla come attiva.
La funzione accetta una stringa rappresentante la lingua principale da usare o una lista di stringhe. In tal caso la prima della lista sarà quella principale e le altre saranno utilizzate come riserve se non viene trovata una traduzione valida.

[code gutter=”false” language=”python”]
set_lang([“it”, “en”])
[/code]

Ovviamente esiste anche get_lang() per recuperare la lingua selezionata.

Errori da evitare

Un errore in cui potreste incappare se non avete esperienza di traduzioni è inserire valori variabili all’interno della stringa da tradurre, ad esempio:

[code gutter=”false” language=”python”]
# Sbagliato
_(“Sono stati trovati “+len(results)+” risultati”)

# Sbagliato
_(“Sono stati trovati %d risultati” % len(results))

# Corretto
_(“Sono stati trovati %d risultati”) % len(results)
[/code]

O anche di tradurre stringhe parziali e poi concatenarle:

[code gutter=”false” language=”python”]
# Sbagliato
message = _(“Benvenuto sul nuovo”)
message += _(“sito di Artera”)

# Corretto
message = _(“Benvenuto sul nuovo”
“sito di Artera”)
[/code]

Altre funzioni utili

Un’utile variante di ugettext è ungettext che serve a fornire la doppia traduzione per il singolare e il plurale in base a un valore passato come parametro.

[code gutter=”false” language=”python”]
def index(self):
return ungettext(“E’ stato trovato %n risultato”, “Sono stati trovati %n risultati”, len(results)) % len(results)
[/code]

Estrarre le stringhe da tradurre

Abbiamo visto come “marcare” le stringhe all’interno dell’applicazione ma per fornire le traduzioni effettive nelle varie lingue che desideriamo supportare, dobbiamo come prima cosa estrarle in un formato comodo, così da non doverci rigirare tutti i sorgenti.

Lo strumento che ci serve è babel, installiamolo con pip:

[code gutter=”false” language=”bash”]
pip install babel
[/code]

Babel provvederà a estrarre per noi le stringhe, in una cartella i18n che va creata manualmente:

[code gutter=”false” language=”bash”]
$ mkdir myapp/i18n
[/code]

il comando da eseguire per l’estrazione è:

[code gutter=”false” language=”bash”]
$ python setup.py extract_messages
[…]
writing PO template file to myapp/i18n/myapp.pot
[/code]

Il file .pot è quello che ci serviva e da questo dobbiamo generare un .po per ogni lingua:

[code gutter=”false” language=”bash”]
$ python setup.py init_catalog -l en
running init_catalog
creating catalog ‘myapp/i18n/en/LC_MESSAGES/myapp.po’
based on ‘myapp/i18n/myapp.pot’
[/code]

Il file .po conterrà 3 righe per ogni stringa da tradurre:

  • Un commento recante il file sorgente e la riga presso la quale è stata trovata la stringa.
  • Il msgid, ovvero la stringa originale
  • La msgstr da modificare inserendo la stringa tradotta

Modificati i file .po li compiliamo in .mo col comando:

[code gutter=”false” language=”bash”]
$ python setup.py compile_catalog
running compile_catalog
1 of 1 messages (100%) translated in ‘myapp/i18n/en/LC_MESSAGES/myapp.po’
compiling catalog ‘myapp/i18n/en/LC_MESSAGES/myapp.po’ to ‘myapp/i18n/en/LC_MESSAGES/myapp.mo’
[/code]

e l’applicazione è tradotta!

Ricordiamoci solo di aggiungere la cartella i18n al controllo di versione se ne usiamo uno.

Condividi