Internazionalizzare dei prodotti Plone
Note: Return to tutorial view.
Prodotto di partenza: MailmanSubForm
Il codice di MailmanSubForm è relativamente semplice, infatti contiene un unico archetype ed una sola vista e quindi si presta bene come esempio a cui far riferimento in una guida per l'internazionalizzazione di un prodotto Plone.
Ed ora qualche informazione: MailmanSubForm è un prodotto per Plone che fornisce dei comodi form per l'iscrizione o la cancellazione da una lista MailMan.
MailMan a sua volta e' un gestore di mailing list, scritto in Python e completo di interfaccia Web.
La mailing list è una lista di indirizzi e-mail dedicata ad un argomento di interesse comune a tutti gli aderenti. Il meccanismo è semplice: si invia una e-mail ad un indirizzo che automaticamente ne rinvia una copia a tutti gli interessati.
Nato nel 1996, all'Università della Virginia, come progetto personale di John Viega, è stato in seguito acquisito dal team di Python.org, ma ha raggiunto l'interesse del grande pubblico solo successivamente al suo ingresso nel progetto GNU di Richard Stallman.
Oggi MailMan è un gestore di liste maturo e completo, ricco di funzioni, come gli autorisponditori e il gateway per interfacciarsi con i news server.
Nato come alternativa a Majordomo, è più potente e più facile da utilizzare, soprattutto per gli utenti non esperti. L'installazione è semplice e funziona praticamente subito.
MailMan concede a ciascuna mailing list una propria pagina Web,permettendo agli utenti di inserire, modificare o cancellare le proprie opzioni direttamente dal Web, senza utilizzare complesse sintassi. Anche l'amministratore della lista puo' gestire la sua mailing list via web.
E' possibile inoltre personalizzare la lista con l'inserimento di template di testo o HTML, realizzando un'integrazione con la grafica e con lo stile del sito.
Premesse sull'internazionalizzazione
Innanzitutto, prima di iniziare, consiglio caldamente la lettura della seguente guida.
Per chi ha fretta di andare subito al sodo, posso fare delle anticipazioni: tutti (o quasi) i prodotti per Plone hanno nel codice al loro interno una cartella i18n. All'interno di tale cartella sono contenute le traduzioni per le varie lingue, in file separati. Per esempio:
- MailmanSubForm-it.po
- MailmanSubForm-en.po
- ecc...
Ognuno di questi file, codificati in maniera particolare, contiene un'intestazione in cui vengono specificate diverse informazioni oltre che una serie di codici a cui associare una traduzione. Gli elementi delle pagine che dovranno essere tradotti (per esempio titolo, label, ecc..) dovranno far riferimento a questi codici (in gergo msgid).
L'intestazione è forse la parte più importante, poiché in essa vengono specificate informazioni fondamentali come il dominio e la lingua (da modificare a seconda dei casi). Ecco un esempio di intestazione di un file po:
# Gettext Message File for PlacelessTranslationService. msgid "" msgstr "" "Project-Id-Version: MailmanSubForm\n" "POT-Creation-Date: 2003-10-04 12:51+0300\n" "Last-Translator: davide.moro@redomino.com\n" "Language-Team: <>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "Language-code: it\n" "Language-name: Italiano\n" "Preferred-encodings: ascii latin1 utf-8\n" "Domain: MailmanSubForm\n
Esempio di associazione di una traduzione ad un codice identificativo (estratta dal file po di traduzione di MailmanSubForm in lingua italiana):
#. Added on Tue Jun 5 15:39:46 2007 #. #: file:MailmanSubForm/skins/MailmanSubForm/mmSubForm_view.cpt #. Line 131, Column 14 #. #. Orginal text: #. List Unsubscribe msgid "list_unsubscribe" msgstr "Cancellazione dalla lista"
Nel caso qualcuno voglia tradurre un qualsiasi prodotto predisposto per l'internazionalizzazione in un altra lingua (per esempio tedesco), non deve far altro che copiare il file po, modificare l'intestazione specificando il codice della lingua corretta e sostituire i vari msgstr.
Come predisporre un prodotto per essere internazionalizzato
Gli sviluppatori con pochi accorgimenti possono rendere i proprio prodotti pronti per essere tradotti in decine di lingue.
Internazionalizzazione script e viste
Nel caso si scrivessero da zero delle viste page template non bisogna far altro che marcare gli elementi da tradurre con degli msgid.
Ecco un estratto di codice:
<legend i18n:domain="MailmanSubForm" i18n:translate="list_unsubscribe">List Unsubscribe</legend>
Oppure, direttamente da codice Python:
testo_tradotto = context.translate(msgid='list_unsubscribe', default='List Unsubscribe', domain='MailmanSubForm')
Naturalmente questi sono solo dei casi semplici, nella guida segnalata all'inizio di questa pagina sono indicati altri casi d'uso più complessi.
Internazionalizzazione dei content type in Plone
La sezione precedente riguardava l'internazionalizzazione di una page template specifica di un prodotto, ancora da scrivere. Tuttavia, quando si crea un nuovo tipo di contenuto in Plone, vengono costruite automaticamente delle viste in modalità edit o view. Progettando i vari campi con qualche accorgimento particolare, si può rendere la vista del nostro oggetto automaticamente predisposta per il multilingua. In poche parole l'unico lavoro da fare è quello di creare una cartella i18n con dentro i file delle varie traduzioni. Facile, no?!
Le informazioni che dovremo aver cura di aggiungere sono:
- label_msgid
- description_msgid
- i18n_domain
Ecco un esempio:
StringField('mmListName',
searchable=0,
required=1,
widget=StringWidget(
label='List Name',
label_msgid='MailmanSubForm_label_mmListName',
description="""
The name of your Mailman list.
""",
description_msgid='MailmanSubForm_help_mmListName',
i18n_domain='MailmanSubForm',
),
), Nota bene:
utilizzando il prodotto ArchGenXML tutti i nuovi content type creati sono automaticamente predisposti per il multilingua!!
ArchGenXML è un generatore di codice automatico per applicazioni Plone/CMF basati sul framework Archetype. La generazione del codice avviene a partire da un file creato utilizzando un editor uml. Ciò significa che è possibile generare l'intero codice del prodotto, pronto per essere installato, progettandone prima graficamente la struttura (anche molto complessa).
Ecco una guida che illustra le potenzialità di questo prodotto: guida.
Iniziamo i lavori...
In questa parte della guida vedremo come sistemare il file MailmanSubForm.py. Per prima cosa, tutti i campi definiti in esso per la configurazione sono sprovvisti di label, description_msgid e di dominio, come mostrato qui sotto:
StringField('mmListName',
searchable=0,
required=1,
widget=StringWidget(
label='List Name',
description="""
The name of your Mailman list.
""",
),
), Quindi non resta altro che aggiungere le informazioni per predisporre il prodotto al multilingua. Ecco il risultato:
StringField('mmListName',
searchable=0,
required=1,
widget=StringWidget(
label='List Name',
label_msgid='MailmanSubForm_label_mmListName',
description="""
The name of your Mailman list.
""",
description_msgid='MailmanSubForm_help_mmListName',
i18n_domain='MailmanSubForm',
),
), Come convenzione nello scegliere i msgid, si può adottare la seguente:
- label: DOMINIO _label_ NOMEFIELD
- description: DOMINIO _help_ NOMEFIELD
In questo modo si renderà più facile ai traduttori lo svolgimento del proprio compito.
Questo lavoro va fatto per ogni campo definito nell'oggetto Archetype che si vuole predisporre per il multilingua.
Nel caso non esista già una cartella i18n, come nel nostro esempio, bisogna provvedere a crearla nella radice della cartella in cui è definito il codice del prodotto.
Una buona parte del lavoro è fatta: basta copiare un file po esistente da un altro prodotto, modificarne l'intestazione e aggiungere a mano le varie associazioni tra msgid e traduzioni per la lingua scelta.
Nelle prossime sezioni vedremo come sarà possibile evitare tutto questo automatizzando la procedura.
Internazionalizzazione viste
Nel prodotto MailmanSubForm è presente una sola vista, senza nessun supporto all'internazionalizzazione (tranne che per gli elementi standard di Plone).
Per prima cosa è necessario modificare l'i18n:domain per l'intera vista e settarlo dal valore originale (Plone) a MailmanSubForm, il nome che abbiamo scelto.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" metal:use-macro="here/main_template/macros/master" i18n:domain="MailmanSubForm">
Inoltre nella nostra vista esiste un i18n:translate che fa riferimento al dominio Plone, quindi specifichiamo implicitamente il dominio corretto per questo elemento in modo tale da continuare ad avere per esso le traduzioni funzionanti.
Quindi, dal codice originale:
<p tal:condition="python: not text and is_editable" i18n:translate="no_body_text" class="discreet"> This item does not have any introductory text, click the edit tab to change it. </p>
passiamo al seguente:
<p tal:condition="python: not text and is_editable" i18n:domain="plone" i18n:translate="no_body_text" class="discreet"> This item does not have any introductory text, click the edit tab to change it. </p>
Per tutti gli elementi significativi della vista di MailmanSubForm, inoltre, sarà necessario effettuare la marcatura assegnando dei codici msgid che abbiano possibilmente dei valori con una certa semantica (per aiutare i traduttori nel lavoro). Questo lavoro è opportuno che venga svolto per:
- messaggi;
- label;
- titoli;
- attributi di elementi (per esempio l'attributo title di un tag a);
- ecc...
Ecco un esempio:
<legend i18n:translate="legend_list_subscribe">List Subscribe</legend>
Oppure per internazionalizzare un attributo:
<input class="context" tabindex="" type="submit" name="form.button.subscribe" value="Subscribe" i18n:attributes="value subscribe_action" tal:attributes="tabindex tabindex/next;" />
Una volta finito, non resta altro che costruire i file po in modo tale da associare i msgid a delle traduzioni.
Come costruire i file po
Esistono diverse tecniche per costruire i file po al fine di internazionalizzare un prodotto esistente:
- farlo a mano;
- utilizzare i18ndude;
- utilizzare PlacelessTranslationService (strada scelta per MailmanSubForm).
La prima strada è quella da escludere subito a priori, a meno che non si debbano fare delle piccole modifiche a file po esistenti. Vediamo cosa comporta invece adottare le altre due opzioni...
NB: è uscita una guida più recente che parla di i18ndude: link. Questo articolo potrebbe contenere informazioni non aggiornate!
i18ndude
i18ndude è un prodotto per Plone che permette di estrarre informazioni sull'internazionalizzazione di page template esistenti, costruendo automaticamente file po. Inoltre consente di trovare elementi senza traduzioni, fare il merging e sincronizzare file po.
E' un approccio molto valido, come mostrato nella seguente guida.
Problemi
In passato, con le prime versioni di i18ndude, si erano verificati alcuni problemi:
- errori nel parsing delle page template di un prodotto;
- estrazione delle informazioni unicamente per le sole page template, ma non per i msgid specificati nello schema dei propri ArcheType.
Ora, invece, i18ndude è in grado di estrarre correttamente le informazioni da tradurre da:
- page template;
- ZCML file;
- moduli Python.
In definitiva, l'uso di i18ndude è consigliato.
PlacelessTranslationService
Utilizzare il PlacelessTranslationService di Plone comporta l'applicazione di un semplice trucchetto consistente in pochi passi:
- creare nella cartella i18n del prodotto da tradurre un file po vuoto (contenente solo l'intestazione specificando la lingua), ad esempio: MailmanSubForm-it.po;
- copiare MailmanSubForm-it.po e creare un file uguale, ma con estensione .missing (esempio: MailmanSubForm-it.missing);
- riavviare Zope;
- visitare le pagine che si vogliono tradurre.
In questo modo il servizio di traduzioni di Plone andrà a riempire il file con estensione .missing con tutte le entry i18n di cui non ha trovato una traduzione, permettendo così il facile recupero dei msgid delle label e delle description definite nei field Archetype degli oggetti che sfuggivano ad i18ndude.
Problemi
Questa tecnica funziona molto bene, nonostante l'approccio estremamente semplice ed anche un po'... grezzo.
Esiste tuttavia un problema: nel file .missing vengono inserite solo le entry i18n effettivamente renderizzate. Ciò significa che se alcune sezioni appaiono solo in certe determinate condizioni (magari a causa di un tal:condition), possono non essere registrate nel file .missing se la condizione non è specificata.
Conclusioni
Sicuramente l'approccio combinato delle tecniche i18ndude e PlacelessTranslationService costituisce la via migliore e più veloce sia per tradurre un prodotto che per costruire e gestire nel tempo i file po per l'internazionalizzazione.
Infatti, utilizzando entrambe le tecniche si è relativamente sicuri di non aver omesso delle entry da tradurre nei file po, e soprattutto è possibile internazionalizzare interi prodotti senza supporto i18n, con un piccolo dispendio di tempo.
Aggiornamento
All'epoca della scrittura di questa guida i18ndude dava qualche problema. Ora invece riesce molto bene ad estrapolare tutte le informazioni da moduli Python, file ZCML e page template. Inoltre mette a disposizione delle comode funzionalità per gestire i merging tra i file po.
Allo stato attuale delle cose, si ritiene che la strada migliore da seguire sia sicuramente quella che prevede l'utilizzo di i18ndude!