Twitter Facebook Google + RSS Feed

Globalización y localización en Silverlight

5
Silverlight

Viernes, 08 de enero de 2010 a las 16:30hs por Gustavo Cantero (The Wolf)

Si uno programó con ASP.NET y comienza a desarrollar una aplicación en Silverlight en múltiples idiomas lo primero que se pregunta es “¿Cuál es la sintaxis de XAML equivalente al <%$ Resources:xx, yy %> de ASP.NET?”, y no es lindo cuando buscamos por internet y no encontramos ninguna respuesta.  Pues bien, en este artículo voy a mostrar cómo se puede hacer para poder poner textos localizables directamente en el XAML como si se lo estuviéramos asignando a un control ASP.NET en la definición del mismo.

Antes que nada, para aquellos que no están familiarizados con los términos del título de este artículo, voy a comentar a qué nos referimos: hablamos de “globalización” cuando nos referimos a las acciones relacionadas con el desarrollo de aplicaciones que se adaptan a culturas diferentes, en cambio la localización hace referencia a todos aquellos procesos de traducción de los distintos recursos para una cultura específica.

Bien, comencemos creando los textos en distintos idiomas, para esto necesitamos crear un archivo de recursos en nuestro proyecto Silverlight al que llamaremos “Textos.resx”.  Al crear el archivo el Visual Studio® nos abre el editor de recursos y veremos que se podemos cargar varios textos, pudiendo ingresar un nombre, valor (el texto en sí) y algún comentario opcional por cada uno.  El nombre es importante porque se utiliza para crear automáticamente una propiedad para acceder al valor del texto.  Veremos en el árbol del proyecto que además del archivo “Textos.resx” se crea un “Textos.Designer.cs” o (“Textos.Designer.vb” en caso de usar Visual Basic®), aquí el IDE crea una clase para la obtener programáticamente de forma fácil los valores de los textos.  Por ejemplo, supongamos que creamos un texto con el nombre “Boton1”, al guardar el recurso vamos a ver que existe una clase llamada “Textos” con algunas propiedades estáticas, entre las cuales está “Boton1”, la cual nos devolverá el valor del texto.

Un punto a tener en cuenta es la opción “Modificador de acceso” (AccessModifier) que se encuentra en la barra de herramientas del editor de recursos, cuyo valor por defecto es “internal”, lo que significa que la clase que se crea para acceder a los recursos va a ser del tipo “interno”, o sea, no se va a poder acceder desde afuera, pero para poder utilizar nuestros recursos directamente en el XAML necesitamos cambiar este valor a “public”.

AccessModifierResource

