Translate

viernes, 11 de octubre de 2013

Traduciendo aplicaciones en ASP.NET MVC 4 y .NET 4.5

Como el título indica la versión utilizada es ASP.NET MVC 4, .NET 4.5 y Visual Studio Express 2012. Si no conoces lo que es un archivo de recurso en ASP.NET puedes visitar el siguiente link en MSDN

Lo primero que haremos es crear una carpeta con el nombre Resources, de igual manera podríamos haber colocado nuestro recurso en la "carpeta especial" App_GlobalResources, pero puede generar problemas tal y como explica Scott Allen en el siguiente artículo el cual recomiendo leer.

Una vez creada la carpeta añadimos un archivo de recursos, Clic derecho en la carpeta, Agregar > Nuevo elemento. Deberíamos dar un nombre significativo por ejemplo: “Text” o “Labels”. Este archivo de recursos, Text.resx, va a ser el idioma por defecto de nuestra aplicación, supongamos que es español, damos doble clic al archivo en el explorador de soluciones y veremos algo parecido a la imagen.



Establecemos las etiquetas de nuestra aplicación y guardamos. Para traducir a otros idiomas copiamos y pegamos este archivo en el mismo directorio (Resources) y le agregamos al nombre original la extensión del idioma al cual queremos traducir; por ejemplo si queremos traducir al inglés sería “Text.en.resx”, Aléman “Text.de.resx”. Esta “extensión” es la cultura y nos va a permitir traducir nuestra aplicación con la ayuda de la clase CultureInfo y su propiedad DefaultThreadCurrentUICulture (Nueva en .NET 4.5). Que nos va a permitir establecer la cultura a nivel de AppDomain. Para más información acerca de Cultura, Globalización y la clase CultureInfo puedes visitar el siguiente link: Globalización y adaptación en ASP.NET

Una vez creado los diferentes archivos de recursos definimos la ruta de nuestra aplicación en el archivo RouteConfig.cs de la carpeta App_Start de manera tal que contenga el idioma elegido por el usuario por ejemplo http://website.com/en/index

routes.MapRoute(
    name: "Default",
    url: "{language}/{controller}/{action}/{id}",
    defaults: new { language = "es", 
                    controller = "Home", 
                    action = "Index", 
                    id = UrlParameter.Optional },
    constraints: new { language = "en|es" }
);


El primer parámetro es language y lo utilizaremos para conocer el lenguaje elegido por el usuario, por defecto es Español, conviene restringir el parámetro language a los idiomas en el cual vaya a estar traducida nuestra aplicación, en este caso español e inglés, para evitar problemas a la hora de establecer la cultura en caso de que el parámetro language sea modificado intencionalmente por el usuario

Ya definida la ruta procedemos a establecer la cultura. Podemos hacerlo de diferentes maneras, mediante el archivo de configuración web.config, mediante código en un Módulo HTTP, o en nuestro caso mediante un Action Filter extendiendo la clase ActionFilterAttribute

using System.Globalization;
using System.Web.Mvc;

namespace MultilingualSite.Filters
{
  public class SetCultureAttribute : ActionFilterAttribute
  {
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
      string lang = filterContext.RouteData.Values["language"].ToString();

      CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(lang);

      base.OnActionExecuting(filterContext);
    }
  }
}

Como vemos sobreescribimos el método OnActionExecuting (Antes de ejecutar una acción) y establecemos la cultura según el parámetro language en la URL Podemos añadir el filtro como atributo al Controller o al Action que queramos traducir o mejor aún podemos configurar nuestro filtro globalmente en el archivo FilterConfig.cs en la carpeta App_Start

filters.Add(new SetCultureAttribute());

Visual Studio crea automáticamente una clase del mismo nombre que el archivo de recursos con miembros estáticos que representan las propiedades del archivo de recursos y podemos acceder a ellas muy fácilmente desde cualquier parte por ejemplo para acceder a la propiedad Username con Razor:

@Resources.Text.Username

Cabe destacar que una vez seleccionada la cultura mediante la clase CultureInfo el runtime automáticamente selecciona el archivo de recursos correspondiente. Lo interesante es que también podemos traducir nuestros modelos con ayuda de los atributos usados frecuentemente, Validaciones, Displays etc. Mediante el archivo de recursos. Por ejemplo:

[Required(ErrorMessageResourceName = "UsernameRequired", ErrorMessageResourceType = typeof(Resources.Text))]
[Display(Name = "Username", ResourceType = typeof(Resources.Text))]

public string Username { get; set; }

Debido a que la clase que crea Visual Studio es internal podríamos encontrarnos con un error parecido al siguiente:
No se puede recuperar la propiedad 'Name' debido a un error en la localización. El tipo 'xxx.yyy.zzz' no es público o no contiene una propiedad de cadena estática pública con el nombre 'Username'. 
Para solucionar este error seleccionamos los archivos resx en el explorador de soluciones y en la ventana propiedades cambiamos el valor HerramientaPersonalizada de ResXFileCodeGenerator a Public ResXFileCodeGenerator tal y como explica Scott Allen en el artículo mencionado 


















Ya para finalizar he subido un ejemplo sencillo de este artículo en mi skydrive el cual es un proyecto MVC 4 que muestra un formulario de inicio de sesión y el usuario puede seleccionar el idioma ingles o español, como puede verse en las las siguientes imágenes. Saludos. 





















Recursos 

CultureInfo
Resource Files and ASP.NET MVC Projects

2 comentarios:

  1. Para un manejo más profesional de los archivos .resx para la localización, le recomiendo que utilice https://poeditor.com.

    Es una herramienta de traducción colaborativa muy útil.

    ResponderEliminar
  2. What are the rules of casinos? - Dr.MD
    If a casino 안성 출장샵 cannot 제천 출장안마 hold an event that is held by the person 이천 출장마사지 who does it, it 김해 출장마사지 cannot do so in person. 부산광역 출장안마 What are the rules of casinos?

    ResponderEliminar