Usant gettext amb php

La utilitat GNU gettext facilita la traducció de programes utilitzant un cataleg de missatges amb l’idioma original i la traducció. També podem utilitzar les funcions de gettext dintre de php per a fer pàgines web amb diferents idiomes. Aquí teniu un exemple molt simple que ilustra l’ús de gettext amb php.

Creem una carpeta on posarem la informació dels diferents locales amb una subcarpeta per a cada locale. Per exemple si volem missatges en català i en castellà crearem la següent estructura de directoris:

# ./locales
# cd ./locales
# mkdir -p es_ES/LC_MESSAGES/
# mkdir -p ca_ES/LC_MESSAGES/

Ara creem el cataleg de missatges per al català. Creem el fitxer ./locales/ca_ES/LC_MESSAGES/messages.po amb el següent contingut:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid \"\"
msgstr \"\"
\"Project-Id-Version: PACKAGE VERSION\n\"
\"POT-Creation-Date: 2003-03-18 10:52+0400\n\"
\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n\"
\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n\"
\"Language-Team: LANGUAGE <LL@li.org>\n\"
\"MIME-Version: 1.0\n\"
\"Content-Type: text/plain; charset=UTF-8\n\"
\"Content-Transfer-Encoding: 8bit\n\"
	
msgid \"The string must be here\"
msgstr \"La cadena ha d'anar aquí\"
	
msgid \"This is a test\"
msgstr \"Això és una prova\"

NOTA: Això és una plantilla, amb valors per defecte, però per a l’exemple ja serveix. Si ho preferiu podeu utilitzar editors específics per a fitxers PO com poedit o KBabel.

És important especificar correctament el charset a l’arxiu .po, en el meu cas he utilitzat UTF-8 per que és charset que utilitzo en el servidor web. Si teniu problemes amb els accents proveu amb ISO-8859-15.

Un cop hem creat el PO amb els missatges que volem traduir hem de compilar-lo, per crear un arxiu .mo. Això ho farem amb la següent comanda:

# msgfmt -v messages.po
2 translated messages.

Cal tenir en compte que cada cop que canvieu el PO per afegir-hi algún missatge tindreu que recompilar el MO.

Podeu repetir el procés per al locale amb castellà. Un cop finalitzat anem a utilitzar gettext desde PHP. En aquest exemple imprimirem els dos missatges que tenim al catàleg amb català, castellà i anglés.

