Mostrando entradas con la etiqueta Internacionalización. Mostrar todas las entradas
Mostrando entradas con la etiqueta Internacionalización. Mostrar todas las entradas

miércoles, 23 de septiembre de 2009

Internacionalización (y III). Moodle.

En Moodle la corrección de los errores de internacionalización es mucho más sencilla, ya que se puede hacer directamente desde Moodle como administrador y que, además, habitualmente se trata de literales que no se encuentran en los ficheros de recursos (o, como se prefiere en la terminología Moodle, paquetes de idioma).
El primer paso es instalar el o los paquetes de idiomas que nos interesen y, desde la administración del sitio, seleccionar la opción de edición del idioma, indicando con el que vamos a trabajar. La figura muestra un ejemplo para el idioma Español:

Una vez aquí, nos interesará saber qué literales están sin traducir. Para ello, seleccionaremos la opción de Revisar las cadenas (strings) perdidas, lo que nos llevará a la siguiente pantalla:

Y ahora viene en donde, en mi opinión, Moodle es superior a Sakai. Llega la hora de poner solución a las cadenas perdidas. Para ello, hay que ir a la opción de Editar palabras o frases y seleccionar, para los idiomas de interés, el módulo/bloque/actividad de Moodle que se quiera revisar. Automáticamente, aparece en pantalla un formulario en el que se muestran la frase original (en inglés) y una caja de texto en donde se nos pida que introduzcamos la traducción en el idioma deseado. La figura aclara estos conceptos:

Con los ficheros de ayuda, ocurre exactamente lo mismo. Desde el propio Moodle, el administrador puede traducir los ficheros para cada bloque/actividad y para cada idioma:

Como vemos, cuando el problema es que faltan literales en los paquetes de idiomas, en Moodle resulta mucho más sencillo cambiarlos que en Sakai. Sin embargo, si el error fuera que el texto está fijo en el código fuente, habría que parametrizarlo de manera muy similar.
En primer lugar, tendríamos que incluir el literal en los ficheros de los paquetes de idiomas. Para ello, abrimos el fichero de un módulo correspondiente al idioma por defecto (el inglés) e incluimos una nueva entrada. Por ejemplo, supongamos que hemos creado un bloque propio de nombre mibloque. Tendríamos que tener un fichero {moodle.root}/blocks/mibloque/lang/en_utf8/block_mibloque.php en el que incluyeran todas las cadenas que se muestran al usuario con el formato

$string['micadenadetexto'] = 'Aquí va el texto';


Una vez incluida esta entrada, cuando queramos mostrar al usuario esa cadena, debemos utilizar el siguiente código:

<?php print_string('micadenadetexto', 'block_mibloque'); ?>

martes, 15 de septiembre de 2009

Internacionalización (II). Sakai

En esta entrada vamos a ver con cierto detalle cómo internacionalizar una herramienta en Sakai. Podréis encontrar más información en la web de i18n de Sakai o la de Spanish Sakai, cuya visita os recomiendo.

Antes de empezar
Java proporciona utilidades estándar empleadas para cambiar el formato de número, de las fechas, etc. Siempre que sea posible, se usarán estas clases. En el tutorial sobre i18n que hay la web de Sun encontramos se explican estos aspectos con cierto nivel de detalle.

Los ficheros de recursos
Como dijimos en la entrada anterior, entenderemos por ficheros de recursos de internacionalización (de ahora en adelantate, solamente recursos) como aquellos ficheros que contienen los mensajes que se muestran al usuario y cuyo contenido varía dinámicamente en función de la información de contexto (habitualmente, el idioma seleccionado por dicho usuario). En el caso de Sakai, estos ficheros reciben la denominación genérica de location bundles y físicamente se corresponden con ficheros de texto con el formato nombre_etiqueta=valor guardados con la extensión .properties.

Un aspecto importante es el del orden. Tan sólo en una herramienta de Sakai pueden llega a haber varios cientos de literales y si no los organizamos con cierto criterio, estos ficheros pueden llegar a hacerse verdaderamente inmanejables. Un ejemplo de organización es el de la figura siguiente:

page.message.key = This is a message will be shown in page "page"



Es decir, el nombre del literal ofrece una referencia de la página a la que pertenece (page), del contenido del mensaje (message) y, por ejemplo, de la acción para la que sirve (key).

Otro aspecto importante relacionado con los ficheros de recursos es que no es necesario (ni recomendable) dividir una sola frase en varios literales únicamente porque algunas partes de dicha frase es variable, bien porque contiene parámetros, o bien para adarpar su estructura a la construcción gramatical de sujeto/verbo/objeto en los diferentes idiomas. Puede y debe dejarse todo en el mismo literal y construir el mensaje apropiado en cada idioma utilizando el método getFormattedMessage de org.sakaiproject.util.ResourceLoader.

