18 de Septiembre, 2004

Internacionalización web fácil con PHP

Más de una vez he tenido que hacer una página web con soporte para varios idiomas. Lamentablemente solo una de esas veces tuve disponible gettext, que es una gozada.

Pero bueno, hay un par de alternativas bastante sencillas que, con un rendimiento aceptable, permiten escribir la página una vez y tener n idiomas.

La más cómoda es jugar con includes y un vector asociativo. Supongamos que nuestro principal idioma de desarrollo es el castellano. Creamos un es.inc.php:

<?php

$i18n=array(
  "Quiénes somos" => "Quiénes somos",
  "Servicio" => "Servicio",
  "Empresa" => "Empresa",
  "Contacto" => "Contacto"
);

?>

Esta variable debe ser global y la emplearemos en lugar de las cadenas propiamente dichas:

echo "<p>" .$i18n["Quiénes somos"] ."</p>\n";

Así solo es necesario traducir el es.inc.php a los distintos idiomas. Por ejemplo en.inc.php:

<?php

$i18n=array(
  "Quiénes somos" => "About us",
  "Servicio" => "Services",
  "Empresa" => "Company",
  "Contacto" => "Contact"
);

?>

Como vemos es fácil. Si en lugar de incluir delante de las páginas el fichero con las cadenas en castellano, incluimos éste, tendremos que la página ya está en inglés.

Ahora solo hay que seleccionar qué idioma, qué include, mostrar al comienzo de cada página. Esto se podría hacer, por ejemplo, así:

<?php

session_start();

/* idiomas que soportamos */
$sup_lang=array("es", "en");

/* recogemos el valor almacenado, de haberlo */
if($_SESSION["lang"]!="")
  $lang=$_SESSION["lang"];
else  /* sino, a ver que nos dice el navegador */
{
  $cli_lang=explode(",", $HTTP_ACCEPT_LANGUAGE);

  /* es un poco lioso, pero no hay más remedio - ejemplo: */
  /* si el cliente indica 'es-es', seleccionaremos 'es' */
  /* en el momento que un idioma coincide, dejamos de buscar */
  for($i=0;$i<count($cli_lang) && !isset($lang); $i++)
    for($j=0;$j<count($sup_lang); $j++)
      if(!strncmp($cli_lang[$i],$sup_lang[$j],strlen($sup_lang[$j])))
      {
        $lang=$sup_lang[$j];
        break;
      }
}

/* podemos cambiar de lenguaje con un GET */
/* y esta decisión manda sobre lo que diga el navegador */
if($_GET["lang"]!="")
  $lang=$_GET["lang"];

switch($lang)
{
  /* por defecto hemos quedado que es castellano */
  default:
  case "es":
    include_once("es.inc.php");
    $_SESSION["lang"]="es";
  break;

  case "en":
    include_once("en.inc.php");
    $_SESSION["lang"]="en";
  break;
}

No es trivial, pero tampoco demasiado complicado. Con los comentarios el código queda bastante claro.

Se puede emplear un sistema basado en definiciones, pero a mi me parece menos claro luego el código. También podríamos emplear plantillas, pero si solo queremos soporte para varios idiomas, veo esta opción más eficiente.

Por último notar que la conversión para comenzar a usar gettext a partir de esta propuesta es relativamente fácil.

Anotación por Juan J. Martínez, clasificada en: php, programming.

Hay 2 comentarios

Gravatar

Gracias por el código que detecta el idioma preferido, me vendrá bien :)

Yo hasta ahora utilizaba variables normales de todo:

Por ejemplo en el ES.php:

$logout = "Salir";
$uploadafile = "Sube un Archivo";

Y despues hacía varias versiones para varios idiomas...

Por cierto, eso de usar acentos directamente en el código ¿no puede dar problemas? :S

por Toad, en 2004-09-18 17:10:25

Gravatar

Los acentos no dan problemas ni en comentarios ni dentro de cadenas de caracteres (lo cual es lógico; los comentarios no se ejecutan y las cadenas de caracteres son eso... incluidos acentos :D). Además, el juego de caracteres del servidor es el adecuado... así que no hay ninguna pega ni con la visualización de los fuentes.

por Juanjo, en 2004-09-18 17:34:17

Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.

Algunas anotaciones relacionadas: