Uno de los problemas que tenemos que resolver en el diseño de una aplicación o servicios de negocio es la internacionalización y localización de los mismos:

  • Por internacionalización entendemos todos los mecanismos que incluimos en nuestro desarrollo para poder adaptar la misma a cualquier lenguaje y país (incluso a un región).
  • Cada una de estas adaptaciones particulares sería la localización.

Un caso representativo serían los literales o etiquetas que aparecen en las pantallas. Lo normal es que el framework que estemos usando nos de un mecanismo basado en ficheros de propiedades (como por ejemplo Struts o Java Server Faces).  Así tendremos un fichero de propiedades con los literales para cada lenguaje. En este caso, al generar la pantalla se tiene en cuenta el lenguaje del usuario (que se obtiene normalmente de los parámetros que envía el navegador) y se compone dinámicamente la pantalla con los literales del idioma apropiado.

Aunque es lo más común y tal vez la mayoría de las aplicaciones se queda ahí, la localización no solo debe tener en cuenta los literales que salen en la pantalla. También tiene que tener en cuenta por ejemplo la ordenación alfabética de las listas. Seguro que a todos os ha pasado al rellenar un formulario, que en la lista de países “España” está en la posición de la “S”, justo donde estaría “Spain”. Evidentemente este es un error en la localización de la aplicación. También hay que tener en cuenta también las monedas, las imágenes, las máscaras de las fechas, las cifras numéricas, convenciones culturales, etc. etc.

Teniendo todo esto en cuenta, viene la pregunta clave:

¿donde se debe gestionar la internalización y localización de una aplicación o servicio?

Si tenemos una aplicación con una capa de frontal (con el interfaz de usuario) y una capa de lógica de negocio, parece de sentido común que se haga en la capa de frontal (precisamente la encargada de “relacionarse” con el usuario). Por otra parte, ¿tendría sentido que la lógica de negocio, el “core” de nuestro negocio, tuviese en cuenta el idioma de la persona que está  sentada detrás de la pantalla? Precisamente uno de los principios de una buena arquitectura debe ser que la lógica de negocio no sabe de presentación (no puede, por ejemplo, devolver código HTML para formatear la salida de los datos), incluso puede que no haya siquiera presentación si a esa lógica de negocio se invoca desde un servicio B2B.

Siguiendo este razonamiento, en un servicio B2B lo que importa es el código asociado a un literal (no el literal en sí mismo que puede estar en españo, en inglés o cualquier otro idioma). Por ejemplo, si nos estamos dando de alta en una página web con un formulario donde nos pide nuestro estado civil (soltero, casado, viudo, etc.) normalmente se suele asignar un código a estos campos (1,2,3,etc.). Sólo deberemos traducir estos estados al idioma correspondiente cuando lo vaya a leer una persona. Dicho en otras palabras:

a la lógica de negocio no le debe importar el idioma del usuario que está sentado delante de la pantalla. Simplemente porque puede que no haya usuario ni pantalla.

¿Como implementar esto?

Para los literales estáticos, normalmente los que aparecen como las etiquetas de los campos de un formulario es suficiente con usar el mecanismo que proporcionan los frameworks basado en ficheros de propiedades.Sin embargo éste tiene un inconveniente, es necesario empaquetar este fichero con el resto de la aplicación. Es decir, si queremos añadir un nuevo literal tendremos que añadirlo al fichero y volver a desplegar la aplicación. Si por requisitos de negocio necesitamos que sea el propio usuario el que pueda dar de alta nuevos literales esta claro que necesitamos un mecanismo mas dinámico que no implique un redespliegue de la aplicación.Una opción seria guardar estos literales en la base de datos. Pero no en la base de datos de negocio. No debemos mezclar datos “puros” de negocio con estos otros que se necesitan para presentar una pantalla al usuario. Podría ser entonces una base de datos de presentación, cuyo único objetivo es hacer corresponder un código que se maneja en la lógica de negocio con un literal, por ejemplo “1” para “casado”

Ventajas e inonvenientes

A continuación repasaremos las ventajas, y lamentablemente, los inconvenientes que plantea el gestionar la internacionalización en la presentación (el frontal) de la aplicación. Las ventajas serían las siguientes:

  1. Fácil incorporación de un nuevo idioma (localización).
    ¿Que pasaría si tenemos una aplicación para el español y queremos adaptarla al inglés?. Si tenemos los literales mezclados con la lógica y los datos de negocio. ¿cómo podríamos encargar a una empresa de traducción que nos haga la adaptación? ¿Tendríamos que pasarle el contenido de la base de datos de negocio?
  2. Simplificación de la lógica de negocio y del modelo de datos.
    La lógica de negocio no tiene que ocuparse de la adaptación del contenido a una localización. La lógica es igual para todos. También el modelo de datos se simplifica ya que no tiene que ocuparse de crear tablas para albergar la información del multidioma. La lógica de negocio, por lo tanto, se dedica a lo que tiene que hacer estableciendo una clara separación de responsabilidades (separation of concerns SoC)