Aclararemos este último punto con un ejemplo. Supongamos que el mensaje que queremos mostrar por pantalla un saludo personalizado para cada usuario:

Bienvenido a Sakai, David. Esperamos que disfrutes la experiencia.



El modo erróneo de hacerlo, sería

page.statement.1 = Bienvenido a Sakai,
page.statement.2 = . Esperamos que disfrutes la experiencia



En su lugar, el literal correcto sería:

page.statement.1 = Bienvenido a Sakai, {0}. Esperamos que disfrutes la experiencia



La clase ResourceLoader
Sakai proporciona una clase, org.sakaiproject.util.java.ResourceLoader, que actúa de envoltorio (wrapper) de java.util.ResourceBundle y que selecciona el Locale (idioma) con el que se cargan los ficheros de recursos según la siguiente orden:

  1. Preferencias de idioma del usuario

  2. Sesión del usuario

  3. Configuración del sistema (JVM)


El ResourceLoader se ubica en kernel-util de Sakai. Por ello, todas las herramientas que lo utilicen deben incluir en el lugar adecuado de su pom.xml la siguiente dependencia:

<dependency>
<groupId>org.sakaiproject.kernel</groupId>
<artifactId>sakai-kernel-util</artifactId>
</dependency>


Una vez hecho esto, cualquier literal podrá ser obtenido del fichero de recursos con el siguiente código JAVA:

ResourceLoader rl = new ResourceLoader("ruta_al_fichero_de_recursos");
String foo = rb.getString("page.statement.1");


Errores debidos a que faltan literales
En http://qa1-nl.sakaiproject.org/international/ está registrado cuál es el estado de traducción de ficheros de properties para distintas versiones de Sakai.
Generalmente, cuando nos encontramos un mensaje en inglés (el idioma por defecto), es porque el mensaje en cuestión no tiene literal asociado en el fichero de properties del idioma seleccionado. Cuando esto ocurre, Sakai carga el fichero en inglés y busca la clave en él.
Si éste es el caso, únicamente hay que copiar la línea del mensaje en inglés y traducir el mensaje al idioma deseado, dejando invariable eso sí, la clave.
Corrección de errores en una JSP/JSF
Una vez que está incluida la dependencia respecto de ResourceLoader, el paso siguiente es utilizar esta clase correctamente.
Una alternativa es cargar el fichero de recursos en el faces-config.xml de la herramienta como si se tratase de un bean más:

<managed-bean>
<description>
Dynamic Resource Bundle Loader
</description>
<managed-bean-name>msgs</managed-bean-name>
<managed-bean-class>org.sakaiproject.util.java.ResourceLoader</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<description>Bundle baseName</description>
<property-name>baseName</property-name>
<value>ruta_al_fichero_de_properties</value>
</managed-property>
</managed-bean>


Otra opción es incluir el bean directamente en la página JSP/JSF:

<jsp:useBean id="msgs" class="org.sakaiproject.util.ResourceLoader" scope="session">
<jsp:setProperty name="msgs" property="baseName" value="_org.sakaiproject.tool.foobar.bundle.Messages_"/>
</jsp:useBean>


Ahora supongamos que encontramos un error de internacionalización consistente en que siempre se muestra el mismo mensaje en pantalla, independientemente del idioma activo (es el más común). Seguramente, será porque en la página JSP/JSF que muestra el mensaje, encontraremos un fragmento de código similar a éste:

<h:outputText value="This is an English text">


Lo primero es detectar la JSP/JSF en la que está texto fijo y llevar este texto a los ficheros de properties, por ejemplo, paquete.de.mi.herramienta.Messages_xx:
  • Messages.properties -> sample_text = This is an English text

  • Messages_es.properties -> sample_text = Éste es un texto en inglés


Cuando lo hayamos hecho, solamente habrá que invocar al bean que haga referencia al ResourceLoader.
Corrección de errores en una VM
En las Velocity Templates, el proceso es muy similar alterior, salvo por el hecho de que ResourceLoader, en lugar de cargarlo en un fichero de configuración (faces-config.xml) o directamente en la página (con la directiva jsp:useBean), se carga en el contexto de la plantilla:

ResourceLoader rb = new ResourceLoader("ruta_al_fichero_de_properties");
context.put("tlang", rb );


Para, posteriormente, poder hacer referencia al mismo de las páginas vm:

$tlang.getString("page.sentence.1");


Corrección de errores en el código JAVA

Cuando el literal se encuentra inmerso en el código JAVA, el proceso es algo más complejo.
El primero paso será detectar en qué clase JAVA se encuentra el gazapo. Para ello, podemos utilizar cualquier herramienta que busque en el contenido de un fichero.
Seguidamente, habrá que incluir en el mensaje en los ficheros de recursos correspondientes.
Hecho esto, nos quedan dos cosas:
  1. Cargar dinámicamente el fichero de recursos en función de las preferencias de idioma del usuario. Esto se consigue importando la clase org.sakaiproject.util.ResourceLoader e indicando el fichero de recursos.

  2. Construir el mensaje con la cadena obtenida por el ResourceLoader.


