Delen via


ASP.NET Core Blazor globalisatie en lokalisatie

Notitie

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikelvoor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie de .NET- en .NET Core-ondersteuningsbeleidvoor meer informatie. Zie de .NET 9-versie van dit artikelvoor de huidige release.

Belangrijk

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikelvoor de huidige release.

In dit artikel wordt uitgelegd hoe u geglobaliseerde en gelokaliseerde inhoud weergeeft aan gebruikers in verschillende culturen en talen.

Globalisering en lokalisatie

Voor globaliseringbiedt Blazor getal- en datumformatering. Voor lokalisatie, Blazor inhoud weergeeft met behulp van het .NET-resourcessysteem.

Een beperkte set lokalisatiefuncties van ASP.NET Core worden ondersteund:

✔️ Ondersteund:IStringLocalizer en IStringLocalizer<T> worden ondersteund in Blazor apps.

Niet ondersteund:IHtmlLocalizer en IViewLocalizer zijn ASP.NET Core MVC-functies en niet ondersteund in Blazor-apps.

Voor Blazor-apps worden gelokaliseerde validatieberichten voor -formuliervalidatie met behulp van gegevensaantekeningen ondersteund als DisplayAttribute.ResourceType en ValidationAttribute.ErrorMessageResourceType worden geïmplementeerd.

In dit artikel wordt beschreven hoe u de globalisatie- en lokalisatiefuncties van Blazorgebruikt op basis van:

  • De Accept-Language koptekst, die door de browser wordt ingesteld op basis van de taalvoorkeuren van een gebruiker in browserinstellingen.
  • Een cultuur die door de app is ingesteld, niet op basis van de waarde van de Accept-Language header. De instelling kan statisch zijn voor alle gebruikers of dynamisch op basis van app-logica. Wanneer de instelling is gebaseerd op de voorkeur van de gebruiker, wordt de instelling meestal opgeslagen voor opnieuw laden bij toekomstige bezoeken.

Zie de volgende bronnen voor aanvullende algemene informatie:

Vaak worden de termen taal en cultuur door elkaar gebruikt bij het omgaan met globaliserings- en lokalisatieconcepten.

In dit artikel verwijst taal naar selecties van een gebruiker in de instellingen van de browser. De taalselecties van de gebruiker worden ingediend in browseraanvragen in de Accept-Language header. Browserinstellingen gebruiken meestal het woord 'taal' in de gebruikersinterface.

Culture heeft betrekking op leden van .NET en Blazor API. Als voorbeeld kan de aanvraag van een gebruiker de Accept-Language header bevatten waarbij een taal wordt aangegeven vanuit het perspectief van de gebruiker, maar de app stelt uiteindelijk de eigenschap CurrentCulture ("cultuur") in op basis van de taal die door de gebruiker is aangevraagd. DE API gebruikt meestal het woord 'cultuur' in de ledennamen.

De richtlijnen in dit artikel hebben geen betrekking op het instellen van het HTML-taalkenmerk van de pagina (<html lang="...">), die hulpprogramma's voor toegankelijkheid gebruiken. U kunt de waarde statisch instellen door een taal toe te wijzen aan het lang kenmerk van de <html>-tag of aan document.documentElement.lang in JavaScript. U kunt de waarde van document.documentElement.lang dynamisch instellen met JS interop.

Notitie

De codevoorbeelden in dit artikel gebruiken nullable reference types (NRTs) en .NET compiler statische analyse van de null-status, die worden ondersteund door ASP.NET Core in .NET 6 of hoger. Wanneer u zich richt op ASP.NET Core 5.0 of eerder, verwijdert u de null-typeaanduiding (?) uit de voorbeelden van het artikel.

Globalisering

De @bind kenmerkrichtlijn past notaties toe en parseert waarden voor weergave op basis van de eerste voorkeurstaal van de gebruiker die de app ondersteunt. @bind ondersteunt de parameter @bind:culture om een System.Globalization.CultureInfo op te geven voor het parseren en opmaken van een waarde.

De huidige cultuur is toegankelijk via de eigenschap System.Globalization.CultureInfo.CurrentCulture.

CultureInfo.InvariantCulture wordt gebruikt voor de volgende veldtypen (<input type="{TYPE}" />, waarbij de tijdelijke aanduiding {TYPE} het type is):

  • date
  • number

De voorgaande veldtypen:

  • Worden weergegeven met behulp van de juiste opmaakregels van de browser.
  • Kan geen vrije tekst bevatten.
  • Gebruikersinteractiekenmerken bieden op basis van de implementatie van de browser.

Blazor biedt ingebouwde ondersteuning voor het weergeven van waarden in de huidige cultuur. Daarom wordt het opgeven van een cultuur met @bind:culture niet aanbevolen wanneer u de date en number veldtypen gebruikt.

De volgende veldtypen hebben specifieke opmaakvereisten en worden niet ondersteund door alle primaire browsers, zodat ze niet worden ondersteund door Blazor:

  • datetime-local
  • month
  • week

Zie Kan ikgebruiken voor de huidige browserondersteuning van de voorgaande typen.

Ondersteuning voor .NET globalization and International Components for Unicode (ICU) (Blazor WebAssembly)

Blazor WebAssembly maakt gebruik van een beperkte globalisatie-API en een set ingebouwde international components voor Unicode-landinstellingen (ICU). Zie .NET globalization and ICU: ICU on WebAssemblyvoor meer informatie.

Als u een aangepast ICU-gegevensbestand wilt laden om de landinstellingen van de app te beheren, raadpleegt u WASM Globalization Icu. Momenteel is het handmatig bouwen van het aangepaste ICU-gegevensbestand vereist. .NET-hulpprogramma's die het proces van bestandmaken vereenvoudigen, zijn gepland voor .NET 10 in november 2025.

Blazor WebAssembly maakt gebruik van een beperkte globalisatie-API en een set ingebouwde international components voor Unicode-landinstellingen (ICU). Zie .NET globalization and ICU: ICU on WebAssemblyvoor meer informatie.

