ASP.NET
Desarrollar aplicaciones MUI (Multiple User Interface).

Fecha: 17/Ago/2004 (16/Ago/04)
Autor: Ariel N. Menendez

 

 

En este artículo se tratan los conceptos fundamentales para realizar una aplicación que cumpla con las características propias de los sistemas multilenguaje. Para ello, se vera en detalle el uso de determinadas herramientas y técnicas para realizar una aplicación Web que nos permita ofrecerle a los usuarios la posibilidad de utilizar la aplicación en su idioma.

 

 

Contenido.

 

Introducción. 

Definir interfase de usuario.

Generar archivo de recurso .resx

Convertir archivo .resx a .resource.

Compilar ensamblado satélite con los archivos de recurso.

Poner todo en funcionamiento.

Conclusión.

 

 

Introducción.

 

Hoy día las aplicaciones en su gran mayoría son realizadas con el fin de abastecer un mercado global el cual trasciende las barreras idiomáticas, por lo tanto, es fundamental que los sistemas cumplan con ciertos requisitos indispensables para poder ser comercializados. Uno de esos requisitos, “el que más resalta a la vista del usuario, inicialmente”, es el idioma en que esta hecho el sistema. Para que una aplicación tenga éxito en un país extranjero, es necesario que esta cumpla ciertas reglas propias de la cultura donde será usado, como por ejemplo, que su interfase de usuario este traducida al idioma que se habla en el país, o aun más, que este traducida no solo en forma neutral, sino que por el contrario haga uso de modismos y características propias de una determinada región. También es fundamental que el sistema adecue el símbolo correspondiente a la moneda local como así también el formato de la fecha, y el calendario.

En el pasado, los mecanismos de internacionalización eran, “por llamarlos de alguna forma”, caseros. Los programadores ideaban sus propias formas de realizar los sistemas multilenguaje, como así también los procesos de conversión, lo cual llevaba a desestandarizar la forma de trabajar. Hoy día, el Runtime de .net posee medios para trabajar en conjunto con la configuración regional del sistema operativo de las maquinas cliente. Lo cual hace que el mecanismo de traducción de una aplicación sea transparente para el usuario final. En los siguientes capítulos veremos de qué manera .net es capaz de ayudarnos a realizar nuestra aplicación siguiendo un estándar, y además podremos comprobar, una vez implementado este mecanismo, lo fácil que resultara escalar la aplicación a cualquier tipo de idioma.

 

Nota: Cabe destacar que el manejo de internacionalización podría llegar a ser extenso si centrase es artículo en los fundamentos para realizar una aplicación multilenguaje. Como la idea del articulo es poder llevar a la practica una implementación de multilenguaje, me concentraré por sobre todas las cosas en su funcionamiento y no tanto en su teoría.

 

 

Definir interfase de usuario.

 

Dentro de lo que es la definición de interfase de usuario antes que nada, es necesario tener en cuenta la forma en que estará constituida la interfase. Cuando me refiero a la forma en que estará constituida no me refiero  al aspecto gráfico, sino a cual será el texto que la constituirá, las imágenes que tendrán información relacionada al lenguaje, y los inputs que contendrá el formulario.

 

Nota: Respecto de las imágenes solo deben ser tomadas en cuenta  aquellas que posean texto que debe ser traducido o gráficos correspondientes a una determinada región.

 

 

 

 

En la imagen anterior podrán observar el listado correspondiente a la página NewUser.aspx en la cual los campos a traducir, serán equivalentes a los campos que contendrá el archivo de recurso para dicha pagina.

 

 

 

 

Observen la relación entre el archivo de Excel creado anteriormente y el formulario de la pagina .aspx, notarán que el listado de campos se corresponde perfectamente con la ubicación de los campos en el formulario. Como antes les había mencionado el listado en Excel nos va a servir para saber ubicar un valor dentro del archivo de recursos. Por ejemplo supongamos que queremos obtener el valor en castellano del campo name, lo que tenderíamos que hacer es buscar el campo “default_name” dentro del archivo de recursos, lo cual nos traería como resultado su valor. Igualmente no nos adelantemos, esto que les estoy tratando de explicar ahora lo voy a profundizar más adelante para que quede realmente claro. Por ahora, solo tengan en cuanta que es necesario realizar este listado para luego poder trabajar mejor.

 

