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, consulte 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 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 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:

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.

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.

Al usar los tipos de campo date y number, no se recomienda especificar una referencia cultural con @bind:culture porque Blazor proporciona compatibilidad integrada para representar valores en la referencia cultural actual.

Los siguientes tipos de campo tienen requisitos de formato específicos y no se admiten actualmente 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, vea ¿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, consulte 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, consulte 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, consulte 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 más información, vaya a esta sección relativa a la versión 8.0 o posteriores de este artículo.

Globalización invariable

Si la aplicación no requiere localización, configure la aplicación para que admita la referencia cultural invariable, que suele basarse en inglés de Estados Unidos (en-US). Establezca la propiedad InvariantGlobalization en true en el archivo del proyecto de la aplicación (.csproj):

<PropertyGroup>
  <InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>

Como alternativa, configure 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 o 1

Para obtener más información, vea Opciones de configuración del entorno de ejecución para la globalización (documentación de .NET).

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>

<p>
    <b>CurrentCulture</b>: @CultureInfo.CurrentCulture
</p>

<h2>Rendered values</h2>

<ul>
    <li><b>Date</b>: @dt</li>
    <li><b>Number</b>: @number.ToString("N2")</li>
</ul>

<h2><code>&lt;input&gt;</code> elements that don't set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</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>&lt;input&gt;</code> elements that set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</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, agregue 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

Agregue 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, establezca 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, consulte 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. Agregue servicios de localización a la aplicación con AddLocalization.

Agregue la siguiente línea al archivo Program donde se registran los servicios:

builder.Services.AddLocalization();

En el desarrollo del lado del servidor, puede especificar los cultivos compatibles con la aplicación inmediatamente después de agregar Middleware de enrutamiento 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, consulte Middleware de ASP.NET Core.

Use el componente CultureExample1 que se muestra en la sección Componente de demostración para estudiar cómo funciona la globalización. Emita una solicitud con inglés de Estados Unidos (en-US). Cambie a español costarriqueño (es-CR) en la configuración de idioma del explorador. Vuelva a solicitar la página web.

Nota

Algunos exploradores le 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

Establezca la propiedad BlazorWebAssemblyLoadAllGlobalizationData en true en el archivo del proyecto de la aplicación (.csproj):

<PropertyGroup>
  <BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>

Por defecto, la configuración del enlazador de lenguaje intermedio (IL) para la renderización en el lado del cliente elimina la información de internacionalización excepto para las configuraciones regionales solicitadas explícitamente. Para más información, vea 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).

Evite 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, consulte la estructura del proyecto ASP.NET CoreBlazor.

Agregue el siguiente bloque <script> después de la etiqueta <script> de Blazor y antes de la etiqueta de cierre </body>:

Aplicación web Blazor:

<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, consulte 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.

Agregue 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");

Importante

Establezca siempre DefaultThreadCurrentCulture y DefaultThreadCurrentUICulture en la misma referencia cultural para usar IStringLocalizer y IStringLocalizer<T>.

Use el componente CultureExample1 que se muestra en la sección Componente de demostración para estudiar cómo funciona la globalización. Emita una solicitud con inglés de Estados Unidos (en-US). Cambie 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. Agregue 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 archivo Program 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 del archivo Program, consulte Middleware de ASP.NET Core.

Las aplicaciones del lado servidor se localizan mediante un middleware de localización. Agregue 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 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, consulte Middleware de ASP.NET Core.

Use el componente CultureExample1 que se muestra en la sección Componente de demostración para estudiar cómo funciona la globalización. Emita una solicitud con inglés de Estados Unidos (en-US). Cambie 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 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.

Agregue el paquete Microsoft.Extensions.Localization al proyecto:

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.

Establezca 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 de JS después de la etiquetaBlazor 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, consulte 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;

Quite las siguientes líneas:

- await builder.Build().RunAsync();

Reemplace 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.GetCulture(result ?? defaultCulture);

if (result == null)
{
    await js.InvokeVoidAsync("blazorCulture.set", defaultCulture);
}

CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;

await host.RunAsync();

Importante

Establezca siempre DefaultThreadCurrentCulture y DefaultThreadCurrentUICulture en la misma referencia cultural para usar IStringLocalizer y IStringLocalizer<T>.

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="Culture">
            @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 Culture
    {
        get => CultureInfo.CurrentCulture;
        set
        {
            if (CultureInfo.CurrentCulture != value)
            {
                var js = (IJSInProcessRuntime)JS;
                js.InvokeVoid("blazorCulture.set", value.Name);

                Navigation.NavigateTo(Navigation.Uri, forceLoad: true);
            }
        }
    }
}

Dentro de la etiqueta de cierre del elemento </main> del componente MainLayout (MainLayout.razor), agregue el componente CultureSelector:

<article class="bottom-row px-4">
    <CultureSelector />
</article>

Use 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, consulte los comentarios al final de esta sección para modificar los modos de representación de los componentes del ejemplo.

Agregue el paquete Microsoft.Extensions.Localization al proyecto.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.

Las aplicaciones del lado servidor se localizan mediante un middleware de localización. Agregue servicios de localización a la aplicación con AddLocalization.

En el archivo Program:

builder.Services.AddLocalization();

Establezca las referencia culturales predeterminadas y admitidas de la aplicación con RequestLocalizationOptions.

Antes de llamar a app.MapRazorComponents en la canalización de procesamiento de solicitudes, coloque el código siguiente:

Después de llamar a app.UseRouting en 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 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:

Agregue lo siguiente a la parte superior del archivo de componente de App (Components/App.razor):

@using System.Globalization
@using Microsoft.AspNetCore.Localization

Agregue 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)));
    }
}

Las modificaciones en el archivo Pages/_Host.cshtml requieren los siguientes espacios de nombres:

Agregue 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:

  • Agregue servicios de MVC mediante una llamada a AddControllers en la colección de servicios en el archivo Program:

    builder.Services.AddControllers();
    
  • Agregue 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, 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

Use 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, consulte 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 NavigationManager Navigation

<p>
    <label>
        Select your locale:
        <select @bind="Culture">
            @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"),
    };

    protected override void OnInitialized()
    {
        Culture = CultureInfo.CurrentCulture;
    }

    private CultureInfo Culture
    {
        get => CultureInfo.CurrentCulture;
        set
        {
            if (CultureInfo.CurrentCulture != value)
            {
                var uri = new Uri(Navigation.Uri)
                    .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
                var cultureEscaped = Uri.EscapeDataString(value.Name);
                var uriEscaped = Uri.EscapeDataString(uri);

                Navigation.NavigateTo(
                    $"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
                    forceLoad: true);
            }
        }
    }
}

Agregar el componente CultureSelector al componente MainLayout. Coloque el siguiente marcado dentro de la etiqueta de cierre </main> en el archivo Components/Layout/MainLayout.razor:

Agregar el componente CultureSelector al componente MainLayout. Coloque el siguiente marcado dentro de la etiqueta de cierre </main> en el archivo Shared/MainLayout.razor:

<article class="bottom-row px-4">
    <CultureSelector />
</article>

Use 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:

  • Agregue 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), aplique el modo de representación interactiva del lado del servidor al componente CultureSelector:

    <CultureSelector @rendermode="InteractiveServer" />
    

Establecimiento dinámico de la referencia cultural en una aplicación web de Blazor por preferencia de usuario

Esta sección se aplica a aplicaciones web de Blazor 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 del cliente), en un cookie de localización o base de datos (habitual en escenarios del lado del servidor), tanto el almacenamiento local como un cookie de localización (aplicaciones web de Blazor 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

Agregue el paquete Microsoft.Extensions.Localization al proyecto de .Client.

Nota:

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.

Establezca 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 Program del proyecto de .Client:

using System.Globalization;
using Microsoft.JSInterop;

Quite las siguientes líneas:

- await builder.Build().RunAsync();

Reemplace 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.GetCulture(result ?? defaultCulture);

if (result == null)
{
    await js.InvokeVoidAsync("blazorCulture.set", defaultCulture);
}

CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;

await host.RunAsync();

Importante

Establezca siempre DefaultThreadCurrentCulture y DefaultThreadCurrentUICulture en la misma referencia cultural para usar IStringLocalizer y IStringLocalizer<T>.

Agregue 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) cuando en-US es la referencia cultural y Ingles () 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 simplemente en-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
@using System.Runtime.InteropServices
@inject IJSRuntime JS
@inject NavigationManager Navigation

<p>
    <label>
        Select your locale:
        <select @bind="Culture">
            @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 Culture
    {
        get => CultureInfo.CurrentCulture;
        set
        {
            if (CultureInfo.CurrentCulture != value)
            {
                JS.InvokeVoidAsync("blazorCulture.set", value.Name);

                var uri = new Uri(Navigation.Uri)
                    .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
                var cultureEscaped = Uri.EscapeDataString(value.Name);
                var uriEscaped = Uri.EscapeDataString(uri);

                Navigation.NavigateTo(
                    $"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
                    forceLoad: true);
            }
        }
    }
}

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>

<p>
    <b>CurrentCulture</b>: @CultureInfo.CurrentCulture
</p>

<h2>Rendered values</h2>

<ul>
    <li><b>Date</b>: @dt</li>
    <li><b>Number</b>: @number.ToString("N2")</li>
</ul>

<h2><code>&lt;input&gt;</code> elements that don't set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</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>&lt;input&gt;</code> elements that set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</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

