En estos últimos días estuve analizando una aplicación para convertirla que posea soporte en múltiples lenguajes. Asp.Net Core nos brinda una gran cantidad de servicios y middleware. Entre ellos tenemos disponibles para manejar la globalización y la localización de una manera muy simple.
El objetivo de esta publicación es tocar las posibles utilizaciones y alcance del manejo de globalización y localización como también que son y para qué son útiles.
Este documento está dirigido a desarrolladores que quieren conocer Asp.Net core o personas que desarrollan tareas de Consultoría de desarrollo o que simplemente están interesados en leer e investigar sobre la tecnología alcanzada por esta publicación.
Desarrollo
Comencemos aclarando algunos conceptos:
- Globalización (Globalization) es el proceso por el cual se debe diseñar una aplicación para que pueda responder a diferentes culturas. Esta agrega soporte para entrada de información, también su salida o visualizaciones definida para cierto lenguaje o para un área geográfica específica.
- La localización (Localization) es la adaptación de una aplicación globalizada para una cultura particular.
Para tener disponibles estas características deberemos hacer uso de 2 interfaces IStringLocalizar y IStringLocalizar<T>. Estas 2 últimas hacen uso de las clases ResourceManager and ResourceReader que proveerán la información específica que será recuperada de los archivos de recursos.
algo para destacar es que no es necesario tener los archivos de recursos disponibles. Si invocamos un valor y no existe un archivo de recurso o valor devolverá el nombre del parámetro. Esto puede utilizarse como idioma por default.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
namespace AspNetCoreGloLoc.Controllers
{
[Route("api/[controller]")]
public class StringTextController : Controller
{
private readonly IStringLocalizer<StringTextController> _localizer;
public StringTextController(IStringLocalizer<StringTextController> localizer)
{
_localizer = localizer;
}
[HttpGet]
public string Get()
{
return _localizer["Title"];
}
}
}
Si necesitamos implementar globalización y localización dentro de código que contengan html una mejor opción es usar las interfaces IHtmlLocalizar y IHtmlLocalizar<T>. Debemos hacer uso de los siguientes namespaces Microsoft.AspNetCore.Localization y Microsoft.AspNetCore.Mvc.Localization. Usualmente usamos siempre texto simple antes que html específico.
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
namespace Localization.StarterWeb.Controllers
{
public class BookController : Controller
{
private readonly IHtmlLocalizer<BookController> _localizer;
public BookController(IHtmlLocalizer<BookController> localizer)
{
_localizer = localizer;
}
public IActionResult Hello(string name)
{
ViewData["Message"] = _localizer["<b>Hello</b><i> {0}</i>", name];
return View();
}
Una opción interesante es la posibilidad de particionar la localización por controller, aread o algún tipo de contenedor. Veamos cómo podemos usar ShareResource para esto.
namespace Localization.StarterWeb
{
public class SharedResource
{
}
}
Podemos usar Startup del proyecto y agregarlo al contenedor global veamos el siguiente controlador de ejemplo:
public class InfoController : Controller
{
private readonly IStringLocalizer<InfoController> _localizer;
private readonly IStringLocalizer<SharedResource> _sharedLocalizer;
public InfoController(IStringLocalizer<InfoController> localizer,
IStringLocalizer<SharedResource> sharedLocalizer)
{
_localizer = localizer;
_sharedLocalizer = sharedLocalizer;
}
public string TestLoc()
{
string msg = "Shared resx: " + _sharedLocalizer["Hello!"] +
" Info resx " + _localizer["Hello!"];
return msg;
}
Para una vista podemos usar IViewLocalizer. ViewLocalizer implementa la interface anterior y busca en los archivos de recursos dependiendo el path del avista.
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<p>@Localizer["Use this area to provide additional information."]</p>
Uno puntos para tener en cuenta:
- Es necesario usar el paquete nuget “Localization.AspNetCore.TagHelpers”.
- Generalmente usamos una sola localizacion para tecto y no HTML
Otra opción que utilizamos mucho puede ser por medio de DataAnnotations.
public class RegisterViewModel
{
[Required(ErrorMessage = "The Email field is required.")]
[EmailAddress(ErrorMessage = "The Email field is not a valid e-mail address.")]
[Display(Name = "Email")]
public string Email { get; set; }
[Required(ErrorMessage = "The Password field is required.")]
[StringLength(8, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
Conclusión
Asp.Net Core posee un conjunto de características las cuales nosotros como desarrolladores podemos sacarle un muy buen provecho a la localización y globalización.