Bueno, una vez realizado nuestro draft de las páginas, y armado el listado con los campos que deberán ser traducidos, podemos pasar al siguiente paso, el cual consiste en armar los archivos de recursos. Estos archivos que ya he nombrado en tantas oportunidades son para mantener el listado de toda aquella información que se corresponde con una cultura en particular.

 

Nota: me refiero a “Cultura”, porque como antes mencioné, la idea de hacer un sistema “multilenguaje” no solo implica que el sistema deba ser traducido de una lengua a otra en particular solamente, el hecho de realizar el cambio, también incluye otros aspectos antes mencionados, como puede ser el uso de modismos dentro de un mismo lenguaje para una región determinada, el uso de un código de moneda diferente, o el uso de un calendario diferente. Por eso es que los sistemas en realidad en lugar de ser consideramos multilenguaje deben ser considerados multicultural.

 

 

Generar archivo de recurso .resx

 

El archivo de recurso es un archivo en el cual se pude guardar datos que se corresponden con cierta información que maneja un sistema, pero que no dependen específicamente de las clases que contiene lógica. Como por ejemplo, toda aquella información que hace a la presentación de los formularios del sistema y que en cierta medida se mantienen estáticos a lo largo de la vida de la  aplicación.

Los archivos de recursos, como ya se habrán dado cuenta, poseen la extensión .resx, esta extensión identifica a un recurso como tal. Dentro de estos archivos no solo se puede guardar cadenas de caracteres, sino que su alcance va mucho más allá. Lo que quiero decir con esto, es que mediante ciertos mecanismos como por ejemplo la serialización, también es posible guardar objetos que dependan de la cultura, y que además no dependan de una lógica de negocio, como así también se pueden guardar imágenes en binario.

 

Nota: para manipular archivos de recursos, .net cuenta con dos clases, ResXResourceWriter y ResXResourceReader. Como el fin de este artículo no es profundizar en el uso de estas clases, no será ampliado el tema.

 

Los archivos de tipo .resx internamente están constituidos por una estructura XML y un esquema (XSD) en línea. Esta estructura puede ser realizada a mano sin ningún inconveniente, pero para que sea valida es necesario cumplir con todos sus requisitos, por lo tanto el IDE de .Net nos brinda la posibilidad de manipular sus datos en forma grafica, y de esta manera nos podemos evitar cualquier error que pudiésemos llegar a cometer.

 

Para crear un archivo de recursos es necesario, crear un proyecto vacío y desde el “explorador de soluciones” hacer un clic con el botón derecho del ratón sobre el proyecto, seleccionar “Add”, y luego “Add New Item”.

 

 

 

Al realizar estos pasos se nos presentará un cuadro de diálogo en el cual podremos seleccionar la opción de  agregar un “archivo de recurso” a nuestro proyecto.

 

 

Noten que el archivo de recursos se encuentra caratulado “Assembly Resource File”. Una vez creado el archivo de recursos, se nos cargará una grilla en la IDE, esta grilla es la que nos va a permitir cargar nuestra información, para luego ser consultada por la aplicación, teniendo en cuenta el idioma que el usuario requiera.

 

 

La grilla del archivo de recursos esta compuesta por cinco columnas, de las cuales solo dos serán utilizadas para cargar los datos que hagan referencia a los campos correspondientes a los formularios de las páginas.

 

Los campos a utilizar son:

Name: en este campo se ingresara el nombre del campo por el cual se consultará el valor del recurso. Este dato provendrá de los datos cargados en la planilla de Excel, como lo habíamos explicado anteriormente.

 

Value: en este campo irá el valor que será mostrado en la interfase de usuario, producto de haber consultado el campo name.

 

Nota: es importante aclarar que los archivos de recursos se corresponden el idioma que se este usando, por lo tanto si la aplicación trabaja con dos idiomas es necesario crear dos archivos de recursos.

 

Ej.:

 

name

value

comment

type

Mimetype

NewUser_name

Name

 

 

 

NewUser_LastName

Lastname

 

 

 

NewUser_Address

Address

 

 

 

 

Este ejemplo representa un archivo de recursos para el idioma ingles.

 

name

value

comment

type

Mimetype

NewUser_name

Nombre

 

 

 

NewUser_LastName

Apellido

 

 

 

NewUser_Address