Het laden van een aangepaste subset van landinstellingen in een Blazor WebAssembly-app wordt ondersteund in .NET 8 of hoger. Raadpleeg deze sectie voor een versie van 8.0 of hoger van dit artikel voor meer informatie.

Invariante globalisering

Deze sectie is alleen van toepassing op Blazor scenario's aan de clientzijde.

Als de app geen lokalisatie vereist, configureert u de app voor de ondersteuning van de invariante cultuur, die doorgaans is gebaseerd op Engels (en-US). Het gebruik van invariante globalisering vermindert de downloadgrootte van de app en resulteert in een snellere start van de app. Stel de eigenschap InvariantGlobalization in op true in het projectbestand van de app (.csproj):

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

U kunt ook invariante globalisering configureren met de volgende benaderingen:

  • In runtimeconfig.json:

    {
      "runtimeOptions": {
        "configProperties": {
          "System.Globalization.Invariant": true
        }
      }
    }
    
  • Met een omgevingsvariabele:

    • Sleutel: DOTNET_SYSTEM_GLOBALIZATION_INVARIANT
    • Waarde: true of 1

Zie Runtime-configuratieopties voor globalisatie (.NET-documentatie)voor meer informatie.

Tijdzonegegevens

Deze sectie is alleen van toepassing op Blazor scenario's aan de clientzijde.

Het aannemen van invariante globalisering resulteert alleen in het gebruik van niet-gelokaliseerde tijdzonenamen. Als u tijdzonecode en -gegevens wilt knippen, waardoor de downloadgrootte van de app wordt verkleind en de app sneller wordt opgestart, past u de eigenschap <InvariantTimezone> MSBuild toe met een waarde van true in het projectbestand van de app:

<PropertyGroup>
  <InvariantTimezone>true</InvariantTimezone>
</PropertyGroup>

Notitie

<BlazorEnableTimeZoneSupport> overschrijft een eerdere <InvariantTimezone>-instelling. U wordt aangeraden de <BlazorEnableTimeZoneSupport>-instelling te verwijderen.

Er wordt een gegevensbestand opgenomen om tijdzonegegevens correct te maken. Als deze functie niet is vereist voor de app, kunt u deze uitschakelen door de eigenschap <BlazorEnableTimeZoneSupport> MSBuild in te stellen op false in het projectbestand van de app:

<PropertyGroup>
  <BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
</PropertyGroup>

Demonstratieonderdeel

Het volgende CultureExample1 onderdeel kan worden gebruikt om Blazor globalisatie- en lokalisatieconcepten te demonstreren die in dit artikel worden behandeld.

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>&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;
}

De getaltekenreeksnotatie (N2) in het voorgaande voorbeeld (.ToString("N2")) is een standaard .NET-numerieke notatieaanduiding. De N2-indeling wordt ondersteund voor alle numerieke typen, bevat een groepsscheidingsteken en geeft maximaal twee decimalen weer.

U kunt desgewenst een menu-item toevoegen aan de navigatie in het NavMenu-onderdeel (NavMenu.razor) voor het CultureExample1 onderdeel.

De cultuur dynamisch instellen op basis van de Accept-Language header

Voeg het Microsoft.Extensions.Localization-pakket toe aan de app.

De Accept-Language koptekst wordt ingesteld door de browser en wordt bepaald door de taalvoorkeuren van de gebruiker in browserinstellingen. In browserinstellingen stelt een gebruiker een of meer voorkeurstalen in op volgorde van voorkeur. De volgorde van voorkeur wordt door de browser gebruikt om kwaliteitswaarden (q, 0-1) in te stellen voor elke taal in de koptekst. In het volgende voorbeeld worden Engels van de Verenigde Staten, Engels en Costa Ricaans Spaans aangegeven, met een voorkeur voor Engels van de Verenigde Staten of Engels.

Accept-Language: en-US, en; q=0.9,es-CR; q=0.8

De cultuur van de app wordt ingesteld door overeen te komen met de eerste aangevraagde taal die overeenkomt met een ondersteunde cultuur van de app.

Stel in ontwikkeling aan de clientzijdede eigenschap BlazorWebAssemblyLoadAllGlobalizationData in op true in het projectbestand van de client-app (.csproj):

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

In ontwikkeling aan de clientzijde, wordt het dynamisch instellen van de cultuur van de Accept-Language header niet ondersteund.

Notitie

Als de specificatie van de app vereist dat de ondersteunde culturen worden beperkt tot een expliciete lijst, raadpleeg dan de sectie Dynamisch de clientzijde cultuur instellen op basis van gebruikersvoorkeur van dit artikel.

Apps worden gelokaliseerd met Localization Middleware. Lokalisatieservices toevoegen aan de app met AddLocalization.

Voeg de volgende regel toe aan het Program-bestand waarin services zijn geregistreerd:

builder.Services.AddLocalization();

Geef in ontwikkeling aan de serverzijdede ondersteunde culturen van de app op vóór middleware die de aanvraagcultuur kan controleren. Over het algemeen plaatst u Request Localization Middleware direct voordat u MapRazorComponentsaanroept. In het volgende voorbeeld worden ondersteunde culturen geconfigureerd voor Engels en Costa Ricaans Spaans in de Verenigde Staten:

Geef in ontwikkeling aan de serverzijdede ondersteunde culturen van de app op direct nadat Routing Middleware (UseRouting) is toegevoegd aan de verwerkingspijplijn. In het volgende voorbeeld worden ondersteunde culturen geconfigureerd voor Engels en Costa Ricaans Spaans in de Verenigde Staten:

app.UseRequestLocalization(new RequestLocalizationOptions()
    .AddSupportedCultures(new[] { "en-US", "es-CR" })
    .AddSupportedUICultures(new[] { "en-US", "es-CR" }));

Zie Programvoor meer informatie over het plaatsen van de Localization Middleware in de middleware-pijplijn van het -bestand.

Gebruik het CultureExample1 onderdeel dat wordt weergegeven in het onderdeel Demonstratie om te onderzoeken hoe globalisering werkt. Dien een aanvraag in met Amerikaans-Engels (en-US). Schakel over naar Costa Ricaans Spaans (es-CR) in de taalinstellingen van de browser. Vraag de webpagina opnieuw aan.

Wanneer de cultuur Engels is (en-US), gebruikt het weergegeven onderdeel de datumnotatie maand/dag (6/7), 12-uurs tijd (AM/PM) en kommascheidingstekens in getallen met een punt voor de decimale waarde (1,999.69):

  • Datum: 7-6-2021 6:45:22 AM
  • Getal: 1.999,69

Wanneer de cultuur Costa Ricaans Spaans is (es-CR), gebruikt het gerenderde onderdeel de datumnotatie dag/maand (7/6), 24-uurs tijd en puntscheidingstekens in getallen met een komma voor de decimale waarde (1.999,69):

  • Datum: 6-7-2021 6:49:38
  • getal: 1.999,69

De cultuur aan de clientzijde statisch instellen

Stel de eigenschap BlazorWebAssemblyLoadAllGlobalizationData in op true in het projectbestand van de app (.csproj):

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

Met de configuratie van de Intermediate Language (IL) Linker voor rendering aan de klantzijde wordt internationalisatie-informatie verwijderd, met uitzondering van locaties die expliciet zijn aangevraagd. Zie De Linker configureren voor ASP.NET Core Blazorvoor meer informatie.

De cultuur van de app kan worden ingesteld in JavaScript wanneer Blazor begint met de applicationCultureBlazor startoptie. In het volgende voorbeeld wordt de app geconfigureerd voor het starten met behulp van de Engelse cultuur (en-US) van de Verenigde Staten.

Voorkom Blazor automatisch opstarten door autostart="false" toe te voegen aan de Blazor-tag van <script>:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>

In het voorgaande voorbeeld zijn de tijdelijke aanduidingen {BLAZOR SCRIPT} en Blazor respectievelijk het scriptpad en de bestandsnaam. Zie ASP.NET Core Blazor projectstructuurvoor de locatie van het script.

Voeg het volgende <script> blok toe na Blazor<script> tag en vóór de afsluitende </body> tag:

Blazor Web App:

<script>
  Blazor.start({
    webAssembly: {
      applicationCulture: 'en-US'
    }
  });
</script>

Zelfstandige Blazor WebAssembly:

<script>
  Blazor.start({
    applicationCulture: 'en-US'
  });
</script>

De waarde voor applicationCulture moet voldoen aan de BCP-47-taallabelindeling. Voor meer informatie over Blazor startup, zie ASP.NET Core Blazor startup.

Een alternatief voor het instellen van de startoptie van cultuur Blazoris het instellen van de cultuur in C#-code. Stel CultureInfo.DefaultThreadCurrentCulture en CultureInfo.DefaultThreadCurrentUICulture in het Program-bestand in op dezelfde cultuur.

Voeg de System.Globalization-naamruimte toe aan het Program-bestand:

using System.Globalization;

Voeg de cultuurinstellingen toe vóór de lijn die de WebAssemblyHostBuilder bouwt en uitvoert (await builder.Build().RunAsync();):

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");

Notitie