Por contra tendríamos los siguientes inconvenientes y restricciones:

  1. Se debe procurar que un campo multidioma sea un tipo enumerado o catálogo, no es conveniente que sea de texto libre.
  2. Si es de texto libre no puede ser utilizado como criterio de búsqueda en el servicio de negocio. En todo caso, al servicio de negocio hay que pasarle el código.
  3. Si se desea buscar una palabra en el texto del campo, es necesario disponer de un indexador de texto en el frontal. Se hará una búsqueda con esa palabra en el indexador y obtendremos el código de ese literal.
  4. En la base de datos donde se guarden los literales para el frontal, es necesario establecer una longitud para este campo. Tiene que ser suficientemente grande para guardar todo tipo de literales. Quizás habría que tener un tipo CLOB para casos específicos.

¿qué se necesita?

Para la implantación de la lógica de negocio adiomática y la gestión completa de la internacionalización en el frontal, se necesitarán varias cosas, desde infraestructura hasta componentes software:

  1. Base de datos de literales.
    Se usará una base de datos para guardar los literales en los distintos idiomas. Esto dará más flexibilidad que los ficheros de propiedades “tradicionales”.
  2. Componente visual de frontal con la tabla de literales
    Cuando se está rellenando un campo que es multidioma, en un formulario de alta, es necesario que el usuario pueda introducir diferentes valores para diferentes idiomas. Este componente se puede implementar, por ejemplo, con una tabla de 2 columnas (idioma y texto del literal).
  3. Componente de consulta de literales.
    Proporciona las lógicas de datos para obtener el literal a partir del código
  4. Generador de códigos únicos.
    La base de datos debe ser única para todos los servicios de negocio. Por lo tanto es necesario establecer una clave única (tal vez pueda usarse el espacio de nombres del servicio de núcleo).
    Esto no aplicaría a:
    los enumerados o catálogos: pueden tener un código autogeneradolos
    literales de pantalla: podrían usar el nombre del paquete del código del flujo de navegación (éste debe ser único en toda la compañía)
  5. En los servicios B2B o destinados a aquellos clientes que no puedan acceder a la base de datos de literales, deberán encapsularse con una transformación del código al literal (del Servicio a la pantalla) o de código a código (de servicio a servicio).

Posibles escenarios que nos encontramos en el desarrollo de servicios de negocio y aplicaciones de frontal

Vamos a suponer que tenemos una aplicación que gestiona clientes:

  • Básicamente, alta, baja, modificación y consulta de clientes.
  • Para cada cliente tenemos un campo “observaciones” que queremos que sea multiioma.

Para los diferentes casos de uso tendríamos lo siguiente:

  1. Alta de cliente
    Cuando el usuario accede al campo observaciones, le tiene que salir un popup o desplegable. una especie de tabla con dos columnas. En la primera el idioma con el que quiere introducir el texto y a la derecha el campo para el texto propiamente dicho en el idioma correspondiente. Este usuario tendría que saber escribir el texto en todos los idioma requeridos. Si no, dejará las celdas en blanco.
    Cuando se da de alta el contenido del campo observaciones, se generará un código automáticamente y se insertarán los textos de los idiomas en la base de datos de literales (la clave de la fila, sería el idioma y el código)
  2. Modificación del cliente
    Es análogo al alta. Evidentemente antes hay que hacer una consulta.
  3. Baja de cliente
    Cuando se da de baja un cliente, se tienen que borrar todas las entradas para las observaciones (en todos los idiomas)
  4. Consulta
    • Si en los parámetros de consulta (el filtro) no interviene el campo Observaciones, se lanza la consulta de negocio. Como valor del campo observaciones, vendrá un código que se tendrá que traducir al literal correspondiente al idioma del usuario.
    • Si en los parámetros de la consulta interviene el campo Observaciones, la cosa se complica bastante. Por ejemplo, el usuario quiere consultar todos los clientes con la palabra “bueno” en las observaciones.Obviamente en el servicio de negocio no sabe qué es el literal “bueno”. Tendríamos primero que hacer la consulta en la base de datos de literales para obtener el código correspondiente y entonces hacer la consulta al servicio de negocio.
  5. Habría que incorporar también los literales (etiquetas en pantalla) que actualmente se guardan en un properties a la base de datos de literales. Cuando la aplicación arranca todos estos literales se leerán de una sola vez y se almacenarán en memoria.

Conclusión:

Hacer posible el principio de que la lógica de negocio debe ser independiente del idioma del usuario no es una tarea fácil. Se necesitan asumir una serie de restricciones en el uso de los campos multidioma. También se necesita cierta infraestructura (como una base de datos) y que el framework que usemos esté preparado para darnos esta funcionalidad

Comparte esta entrada…

Share

Anuncios