Lo qué
Luego de dar vueltas todo un fin de semana buscando una forma fácil de hacer un sitio web MVC4 multi idioma / multi cultura, hago aquí un rejunte de la parva de artículos leídos. En esta notas pongo en práctica la forma que me pareció más directa de implementarlo. No se si es la mejor (me lo dirán en sus comentarios), pero la forma más simple que encontré es utilizando Code52, incluido como paquete Nuget.
No voy a explicar los por qué de cada cosa, lo que dejo librado a la inquietud de cada uno. Así que vamos derecho a hacer un ejemplo completo, paso a paso y con muchas imágenes.
El proyecto con el código de este ejemplo está disponible aquí. (hacer clic en "Archivo > Descargar" para bajarlo completo).
El proyecto con el código de este ejemplo está disponible aquí. (hacer clic en "Archivo > Descargar" para bajarlo completo).
Qué se necesita
Para este ejemplo voy a utilizar Visual Studio 2010 con C#. Es necesario tener instalado la extensión Nuget para Visual Studio. Se puede instalar y obtener la documentación de Nuget en http://nuget.codeplex.com/.
Luego de eso es necesario instalar el paquete MVC4.
Para esto, abrir la consola Nuget de administación de paquetes (PM) desde Tools > Library Package Manager > Package Manager Console. En la consola escribir PM> Install-Package AspNetMvc (y darle Enter).
Una vez descargado e instalado estará todo listo para crear sitios Web con MVC4.
Luego de eso es necesario instalar el paquete MVC4.
Para esto, abrir la consola Nuget de administación de paquetes (PM) desde Tools > Library Package Manager > Package Manager Console. En la consola escribir PM> Install-Package AspNetMvc (y darle Enter).
Una vez descargado e instalado estará todo listo para crear sitios Web con MVC4.
Crear el sitio
Vamos a crear un sitio Web del tipo MVC4 que para este ejemplo se llamará "GlobalMVC4"
El tipo de aplicación será Internet Application con Razor
Así que lo que vamos a hacer ahora es crear una entrada de texto para el idioma predeterminado (en este caso dejamos inglés) y la vamos a reproducir en español y portugués.
En el archivo de recursos, reemplazar la clave "String1" por "Home_Title", así:
Luego vamos a copiar y pegar dos veces el archivo "Language.resx", uno para español Argentina y el otro para Portugués Brasil. Renombrar cada uno como "Language.es-AR.resx" y "Language.pt-BR,resx". Cabe notar que a pesar de que "Language.resx" es el archivo predeterminado para inglés de Gran Bretaña, no tiene en realidad ninguna cultura definida (ni general ni específica), por lo que podríamos en realidad utilizarlo para cualquier idioma de forma predeterminada. Yo en general construyo toda la aplicación utilizando este archivo, y al final suelo agregar los otros idiomas o culturas.
Ahora hay que editar las entradas para cada idioma. En este caso, para la única entrada que tiene casda uno, en "Language.es-AR.resx" ponemos "Página de inicio", y en "Language.pt-BR" ponemos "Tela de inicio" (no es traducción literal, es solo a los fines de notar el cambio de idioma).
Abrir la página "_Layout.cshtml" (Views/Shared/_Layout.cshtml) y al principio de todo agregar:
Luego, dentro del cuerpo agregar en algún lado la siguiente línea:
(la ubicación depende del diseño, cosa que por ahora no vamos a ver).
Nota: "GlobalMVC4" corresponde al espacio de nombres de nuestra aplicación.
4 - La primer línea de código que agregamos corresponde a una vista parcial que el paquete agregó como un control .ascx (Views/Shared/LanguageSelection.ascx) y que editaremos más adelante. Este control utiliza una hoja de estilos predeterminada que trae el mismo paquete, por lo que el siguiente paso es hacer referencia a esta hoja de estilos (Content/Code52.i18n/Code52.i18n.css) en las páginas de nuestro sitio.
La última versión de MVC4 incorpora una nueva estructura que facilita las configuraciones generales y otras funciones que se agregaban normalmente al Global.asax. Se verá por lo tanto una nueva carpeta llamada "App_Start", donde editaremos el archivo "BundleConfig.cs" (App_Start/BundleConfig.cs).
Dentro de esta clase buscamos la línea donde se configura la hoja de estilos general del sitio.
Una vez creado el sitio, vamos a verificar que funcione correctamente, para lo que presionamos F5. Si se creó correctamente, se verá la página de inicio (Home).
detenemos el sitio y pasamos a instalar el paquete internacionalización, lo que finalmente nos mostrará un menú de idiomas para seleccionar alguna de las culturas disponibles.
Code52.i18n
Este es el paquete que vamos a utilizar para manejar la internacionalización de nuestro sitio. Para instalarlo, en la consola de Nuget debemos escribir: PM> Install-Package Code52.i18n.MVC4
Toda la información sobre el paquete está en el sitio de Code52.org. La mayor parte sobre la que se basa este artículo está en esta guía paso a paso para configurar i18n.
Como se puede ver en la imagen, luego de descargado se instalan varios archivos nuevos, que pueden verse también en las carpetas y archivos de la solución. Los paquetes instalados por Nuget quedan además registrados en el archivo packages.config
Listos para comenzar
A partir de este momento hay que trabajar en el sitio para poner todo lo instalado a funcionar. Así que vamos paso a paso:
Preparar los archivos
En el directorio raíz, crear una carpeta llamada "Resources", y dentro de ella agregar un archivo de recursos llamado "Language.resx". Este es el nombre de archivo de recursos predeterminado con que trabaja Code52.i18n. Se puede utilizar otro, pero habrá que cambiar luego las referencias dentro del código.
Nuestro directorio quedará como la imagen siguiente. Se ve el nombre de la entrada String1 en el archivo de recursos, donde luego pondremos nuestros textos para cada idioma.
Agregar los recursos de idioma para cada cultura
Cuando se instala el paquete de internacionalización se crean tres culturas a modo de ejemplo: Polaco, Inglés y Francés. Como esta nota está den español, para nuestro sitio vamos a cambiar el francés y el polaco por Español Argentina (es-AR) y Portugués Brasil (pt-BR).Así que lo que vamos a hacer ahora es crear una entrada de texto para el idioma predeterminado (en este caso dejamos inglés) y la vamos a reproducir en español y portugués.
En el archivo de recursos, reemplazar la clave "String1" por "Home_Title", así:
Luego vamos a copiar y pegar dos veces el archivo "Language.resx", uno para español Argentina y el otro para Portugués Brasil. Renombrar cada uno como "Language.es-AR.resx" y "Language.pt-BR,resx". Cabe notar que a pesar de que "Language.resx" es el archivo predeterminado para inglés de Gran Bretaña, no tiene en realidad ninguna cultura definida (ni general ni específica), por lo que podríamos en realidad utilizarlo para cualquier idioma de forma predeterminada. Yo en general construyo toda la aplicación utilizando este archivo, y al final suelo agregar los otros idiomas o culturas.
Ahora hay que editar las entradas para cada idioma. En este caso, para la única entrada que tiene casda uno, en "Language.es-AR.resx" ponemos "Página de inicio", y en "Language.pt-BR" ponemos "Tela de inicio" (no es traducción literal, es solo a los fines de notar el cambio de idioma).
Editar páginas y clases
Ya tenemos los recursos. Ahora hay que modificar algunos archivos del sitio para poner en acción el paquete de Code52 y hacer que funcione:Abrir la página "_Layout.cshtml" (Views/Shared/_Layout.cshtml) y al principio de todo agregar:
@using GlobalMVC4.Code52.i18n
Luego, dentro del cuerpo agregar en algún lado la siguiente línea:
@Html.Partial("LanguageSelection")
(la ubicación depende del diseño, cosa que por ahora no vamos a ver).
Nota: "GlobalMVC4" corresponde al espacio de nombres de nuestra aplicación.
4 - La primer línea de código que agregamos corresponde a una vista parcial que el paquete agregó como un control .ascx (Views/Shared/LanguageSelection.ascx) y que editaremos más adelante. Este control utiliza una hoja de estilos predeterminada que trae el mismo paquete, por lo que el siguiente paso es hacer referencia a esta hoja de estilos (Content/Code52.i18n/Code52.i18n.css) en las páginas de nuestro sitio.
La última versión de MVC4 incorpora una nueva estructura que facilita las configuraciones generales y otras funciones que se agregaban normalmente al Global.asax. Se verá por lo tanto una nueva carpeta llamada "App_Start", donde editaremos el archivo "BundleConfig.cs" (App_Start/BundleConfig.cs).
Dentro de esta clase buscamos la línea donde se configura la hoja de estilos general del sitio.
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));
Editarla de esta manera para incluir la página de estilos que utiliza el menú de idiomas (el agregado está resaltado):
bundles.Add(
new StyleBundle("~/Content/css")
.Include("~/Content/site.css"
, "~/Content/Code52.i18n/Code52.i18n.css"));
Agregar Sripts
Ahora es necesario agregar las siguientes referencias a los scripts necesarios. Al igual que la hoja de estilos, podrían agregarse también en BundleConfig.cs, pero ahora por cuestiones de simplicidad lo hacemos directamente en la vista _Layout.cshtml, así que justo antes del cierre del tag
</body>
agregamos lo siguiente (recomiendo copiar y pegar, presionando luego Ctrl+K+D para acomodar el indentado :))
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.globalize/globalize.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.cookie.js")"></script>
<script type="text/javascript" src="@Url.Content(string.Format("~/Scripts/jquery.globalize/cultures/globalize.culture.{0}.js", CultureHelper.GetCurrentCulture()))"></script>
@if (CultureHelper.GetCurrentNeutralCulture() != "en")
{
<script type="text/javascript" src="@String.Format("http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/localization/messages_{0}.js", CultureHelper.GetCurrentNeutralCulture())"></script>
}
<script type="text/javascript" src="@Url.Content("~/Scripts/Code52.i18n.js")"></script>
<script type="text/javascript" src="@Url.Content("/i18n/Code52.i18n.language.js")"></script>
<script type="text/javascript">
Code52.Language.Init('@CultureHelper.GetCurrentCulture()');
</script>
Debería quedar así:
Editar el menú de idiomas
Llegó el momento de editar el selector donde el usuario elige el idioma. Para esto editaremos el control .ascx al que le hicimos referencia antes en la vista general (_Layout.cshtml).
Abriendo el control encontraremos los elementos del menú de idiomas. El archivo instalado por el paquete viene con las opciones para seleccionar inglés de Gran Bretaña (en-GB), francés de Francia (fr-FR) y polaco de Polonia (pl-PL).
Quizás para cuando leas esto ya esté corregido, pero de momento el código viene con un error, donde se repite dos veces el atributo
href
, por lo que hay que eliminarlos (indicados con las flechas).Vamos a editarlos cambiando el francés y el polaco por el español y el portugués respectivamente. Nuestro menú quedará así:
Cabe aclarar que pueden utilizarse idiomas sin referencia a cultura alguna (parent culture), por ejemplo definiendo "es" en lugar de "es-AR" para español sin especificar país.
Ahora hay que abrir el archivo "CultureHelper.cs" (Code52.i18n/CultureHelper.cs), donde encontraremos las colecciones de las culturas soportadas y las utilizadas en el sitio. Para eso vamos a modificar las que trae de manera predeterminada, como se ve en la imagen:
Cambiamos el francés (fr) por es-AR y el polaco (pl) por pt-BR. Como se puede ver, el primero de la lista es el que será el predeterminado del sitio cuando el usuario aún no haya seleccionado ninguno.
Aplicar las referencias
Queda finalmente la parte más pesada dentro de la programación de una aplicación que soportan múltiples culturas: aplicar los textos en los controladores y las vistas. Y siguiendo con este ejemplo, vamos a utilizar nuestra entrada que creamos en cada uno de los tres idiomas. Para esto, abrimos el controlador de la home page y cambiamos el texto fijo que se ve aquí...... por nuestra referencia al recurso correspondiente. El IntelliSense nos ayuda a encontrar la entrada de nuestro archivo de recursos:
Comprobando el resultado
Teniendo ya todo junto, es hora de probarlo, así que a darle a F5 para correr el sitio. Veremos que aparece la opción de seleccionar idioma (no se por qué no me apareció la banderita de Brasil).He aquí la selección de cada uno:
Conclusión
Sobre el tema de internacionalización de aplicaciones hay mucha tela para cortar aún. Especialmente en los sitios MVC, una cuestión a tener bien en cuenta es el tema de las validaciones de fechas y decimales, cosa que no hemos tratado aquí.Por otra parte, y si bien esto escapa también al alcance de esta nota, una de las cosas que más me gustan de construir aplicaciones MVC con Visual Studio es el Scaffolding, para lo cual antes de construir la aplicación con soporte internacional yo suelo modificar las plantillas T4, para que cada vista y controlador creados a partir del modelo ya traigan los botones y textos haciendo referencia a los archivos de recursos.
En resumen, espero que esto les sea de utilidad. Dado que me costó encontrar una guía completa que funcionara quise ser lo más detallista posible. Espero que no haya grande cambios en los paquetes y/o clases, cosa de que este artículo sirva y tenga vigencia, pero como sabemos, eso con la tecnología y tratándose de Microsoft, es bastante impredecible.
Saludos y éxito en la tarea!