Globalización y localización en ASP.NET Core
Nota:
Esta no es la versión más reciente de este artículo. Para la versión actual, consulta la versión .NET 8 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulta la Directiva de soporte técnico de .NET y .NET Core. Para la versión actual, consulta la versión .NET 8 de este artículo.
Importante
Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
Para la versión actual, consulta la versión .NET 8 de este artículo.
By Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana y Hisham Bin Ateya
Con un sitio web multilingüe se puede llegar a un público más amplio. ASP.NET Core proporciona servicios y software intermedio para la localización en diferentes idiomas y referencias culturales.
Para obtener instrucciones de localización para Blazor, que agrega o reemplaza las instrucciones de este artículo, consulta Globalización y localización en ASP.NET Core Blazor.
Términos
- Globalización (G11N): es el proceso de hacer que una aplicación admita diferentes idiomas y regiones. La abreviatura procede de la primera y la última letra y el número de letras entre ellas.
- Localización (L10N): proceso de personalización de una aplicación globalizada para regiones e idiomas específicos.
- Internacionalización (I18N): la globalización y la localización.
- Referencia cultural: un idioma y, opcionalmente, una región.
- Referencia cultural neutra: se trata de una referencia cultural que tiene un idioma especificado, pero no una región (por ejemplo, "en", "es").
- Referencia cultural específica: referencia cultural que tiene un idioma y una región especificados (por ejemplo, "en-US", "en-GB", "es-CL").
- Referencia cultural primaria: referencia cultural neutra que contiene una referencia cultural específica (por ejemplo, "en" es la referencia cultural primaria de "en-US" y "en-GB").
- Configuración regional: la configuración regional es lo mismo que la referencia cultural.
Códigos de idioma y de país o región
El formato RFC 4646 para el nombre de la referencia cultural es <language code>-<country/region code>
, donde <language code>
identifica el idioma y <country/region code>
identifica la referencia cultural secundaria. Por ejemplo, es-CL
para español (Chile), en-US
para inglés (Estados Unidos) y en-AU
para inglés (Australia). RFC 4646 es una combinación de un código de referencia cultural ISO 639 de dos letras en minúsculas asociado con un idioma y un código de referencia cultural secundaria ISO 3166 de dos letras en mayúsculas asociado con un país o región. Para obtener más información, consulta System.Globalization.CultureInfo.
Tareas para localizar una aplicación
La globalización y la localización de una aplicación implica las tareas siguientes:
- Hacer que el contenido de una aplicación de ASP.NET Core sea localizable
- Proporcionar recursos localizados para las referencias culturales que admite la aplicación
- Implementar una estrategia para seleccionar la referencia cultural de cada solicitud
Consulta o descarga el código de ejemplo (cómo descargarlo)
Recursos adicionales
- Proveedor de referencia cultural de direcciones URL mediante middleware como filtros en ASP.NET Core
- Aplicación global de RouteDataRequest CultureProvider con middleware como filtros
IStringLocalizer
: usa ResourceManager y ResourceReader para proporcionar recursos específicos de la referencia cultural en tiempo de ejecución. La interfaz tiene un indizador y unIEnumerable
para devolver las cadenas localizadas.IHtmlLocalizer
: para los recursos que contienen HTML.- Vista y DataAnnotations
- Solución de problemas de localización de ASP.NET Core
- Globalización y localización de aplicaciones .NET
- Recursos en archivos .resx
- Kit de herramientas de aplicaciones multilingüe de Microsoft
- Localización y genéricos
By Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana y Hisham Bin Ateya
Con un sitio web multilingüe se puede llegar a un público más amplio. ASP.NET Core proporciona servicios y software intermedio para la localización en diferentes idiomas y referencias culturales.
Términos
- Globalización (G11N): es el proceso de hacer que una aplicación admita diferentes idiomas y regiones. La abreviatura procede de la primera y la última letra y el número de letras entre ellas.
- Localización (L10N): proceso de personalización de una aplicación globalizada para regiones e idiomas específicos.
- Internacionalización (I18N): la globalización y la localización.
- Referencia cultural: un idioma y, opcionalmente, una región.
- Referencia cultural neutra: se trata de una referencia cultural que tiene un idioma especificado, pero no una región (por ejemplo, "en", "es").
- Referencia cultural específica: referencia cultural que tiene un idioma y una región especificados (por ejemplo, "en-US", "en-GB", "es-CL").
- Referencia cultural primaria: referencia cultural neutra que contiene una referencia cultural específica (por ejemplo, "en" es la referencia cultural primaria de "en-US" y "en-GB").
- Configuración regional: la configuración regional es lo mismo que la referencia cultural.
Códigos de idioma y de país o región
El formato RFC 4646 para el nombre de la referencia cultural es <language code>-<country/region code>
, donde <language code>
identifica el idioma y <country/region code>
identifica la referencia cultural secundaria. Por ejemplo, es-CL
para español (Chile), en-US
para inglés (Estados Unidos) y en-AU
para inglés (Australia). RFC 4646 es una combinación de un código de referencia cultural ISO 639 de dos letras en minúsculas asociado con un idioma y un código de referencia cultural secundaria ISO 3166 de dos letras en mayúsculas asociado con un país o región. Para obtener más información, consulta System.Globalization.CultureInfo.
Tareas para localizar una aplicación
La globalización y la localización de una aplicación implica las tareas siguientes:
- Hacer que el contenido de una aplicación de ASP.NET Core sea localizable
- Proporcionar recursos localizados para las referencias culturales que admite la aplicación
- Implementar una estrategia para seleccionar la referencia cultural de cada solicitud
Vea o descargue el código de ejemplo (cómo descargarlo)
Recursos adicionales
- Hacer que el contenido de una aplicación de ASP.NET Core sea localizable
- Proporcionar recursos localizados para idiomas y referencias culturales en una aplicación de ASP.NET Core
- Estrategias para seleccionar el idioma y la referencia cultural en una aplicación de ASP.NET Core localizada
- Solución de problemas de localización de ASP.NET Core
- Globalización y localización de aplicaciones .NET
- Proyecto Localization.StarterWeb usado en el artículo
- Recursos en archivos .resx
- Kit de herramientas de aplicaciones multilingüe de Microsoft
- Localización y genéricos
By Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana y Hisham Bin Ateya
Con un sitio web multilingüe, se puede llegar a un público más amplio. ASP.NET Core proporciona servicios y software intermedio para la localización en diferentes idiomas y referencias culturales.
La internacionalización implica el uso de System.Globalization y localización. La globalización es el proceso de diseñar aplicaciones que admiten diferentes referencias culturales. La globalización agrega compatibilidad con la entrada, la visualización y la salida de un conjunto definido de scripts de lenguaje relacionados con áreas geográficas específicas.
La localización es el proceso de adaptar una aplicación globalizada, que ya se ha procesado para la localizabilidad, a una determinada referencia cultural o configuración regional. Para más información, vea Términos relacionados con la globalización y la localización al final de este documento.
La localización de la aplicación implica lo siguiente:
- Hacer que el contenido de la aplicación sea localizable
- Proporcionar recursos localizados para los idiomas y las referencias culturales admitidos
- Implementar una estrategia para seleccionar el idioma o la referencia cultural de cada solicitud
Vea o descargue el código de ejemplo (cómo descargarlo)
Preparación del contenido de la aplicación para su localización
IStringLocalizer y IStringLocalizer<T> se diseñaron para mejorar la productividad al desarrollar aplicaciones localizadas. IStringLocalizer
usa ResourceManager y ResourceReader para proporcionar recursos específicos de la referencia cultural en tiempo de ejecución. La interfaz tiene un indizador y un IEnumerable
para devolver las cadenas localizadas. IStringLocalizer
no necesita que se almacenen las cadenas de idioma predeterminado en un archivo de recursos. Puede desarrollar una aplicación destinada a la localización sin necesidad de crear archivos de recursos al principio de la fase de desarrollo. En el código siguiente se muestra cómo ajustar la cadena "About Title" para la localización.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
namespace Localization.Controllers
{
[Route("api/[controller]")]
public class AboutController : Controller
{
private readonly IStringLocalizer<AboutController> _localizer;
public AboutController(IStringLocalizer<AboutController> localizer)
{
_localizer = localizer;
}
[HttpGet]
public string Get()
{
return _localizer["About Title"];
}
}
}
En el código anterior, la implementación de IStringLocalizer<T>
procede de la inserción de dependencias. Si no se encuentra el valor localizado de "About Title, se devuelve la clave de indizador, es decir, la cadena "About Title". Puede dejar las cadenas literales del idioma predeterminado en la aplicación y ajustarlas en el localizador, de modo que se pueda centrar en el desarrollo de la aplicación. Desarrolle la aplicación con el idioma predeterminado y prepárela para el proceso de localización sin necesidad de crear primero un archivo de recursos predeterminado. También puede seguir el método tradicional y proporcionar una clave para recuperar la cadena de idioma predeterminado. El nuevo flujo de trabajo, que carece de archivo .resx de idioma predeterminado y simplemente ajusta los literales de cadena, puede ahorrar a muchos desarrolladores la sobrecarga de localizar una aplicación. Otros desarrolladores preferirán el flujo de trabajo tradicional, ya que facilita el trabajo con literales de cadena más largos, así como la actualización de las cadenas localizadas.
Use la implementación de IHtmlLocalizer<T>
para los recursos que contienen HTML. El HTML de IHtmlLocalizer
codifica los argumentos a los que se da formato en la cadena de recursos, pero no codifica como HTML la cadena de recursos en sí misma. En el ejemplo que se muestra a continuación, solo está codificado en HTML el valor del parámetro name
.
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
namespace Localization.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();
}
Nota
Por lo general, solo se localiza texto, no HTML.
En el nivel más bajo, puede obtener IStringLocalizerFactory
de la inserción de dependencias:
{
public class TestController : Controller
{
private readonly IStringLocalizer _localizer;
private readonly IStringLocalizer _localizer2;
public TestController(IStringLocalizerFactory factory)
{
var type = typeof(SharedResource);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create(type);
_localizer2 = factory.Create("SharedResource", assemblyName.Name);
}
public IActionResult About()
{
ViewData["Message"] = _localizer["Your application description page."]
+ " loc 2: " + _localizer2["Your application description page."];
En el código anterior se muestran los dos métodos factory.Create.
Puede dividir las cadenas localizadas por controlador o por área, o bien tener un solo contenedor. En la aplicación de ejemplo, se usa una clase ficticia denominada SharedResource
para los recursos compartidos.
// Dummy class to group shared resources
namespace Localization
{
public class SharedResource
{
}
}
Algunos programadores usan la clase Startup
para contener cadenas globales o compartidas. En el ejemplo siguiente, se usan los localizadores InfoController
y SharedResource
:
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;
}
Localización de vista
El servicio IViewLocalizer
proporciona cadenas localizadas para una vista. La clase ViewLocalizer
implementa esta interfaz y busca la ubicación del recurso en la ruta de acceso del archivo de vista. En el código siguiente se muestra cómo usar la implementación predeterminada de IViewLocalizer
:
@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>
La implementación predeterminada de IViewLocalizer
busca el archivo de recursos según el nombre del archivo de vista. No se puede usar un archivo de recursos compartidos global. ViewLocalizer
implementa el localizador mediante IHtmlLocalizer
, por lo que Razor no codifica como HTML la cadena localizada. Puede parametrizar las cadenas de recursos y IViewLocalizer
codificará como HTML los parámetros, pero no la cadena de recursos. Observe el siguiente marcado Razor:
@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]
Un archivo de recursos en francés podría contener lo siguiente:
Key | Valor |
---|---|
<i>Hello</i> <b>{0}!</b> |
<i>Bonjour</i> <b>{0} !</b> |
La vista representada contendría el marcado HTML del archivo de recursos.
Nota
Por lo general, solo se localiza texto, no HTML.
Para usar un archivo de recursos compartido en una vista, inserte IHtmlLocalizer<T>
:
@using Microsoft.AspNetCore.Mvc.Localization
@using Localization.Services
@inject IViewLocalizer Localizer
@inject IHtmlLocalizer<SharedResource> SharedLocalizer
@{
ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h1>@SharedLocalizer["Hello!"]</h1>
Localización de DataAnnotations
Los mensajes de error de DataAnnotations se localizan con IStringLocalizer<T>
. Mediante la opción ResourcesPath = "Resources"
, es posible almacenar los mensajes de error en RegisterViewModel
en cualquiera de las rutas de acceso siguientes:
- Resources/ViewModels.Account.RegisterViewModel.fr.resx
- Resources/ViewModels/Account/RegisterViewModel.fr.resx
public class RegisterViewModel
{
[Required(ErrorMessage = "The Email field is required.")]
[EmailAddress(ErrorMessage = "The Email field is not a valid email 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; }
}
Los atributos que no son de validación están localizados.
Uso de una cadena de recursos para varias clases
En el código siguiente se muestra cómo usar una cadena de recursos para atributos de validación con varias clases:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddDataAnnotationsLocalization(options => {
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResource));
});
}
En el código anterior, SharedResource
es la clase correspondiente al archivo resx donde se almacenan los mensajes de validación. Según este método, DataAnnotations solo usará SharedResource
, en lugar del recurso de cada clase.
Proporcionar recursos localizados para los idiomas y las referencias culturales admitidos
SupportedCultures y SupportedUICultures
ASP.NET Core permite especificar dos valores de referencia cultural, SupportedCultures y SupportedUICultures. El objeto CultureInfo para SupportedCultures
determina los resultados de funciones dependientes de la referencia cultural, como el formato de fecha, hora, número y moneda. SupportedCultures
también determina el criterio de ordenación del texto, las convenciones sobre el uso de mayúsculas y minúsculas, y las comparaciones de cadenas. Para obtener más información sobre cómo el servidor obtiene la referencia cultural, consulta CultureInfo.CurrentCulture y CultureInfo.CurrentUICulture. SupportedUICultures
determina qué cadenas traducidas buscará ResourceManager (en archivos .resx
). ResourceManager
busca cadenas específicas de referencias culturales determinadas por CurrentUICulture
. Todos los subprocesos de .NET tienen objetos CurrentCulture
y CurrentUICulture
. El marco inspecciona estos valores al representar funciones dependientes de la referencia cultural. Si la referencia cultural del subproceso actual está configurada como en-US
(inglés, Estados Unidos), DateTime.Now.ToLongDateString()
muestra Thursday, February 18, 2016
; pero si CurrentCulture
está configurada como es-ES
(español, España), la salida es jueves, 18 de febrero de 2016
.
Archivos de recursos
Un archivo de recursos es un mecanismo útil para separar del código las cadenas localizables. Las cadenas traducidas para el idioma no predeterminado están aisladas en archivos de recursos .resx. Pongamos por caso que quiere crear un archivo de recursos de español denominado Welcome.es.resx que contenga cadenas traducidas. "es" es el código de idioma para español. Para crear este archivo de recursos en Visual Studio:
En el Explorador de soluciones, haz clic con el botón derecho en la carpeta que contendrá el archivo de recursos >Agregar>Nuevo elemento.
En el cuadro para buscar plantillas instaladas, escribe "recurso" y asigna un nombre al archivo.
Escribe el valor de clave (cadena nativa) en la columna Nombre y la cadena traducida en la columna Valor.
El archivo Welcome.es.resx aparece en Visual Studio.
Nomenclatura de los archivos de recursos
El nombre de los recursos es el nombre del tipo completo de su clase menos el nombre del ensamblado. Por ejemplo, un recurso francés de un proyecto cuyo ensamblado principal sea LocalizationWebsite.Web.dll
para la clase LocalizationWebsite.Web.Startup
se denominará Startup.fr.resx. Un recurso para la clase LocalizationWebsite.Web.Controllers.HomeController
se denominará Controllers.HomeController.fr.resx. Si el espacio de nombres de la clase de destino no es igual que el nombre del ensamblado, necesitará el nombre de tipo completo. Por ejemplo, en el proyecto de ejemplo, un recurso para el tipo ExtraNamespace.Tools
se denominará ExtraNamespace.Tools.fr.resx.
En el proyecto de ejemplo, el método ConfigureServices
establece ResourcesPath
en "Resources", por lo que la ruta de acceso relativa del proyecto para el archivo de recursos en francés del controlador de home es Resources/Controllers.Controller.fr.resx. También puedes usar carpetas para organizar los archivos de recursos. Para el controlador de home, la ruta de acceso sería Resources/Controllers/Controller.fr.resx. Si no usas la opción ResourcesPath
, el archivo .resx estará en el directorio base del proyecto. El archivo de recursos para HomeController
se denominará Controllers.HomeController.fr.resx. La opción de usar la convención de nomenclatura de punto o ruta de acceso depende de la manera en que quiera organizar los archivos de recursos.
Nombre del recurso | Nomenclatura de punto o ruta de acceso |
---|---|
Resources/Controllers.HomeController.fr.resx | Punto |
Resources/Controllers/HomeController.fr.resx | Path |
Los archivos de recursos que usan @inject IViewLocalizer
en las vistas de Razor siguen un patrón similar. Para asignar un nombre al archivo de recursos de una vista, se puede usar la nomenclatura de punto o de ruta de acceso. Los archivos de recursos de una vista de Razor imitan la ruta de acceso de su archivo de vista asociado. Supongamos que establecemos ResourcesPath
en "Resources". En ese caso, el archivo de recursos de francés asociado a la vista Views/Home/About.cshtml
podría ser uno de los siguientes:
Resources/Views/Home/About.fr.resx
Resources/Views.Home.About.fr.resx
Si no usas la opción ResourcesPath
, el archivo .resx de una vista se ubicará en la misma carpeta que la vista.
RootNamespaceAttribute
El atributo RootNamespaceAttribute proporciona el espacio de nombres raíz de un ensamblado cuando el espacio de nombres raíz del ensamblado es diferente del nombre de ensamblado.
Advertencia
Esto puede ocurrir cuando el nombre de un proyecto no es un identificador de .NET válido. Por ejemplo my-project-name.csproj
usará el espacio de nombres raíz my_project_name
y el nombre de ensamblado my-project-name
, lo que lleva a este error.
Si el espacio de nombres raíz de un ensamblado es diferente del nombre de ensamblado:
- La localización no funciona de forma predeterminada.
- Se produce un error en la localización debido a la manera en que se buscan los recursos dentro del ensamblado.
RootNamespace
es un valor en tiempo de compilación que no está disponible para el proceso en ejecución.
Si RootNamespace
es diferente de AssemblyName
, incluya lo siguiente en AssemblyInfo.cs
(con los valores de parámetro reemplazados por los valores reales):
using System.Reflection;
using Microsoft.Extensions.Localization;
[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]
El código anterior permite la resolución correcta de los archivos resx.
Comportamiento de reserva de la referencia cultural
Cuando se busca un recurso, la localización entra en un proceso conocido como "reserva de la referencia cultural". Partiendo de la referencia cultural solicitada, si esta no se encuentra, se revierte a su referencia cultural principal correspondiente. Como inciso, decir que la propiedad CultureInfo.Parent representa la referencia cultural principal. Eso suele conllevar (aunque no siempre) la eliminación del significante nacional del código ISO. Así, por ejemplo, el dialecto de español hablado en México es "es-MX". Contiene el elemento principal "es", que corresponde a español no específico de ningún país en concreto.
Imagine que su sitio recibe una solicitud sobre un recurso "Welcome" donde se emplea la referencia cultural "fr-CA". El sistema de localización busca los recursos siguientes (en orden) y selecciona la primera coincidencia:
- Welcome.fr-CA.resx
- Welcome.fr.resx
- Welcome.resx (si
NeutralResourcesLanguage
es "fr-CA")
Consideremos, por ejemplo, que quita el designador de referencia cultural ".fr" y la referencia cultural está establecida en francés. En ese caso, se lee el archivo de recursos predeterminado y se localizan las cadenas. El Administrador de recursos designa un recurso predeterminado o de reserva para los casos en que nada coincida con la referencia cultural solicitada. Si quiere simplemente devolver la clave cuando falte un recurso para la referencia cultural solicitada, no debe tener un archivo de recursos predeterminado.
Generar archivos de recursos con Visual Studio
Si crea un archivo de recursos en Visual Studio sin una referencia cultural en el nombre de archivo (por ejemplo, Welcome.resx), Visual Studio creará una clase de C# con una propiedad para cada cadena. Normalmente esto no interesa con ASP.NET Core; por lo general, no tendrá un archivo de recursos .resx predeterminado (un archivo .resx sin el nombre de la referencia cultural). Se recomienda que cree el archivo .resx con un nombre de referencia cultural (por ejemplo, Welcome.fr.resx). Cuando cree un archivo .resx con un nombre de referencia cultural, Visual Studio no generará el archivo de clase.
Agregar otras referencias culturales
Cada combinación de idioma y referencia cultural (que no sea el idioma predeterminado) requiere un archivo de recursos único. Para crear archivos de recursos para otras referencias culturales y configuraciones regionales, debe crear archivos de recursos en los que los códigos de idioma ISO formen parte del nombre de archivo (por ejemplo, en-us, fr-ca y en-gb). Estos códigos ISO se colocan entre el nombre de archivo y la extensión de archivo .resx, como en Welcome.es-MX.resx (español [México]).
Implementar una estrategia para seleccionar el idioma o la referencia cultural de cada solicitud
Configurar la localización
La localización se configura en el método Startup.ConfigureServices
:
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
AddLocalization
agrega los servicios de localización al contenedor de servicios. El código anterior también establece la ruta de acceso a los recursos en "Resources".AddViewLocalization
agrega compatibilidad con los archivos de vista localizados. En este ejemplo, la localización de vista se basa en el sufijo del archivo de vista. Por ejemplo, "fr" en el archivoIndex.fr.cshtml
.AddDataAnnotationsLocalization
agrega compatibilidad con mensajes de validación deDataAnnotations
localizados mediante abstraccionesIStringLocalizer
.
Software intermedio de localización
La referencia cultural actual de una solicitud se establece en el software intermedio de localización. El software intermedio de localización se habilita en el método Startup.Configure
. El middleware de localización debe configurarse antes que cualquier software intermedio que pueda comprobar la referencia cultural de la solicitud (por ejemplo, app.UseMvcWithDefaultRoute()
). El middleware de localización debe aparecer después del middleware de enrutamiento si se usa RouteDataRequestCultureProvider. Para obtener más información sobre el orden del middleware, consulta Middleware de ASP.NET Core.
var supportedCultures = new[] { "en-US", "fr" };
var localizationOptions = new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Si quieres que los comentarios de código se traduzcan en más idiomas además del inglés, háznoslo saber en este problema de debate de GitHub.
UseRequestLocalization
inicializa un objeto RequestLocalizationOptions
. En todas las solicitudes, se enumera la lista de RequestCultureProvider
en RequestLocalizationOptions
y se usa el primer proveedor que puede determinar correctamente la referencia cultural de la solicitud. Los proveedores predeterminados proceden de la clase RequestLocalizationOptions
:
QueryStringRequestCultureProvider
CookieRequestCultureProvider
AcceptLanguageHeaderRequestCultureProvider
La lista predeterminada va de más específico a menos específico. Más adelante en el artículo veremos cómo puedes cambiar el orden e incluso agregar un proveedor de referencia cultural personalizado. Si ninguno de los proveedores puede determinar la referencia cultural de la solicitud, se usa DefaultRequestCulture
.
QueryStringRequestCultureProvider
Algunas aplicaciones usarán una cadena de consulta para establecer CultureInfo. Para las aplicaciones que usan el método de cookie o de encabezado Accept-Language, es útil agregar una cadena de consulta a la dirección URL para depurar y probar el código. De forma predeterminada, QueryStringRequestCultureProvider
está registrado como primer proveedor de localización en la lista RequestCultureProvider
. Debes pasar los parámetros de cadena de consulta culture
y ui-culture
. En el ejemplo siguiente, la referencia cultural específica (idioma y región) se establece en español (México):
http://localhost:5000/?culture=es-MX&ui-culture=es-MX
Si solo pasas uno de los dos parámetros (culture
o ui-culture
), el proveedor de la cadena de consulta usará el valor que usted ha pasado para establecer ambos valores. Por ejemplo, si solo estableces la referencia cultural, se establecerán Culture
y UICulture
:
http://localhost:5000/?culture=es-MX
CookieRequestCultureProvider
Las aplicaciones de producción suelen proporcionar un mecanismo para establecer la referencia cultural con la cookie de la referencia cultural de ASP.NET Core. Usa el método MakeCookieValue
para crear una cookie.
CookieRequestCultureProvider
DefaultCookieName
devuelve el nombre de cookie predeterminado usado para realizar un seguimiento de la información de la referencia cultural preferida del usuario. El nombre de cookie predeterminado es .AspNetCore.Culture
.
El formato de la cookie es c=%LANGCODE%|uic=%LANGCODE%
, donde c
es Culture
y uic
es UICulture
, por ejemplo:
c=en-UK|uic=en-US
Si solo especificas uno de los dos valores, ya sea la información de la referencia cultural o la referencia cultural de la interfaz de usuario, la referencia cultural especificada se usará tanto para la información de la referencia cultural como para la referencia cultural de la interfaz de usuario.
Encabezado HTTP Accept-Language
El encabezado Accept-Language se puede establecer en la mayoría de los exploradores y está diseñado inicialmente para especificar el idioma del usuario. Este valor indica qué debe enviar el explorador o qué ha heredado del sistema operativo subyacente. El encabezado HTTP Accept-Language de una solicitud del explorador no es un método infalible para detectar el idioma preferido del usuario (consulta Setting language preferences in a browser). Una aplicación de producción debe ofrecer al usuario una manera de personalizar su opción de referencia cultural.
Establecer el encabezado HTTP Accept-Language en Internet Explorer
En el icono de engranaje, pulsa Opciones de Internet.
Haz clic en Lenguajes.
Haz clic en Establecer preferencias de idioma.
Haz clic en Agregar un idioma.
Agrega el idioma.
Haz clic en el idioma y, después, en Subir.
Usar un proveedor personalizado
Imagina que quieres permitir que los clientes almacenen tu idioma y tu referencia cultural en las bases de datos. Puedes escribir un proveedor para que busque estos valores para el usuario. En el código siguiente se muestra cómo agregar un proveedor personalizado:
private const string enUSCulture = "en-US";
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo(enUSCulture),
new CultureInfo("fr")
};
options.DefaultRequestCulture = new RequestCulture(culture: enUSCulture, uiCulture: enUSCulture);
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context =>
{
// My custom request culture logic
return await Task.FromResult(new ProviderCultureResult("en"));
}));
});
Usa RequestLocalizationOptions
para agregar o quitar proveedores de localización.
Cambio del orden de los proveedores de referencia cultural de la solicitud
RequestLocalizationOptions tiene tres proveedores de referencia cultural para las solicitudes: QueryStringRequestCultureProvider, CookieRequestCultureProvider y AcceptLanguageHeaderRequestCultureProvider. Usa la propiedad [RequestLocalizationOptions.RequestCultureProviders
]](xref:Microsoft.AspNetCore.Builder.RequestLocalizationOptions.RequestCultureProviders) para cambiar el orden de estos proveedores, como se muestra a continuación:
app.UseRequestLocalization(options =>
{
var questStringCultureProvider = options.RequestCultureProviders[0];
options.RequestCultureProviders.RemoveAt(0);
options.RequestCultureProviders.Insert(1, questStringCultureProvider);
});
En el ejemplo anterior, el orden de QueryStringRequestCultureProvider
y CookieRequestCultureProvider
está intercambiado, por lo que RequestLocalizationMiddleware
busca primero las referencias culturales de las cookies y, después, la cadena de consulta.
Como se mencionó anteriormente, la adición de un proveedor personalizado a través de AddInitialRequestCultureProvider establece el orden en 0
, por lo que este proveedor tiene prioridad sobre los demás.
Establecer la referencia cultural mediante programación
Este proyecto Localization.StarterWeb de ejemplo de GitHub contiene una interfaz de usuario para establecer el valor Culture
. El archivo Views/Shared/_SelectLanguagePartial.cshtml
te permite seleccionar la referencia cultural de la lista de referencias culturales admitidas:
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options
@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var cultureItems = LocOptions.Value.SupportedUICultures
.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
.ToList();
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}
<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
<form id="selectLanguage" asp-controller="Home"
asp-action="SetLanguage" asp-route-returnUrl="@returnUrl"
method="post" class="form-horizontal" role="form">
<label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label> <select name="culture"
onchange="this.form.submit();"
asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
</select>
</form>
</div>
El archivo Views/Shared/_SelectLanguagePartial.cshtml
se agrega a la sección footer
del archivo de diseño para que esté disponible para todas las vistas:
<div class="container body-content" style="margin-top:60px">
@RenderBody()
<hr>
<footer>
<div class="row">
<div class="col-md-6">
<p>© @System.DateTime.Now.Year - Localization</p>
</div>
<div class="col-md-6 text-right">
@await Html.PartialAsync("_SelectLanguagePartial")
</div>
</div>
</footer>
</div>
El método SetLanguage
establece la cookie de la referencia cultural.
[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
);
return LocalRedirect(returnUrl);
}
No se puede conectar el archivo _SelectLanguagePartial.cshtml
con código de ejemplo para este proyecto. El proyecto Localization.StarterWeb de GitHub tiene código para enviar RequestLocalizationOptions
a una vista parcial de Razor a través del contenedor de inserción de dependencias.
Datos de ruta y cadenas de consulta de enlace de modelos
Vea Comportamiento de globalización de los datos de ruta de enlace de modelos y las cadenas de consulta.
Términos relacionados con la globalización y la localización
Para localizar una aplicación también es necesario contar con unos conocimientos básicos sobre los juegos de caracteres pertinentes que se usan en el desarrollo de software moderno y sobre los problemas asociados. Aunque todos los equipos almacenan texto como números (códigos), cada sistema almacena el mismo texto con números diferentes. El proceso de localización consiste en traducir la interfaz de usuario (IU) de la aplicación a una referencia cultural o configuración regional específica.
La localizabilidad es un proceso intermedio para comprobar que una aplicación globalizada está preparada para la localización.
El formato RFC 4646 para el nombre de la referencia cultural es <languagecode2>-<country/regioncode2>
, donde <languagecode2>
es el código de idioma y <country/regioncode2>
es el código de la referencia cultural secundaria. Por ejemplo, es-CL
para español (Chile), en-US
para inglés (Estados Unidos) y en-AU
para inglés (Australia). RFC 4646 es una combinación de un código de referencia cultural ISO 639 de dos letras en minúsculas asociado con un idioma y un código de referencia cultural secundaria ISO 3166 de dos letras en mayúsculas asociado con un país o región. Para más información, consulte System.Globalization.CultureInfo.
"Internacionalización" suele abreviarse como "I18N". La abreviatura toma la primera y la última letra de la palabra, y el número de letras que hay entre ellas, es decir, el 18 representa el número de letras que hay entre la "I" inicial y la "N" final. Lo mismo se puede decir de "globalización" (G11N) y "localización" (L10N).
Términos:
- Globalización (G11N): es el proceso de hacer que una aplicación admita diferentes idiomas y regiones.
- Localización (L10N): es el proceso de personalizar una aplicación para un idioma y región determinados.
- Internacionalización (I18N): hace referencia a la globalización y la localización.
- Referencia cultural: es un idioma y, opcionalmente, una región.
- Referencia cultural neutra: se trata de una referencia cultural que tiene un idioma especificado, pero no una región. (por ejemplo, "en" y "es").
- Referencia cultural específica: es una referencia cultural que tiene un idioma y una región especificados (por ejemplo, "en-US", "en-GB" y "es-CL").
- Referencia cultural principal: se trata de la referencia cultural neutra que contiene una referencia cultural específica. (por ejemplo, "en" es la referencia cultural principal de "en-US" y "en-GB").
- Configuración regional: la configuración regional es lo mismo que la referencia cultural.
Nota
Es posible que no pueda escribir comas decimales en campos decimales. Para que la validación de jQuery sea compatible con configuraciones regionales distintas del inglés que usan una coma (",") en lugar de un punto decimal y formatos de fecha distintos del de Estados Unidos, debe seguir unos pasos para globalizar la aplicación. Consulte este comentario 4076 de GitHub para instrucciones sobre cómo agregar la coma decimal.
Nota
Antes de ASP.NET Core 3.0, las aplicaciones escribían un registro de tipo LogLevel.Warning
por solicitud si no se admitía la referencia cultural solicitada. El registro de un valor LogLevel.Warning
por solicitud puede crear archivos de registro de gran tamaño con información redundante. Este comportamiento ha cambiado en ASP.NET 3.0. RequestLocalizationMiddleware
escribe un registro de tipo LogLevel.Debug
, lo que reduce el tamaño de los registros de producción.