Dirección

 

 

 

 

Este ejemplo representa un archivo de recursos para el idioma español.

 

 

Noten que en las dos tablas anteriores lo único que cambia son los valores que serán mostrados al usuario en las páginas, el resto se mantiene exactamente igual.

 

Una vez finalizada la carga de los datos correspondientes a cada uno de los idiomas, es necesario grabar estos archivos en ubicaciones distintas de una estructura de directorio, puesto que como he mencionado antes estos archivos solo se diferencian por el valor de retorno que se obtendrá de ellos, el resto es todo igual, o sea que los dos tendrán el mismo nombre.

 

Para guardarlos se debe seguir una nomenclatura estándar respecto del directorio donde quede alojado el archivo de recursos, (esta forma de estructurar la información nos será útil para luego realizar la aplicación que utilice los recursos), la cual hacer referencia al leguaje y el país.

 

Respecto de la nomenclatura antes mencionada es preciso asignar estos nombres estandarizados puesto que el CLR se maneja con ellos para trabajar en lo que refiere al manejo de la Cultura de las aplicaciones.

El motor de tiempo de ejecución identifica a un recurso por su nombre el cual esta compuesto por un nombre único. Dicho nombre esta constituido por una referencia cultural asociada a un idioma el cual esta compuesto por dos caracteres en minúscula y una subreferencia cultural que esta compuesta por dos caracteres en mayúscula asociado a un país o región. Estas dos referencias que mencione anteriormente son las que definen una referencia cultural, la cual además de estos dos códigos también posee un guión (-) el cual separa una referencia de otra.

 

Un ejemplo de una referencia cultural seria: es-AR donde es estaría representando al idioma “Español” y AR estaría representando al país “Argentina”.

 

Por lo tanto, y volviendo al tema en cuestión de este capitulo, la idea seria, crear para cada uno de nuestros archivos de recursos un directorio que haga referencia a la “Cultura” que queramos representar.

 

 

 

 

El grafico mostrado arriba representa el directorio raíz del proyecto donde se encontraría el assembly correspondiente al Code-Behind de las páginas .aspx (esto es equivalente al directorio bin), y los subdirectorios con la referencia cultural correspondientes a (Ingles/EEUU) y (Español / Argentina).

 

Nota: esta forma de organizar los recursos dentro del proyecto debe ser así y solo así, puesto que esta es la única forma en la cual el CLR podrá ubicar los recursos.

 

Una vez realizado los archivos de recurso correspondiente a cada idioma debemos preparar dichos archivos para que puedan ser insertados en los assemblies satélite.

 

 

Convertir archivo .resx a .resource.

 

 

En primer lugar, antes de ver de que manera podemos convertir un archivo .resx a un archivo .resource, es necesario explicar el motivo por el cual es necesaria esta conversión.

 

Como ya he mencionado varias veces, los recursos se almacenan en ensamblados satélites, dichos ensamblados a diferencia del resto, no contienen lógica ejecutable, por lo tanto solo están pensados para contener información inherente al sistema (recursos). Esta información es la que inicialmente almacenamos en los ya conocidos archivos de recursos. Como ya hemos visto anteriormente los archivo de recursos que guardan la información son de tipo .resx; el problema con este tipo de archivo es que no se pueden embeber en ensamblados satélite, por lo tanto, para poder hacerlo es necesario convertir dichos archivos a un formato que sea admitido por los ensamblados satélite. Este formato es “.resorces”. Para poder realizar tal conversión se utiliza una herramienta que provee el SDK de .Net llamada (Resgen.exe).

 

Aunque sea posible realizar la lectura de recursos sin necesidad de embeber los archivos de recursos en ensamblados satélite para la tecnología ASP.NET no es aconsejable realizar la lectura directamente puesto que esto podría llegar a causar problemas de bloqueo y por lo tanto interrumpir la implementación de XCOPY para realizar la actualización de dichos archivos.

 

Nota: XCOPY es un proceso por el cual es posible actualizar versiones de assemblies sin necesidad de cortar el funcionamiento de la aplicación.

 

A continuación mostraremos de qué forma se realiza la conversión de un formato a otro con la herramienta Resgen:

 

En primer lugar es necesario haber creado el archivo de recurso .resx el cual debería estar almacenado en el directorio correspondiente a su referencia cultural. Ej.: C:\proyecto\en-US\myResource.resx.

 

