Siti multilingua in PHP
mercoledì 29 agosto 2007Ci sono diversi modi per creare un sito multilingua. Alcuni creano dei sottodomini del tipo en.dominio.ext, altri creano delle cartelle con contenuti diversi a seconda della lingua desiderata (www.dominio.ext/en oppure www.dominio.ext/it) altri ancora (compreso il sottoscritto) invece vorrebbero mantenere un unico dominio e un nome unico per le pagine, permettendo però all'utente di cambiare lingua a proprio piacimento.
In PHP (torno a ripetermi) ci sono diversi modi di realizzare un sito multilingua. Oggi ne vediamo uno: non il migliore, per carità (e vedremo dopo il perché) ma è il modo che mi viene pù comodo.
Utilizzeremo una tabella del database del sito web che conterrà le varie stringhe nelle lingue desiderate e tramite le variabili di sessione andremo a scegliere di volta in volta la stringa giusta, tenendo come base di partenza la lingua italiana: la funzione scrivi("Parola in italiano"), utilizzata per ogni stringa all'interno delle nostre pagine ci aiuterà durante la scrittura del codice, mantenendo tutto più leggibile.
PREREQUISITI
Bisogna saper utilizzare le variabili di sessione in PHP. Maggiori informazioni le trovate a questo indirizzo e sul manuale.
CREAZIONE DELLA TABELLA NEL DATABASE
Per prima cosa creiamo la tabella stringhe all'interno del database del nostro sito web.
CREATE TABLE `stringhe` ( `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, `sITA` text NOT NULL, `sENG` text NOT NULL, `sGER` text NOT NULL, `sFRA` text NOT NULL, PRIMARY KEY (`id`) )
Nella tabella, com'è facile immaginare, ogni riga conterrà una parola (o una frase) tradotta in quattro lingue (ma se ne possono impostare 20, 30, dipende tutto da quanti interpreti abbiamo a disposizione). La prima riga ad esempio potrebbe contenere i valori ("uno","one","ein","un")
LE VARIABILI DI SESSIONE
Le variabili di sessione sono il vero cuore del sistema. All'inizio di ogni pagina andremo a chiamare il seguente codice, che imposterà la lingua italiana come default, se non esiste una lingua già preimpostata.
// Inizia sessione, usato per la lingua session_start(); // Se non è selezionata la lingua la imposta if(!isset($_SESSION["lingua"])) $_SESSION["lingua"] = "ITA";
Notato niente? La variabile $_SESSION["lingua"] contiene un valore di 3 lettere uguale a quello contenuto nei vari campi del database.
Come fare a cambiare lingua? Semplice, creiamo il nostro bel menù (di solito composto di bandierine) e colleghiamolo ad un file (ad esempio passandogli una variabile via GET) che si occuperà di impostare la variabile di sessione a seconda della lingua scelta e di ritornare alla pagina che l'ha chiamata.
// Inizia sessione, usato per la lingua session_start(); // Imposto la lingua $_SESSION["lingua"] = $_GET["lingua"]; // Redirect header("Location: {$_SERVER["HTTP_REFERER"]}");
Poniamo di aver chiamato questo file "cambialingua.php", creando un collegamento a cambialingua.php?lingua=ENG possiamo passare alla lingua inglese e ritornare alla nostra pagina.
LA FUNZIONE SCRIVI()
Ok, abbiamo creato il meccanismo di "cambio lingua", ma come fare per stampare il testo in lingue diverse ogni volta? La funzione scrivi() si occuperà di tutto. In pratica la funzione riceverà come parametro la stringa in lingua italiana, restituendo la stringa nella lingua impostata nella variabile di sessione.
// Ritorna la stringa in base alla parola passata e la lingua attiva function scrivi($ita) { global $connessione; // Costruisco nome campo $lingua = "s" . $_SESSION["lingua"]; // Eseguo query $sql = "SELECT * FROM stringhe WHERE sITA = '{$ita}'"; $result = mysql_query($sql,$connessione) or die("Errore SQL: " . mysql_error()); $row = mysql_fetch_assoc($result); // Se il termine manca nella lingua scelta viene mostrato quello inglese if($row[$lingua] != "") echo $row[$lingua]; else echo $row["sENG"]; }
Ecco nel dettaglio cosa fa questa funzione:
- Viene costruita la stringa "s" + "variabile di sessione corrispondente alla lingua attiva"
- Viene fatta una query impostando come chiave di ricerca la stringa in lingua italiana passata come parametro
- Viene stampato il termine nella lingua scelta
All'interno delle nostre pagine ogni volta che dobbiamo stampare una stringa che dovrà essere tradotta chiameremo scrivi() passando come parametro la frase (o la parola) scritta in lingua italiana. Il sistema si occuperà del resto.
QUANDO USARE QUESTO SISTEMA E QUANDO NON USARLO
Questo sistema non è perfetto. Crea abbastanza carico sul server (esegue una query per ogni stringa da stampare). Va quindi abbinato ad un sistema di caching delle pagine se ne vogliamo aumentare l'efficienza. Per siti "grandi" addirittura consiglierei di non usarlo e di usare uno dei metodi elencati a fondo post.
E' possibile riconoscere automaticamente da PHP la lingua usata dal browser dell'utente e presentargli la versione adatta modificando al volo la variabile di sessione, cosa che in questo esempio non è stata implementata.
Funziona bene invece per siti piccoli, con poco testo che magari deve essere tradotto in molte lingue (personalmente ho provato a creare un sito con 8 lingue diverse). Modificando di poco il codice presente all'inizio di ogni pagina è facile impostare una lingua di default, senza dover intervenire sul db o su altre variabili.
I motori di ricerca indicizzeranno la lingua di default immagino. Non ho effettuato esperimenti in tal senso e quindi non posso essere sicuro della cosa
Ecco comunque un interessante articolo su SEO e siti multilingua.
METODI ALTERNATIVI
Vediamo una carrellata di metodi alternativi, da scegliere a seconda delle esigenze e delle proprie capacità.
- Usare array e files diversi per ogni lingua
- Usare mod_rewrite e/o cartelle diverse per ogni versione del sito
- Utilizzare un file .ini dove conservare le varie frasi divise per lingua
- Utilizzare un file .xml (come sopra)
- Paolo Rossi mi suggerisce anche i file .po e la funzione gettext() (me la vado a guardare, grazie) che se non sbaglio è lo stesso sistema utilizzato da WordPress
CONCLUSIONI
Niente esempio questa volta. Rimango comunque a disposizione nei commenti per eventuali domande, critiche e/o correzioni...
In alternativa puoi abbonarti alla newsletter, riceverai un'email ogni volta che verrà pubblicato un nuovo post. Il tuo indirizzo email sarà gestito da Feedburner.











(3 voti, media: 4,67)
29 agosto 2007 alle 08:57
Ciao napolux,
perché non usare gettext cambiando al volo il locale a seconda dell’impostazione/preferenze dell’utente? I files .po sono facili da manutere e la loro elaborazione carica poco il server… che ne dici
29 agosto 2007 alle 09:01
Interessante, davvero interessante, approfondirò senza dubbio l’argomento. Io per ora adopero uno dei classici plugin.
29 agosto 2007 alle 09:14
@Paolo Rossi
Grazie, non ci avevo assolutamente pensato. E’ lo stesso sistema che usa WP se non sbaglio…
29 agosto 2007 alle 09:17
@napolux
…esatto!
29 agosto 2007 alle 09:18
Interessante ma resto fedele ad un usare un file di stringhe per ogni lingua. In questo modo non devo far altro che tradurre il file et voilà il gioco è fatto.
Come ulteriore ottimizzazione suddivido i file stringhe rendendoli più piccoli per ogni pagina che dovrebbe caricarli, in questo modo non appesantisco il server caricando un array di 10.000 righe se me ne servono solo 10 o 100 per una semplice pagina …
Per il resto come al solito … un articolo interessante …
29 agosto 2007 alle 09:20
Grazie Napolux!
29 agosto 2007 alle 09:22
Condivido appieno. Per i siti multilingua è necessario avere una buona analisi del prodotto da fare e soprattutto della sua scalabilità, fino a proporre un multi-lingua completamente dinamico e interfacciato a DB.
http://tinyurl.com/2vxjqx
29 agosto 2007 alle 10:50
Personalmente per evitare troppo carico al server uso un misto tra quello indicato da te, file inclusi e querystring con la lingua.
In poche parole, seguo questa logica: tutto il testo strutturale tipo menu, label dei form, footer ed altri testi statici li gestisco con un file [lingua].php nella cartella “dictionary”; ad esempio: en.php, it.php etc. All’inizio della pagine includo il file della ligua appropriata (o eventualmente quello di default).
Non esiste una pagina di cambio lingua, basta cliccare sulla bandierina desiderata e la pagina si traduce automaticamente.
Non appena sarà pronto il mio blog (se mai sarà pronto) credo che tratterò anch’io l’argomento spiegando nel dettaglio la tecnica utilizzata.
29 agosto 2007 alle 12:47
è più veloce a leggere su file che a leggere su database… secondo me è una scelta sbagliata questa.
29 agosto 2007 alle 13:10
Io preferisco la versione con file per ogni lingua in cui metti un array (magari fai più file, dipende dalla dimensione)… sicuramente carica di meno il server…
il metodo con gettext mi sono sempre ripromesso di darci un’occhiata, ma ancora non ho avuto modo di farlo…
29 agosto 2007 alle 13:12
@Skyline
A volte oltre all’efficienza bisogna anche guardare alla comodità. Tante volte il db è più facile da manutenere rispetto ai file di testo…
29 agosto 2007 alle 13:35
@napolux penso che per una persona che non sappia molto programmare sia più semplice mettere una stringa in un file di testo oppure una nuova cartella per aggiungere una nuova lingua.
invece con il tuo sistema per aggiungere una lingua addio, devi aggiungere un campo nella tabella e dopo riempirli uno ad uno.
29 agosto 2007 alle 14:54
ottimo tutorial, anche se condivido il pensiero di skyline.
un file di testo è più facile da gestire sia per chi deve aggiungere/togliere stringhe, sia per il server.
interessante la funzione gettext() e i files .po, non ne ero a conoscenza (anche se li ho usati con wp)
29 agosto 2007 alle 15:14
gettext è una liberia GNU consolidata e molto diffusa, utilizzata dalla quasi totalità dei linguaggi di programmazione (C, Python, PHP, Perl, Ruby, etc.). Consente tra l’altro di gestire la sostituzione di variabili all’interno dei messaggi e altre sciccherie come la gestione delle forme singolari/plurali.
La preparazione dei file .po e la loro compilazione può essere effettuata anche attraverso comode GUI per chi preferisce evitare la riga di comando.
http://www.gnu.org/software/gettext/
29 agosto 2007 alle 16:58
Appoggio 100% Paolo Rossi.
31 agosto 2007 alle 09:26
Condivido l’idea del Gettext. Se, per caso, non fosse installata sul server come estensione, esistono anche classi per renderla lo stesso fruibile.
31 agosto 2007 alle 17:58
Questo metodo sarà più complicato dell’usare i files di testo.. ma se si deve far inserire dati (testi) all’utente passando da un ipotetito pannello di controllo (in stile wordpress per capirci) è sicuramente un’ottima soluzione
Grazie Nepolux
31 agosto 2007 alle 19:25
stile wordpress? ma wordpress mica usava gettext? sei confuso mi sa.
31 agosto 2007 alle 19:47
Ti sei confuso tu. JeKo intendeva parlare dei siti in cui il testo va inserito dall’utente (per i più svariati motivi), utilizzando un pannello di controllo simile a quello di wordpress.
19 settembre 2007 alle 14:00
[...] Inoltre a breve, grazie alla guida di Napolux, troverete anche la versione in lingua Inglese. Poi penso che iniziative italiane possano sempre far piacere! [...]