Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Nota
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la directiva de compatibilidad de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 9 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 de .NET 9 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:
Soportadas:IStringLocalizer y IStringLocalizer<T> están soportadas en las aplicaciones Blazor.
No se admite:IHtmlLocalizer y IViewLocalizer son características de MVC de ASP.NET Core y no se admiten en aplicaciones Blazor.
Para aplicaciones Blazor, se admiten mensajes de validación localizados para la validación de formularios usando anotaciones de datos si DisplayAttribute.ResourceType y ValidationAttribute.ErrorMessageResourceType están implementados.
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 lo define el explorador en función de las preferencias de idioma del usuario reflejadas en la configuración del explorador. - Una referencia cultural establecida por la aplicación que no está basada 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 dentro de 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 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 "cultura" 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 establecerse dinámicamente el valor de document.documentElement.lang con JS interop.
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 apuntar a .NET 5 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):
datenumber
Los tipos de campo anteriores:
- Se muestran según las reglas de formato del navegador 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 la funcionalidad integrada para mostrar 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-localmonthweek
Para conocer la compatibilidad actual de los tipos anteriores en los navegadores, consulta ¿Puedo usar?
De forma predeterminada, Blazor carga un subconjunto de datos de globalización que contiene la referencia cultural de la aplicación. Para cargar todos los datos de globalización, establezca <BlazorWebAssemblyLoadAllGlobalizationData>true en el archivo de proyecto de la aplicación (.csproj):
<PropertyGroup>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
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).
En las aplicaciones WebAssembly (Wasm), cuando el modo invariable de globalización está deshabilitado, se carga un archivo de datos de ICU. Hay cuatro tipos básicos de estos archivos:
-
icudt.dat: datos completos -
icudt_EFIGS.dat: datos para localizaciones:en-*,fr-FR,es-ES,it-IT, yde-DE. -
icudt_CJK.dat: datos para configuraciones regionales:en-*,ja,ko, yzh-*. -
icudt_no_CJK.dat: datos para todas las configuraciones regionales deicudt.dat, exceptoja,koyzh-*.
Especifique un archivo para cargar con la <BlazorIcuDataFileName> propiedad MSBuild en el archivo de proyecto de la aplicación (.csproj). En el ejemplo siguiente se carga el icudt_no_CJK.dat archivo:
<PropertyGroup>
<BlazorIcuDataFileName>icudt_no_CJK.dat</BlazorIcuDataFileName>
</PropertyGroup>
<BlazorIcuDataFileName> solo acepta un único archivo. El archivo puede ser un archivo personalizado creado por el desarrollador. Para crear un archivo de ICU personalizado, consulte WASM Globalization Icu: Custom ICU.
Si no se especifica un archivo con <BlazorIcuDataFileName>, se comprueba la cultura de la aplicación y se carga el archivo de ICU correspondiente para su cultura. Por ejemplo, la en-US referencia cultural da como resultado cargar el icudt_EFIGS.dat archivo. Para zh-CN, se usa el icudt_CJK.dat archivo .
Para obtener más información, consulta Globalización de .NET e ICU: ICU en 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.
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, acceda a esta sección para una versión .NET 8 o posterior 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:
trueo1
- 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.
Establecer dinámicamente la configuración cultural desde el encabezado Accept-Language
Agrega el paquete Microsoft.Extensions.Localization a la aplicación.
El encabezado Accept-Language lo establece el navegador y se controla mediante las preferencias de idioma del usuario en la configuración del navegador. 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 del servidor, especifique las referencias culturales admitidas de la aplicación, antes de que algún middleware 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 culturas admitidas para el inglés estadounidense y el español costarricense:
En el desarrollo del lado servidor, especifique las referencias culturales inmediatamente después de que se añada Routing Middleware (UseRouting) al pipeline de procesamiento. En el ejemplo siguiente se configuran las referencias culturales admitidas para inglés de Estados Unidos y español de Costa Rica mediante la SIGUIENTE API:
- AddSupportedCultures agrega el conjunto de referencias culturales admitidas para la globalización (formato de fecha, número y moneda).
- AddSupportedUICultures agrega el conjunto de culturas de interfaz de usuario admitidas para la localización (cadenas de interfaz de usuario traducidas para mostrar contenido).
app.UseRequestLocalization(new RequestLocalizationOptions()
.AddSupportedCultures(new[] { "en-US", "es-CR" })
.AddSupportedUICultures(new[] { "en-US", "es-CR" }));
En el ejemplo anterior, las mismas culturas de formato y culturas de interfaz de usuario admitidas se especifican en un contexto limitado en el que la aplicación solo se usa en los Estados Unidos y Costa Rica. Como alternativa, una aplicación puede usar un conjunto más amplio de referencias culturales para el formato de fecha, número y moneda, pero solo proporcionar contenido localizado para Estados Unidos y Costa Rica, como se muestra en el ejemplo siguiente:
var uiCultures = new[] { "en-US", "es-CR" };
var formattingCultures = CultureInfo
.GetCultures(CultureTypes.SpecificCultures)
.Select(c => c.Name)
.ToArray();
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(uiCultures[0])
.AddSupportedCultures(formattingCultures)
.AddSupportedUICultures(uiCultures);
app.UseRequestLocalization(localizationOptions);
En el ejemplo anterior, CultureTypes.SpecificCultures devuelve solo referencias culturales específicas de un país o región, como en-US o fr-FR, que vienen con datos completos de globalización concretos (para fechas, números, calendarios y otra interfaz de usuario cultural) que .NET puede usar para un formato y análisis precisos. Es posible que las referencias culturales neutras, como en o fr, no tengan datos de globalización completos, por lo que no se incluyen en esta lista.
Para obtener información sobre cómo ordenar el middleware de localización en la canalización de middleware del archivo Program, consulte 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. Vuelva a solicitar la página web.
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
Establecer de forma estática la cultura del lado del 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 presentación en el lado cliente elimina información de internacionalización, excepto para las configuraciones regionales solicitadas de forma explícita. Para obtener más información, consulta Configuración del enlazador de ASP.NET Core Blazor.
La cultura de la aplicación se puede configurar en JavaScript cuando Blazor se inicia con la opción applicationCultureBlazor. En el ejemplo siguiente se configura la aplicación para que se inicie con la cultura de inglés de Estados Unidos (en-US).
Evite Blazor el inicio automático añadiendo autostart="false" a la etiqueta de Blazor<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.
Agregue el siguiente bloque <script> después de la etiqueta de Blazor<script> 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 más información sobre el inicio de Blazor, vea 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#. Establezca 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;
Agregue 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
En .NET 9 o versiones anteriores, las aplicaciones independientes Blazor WebAssembly cargan recursos de globalización de la interfaz de usuario en función de CultureInfo.DefaultThreadCurrentCulture. Si desea cargar datos adicionales de globalización para la cultura de referencia de localización definida por CultureInfo.DefaultThreadCurrentUICulture, actualice la aplicación a .NET 10 o posterior.
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. Vuelva 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 cultura estática en el archivo Program antes de cualquier middleware que pueda comprobar la cultura 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 archivo Program inmediatamente después de añadir el middleware de enrutamiento al pipeline de procesamiento (UseRouting). En el ejemplo siguiente se configura inglés de Estados Unidos:
app.UseRequestLocalization("en-US");
El valor 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, consulte 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();
Especifique 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 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, consulte 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. Vuelva 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).
Configurar dinámicamente la cultura del lado del cliente según la preferencia 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 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.
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.
Proporcione funciones JS después de la etiqueta de Blazor<script> para obtener y definir 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.
Agregue 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 añade el servicio de localización de Blazor a la recopilación de servicios de la aplicación con AddLocalization y usa JS interop para llamar a JS y obtener la referencia cultural del usuario desde el 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
En .NET 9 o versiones anteriores, las aplicaciones independientes Blazor WebAssembly cargan recursos de globalización de la interfaz de usuario en función de CultureInfo.DefaultThreadCurrentCulture. Si desea cargar datos adicionales de globalización para la cultura de referencia de localización definida por CultureInfo.DefaultThreadCurrentUICulture, actualice la aplicación a .NET 10 o posterior.
El componente CultureSelector siguiente muestra cómo realizar las siguientes acciones:
- Establezca la selección de la referencia cultural del usuario en el almacenamiento local del explorador a través de la interoperabilidad de JS.
- Vuelva a cargar el componente que solicitó (
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 Cómo llamar a funciones de JavaScript desde métodos .NET en ASP.NET Core Blazor.
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.
Configurar dinámicamente la cultura del servidor según la preferencia 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 demuestra cómo utilizar cookie para la localización.
Nota
En el siguiente ejemplo, se asume que la aplicación adopta la interactividad global al especificar la representación interactiva del servidor (SSR interactivo) en el componente Routes dentro 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 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.
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 culturas 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, consulte Middleware de ASP.NET Core.
En el siguiente ejemplo se muestra cómo establecer la cultura actual en una cookie que puede ser leída por el middleware de localización.
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, consulte 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
Programllamando a MapControllers en el IEndpointRouteBuilder (app):app.MapControllers();
Para especificar una interfaz de usuario que permita a un usuario seleccionar una referencia cultural, se use 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:
Añade el modo de renderización interactiva del servidor en la parte superior del archivo de componentes
CultureExample1(Components/Pages/CultureExample1.razor):@rendermode InteractiveServerEn 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 un Blazor Web App según las preferencias del usuario
Esta sección se aplica a las 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 en el proyecto .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>
Agregue los espacios de nombres para System.Globalization y Microsoft.JSInterop a la parte superior del archivo .Client del proyecto de 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 añade el servicio de localización de Blazor a la recopilación de servicios de la aplicación con AddLocalization y usa JS interop para llamar a JS y obtener la referencia cultural del usuario desde el 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
En .NET 9 o versiones anteriores, las aplicaciones independientes Blazor WebAssembly cargan recursos de globalización de la interfaz de usuario en función de CultureInfo.DefaultThreadCurrentCulture. Si desea cargar datos adicionales de globalización para la cultura de referencia de localización definida por CultureInfo.DefaultThreadCurrentUICulture, actualice la aplicación a .NET 10 o posterior.
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 mostrado de cada cultura disponible en la lista desplegable, ya que los datos de globalización del lado del cliente incluyen texto localizado de los nombres mostrados de las culturas que proporcionan los datos de globalización del lado del servidor. Por ejemplo, la localización del lado servidor muestra
English (United States)cuandoen-USes 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 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);
}
}
}
En el .Client Proyectos _Imports archivo (_Imports.razor), agregue el espacio de nombres para los componentes en el archivo Pages carpeta, actualizando el espacio de nombres para que coincida con su .Client Espacio de nombres del proyecto:
@using BlazorSample.Client.Pages
Nota
Para obtener más información sobre IJSInProcessRuntime, consulta Cómo llamar a funciones de JavaScript desde métodos .NET en ASP.NET Core Blazor.
en el .Client proyecto, agregue el CultureSelector al componente MainLayout componente. Coloca el siguiente marcado dentro de la etiqueta de cierre </main> en el archivo Layout/MainLayout.razor:
<article class="bottom-row px-4">
<CultureSelector @rendermode="InteractiveAuto" />
</article>
En el proyecto .Client, coloque 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;
}
En el proyecto .Client, ubique el siguiente componente CultureServer para estudiar cómo funciona la globalización para los componentes de SSR.
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;
}
Usa el componente CultureExample1 que se muestra en la sección de Componentes de demostración de para estudiar cómo funciona la globalización de un componente que hereda el modo global de representación automática. Agregue el CultureExample1 al componente .Client Proyectos Pages carpeta.
Agregue el CultureClient, CultureServer, y CultureExample1 componentes a la barra lateral de navegación en 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>
<div class="nav-item px-3">
<NavLink class="nav-link" href="culture-example-1">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Culture (Auto)
</NavLink>
</div>
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 culturas 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 cultura actual en una cookie que puede ser leída por el middleware de localización.
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.
Tras la etiqueta deBlazor<script>, proporcioneJS funciones para leer y definir la referencia cultural del usuario mediante 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 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
Programllamando a MapControllers en el IEndpointRouteBuilder (app):app.MapControllers();
Para permitir que un usuario seleccione una referencia cultural para los componentes de SSR, use 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.
Componentes automáticos interactivos
La guía de esta sección también es válida para componentes de aplicaciones que adoptan el renderizado por página/componente y especifican el modo de renderizado Automático interactivo:
@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, agregue 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
Use 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.
- Especifique 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 verificar la referencia cultural de la solicitud. Por lo general, coloque el middleware inmediatamente antes de llamar a MapRazorComponents:
Inmediatamente después el middleware de enrutamiento (UseRouting) es añadido a la pipeline 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, consulte Middleware de ASP.NET Core.
- Agrega servicios de localización a la aplicación con AddLocalization.
- Especifica la cultura predeterminada y las culturas 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();
En Startup.Configure inmediatamente después de añadir el middleware de enrutamiento (UseRouting) se añade al pipeline 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, consulte 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, use una referencia cultural de localización cookie. El uso de un cookie garantiza que la conexión WebSocket pueda propagar correctamente la cultura. 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 utilizar una cultura de localización cookie. 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 siguiente componente muestra el uso de la cadena localizada Greeting 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.
Agregue 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.
Confirme que el
Microsoft.Extensions.LocalizationEl proyecto hace referencia al paquete.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.
Confirme que el Microsoft.Extensions.Localization El espacio de nombres está disponible para el proyecto. Razor componentes a través de una entrada en el del proyecto.
_Importsarchivo:@using Microsoft.Extensions.LocalizationCrea una clase ficticia con un nombre de clase arbitrario. En el ejemplo siguiente:
- La aplicación usa el espacio de nombres
BlazorSampley 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
Localizationen la raíz de la aplicación.
Nota
No utilice un archivo de diseñador generado automáticamente (por ejemplo,
SharedResources.Designer.cs). La clase simulada está pensada para actuar como la clase de recursos compartidos. La presencia de un archivo de diseñador produce una colisión de espacio de nombres.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
Localizationcon la claseSharedResourceficticia (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.resxLocalization/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
@usingpara 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
Localizationpara la clase ficticiaSharedResourcecon una directiva@using. - En el segundo ejemplo se indica el espacio de nombres de la clase ficticia
SharedResourceexplí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 Blazor La localización no funciona con InteractiveServer (dotnet/aspnetcore #53707).
Recursos adicionales
- ruta de acceso base de la aplicación ASP.NET Core Blazor
- Globalización y localización en ASP.NET Core
- Globalización y localización de aplicaciones .NET
- Recursos en archivos .resx
- Localización y genéricos
-
La llamada a
InvokeAsync(StateHasChanged)hace que la página retroceda a la cultura predeterminada (dotnet/aspnetcore #28521) -
Blazor (
dotnet/aspnetcore)