Development

Documentation/it_IT/book/1.0/13-I18n-and-L10n

You must first sign up to be able to contribute.

Capitolo 13 - i18n e l10n

Qualora tu abbia mai sviluppato un'applicazione internazionale, sai che gestire ogni aspetto delle traduzioni dei testi, degli standard locali e dei contenuti localizzati è un incubo. Fortunatamente, symfony automatizza nativamente tutti gli aspetti dell'internazionalizzazione.

Dato che si tratta di una parola lunga, spesso gli sviluppatori si riferiscono all'internazionalizzazione con i18n (conta le lettere della parola "internationalization" per capirne il motivo). Ci si riferisce alla localizzazione invece come l10n. Esse coprono due diversi aspetti delle applicazioni web multi-lingua.

Un'applicazione internazionalizzata contiene diverse versioni dello stesso contenuto i diverse lingue e formati. Ad esempio, un'interfaccia webmail può offrire lo stesso servizio in diverse lingue; solo l'interfaccia stessa cambia.

Un'applicazione localizzata invece contiene informazioni distinte a seconda del paese da cui la si sta visitando. Pensa al contenuto di un portale di notizie: se navigato dagli Stati Uniti fornisce notizie sugli Stati Uniti, mentre se lo navighi dall'Italia vedrai notizie sull'Italia. Per cui un'applicazione l10n non solo fornisce testo tradotto, ma i contenuti possono essere diversi da una versione all'altra.

