gettext e PHP

adlunamjovem adlunamjovem@tiscali.it
Lun 11 Giu 2007 18:19:46 CEST


Evviva, finalmente un argomento che mi appassiona :)

Io lavoro alla facolta'  lingue e faccio proprio programmi php
multilingua, inoltre leggo e scrivo l'arabo e ti assicuro che se riesci
a far andare il tuo sito con l'arabo, il resto delle lingue sara' una
passeggiata.

L'estensione gettext per php ha una serie enorme di inconvenietni, tra cui:

1) il server su cui gira il programma deve avere questa libreria
installata e php deve essere compilato con --with-gettext[=DIR] (DIR di
default e' /usr/local

2) i locales che ti servono devono essere installati sul sistema, se un
locale non e' installato nel sistema il tuo programma non funzionaera'.
Se stai sviluppando un'applicazione finalizzata ad una utenza non
tecnica, e' quasi impossibile pretendere che per ogni lingua utilizzata
si debbano installare i locales sul server.
Inoltre alcune distribuzioni usano dei locales con nomi differenti
rispetto ai classici "en" "it" ecc... (non so se lo sai ma esistono 3
diverse versioni dello standard per i codici di lingua) per cui anche
installando i locales a volte il tuo programma non funzionera' lo stesso

3) i files .mo sono compilati in base alla piattaforma, cio' significa
che un file mo compilato per un server linux non girera' su un php sotto
a windows

4) il sistema gettext e' (e qui esprimo un parere mio e del tutto
personale) un sistema poco pulito ed estremamente contorto: scrivere
_("ciao mi chiamo Claudio") e poi andare a cercare la traduzione di tale
stringa in un file e' una cosa assai assurda, soprattutto se invece di
una stringa stai traducendo un blocco di testo di svariate righe.


Risultato: dopo anni di lavoro in questo campo ho deciso di creare un
sistema mio per l'internazionalizzazione.
L'ho fatto usando UNA SOLA LINEA di php:

$_stringhe = parse_ini_files('percorso_del_file', true);

Cosa fa questa riga? Semplicissimo: legge un file ini e restituisce un
array bidimensionale (o monodimensionale se non metti il secondo parametro)

Mi spiego meglio:

Immagina un file ini con queste righe:

[pagina_uno]
titolo   = "Pagina uno"
testo    = "Benvenuti sul mio sito"
link     = "Cliccami"

[pagina_due]
titolo   = "Pagina due"
testo    = "Siete a pagina due"
link     = "Torna alla pagina uno"


Ora, chiamiamo questo file "it.ini" e magari creiamone uno parallelo per
l'inglese.
Supponiamo che in $_SESSION['lang'] ci sia la lingua scelta dall'utente,
ecco il testo della pagina uno:

<?php

// se ha scelto it ci prepariamo a leggere il file it.ini
// altrimenti il file en.ini
$_lingua = ( (isset($_SESSION['lang']) && ($_SESSION['lang'] == 'it')) ?
'it' : 'en';

// carico il file
$_stringhe = parse_ini_files('./traduzioni/'.$_lingua.'.ini', true);

/*
A questo punto nella variabile stringhe abbiamo un array bidimensionale
fatto cosi':

$_stringhe['pagina_uno']['titolo'] = "Pagina uno"
$_stringhe['pagina_uno']['testo']  = "Benvenuti sul mio sito"
$_stringhe['pagina_uno']['link']   = "Cliccami"
$_stringhe['pagina_due']['titolo'] = "Pagina due"
$_stringhe['pagina_due']['testo']  = "Siete a pagina due"
$_stringhe['pagina_due']['link']   = "Torna alla pagina uno"

Tutto quelo che dobbiamo fare e' inserire la voce corretta al posto
della stringa, cosi':

*/
?>


<html>
  <head>
    <title> <?php echo $_stringhe['pagina_uno']['titolo'] ?>  </title>
  </head>
  <body>
    <h1> <?php echo $_stringhe['pagina_uno']['testo'] ?> </h1>
    <p>
      <a href="pagina_due.htm" title=''>
        <?php echo $_stringhe['pagina_uno']['link'] ?>
      </a>
    </p>
  </body>
</html>


O se come me preferisci avere tutta la pagina dentro ad un echo, non
chiudi il php e scrivi:


echo <<<PAGINA

<html>
  <head>
    <title> {$_stringhe['pagina_uno']['titolo']} </title>
  </head>
  <body>
    <h1> {$_stringhe['pagina_uno']['testo']} </h1>
    <p>
      <a href="pagina_due.htm" title=''>
        {$_stringhe['pagina_uno']['link']}
      </a>
    </p>
  </body>
</html>

PAGINA;
?>


Se il file ini e' scritto con codifica utf-8, supportera' anche l'arabo
e qualunque altra lingua.
Se imposti il secondo parametro di parse_ini_file a false (o non lo
metti) otterrai un array monodimensionale, ma perderai la possibilita'
di definire due volte la stessa chiave (qui ad esempio abbiamo usato
titolo, testo e link due volte)

Ti assicuro che questo metodo funziona a meraviglia, ti fornisce un
estremo controllo sulla traduzione e sul codice, ingombra molto meno che
scrivere le stringhe in gettext e funziona su tutti i server.


Spero che ti sia d'aiuto.


:)

Claudio


Maggiori informazioni sulla lista glug