Globalización y localización de Blazor de 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, consulte la versión .NET 8 de este artículo.
En este artículo se explica cómo representar contenido globalizado y localizado a los usuarios de diferentes referencias culturales e idiomas.
Globalización y localización
Para la globalización, Blazor proporciona formato de número y fecha. Para la localización, Blazor representa el contenido mediante el sistema de recursos de .NET.
Se admite un conjunto limitado de características de localización de ASP.NET Core:
Se admite: IStringLocalizer y IStringLocalizer<T> se admiten en aplicaciones de Blazor.
No se admite: IHtmlLocalizer, IViewLocalizer y la localización de anotaciones de datos son características de ASP.NET Core MVC y no se admiten en aplicaciones de Blazor.
En este artículo se describe cómo usar las características de globalización y localización de Blazor basadas en:
- El encabezado
Accept-Language
, que el explorador establece en función de las preferencias de idioma de un usuario en la configuración del explorador. - Una referencia cultural establecida por la aplicación que no se basa en el valor del encabezado
Accept-Language
. La configuración puede ser estática para todos los usuarios o dinámica en función de la lógica de la aplicación. Cuando la configuración se basa en las preferencias del usuario, esta normalmente se guarda para volver a cargarse en futuras visitas.
Para obtener información general adicional, consulte los recursos siguientes:
- Globalización y localización en ASP.NET Core
- Aspectos básicos de .NET: Globalización
- Aspectos básicos de .NET: Localización
A menudo, los términos idioma y referencia cultural se usan indistintamente al hablar de los conceptos de globalización y localización.
En este artículo, el idioma hace referencia a las selecciones realizadas por un usuario en la configuración del explorador. Las selecciones de idioma del usuario se envían en las solicitudes del explorador en el encabezado Accept-Language
. La configuración del explorador suele usar la palabra "idioma" en la interfaz de usuario.
La referencia cultural pertenece a los miembros de .NET y a la API Blazor. Por ejemplo, la solicitud de un usuario puede incluir el encabezado Accept-Language
que especifica un idioma desde la perspectiva del usuario, pero la aplicación establece en última instancia la propiedad CurrentCulture ("referencia cultural") del idioma solicitado por el usuario. La API suele utilizar la palabra "referencia cultural" en los nombres de los miembros.
Las instrucciones de este artículo no cubren la configuración del atributo de lenguaje HTML de la página (<html lang="...">
), que usan las herramientas de accessiblity. Puede establecer el valor estáticamente asignando un idioma al atributo lang
de la etiqueta <html>
o a document.documentElement.lang
en JavaScript. Puede establecer dinámicamente el valor de document.documentElement.lang
con JSde interoperabilidad.
Nota:
En los ejemplos de código de este artículo se adoptan tipos de referencia que admiten un valor NULL (NRT) y análisis estático de estado NULL del compilador de .NET, que se admiten en ASP.NET Core en .NET 6 o posterior. Al tener como destino ASP.NET Core 5.0 o versiones anteriores, quite la designación de tipo null (?
) de los ejemplos del artículo.
Globalización
La directiva de atributo @bind
aplica formatos y analiza los valores para mostrar en función del primer idioma preferido del usuario que admita la aplicación. @bind
admite el parámetro @bind:culture
para proporcionar un elemento System.Globalization.CultureInfo para analizar y dar formato a un valor.
Se puede acceder a la referencia cultural actual desde la propiedad System.Globalization.CultureInfo.CurrentCulture.
CultureInfo.InvariantCulture se usa para los siguientes tipos de campo (<input type="{TYPE}" />
, donde el marcador de posición {TYPE}
es el tipo):
date
number
Los tipos de campo anteriores:
- Se muestran según sus reglas de formato basado en explorador correspondientes.
- No pueden contener texto de forma libre.
- Proporcionar características de interacción del usuario en función de la implementación del explorador.
Blazor proporciona compatibilidad integrada para representar valores en la referencia cultural actual. Por lo tanto, no se recomienda especificar una referencia cultural con @bind:culture
cuando se usen los tipos de campo date
y number
.
Los siguientes tipos de campo tienen requisitos de formato específicos y no se admiten en Blazor, ya que no son compatibles con todos los exploradores principales:
datetime-local
month
week
Para obtener compatibilidad con el explorador actual de los tipos anteriores, consulta ¿Puedo usar ?
Compatibilidad con la globalización de .NET y los componentes internacionales para Unicode (ICU) (Blazor WebAssembly)
Blazor WebAssembly usa una API de globalización reducida y un conjunto de configuraciones regionales integradas de componentes internacionales para Unicode (ICU). Para obtener más información, consulta Globalización de .NET e ICU: ICU en WebAssembly.
Para cargar un archivo de datos de ICU personalizado para controlar las configuraciones regionales de la aplicación, consulta WASM Globalization Icu. Actualmente es necesario crear manualmente el archivo de datos de ICU personalizado. Las herramientas de .NET para facilitar el proceso de creación del archivo están previstas para .NET 9 en noviembre de 2024.
Blazor WebAssembly usa una API de globalización reducida y un conjunto de configuraciones regionales integradas de componentes internacionales para Unicode (ICU). Para obtener más información, consulta Globalización de .NET e ICU: ICU en WebAssembly.
La carga de un subconjunto personalizado de configuraciones regionales en una aplicación Blazor WebAssembly se admite en .NET 8 o versiones posteriores. Para obtener más información, ve a esta sección relativa a la versión 8.0 o posteriores de este artículo.
Globalización invariable
Esta sección solo se aplica a los escenarios Blazor del lado cliente.
Si la aplicación no requiere localización, configura la aplicación para que admita la referencia cultural invariable, que suele basarse en inglés de Estados Unidos (en-US
). El uso de la globalización invariable reduce el tamaño de descarga de la aplicación y da como resultado un inicio de la aplicación más rápido. Establece la propiedad InvariantGlobalization
en true
en el archivo del proyecto de la aplicación (.csproj
):
<PropertyGroup>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
Como alternativa, configura la globalización invariable con los enfoques siguientes:
En
runtimeconfig.json
:{ "runtimeOptions": { "configProperties": { "System.Globalization.Invariant": true } } }
Con una variable de entorno:
- Clave:
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT
- Valor:
true
o1
- Clave:
Para obtener más información, consulta Opciones de configuración de runtime para la globalización (documentación de .NET).
Información sobre zona horaria
Esta sección solo se aplica a los escenarios Blazor del lado cliente.
La adopción de la globalización invariable solo da como resultado el uso de nombres de zona horaria sin localizar. Para recortar el código y los datos de la zona horaria, lo que reduce el tamaño de descarga de la aplicación y da como resultado un inicio de la aplicación más rápido, aplica la propiedad MSBuild <InvariantTimezone>
con un valor de true
en el archivo del proyecto de la aplicación:
<PropertyGroup>
<InvariantTimezone>true</InvariantTimezone>
</PropertyGroup>
Nota:
<BlazorEnableTimeZoneSupport>
invalida una configuración <InvariantTimezone>
anterior. Se recomienda quitar la configuración <BlazorEnableTimeZoneSupport>
.
Se incluye un archivo de datos para que la información de zona horaria sea correcta. Si la aplicación no necesita esta característica, considera la posibilidad de deshabilitarla estableciendo la propiedad MSBuild <BlazorEnableTimeZoneSupport>
en false
en el archivo del proyecto de la aplicación:
<PropertyGroup>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
</PropertyGroup>
Componente de demostración
El componente CultureExample1
siguiente se puede usar para mostrar los conceptos de globalización y localización de Blazor que se tratan en este artículo.
CultureExample1.razor
:
@page "/culture-example-1"
@using System.Globalization
<h1>Culture Example 1</h1>
<ul>
<li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
<li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>
<h2>Rendered values</h2>
<ul>
<li><b>Date</b>: @dt</li>
<li><b>Number</b>: @number.ToString("N2")</li>
</ul>
<h2><code><input></code> elements that don't set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.CurrentCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input @bind="dt" /></label></li>
<li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>
<h2><code><input></code> elements that set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.InvariantCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
<li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>
@code {
private DateTime dt = DateTime.Now;
private double number = 1999.69;
}
El formato de cadena de número (N2
) del ejemplo anterior (.ToString("N2")
) es un especificador de formato numérico de .NET estándar. El formato N2
es compatible con todos los tipos numéricos, incluye un separador de grupo y representa hasta dos posiciones decimales.
Opcionalmente, agrega un elemento de menú a la navegación en el componente NavMenu
(NavMenu.razor
) para el componente CultureExample1
.
Establecimiento dinámico de la referencia cultural desde el encabezado Accept-Language
Agrega el paquete Microsoft.Extensions.Localization
al proyecto.
El encabezado Accept-Language
lo establece el explorador y se controla mediante las preferencias de idioma del usuario en la configuración del explorador. En la configuración del explorador, un usuario establece uno o varios idiomas preferidos en orden de preferencia. El explorador usa el orden de preferencia para establecer los valores de calidad (q
, 0-1) para cada idioma del encabezado. En el ejemplo siguiente se especifica inglés de Estados Unidos, inglés y español costarriqueño con una preferencia por inglés de Estados Unidos o inglés:
Accept-Language: en-US,en; q=0.9,es-CR; q=0.8
La referencia cultural de la aplicación se establece al asociar el primer idioma solicitado que coincida con una referencia cultural admitida de la aplicación.
En el desarrollo del lado cliente, establece la propiedad BlazorWebAssemblyLoadAllGlobalizationData
en true
en el archivo de proyecto de la aplicación del lado cliente (.csproj
):
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
En el desarrollo del lado cliente, no se admite la configuración dinámica de la referencia cultural desde el encabezado Accept-Language
.
Nota
Si la especificación de la aplicación requiere limitar las referencias culturales admitidas a una lista explícita, consulta la sección Establecimiento dinámico de la referencia cultural del lado cliente según las preferencias del usuario de este artículo.
Las aplicaciones se localizan utilizando Middleware de Localización. Agrega servicios de localización a la aplicación con AddLocalization.
Agrega la siguiente línea al archivo Program
donde se registran los servicios:
builder.Services.AddLocalization();
En el desarrollo del lado servidor, especifique las referencias culturales admitidas de la aplicación antes de cualquier middleware que pueda comprobar la referencia cultural de la solicitud. Por lo general, coloque el middleware de localización de solicitudes inmediatamente antes de llamar a MapRazorComponents. En el ejemplo siguiente se configuran las referencia culturales admitidas para inglés de Estados Unidos y español costarriqueño:
En el desarrollo del lado servidor, especifique las referencias culturales admitidas de la aplicación inmediatamente después de agregar middleware de enrutamiento (UseRouting) a la canalización de procesamiento. En el ejemplo siguiente se configuran las referencia culturales admitidas para inglés de Estados Unidos y español costarriqueño:
app.UseRequestLocalization(new RequestLocalizationOptions()
.AddSupportedCultures(new[] { "en-US", "es-CR" })
.AddSupportedUICultures(new[] { "en-US", "es-CR" }));
Para obtener información sobre cómo ordenar el middleware de localización en la canalización de middleware del archivo Program
, consulta Middleware de ASP.NET Core.
Usa el componente CultureExample1
que se muestra en la sección Componente de demostración para estudiar cómo funciona la globalización. Emite una solicitud con inglés de Estados Unidos (en-US
). Cambia a español costarriqueño (es-CR
) en la configuración de idioma del explorador. Vuelve a solicitar la página web.
Nota
Algunos exploradores te obligan a usar la configuración de idioma predeterminada tanto para las solicitudes como para la propia configuración de la interfaz de usuario del explorador. Esto puede complicar el cambio a un idioma que se entienda, ya que todas las pantallas de la interfaz de usuario de configuración pueden acabar en un idioma que no se puede leer. Un explorador como Opera es una buena opción para realizar pruebas, ya que permite establecer un idioma predeterminado para las solicitudes de páginas web, pero deje la interfaz de usuario de configuración del explorador en su idioma.
Cuando la referencia cultural es inglés de Estados Unidos (en-US
), el componente representado usa el formato de fecha mes/día (6/7
), el formato de 12 horas (AM
/PM
) y separadores de coma en números con un punto para el valor decimal (1,999.69
):
- Fecha: 6/7/2021 6:45:22 AM
- Número: 1,999.69
Cuando la referencia cultural es español costarriqueño (es-CR
), el componente representado usa el formato de fecha día/mes (7/6
), el formato de 24 horas y separadores de punto en números con una coma para el valor decimal (1.999,69
):
- Fecha: 7/6/2021 6:49:38
- Número: 1.999,69
Establecimiento estático de la referencia cultural del lado cliente
Establece la propiedad BlazorWebAssemblyLoadAllGlobalizationData
en true
en el archivo del proyecto de la aplicación (.csproj
):
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
La configuración del enlazador de lenguaje intermedio (IL) para la representación en el lado del cliente elimina la información de internacionalización excepto para las configuraciones regionales solicitadas explícitamente. Para obtener más información, consulta Configuración del enlazador de ASP.NET Core Blazor.
La referencia cultural de la aplicación se puede establecer en JavaScript cuando Blazor comienza con la opción de inicio applicationCulture
de Blazor. En el ejemplo siguiente se configura la aplicación para que se inicie con la referencia cultural de inglés de Estados Unidos (en-US
).
Evita el inicio automático de Blazor agregando autostart="false"
a a la Blazoretiqueta <script>
:
<script src="{BLAZOR SCRIPT}" autostart="false"></script>
En el ejemplo anterior, el marcador de posición {BLAZOR SCRIPT}
es la ruta de acceso del script y el nombre de archivo Blazor. Para obtener la ubicación del script, consulta la estructura del proyecto ASP.NET CoreBlazor.
Agrega el siguiente bloque <script>
después de la etiqueta <script>
de Blazor y antes de la etiqueta de cierre </body>
:
Blazor Web App:
<script>
Blazor.start({
webAssembly: {
applicationCulture: 'en-US'
}
});
</script>
Blazor WebAssembly independiente:
<script>
Blazor.start({
applicationCulture: 'en-US'
});
</script>
El valor de applicationCulture
debe ajustarse al formato de etiqueta de idioma BCP-47. Para obtener más información sobre el inicio de Blazor, consulta Inicio de Blazor en ASP.NET Core.
Una alternativa a establecer la opción de inicio Blazor de la referencia cultural es definir la referencia cultural en código de C#. Establece CultureInfo.DefaultThreadCurrentCulture y CultureInfo.DefaultThreadCurrentUICulture en el archivo Program
en la misma referencia cultural.
Agrega el espacio de nombres System.Globalization al archivo Program
:
using System.Globalization;
Agrega la configuración de la referencia cultural antes de la línea que compila y ejecuta WebAssemblyHostBuilder (await builder.Build().RunAsync();
):
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");
Nota:
Actualmente las aplicaciones de Blazor WebAssembly solo cargan recursos basados en DefaultThreadCurrentCulture. Para obtener más información, consulta Blazor WASM solo se basa en la referencia cultural actual (no se respeta la referencia cultural actual de la interfaz de usuario) (dotnet/aspnetcore
#56824).
Usa el componente CultureExample1
que se muestra en la sección Componente de demostración para estudiar cómo funciona la globalización. Emite una solicitud con inglés de Estados Unidos (en-US
). Cambia a español costarriqueño (es-CR
) en la configuración de idioma del explorador. Vuelve a solicitar la página web. Cuando el idioma solicitado es Español costarriqueño, la referencia cultural de la aplicación se mantiene como inglés de Estados Unidos (en-US
).
Establecimiento estático de la referencia cultural del lado servidor
Las aplicaciones del lado servidor se localizan mediante un middleware de localización. Agrega servicios de localización a la aplicación con AddLocalization.
En el archivo Program
:
builder.Services.AddLocalization();
Especifique la referencia cultural estática en el Program
archivo antes de cualquier middleware que pueda comprobar la referencia cultural de la solicitud. Por lo general, coloque el middleware de localización de solicitudes inmediatamente antes de MapRazorComponents. En el ejemplo siguiente se configura inglés de Estados Unidos:
Especifique la referencia cultural estática en el Program
archivo inmediatamente después de agregar middleware de enrutamiento (UseRouting) a la canalización de procesamiento. En el ejemplo siguiente se configura inglés de Estados Unidos:
app.UseRequestLocalization("en-US");
El valor de la referencia cultural de UseRequestLocalization debe ajustarse al formato de etiqueta de idioma BCP-47.
Para obtener información sobre cómo ordenar el middleware de localización en la canalización de middleware del archivo Program
, consulta Middleware de ASP.NET Core.
Las aplicaciones del lado servidor se localizan mediante un middleware de localización. Agrega servicios de localización a la aplicación con AddLocalization.
En Startup.ConfigureServices
(Startup.cs
):
services.AddLocalization();
Especifica la referencia cultural estática en Startup.Configure
(Startup.cs
) inmediatamente después de agregar el middleware de enrutamiento a la canalización de procesamiento. En el ejemplo siguiente se configura inglés de Estados Unidos:
app.UseRequestLocalization("en-US");
El valor de la referencia cultural de UseRequestLocalization debe ajustarse al formato de etiqueta de idioma BCP-47.
Para obtener información sobre cómo ordenar el middleware de localización en la canalización de middleware de Startup.Configure
, consulta Middleware de ASP.NET Core.
Usa el componente CultureExample1
que se muestra en la sección Componente de demostración para estudiar cómo funciona la globalización. Emite una solicitud con inglés de Estados Unidos (en-US
). Cambia a español costarriqueño (es-CR
) en la configuración de idioma del explorador. Vuelve a solicitar la página web. Cuando el idioma solicitado es Español costarriqueño, la referencia cultural de la aplicación se mantiene como inglés de Estados Unidos (en-US
).
Establecimiento dinámico de la referencia cultural del lado cliente según las preferencias del usuario
Entre los ejemplos de ubicaciones en las que una aplicación podría almacenar las preferencias de un usuario se incluyen el almacenamiento local del explorador (común en escenarios del lado cliente), en una localización cookie o base de datos (común en escenarios del lado servidor) o en un servicio externo asociado a una base de datos externa y al que tiene acceso una API web. En el ejemplo siguiente se muestra cómo usar el almacenamiento local del explorador.
Agrega el paquete Microsoft.Extensions.Localization
al proyecto:
Nota
Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulta los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (documentación de NuGet). Confirma las versiones correctas del paquete en NuGet.org.
Establece la propiedad BlazorWebAssemblyLoadAllGlobalizationData
en true
en el archivo del proyecto:
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
La referencia cultural de la aplicación para la representación del lado cliente (CSR) se establece mediante la API del marco Blazor. La selección de la referencia cultural de un usuario se puede conservar en el almacenamiento local del explorador.
Proporciona funciones de JS después de la etiqueta Blazor de <script>
para obtener y establecer la selección de la referencia cultural del usuario con el almacenamiento local del explorador:
<script>
window.blazorCulture = {
get: () => window.localStorage['BlazorCulture'],
set: (value) => window.localStorage['BlazorCulture'] = value
};
</script>
Nota:
En el ejemplo anterior se contamina el cliente con funciones globales. Para obtener un mejor enfoque en las aplicaciones de producción, consulta Aislamiento de JavaScript en módulos de JavaScript.
Agrega los espacios de nombres para System.Globalization y Microsoft.JSInterop al principio del archivo Program
:
using System.Globalization;
using Microsoft.JSInterop;
Quita las siguientes líneas:
- await builder.Build().RunAsync();
Reemplaza la línea anterior por el código siguiente. El código agrega el servicio de localización de Blazor a la colección de servicios de la aplicación con AddLocalization y usa la interoperabilidad de JS para llamar a JS y recuperar la selección de referencia cultural del usuario del almacenamiento local. Si el almacenamiento local no contiene ninguna referencia cultural para el usuario, el código establece un valor predeterminado de inglés de Estados Unidos (en-US
).
builder.Services.AddLocalization();
var host = builder.Build();
const string defaultCulture = "en-US";
var js = host.Services.GetRequiredService<IJSRuntime>();
var result = await js.InvokeAsync<string>("blazorCulture.get");
var culture = CultureInfo.GetCultureInfo(result ?? defaultCulture);
if (result == null)
{
await js.InvokeVoidAsync("blazorCulture.set", defaultCulture);
}
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
await host.RunAsync();
Nota:
Actualmente las aplicaciones de Blazor WebAssembly solo cargan recursos basados en DefaultThreadCurrentCulture. Para obtener más información, consulta Blazor WASM solo se basa en la referencia cultural actual (no se respeta la referencia cultural actual de la interfaz de usuario) (dotnet/aspnetcore
#56824).
El componente CultureSelector
siguiente muestra cómo realizar las siguientes acciones:
- Establece la selección de la referencia cultural del usuario en el almacenamiento local del explorador a través de la interoperabilidad de JS.
- Vuelve a cargar el componente que solicitaste (
forceLoad: true
), que usa la referencia cultural actualizada.
CultureSelector.razor
:
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select @bind="selectedCulture" @bind:after="ApplySelectedCultureAsync">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task ApplySelectedCultureAsync()
{
if (CultureInfo.CurrentCulture != selectedCulture)
{
await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);
Navigation.NavigateTo(Navigation.Uri, forceLoad: true);
}
}
}
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select value="@selectedCulture" @onchange="HandleSelectedCultureChanged">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task HandleSelectedCultureChanged(ChangeEventArgs args)
{
selectedCulture = CultureInfo.GetCultureInfo((string)args.Value!);
if (CultureInfo.CurrentCulture != selectedCulture)
{
await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);
Navigation.NavigateTo(Navigation.Uri, forceLoad: true);
}
}
}
Nota:
Para obtener más información sobre IJSInProcessRuntime, consulta Llamada a métodos de funciones de JavaScript en Blazor de ASP.NET Core.
Dentro de la etiqueta de cierre del elemento </main>
del componente MainLayout
(MainLayout.razor
), agrega el componente CultureSelector
:
<article class="bottom-row px-4">
<CultureSelector />
</article>
Usa el componente CultureExample1
que se muestra en la sección Componente de demostración para estudiar cómo funciona el ejemplo anterior.
Establecimiento dinámico de la referencia cultural del lado servidor según las preferencias del usuario
Entre los ejemplos de ubicaciones en las que una aplicación podría almacenar las preferencias de un usuario se incluyen el almacenamiento local del explorador (común en escenarios del lado cliente), en una localización cookie o base de datos (común en escenarios del lado servidor) o en un servicio externo asociado a una base de datos externa y al que tiene acceso una API web. En el siguiente ejemplo se muestra cómo usar una cookie de localización.
Nota:
En el ejemplo siguiente se supone que la aplicación adopta la interactividad global especificando la representación interactiva del lado del servidor en el componente Routes
del componente App
(Components/App.razor
):
<Routes @rendermode="InteractiveServer" />
Si la aplicación adopta la interactividad por página o componente, consulta los comentarios al final de esta sección para modificar los modos de representación de los componentes del ejemplo.
Agrega el paquete Microsoft.Extensions.Localization
al proyecto.
Nota
Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulta los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (documentación de NuGet). Confirma las versiones correctas del paquete en NuGet.org.
Las aplicaciones del lado servidor se localizan mediante un middleware de localización. Agrega servicios de localización a la aplicación con AddLocalization.
En el archivo Program
:
builder.Services.AddLocalization();
Establece las referencia culturales predeterminadas y admitidas de la aplicación con RequestLocalizationOptions.
Antes de llamar a MapRazorComponents en la canalización de procesamiento de solicitudes, coloca el código siguiente:
Después de agregar middleware de enrutamiento (UseRouting) a la canalización de procesamiento de solicitudes, coloque el código siguiente:
var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Para obtener información sobre cómo ordenar el middleware de localización en la canalización de middleware, consulta Middleware de ASP.NET Core.
En el siguiente ejemplo se muestra cómo establecer la referencia cultural actual en una cookie que el middleware de localización puede leer.
Los siguientes espacios de nombres son necesarios para el componente App
:
Agrega lo siguiente a la parte superior del archivo de componente de App
(Components/App.razor
):
@using System.Globalization
@using Microsoft.AspNetCore.Localization
Agrega el siguiente bloque @code
a la parte inferior del archivo de componente App
:
@code {
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
protected override void OnInitialized()
{
HttpContext?.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(
CultureInfo.CurrentCulture,
CultureInfo.CurrentUICulture)));
}
}
Las modificaciones en el archivo Pages/_Host.cshtml
requieren los siguientes espacios de nombres:
Agrega el siguiente código al archivo:
@using System.Globalization
@using Microsoft.AspNetCore.Localization
@{
this.HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(
CultureInfo.CurrentCulture,
CultureInfo.CurrentUICulture)));
}
Para obtener información sobre cómo ordenar el middleware de localización en la canalización de middleware, consulta Middleware de ASP.NET Core.
Si la aplicación no está configurada para procesar acciones del controlador:
Agrega servicios de MVC mediante una llamada a AddControllers en la colección de servicios en el archivo
Program
:builder.Services.AddControllers();
Agrega el enrutamiento del punto de conexión del controlador en el archivo de
Program
llamando a MapControllers en el IEndpointRouteBuilder (app
):app.MapControllers();
Para especificar una interfaz de usuario que permita a un usuario seleccionar una referencia cultural, usa un método basado en el redireccionamiento con una cookie de localización. La aplicación conserva la referencia cultural seleccionada por el usuario a través de un redireccionamiento a un controlador. Este controlador establece la referencia cultural seleccionada del usuario en una cookie y redirige al usuario de nuevo al URI original. El proceso es similar a lo que ocurre en una aplicación web cuando un usuario intenta acceder a un recurso seguro, donde se redirige al usuario a una página de inicio de sesión y, después, se le redirige nuevamente de vuelta al recurso original.
Controllers/CultureController.cs
:
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
[Route("[controller]/[action]")]
public class CultureController : Controller
{
public IActionResult Set(string culture, string redirectUri)
{
if (culture != null)
{
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(culture, culture)));
}
return LocalRedirect(redirectUri);
}
}
Advertencia
Usa el resultado de la acción LocalRedirect, como se muestra en el ejemplo anterior, para evitar ataques de redirección abiertos. Para obtener más información, consulta Prevención de ataques de redireccionamiento abierto en ASP.NET Core.
El componente CultureSelector
siguiente muestra cómo llamar al método Set
con la nueva referencia cultural CultureController
. El componente se coloca en la carpeta Shared
para su uso en toda la aplicación.
CultureSelector.razor
:
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select @bind="selectedCulture" @bind:after="ApplySelectedCultureAsync">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task ApplySelectedCultureAsync()
{
if (CultureInfo.CurrentCulture != selectedCulture)
{
var uri = new Uri(Navigation.Uri)
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
var uriEscaped = Uri.EscapeDataString(uri);
Navigation.NavigateTo(
$"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
forceLoad: true);
}
}
}
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select value="@selectedCulture" @onchange="HandleSelectedCultureChanged">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
</label>
</p>
@code
{
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task HandleSelectedCultureChanged(ChangeEventArgs args)
{
selectedCulture = CultureInfo.GetCultureInfo((string)args.Value!);
if (CultureInfo.CurrentCulture != selectedCulture)
{
var uri = new Uri(Navigation.Uri)
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
var uriEscaped = Uri.EscapeDataString(uri);
Navigation.NavigateTo(
$"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
forceLoad: true);
}
}
}
Agrega el componente CultureSelector
al componente MainLayout
. Coloca el siguiente marcado dentro de la etiqueta de cierre </main>
en el archivo Components/Layout/MainLayout.razor
:
Agrega el componente CultureSelector
al componente MainLayout
. Coloca el siguiente marcado dentro de la etiqueta de cierre </main>
en el archivo Shared/MainLayout.razor
:
<article class="bottom-row px-4">
<CultureSelector />
</article>
Usa el componente CultureExample1
que se muestra en la sección Componente de demostración para estudiar cómo funciona el ejemplo anterior.
En el ejemplo anterior se supone que la aplicación adopta la interactividad global especificando el modo de representación del Servidor interactivo en el componente Routes
del componente App
(Components/App.razor
):
<Routes @rendermode="InteractiveServer" />
Si la aplicación adopta la interactividad por página o componente, realice los cambios siguientes:
Agrega el modo de representación interactiva del lado del servidor en la parte superior del archivo de componente de
CultureExample1
(Components/Pages/CultureExample1.razor
):@rendermode InteractiveServer
En el diseño principal de la aplicación (
Components/Layout/MainLayout.razor
), aplica el modo de representación interactiva del lado del servidor al componenteCultureSelector
:<CultureSelector @rendermode="InteractiveServer" />
Establecimiento dinámico de la referencia cultural en una Blazor Web App por preferencia de usuario
Esta sección se aplica a Blazor Web App que adoptan la interactividad automática (servidor y WebAssembly).
Entre los ejemplos de ubicaciones en las que una aplicación puede almacenar las preferencias de un usuario se incluyen el almacenamiento local del navegador (habitual en escenarios del lado cliente), en un objeto cookie de localización o base de datos (habitual en escenarios del lado servidor), tanto el almacenamiento local como un objeto cookie de localización (Blazor Web App con componentes de servidor y WebAssembly), o en un servicio externo conectado a una base de datos externa y al que se accede mediante una API web. En el siguiente ejemplo se muestra cómo usar el almacenamiento local del explorador para los componentes representados en el lado cliente (CSR) y un cookie de localización para los componentes representados en el lado servidor (SSR).
Actualizaciones del proyecto de .Client
Agrega el paquete Microsoft.Extensions.Localization
al proyecto de .Client
.
Nota:
Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulta los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (documentación de NuGet). Confirma las versiones correctas del paquete en NuGet.org.
Establece la propiedad BlazorWebAssemblyLoadAllGlobalizationData
en true
en el archivo de proyecto de .Client
:
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
Agrega los espacios de nombres para System.Globalization y Microsoft.JSInterop a la parte superior del archivo Program
del proyecto de .Client
:
using System.Globalization;
using Microsoft.JSInterop;
Quita las siguientes líneas:
- await builder.Build().RunAsync();
Reemplaza la línea anterior por el código siguiente. El código agrega el servicio de localización de Blazor a la colección de servicios de la aplicación con AddLocalization y usa la interoperabilidad de JS para llamar a JS y recuperar la selección de referencia cultural del usuario del almacenamiento local. Si el almacenamiento local no contiene ninguna referencia cultural para el usuario, el código establece un valor predeterminado de inglés de Estados Unidos (en-US
).
builder.Services.AddLocalization();
var host = builder.Build();
const string defaultCulture = "en-US";
var js = host.Services.GetRequiredService<IJSRuntime>();
var result = await js.InvokeAsync<string>("blazorCulture.get");
var culture = CultureInfo.GetCultureInfo(result ?? defaultCulture);
if (result == null)
{
await js.InvokeVoidAsync("blazorCulture.set", defaultCulture);
}
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
await host.RunAsync();
Nota:
Actualmente las aplicaciones de Blazor WebAssembly solo cargan recursos basados en DefaultThreadCurrentCulture. Para obtener más información, consulta Blazor WASM solo se basa en la referencia cultural actual (no se respeta la referencia cultural actual de la interfaz de usuario) (dotnet/aspnetcore
#56824).
Agrega el siguiente componente CultureSelector
al proyecto de .Client
.
El componente adopta los siguientes enfoques para trabajar con componentes de SSR o CSR:
- Un diccionario proporciona el nombre para mostrar de cada referencia cultural disponible en la lista desplegable, ya que los datos de globalización del lado cliente incluyen texto localizado de la referencia cultural que proporcionan los datos de globalización del lado servidor. Por ejemplo, la localización del lado servidor muestra
English (United States)
cuandoen-US
es la referencia cultural yIngles ()
cuando se usa una referencia cultural diferente. Dado que la localización de los nombres para mostrar de la referencia cultural no está disponible con globalización Blazor WebAssembly, el nombre para mostrar del inglés de Estados Unidos en el cliente para cualquier referencia cultural cargada es simplementeen-US
. El uso de un diccionario personalizado permite que el componente muestre al menos nombres de referencia cultural en inglés completos. - Cuando el usuario cambia la referencia cultural, la interoperabilidad JS establece la referencia cultural en el almacenamiento del explorador local y una acción del controlador actualiza la localización de cookie con la referencia cultural. El controlador se añade a la aplicación más adelante, en la sección Actualizaciones del proyecto de servidor.
Pages/CultureSelector.razor
:
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation
<p>
<label>
Select your locale:
<select @bind="@selectedCulture" @bind:after="ApplySelectedCultureAsync">
@foreach (var culture in supportedCultures)
{
<option value="@culture">@cultureDict[culture.Name]</option>
}
</select>
</label>
</p>
@code
{
private Dictionary<string, string> cultureDict =
new()
{
{ "en-US", "English (United States)" },
{ "es-CR", "Spanish (Costa Rica)" }
};
private CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("es-CR"),
};
private CultureInfo? selectedCulture;
protected override void OnInitialized()
{
selectedCulture = CultureInfo.CurrentCulture;
}
private async Task ApplySelectedCultureAsync()
{
if (CultureInfo.CurrentCulture != selectedCulture)
{
await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);
var uri = new Uri(Navigation.Uri)
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
var uriEscaped = Uri.EscapeDataString(uri);
Navigation.NavigateTo(
$"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
forceLoad: true);
}
}
}
Nota:
Para obtener más información sobre IJSInProcessRuntime, consulta Llamada a métodos de funciones de JavaScript en Blazor de ASP.NET Core.
En el proyecto .Client
, coloca el siguiente componente de CultureClient
para estudiar cómo funciona la globalización para los componentes de CSR.
Pages/CultureClient.razor
:
@page "/culture-client"
@rendermode InteractiveWebAssembly
@using System.Globalization
<PageTitle>Culture Client</PageTitle>
<h1>Culture Client</h1>
<ul>
<li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
<li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>
<h2>Rendered values</h2>
<ul>
<li><b>Date</b>: @dt</li>
<li><b>Number</b>: @number.ToString("N2")</li>
</ul>
<h2><code><input></code> elements that don't set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.CurrentCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input @bind="dt" /></label></li>
<li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>
<h2><code><input></code> elements that set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.InvariantCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
<li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>
@code {
private DateTime dt = DateTime.Now;
private double number = 1999.69;
}
Actualizaciones del proyecto de servidor
Agrega el paquete Microsoft.Extensions.Localization
al proyecto de servidor.
Nota:
Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulta los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (documentación de NuGet). Confirma las versiones correctas del paquete en NuGet.org.
Las aplicaciones del lado servidor se localizan mediante un middleware de localización. Agrega servicios de localización a la aplicación con AddLocalization.
En el archivo Program
del proyecto de servidor donde se registran los servicios:
builder.Services.AddLocalization();
Establece las referencia culturales predeterminadas y admitidas de la aplicación con RequestLocalizationOptions.
Antes de llamar a MapRazorComponents en la canalización de procesamiento de solicitudes, coloca el código siguiente:
var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
En el siguiente ejemplo se muestra cómo establecer la referencia cultural actual en una cookie que el middleware de localización puede leer.
Los siguientes espacios de nombres son necesarios para el componente App
:
Agrega lo siguiente a la parte superior del archivo de componente de App
(Components/App.razor
):
@using System.Globalization
@using Microsoft.AspNetCore.Localization
La referencia cultural de la aplicación para la representación del lado cliente (CSR) se establece mediante la API del marco Blazor. La selección de referencia cultural de un usuario se puede conservar en el almacenamiento local del explorador para los componentes de CSR.
Después de la etiqueta <script>
de Blazor, proporciona funciones JS para obtener y establecer la selección de referencia cultural del usuario con el almacenamiento local del explorador:
<script>
window.blazorCulture = {
get: () => window.localStorage['BlazorCulture'],
set: (value) => window.localStorage['BlazorCulture'] = value
};
</script>
Nota:
En el ejemplo anterior se contamina el cliente con funciones globales. Para obtener un mejor enfoque en las aplicaciones de producción, consulta Aislamiento de JavaScript en módulos de JavaScript.
Agrega el siguiente bloque @code
a la parte inferior del archivo de componente de App
:
@code {
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
protected override void OnInitialized()
{
HttpContext?.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(
CultureInfo.CurrentCulture,
CultureInfo.CurrentUICulture)));
}
}
Si el proyecto de servidor no está configurado para procesar las acciones del controlador:
Agrega servicios de MVC mediante una llamada a AddControllers en la colección de servicios en el archivo
Program
:builder.Services.AddControllers();
Agrega el enrutamiento del punto de conexión del controlador en el archivo de
Program
llamando a MapControllers en el IEndpointRouteBuilder (app
):app.MapControllers();
Para permitir que un usuario seleccione una referencia cultural para los componentes de SSR, usa un enfoque basado en redireccionamiento con un cookie de localización. La aplicación conserva la referencia cultural seleccionada por el usuario a través de un redireccionamiento a un controlador. Este controlador establece la referencia cultural seleccionada del usuario en una cookie y redirige al usuario de nuevo al URI original. El proceso es similar a lo que ocurre en una aplicación web cuando un usuario intenta acceder a un recurso seguro, donde se redirige al usuario a una página de inicio de sesión y, después, se le redirige nuevamente de vuelta al recurso original.
Controllers/CultureController.cs
:
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
[Route("[controller]/[action]")]
public class CultureController : Controller
{
public IActionResult Set(string culture, string redirectUri)
{
if (culture != null)
{
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(culture, culture)));
}
return LocalRedirect(redirectUri);
}
}
Advertencia
Usa el resultado de la acción LocalRedirect, como se muestra en el ejemplo anterior, para evitar ataques de redirección abiertos. Para obtener más información, consulta Prevención de ataques de redireccionamiento abierto en ASP.NET Core.
Agrega el componente CultureSelector
al componente MainLayout
. Coloca el siguiente marcado dentro de la etiqueta de cierre </main>
en el archivo Components/Layout/MainLayout.razor
:
<article class="bottom-row px-4">
<CultureSelector @rendermode="InteractiveAuto" />
</article>
Usa el componente CultureExample1
que se muestra en la sección Componente de demostración para estudiar cómo funciona el ejemplo anterior.
En el proyecto de servidor, coloca el siguiente componente de CultureServer
para estudiar cómo funciona la globalización para los componentes de SSR.
Components/Pages/CultureServer.razor
:
@page "/culture-server"
@rendermode InteractiveServer
@using System.Globalization
<PageTitle>Culture Server</PageTitle>
<h1>Culture Server</h1>
<ul>
<li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
<li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>
<h2>Rendered values</h2>
<ul>
<li><b>Date</b>: @dt</li>
<li><b>Number</b>: @number.ToString("N2")</li>
</ul>
<h2><code><input></code> elements that don't set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.CurrentCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input @bind="dt" /></label></li>
<li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>
<h2><code><input></code> elements that set a <code>type</code></h2>
<p>
The following <code><input></code> elements use
<code>CultureInfo.InvariantCulture</code>.
</p>
<ul>
<li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
<li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>
@code {
private DateTime dt = DateTime.Now;
private double number = 1999.69;
}
Agrega los componentes CultureClient
y CultureServer
a la navegación de la barra lateral en Components/Layout/NavMenu.razor
:
<div class="nav-item px-3">
<NavLink class="nav-link" href="culture-server">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Culture (Server)
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="culture-client">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Culture (Client)
</NavLink>
</div>
Componentes automáticos interactivos
Las instrucciones de esta sección también funcionan para los componentes que adoptan el modo de representación automática interactiva:
@rendermode InteractiveAuto
Localización
Si la aplicación aún no admite la selección de referencia cultural dinámica, agregue el paquete Microsoft.Extensions.Localization
a la aplicación.
Nota
Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulta los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (documentación de NuGet). Confirma las versiones correctas del paquete en NuGet.org.
Localización del lado cliente
Establece la propiedad BlazorWebAssemblyLoadAllGlobalizationData
en true
en el archivo del proyecto de la aplicación (.csproj
):
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
En el archivo Program
, agrega el espacio de nombres para System.Globalization en la parte superior del archivo:
using System.Globalization;
Agrega el servicio de localización de Blazor a la colección de servicios de la aplicación con AddLocalization:
builder.Services.AddLocalization();
Localización del lado servidor
Usa el middleware de localización para establecer la referencia cultural de la aplicación.
Si la aplicación aún no admite la selección de referencia cultural dinámica:
- Agrega servicios de localización a la aplicación con AddLocalization.
- Especifica las referencia culturales predeterminadas y admitidas de la aplicación en el archivo
Program
. En el ejemplo siguiente se configuran las referencia culturales admitidas para inglés de Estados Unidos y español costarriqueño.
builder.Services.AddLocalization();
Coloque el middleware de localización de solicitudes antes de cualquier middleware que pueda comprobar la referencia cultural de la solicitud. Por lo general, coloque el middleware inmediatamente antes de llamar a MapRazorComponents:
Inmediatamente después de agregar middleware de enrutamiento (UseRouting) a la canalización de procesamiento:
var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Para obtener información sobre cómo ordenar el middleware de localización en la canalización de middleware, consulta Middleware de ASP.NET Core.
- Agrega servicios de localización a la aplicación con AddLocalization.
- Especifica las referencia culturales predeterminadas y admitidas de la aplicación en
Startup.Configure
(Startup.cs
). En el ejemplo siguiente se configuran las referencia culturales admitidas para inglés de Estados Unidos y español costarriqueño.
En Startup.ConfigureServices
(Startup.cs
):
services.AddLocalization();
Inmediatamente Startup.Configure
después de agregar middleware de enrutamiento (UseRouting) a la canalización de procesamiento:
var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Para obtener información sobre cómo ordenar el middleware de localización en la canalización de middleware de Startup.Configure
, consulta Middleware de ASP.NET Core.
Si la aplicación debe localizar los recursos en función del almacenamiento de la configuración de referencia cultural de un usuario, usa una referencia cultural de localización cookie. El uso de una cookie garantiza que la conexión WebSocket puede propagar correctamente la referencia cultural. Si los esquemas de localización se basan en la ruta de acceso URL o en la cadena de consulta, puede que el esquema no funcione con WebSockets, por lo que no se podrá conservar la referencia cultural. Por lo tanto, el enfoque recomendado es usar una cookie de referencia cultural de localización. Consulta la sección Establecimiento dinámico de la referencia cultural del lado servidor según las preferencias del usuario de este artículo para ver una expresión Razor de ejemplo que conserva la selección de referencia cultural del usuario.
Ejemplo de recursos localizados
El ejemplo de recursos localizados de esta sección funciona con los ejemplos anteriores de este artículo, donde las referencia culturales admitidas de la aplicación son inglés (en
) como configuración regional predeterminada y español (es
) como configuración regional alternativa que el usuario puede seleccionar o que el explorador puede especificar.
Crea un archivo de recursos para cada configuración regional. En el ejemplo siguiente, se crean recursos para una cadena Greeting
en inglés y español:
- Inglés (
en
):Hello, World!
- Español (
es
):¡Hola, Mundo!
Nota:
El siguiente archivo de recursos se puede agregar en Visual Studio; para ello, haz clic con el botón derecho en la carpeta Pages
y selecciona Agregar>Nuevo elemento>Archivo de recursos. Asigna al archivo el nombre CultureExample2.resx
. Cuando aparezca el editor, proporciona datos para una nueva entrada. Establece el Nombre en Greeting
y el Valor en Hello, World!
. Guarda el archivo.
Si usas Visual Studio Code, se recomienda instalar el Visor y editor ResX de Tim Heuer. Agrega un archivo CultureExample2.resx
vacío a la carpeta Pages
. La extensión se encarga automáticamente de administrar el archivo en la interfaz de usuario. Selecciona el botón Agregar nuevo recurso. Sigue las instrucciones a fin de agregar una entrada para Greeting
(clave), Hello, World!
(valor) y None
(comentario). Guarda el archivo. Si cierras y vuelves a abrir el archivo, podrás ver el recurso Greeting
.
El visor y editor ResX de Tim Heuer no es propiedad de Microsoft ni está cubierto por ningún contrato ni licencia de Soporte técnico de Microsoft.
A continuación se muestra un archivo de recursos típico. Puedes colocar manualmente los archivos de recursos en la carpeta Pages
de la aplicación si prefieres no usar herramientas integradas con un entorno de desarrollo integrado (IDE), como el editor de archivos de recursos integrado de Visual Studio o Visual Studio Code con una extensión para crear y editar archivos de recursos.
Pages/CultureExample2.resx
:
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Greeting" xml:space="preserve">
<value>Hello, World!</value>
</data>
</root>
Nota:
El siguiente archivo de recursos se puede agregar en Visual Studio; para ello, haz clic con el botón derecho en la carpeta Pages
y selecciona Agregar>Nuevo elemento>Archivo de recursos. Asigna al archivo el nombre CultureExample2.es.resx
. Cuando aparezca el editor, proporciona datos para una nueva entrada. Establece el Nombre en Greeting
y el Valor en ¡Hola, Mundo!
. Guarda el archivo.
Si usas Visual Studio Code, se recomienda instalar el Visor y editor ResX de Tim Heuer. Agrega un archivo CultureExample2.resx
vacío a la carpeta Pages
. La extensión se encarga automáticamente de administrar el archivo en la interfaz de usuario. Selecciona el botón Agregar nuevo recurso. Sigue las instrucciones a fin de agregar una entrada para Greeting
(clave), ¡Hola, Mundo!
(valor) y None
(comentario). Guarda el archivo. Si cierras y vuelves a abrir el archivo, podrás ver el recurso Greeting
.
A continuación se muestra un archivo de recursos típico. Puedes colocar manualmente los archivos de recursos en la carpeta Pages
de la aplicación si prefieres no usar herramientas integradas con un entorno de desarrollo integrado (IDE), como el editor de archivos de recursos integrado de Visual Studio o Visual Studio Code con una extensión para crear y editar archivos de recursos.
Pages/CultureExample2.es.resx
:
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Greeting" xml:space="preserve">
<value>¡Hola, Mundo!</value>
</data>
</root>
El componente siguiente muestra el uso de la cadena Greeting
localizada con IStringLocalizer<T>. El Razormarcado@Loc["Greeting"]
del ejemplo siguiente localiza la cadena con clave en el valor Greeting
, que se establece en los archivos de recursos anteriores.
Agrega el espacio de nombres para Microsoft.Extensions.Localization al archivo _Imports.razor
de la aplicación:
@using Microsoft.Extensions.Localization
CultureExample2.razor
:
@page "/culture-example-2"
@using System.Globalization
@inject IStringLocalizer<CultureExample2> Loc
<h1>Culture Example 2</h1>
<ul>
<li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
<li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>
<h2>Greeting</h2>
<p>
@Loc["Greeting"]
</p>
<p>
@greeting
</p>
@code {
private string? greeting;
protected override void OnInitialized()
{
greeting = Loc["Greeting"];
}
}
Opcionalmente, agrega un elemento de menú para el componente CultureExample2
a la navegación en el componente NavMenu
(NavMenu.razor
).
Origen de referencia del proveedor de referencia cultural de WebAssembly
Para comprender mejor cómo procesa el marco Blazor la localización de procesos, consulta la clase WebAssemblyCultureProvider
en el código fuente de referencia de ASP.NET Core.
Nota
Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, usa la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, consulta Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Recursos compartidos
Para crear recursos compartidos de localización, adopta el siguiente enfoque.
Crea una clase ficticia con un nombre de clase arbitrario. En el ejemplo siguiente:
- La aplicación usa el espacio de nombres
BlazorSample
y los recursos de localización usan el espacio de nombresBlazorSample.Localization
. - La clase ficticia se denomina
SharedResource
. - El archivo de clase se coloca en una carpeta
Localization
en la raíz de la aplicación.
Localization/SharedResource.cs
:namespace BlazorSample.Localization; public class SharedResource { }
- La aplicación usa el espacio de nombres
Crea los archivos de recursos compartidos con una acción de compilación de
Embedded resource
. En el ejemplo siguiente:Los archivos se colocan en la carpeta
Localization
con la claseSharedResource
ficticia (Localization/SharedResource.cs
).Asigna un nombre a los archivos de recursos para que coincida con el nombre de la clase ficticia. En los siguientes archivos de ejemplo se incluyen un archivo de localización predeterminado y un archivo para la localización en español (
es
).Localization/SharedResource.resx
Localization/SharedResource.es.resx
Advertencia
Si sigues el planteamiento de esta sección, no podrás establecer LocalizationOptions.ResourcesPath y usar IStringLocalizerFactory.Create simultáneamente para cargar recursos.
Para hacer referencia a la clase ficticia para un elemento IStringLocalizer<T> insertado en un componente Razor, coloca una directiva
@using
para el espacio de nombres de localización o incluye el espacio de nombres de localización en la referencia de clase ficticia. En los siguientes ejemplos:- En el primer ejemplo se indica el espacio de nombres
Localization
para la clase ficticiaSharedResource
con una directiva@using
. - En el segundo ejemplo se indica el espacio de nombres de la clase ficticia
SharedResource
explícitamente.
En un componente Razor, usa cualquiera de los enfoques siguientes:
@using Localization @inject IStringLocalizer<SharedResource> Loc
@inject IStringLocalizer<Localization.SharedResource> Loc
- En el primer ejemplo se indica el espacio de nombres
Para obtener orientación adicional, consulta Globalización y localización en ASP.NET Core.
Anulación de ubicación mediante el panel "Sensores" en las herramientas de desarrollo
Al usar la invalidación de ubicación mediante el panel Sensores en Google Chrome o las herramientas de desarrollo de Microsoft Edge, el idioma alternativo se restablece después de la representación previa. Evita establecer el idioma mediante el panel Sensores al realizar pruebas. Establece el idioma mediante la configuración de idioma del explorador.
Para obtener más información, consulta Localización Blazor no funciona con InteractiveServer (dotnet/aspnetcore
#53707).
Recursos adicionales
- Establecimiento de la ruta de acceso base de la aplicación
- Globalización y localización en 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
- La llamada a
InvokeAsync(StateHasChanged)
hace que la página vuelva a la referencia cultural predeterminada (dotnet/aspnetcore #28521) - Localización Blazor no funciona con InteractiveServer (
dotnet/aspnetcore
#53707) (Location override using "Sensors" pane)