In conclusione, gestire i18n e l10n significa occuparsi dei seguenti punti:

  • Traduzione dei testi (interfacce, risorse e contenuti)
  • Standard e formati (date, quantità, numeri e cosi' via)
  • Contenuti localizzati (diverse versioni dello stesso oggetto a seconda del paese)

Questo capitolo spiega il modo in cui symfony gestisce questi elementi, e come puoi sviluppare applicazioni localizzate ed internazionalizzate.

User Culture

Tutte le funzionalità i18n incluse in symfony sono basate su di un parametro della sessione utente chiamato culture. Esso è una combinazione del paese e della lingua dell'utente, e determina il modo in cui vengono visualizzati testi ed informazioni dipendenti dalla propria cultura. Dato che viene serializzato in sessione, esso è persistente nelle pagine.

Impostare la culture di default

Per default, la cultura di nuovi utenti è default_culture. Puoi cambiare questa impostazione nel file di configurazione i18n.yml, come mostrato nel Listato 13-1.

Listato 13-1 - Impostare la cultura di default, in myapp/config/i18n.yml

[php]
all:
  default_culture:     it_IT

NOTE Durante lo sviluppo, potresti essere sorpreso nel non vedere cambiamenti nel browser dopo aver modificato l'impostazione nel file i18n.yml. Questo è dovuto al fatto che la sessione possiede già la cultura dalle pagine precedenti; se vuoi vedere le modifiche devi eliminare i cookie del dominio o riavviare il browser.

Mantenere sia il paese che la lingua nell'oggetto culture è importante in quanto potresti avere traduzioni francesi differenti per Francia, Belgio o Canada, oppure per Spagna e Messico. La lingua e' codificata in due caratteri minuscoli, secondo lo standard ISO 639-1 (ad esempio, en per inglese). Il paese invece con due caratteri maiuscoli, secondo lo standard ISO 3166-1 (ad esempio GB per Gran Bretagna).

Cambiare la cultura di un utente

La cultura di un utente può essere cambiata durante la navigazione; ad esempio, se l'utente decide di cambiare versione dell'applicazione, da francese a inglese, oppure quando un utente si autentica e viene visualizzata la lingua memorizzata nelle sue preferenze. Ecco perché la classe sfUser offre metodi getter e setter per la cultura. Il Listato 13-2 mostra tali metodi in azione.

Listato 13-2 - Impostare e recuperare la cultura in un'azione

[php]
// Culture setter
$this->getUser()->setCulture('en_US');

// Culture getter
$culture = $this->getUser()->getCulture();
 => en_US

SIDEBAR Cultura nelle URL

Utilizzando le funzionalità i18n e l10n di symfony, le pagine tendono ad avere diverse versioni per una URL singola; ognuna dipende dalla sessione utente. Ciò è di ostacolo al caching ed all'indicizzazione nei motori di ricerca. Una soluzione potrebbe essere quella di mostrare la cultura ogni URL, in modo che le pagine tradotte vengano viste come URL diverse nel mondo esterno. Per fare ciò, aggiungi il token :sf_culture ad ogni regola del file routing.yml della tua applicazione: [php] page: url: /:sf_culture/:page requirements: { sf_culture: (?:fr|en|de) } params: ...
article: url: /:sf_culture/:year/:month/:day/:slug requirements: { sf_culture: (?:fr|en|de) } params: ...

Per evitare di impostare manualmente il parametro di richiesta sf_culture in ogni link_to(), symfony aggiunge automaticamente la cultura dell'utente ai parametri di routing di default. Ciò funziona anche in ingresso, in quanto symfony cambierà automaticamente la cultura dell'utente se trova il parametro sf_culture nell'URL.

Determinare automaticamente la cultura

In molte applicazioni la cultura viene definita durante la prima richiesta, basandosi sulle preferenze del browser. Gli utenti possono definire nel browser una lista di lingue accettate, e tale dato viene spedito al server ad ogni richiesta, nell'header HTTP Accepted-Language. Puoi vederlo in symfony tramite l'oggetto sfRequest. Ad esempio, per vedere in un'azione la lista delle lingue preferite di un utente scrivi:

[php]
$languages = $this->getRequest()->getLanguages();

L'header HTTP è una stringa, ma symfony ne fa il parsing automaticamente e la converte in un array. Per cui nell'esempio precedente la lingua preferita dall'utente e' disponibile in $languages[0].

Può essere utile impostare automaticamente la cultura dell'utente nella sua lingua preferita per la home page od in un filtro per tutte le pagine.

CAUTION L'header HTTP Accept-Language non è in realtà un'informazione molto affidabile, in quanto raramente l'utente sa come modificarlo nelle proprie impostazioni del browser. La maggior parte delle volte, la lingua preferita nella navigazione e' quella dell'interfaccia, ed i browser non sono disponibili in tutte le lingue. Se decidi di impostare la lingua di default secondo quella utilizzata nel browser, assicurati di fornire all'utente un modo per cambiarla.

Standard e formati

Gli interni di un'applicazione web di solito non si preoccupano molto delle particolarità culturali. I database, ad esempio, utilizzano standard internazionali per memorizzare i dati, quantità e così via. Ma quando un dato è spedito o ricevuto da un utente, è necessaria una conversione. Gli utenti non capiranno i timestamp, e preferiranno impostare la propria lingua come English invece di Inglese. Per cui c'è bisogno di aiuto nella conversione automatica di tali valori basati sulla cultura.

Visualizzare i dati nella cultura dell'utente

Una volta che la cultura è definita, gli helper che dipendono da essa stamperanno automaticamente i dati nel formato corretto. Ad esempio, l'helper format_number() visualizza automaticamente nel formato familiare all'utente, secondo la propria cultura, come mostrato nel Listato 13-3.

Listato 13-3 - Visualizzare numeri nella cultura dell'utente

[php]
<?php use_helper('Number') ?>

<?php $sf_user->setCulture('en_US') ?>
<?php echo format_number(12000.10) ?>
 => '12,000.10'

<?php $sf_user->setCulture('fr_FR') ?>
<?php echo format_number(12000.10) ?>
 => '12 000,10'

Non hai bisogno di passare esplicitamente la cultura agli helper. Essi la cercheranno da soli nell'oggetto sessione corrente. Il Listato 13-4 mostra una lista degli helper che tengono conto della cultura nel loro output.

Listato 13-4 - Helper dipendenti dalla cultura

[php]
<?php use_helper('Date') ?>

<?php echo format_date(time()) ?>
 => '9/14/06'

<?php echo format_datetime(time()) ?>
 => 'September 14, 2006 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, 2006)) ?>
 => input type="text" name="birth_date" id="birth_date" value="9/14/06" 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 accettano un parametro aggiuntivo di formattazione per forzare una visualizzazione indipendente dalla cultura, ma non dovresti usarlo se la tua applicazione e' internazionalizzata.

Ricevere i dati da un input localizzato

Se è necessario mostrare i dati nella cultura dell'utente, così come riceverli, dovresti per quanto possibile educare i tuoi utenti ad inserire dati già internazionalizzati. Questo approccio di eviterà di cercare di capire come convertire dati con diversi formati. Ad esempio, chi potrebbe inserire in un campo di testo un valore monetario con la virgola?

Puoi limitare la formattazione dell'input inserito dall'utente sia nascondendo i dati effettivi (come nel caso di select_country_tag()) sia dividendo i diversi componenti di dati complessi in vari campi di testo.

Per le date, comunque, spesso questo non e' possibile. Gli utenti sono abituati ad inserire le date nel proprio formato culturale, e hai bisogno di saper convertire tali date in un formato interno (ed internazionale). Ecco dove ti viene in aiuto la classe sfI18N. Il Listato 13-5 mostra come usarla.

Listato 13-5 - Ricevere una data in formato localizzato in un'azione

[php]
$date= $this->getRequestParameter('birth_date');
$user_culture = $this->getUser()->getCulture();

// Ricevere un timestamp
$timestamp = sfI18N::getTimestampForCulture($date, $user_culture);

// Ricevere una data strutturata
list($d, $m, $y) = sfI18N::getDateForCulture($date, $user_culture);

Testi nel database

Un'applicazione localizzata fornisce diversi contenuti a seconda della cultura dell'utente. Ad esempio, un negozio online può fornire prodotti allo stesso prezzo in tutto il mondo, ma con descrizioni differenti a seconda del paese. Ciò significa che il database deve essere capace di memorizzare diverse versioni dello stesso dato, e per questo devi disegnare il tuo schema in un modo particolare; inoltre devi usare la cultura ogni volta che manipoli gli oggetti del modello.

Creare uno schema localizzato

Devi dividere ogni tabella contenente dati localizzati in due parti: una tabella senza alcuna colonna i18n, e l'altra contenente esclusivamente colonne i18n. Le due tabelle saranno collegate tramite una relazione uno-a-molti. Questo setup ti permette di aggiungere nuove lingue qualora ce ne sia il bisogno, senza modificare il modello. Vediamo un esempio considerando la tabella Product.

Prima di tutto crea lo schema delle tabelle come mostrato nel Listato 13-6.

Listato 13-6 - Esempio di schema per dati i18n, in config/schema.yml

[php]
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 }

