Se qualcuno ha mai sviluppato un'applicazione internazionale, sicuramente sa quale incubo possa essere avere a che fare con ogni aspetto della traduzione dei testi, standard locali, contenuti localizzati. Fortunatamente, symfony automatizza in modo nativo tutti gli aspetti dell'internazionalizzazione.
Essendo una parola lunga, spesso gli sviluppatori fanno riferimento all'internazionalizzazione come i18n (contando le lettere della parola inglese). Analogamente, la localizzazione è abbreviata in l10n. Questi due argomenti coprono diversi aspetti delle applicazioni web multilingua.
Un'applicazione internazionalizzata contiene diverse versioni dello stesso contenuto, in varie lingue o formati. Ad esempio, un'interfaccia web per la posta elettronica può offrire lo stesso servizio in diverse lingue: solo l'interfaccia cambia.
Un'applicazione localizzata contiene informazioni distinte, in base al paese dal quale viene acceduta. Si pensi ai contenuti di un portale di notizie: se vi si accede dagli Stati Uniti, mostrerà le ultime informazioni dagli Stati Uniti, ma se vi si accede dalla Francia, le informazioni saranno relative alla Francia. Quindi, un'applicazione l10n non fornisce solo traduzione dei contenuti, ma anche i contenuti stessi possono essere diversi da una versione localizzata all'altra.
Tutto considerato, avere a che fare con i18n e l10n vuol dire che l'applicazione può occuparsi dei seguenti aspetti:
- Traduzione di testi (interfaccia, elementi, contenuti)
- Misure e formati (date, standard, numeri, ecc.)
- Contenuti localizzati (più versioni di un dato oggetto, secondo il paese)
Questo capitolo copre i modi in cui symfony tratta questi elementi e come lo si può usare per sviluppare applicazioni internazionalizzate e localizzate.
Cultura dell'utente
Tutte le caratteristiche i18n predefinite di symfony sono basate su un parametro nella sessione, chiamato cultura. La cultura è la combinazione del paese e della lingua dell'utente e determina il modo in cui testi e informazioni dipendenti dalla cultura sono visualizzati. Poiché è serializzata nella sessione, la cultura è persistente tra le pagine.
Impostare la cultura predefinita
Per impostazione predefinita, la cultura dei nuovi utenti è default_culture
. Si può
modificare questa impostazione nel file di configurazione settings.yml
, come mostrato
nel listato 13-1.
Listato 13-1 - Impostare la cultura predefinita, in frontend/config/settings.yml
all: .settings: default_culture: it_IT
note
Durante lo sviluppo, ci si potrebbe stupire perché la modifica della cultura in
settings.yml
non cambia la cultura nel browser. Questo perché la sessione ha già
una cultura impostata. Se si vuole che l'applicazione usi la nuova cultura, occorre
cancellare i cookie di dominio o riavviare il browser.
Mantenere sia la lingua che il paese è necessario, perché si potrebbero avere diverse
traduzioni italiane per utenti dell'Italia o della Svizzera e diversi contenuti
spagnoli per gli utenti dalla Spagna o dal Messico. La lingua è codificata in due
caratteri minuscoli, secondo lo standard ISO 639-1 (ad esempio, en
per inglese). Il
paese è codificato in due caratteri maiuscoli, secondo lo standard ISO 3166-1 (ad esempio,
GB
per la Gran Bretagna).
Cambiare la cultura di un utente
La cultura di un utente può essere cambiata durante la sessione, ad esempio quando un
utente decide di passare dalla versione inglese a quella italiana dell'applicazione,
oppure quando un utente entra nell'applicazione e usa la lingua impostata nelle sue
preferenze. È per questo che la classe sfUser
offre dei metodi getter e setter per la
cultura. Il listato 13-2 mostra come usare questi metodi in un'azione.
Listato 13-2 - Impostare e recuperare la cultura in un'azione
// Setter $this->getUser()->setCulture('en_US'); // Getter $culture = $this->getUser()->getCulture(); => en_US
Determinare automaticamente la cultura
In molte applicazioni, la cultura è definita nella prima richiesta, basandosi sulle
preferenze del browser. Gli utenti possono definire una lista di lingue accettate nel
loro browser e questi dati sono inviati al server a ogni richiesta, nell'header HTTP
Accept-Language
. Possono essere recuperati tramite l'oggetto sfWebRequest
. Ad esempio,
per ottenere la lista delle lingue preferite in un'azione, usare questo:
$languages = $request->getLanguages();
L'header HTTP è una stringa, ma symfony lo converte automaticamente in un array. Quindi,
la lingua preferita è accessibile nel precedente esempio in $languages[0]
.
Può essere utile impostare automaticamente la cultura dell'utente alla sua lingua
preferita nella pagina iniziale di un sito oppure in un filtro per tutte le pagine.
Ma poiché il sito probabilmente supporterà un numero limitato di lingue, è meglio usare
il metodo getPreferredCulture()
. Esso restituisce la lingua migliore, confrontando
le lingue preferite e quelle supportate:
$language = $request->getPreferredCulture(array('en', 'it')); // il sito è disponibile in inglese e in italiano
Se non c'è corrispondenza, il metodo restituisce la prima lingua supportata (en
,
nell'esempio precedente).
caution
L'header HTTP Accept-Language
non è un'informazione molto attendibile, perché raramente
gli utenti la modificano nel browser. La maggior parte delle volte, la lingua preferita
del browser è quella dell'interfaccia e i browser non sono disponibili in tutte le
lingue. Se si decide di impostare automaticamente la cultura in base alla lingua
preferita del browser, assicurarsi di fornire un modo all'utente di scegliere una lingua
alternativa.
Standard e formati
Le parti interne di un'applicazione web non si curano delle particolarità culturali. I database, ad esempio, usano standard internazionali per memorizzare date, cifre, ecc. Ma quando i dati sono inviati o recuperati da utenti, occorre eseguire una conversione. Gli utenti non capirebbero i timestamp e preferirebbero dichiarare la propria madrelingua come "italiano" piuttosto che "Italian". Quindi, occorre un'assistenza per eseguire automaticamente la conversione, basata sulla cultura dell'utente.
Mostrare i dati nella cultura dell'utente
Una volta definita la cultura, gli helper che dipendono da essa avranno automaticamente
l'output adeguato. Ad esempio, l'helper format_number()
mostra automaticamente un
numero nel formato familiare all'utente, secondo la sua cultura, come mostrato nel
Listato 13-3.
Listato 13-3 - Mostrare un numero per la cultura dell'utente
<?php use_helper('Number') ?> <?php $sf_user->setCulture('en_US') ?> <?php echo format_number(12000.10) ?> => '12,000.10' <?php $sf_user->setCulture('it_IT') ?> <?php echo format_number(12000.10) ?> => '12000,10'
Non occorre passare esplicitamente la cultura agli helper. Essi la cercano nell'oggetto sessione corrente. Il listato 13-4 elenca gli helper che tengono conto della cultura dell'utente nel loro output.
Listato 13-4 - Helper dipendenti dalla cultura
<?php use_helper('Date') ?> <?php echo format_date(time()) ?> => '9/14/10' <?php echo format_datetime(time()) ?> => 'September 14, 2010 6:11:07 PM CEST' <?php use_helper('Number') ?> <?php echo format_number(12000.10) ?> => '12,000.10' <?php echo format_currency(1350, 'USD') ?> => '$1,350.00' <?php use_helper('I18N') ?> <?php echo format_country('US') ?> => 'United States' <?php format_language('en') ?> => 'English' <?php use_helper('Form') ?> <?php echo input_date_tag('birth_date', mktime(0, 0, 0, 9, 14, 2010)) ?> => input type="text" name="birth_date" id="birth_date" value="9/14/10" size="11" /> <?php echo select_country_tag('country', 'US') ?> => <select name="country" id="country"><option value="AF">Afghanistan</option> ... <option value="GB">United Kingdom</option> <option value="US" selected="selected">United States</option> <option value="UM">United States Minor Outlying Islands</option> <option value="UY">Uruguay</option> ... </select>
Gli helper delle date possono accettare un parametro addizionale format
, per forzare
una visualizzazione indipendente dalla cultura, ma non andrebbe fatto in
un'applicazione internazionalizzata.
Ottenere dati da un input localizzato
Se occorre mostrare dati nella cultura dell'utente, oppure recuperare dei dati, si dovrebbe indurre, per quanto possibile, gli utenti a inserirli già in formato internazionalizzato. Questo approccio risparmierà dal tentare di capire in che modo convertire i dati nei vari formati. Ad esempio, chi potrebbe inserire un valore monetario con la virgola come separatore, in un input?
Si può forzare il formato di inserimento o nascondendo i veri dati (come in
select_country_tag()
) o separando i componenti di dati complessi in diversi
input semplici.
Per le date, tuttavia, spesso non è possibile. Gli utenti sono abituati a inserire le
date nel loro formato culturale e occorre convertire queste date in un formato interno
(e internazionale). Qui si applica la classe sfI18N
. Il listato 13-5 mostra come usare
questa classe.
Listato 13-5 - Ottenere una data da un formato localizzato in un'azione
$date= $request->getParameter('birth_date'); $user_culture = $this->getUser()->getCulture(); // Ottenere un timestamp $timestamp = $this->getContext()->getI18N()->getTimestampForCulture($date, $user_culture); // Ottenere una data strutturata list($d, $m, $y) = $this->getContext()->getI18N()->getDateForCulture($date, $user_culture);
Informazione testuale nel database
Un'applicazione localizzata offre diversi contenuti a seconda della cultura dell'utente. Ad esempio, un negozio online può offrire prodotti in tutto il mondo allo stesso prezzo, ma con una descrizione personalizzata per ogni paese. Questo vuol dire che il database deve poter memorizzare diverse versioni di un dato pezzo di dato e, per questo, occorre definire lo schema in un modo particolare e usare la cultura ogni volta che si manipolano oggetti localizzati.
Creare uno schema localizzato
Ogni tabella che contiene dati localizzati deve essere separata in due parti: una tabella
senza alcuna colonna i18n e un'altra con le sole colonne i18n. Le due tabelle sono legate
da una relazione uno-a-uno. Questa configurazione consente di aggiungere altre lingue
senza dover cambiare il modello. Consideriamo un esempio, usando una tabella Product
.
Innanzitutto, creare le tabelle nel file schema.yml
, come mostrato nel listato 13-6.
Listato 13-6 - Schema di esempio per dati i18n Data con Propel, in config/schema.yml
my_connection: my_product: _attributes: { phpName: Product, isI18N: true, i18nTable: my_product_i18n } id: { type: integer, required: true, primaryKey: true, autoincrement: true } price: { type: float } my_product_i18n: _attributes: { phpName: ProductI18n } id: { type: integer, required: true, primaryKey: true, foreignTable: my_product, foreignReference: id } culture: { isCulture: true, type: varchar, size: 7, required: true, primaryKey: true } name: { type: varchar, size: 50 }
Si notino gli attributi isI18N
e i18nTable
nella prima tabella e la colonna speciale
culture
nella seconda. Tutti questi sono caratteristiche specifiche di Propel.
Listato 13-7 - Schema di esempio per dati i18n Data con Doctrine, in config/doctrine/schema.yml
Product: actAs: I18n: fields: [name] columns: price: { type: float } name: { type: string(50) }
Gli automatismi di symfony consentono di rendere tutto più veloce da scrivere. Se la
tabella che contiene i dati internazionalizzati ha lo stesso nome della tabella
principale con _i18n
come suffisso e se sono collegate con una colonna id
in entrambe,
si possono omettere le colonne id
e culture
nella tabella _i18n
e gli attributi
specifici nella tabella principale: symfony li inferirà. Questo vuol dire che symfony
vedrà lo schema nel listato 13-8 come quello nel listato 13-6.
Listato 13-8 - Schema di esempio per dati i18n, versione breve, in config/schema.yml
my_connection: my_product: _attributes: { phpName: Product } id: price: float my_product_i18n: _attributes: { phpName: ProductI18n } name: varchar(50)
Usare gli oggetti i18n generati
Una volta costruiti i corrispondente oggetti del modello (non dimenticare di richiamare
il task propel:build --model
dopo ogni modifica a schema.yml
), si può usare la classe
Product
con supporto i18n, come se fosse una sola tabella, come mostrato nel listato
13-9.
Listato 13-9 - Trattare gli oggetti i18n
$product = ProductPeer::retrieveByPk(1); $product->setName('Nom du produit'); // la cultura dell'utente è quella predefinita $product->save(); echo $product->getName(); => 'Nom du produit' $product->setName('Product name', 'en'); // cambiare il valore per la cultura 'en' $product->save(); echo $product->getName('en'); => 'Product name'
Come per le query con oggetti peer, si possono restringere i risultati a oggetti che
abbiamo la traduzione per la cultura corrente, usando il metodo doSelectWithI18n
,
invece del solito doSelect
, come mostrato nel listato 13-10. Inoltre, esso creerà gli
oggetti i18n correlati contemporaneamente a quelli normali, riducendo così il numero di
query necessarie per ottenere tutti i contenuti (fare riferimento al capitolo 18 per
maggiori informazioni sugli impatti positivi di questo metodo sulle prestazioni).
Listato 13-10 - Recuperare oggetti con Criteria
i18n
$c = new Criteria(); $c->add(ProductPeer::PRICE, 100, Criteria::LESS_THAN); $products = ProductPeer::doSelectWithI18n($c, $culture); // Il parametro $culture è opzionale // Se non passato, è usata la cultura dell'utente
Quindi, fondamentalmente, non si ha mai bisogno di trattare direttamente gli oggetti i18n, ma invece basta passare la cultura al modello (o lasciare che la ricavi) ogni volta che si esegue una query con gli oggetti normali.
Traduzione dell'interfaccia
L'interfaccia utente ha bisogno di essere adattata alle applicazioni i18n. I template devono poter mostrare etichette, messaggi e navigazione in diverse lingue, ma con la stessa presentazione. Symfony raccomanda di costruire i template nella lingua predefinita e poi fornire una traduzione per le frasi usate nei template, in un file dizionario. In questo modo, non occorre modificare i template ogni volta che si modifica, aggiunge o rimuove una traduzione.
Configurare la traduzione
I template non sono tradotti in modo predefinito, il che vuol dire che occorre attivare
la traduzione dei template nel file settings.yml
prima di tutto, come mostrato nel
Listato 13-11.
Listato 13-11 - Attivare l'interfaccia di traduzione, in frontend/config/settings.yml
all: .settings: i18n: true
Usare l'helper della traduzione
Supponiamo di voler creare un sito in inglese e italiano, con l'inglese come lingua predefinita. Prima ancora di pensare di avere il sito tradotto, probabilmente si scriverà nei template qualcosa come l'esempio mostrato nel listato 13-12.
Listato 13-12 - Un template mono-lingua
Welcome to our website. Today's date is <?php echo format_date(date()) ?>
Per fare in modo che symfony possa tradurre le frasi di un template, queste devono
essere identificate come testo da tradurre. Questo è lo scopo dell'helper __()
(due
trattini bassi), un membro del gruppo di helper I18N. Quindi, tutti i template hanno
bisogno di racchiudere le frasi da tradurre in chiamate a questa funzione. Il listato
13-11, ad esempio, può essere modificato come nel listato 13-13 (come si vedrà nella
sezione successiva "Gestire esigenze complesse di traduzione", c'è un modo migliore per
richiamare l'helper di traduzione in questo esempio).
Listato 13-13 - Un template pronto per il multilingua
<?php use_helper('I18N') ?> <?php echo __('Welcome to our website.') ?> <?php echo __("Today's date is ") ?> <?php echo format_date(date()) ?>
tip
Se l'applicazione usa il gruppo di helper I18N per ogni pagina, probabilmente è una buona
idea includerlo nell'impostazione standard_helpers
in settings.yml
, in modo da
evitare di ripetere use_helper('I18N')
per ogni template.
Usare i file dizionario
Ogni volta che la funzione __()
è richiamata, symfony cerca una traduzione del suo
parametro nel dizionario della cultura corrente dell'utente. Se trova una frase
corrispondente, invia e mostra la traduzione nella risposta. Quindi, la traduzione
dell'interfaccia utente si basa sui file dizionario.
I file dizionario sono scritti in XLIFF (XML Localization Interchange File Format), con
un nome che segue lo schema messages.[codice lingua].xml
e memorizzati nella cartella
i18n/
dell'applicazione.
XLIFF è un formato standard basato su XML. Essendo ben noto, si possono usare strumenti di traduzione di terze parti per tradurre tutti i testi del sito. Le aziende che si occupano di traduzione gestiscono normalmente questi file e traducono interi siti, creando una nuova traduzione XLIFF.
tip
Oltre allo standard XLIFF, symfony supporta anche diversi altri sistemi di traduzioni per dizionari: gettext, MySQL e SQLite. Si faccia riferimento alla documentazione delle API per maggiori informazioni sulla configurazione di questi sistemi.
Il listato 13-14 mostra un esempio di sintassi XLIFF col file messages.it.xml
necessario per tradurre il listato 13-14 in italiano.
Listato 13-14 - Un dizionario XLIFF, in frontend/i18n/messages.it.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd"> <xliff version="1.0"> <file original="global" source-language="en_US" datatype="plaintext"> <body> <trans-unit id="1"> <source>Welcome to our website.</source> <target>Bevenuto nel nostro sito.</target> </trans-unit> <trans-unit id="2"> <source>Today's date is </source> <target>La data di oggi è </target> </trans-unit> </body> </file> </xliff>
L'attributo source-language
deve sempre contenere il codice completo ISO della cultura
predefinita. Ogni traduzione è scritta in un tag trans-unit
con un attributo univoco
id
.
Con la cultura predefinita (en_US
), le frasi non sono tradotte e sono mostrati i
parametri delle chiamate __()
, così come sono. Il risultato del listato 13-12 è allora
simile al listato 13-11. Se tuttavia si cambia cultura in it_IT
o it_CH
, sono invece
mostrate le traduzioni del file messages.it.xml
e il risultato appare come nel listato
13-15.
Listato 13-15 - Un template tradotto
Benvenuto nel nostro sito. La data di oggi è <?php echo format_date(date()) ?>
Se occorrono ulteriori traduzioni, basta aggiungere un file di traduzione messages.XX.xml
nella stessa cartella.
tip
Poiché la ricerca dei file dizionario, la sua analisi e l'estrazione della traduzione
corretta di una data stringa potrebbe richiedere un po' di tempo, symfony usa una cache
interna per accelerare il processo. Per impostazione predefinita, questa cache usa il
filesystem. Si può configurare la modalità di funzionamento della cache i18n (ad esempio,
per condividere la cache tra server diversi) in factories.yml
(vedere capitolo 19).
Gestire i dizionari
Se i file messages.XX.xml
diventano troppo lunghi da leggere, possono essere divisi
in diversi file, con nomi opportuni. Ad esempio, si può dividere il file messages.it.xml
in questi tre file, nella cartella i18n/
dell'applicazione:
navigation.it.xml
terms_of_service.it.xml
search.it.xml
Si noti che, poiché la traduzione non si trova nel file predefinito messages.XX.xml
,
occorre dichiarare quel dizionario va usato, a ogni chiamata all'helper __()
, usando il
suo terzo parametro. Ad esempio, per mostrare una stringa tradotta nel dizionario
navigation.it.xml
, va scritto:
<?php echo __('Welcome to our website', null, 'navigation') ?>
Un altro modo per organizzare i dizionari è quello di dividerli per modulo. Invece di
scrivere un singolo file messages.XX.xml
per l'intera applicazione, se ne può scrivere
uno in ogni cartella modules/[nome_modulo]/i18n/
. Questo rende i moduli più
indipendenti dall'applicazione, il che è necessario se si vuole riutilizzarli, come in
un plugin (vedere capitolo 17).
Poiché l'aggiornamento manuale dei dizionari è spesso soggetto a errori, symfony fornisce
un task per automatizzare il processo. Il task i18n:extract
analizza un'applicazione
symfony ed estrae tutte le stringhe che necessitano di traduzione. Accetta come parametri
un'applicazione e una cultura.
$ php symfony i18n:extract frontend en
Per impostazione predefinita, il task non modifica i dizionari, ma mostra solo i numeri
di nuove e vecchie stringhe i18n. Per aggiungere le nuove stringhe al dizionario,
si può passare l'opzione --auto-save
:
$ php symfony i18n:extract --auto-save frontend en
Si possono anche cancellare le vecchie stringhe automaticamente, passando l'opzione
--auto-delete
:
$ php symfony i18n:extract --auto-save --auto-delete frontend en
note
Il task ha alcune limitazioni. Funziona solo col dizionario predefinito messages
e per
i sistemi basati su file (XLIFF
or gettext
), salva e cancella solo stringhe nel file
principale apps/frontend/i18n/messages.XX.xml
.
Gestire altri elementi che richiedono traduzione
I seguenti sono altri elementi che potrebbero richiedere traduzione:
Immagini, documenti di testo o altri tipi di risorse che potrebbero variare con la cultura dell'utente. L'esempio migliore è un pezzo di testo con un carattere tipografico particolare, che in realtà è un'immagine. Per questo, si possono creare delle sottocartelle con nomi che dipendono da
culture
:<?php echo image_tag($sf_user->getCulture().'/myText.gif') ?>
I messaggi di errori di file di validazione dei form passano automaticamente per
__()
, quindi basta aggiungere le loro traduzioni a un dizionario per averli tradotti.- Le pagine predefinite di symfony (pagina non trovata, errore interno del server,
accesso vietato, ecc.) sono in inglese e devono essere riscritte in una applicazione
i18n. Probabilmente si vorrà creare un proprio modulo
default
nell'applicazione e usare__()
nei suoi template. Si faccia riferimento al capitolo 19 per vedere come personalizzare queste pagine.
Gestire esigenze complesse di traduzione
Le traduzioni hanno senso solo se il parametro di __()
è una frase completa. Tuttavia,
se occorrono delle formattazioni o delle variabili mescolate con parole, si può essere
tentati di dividere le frasi in pezzi, quindi richiamare l'helper su frasi senza senso.
Fortunatamente, l'helper __()
offre una soluzione basata su token, che aiutano a
mantenere un dizionario sensato, che è più facile da gestire per i traduttori.
Anche la formattazione HTML può essere lasciata nell'helper. Il listato 13-16 mosta un
esempio.
Listato 13-16 - Traduzione di frasi che contengono codice
// Esempio di base Welcome to all the <b>new</b> users.<br /> There are <?php echo count_logged() ?> persons logged. // Modo inappropriato di abilitare la traduzione <?php echo __('Welcome to all the') ?> <b><?php echo __('new') ?></b> <?php echo __('users') ?>.<br /> <?php echo __('There are') ?> <?php echo count_logged() ?> <?php echo __('persons logged') ?> // Modo appropriato di abilitare la traduzione <?php echo __('Welcome to all the <b>new</b> users') ?> <br /> <?php echo __('There are %1% persons logged', array('%1%' => count_logged())) ?>
In questo esempio, il token è %1%
, ma può essere qualsiasi cosa, perché la funzione di
sostituzione usata dall'helper di traduzione è strtr()
.
Uno dei problemi più comuni con la traduzione è l'uso di forme plurali. A seconda del
numero di risultati, il testo cambia, ma non nello stesso modo in ogni lingua. Ad esempio,
l'ultima frase del listato 13-15 è sbagliata, se count_logged()
restituisce 0 o 1. Si
potrebbe aggiungere una condizione sul valore restituito dalla funzione e scegliere la
frase giusta da usare, ma richiederebbe molto codice. Inoltre, lingue diverse hanno regole
grammatiche diverse e quindi le regole di declinazione del plurale potrebbero essere
molto complesse. Essendo il problema molto comune, symfony fornisce un helper per
risolverlo, chiamato format_number_choice()
. Il listato 13-17 mostra come usare questo
helper.
Listato 13-17 - Traduzione di frasi in base al valore dei parametri
<?php echo format_number_choice( '[0]Nobody is logged|[1]There is 1 person logged|(1,+Inf]There are %1% persons logged', array('%1%' => count_logged()), count_logged()) ?>
Il primo parametro rappresenta le molteplici possibilità del testo. Il secondo parametro è
lo schema di sostituzione (come con l'helper __()
) ed è opzionale. Il terzo parametro è
il numero in base a cui fare il controllo per determinare quale testo usare.
Il messaggio o la stringa scelte sono separati da un carattere di barra verticale (|
)
seguito da un array di valori accettabili, secondo la seguente sintassi:
[1,2]
: Accetta valori tra 1 e 2, inclusi(1,2)
: Accetta valori tra 1 e 2, esclusi 1 e 2{1,2,3,4}
: Accetta solo i valori elencati[-Inf,0)
: Accetta valori maggiori o uguali a meno infinito e minori di zero{n: n % 10 > 1 && n % 10 < 5} pliki
: Accetta numeri come 2, 3, 4, 22, 23, 24 (utile per lingue come il polacco o il russo)
Qualsiasi combinazione non vuota di delimitatori con parentesi tonde e quadre è accettabile.
Il messaggio deve comparire esplicitamente nel file XLIFF per poter avere la giusta traduzione. Il listato 13-18 mostra un esempio.
Listato 13-18 - Dizionario XLIFF per format_number_choice()
... <trans-unit id="3"> <source>[0]Nobody is logged|[1]There is 1 person logged|(1,+Inf]There are %1% persons logged</source> <target>[0]Nessun utente connesso|[1]Un utente connesso|(1,+Inf]Ci sono %1% utenti connessi</target> </trans-unit> ...
Richiamare l'helper di traduzione fuori da un template
Non tutti il testo mostrato in una pagina deriva da template. Per questo spesso occorre
richiamare l'helper __()
in altre parti dell'applicazione: azioni, filtri, classi del
modello, ecc. Il listato 13-19 mostra come richiamare l'helper in un'azione, recuperando
l'istanza corrente dell'oggetti I18N
attraverso il contesto.
Listato 13-19 - Richiamare __()
in un'azione
$this->getContext()->getI18N()->__($text, $args, 'messages');
Riepilogo
la gestione dell'internazionalizzazione e della localizzazione nelle applicazioni web è
indolore, se si sa come gestire la cultura dell'utente. Gli helper si occupano
automaticamente di mostrare correttamente i dati formattati e i contenuti localizzati del
database sono visti come se fossero parte di una semplice tabella. Come per l'interfaccia
di traduzione, l'helper __()
e i dizionari XLIFF assicurano la massima versatilità col
minimo sforzo.
This work is licensed under the GFDL license.