Op dit moment laden Blazor WebAssembly apps alleen resources op basis van DefaultThreadCurrentCulture. Voor meer informatie, zie Blazor waar WASM alleen afhankelijk is van de huidige cultuur (en de huidige UI-cultuur niet wordt gerespecteerd) (dotnet/aspnetcore #56824).

Gebruik het CultureExample1 onderdeel dat wordt weergegeven in het onderdeel Demonstratie om te onderzoeken hoe globalisering werkt. Dien een aanvraag in met Amerikaans-Engels (en-US). Schakel over naar Costa Ricaans Spaans (es-CR) in de taalinstellingen van de browser. Vraag de webpagina opnieuw aan. Wanneer de aangevraagde taal Costa Ricaans Spaans is, blijft de cultuur van de app Engels (en-US).

De cultuur aan de serverzijde statisch instellen

Apps aan de serverzijde worden gelokaliseerd met behulp van Localization Middleware. Lokalisatieservices toevoegen aan de app met AddLocalization.

In het bestand Program:

builder.Services.AddLocalization();

Geef de statische cultuur op in het Program-bestand voordat er middleware is die de aanvraagcultuur kan controleren. Over het algemeen plaatst u Request Localization Middleware direct voor MapRazorComponents. In het volgende voorbeeld wordt Engels in de Verenigde Staten geconfigureerd:

Geef de statische cultuur op in het Program-bestand direct nadat Routing Middleware (UseRouting) is toegevoegd aan de verwerkingspijplijn. In het volgende voorbeeld wordt Engels in de Verenigde Staten geconfigureerd:

app.UseRequestLocalization("en-US");

De cultuurwaarde voor UseRequestLocalization moet voldoen aan de BCP-47-taallabelindeling.

Zie Programvoor meer informatie over het plaatsen van de Localization Middleware in de middleware-pijplijn van het -bestand.

Apps aan de serverzijde worden gelokaliseerd met behulp van Localization Middleware. Lokalisatieservices toevoegen aan de app met AddLocalization.

In Startup.ConfigureServices (Startup.cs):

services.AddLocalization();

Geef de statische cultuur op in Startup.Configure (Startup.cs) direct nadat Routing Middleware is toegevoegd aan de verwerkingspijplijn. In het volgende voorbeeld wordt Engels in de Verenigde Staten geconfigureerd:

app.UseRequestLocalization("en-US");

De cultuurwaarde voor UseRequestLocalization moet voldoen aan de BCP-47-taallabelindeling.

Zie Startup.Configurevoor informatie over het bestellen van de Localization Middleware in de middlewarepipeline van .

Gebruik het CultureExample1 onderdeel dat wordt weergegeven in het onderdeel Demonstratie om te onderzoeken hoe globalisering werkt. Dien een aanvraag in met Amerikaans-Engels (en-US). Schakel over naar Costa Ricaans Spaans (es-CR) in de taalinstellingen van de browser. Vraag de webpagina opnieuw aan. Wanneer de aangevraagde taal Costa Ricaans Spaans is, blijft de cultuur van de app Engels (en-US).

De cultuur aan de clientzijde dynamisch instellen op gebruikersvoorkeur

Voorbeelden van locaties waar een app de voorkeur van een gebruiker kan opslaan, zijn opgenomen in lokale opslag (gebruikelijk voor scenario's aan de clientzijde), in een lokalisatie cookie of database (algemeen voor scenario's aan de serverzijde) of in een externe service die is gekoppeld aan een externe database en toegankelijk is voor een web-API. In het volgende voorbeeld ziet u hoe u lokale browseropslag gebruikt.

Voeg het Microsoft.Extensions.Localization-pakket toe aan de app.

Notitie

Zie de artikelen onder Pakketten installeren en beheren bij Verbruikswerkstroom voor pakketten (NuGet-documentatie)voor begeleiding bij het toevoegen van pakketten in .NET-apps. Bevestig de juiste pakketversies op NuGet.org.

Stel de eigenschap BlazorWebAssemblyLoadAllGlobalizationData in op true in het projectbestand:

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

De cultuur van de app voor rendering aan de clientzijde wordt ingesteld met behulp van de API van het Blazor Framework. De cultuurselectie van een gebruiker kan worden behouden in lokale opslag in de browser.

Bied JS functies aan na de Blazor tag van <script> voor het ophalen en vastleggen van de cultuurkeuze van de gebruiker met behulp van lokale browseropslag.

<script>
  window.blazorCulture = {
    get: () => window.localStorage['BlazorCulture'],
    set: (value) => window.localStorage['BlazorCulture'] = value
  };
</script>

Notitie

Het voorgaande voorbeeld vervuilt de klant met globale functies. Zie JavaScript-isolatie in JavaScript-modulesvoor een betere benadering van productie-apps.

Voeg de naamruimten voor System.Globalization en Microsoft.JSInterop toe aan de bovenkant van het Program-bestand:

using System.Globalization;
using Microsoft.JSInterop;

Verwijder de volgende regel:

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

Vervang de voorgaande regel door de volgende code. De code voegt de lokalisatieservice van Blazortoe aan de servicecollectie van de app met AddLocalization en gebruikt JS interop om een oproep te doen naar JS en de cultuurkeuze van de gebruiker op te halen uit de lokale opslag. Als lokale opslag geen cultuur voor de gebruiker bevat, wordt met de code een standaardwaarde ingesteld voor Engels (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();

Notitie

Op dit moment laden Blazor WebAssembly apps alleen resources op basis van DefaultThreadCurrentCulture. Voor meer informatie, zie Blazor waar WASM alleen afhankelijk is van de huidige cultuur (en de huidige UI-cultuur niet wordt gerespecteerd) (dotnet/aspnetcore #56824).

In het volgende CultureSelector onderdeel ziet u hoe u de volgende acties uitvoert:

  • Stel de cultuurselectie van de gebruiker in de browserlokale opslag in via JS interop.
  • Laad het aangevraagde onderdeel (forceLoad: true), dat gebruikmaakt van de bijgewerkte cultuur.

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

Notitie

Zie Blazorvoor meer informatie over .

Voeg in de afsluitende tag van het </main>-element in het MainLayout-onderdeel (MainLayout.razor) het CultureSelector-onderdeel toe:

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

Gebruik het CultureExample1 onderdeel dat wordt weergegeven in het gedeelte Demonstratieonderdeel om te onderzoeken hoe het voorgaande voorbeeld werkt.

De cultuur aan de serverzijde dynamisch instellen op gebruikersvoorkeur

Voorbeelden van locaties waar een app de voorkeur van een gebruiker kan opslaan, zijn opgenomen in lokale opslag (gebruikelijk voor scenario's aan de clientzijde), in een lokalisatie cookie of database (algemeen voor scenario's aan de serverzijde) of in een externe service die is gekoppeld aan een externe database en toegankelijk is voor een web-API. In het volgende voorbeeld ziet u hoe u een lokalisatie cookiegebruikt.

Notitie

In het volgende voorbeeld wordt ervan uitgegaan dat de app globale interactiviteit gebruikt door de interactieve rendering aan serverzijde (interactieve SSR) op te geven op het Routes onderdeel in het App-onderdeel (Components/App.razor):

<Routes @rendermode="InteractiveServer" />

Als de app per pagina/onderdeel interactiviteit gebruikt, raadpleegt u de opmerkingen aan het einde van deze sectie om de weergavemodi van de onderdelen van het voorbeeld te wijzigen.

Voeg het Microsoft.Extensions.Localization-pakket toe aan de app.

Notitie

Zie de artikelen onder Pakketten installeren en beheren bij Verbruikswerkstroom voor pakketten (NuGet-documentatie)voor begeleiding bij het toevoegen van pakketten in .NET-apps. Bevestig de juiste pakketversies op NuGet.org.

Apps aan de serverzijde worden gelokaliseerd met behulp van Localization Middleware. Lokalisatieservices toevoegen aan de app met AddLocalization.

In het bestand Program:

builder.Services.AddLocalization();

Stel de standaard- en ondersteunde culturen van de app in met RequestLocalizationOptions.

Plaats vóór de aanroep naar MapRazorComponents in de aanvraagverwerkingspijplijn de volgende code:

Nadat Routing Middleware (UseRouting) is toegevoegd aan de aanvraagverwerkingspijplijn, plaatst u de volgende code:

var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

Zie ASP.NET Core Middlewarevoor meer informatie over het ordenen van de Localization Middleware in de middleware-pijplijn.

In het volgende voorbeeld ziet u hoe u de huidige cultuur instelt in een cookie die kan worden gelezen door de Localization Middleware.

De volgende naamruimten zijn vereist voor het App-onderdeel:

Voeg het volgende toe aan de bovenkant van het App-onderdeelbestand (Components/App.razor):

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

Voeg het volgende @code blok toe aan de onderkant van het App-onderdeelbestand:

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

Voor wijzigingen in het Pages/_Host.cshtml-bestand zijn de volgende naamruimten vereist:

Voeg het volgende toe aan het bestand:

@using System.Globalization
@using Microsoft.AspNetCore.Localization
@{
    this.HttpContext.Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(
            new RequestCulture(
                CultureInfo.CurrentCulture,
                CultureInfo.CurrentUICulture)));
}

Zie ASP.NET Core Middlewarevoor meer informatie over het ordenen van de Localization Middleware in de middleware-pijplijn.

Als de app niet is geconfigureerd om controlleracties te verwerken:

  • Voeg MVC-services toe door AddControllers aan te roepen voor de serviceverzameling in het bestand Program:

    builder.Services.AddControllers();
    
  • Voeg controllereindpuntroutering toe aan het Program bestand door MapControllers aan te roepen op de IEndpointRouteBuilder (app):

    app.MapControllers();
    

Als u een gebruikersinterface wilt bieden zodat een gebruiker een cultuur kan selecteren, gebruikt u een benadering op basis van omleiding met een lokalisatie-cookie. De app behoudt de geselecteerde cultuur van de gebruiker via een omleiding naar een controller. De controller stelt de geselecteerde cultuur van de gebruiker in op een cookie en stuurt de gebruiker terug naar de oorspronkelijke URI. Het proces is vergelijkbaar met wat er gebeurt in een web-app wanneer een gebruiker probeert toegang te krijgen tot een beveiligde resource, waarbij de gebruiker wordt omgeleid naar een aanmeldingspagina en vervolgens wordt omgeleid naar de oorspronkelijke resource.

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

Waarschuwing

Gebruik het LocalRedirect actieresultaat, zoals wordt weergegeven in het vorige voorbeeld, om open omleidingsaanvallen te voorkomen. Zie Open redirect-aanvallen voorkomen in ASP.NET Corevoor meer informatie.

In het volgende CultureSelector onderdeel ziet u hoe u de Set methode van de CultureController aanroept met de nieuwe cultuur. Het onderdeel wordt in de Shared map geplaatst voor gebruik in de app.

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

Voeg het CultureSelector onderdeel toe aan het MainLayout-onderdeel. Plaats de volgende markeringen in de afsluitende </main> tag in het Components/Layout/MainLayout.razor-bestand:

Voeg het CultureSelector onderdeel toe aan het MainLayout-onderdeel. Plaats de volgende markeringen in de afsluitende </main> tag in het Shared/MainLayout.razor-bestand:

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

Gebruik het CultureExample1 onderdeel dat wordt weergegeven in het gedeelte Demonstratieonderdeel om te onderzoeken hoe het voorgaande voorbeeld werkt.

In het voorgaande voorbeeld wordt ervan uitgegaan dat de app globale interactiviteit gebruikt door de weergavemodus Interactive Server op te geven op het Routes onderdeel in het App-onderdeel (Components/App.razor):

<Routes @rendermode="InteractiveServer" />

Als de app per pagina/onderdeel interactiviteit gebruikt, moet u de volgende wijzigingen aanbrengen:

  • Voeg de weergavemodus interactieve server toe aan de bovenkant van het CultureExample1-onderdeelbestand (Components/Pages/CultureExample1.razor):

    @rendermode InteractiveServer
    
  • Pas in de hoofdindeling van de app (Components/Layout/MainLayout.razor) de weergavemodus interactieve server toe op het CultureSelector-onderdeel:

    <CultureSelector @rendermode="InteractiveServer" />
    

De cultuur dynamisch instellen in een Blazor Web App op basis van gebruikersvoorkeur

Deze sectie is van toepassing op Blazor Web App's die Auto (Server en WebAssembly) interactiviteit aannemen.

Voorbeelden van locaties waar een app de voorkeur van een gebruiker kan opslaan in lokale opslag (veelvoorkomend voor scenario's aan de clientzijde), in een lokalisatie cookie of database (algemeen voor scenario's aan de serverzijde), zowel lokale opslag als een lokalisatie-cookie (Blazor Web Appmet server- en WebAssembly-onderdelen) of in een externe service die is gekoppeld aan een externe database en toegankelijk is voor een web-API. In het volgende voorbeeld ziet u hoe u lokale browseropslag gebruikt voor csr-onderdelen (clientzijde) en een lokalisatie-cookie voor SSR-onderdelen (serverzijde).

Updates voor het .Client-project

Voeg het Microsoft.Extensions.Localization-pakket toe aan het .Client project.

Notitie

Zie de artikelen onder Pakketten installeren en beheren bij Verbruikswerkstroom voor pakketten (NuGet-documentatie)voor begeleiding bij het toevoegen van pakketten in .NET-apps. Bevestig de juiste pakketversies op NuGet.org.

Stel de eigenschap BlazorWebAssemblyLoadAllGlobalizationData in op true in het .Client projectbestand:

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

Voeg de naamruimten voor System.Globalization en Microsoft.JSInterop toe aan het begin van het .Client-bestand van het Program project:

using System.Globalization;
using Microsoft.JSInterop;

Verwijder de volgende regel:

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

Vervang de voorgaande regel door de volgende code. De code voegt de lokalisatieservice van Blazortoe aan de servicecollectie van de app met AddLocalization en gebruikt JS interop om een oproep te doen naar JS en de cultuurkeuze van de gebruiker op te halen uit de lokale opslag. Als lokale opslag geen cultuur voor de gebruiker bevat, wordt met de code een standaardwaarde ingesteld voor Engels (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();

Notitie

Op dit moment laden Blazor WebAssembly apps alleen resources op basis van DefaultThreadCurrentCulture. Voor meer informatie, zie Blazor waar WASM alleen afhankelijk is van de huidige cultuur (en de huidige UI-cultuur niet wordt gerespecteerd) (dotnet/aspnetcore #56824).

Voeg het volgende CultureSelector-onderdeel toe aan het .Client-project.

De component past de volgende benaderingen toe voor het werken met SSR- of CSR-componenten.

  • De weergavenaam van elke beschikbare cultuur in de vervolgkeuzelijst wordt geleverd door een woordenlijst, omdat globalisatiegegevens aan de clientzijde gelokaliseerde tekst van cultuurweergavenamen bevatten die door globalisatiegegevens aan de serverzijde worden verstrekt. Lokalisatie aan de serverzijde geeft bijvoorbeeld English (United States) weer wanneer en-US de cultuur is en Ingles () wanneer een andere cultuur wordt gebruikt. Omdat lokalisatie van de weergavenamen van de cultuur niet beschikbaar is voor Blazor WebAssembly globalisatie, is de weergavenaam voor Engels in de Verenigde Staten op de client voor elke geladen cultuur gewoon en-US. Met behulp van een aangepaste woordenlijst kan het onderdeel ten minste volledige Engelse cultuurnamen weergeven.
  • Wanneer de gebruiker de cultuur wijzigt, stelt JS de cultuur in lokale browseropslag in en werkt een controlleractie de lokalisatie cookie bij met de cultuur. De controller wordt later in het gedeelte van de updates van het Server-project aan de app toegevoegd.

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

Voeg in het .Client-bestand (_Imports) van het _Imports.razor project de naamruimte voor de onderdelen in de map Pages toe en werk de naamruimte bij zodat deze overeenkomt met de naamruimte van uw .Client project:

@using BlazorSample.Client.Pages

Notitie

Zie Blazorvoor meer informatie over .

Voeg in het .Client project het CultureSelector-onderdeel toe aan het MainLayout-onderdeel. Plaats de volgende markeringen in de afsluitende </main> tag in het Layout/MainLayout.razor-bestand:

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

Plaats in het .Client project het volgende CultureClient onderdeel om te onderzoeken hoe globalisering werkt voor CSR-onderdelen.

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>&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;
}

Plaats in het .Client project het volgende CultureServer onderdeel om te onderzoeken hoe globalisering werkt voor SSR-onderdelen.

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>&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;
}

Gebruik het CultureExample1 onderdeel dat wordt weergegeven in het demonstratieonderdeel sectie om te onderzoeken hoe globalisering werkt voor een onderdeel dat de globale modus voor automatisch renderen over neemt. Voeg de CultureExample1-component toe aan de map .Client van het Pages-project.

Voeg de onderdelen CultureClient, CultureServeren CultureExample1 toe aan de zijbalknavigatie in 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>

Server Projectupdates

Voeg het Microsoft.Extensions.Localization-pakket toe aan het serverproject.

Notitie

Zie de artikelen onder Pakketten installeren en beheren bij Verbruikswerkstroom voor pakketten (NuGet-documentatie)voor begeleiding bij het toevoegen van pakketten in .NET-apps. Bevestig de juiste pakketversies op NuGet.org.

Apps aan de serverzijde worden gelokaliseerd met behulp van Localization Middleware. Lokalisatieservices toevoegen aan de app met AddLocalization.

In het Program-bestand van het serverproject waarin services zijn geregistreerd:

builder.Services.AddLocalization();

Stel de standaard- en ondersteunde culturen van de app in met RequestLocalizationOptions.

Plaats vóór de aanroep naar MapRazorComponents in de aanvraagverwerkingspijplijn de volgende code:

var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

In het volgende voorbeeld ziet u hoe u de huidige cultuur instelt in een cookie die kan worden gelezen door de Localization Middleware.

De volgende naamruimten zijn vereist voor het App-onderdeel:

Voeg het volgende toe aan de bovenkant van het App-onderdeelbestand (Components/App.razor):

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

De cultuur van de app voor rendering aan de clientzijde wordt ingesteld met behulp van de API van het Blazor Framework. De cultuurselectie van een gebruiker kan worden bewaard in de lokale browseropslag voor CSR-onderdelen.

Nadat de Blazor's <script> tagis, biedt u JS functies aan om de keuze van de gebruikerscultuur op te halen en in te stellen met lokale opslag van de browser.

<script>
  window.blazorCulture = {
    get: () => window.localStorage['BlazorCulture'],
    set: (value) => window.localStorage['BlazorCulture'] = value
  };
</script>

Notitie

Het voorgaande voorbeeld vervuilt de klant met globale functies. Zie JavaScript-isolatie in JavaScript-modulesvoor een betere benadering van productie-apps.

Voeg het volgende @code blok toe aan de onderkant van het App-onderdeelbestand:

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

Als het serverproject niet is geconfigureerd voor procescontrolleracties:

  • Voeg MVC-services toe door AddControllers aan te roepen voor de serviceverzameling in het bestand Program:

    builder.Services.AddControllers();
    
  • Voeg controllereindpuntroutering toe aan het Program bestand door MapControllers aan te roepen op de IEndpointRouteBuilder (app):

    app.MapControllers();
    

Als u wilt dat een gebruiker een cultuur voor SSR-onderdelen selecteert, gebruikt u een benadering op basis van omleiding met een lokalisatie-cookie. De app behoudt de geselecteerde cultuur van de gebruiker via een omleiding naar een controller. De controller stelt de geselecteerde cultuur van de gebruiker in op een cookie en stuurt de gebruiker terug naar de oorspronkelijke URI. Het proces is vergelijkbaar met wat er gebeurt in een web-app wanneer een gebruiker probeert toegang te krijgen tot een beveiligde resource, waarbij de gebruiker wordt omgeleid naar een aanmeldingspagina en vervolgens wordt omgeleid naar de oorspronkelijke resource.

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

Waarschuwing

Gebruik het LocalRedirect actieresultaat, zoals wordt weergegeven in het vorige voorbeeld, om open omleidingsaanvallen te voorkomen. Zie Open redirect-aanvallen voorkomen in ASP.NET Corevoor meer informatie.

Interactieve autoonderdelen

De richtlijnen in deze sectie werken ook voor onderdelen in apps die gebruikmaken van weergave per pagina/onderdeel en de interactieve modus voor automatisch renderen opgeven:

@rendermode InteractiveAuto

Lokalisatie

Als de app nog geen dynamische cultuurselectie ondersteunt, voegt u het Microsoft.Extensions.Localization-pakket toe aan de app.

Notitie

Zie de artikelen onder Pakketten installeren en beheren bij Verbruikswerkstroom voor pakketten (NuGet-documentatie)voor begeleiding bij het toevoegen van pakketten in .NET-apps. Bevestig de juiste pakketversies op NuGet.org.

Lokalisatie aan de clientzijde

Stel de eigenschap BlazorWebAssemblyLoadAllGlobalizationData in op true in het projectbestand van de app (.csproj):

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

Voeg in het Program-bestand de naamruimte voor System.Globalization toe aan het begin van het bestand.

using System.Globalization;

Voeg de lokalisatieservice van Blazortoe aan de serviceverzameling van de app met AddLocalization:

builder.Services.AddLocalization();

Lokalisatie aan de serverzijde

Gebruik Localization Middleware om de cultuur van de app in te stellen.

Als de app nog geen dynamische cultuurselectie ondersteunt:

  • Lokalisatieservices toevoegen aan de app met AddLocalization.
  • Geef de standaard- en ondersteunde culturen van de app op in het Program-bestand. In het volgende voorbeeld worden ondersteunde culturen geconfigureerd voor Engels en Costa Ricaans Spaans in de Verenigde Staten.
builder.Services.AddLocalization();

Plaats middleware voor lokalisatie van aanvragen vóór middleware die de aanvraagcultuur kan controleren. Over het algemeen plaatst u de middleware direct voordat u MapRazorComponentsaanroept:

Direct nadat Routing Middleware (UseRouting) is toegevoegd aan de verwerkingspijplijn:

var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

Zie ASP.NET Core Middlewarevoor meer informatie over het ordenen van de Localization Middleware in de middleware-pijplijn.

  • Lokalisatieservices toevoegen aan de app met AddLocalization.
  • Geef de standaard- en ondersteunde culturen van de app op in Startup.Configure (Startup.cs). In het volgende voorbeeld worden ondersteunde culturen geconfigureerd voor Engels en Costa Ricaans Spaans in de Verenigde Staten.

In Startup.ConfigureServices (Startup.cs):

services.AddLocalization();

In Startup.Configure direct nadat Routing Middleware (UseRouting) is toegevoegd aan de verwerkingspijplijn:

var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

Zie Startup.Configurevoor informatie over het bestellen van de Localization Middleware in de middlewarepipeline van .

Als de app resources moet lokaliseren op basis van het opslaan van de cultuurinstelling van een gebruiker, gebruikt u een lokalisatiecultuur cookie. Het gebruik van een cookie zorgt ervoor dat de WebSocket-verbinding de cultuur correct kan doorgeven. Als lokalisatieschema's zijn gebaseerd op het URL-pad of de queryreeks, kan het schema mogelijk niet werken met WebSockets, waardoor de cultuur niet behouden blijft. Daarom is de aanbevolen aanpak om een lokalisatiecultuur te gebruiken cookie. Zie de sectie Dynamisch instellen van de serverzijde cultuur op basis van gebruikersvoorkeur van dit artikel voor een voorbeeld van de Razor expressie die de cultuurselectie van de gebruiker bewaart.

Voorbeeld van gelokaliseerde resources

Het voorbeeld van gelokaliseerde resources in deze sectie werkt met de eerdere voorbeelden in dit artikel, waarbij de ondersteunde culturen van de app Engels (en) zijn als een standaardlandinstelling en Spaans (es) als een door de gebruiker te selecteren of door de browser opgegeven alternatieve landinstelling.

Maak een resourcebestand voor elke locatie. In het volgende voorbeeld worden resources gemaakt voor een Greeting tekenreeks in het Engels en Spaans:

  • Engels (en): Hello, World!
  • Spaans (es): ¡Hola, Mundo!

Notitie

Het volgende resourcebestand kan worden toegevoegd in Visual Studio door met de rechtermuisknop op de map Pages te klikken en Add>New Item>Resources Filete selecteren. Geef het bestand de naam CultureExample2.resx. Wanneer de editor wordt weergegeven, geeft u gegevens op voor een nieuwe vermelding. Stel de naam in op Greeting en waarde op Hello, World!. Sla het bestand op.

Als u Visual Studio Code gebruikt, raden we u aan om ResX Viewer en Editor van Tim Heuerte installeren. Voeg een leeg CultureExample2.resx bestand toe aan de map Pages. De extensie neemt automatisch het beheer van het bestand in de gebruikersinterface over. Selecteer de knop Nieuwe resource toevoegen. Volg de instructies om een vermelding toe te voegen voor Greeting (sleutel), Hello, World! (waarde) en None (opmerking). Sla het bestand op. Als u het bestand sluit en opnieuw opent, ziet u de Greeting resource.

ResX Viewer en Editor van Tim Heuer niet eigendom is van of wordt onderhouden door Microsoft en niet wordt gedekt door een Microsoft-ondersteuningsovereenkomst of -licentie.

Hieronder ziet u een typisch resourcebestand. U kunt resourcebestanden handmatig in de map Pages van de app plaatsen als u liever geen ingebouwde hulpprogramma's gebruikt met een geïntegreerde ontwikkelomgeving (IDE), zoals de ingebouwde resourcebestandseditor van Visual Studio of Visual Studio Code met een extensie voor het maken en bewerken van resourcebestanden.

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>

Notitie

Het volgende resourcebestand kan worden toegevoegd in Visual Studio door met de rechtermuisknop op de map Pages te klikken en Add>New Item>Resources Filete selecteren. Geef het bestand de naam CultureExample2.es.resx. Wanneer de editor wordt weergegeven, geeft u gegevens op voor een nieuwe vermelding. Stel de naam in op Greeting en waarde op ¡Hola, Mundo!. Sla het bestand op.

Als u Visual Studio Code gebruikt, raden we u aan om ResX Viewer en Editor van Tim Heuerte installeren. Voeg een leeg CultureExample2.resx bestand toe aan de map Pages. De extensie neemt automatisch het beheer van het bestand in de gebruikersinterface over. Selecteer de knop Nieuwe resource toevoegen. Volg de instructies om een vermelding toe te voegen voor Greeting (sleutel), ¡Hola, Mundo! (waarde) en None (opmerking). Sla het bestand op. Als u het bestand sluit en opnieuw opent, ziet u de Greeting resource.

Hieronder ziet u een typisch resourcebestand. U kunt resourcebestanden handmatig in de map Pages van de app plaatsen als u liever geen ingebouwde hulpprogramma's gebruikt met een geïntegreerde ontwikkelomgeving (IDE), zoals de ingebouwde resourcebestandseditor van Visual Studio of Visual Studio Code met een extensie voor het maken en bewerken van resourcebestanden.

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>

In het volgende onderdeel ziet u het gebruik van de gelokaliseerde Greeting tekenreeks met IStringLocalizer<T>. De Razor markering @Loc["Greeting"] in het volgende voorbeeld lokaliseert de tekenreeks die is gekoppeld aan de Greeting-waarde, die is ingesteld in de voorgaande resourcebestanden.

Voeg de naamruimte voor Microsoft.Extensions.Localization toe aan het _Imports.razor-bestand van de app:

@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"];
    }
}