Nota gli attributi isI18N e i18nTable della prima tabella, e la colonna speciale culture nella seconda. Sono entrambi miglioramenti specifici di symfony dovuti a Propel.

Le automazioni di symfony rendono questo molto veloce da scrivere. Se la tabella che contiene i dati internazionalizzati ha lo stesso nome della tabella principale con il suffisso _i18n, ed esse sono collegate tramite id, puoi evitare di scrivere le colonne id e culture nella tabella _i18n e gli attributi i18n della tabella principale; symfony si occuperà di tutto. Con tali presupposti, symfony vedrà lo schema del Listato 13-7 esattamente come quello del Listato 13-6.

Listato 13-7 - Esempio di schema per dati i18n, versione abbreviata, in config/schema.yml

[php]
my_connection:
  my_product:
    _attributes: { phpName: Product }
    id:
    price:       float
  my_product_i18n:
    _attributes: { phpName: ProductI18n }
    name:        varchar(50)

Utilizzare gli oggetti i18n generati

Una volta creato il corrispondente modello (non dimenticare di di chiamare symfony propel-build-model e di pulire la cache con smyfony cc dopo aver modificato il file schema.yml), puoi usare la tabella Product con il supporto i18n come se fosse una tabella unica, come mostrato dal Listato 13-8.

Listato 13-8 - Gestire oggetti i18n

[php]
$product = ProductPeer::retrieveByPk(1);
$product->setCulture('fr');
$product->setName('Nom du produit');
$product->save();

$product->setCulture('en');
$product->setName('Product name');
$product->save();

echo $product->getName();
 => 'Product name'

$product->setCulture('fr');
echo $product->getName();
 => 'Nom du produit'

Se non ti vuoi preoccupare di cambiare la cultura ogni volta che usi un oggetto i18n, puoi anche cambiare il metodo hydrate() della classe. Vedi un esempio nel Listato 13-9.