Agregue el paquete Microsoft.Extensions.Localization al proyecto de servidor.

Nota:

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.

Las aplicaciones del lado servidor se localizan mediante un middleware de localización. Agregue 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();

Establezca las referencia culturales predeterminadas y admitidas de la aplicación con RequestLocalizationOptions.

Antes de llamar a app.MapRazorComponents en 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);

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:

Agregue 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, proporcione 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, consulte Aislamiento de JavaScript en módulos de JavaScript.

Agregue 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:

  • Agregue servicios de MVC mediante una llamada a AddControllers en la colección de servicios en el archivo Program:

    builder.Services.AddControllers();
    
  • Agregue 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, 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

Use el resultado de la acción LocalRedirect, como se muestra en el ejemplo anterior, para evitar ataques de redirección abiertos. Para más información, consulte Prevención de ataques de redireccionamiento abierto en ASP.NET Core.

Agregar el componente CultureSelector al componente MainLayout. Coloque 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>

Use 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, coloque 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>

<p>
    <b>CurrentCulture</b>: @CultureInfo.CurrentCulture
</p>

<h2>Rendered values</h2>

<ul>
    <li><b>Date</b>: @dt</li>
    <li><b>Number</b>: @number.ToString("N2")</li>
</ul>

<h2><code>&lt;input&gt;</code> elements that don't set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</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>&lt;input&gt;</code> elements that set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</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;
}

Agregue 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, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.

Localización del lado cliente

Establezca 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;

Agregue 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:

  • Agregue 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();

Inmediatamente después de agregar el middleware de enrutamiento 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, consulte Middleware de ASP.NET Core.

  • Agregue servicios de localización a la aplicación con AddLocalization.
  • Especifique 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();

En Startup.Configure, inmediatamente después de agregar el middleware de enrutamiento 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, 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 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. Consulte 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.

Cree 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, haga clic con el botón derecho en la carpeta Pages y seleccione Agregar>Nuevo elemento>Archivo de recursos. Asigne al archivo el nombre CultureExample2.resx. Cuando aparezca el editor, proporcione datos para una nueva entrada. Establezca el Nombre en Greeting y el Valor en Hello, World!. Guarde el archivo.

Si usa Visual Studio Code, se recomienda instalar el Visor y editor ResX de Tim Heuer. Agregue 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. Seleccione el botón Agregar nuevo recurso. Siga las instrucciones a fin de agregar una entrada para Greeting (clave), Hello, World! (valor) y None (comentario). Guarde el archivo. Si cierra y vuelve a abrir el archivo, podrá 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. Puede colocar manualmente los archivos de recursos en la carpeta Pages de la aplicación si prefiere 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, haga clic con el botón derecho en la carpeta Pages y seleccione Agregar>Nuevo elemento>Archivo de recursos. Asigne al archivo el nombre CultureExample2.es.resx. Cuando aparezca el editor, proporcione datos para una nueva entrada. Establezca el Nombre en Greeting y el Valor en ¡Hola, Mundo!. Guarde el archivo.

Si usa Visual Studio Code, se recomienda instalar el Visor y editor ResX de Tim Heuer. Agregue 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. Seleccione el botón Agregar nuevo recurso. Siga las instrucciones a fin de agregar una entrada para Greeting (clave), ¡Hola, Mundo! (valor) y None (comentario). Guarde el archivo. Si cierra y vuelve a abrir el archivo, podrá ver el recurso Greeting.

A continuación se muestra un archivo de recursos típico. Puede colocar manualmente los archivos de recursos en la carpeta Pages de la aplicación si prefiere 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.

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>

<p>
    <b>CurrentCulture</b>: @CultureInfo.CurrentCulture
</p>

<h2>Greeting</h2>

<p>
    @Loc["Greeting"]
</p>

<p>
    @greeting
</p>

@code {
    private string? greeting;

    protected override void OnInitialized()
    {
        greeting = Loc["Greeting"];
    }
}

Opcionalmente, agregue 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, vea 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, use la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, vea 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, adopte el siguiente enfoque.

  • Cree 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 nombres BlazorSample.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
    {
    }
    
  • Cree 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 clase SharedResource ficticia (Localization/SharedResource.cs).

    • Asigne 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

    Nota

    Localization es la ruta de acceso del recurso que se puede establecer a través de LocalizationOptions.

  • Para hacer referencia a la clase ficticia para un elemento IStringLocalizer<T> insertado en un componente Razor, coloque una directiva @using para el espacio de nombres de localización o incluya 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 ficticia SharedResource 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, use cualquiera de los enfoques siguientes:

    @using Localization
    @inject IStringLocalizer<SharedResource> Loc
    
    @inject IStringLocalizer<Localization.SharedResource> Loc
    

Para obtener orientación adicional, consulte Globalización y localización en ASP.NET Core.

Recursos adicionales