U kunt eventueel een menu-item voor het CultureExample2-onderdeel toevoegen aan de navigatie in het NavMenu-onderdeel (NavMenu.razor).

Referentiebron voor webassembly-cultuurprovider

Zie de WebAssemblyCultureProvider in de ASP.NET Core-referentiebron voor meer informatie over de lokalisatie van het framework.

Notitie

Documentatiekoppelingen naar .NET-referentiebron laden meestal de standaardbranch van de opslagplaats, die de huidige ontwikkeling vertegenwoordigt voor de volgende release van .NET. Als u een tag voor een specifieke release wilt selecteren, gebruikt u de Switch-vertakkingen of tags vervolgkeuzelijst. Zie Een versietag selecteren van ASP.NET Core-broncode (dotnet/AspNetCore.Docs #26205)voor meer informatie.

Gedeelde middelen

Om gedeelde lokalisatiebronnen te creëren, hanteer de volgende aanpak.

  • Controleer of naar het Microsoft.Extensions.Localization-pakket wordt verwezen door het project.

    Notitie

    Zie de artikelen onder Pakketten installeren en beheren bij Verbruikswerkstroom voor pakketten (NuGet-documentatie)voor begeleiding bij het toevoegen van pakketten in .NET-apps. Bevestig de juiste pakketversies op NuGet.org.

  • Controleer of de Microsoft.Extensions.Localization naamruimte beschikbaar is voor de Razor onderdelen van het project via een vermelding in het _Imports-bestand van het project:

    @using Microsoft.Extensions.Localization
    
  • Maak een dummyklasse met een willekeurige klassenaam. In het volgende voorbeeld:

    • De app maakt gebruik van de BlazorSample naamruimte en lokalisatieassets maken gebruik van de BlazorSample.Localization naamruimte.
    • De dummyklasse heet SharedResource.
    • Het klassebestand wordt in een Localization map in de hoofdmap van de app geplaatst.

    Notitie

    Gebruik geen automatisch gegenereerd designer-bestand (bijvoorbeeld SharedResources.Designer.cs). De dummy-klasse is bedoeld om te fungeren als de gedeelde hulpbronklasse. De aanwezigheid van een ontwerpfunctiebestand resulteert in een naamruimteconflict.

    Localization/SharedResource.cs:

    namespace BlazorSample.Localization;
    
    public class SharedResource
    {
    }
    
  • Maak de gedeelde resourcebestanden met een Buildactie van Embedded resource. In het volgende voorbeeld:

    • De bestanden worden in de Localization map geplaatst met de dummy SharedResource klasse (Localization/SharedResource.cs).

    • Geef de resourcebestanden een naam die overeenkomt met de naam van de dummy-klasse. De volgende voorbeeldbestanden bevatten een standaardlokalisatiebestand en een bestand voor Spaans (es) lokalisatie.

    • Localization/SharedResource.resx

    • Localization/SharedResource.es.resx

    Waarschuwing

    Wanneer u de aanpak in deze sectie volgt, kunt u niet tegelijkertijd LocalizationOptions.ResourcesPath instellen en IStringLocalizerFactory.Create gebruiken om resources te laden.

  • Als u wilt verwijzen naar de dummyklasse voor een geïnjecteerde IStringLocalizer<T> in een Razor-onderdeel, plaatst u een @using-instructie voor de lokalisatienaamruimte of neemt u de lokalisatienaamruimte op in de verwijzing naar de dummy-klasse. In de volgende voorbeelden:

    • In het eerste voorbeeld wordt de Localization naamruimte voor de SharedResource dummyklasse met een @using-instructie aangegeven.
    • In het tweede voorbeeld wordt de naamruimte van de SharedResource-dummyklasse expliciet genoemd.

    Gebruik in een Razor-onderdeel een van de volgende methoden:

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

Zie Globalization and localization in ASP.NET Corevoor aanvullende richtlijnen.

Locatie negeren met behulp van het deelvenster Sensoren in ontwikkelhulpprogramma's

Wanneer u de locatie overschrijft met behulp van het deelvenster Sensors in Google Chrome of de ontwikkelaarstools van Microsoft Edge, wordt de terugvaltaal opnieuw ingesteld na het prerenderen. Vermijd het instellen van de taal met behulp van het deelvenster Sensoren tijdens het testen. Stel de taal in met de taalinstellingen van de browser.

Zie Blazor Lokalisatie werkt niet met InteractiveServer (dotnet/aspnetcore #53707)voor meer informatie.

Aanvullende informatiebronnen