Colabora
   

Clases para aplicaciones multi idioma

 

Fecha: 18/Mar/2008 (12-03-08)
Autor: Juan Miguel Molina Guzmán

 


Introducción

En este artículo voy a presentar un grupo de clases que permiten la gestión de conjuntos de idiomas para la interacción de nuestras aplicaciones con el usuario.

Dentro del conjunto de clases proveedoras tendremos dos tipos de clases, la clase base que define e implementa la funcionalidad común del proveedor y las clases derivadas que contienen la implementación específica de cada origen de datos.

En el proyecto he implementado dos clases herederas a modo de ejemplo, una obtiene los datos de un fichero de recursos del proyecto o de una librería y la otra los obtiene de un fichero XML. Yo he hecho estas dos clases, pero se podrían crear clases que recuperaran la información desde casi cualquier origen, como una base de datos, ficheros de texto o binarios… siendo totalmente compatibles entre ellas gracias a que todas heredan de la misma clase base.

 

Las cadenas de idioma

Las cadenas de idioma son un conjunto identificador/mensaje que compondrán los diferentes idiomas, siendo el identificador, como su nombre indica, la clave que representará al mensaje; y el mensaje será el texto en el idioma correspondiente. Las claves son comunes a todos los idiomas, los mensajes son específicos de cada uno.

Para que esta implementación sea funcional, además de permitir obtener una cadena en diferentes idiomas también nos tiene que permitir incrustar información en esa cadena; de eso se ocupan los parámetros de la cadena.

Los parámetros de la cadena toman la forma @[número de parámetro], por ejemplo @0,@1,@34. Entonces una cadena con parámetros incrustados quedaría así: “Son las @0”. Un parámetro se puede repetir tantas veces como queramos.

Estos parámetros siempre tienen que empezar por el parámetro 0 y deberán seguir en orden ascendente; esto es debido a que el valor que tomarán esos parámetros se pasa a través de un array de cadenas, entonces cada parámetro tomará el valor de la cadena situada en la posición correspondiente del array.

string[] valores = { “pera”,”limón”,”naranja” };

string mensaje = “El elemento 0 del array es @0, el 1 es @1 y el 2 es @2”;

Al proceso de unir los parámetros y la cadena lo llamo componer la cadena, y lo realizará la clase base del proveedor de idioma; una vez compuesta la cadena con sus parámetros quedaría así:

“El elemento 0 del array es pera, el 1 es limón y el 2 es naranja”

 

La clase ProveedorIdiomaBase

Esta es la clase base, contiene todas las definiciones de los miembros comunes y la implementación de los elementos que son independientes del origen de datos.

El funcionamiento de esta clase es muy sencillo, tiene un enumerador que recibe como parámetro el identificador a recuperar, y devuelve el texto del mensaje asociado a ese identificador en el idioma del proveedor. La búsqueda se realiza a través de la función protegida BuscaMensaje, esta función se implementará en las clases herederas.

Esta clase también implementa la función ComponCadena, que se ocupa de sustituir los parámetros de las cadenas por sus valores correspondientes, esta función es un poco extensa, pero básicamente lo que hace es recorrer la cadena y cuando encuentra una @ comprueba si esta va seguida por otra @, en este caso la ignora y continua, en caso de que lo que haya a continuación sea un número lo recupera e inserta en esa posición el texto contenido en la posición del array indicada por ese número.

Miembros de la clase ProveedorIdiomaBase:

public abstract class ProveedorIdiomaBase
 {
     public bool ActivarExcepciones
 
     public string Idioma
     
     public string Version

     protected abstract string BuscaMensaje(string Identificador);

     public string this[string Identificador]

     public string BuscarYComponer(string Identificador, string[] Elementos)

     public string ComponCadena(string Cadena, string[] Elementos)
  }

 

Las clases ProveedorIdiomaFichero y ProveedorIdiomaRecursos

Hasta ahora todo lo que tenemos está muy bien, pero nos falta lo más importante; la forma de acceder y recuperar los mensajes desde diferentes orígenes. De esto se ocupan estas dos clases, que lo único que contienen es el código necesario para acceder al origen de datos y la implementación de la función BuscaMensaje.

La primera recupera los datos de un fichero XML y la segunda de un fichero de recursos de .Net.

Miembros de ProveedorIdiomaFichero:

public class ProveedorIdiomaFichero : ProveedorIdiomaBase
{
    private struct LineaIdioma
    {
        public string idMensaje;
        public string Mensaje;
    }

    private List<LineaIdioma> Mensajes = new List<LineaIdioma>();

    protected override string BuscaMensaje(string Identificador)
   
    public ProveedorIdiomaFichero(string Fichero) : base()
}

Miembros de ProveedorIdiomaRecursos:

public class ProveedorIdiomaRecursos : ProveedorIdiomaBase
{
    public ResourceManager GestorRecursos

    protected override string BuscaMensaje(string Identificador)

    public ProveedorIdiomaRecursos(ResourceManager Gestor) : base()
}

 

Utilizando las clases

//Objeto de tipo base, así podremos intercambiar los diferentes orígenes
//en caso de ser necesario
 ProveedorIdiomaBase Proveedor;

//Instanciamos el objeto utilizando una de las clases herederas
Proveedor = new ProveedorIdiomaRecursos(EjemploRecursos.Español.ResourceManager);

//Creación de un array de parámetros con el valor de la fecha actual
//y la hora actual
string[] P1 = { DateTime.Now.ToShortDateString(),  DateTime.Now.ToShortTimeString()};

//Composición y asignación de la cadena
label1.Text = Proveedor.BuscarYComponer("M_Hora", P1);

Hay un ejemplo más detallado en el proyecto, en el formulario Ejemplo.cs.

Nota:
Para que el programa de ejemplo no de problemas hay que copiar el fichero idioma.txt de la carpeta del proyecto a la carpeta donde se encuentre el ejecutable de la aplicación

Nota:
En el proyecto hay un ejemplo de fichero de recursos en idioma "inglés", las traducciones casi seguro que están mal; pero bueno, lo que importa es el código ¿no? ;-)


Espacios de nombres usados en el código de este artículo:

System.Windows.Forms
System.Collections.Generic
System.Diagnostics
System.Resources
System.IO
System.Xml

 



Compromiso del autor del artículo con el sitio del Guille:

Lo comentado en este artículo está probado (y funciona) con la siguiente configuración:

El autor se compromete personalmente de que lo expuesto en este artículo es cierto y lo ha comprobado usando la configuración indicada anteriormente.

En cualquier caso, el Guille no se responsabiliza del contenido de este artículo.

Si encuentras alguna errata o fallo en algún link (enlace), por favor comunícalo usando este link:

Gracias.


Código de ejemplo (comprimido):

 

Fichero con el código de ejemplo: Jumimo_AplicacionesMultiIdioma.zip - 26.00 KB

(MD5 checksum: C9252A1DEFC68233F20C973ABE34B961)

 


Ir al índice principal de el Guille