Listato 13-9 - Override del metodo hydrate() per impostare la cultura, in myproject/lib/model/Product.php

[php]
public function hydrate(ResultSet $rs, $startcol = 1)
{
  parent::hydrate($rs, $startcol);
  $this->setCulture(sfContext::getInstance()->getUser()->getCulture());
}

Come per le query con gli oggetti peer, puoi restringere il risultato ad oggetti che abbiano una traduzione per la cultura corrente tramite il metodo doSelectWithI18n, invece di doSelect, come mostrato dal Listato 10-13. Inoltre, esso creerà l'oggetto i18n relativo nello stesso momento di quello di default, in modo che il numero di query per recuperare il contenuto sarà ridotto (consulta il Capitolo 18 per maggiori informazioni sull'impatto positivo di questo metodo sulle prestazioni).

Listato 13-10 - Recuperare oggetti con un Criteria i18n

[php]
$c = new Criteria();
$c->add(ProductPeer::PRICE, 100, Criteria::LESS_THAN);
$products = ProductPeer::doSelectWithI18n($c, $culture);
// Il parametro $culture e' opzionale
// Se non viene passata alcuna cultura viene utilizzata quella di default dell'utente corrente

Per cui, fondamentalmente, non dovresti mai gestire gli oggetti i18n direttamente, piuttosto passare la cultura al modello (o farglielo capire) ogni volta che esegui query.

Traduzione delle interfacce

Le interfacce utente hanno bisogno di essere adattate per applicazioni i18n. Le template devono saper presentare nello stesso formato, ma in lingue differenti, etichette, messaggi, e menu di navigazione. Symfony raccomanda di costruire le tue template nella lingua di default, per poi fornire le traduzioni in un dizionario. In tale maniera, non hai bisogno di cambiare le template ogni volta che modifichi, aggiungi o elimini una nuova lingua.

Configurare la traduzione

Le template non vengono tradotte per default, ciò significa che devi prima di tutto attivare la gestione delle traduzioni nel file settings.yml, come mostrato nel Listato 13-11.

Listato 13-11 - Attivazione della traduzione delle interfacce, in myapp/config/settings.yml

[php]
all:
  .settings:
    i18n: on

Utilizzare l'helper per la traduzione

Diciamo che tu voglia costruire un sito in inglese e francese, con l'inglese come lingua di default. Ancora prima di pensare alle traduzioni, probabilmente hai scritto nelle tue template qualcosa come mostrato nell'esempio del Listato 13-12.

Listato 13-12 - Template a lingua unica

[php]
Welcome to our website. Today's date is <?php echo format_date(date()) ?>

Per poter fare in modo che symfony traduca i testi delle template, essi devono essere in qualche modo riconoscibili. Questo è lo scopo dell'helper __() (due underscore), un membro del gruppo di helper I18n. Per cui, in tutte le tue template, tutto ciò che deve essere tradotto deve essere racchiuso in tale helper. Il Listato 13-12, ad esempio, può essere modificato come nel Listato 13-13 (come vedrai nella sezione "Gestire traduzioni complesse" più avanti in questo capitolo, c'e' anche un modo migliore per chiamare l'helper delle traduzioni di quello in questo esempio).

Listato 13-13 - Template multi-lingua

[php]
<?php use_helper('I18N') ?>

<?php echo __('Welcome to our website.') ?>
<?php echo __("Today's date is ") ?>
<?php echo format_date(date()) ?>

TIP Se la tua applicazione utilizza il gruppo di helper I18n per ogni pagina, probabilmente è una buona idea includerlo nell'impostazione standard_helpers del file settings.yml, in modo da ripetere in ogni template la chiamata use_helper('I18N').

Utilizzare un dizionario

Ogni volta che viene chiamata la funzione __() symfony cerca una traduzione del testo passatole come argomento nel dizionario della cultura dell'utente. Se trova una corrispondenza, viene visualizzata la traduzione, che quindi si basa su un file contenente il dizionario.

I file dei dizionari con le traduzioni sono scritti in XML Localization Interchange File Format (XLIFF), nominati secondo il pattern messages.[codice linguaggio].xml e memorizzati nella cartella i18n/ dell'applicazione.