Llegados a este punto, si desplegamos y volvemos a la herramienta veremos que se ha solucionado.
Os propongo que detectéis uno error de este tipo y lo intentéis solucionar. Yo estaré encantado de asistiros en el proceso. Tan sólo tenéis que preguntar. Eso sí, os pediría que, por favor, si encontráis algún error, lo indiquéis en el JIRA, el sistema de bugtracking de Sakai.

viernes, 11 de septiembre de 2009

Internacionalización (I). Problemas.

La internacionalización, también llamada i18n, según la Wikipedia puede definirse como "el proceso de diseñar software de manera tal que pueda adaptarse a diferentes idiomas y regiones sin la necesidad de realizar cambios de ingeniería ni en el código". Se trata de un concepto muy amplio que abarca desde ser capaz de modificar dinámicamente los mensajes mostrados al usuario (por defecto, suelen estar en inglés) hasta mostrar la interfaz construida de derecha a izquierda como ocurre en los países árabes, pasando por tener en cuenta las costumbres regionales a la hora de presentar los iconos, por ejemplo.
Como dijimos al hablar de los criterios de selección de plataformas, la i18n es uno de los fundamentales sobre en todo países o regiones con diversidad lingüística en donde se dispone de varios idiomas oficiales. Si éste es el caso, una vez seleccionadas las herramientas que se pondrán a disposición de los usuarios, resulta imprescindible probarlas concienzudamente en los idiomas requeridos, haciendo especial hincapié en los problemas de internacionalización más comunes y que, a modo de resumen, son los siguientes:

  1. Mensajes de la interfaz de usuario: lo habitual es que los mensajes mostrados en la interfaz de usuario estén contenidos en ficheros de texto, tal y como ocurre en Moodle (paquetes de idiomas) y en Sakai (ficheros de properties). Sin embargo, puede ocurrir que nos encontremos con alguna herramienta en la que aparecen en inglés independientemente del idioma seleccionado. Esto, generalmente, se debe a alguno de los dos siguientes errores de i18n:
    • El mensaje en cuestión es incluido "tal cual" en el código fuente: en este caso, habrá que editar el código fuente y parametrizarlo adecuadamente, incluyendo el mensaje problemático y su correspondiente traducción en un paquete de idioma (caso de Moodle) o en un fichero de properties (caso de Sakai)

    • El mensaje está el fichero de recursos en inglés pero no en el del idioma seleccionado: la solución es muy sencilla y consiste en incluir la traducción del mensaje en el fichero del idioma seleccionado.


  2. Las listas de nombres (por ejemplo, alumnos) no se ordenan correctamente: desgraciadamente, éste es uno de los problemas más comunes. Se debe a las diferencias en el esquema de codificación esperado por la plataforma. Por este motivo, se recomienda utilizar UTF-8, juego de caracteres que contiene todos los símbolos de nuestro entorno.

  3. Formato de los calendarios: el día considerado como comienzo de la semana varía de unos países a otros. Por ejemplo, en España se considera que la semana comienza en Lunes mientras que en los países de habla sajona, convierten al domingo en su primer día semanal.
    En esta misma línea conviene revisar el formato de fechas, ya que algunas aplicaciones fallar con formatos de fechas diferentes del que tienen por defecto. La solución pasa por parametrizar el formato de las fechas y, en caso de no ser posible, por hacer una conversión del formato del usuario al formato con el que trabaja la herramienta.

  4. Formato de los números:hay que tener cuidado con la separación entre la parte entera y la parte decimal. Mientras que en España se emplea la coma como separador, en los países sajones se utiliza el punto. La solución es formatear los números en función del idioma seleccionado o bien incluyéndolo como un parámetro más de la instalación.

  5. Información de estado: este tipo de información debe ser independiente del idioma. Si no lo fuera, podría ocurrir, por ejemplo, que un mensaje de un foro apareciera en la carpeta de mensajes "Received" cuando se está visualizando en inglés pero no lo hiciera en la carpeta "Recibidos" al verlo en español. La solución suele ser almacenar en base de datos un código de estado y mostrar por pantalla una descripción del mismo consultando los ficheros de properties o los paquetes de idiomas correspondientes.

  6. Aplicaciones que están internacionalizadas pero toman el idioma del navegador o del servidor de aplicaciones y no permiten al usuario modificarlo dinámicamente: como ejemplo, algunas aplicaciones de Sakai basadas en Spring (algunas páginas de Samigo, por ejemplo) usan el idioma del Tomcat. E internet está lleno de formularios web que toman el del navegador (contribución de Daniel Merino Echeverría).


En la próxima entrada aprenderemos a comprobar el estado de la internacionalización en Sakai y en Moodle. Nos vemos la semana que viene.