Una vez que tengo creado y cargado con la información necesaria el archivo de recursos, es necesario abrir una consola DOS. Desde la consola DOS es necesario llegar hasta la carpeta que contiene nuestro archivo .resx, una ves que nos encontramos ahí debemos ejecutar el comando Resgen.exe de la siguiente forma:

 

 

 

La estructura para convertir de un formato a otro utilizando Resgen.exe es

Nombre de comando + archivo .resx + {archivo destino. + Referencia cultural + extensión .resources}

 

Es importante tener en cuenta que este procedimiento se debe cumplir con cada uno de los archivos de recursos creados para cada uno de las carpetas de definición cultural.

 

Una vez realizado esto, si observa las carpetas verá que ahora aparece un nuevo archivo en cada una de las carpetas con la indicación de su referencia cultural más la extensión .resources, este será el archivo que podremos embeber en el ensamblado satélite. Es importante recalcar que el formato propuesto para el nombre de los archivos de recurso debe ser respetado, de lo contrario, el CLR no podrá reconocerlo como archivo de recurso.

 

Nota: recuerden que .Net nos provee de una consola que nos permite ejecutar cualquier herramienta del SDK desde cualquier carpeta de la estructura de directorios, la cual se encuentra en “Start\All programs\Microsoft Visual Studio .Net 2003\Visual Studio .Net Tools\Visual Studio .Net 2003 Command Prompt”

 

 

Ahora ya estamos en condiciones de seguir con el siguiente paso, el cual consisten en crear el ensamblado satélite para comenzar a programar nuestra aplicación.

 

 

Compilar ensamblado satélite con los archivos de recurso.

 

Para realizar nuestro ensamblado satélite es necesario utilizar otra herramienta del SDK denominada al.exe (Assembly Linker) las cual nos permitirá crear dicho assembly y a su vez embeber el recurso correspondiente.

 

De la misma forma que con la herramienta Resgen.exe es necesario situarnos en la carpeta donde se encuentra nuestro, anteriormente creado, archivo de recursos .resources.

 

 

 

La estructura para la ejecución de al.exe es un poco más compleja que Resgen.exe. A continuación describiré los parámetros utilizados para realizar el ensamblado satélite:

 

/t:lib à este parámetro le indica al comando que lo que se obtendrá como output será una librería.

 

/embed à es el parámetro por el cual se le pasa al comando el archivo de recurso que será embebido en el ensamblado satélite.

 

Nota: es importante mencionar que si lo que se desea hacer es insertar mas de un archivo de recurso, la separación entre uno y otro se realizara mediante una coma (,). Ej.: /embed:MyResource.resources,MyResources2.resources.

 

/culture:”en-US”  à este parámetro le indica al comando al que el assembly satélite que se esta creando es para operar sobre la referencia cultural que se define. Este parámetro es esencial para la realización de assemblies que sean utilizados para manejo de cultura, puesto que si no se incluye el assembly será considerado sin referencia cultural y por lo tanto el CLR no podrá utilizarlo para el proceso de traducción. El código de referencia cultural debe ir entre comillas. Ej.: /culture:”en-US”.

 

/out: à este parámetro indica la salida, o sea, con que nombre será identificado el assembly que será generado, producto de haber utilizado la herramienta al.exe.

 

Nota: Noten que el assembly de recursos en la composición de su nombre posee también la palabra resources, (MyResource.resources.dll). Esta forma de nombrar el assembly al igual que el parámetro culture, es obligatorio, si no nombra sus assemblies satélites con referencia cultural de este modo, el CRL no los reconocerá y al momento de querer invocarlos el Runtime devolverá una excepción FileNotFoundException.

 

Una vez ejecutado el comando al.exe, si observan en las carpetas correspondientes a la referencia cultural verán que ahora aparece un nuevo archivo que representa una librería (.dll), este será el assembly que usaremos para trabajar en la aplicación que creemos.

 

Nota: es importante aclarar que, por cada referencia cultural, debe haber un assembly satélite que la respalde.

 

Poner todo en funcionamiento.

 