<?
// Especifiquem la ubicació de les translation tables
bindtextdomain(\"messages\", \"./locale/\");
	
// Especifiquem el locale en Català
setlocale(LC_ALL, 'ca_ES');
	
// Imprimim els missatges
echo gettext(\"This is a test\");
echo _(\"The string must be here\");
	
// Especifiquem el locale en Castellà
setlocale(LC_ALL, 'es_ES');
	
// Imprimim els missatges
echo _(\"This is a test\");
echo gettext(\"The string must be here\");
	
// Especifiquem el locale en Anglés
setlocale(LC_ALL, 'en_US');
	
// Imprimim els missatges
echo gettext(\"This is a test\");
echo _(\"The string must be here\");
	
?>

Fixeu-vos que en l’exemple he utilitzat indistintament la funció gettext() i la funció _(), que és un àlias de la primera, més còmode d’utilitzar.

Si voleu aprofundir més en aquest tema podeu consultar el manual de gettext i en la documentació de php.

Update:Tal com comenta adobo es pot generar el .po automàticament amb la comanda xgettext -a -n --from-code=utf-8 *.php, o amb intltool-update.

This entry was posted in linux. Bookmark the permalink.

8 Responses to Usant gettext amb php

  1. Iván says:

    Por si a alguien le sirve, yo para el desarrollo de paginas web en varios lenguajes suelo crear un fichero para cada lenguaje: es.inc.php, cat.inc.php, en.inc.php.
    Despues en la pagina pongo unos png chiquititos con las tipicas banderitas para la seleccion de idioma, y las enlazo a una pagina que activa una cookie. Segun la cookie que haya activado el cliente incluyo un fichero u otro.

    Si se quiere hacer que un lenguaje sea por defecto segun el idioma que utilice por defecto el navegador, se puede hacer recogiendo la variable HTTP_ACCEPT_LANGUAGE de apache y parseandola con un simple substr().

    No es tan elegante como gettext, pero para los que no sabemos demasiado tambien va bien y aparte no hay que compilar nada :-)

  2. melmak says:

    Vaya!
    Me parece muy interesante el tema. Lo que yo he hecho en http://homesitemaker.no-ip.org, es más parecido a lo que hace pof que a lo que hace ivan, si bien el método de pof me parece más simple y sostenible y administrable que el mio.
    Lo que hago es definir el idioma en el archivo de configuración del site. Luego, en base a eso utilizo las variables de unos ficheritos de idioma. Tengo un directorio para cada lenguaje y luego alli un ficherito con los mensajes en variables.
    El nombre de los ficheros sigue un patrón que me permite incluirlos fácilmente en cada uno de los archivos con mensajes a traducir. De esta manera, cada .php susceptible de vomitar texto por pantalla, hace un include de su fichero de idioma.
    Los problemas de este método están claros: Por un lado, el código se vuelve más bonito pero más complicado, pues en lugar de ver los mensajes de texto veo variables. En segundo lugar, las modificaciones se hacen por triplicado en ficheros distintos, castellano, ingles y catalán. Por otra parte, es dífícil reutilizar textos cuando estos aparecen en ficheros diferentes o bien cuando hay muchas variables, ya que te has de dar cuenta (con mi limitado cerebro de humanoide) si ya has puesto un texto y lo puedes rehutilizar (reduciendo asi el número de variables) o no.
    Bueno, en cualquier caso tomo nota y no descarto migrar la actual implementación a una solución basada en gettext que es, a todas luces, mucho mas pofesioná!
    Salu2!

  3. Iván says:

    Melmak, permiteme decirte que segun tu explicacion lo que haces se parece muchisimo mas a lo que hago yo. EN lugar de meter el fichero en un directorio para cada idioma, eso si, yo los tengo todos juntos en un directorio locale/ o language/.
    Y luego el nombre de cada fichero identifica el lenguaje al que responde (es.inc.php, en.inc.php…).
    Simplemente la eleccion del lenguaje genera una cookie con el lenguaje que uses. Por ejemplo para que te hagas una idea:

    setcookie(“langcookie”,”es”);

    Luego simplemente la recojo desde los php’s que contienen lineas de texto asi:

    $setlocale=$_COOKIE[‘langcookie’]
    include ($langdir.”/”.$setlocale.”.inc.php”);

    es muy muy facil.

  4. Iván says:

    joder con los guioncitos bajos, a veces se los come y en su lugar escribe en cursiva… maravillas de wordpress 😛

  5. pof says:

    Yo creo que elegir una solución u otra depende de la magnitud del proyecto… yo por ejemplo en el wapmail también lo hice con ficheros de idioma, usando un array; pero las soluciones de este tipo a la larga se suelen hacer inmantenibles, sobre todo si el proyecto crece, por eso si vais distribuir vuestro proyecto es mejor usar gettext.

  6. melmak says:

    vaaaaale! Aceptamos barco ivan. Lo que pasa es que no he debido entender muy bien en que se basaba tu solución.
    En cualquier caso, creo que para proyectos que puedar terminar siendo de una determinada envergadura, gettext parece ser, IMHO, la solución más indicada.Salu2!

  7. adobo says:

    Hola, me he fijado en que no has usado xgettext para extraer las cadenas, que creo que es mucho más cómodo. Así te ahorras el escribir a mano todas las cadenas que existen en tu código.

    Incluso hace poco descubrí un alguna utilidad para este asunto, intltool-update, aunque aún estoy haciendo pruebas con ella. Se puede ver un ejemplo de uso en gajim (http://www.gajim.org).

    Saludín!

  8. pof says:

    Tienes razón, he actualizado el artículo y he puesto como hacerlo con xgettext y he enlazado tu artículo donde hablas de intltool-update, que por cierto me parece muy cómodo y no lo había usado nunca. 😉

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>