XLIFF è uno standard basato su XML. Dato che è molto conosciuto, puoi usare software di terze parti per trovare e gestire tutte le traduzioni. Le aziende che si occupano di traduzioni sanno come gestire tali file e come tradurre un intero sito semplicemente aggiungendone uno.

NOTE In aggiunta allo standard XLIFF, symfony supporta anche diversi strumenti di backend per la traduzione, quali gettext, MySQL, SQLite, e Creole. Consulta la documentazione sulle API per la configurazione di tali backend.

Il Listato 13-14 mostra un esempio di sintassi XLIFF con il file messages.fr.xml per la traduzione in francese del Listato 13-13.

Listato 13-14 - Dizionario XLIFF, in myapp/i18n/messages.fr.xml

[php]
<?xml version="1.0" ?>
<xliff version="1.0">
  <file orginal="global" source-language="en_US" datatype="plaintext">
    <body>
      <trans-unit id="1">
        <source>Welcome to our website.</source>
        <target>Bienvenue sur notre site web.</target>
      </trans-unit>
      <trans-unit id="2">
        <source>Today's date is </source>
        <target>La date d'aujourd'hui est </target>
      </trans-unit>
    </body>
  </file>
</xliff>

L'attributo source-language deve sempre contenere l'intero codice ISO della lingua della cultura di default, mentre ogni traduzione e' racchiusa tra tag trans-unit ed ha un id unico.

Nella lingua di default (in questo caso en_US) non avviene alcuna traduzione ed è visualizzata la stringa passata come argomento all'helper. Il risultato del Listato 13-13 è quindi simile a quello del Listato 13-12. Ma se la cultura viene cambiata in fr_FR o fr_BE, vengono invece mostrate le traduzioni del file messages.fr.xml, ed il risultato è il Listato 13-15.

Listato 13-15 - Template tradotta

[php]
Bienvenue sur notre site web. La date d'aujourd'hui est
<?php echo format_date(date()) ?>

Se hai bisogno di aggiungere lingue, non devi far altro che creare altri file messages.XX.xml nella stessa cartella.

Gestione dei dizionari

Se il tuo file messages.XX.xml del dizionario diventa troppo lungo da leggere, lo puoi suddividere in più file, magari nominandoli per "tema". Ad esempio si potrebbe dividere il file messages.fr.xml nella cartella i18n/ nei seguenti tre:

  • navigation.fr.xml
  • terms_of_service.fr.xml
  • search.fr.xml

Nota che ogni volta che non deve essere usato il file di default messages.XX.xml, occorre dichiarare esplicitamente quali file sono da utilizzare ogni volta che usi l'helper __(), specificandone il terzo argomento. Ad esempio, per stampare una stringa dal dizionario navigation.fr.xml:

[php]
<?php echo __('Welcome to our website', null, 'navigation') ?>

Un altro modo per organizzare i dizionari è quello di suddividerli in moduli. Invece di scrivere un unico file messages.XX.xml per tutta l'applicazione, ne puoi scrivere uno in ogni cartella modules/[module_name]/i18n/. Questo rende i moduli più indipendenti dall'applicazione, cosa particolarmente utile quando hai la necessità di riutilizzarli (ad esempio come per i plugin, Capitolo 17).

Gestione di altri elementi che necessitano di traduzione

Altri elementi che potrebbero necessitare di una traduzione sono i seguenti:

  • Immagini, documenti di testo, od ogni altro tipo di risorsa. Un esempio potrebbe essere un pezzo di testo con una tipografia particolare, visualizzata come immagine; per tutte queste risorse, puoi creare sotto cartelle con il la culture nel nome:

    [php] <? getCulture().'/myText.gif') ?>

  • I messaggi di errore della validazione vengono automaticamente stampati in output con __(), per cui hanno solo bisogno di avere le traduzioni corrispondenti nei dizionari.

  • Le pagine di default di symfony (pagina non trovata, errore interno del server, accesso riservato e così via) sono scritte in inglese e devono essere riscritte. Probabilmente dovresti scrivere il tuo modulo default personalizzato ed usare __() nelle template. Vedi il Capitolo 19 per capire come personalizzare tali pagine.

Gestire traduzioni complesse