Una vez realizado los pasos anteriores, y habiendo obtenido los assemblies satélites necesarios para realizar nuestra aplicación, podemos dar comienzo a la programación de la misma. En primer lugar, como ya he mencionado anteriormente, es necesario tener definida la estructura de cómo va a estar conformado nuestro proyecto respecto de todo lo inherente al manejo de la cultura. Recuerden que es necesario que los assemblies satélites con referencia cultural se encuentren situados en la ubicación correcta para que el CLR los pueda identificar como tal, con el fin de utilizarlos al momento de realizar las operaciones necesarias para poder obtener los valores en el lenguaje correspondiente de acuerdo a la configuración regional del cliente.

 

Nuestra demostración será simplemente la realización de un formulario, el cual de acuerdo a la configuración regional que posea la estación de trabajo, mostrará los campos (inputs) a llenar en un idioma u otro.

 

Para comenzar con nuestro ejemplo inicialmente crearemos un proyecto “ASP.NET Web Application” denominado “MyMUITest”.

 

Nota: MUI es el acrónimo de “Multi User Interface”.

 

Una vez creada la aplicación Web podemos tomar las dos carpetas de cultura creadas anteriormente y copiarlas dentro de la carpeta “bin” de nuestro actual proyecto, Es en este sitio definitivamente donde quedarán ubicadas con el fin de ser utilizadas por el CLR.

 

Otro punto importante a tener en cuenta es que siendo que las aplicaciones Web pueden ser utilizadas desde cualquier parte del mundo, la cantidad de referencias culturales que podría llegar a necesitar una aplicación serian muchísimas, por lo tanto, dentro de las necesidades de un sistema con manejo de cultura se encuentra la necesidad de definirle al mismo un lenguaje por default, este leguaje puede ser un leguaje neutro a una referencia cultural especifica, como por ejemplo el ingles. Dentro de las estructuras antes mencionadas para lo que se refiere al manejo de la cultura de un sistema los lenguajes por default que no hacen referencia a un Cultura en particular deben tener alojado su assembly satélite en lo que seria el root de la estructura, o sea el assembly debería ser un archivo suelto dentro de la carpeta “bin”, por lo tanto, si la configuración regional de un cliente tuviese especificada una cultura la cual no esta contemplada dentro de nuestro sistema, el assembly satélite sin referencia cultural entraría en juego para ser utilizado como un lenguaje por default. Por lo tanto vamos a realizar nuestro assembly satélite sin referencia cultural, para ello es necesario tomar uno de los archivos de recurso – precisamente el archivo MyResource.resx  que se encuentra situado en la carpeta en-US y lo copiaremos a la carpeta bin.

Una vez que hayamos realizado la copia, vamos a editar el archivo, y en el campo donde va especificado el apellido del usuario, reemplazaremos la palabra Lastname por Surname (Esto nos servirá para poder notar la diferencia entre tener el assembly sin referencia cultural cargado contra el que si tiene referencia cultural). Luego de realizar la copia, y haber modificado el campo, procederemos a realizar el archivo de recursos .resources y posteriormente el assembly satélite.

 

Nota: la forma de realizar este ensamblado satélite es exactamente de la misma forma que fue explicado anteriormente, con la única diferencia de que a este ensamblado no se le debe especificar ninguna referencia cultural, o sea, el parámetro “/culture” en el comando “al.exe” no será usado, ni tampoco se le debe poner en el nombre del assembly la palabra “resources” como fue especificado en los assemblies satélites anteriores.

 

 

Forma de crear el ensamblado satélite sin referencia cultural.

 

 

Bueno, en este momento ya nos encontramos con toda la estructura completa y bien definida para poder programar nuestras páginas.

 

En primer lugar vamos a renombrar la página que nos crea el proyecto por default,  la cual nombraremos NewUser.aspx. Una vez realizado esto lo que vamos a hacer será insertar una tabla la cual usaremos como marco de nuestro formulario. La tabla estará conformada por 8 rows y 2 columns, el borde estará definido en 0.

 

Una vez creada la tabla insertaremos 7 textbox en la columna 2 comenzando de arriba hacia abajo. Y en la columna 1 ingresaremos un espacio precedido del signo de dos puntos (:) en cada una de las filas hasta llegar a la séptima.

 

Por ultimo, en la segunda columna de la tabla, en el último row, insertaremos un botón.

 

 

De esta forma debería ser el aspecto grafico de nuestro formulario en tiempo de diseño.

 

 