Ahora bien, supongamos que en este archivo de recursos estamos cargando los textos en español, pero queremos que nuestra aplicación Silverlight también pueda mostrarlos en inglés, entonces vamos a crear en el mismo lugar donde está nuestro archivo de recursos, otro llamado “Textos.en.resx”.  Nótese que este nuevo archivo antes de su extensión tiene la cadena “en”, esto significa que contendrá los textos en “inglés”.  Podemos crear cuantos recursos necesitemos utilizando esta nomenclatura para el idioma, pero .NET no sólo nos permite crear recursos por idioma, sino por cultura, por ejemplo, permitiéndonos crear recursos en inglés americano (llamando al archivo “Textos.en-US.resx”) o en inglés británico (“Textos.en-GB.resx”).  Debajo del artículo les copio una tabla con las distintas culturas soportadas por .NET Framework (para más información se puede ver la documentación de la clase CultureInfo en http://msdn.microsoft.com/es-ar/library/system.globalization.cultureinfo(VS.95).aspx).

Ahora que ya tenemos creados nuestros recursos en español e inglés, debemos modificar el archivo de proyecto para especificar los lenguajes que va a soportar nuestra aplicación.  Para hacer esto necesitamos editar el archivo .csproj, para lo cual pulsaremos el botón derecho de nuestro mouse sobre el proyecto en nuestro IDE y seleccionaremos la opción “Descargar proyecto” (Unload project), lo cual hará momentáneamente inaccesible los archivos de nuestro proyecto pero nos permitirá, pulsando nuevamente el botón derecho, seleccionar la opción “Editar …” (Edit …) para poder modificar el archivo en el editor del Visual Studio®.  Una vez abierto el archivo veremos que se trata de un XML, el cual contiene una etiqueta llamada “SupportedCultures”, la cual obviamente contiene las culturas soportadas por nuestra aplicación.  Aquí escribiremos todas las culturas que queremos que soporte nuestra aplicación, en nuestro ejemplo:

<SupportedCultures>es;en</SupportedCultures>

Cabe mencionar que las culturas deben ingresarse separadas por un punto y coma, inclusive las que son del mismo idioma, por ejemplo, si quisiéramos que nuestra aplicación soporte las culturas español, español de argentina e inglés, deberíamos ingresar:

<SupportedCultures>es;es-ar;en</SupportedCultures>

Luego de grabar el archivo volvemos a pulsar el botón derecho sobre el proyecto, elegimos la opción “Recargar proyecto” (Reload project).

Bien, hasta acá establecimos los posibles lenguajes, pero vamos a ver cómo utilizar los recursos directamente en el XAML.  La idea básica es crear el objeto que devuelve los textos como un recurso de la aplicación, pero no podemos usar el que creó automáticamente el Visual Studio® ya que, aunque las propiedades estáticas son públicas, su constructor es interno.  Una de las formas de solucionar esto es modificar la clase cambiando el “internal Textos() {}” por “public Textos() {}”, pero cada vez que modifiquemos algún texto el IDE nos va a volver a generar esta clase y vamos a necesitar cambiar nuevamente el constructor.  Para evitar esto podemos crear otra clase que simplemente cree este objeto (al cual va a tener acceso porque es interno) y lo devuelva a través de una propiedad pública, como muestro a continuación:

public class Recursos {
    private static Textos objTextos = new Textos();
    public Textos Textos {
        get { return objTextos; }
    }
}

Ahora podemos agregar nuestra clase como recurso de la aplicación, para lo cual tenemos que abrir el archivo “App.xaml” de nuestra y dentro de “Application.Resources” agregar nuestro objeto de recursos:

<Application.Resources>
<local:Recursos xmlns:local="clr-namespace:Globalizacion" x:Key="Recursos" />
</Application.Resources>

Nótese que el atributo “xmlns:local” define el namespace de nuestra clase, por lo tanto, si su clase Recursos está en uno distinto deberán ingresar el correcto.

Hecho esto ya podemos utilizar nuestros recursos en cualquier XAML de nuestra aplicación haciendo “binding” entre las propiedades de nuestros controles y la del objeto de recursos con el texto a mostrar.  Por ejemplo, a continuación muestro el código para establecerle a la propiedad “Text” de un TextBlock el valor del texto “Prueba” de nuestros recursos:

<TextBlock Text="{Binding Textos.Prueba, Source={StaticResource Recursos}}" />

La sintaxis, si bien no es igual a la de ASP.NET, nos permite establecer textos localizados directamente en nuestros XAML, sin necesidad de hacerlo programáticamente.

Ahora lo único que nos queda por hacer es establecer de alguna forma el idioma que queremos mostrar en nuestra aplicación.  Una forma sería cambiar el UICulture de nuestra aplicación programáticamente de la siguiente forma:

Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");

Pero si queremos automatizarlo podemos hacer que nuestra página ASP.NET le pase el idioma que está utilizando, cambiando el parámetro “uiculture” del objeto Silverlight en HTML.  Si queremos que además de nuestros textos la aplicación adapte los formatos de fecha, números, etc., también debemos establecer la cultura al parámetro “cultura”.  Por ejemplo, en el siguiente código HTML le establezco la cultura inglés a nuestra aplicación:

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
    <param name="source" value="ClientBin/Globalizacion.xap" />
    <param name="onError" value="onSilverlightError" />
    <param name="background" value="white" />
    <param name="minRuntimeVersion" value="3.0.40624.0" />
    <param name="autoUpgrade" value="true" />
    <param name="uiculture" value="en" />
    <param name="culture" value="en" />
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration: none">
        <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight"
            style="border-style: none" />
    </a>
</object>

Como hablamos antes de “automatizar” la cultura, podemos hacer que el ASP.NET elija automáticamente la cultura a mostrar según la configuración del navegador del cliente estableciendo el valor “auto” a las propiedades “uiculture” y “culture” en la etiqueta “globalization” de nuestro web.config:

<globalization uiCulture="auto" culture="auto"/>

Si “globalization” no existe en el web.config habrá que crearlo dentro de “system.web”.

Por último, debemos pasarle al Silverlight la cultura seleccionada por el ASP.NET:

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
    <param name="source" value="ClientBin/Globalizacion.xap" />
    <param name="onError" value="onSilverlightError" />
    <param name="background" value="white" />
    <param name="minRuntimeVersion" value="3.0.40624.0" />
    <param name="autoUpgrade" value="true" />
    <param name="uiculture" value="<%=System.Threading.Thread.CurrentThread.CurrentUICulture%>" />
    <param name="culture" value="<%=System.Threading.Thread.CurrentThread.CurrentCulture%>" />
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration: none">
        <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight"
            style="border-style: none" />
    </a>
</object>

Y listo, nuestra aplicación ya se adapta a la configuración del navegador del usuario y cambia sus textos y formatos.

Aquí les dejo el proyecto realizado con Visual Studio® 2008 para bajar y las capturas de la página donde se ve cómo cambia la cultura entre español, inglés y español de Argentina (qué es la configuración de mi PC) al utilizar la selección automática (nótese la diferencia en el formato de hora con la cultura “español”).

Cultura en español

Cultura en inglés

Cultura en auto

Espero que el artículo les haya sido de utilidad y como siempre los insto a dejar sus consultas, dudas o sugerencias.

Culturas soportadas por .NET

Cultura Referencia
“” (cadena vacía) Referencia cultural de todos los idiomas
af Afrikaans
af-ZA Afrikaans (Sudáfrica)
sq Albanés
sq-AL Albanés (Albania)
ar Árabe
ar-DZ Árabe (Argelia)
ar-BH Árabe (Bahréin)
ar-EG Árabe (Egipto)
ar-IQ Árabe (Iraq)
ar-JO Árabe (Jordania)
ar-KW Árabe (Kuwait)
ar-LB Árabe (Líbano)
ar-LY Árabe (Libia)
ar-MA Árabe (Marruecos)
ar-OM Árabe (Omán)
ar-QA Árabe (Qatar)
ar-SA Árabe (Arabia Saudí)
ar-SY Árabe (Siria)
ar-TN Árabe (Túnez)
ar-AE Árabe (Emiratos Árabes Unidos)
ar-YE Árabe (Yemen)
hy Armenio
hy-AM Armenio (Armenia)
az Azerí
az-Cyrl-AZ Azerí (Azerbaiyán, Cirílico)
az-Latn-AZ Azerí (Azerbaiyán, Latín)
eu Vasco
eu-ES Vasco (España)
be Bielorruso
be-BY Bielorruso (Belarús)
bg Búlgaro
bg-BG Búlgaro (Bulgaria)
ca Catalán
ca-ES Catalán (España)
zh-HK Chino (Hong Kong RAE, RPC)
zh-MO Chino (Macao RAE)
zh-CN Chino (RPC)
zh-Hans Chino (simplificado)
zh-SG Chino (Singapur)
zh-TW Chino (Taiwán)
zh-Hant Chino (tradicional)
hr Croata
hr-BA Croata (Bosnia-Herzegovina)
hr-HR Croata (Croacia)
cs Checo
cs-CZ Checo (República Checa)
da Danés
da-DK Danés (Dinamarca)
dv Divehi
dv-MV Divehi (Maldivas)
nl Holandés
nl-BE Neerlandés (Bélgica)
nl-NL Neerlandés (Países Bajos)
en Inglés
en-AU Inglés (Australia)
en-BZ Inglés (Belice)
en-CA Inglés (Canadá)
en-029 Inglés (Caribe)
en-IE Inglés (Irlanda)
en-JM Inglés (Jamaica)
en-NZ Inglés (Nueva Zelanda)
en-PH Inglés (Filipinas)
en-ZA Inglés (Sudáfrica)
en-TT Inglés (Trinidad y Tobago)
en-GB Inglés (Reino Unido)
en-US Inglés (Estados Unidos)
en-ZW Inglés (Zimbabue)
et Estonio
et-EE Estonio (Estonia)
fo Feroés
fo-FO Feroés (Islas Feroe)
fa Persa
fa-IR Farsi (Irán)
fi Finlandés
fi-FI Finés (Finlandia)
fr Francés
fr-BE Francés (Bélgica)
fr-CA Francés (Canadá)
fr-FR Francés (Francia)
fr-LU Francés (Luxemburgo)
fr-MC Francés (Mónaco)
fr-CH Francés (Suiza)
gl Gallego
gl-ES Gallego (España)
ka Georgiano
ka-GE Georgiano (Georgia)
de Alemán
de-AT Alemán (Austria)
de-DE Alemán (Alemania)
de-DE_phoneb Alemán (Alemania, ordenación de la libreta de teléfonos)
de-LI Alemán (Liechtenstein)
de-LU Alemán (Luxemburgo)
de-CH Alemán (Suiza)
el Griego
el-GR Griego (Grecia)
gu Gujarati
gu-IN Gujarati (India)
he Hebreo
he-IL Hebreo (Israel)
hi Hindi
hi-IN Hindi (India)
hu Húngaro
hu-HU Húngaro (Hungría)
es Islandés
is-IS Islandés (Islandia)
id Indonesio
id-ID Indonesio (Indonesia)
it Italiano
it-IT Italiano (Italia)
it-CH Italiano (Suiza)
ja Japonés
ja-JP Japonés (Japón)
kn Kannada
kn-IN Kannada (India)
kk Kazajo
kk-KZ Kazajo (Kazajistán)
kok Konkani
kok-IN Konkani (India)
ko Coreano
ko-KR Coreano (Corea)
ky Kirguís
ky-KG Kirguís (Kirguistán)
lv Letón
lv-LV Letón (Letonia)
lt Lituano
lt-LT Lituano (Lituania)
mk Macedonio
mk-MK Macedonio (Macedonia, Ex-República Yugoslava de Macedonia)
ms Malayo
ms-BN Malayo (Estado de Brunéi Darussalam)
ms-MY Malayo (Malasia)
mr Marathi
mr-IN Marathi (India)
mn Mongol
mn-MN Mongol (Mongolia)
no Noruego
nb-NO Noruego (Bokmål, Noruega)
nn-NO Noruego (Nynorsk, Noruega)
pl Polaco
pl-PL Polaco (Polonia)
pt Portugués
pt-BR Portugués (Brasil)
pt-PT Portugués (Portugal)
pa Punjabi
pa-IN Punjabi (India)
ro Rumano
ro-RO Rumano (Rumanía)
ru Ruso
ru-RU Ruso (Rusia)
sa Sánscrito
sa-IN Sánscrito (India)
sr-Cyrl-CS Serbio cirílico (Serbia y Montenegro)
sr-Latn-CS Serbio latino (Serbia y Montenegro)
sk Eslovaco
sk-SK Eslovaco (Eslovaquia)
sl Esloveno
sl-SI Esloveno (Eslovenia)
es Español
es-AR Español (Argentina)
es-BO Español (Bolivia)
es-CL Español (Chile)
es-CO Español (Colombia)
es-CR Español (Costa Rica)
es-DO Español (República Dominicana)
es-EC Español (Ecuador)
es-SV Español (El Salvador)
es-GT Español (Guatemala)
es-HN Español (Honduras)
es-MX Español (México)
es-NI Español (Nicaragua)
es-PA Español (Panamá)
es-PY Español (Paraguay)
es-PE Español (Perú)
es-PR Español (Puerto Rico)
es-ES Español (España)
es-ES_tradnl Español (España – alfabetización tradicional)
es-UY Español (Uruguay)
es-VE Español (Venezuela)
sw Suajili
sw-KE Swahili (Kenia)
sv Sueco
sv-FI Sueco (Finlandia)
sv-SE Sueco (Suecia)
syr Sirio
syr-SY Sirio (Siria)
ta Tamil
ta-IN Tamil (India)
tt Tatar
tt-RU Tatar (Rusia)
te Telugu
te-IN Telugu (India)
th Tailandés
th-TH Tailandés (Tailandia)
tr Turco
tr-TR Turco (Turquía)
uk Ucraniano
uk-UA Ucraniano (Ucrania)
ur Urdú
ur-PK Urdú (Pakistán)
uz Uzbeko
uz-Cyrl-UZ Uzbeko (Uzbekistán, Cirílico)
uz-Latn-UZ Uzbeko (Uzbekistán, Latino)
vi Vietnamita
vi-VN Vietnamita (Vietnam)

5 comentarios »

  1. Jesus Sanchez dice:

    Buenas amigo, disculpa tengo una pregunta. ¿Para que versión de silverlight es este articulo?
    Actualmente estoy desarrollando aplicaciones con la version 3 de silverlight y me da un problema con esta parte del codigo que expones:

    ¿Tienes alguna idea de por que no me funciona?

    Muchas gracias por tu atención

  2. Fredy dice:

    probado en SL5. MUY bueno el articulo! gracias! =D

  3. Selena Henn dice:

    ¡Hola! Si estan interesados en localizar cualqier tipo de software, reccomendo con calor este rápido y intuitiva herramienta de localización: http://poeditor.com/.

Deja un comentario

Buscar