Le traduzioni hanno senso solo quando l'argomento di __() e' una frase completa. Tuttavia, potresti avere la necessità di inserire parametri in una frase, ed essere quindi tentato di suddividere la frase in diversi parti, cosicché l'argomento dell'helper perde di significato. Fortunatamente, l'helper __() offre una funzionalità basata su token che aiuta i traduttori ad avere un dizionario sensato. Il Listato 13-16 ne mostra qualche esempio.

Listato 13-16 - Tradurre frasi che contengono codice

[php]
// Esempio di base
Welcome to all the <b>new</b> users.<br />
There are <?php echo count_logged() ?> persons logged.

// Modo sbagliato di tradurre
<?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 migliore da utilizzare
<?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 potrebbe essere qualsiasi cosa, dato che la funzione usata per la sostituzione è strtr().

Uno dei problemi più comuni nelle traduzioni è la forma plurale. A seconda della lingua e del numero di risultati il testo può cambiare. Per esempio nel Listato 13-16 la frase non è corretta se il risultato della funzione count_logged() fosse 0 o 1. Potresti certamente fare un test per verificare il valore e scegliere la frase di conseguenza, ma ciò implicherebbe scrivere più codice del necessario. Inoltre le lingue hanno regole differenti per il plurale, per cui la cosa può diventare complicata. Dato che questo problema è molto diffuso, symfony offre un helper per gestirlo, chiamato format_number_choice(). Il Listato 13-17 mostra come usarlo.

Listato 13-17 - Frasi tradotte a seconda del valore di parametri

[php]
<?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 è una lista con le possibili scelte; il secondo, come per l'helper __() e' il pattern di sostituzione, ed è opzionale. Il terzo è un numero sul quale si basa la scelta del testo da stampare. La sintassi di ogni singola frase (possibilità) da stampare è composta da pipe (|) come separatore, seguito da un array di valori accettabili:

  • [1,2]: accetta valori tra 1 e 2, inclusi
  • (1,2): accetta valori tra 1 e 2, esclusi
  • {1,2,3,4}: accetta solo i valori definiti tra le parentesi
  • [-Inf,0): accetta valori compresi tra infinito negativo e 0 (escluso)

È accettabile anche una composizione non vuota di parentesi quadre e tonde.

Il messaggio dovrà apparire esplicitamente anche nel file XLIFF per essere visualizzato nel modo corretto. Il Listato 13-18 mostra come.

Listato 13-18 - Dizionario XLIFF per la funzione format_number_choice()

[php]
...
<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]Personne n'est connecté|[1]Une personne est connectée|(1,+Inf]Il y a %1% personnes en ligne</target>
</trans-unit>
...

SIDEBAR Qualche parola a proposito di charset Gestire traduzioni porta spesso a problemi con i charset. Se usi un charset localizzato, dovrai cambiarlo ogni volta che l'utente cambia cultura. Inoltre, le template scritte in un charset non saranno visualizzate correttamente in un altro. Per tale motivo, quando gestisci più di una cultura, tutte le template devono essere salvate in formato UTF-8, ed il layout deve dichiarare il contenuto di tale tipo. Se lavori sempre con questo formato ti risparmierai brutte sorprese e pesanti mal di testa. Le applicazioni symfony si basano su un'impostazione centrale per il charset, nel file settings.yml. Cambiare tale parametro cambierà l'header content-type di tutte le risposte.

[php] all: .settings: charset: utf-8

Chiamare l'helper per la traduzione fuori dalle template

Non tutti i testi di un'applicazione provengono dalle template. Per cui spesso potresti aver bisogno di chiamare __() in altre parti dell'applicazione: azioni, filtri, classi del modello e cosi' via. Il Listato 13-19 mostra come chiamare l'helper in un'azione recuperando l'istanza corrente dell'oggetto I18n attraverso il singleton.

Listato 13-19 - Chiamare __() in un'azione

[php]
$this->getContext()->getI18N()->__($text, $args, 'messages');

Sommario

La gestione dell'internazionalizzazione e della localizzazione è più semplice se sai come gestire la cultura dell'utente. Gli helper si occupano automaticamente di stampare i dati formattati nel modo corretto, ed i contenuti localizzati nel database vengono visti come facenti parte di un'unica tabella. Per la traduzione delle interfacce l'helper __() ed i dizionari XLIFF assicurano che tu abbia la massima versatilità con il minimo sforzo.