Una vez finalizado el formulario, presionamos F7 para pasar al “Code Behind” de nuestra página. En esta parte vamos a comenzar a definir la lógica que corresponde con el llenado de los campos del formulario. Lo que debemos hacer inicialmente, es crear un campo de tipo string con un modificador de acceso private para cada uno de los datos que serán cargados desde el assembly satélite.

 

Nota: si a esta altura ya se olvidaron el nombre de los campos, les sugiero utilizar el archivo de Excel que creamos al principio de nuestro artículo.

 

 


private string _name;
private string _lastName;
private string _address;
private string _state;
private string _country;
private string _phone;
private string _email;

 

 

Una vez realizado los campos, es necesario crear una propiedad para cada campo, la cual será de solo lectura, retornará un string y su  modificador de acceso será de tipo protected. Estas propiedades devolverán el valor que será cargado en los campos antes realizados.

 


protected string Name{get{return _name;}}
protected string LastName{get{return _lastName;}}
protected string Address{get{return _address;}}
protected string State{get{return _state;}}
protected string Country{get{return _country;}}
protected string Phone{get{return _phone;}}
protected string Email{get{return _email;}}

 

Luego de haber definido las propiedades, es necesario volver al formulario de la aplicación, pero en lugar de ver el formulario desde su diseño, pasaremos a ver directamente el código HTML presionando sobre el botón HTML situado en el margen inferior izquierdo de la ventada de trabajo.

Ahora bien, para poder mostrar los valores que fueron cargados en los campos privados del Code-Behind, es necesario realizar un “Bind” de los datos, y para ello utilizaremos las propiedades antes definidas, la cuales serán invocadas desde el formulario HTML de la siguiente forma:

 


<TABLE>
            <TR>
                        <TD><%#Name%> &nbsp;:</TD>
 
...

 

De esta forma, al cargar con datos los campos privados estos nos darán la posibilidad de transferir esa información a la interfase de usuario para luego ser mostrada al cliente.

 

El siguiente paso, es cargar los datos con la información que nos proveerá el assembly satélite correspondiente a la referencia cultural solicitada por el cliente.

Para ello, inicialmente lo que uno tiene que asegurarse es que aunque el ensamblado no coincida con la configuración regional del cliente, el sistema cargue el ensamblado satélite por default, por lo tanto, para ello, utilizaremos los eventos del global.asax en el cual inicialmente cargaremos dicho ensamblado en una variable de aplicación de la siguiente forma.

 


using System.Reflection;
using System.Resources;
using System.Threading;
using System.Globalization;
 
...
 
protected void Application_Start(Object sender, EventArgs e)
{
      Assembly a = Assembly.Load("MyResource");
      Application["RSM"] = new ResourceManager("MyResource",a);
}

 

En primer lugar, es necesario declarar los cuatro espacios de nombre que se  muestran en el cuadro anterior, en el global.asax. Estos espacios de nombre nos proveerán de las clases necesarias para poder trabajar un sistema MUI.

 

System.Reflection à referenciando este espacio de nombre tendremos acceso a la clase Assembly, la cual nos permitirá cargar nuestro asembly satélite por default, para ello, utilizaremos el método Load el cual espera que le pasemos una cadena representando el nombre del assembly a cargar.

 

System.Resources à este espacio de nombre nos permitirá utilizar la clase ResourceManager la cual es la encargada de leer la información almacenada en los archivos de recurso que posee el assembly satélite. Esta clase posee una sobrecarga en su constructor que recibe como parámetro, el nombre del recurso al que se quiere acceder (esto es porque como habíamos mencionada anteriormente un assembly puede contener mas de un archivo de recurso embebido), y el nombre de la variable de tipo Assembly que posee cargado el assembly satélite que utilizaremos.

 

System.Threading à con este espacio de nombre lo que podremos hacer es obtener el valor de la cultura que se encuentra seteada en el proceso actual, o sea en el proceso que se encuentra corriendo nuestra aplicación. Esto lo utilizaremos mas adelante para poder cambiar de cultura la aplicación, respecto de la configuración regional que posea el cliente.

 

System.Globalization à aquí es donde se encuentra la clase encargada del manejo de cultural de las aplicaciones.

 

Una vez que fueron cargados los espacios de nombres correspondiente, es necesario aplicar la lógica que nos permitirá cargar el assembly satélite que utilizaremos por default. Como ya habrán notado, el assembly por default será cargado al momento de ejecutarse el evento Application_Start de la aplicación. Por lo tanto dicho assembly será lo primero en cargar para asegurarnos que si la configuración regional del cliente no coincide con nuestro aseemblies satélite, por lo menos la aplicación contará con un ensamblado por default.

 

Una vez echo esto, y antes de continuar con la codificación de los assemblies correspondientes a una cultura en particular, veremos de que manera se puede obtener los valores de los recursos para cargar los campos privados que abastecerán a las propiedades que se encargarán de mostrar la información en pantalla. Por lo tanto, vallamos al Code-Behind de nuestra página denominada NewUser.aspx y a continuación en el método InitializeComponent agreguemos el evento “init” de la página de la siguiente forma.

 


private void InitializeComponent()
{    
      this.Load += new System.EventHandler(this.Page_Load);
      this.Init +=new EventHandler(WebForm1_Init);
}
...

 

Noten que en el constructor del delegado EventHandler se le pasa como parámetro el método WebForm1_Init, en este método es donde cargaremos nuestros campos privados para poder ser utilizados por las propiedades que decoran el formulario.

El método WebForm1_Init lucirá de la siguiente forma:

 


rm  = (ResourceManager)Application["RSM"];
 
_name       = rm.GetString("NewUser_Name");
_lastName   = rm.GetString("NewUser_LastName");
_address    = rm.GetString("NewUser_Address");
 
...
 
DataBind();

 

 

En primer lugar encontraremos un campo denominado “rm” el cual será declarado de tipo ResourceManager con un modificador de acceso private, como ya es de imaginarse su scope dentro de la clase será de tipo global puesto que esta declarado fuera del método. Noten que al momento de inicializar el campo con un valor, dicho valor es casteado a un tipo “ResourceManager”, esto es por que en el global.asax el objeto ResourceManager  fue cargado en una variable de aplicación la cual guarda al objeto de tipo “Object”, por lo tanto, para que lo podamos utilizar, es necesario convertirlo a su tipo original. Ha, otra cosa que me estaba olvidando decir, aquí  también es necesario declarar el espacio de nombre System.Resources, para poder trabajar con la clase ResourceManager.

 

Una vez inicializado el campo rm  ya estamos en condición de cargar los valores del archivo de recurso a los campos. Para ello se utilizara el método GetString del objeto rm, el cual recibe como parámetro el nombre del campo que quiero invocar del archivo de recursos que nos provee el assembly satélite.

 

Nota: en este momento nos sería de mucho valor contar con la planilla de Excel que posee el nombre de cada campo por página.

 

Una vez realizado esto solo nos resta por invocar el medo “DataBind” el cual nos da la posibilidad de vincular las propiedades cargadas en el “Code-Behind” , para posteriormente puedan ser cargadas en el formulario y de este modo, sean visualizadas por el cliente (Browser). En este momento solo nos resta probar que todo funcione como fue previsto, por lo tanto, presionemos F5, para compilar la aplicación, y ver que sucede.

 

Nota: es importante aclarar que el nombre de los campos provenientes del archivo de recursos es “CaseSensitive” por lo tanto escribir NewUser_Name  no es lo mismo que escribir newuser_name.

 

Bueno, seguramente ya les esta funcionando todo de maravilla, por lo tanto, podemos continuar con la parte que nos queda, la cual involucra a los ensamblados satélite con referencia cultural.

 

En primer lugar para continuar es necesario que volvamos al “global.asax”, puesto que el resto de nuestro trabajo (en lo que refiere a los archivos de recurso), se concentrará ahí.

 

Una vez situados en el global.asax, nos concentraremos en trabajar en el evento “Application_BeginRequest”, es aquí donde realizaremos los cambios de cultura de nuestra aplicación, teniendo en cuenta la configuración regional de la máquina del usuario.

Para ello, es necesario escribir las siguientes líneas de código:

 


try
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo(Request.UserLanguages[0],false);
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture
        (Thread.CurrentThread.CurrentCulture.Name);
}
catch(Exception)
{     
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");   
}
finally
{
    Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
}

 

 

Bueno, una vez presentado el código que se encargará de cambiar la cultura de la aplicación, es necesario explicarlo, por lo tanto, comencemos por la primera línea después del “try”. Como ya había mencionado anteriormente la aplicación se encuentra corriendo en un sub-proceso el cual posee una cierta configuración inicial, esta configuración inicial es la que será utilizada por el sistema en caso de que no se le realice ningún cambio en medio. Es por eso que en este evento, Applicciont_BeginRequest, como su nombre lo indica, es ejecutado por cada comienzo de solicitud. Realizaremos las acciones correspondientes para que el CLR obtenga el ensamblado satélite correspondiente a la cultura del cliente. Como les decía, dentro del sub-proceso se encuentra la propiedad “CurrentThread” la cual hace referencia al proceso actual y dentro de ella, la propiedad “CurrentCulture”, la cual hace referencia a la cultura actual, para que la cultura de la aplicación cambie, de acuerdo con la configuración regional del cliente es necesario que  de esta ultima propiedad mencionada se cree un objeto de tipo “CultureInfo” el cual recibirá como parámetro la cultura actual del usuario que esta realizando el Request por medio de “Request.UserLangages[0]”, además al constructor es necesario que se le pase un segundo parámetro de tipo bolean el cual es para que el constructor tome la configuración de cultura por default que posee el CLR, puesto que de lo contrario, si el usuario le realizó algún cambio a su configuración regional, el sistema tomará este cambio y como consecuencia podría surgir un error de incompatibilidad de cultura.

 

Luego, la siguiente línea de código nos permitirá, mediante el método estático “CreateSpecificCulture”, de la clase CultureInfo, cambiar la cultura del sistema, por la que fue obtenida de la configuración regional del cliente. Para realizarlo, al método CreateSpecificCulture  es necesario pasarle por parámetro el nombre de la cultura actual. Dentro de este mecanismo es cuando el CLR se encarga de buscar en la carpeta correspondiente a la cultura solicitada. De no encontrar la carpeta con los recursos para dicha cultura el CLR cargará la cultura por default. Cabe aclarar que aunque el CLR no haya encontrado la carpeta con los recursos necesarios para la cultura solicitada, igualmente todo lo que refiere a código de moneda, fechas y calendario se adecuara a la cultura solicitada por el cliente.

 

Finalizado este punto, el código terminará su ejecución en la instrucción “finally” del bloque donde al proceso actual se le cargará en la propiedad “CurrentUICulture” la cultura actual. Esto se hace con el fin de que tanto el código de moneda como, los manejos de fechas, calendarios y ordenamientos, cumplan con lo establecido por dicha referencia cultural.

 

En caso de ocurrir una excepción por algún motivo, en el bloque de código “catch” se cargará la referencia cultura “en-US”. Esto es una de muchas cosas que se podría llegar a hacer al momento de una excepción, por lo tanto, tengan en cuenta que, no es necesario seguir este punto en forma obligada.

En este momento ya estamos en condiciones de realizar pruebas con el sistema, presione F5 par compilar. Una vez compilado abra la “Configuración Regional” desde el panel de control.

Start \Control Panel\Regional and Language Options.

 

 

Al abrirse el cuadro de dialogo, puede seleccionar el idioma y país presionar “Apply” y luego ir al Browser donde se encuentra nuestro formulario y presionar F5 para refrescar la pantalla.

 

Nota: Para ver los cambios alterne entre los lenguajes y países utilizados en este articulo.

 

 

 

Conclusión.

 

Hoy día realizar aplicaciones que se adecuen a la región cultural donde vayan a ser utilizados, es un punto sumamente importante para que los sistemas puedan ser comercializados en forma global. El mecanismo de Internacionalización propuesto por .Net, es muy fácil y rápido de integrar a los sistemas. Inicialmente, tal vez resulte un poco molesto, pero a no muy largo plazo uno puede notar que vale la pena realizarlo de esta forma puesto que el código relacionado al negocio no sufriría absolutamente ninguna alteración si en un sistema trabajando en producción se decidiera agregar una nueva cultura, puesto que de este modo los recursos correspondientes a la cultura y la aplicación en si, se encuentran completamente separados.

 

A mi modo de ver las cosas, vuelvo a repetir, este mecanismo es excelente.

 

 


 

Ariel Norberto Menéndez
menendea@hotmail.com
www.cardinal-cg.com

ir al índice

Fichero con el código de ejemplo: menendea_DesarrollarAplicacionesMUI.zip- 26KB