Partager via


Globalisation et localisation dans ASP.NET Core Blazor

Note

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 10 de cet article.

Warning

Cette version d'ASP.NET Core n'est plus prise en charge. Pour plus d’informations, consultez la stratégie de prise en charge de .NET et .NET Core. Pour la version actuelle, consultez la version .NET 10 de cet article.

Cet article explique comment restituer du contenu globalisé et localisé aux utilisateurs aux cultures et langues différentes.

Globalisation et localisation

Pour la globalisation, Blazor fournit la mise en forme des nombres et des dates. Pour la localisation, Blazor restitue le contenu à l’aide du système de ressources .NET.

Un ensemble limité de fonctionnalités de localisation d’ASP.NET Core sont prises en charge :

Pris en charge :IStringLocalizer and IStringLocalizer<T> sont pris en charge dans les applications Blazor.

Non pris en charge :IHtmlLocalizer et IViewLocalizer sont des fonctionnalités d'ASP.NET Core MVC et non pris en charge dans les applications Blazor.

Pour les applications Blazor, les messages de validation localisés pour la validation des formulaires à l’aide d’annotations de données sont pris en charge si DisplayAttribute.ResourceType et ValidationAttribute.ErrorMessageResourceType sont implémentés.

Cet article explique comment utiliser les fonctionnalités de globalisation et de localisation de Blazor en fonction des éléments suivants :

  • L’en-tête Accept-Language, qui est défini par le navigateur en fonction des préférences linguistiques d’un utilisateur dans les paramètres du navigateur.
  • La culture définie par l’application, qui n’est pas basée sur la valeur de l’en-tête Accept-Language. Le paramètre peut être statique pour tous les utilisateurs, ou dynamique en fonction de la logique de l’application. Lorsque le paramètre est basé sur la préférence de l’utilisateur, le paramètre est généralement enregistré pour être rechargé lors de visites ultérieures.

Pour des informations générales supplémentaires, consultez les ressources suivantes :

Souvent, les termes langue et culture sont utilisés indifféremment lorsqu’il s’agit de concepts de globalisation et de localisation.

Dans cet article, langue fait référence aux sélections effectuées par un utilisateur dans les paramètres de son navigateur. Les sélections de langue de l’utilisateur sont envoyées dans les requêtes de navigateur dans l’en-tête Accept-Language. Les paramètres du navigateur utilisent généralement le mot « langue » dans l’interface utilisateur.

La culture concerne les membres de .NET et de l’API Blazor. Par exemple, la requête d’un utilisateur peut inclure l’en-tête Accept-Language spécifiant une langue du point de vue de l’utilisateur, mais l’application définit la propriété CurrentCulture (« culture ») à partir de la langue demandée par l’utilisateur. L’API utilise généralement le mot « culture » dans ses noms de membres.

Les instructions de cet article ne couvrent pas la définition de l’attribut de langue HTML de la page (<html lang="...">), que les outils d’accessibilité utilisent. Vous pouvez définir la valeur de manière statique en attribuant une langue à l’attribut lang de la balise <html> ou à document.documentElement.lang dans JavaScript. Vous pouvez définir de manière dynamique la valeur de document.documentElement.lang avec JS interop.

Note

Les exemples de code de cet article adoptent les types référence null (NRT) et l'analyse statique de l'état null du compilateur .NET, qui sont pris en charge dans ASP.NET Core en .NET 6 ou une version ultérieure. Lorsque vous ciblez .NET 5 ou une version antérieure, supprimez la désignation de type Null (?) des exemples de l’article.

Globalisation

La directive d’attribut @bind applique des formats et analyse les valeurs d’affichage en fonction de la première langue préférée de l’utilisateur prise en charge par l’application. @bind prend en charge le paramètre @bind:culture pour fournir un System.Globalization.CultureInfo pour l’analyse et la mise en forme d’une valeur.

La culture actuelle est accessible à partir de la propriété System.Globalization.CultureInfo.CurrentCulture.

CultureInfo.InvariantCulture est utilisé pour les types de champs suivants (<input type="{TYPE}" />, où l’espace réservé {TYPE} est le type) :

  • date
  • number

Les types de champs précédents :

  • Sont affichés à l’aide de leurs règles de mise en forme basées sur le navigateur appropriées.
  • Ne peuvent pas contenir de texte de forme libre.
  • Fournissent des caractéristiques d’interaction utilisateur en fonction de l’implémentation du navigateur.

Blazor fournit une prise en charge intégrée du rendu des valeurs dans la culture actuelle. Par conséquent, il n’est pas recommandé de spécifier une culture avec @bind:culture lorsque les types de champs date et number sont utilisés.

Les types de champ suivants ont des exigences de mise en forme spécifiques et ne sont pas pris en charge par tous les principaux navigateurs ; ils ne sont donc pas pris en charge par Blazor :

  • datetime-local
  • month
  • week

Pour connaître la prise en charge actuelle des navigateurs des types précédents, consultez Puis-je utiliser.

Par défaut, Blazor charge un sous-ensemble de données de globalisation qui contient la culture de l’application. Pour charger toutes les données de globalisation, définissez-les <BlazorWebAssemblyLoadAllGlobalizationData>true dans le fichier projet de l’application (.csproj) :

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

Globalisation .NET et prise en charge (Blazor WebAssembly) des composants internationaux pour Unicode (ICU)

Blazor WebAssembly utilise une API de globalisation réduite et un ensemble de paramètres régionaux pour les composants internationaux Unicode (ICU) intégrés.

Dans les applications WebAssembly (Wasm), lorsque le mode invariant de la globalisation est désactivé, un fichier de données ICU est chargé. Il existe quatre types de base de ces fichiers :

  • icudt.dat: Données complètes
  • icudt_EFIGS.dat: données pour les paramètres régionaux : en-*, fr-FR, es-ES, it-IT, et de-DE.
  • icudt_CJK.dat: Données pour les paramètres régionaux : en-*, ja, ko, et zh-*.
  • icudt_no_CJK.dat: données pour tous les paramètres régionaux de icudt.dat, à l’exclusion de ja, ko et zh-*.

Spécifiez un fichier à charger avec la <BlazorIcuDataFileName> propriété MSBuild dans le fichier projet de l’application (.csproj). L’exemple suivant charge le icudt_no_CJK.dat fichier :

<PropertyGroup>
  <BlazorIcuDataFileName>icudt_no_CJK.dat</BlazorIcuDataFileName>
</PropertyGroup>

<BlazorIcuDataFileName> accepte uniquement un seul fichier. Le fichier peut être un fichier personnalisé créé par le développeur. Pour créer un fichier d’ICU personnalisé, consultez l’Icu de globalisation WASM : ICU personnalisé.

Si un fichier n’est pas spécifié avec <BlazorIcuDataFileName>, la culture de l’application est vérifiée et le fichier DCU correspondant est chargé pour sa culture. Par exemple, la en-US culture entraîne le chargement du icudt_EFIGS.dat fichier. Pour zh-CN, le icudt_CJK.dat fichier est utilisé.

Pour plus d’informations, consultez Globalisation .NET et ICU : ICU sur WebAssembly.

Blazor WebAssembly utilise une API de globalisation réduite et un ensemble de paramètres régionaux pour les composants internationaux Unicode (ICU) intégrés. Pour plus d’informations, consultez Globalisation .NET et ICU : ICU sur WebAssembly.

Le chargement d’un sous-ensemble personnalisé de paramètres régionaux dans une application Blazor WebAssembly est pris en charge dans .NET 8 ou version ultérieure. Pour plus d’informations, accédez à cette section pour une version .NET 8 ou ultérieure de cet article.

Globalisation invariante

Cette section s’applique uniquement aux scénarios Blazor côté client.

Si l’application ne nécessite pas de localisation, configurez l’application pour prendre en charge la culture invariante, qui est généralement basée sur l’anglais des États-Unis (en-US). L’utilisation de la globalisation invariante réduit la taille de téléchargement de l’application et permet un démarrage accéléré des applications. Définissez la propriété InvariantGlobalization sur true dans le fichier projet de l’application (.csproj) :

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

Vous pouvez également configurer la globalisation invariante avec les approches suivantes :

  • Dans runtimeconfig.json :

    {
      "runtimeOptions": {
        "configProperties": {
          "System.Globalization.Invariant": true
        }
      }
    }
    
  • Avec une variable d’environnement :

    • Clé :DOTNET_SYSTEM_GLOBALIZATION_INVARIANT
    • Valeur : true ou 1

Pour plus d’informations, consultez Options de configuration d’exécution pour la globalisation (documentation .NET).

Informations sur le fuseau horaire

Cette section s’applique uniquement aux scénarios Blazor côté client.

L’adoption d’une globalisation invariante entraîne uniquement l’utilisation de noms de fuseaux horaires non localisés. Pour réduire le code et les données de fuseau horaire, ce qui réduit la taille du téléchargement de l’application et accélère son démarrage, appliquez la propriété MSBuild <InvariantTimezone> avec la valeur true dans le fichier projet de l’application :

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

Note

<BlazorEnableTimeZoneSupport> remplace un paramètre <InvariantTimezone> antérieur. Nous vous recommandons de supprimer le paramètre <BlazorEnableTimeZoneSupport>.

Un fichier de données est inclus pour que les informations de fuseau horaire soient correctes. Si l’application n’a pas besoin de cette fonctionnalité, vous pouvez la désactiver en définissant la propriété MSBuild <BlazorEnableTimeZoneSupport> sur la valeur false dans le fichier projet de l’application :

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

Composant de démonstration

Le composant CultureExample1 suivant peut être utilisé pour illustrer les concepts de globalisation et de localisation de Blazor abordés par cet article.

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

Le format de chaîne numérique (N2) dans l’exemple précédent (.ToString("N2")) est un spécificateur de format numérique .NET standard. Le format N2 est pris en charge pour tous les types numériques, inclut un séparateur de groupe et affiche jusqu’à deux décimales.

Si vous le souhaitez, ajoutez un élément de menu à la navigation dans le composant NavMenu (NavMenu.razor) pour le composant CultureExample1.

Définir dynamiquement la culture à partir de l’en-tête Accept-Language

Ajoutez le package Microsoft.Extensions.Localization à l’application.

L’en-tête Accept-Language est défini par le navigateur et contrôlé par les préférences linguistiques de l’utilisateur dans les paramètres du navigateur. Dans les paramètres du navigateur, un utilisateur définit une ou plusieurs langues préférées par ordre de préférence. L’ordre de préférence est utilisé par le navigateur pour définir des valeurs de qualité (q, 0-1) pour chaque langue dans l’en-tête. L’exemple suivant spécifie l’anglais des États-Unis, l’anglais et l’espagnol costaricain avec une préférence pour l’anglais des États-Unis ou l’anglais :

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

La culture de l’application est définie en mettant en correspondance la première langue demandée qui correspond à une culture prise en charge de l’application.

Lors du développement côté client, définissez la propriété BlazorWebAssemblyLoadAllGlobalizationData sur true dans le fichier projet de l’application côté client (.csproj) :

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

Lors du développement côté client, la définition dynamique de la culture à partir de l’en-tête Accept-Language n’est pas prise en charge.

Note

Si la spécification de l’application nécessite de limiter les cultures prises en charge à une liste explicite, consultez la section Définir dynamiquement la culture côté client par préférence utilisateur de cet article.

Les applications sont localisées à l’aide d’un intergiciel (middleware) de localisation. Ajoutez des services de localisation à l’application avec AddLocalization.

Ajoutez la ligne suivante au fichier Program dans lequel les services sont inscrits :

builder.Services.AddLocalization();

Dans le développement côté serveur, spécifiez les cultures prises en charge par l’application avant tout intergiciel qui peut vérifier la culture de la requête. En règle générale, placez l’intergiciel de localisation de la requête immédiatement avant d’appeler MapRazorComponents. L’exemple suivant configure les cultures prises en charge pour l’anglais des États-Unis et l’espagnol costaricain :

Dans le développement côté serveur, spécifiez les cultures prises en charge par l’application immédiatement après l’ajout du middleware de routage (UseRouting) au pipeline de traitement. L’exemple suivant configure les cultures prises en charge pour l’anglais et l’espagnol costa ricain aux États-Unis à l’aide de l’API suivante :

  • AddSupportedCultures ajoute l’ensemble des cultures prises en charge pour la globalisation (date, nombre et mise en forme monétaire).
  • AddSupportedUICultures ajoute l’ensemble des cultures d’interface utilisateur prises en charge pour la localisation (chaînes d’interface utilisateur traduites pour le rendu du contenu).
app.UseRequestLocalization(new RequestLocalizationOptions()
    .AddSupportedCultures(new[] { "en-US", "es-CR" })
    .AddSupportedUICultures(new[] { "en-US", "es-CR" }));

Dans l’exemple précédent, les mêmes cultures de mise en forme et cultures d’interface utilisateur prises en charge sont spécifiées dans un cas étroit où l’application est utilisée uniquement aux États-Unis et au Costa Rica. Une application peut également utiliser un ensemble plus large de cultures pour la mise en forme de date, de nombre et de devise, mais uniquement fournir du contenu localisé pour les États-Unis et le Costa Rica, comme l’illustre l’exemple suivant :

var uiCultures = new[] { "en-US", "es-CR" };

var formattingCultures = CultureInfo
    .GetCultures(CultureTypes.SpecificCultures)
    .Select(c => c.Name)
    .ToArray();

var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(uiCultures[0])
    .AddSupportedCultures(formattingCultures)
    .AddSupportedUICultures(uiCultures);

app.UseRequestLocalization(localizationOptions);

Dans l’exemple précédent, CultureTypes.SpecificCultures retourne uniquement les cultures spécifiques à un pays ou à une région, par exemple, en-US ou fr-FR, qui sont fournies avec des données complètes et concrètes de globalisation (pour les dates, les nombres, les calendriers et d’autres interfaces utilisateur culturelles) que .NET peut utiliser pour une mise en forme et une analyse précises. Les cultures neutres, telles que en ou fr, peuvent ne pas avoir de données de globalisation complètes, de sorte qu’elles ne sont pas incluses dans cette liste.

Pour plus d’informations sur la commande d’intergiciels de localisation dans le pipeline d’intergiciels du fichier Program, consultez Intergiciel ASP.NET Core.

Utilisez le composant CultureExample1 indiqué dans la section Composant de démonstration pour étudier le fonctionnement de la globalisation. Émettre une requête avec l’anglais des États-Unis (en-US). Basculez vers l’espagnol costaricain (es-CR) dans les paramètres de langue du navigateur. Demandez à nouveau la page web.

Lorsque la culture est l’anglais des États-Unis (en-US), le composant rendu utilise la mise en forme de date mois/jour (6/7), une heure sur le modèle de 12 heures (AM/PM) et des virgules de séparation dans les nombres avec un point pour la valeur décimale (1,999.69) :

  • Date: 6/7/2021 6:45:22 AM
  • Numéro : 1,999.69

Lorsque la culture est l’espagnol costaricain (es-CR), le composant rendu utilise la mise en forme de date jour/mois (7/6), une heure sur le modèle de 24 heures et des points comme séparateur de nombres avec une virgule pour la valeur décimale (1.999,69) :

  • Date : 6/7/2021 6:49:38
  • Numéro : 1,999.69

Définir statiquement la culture côté client

Définissez la propriété BlazorWebAssemblyLoadAllGlobalizationData sur true dans le fichier projet de l’application (.csproj) :

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

Par défaut, la configuration de l’éditeur de liens pour Intermediate Language (IL) du rendu côté client supprime les informations d’internationalisation, à l’exception des paramètres régionaux explicitement demandés. Pour plus d’informations, consultez Configurer l’éditeur de liens pour ASP.NET Core Blazor.

La culture de l’application peut être définie en JavaScript lorsque Blazor commence par l’option de démarrage applicationCultureBlazor. L’exemple suivant configure le lancement de l’application à l’aide de la culture Anglais des États-Unis (en-US).

Empêcher le démarrage automatique de Blazor en ajoutant autostart="false" à la balise Blazor de <script> :

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

Dans l’exemple précédent, l’espace réservé {BLAZOR SCRIPT} est le chemin d’accès de script Blazor et le nom de fichier. Pour connaître l’emplacement du script, consultez Structure de projet ASP.NET Core Blazor.

Ajoutez le bloc <script> suivant après la balise Blazor de <script> et avant la balise </body> fermante :

Blazor Web App :

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

Blazor WebAssembly autonome :

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

La valeur pour applicationCulture doit être conforme au format de balise de langue BCP-47. Pour plus d’informations sur le démarrage de Blazor, consultez Démarrage d’ASP.NET Core Blazor.

Une alternative à la définition de l’option de démarrage Blazor de la culture consiste à définir la culture en code C#. Définissez CultureInfo.DefaultThreadCurrentCulture et CultureInfo.DefaultThreadCurrentUICulture dans le fichier Program sur la même culture.

Ajoutez l’espace de noms System.Globalization au fichier Program :

using System.Globalization;

Ajoutez les paramètres de culture avant la ligne qui génère et exécute WebAssemblyHostBuilder (await builder.Build().RunAsync();) :

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

Note

Dans .NET 9 ou version antérieure, les applications autonomes Blazor WebAssembly chargent les ressources de globalisation de l’interface utilisateur en fonction de CultureInfo.DefaultThreadCurrentCulture. Si vous souhaitez charger des données de globalisation supplémentaires pour votre culture de localisation définie par CultureInfo.DefaultThreadCurrentUICulture, mettez à niveau l’application vers .NET 10 ou version ultérieure.

Utilisez le composant CultureExample1 indiqué dans la section Composant de démonstration pour étudier le fonctionnement de la globalisation. Émettre une requête avec l’anglais des États-Unis (en-US). Basculez vers l’espagnol costaricain (es-CR) dans les paramètres de langue du navigateur. Demandez à nouveau la page web. Lorsque la langue demandée est l’espagnol costaricain, la culture de l’application reste l’anglais des États-Unis (en-US).

Définir statiquement la culture côté serveur

Les applications côté serveur sont localisées à l’aide d’un intergiciel de localisation. Ajoutez des services de localisation à l’application avec AddLocalization.

Dans le fichier Program :

builder.Services.AddLocalization();

Spécifiez la culture statique dans le fichier Program avant tout intergiciel qui peut vérifier la culture de la requête. En règle générale, placez l’intergiciel de localisation de la requête immédiatement avant MapRazorComponents. L’exemple suivant configure l’anglais des États-Unis :

Spécifiez la culture statique dans le fichier Program immédiatement après l’ajout de l’intergiciel de routage (UseRouting) au pipeline de traitement. L’exemple suivant configure l’anglais des États-Unis :

app.UseRequestLocalization("en-US");

La valeur de culture pour UseRequestLocalization doit être conforme au format de balise de langue BCP-47.

Pour plus d’informations sur la commande d’intergiciels de localisation dans le pipeline d’intergiciels du fichier Program, consultez Intergiciel ASP.NET Core.

Les applications côté serveur sont localisées à l’aide d’un intergiciel de localisation. Ajoutez des services de localisation à l’application avec AddLocalization.

Dans Startup.ConfigureServices (Startup.cs) :

services.AddLocalization();

Spécifiez la culture statique dans Startup.Configure (Startup.cs) immédiatement après l’ajout de l’intergiciel de routage au pipeline de traitement. L’exemple suivant configure l’anglais des États-Unis :

app.UseRequestLocalization("en-US");

La valeur de culture pour UseRequestLocalization doit être conforme au format de balise de langue BCP-47.

Pour plus d’informations sur la commande d’intergiciels de localisation dans le pipeline d’intergiciel de Startup.Configure, consultez Intergiciels ASP.NET Core.

Utilisez le composant CultureExample1 indiqué dans la section Composant de démonstration pour étudier le fonctionnement de la globalisation. Émettre une requête avec l’anglais des États-Unis (en-US). Basculez vers l’espagnol costaricain (es-CR) dans les paramètres de langue du navigateur. Demandez à nouveau la page web. Lorsque la langue demandée est l’espagnol costaricain, la culture de l’application reste l’anglais des États-Unis (en-US).

Définir dynamiquement la culture côté client par préférence utilisateur

Les préférences d’un utilisateur peuvent être stockées par une application dans le stockage local du navigateur (courant pour les scénarios côté client), dans un cookie ou une base de données de localisation (courant pour les scénarios côté serveur), ou dans un service externe lié à une base de données externe et accessible par une API web, par exemple. L’exemple suivant montre comment utiliser le stockage local du navigateur.

Ajoutez le package Microsoft.Extensions.Localization à l’application.

Note

Pour obtenir des conseils sur l'ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

Définissez la propriété BlazorWebAssemblyLoadAllGlobalizationData sur true dans le fichier projet :

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

La culture de l’application pour le rendu côté client est définie à l’aide de l’API de l’infrastructure Blazor. La sélection de culture d’un utilisateur peut être conservée dans le stockage local du navigateur.

Fournissez des fonctions JS après la balise Blazor de <script> pour obtenir et définir la sélection de la culture de l’utilisateur avec le stockage local du navigateur :

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

Note

L’exemple précédent pollue le client avec des fonctions globales. Pour une meilleure approche dans les applications de production, consultez Isolation JavaScript dans les modules JavaScript.

Ajoutez les espaces de noms pour System.Globalization et Microsoft.JSInterop en haut du fichier Program :

using System.Globalization;
using Microsoft.JSInterop;

Supprimez la ligne suivante :

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

Remplacez la ligne précédente par le code suivant. Le code ajoute le service de localisation de Blazor à la collection de services de l’application avec AddLocalization, et utilise l’interopérabilité JS pour appeler JS et récupérer la sélection de la culture de l’utilisateur à partir du stockage local. Si le stockage local ne contient pas de culture pour l’utilisateur, le code définit la valeur par défaut Anglais des États-Unis (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();

Note

Dans .NET 9 ou version antérieure, les applications autonomes Blazor WebAssembly chargent les ressources de globalisation de l’interface utilisateur en fonction de CultureInfo.DefaultThreadCurrentCulture. Si vous souhaitez charger des données de globalisation supplémentaires pour votre culture de localisation définie par CultureInfo.DefaultThreadCurrentUICulture, mettez à niveau l’application vers .NET 10 ou version ultérieure.

Le composant CultureSelector suivant montre comment effectuer les actions suivantes :

  • Définissez la sélection de culture de l’utilisateur dans le stockage local du navigateur via l’interopérabilité JS.
  • Rechargez le composant demandé (forceLoad: true), qui utilise la culture mise à jour.

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

À l’intérieur de la balise fermante de l’élément </main> du composant MainLayout (MainLayout.razor), ajoutez le composant CultureSelector :

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

Utilisez le composant CultureExample1 indiqué dans la section Composant de démonstration pour étudier le fonctionnement de l’exemple précédent.

Définir dynamiquement la culture côté serveur par préférence utilisateur

Les préférences d’un utilisateur peuvent être stockées par une application dans le stockage local du navigateur (courant pour les scénarios côté client), dans un cookie ou une base de données de localisation (courant pour les scénarios côté serveur), ou dans un service externe lié à une base de données externe et accessible par une API web, par exemple. L’exemple suivant montre comment utiliser un cookie de localisation.

Note

L’exemple suivant suppose que l’application adopte une interactivité globale en spécifiant le rendu interactif côté serveur (interactive SSR) sur le composant Routes dans le composant App (Components/App.razor) :

<Routes @rendermode="InteractiveServer" />

Si l’application adopte l’interactivité par page/composant, consultez les remarques à la fin de cette section pour modifier les modes de rendu des composants de l’exemple.

Ajoutez le package Microsoft.Extensions.Localization à l’application.

Note

Pour obtenir des conseils sur l'ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

Les applications côté serveur sont localisées à l’aide d’un intergiciel de localisation. Ajoutez des services de localisation à l’application avec AddLocalization.

Dans le fichier Program :

builder.Services.AddLocalization();

Définissez les cultures par défaut et prises en charge de l’application avec RequestLocalizationOptions.

Avant l’appel à MapRazorComponents dans le pipeline de traitement des requêtes, placez le code suivant :

Une fois l’intergiciel de routage (UseRouting) ajouté au pipeline de traitement des requêtes, placez le code suivant :

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

app.UseRequestLocalization(localizationOptions);

Pour plus d’informations sur la commande d’intergiciels de localisation dans le pipeline d’intergiciels, consultez Intergiciel ASP.NET Core.

L’exemple suivant montre comment définir la culture actuelle dans un cookie qui peut être lu par l’intergiciel de localisation.

Les espaces de noms suivants sont requis pour le composant App :

Ajoutez ce qui suit au début du fichier de composant App (Components/App.razor) :

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

Ajoutez le bloc @code suivant au bas du fichier de composant App :

@code {
    [CascadingParameter]
    private HttpContext? HttpContext { get; set; }

    protected override void OnInitialized()
    {
        HttpContext?.Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(
                new RequestCulture(
                    CultureInfo.CurrentCulture,
                    CultureInfo.CurrentUICulture)));
    }
}

Les modifications apportées au fichier Pages/_Host.cshtml nécessitent les espaces de noms suivants :

Ajoutez le code suivant au fichier :

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

Pour plus d’informations sur la commande d’intergiciels de localisation dans le pipeline d’intergiciels, consultez Intergiciel ASP.NET Core.

Si l’application n’est pas configurée pour traiter les actions du contrôleur :

  • Ajoutez des services MVC en appelant AddControllers sur la collection de services dans le fichier Program :

    builder.Services.AddControllers();
    
  • Ajoutez le routage du point de terminaison du contrôleur dans le fichier Program en appelant MapControllers sur IEndpointRouteBuilder (app) :

    app.MapControllers();
    

Pour fournir une interface utilisateur permettant à un utilisateur de sélectionner une culture, utilisez une approche basée sur la redirection avec un cookie de localisation. L’application conserve la culture sélectionnée de l’utilisateur via une redirection vers un contrôleur. Le contrôleur définit la culture sélectionnée de l’utilisateur dans un cookie et redirige l’utilisateur vers l’URI d’origine. Le processus est similaire à ce qui se produit dans une application web lorsqu’un utilisateur tente d’accéder à une ressource sécurisée, où l’utilisateur est redirigé vers une page de connexion, puis vers la ressource d’origine.

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

Warning

Utilisez le résultat de l’action LocalRedirect, comme indiqué dans l’exemple précédent, pour empêcher les attaques de redirection ouvertes. Pour plus d’informations, consultez Empêcher les attaques par redirection ouverte dans ASP.NET Core.

Le composant CultureSelector suivant montre comment appeler la méthode Set de CultureController avec la nouvelle culture. Le composant est placé dans le dossier Shared pour une utilisation dans l’ensemble de l’application.

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

Ajoutez le composant CultureSelector au composant MainLayout : Placez le balisage suivant à l’intérieur de la balise </main> de fermeture dans le fichier Components/Layout/MainLayout.razor :

Ajoutez le composant CultureSelector au composant MainLayout : Placez le balisage suivant à l’intérieur de la balise </main> de fermeture dans le fichier Shared/MainLayout.razor :

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

Utilisez le composant CultureExample1 indiqué dans la section Composant de démonstration pour étudier le fonctionnement de l’exemple précédent.

L’exemple précédent suppose que l’application adopte l’interactivité globale en spécifiant le mode de rendu de serveur interactif sur le composant Routes dans le composant App (Components/App.razor) :

<Routes @rendermode="InteractiveServer" />

Si l’application adopte l’interactivité par page/composant, apportez les modifications suivantes :

  • Ajoutez le mode de rendu Serveur interactif en haut du fichier de composant CultureExample1 (Components/Pages/CultureExample1.razor) :

    @rendermode InteractiveServer
    
  • Dans la présentation principale de l’application (Components/Layout/MainLayout.razor), appliquez le mode de rendu Serveur interactif au composant CultureSelector :

    <CultureSelector @rendermode="InteractiveServer" />
    

Définir dynamiquement la culture dans une Blazor Web App en fonction des préférences de l’utilisateur

Cette section s’applique aux Blazor Web App qui adoptent l’interactivité automatique (serveur et WebAssembly).

Les préférences d’un utilisateur peuvent être stockées par une application dans le stockage local du navigateur (courant pour les scénarios côté client), dans un cookie ou une base de données de localisation (courant pour les scénarios côté serveur), à la fois dans le stockage local et dans un cookie de localisation (Blazor Web App avec serveur et composants WebAssembly), ou dans un service externe lié à une base de données externe et accessible par une API Web, par exemple. L’exemple suivant montre comment utiliser le stockage local du navigateur pour les composants rendus côté client (CSR) et un cookie de localisation pour les composants rendus côté serveur (SSR).

Mises à jour du projet .Client

Ajoutez le package Microsoft.Extensions.Localization au projet .Client.

Note

Pour obtenir des conseils sur l'ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

Définissez la propriété BlazorWebAssemblyLoadAllGlobalizationData sur true dans le fichier projet .Client :

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

Ajoutez l’espace de noms pour System.Globalization et Microsoft.JSInterop en haut du fichier .Client du projet Program :

using System.Globalization;
using Microsoft.JSInterop;

Supprimez la ligne suivante :

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

Remplacez la ligne précédente par le code suivant. Le code ajoute le service de localisation de Blazor à la collection de services de l’application avec AddLocalization, et utilise l’interopérabilité JS pour appeler JS et récupérer la sélection de la culture de l’utilisateur à partir du stockage local. Si le stockage local ne contient pas de culture pour l’utilisateur, le code définit la valeur par défaut Anglais des États-Unis (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();

Note

Dans .NET 9 ou version antérieure, les applications autonomes Blazor WebAssembly chargent les ressources de globalisation de l’interface utilisateur en fonction de CultureInfo.DefaultThreadCurrentCulture. Si vous souhaitez charger des données de globalisation supplémentaires pour votre culture de localisation définie par CultureInfo.DefaultThreadCurrentUICulture, mettez à niveau l’application vers .NET 10 ou version ultérieure.

Ajoutez le composant CultureSelector suivant au projet .Client.

Le composant adopte les approches suivantes pour travailler pour les composants SSR ou CSR :

  • Le nom d’affichage de chaque culture disponible dans la liste déroulante est fourni par un dictionnaire parce que les données de globalisation côté client incluent le texte localisé des noms d’affichage des cultures que les données de globalisation côté serveur fournissent. Par exemple, la localisation côté serveur affiche English (United States) lorsque en-US est la culture et Ingles () lorsqu’une autre culture est utilisée. Étant donné que la localisation des noms d’affichage des cultures n’est pas disponible avec la globalisation de Blazor WebAssembly, le nom d’affichage pour l’anglais des États-Unis sur le client pour n’importe quelle culture chargée est simplement en-US. L’utilisation d’un dictionnaire personnalisé permet au composant d’afficher au moins des noms complets de culture anglaise.
  • Lorsque l’utilisateur change de culture, l’interopérabilité JS définit la culture dans le stockage du navigateur local et une action du contrôleur met à jour le cookie de localisation avec la culture. Le contrôleur est ajouté à l’application plus loin dans la section Mise à jour du projet serveur.

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

Dans le fichier .Client du projet _Imports (_Imports.razor), ajoutez l’espace de noms des composants dans le dossier Pages, en mettant à jour l’espace de noms pour qu’il corresponde à celui de votre projet .Client:

@using BlazorSample.Client.Pages

Dans le projet .Client, ajoutez le composant CultureSelector au composant MainLayout. Placez le balisage suivant à l’intérieur de la balise </main> de fermeture dans le fichier Layout/MainLayout.razor :

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

Dans le projet .Client, placez le composant CultureClient suivant pour étudier comment fonctionne la globalisation pour les composants CSR.

Pages/CultureClient.razor :

@page "/culture-client"
@rendermode InteractiveWebAssembly
@using System.Globalization

<PageTitle>Culture Client</PageTitle>

<h1>Culture Client</h1>

<ul>
    <li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
    <li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>

<h2>Rendered values</h2>

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

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

Dans le projet .Client, placez le composant CultureServer suivant pour étudier comment fonctionne la globalisation pour les composants SSR.

Pages/CultureServer.razor :

@page "/culture-server"
@rendermode InteractiveServer
@using System.Globalization

<PageTitle>Culture Server</PageTitle>

<h1>Culture Server</h1>

<ul>
    <li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
    <li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>

<h2>Rendered values</h2>

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

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

Utilisez le composant CultureExample1 présenté dans la section Composant de démonstration pour étudier comment fonctionne la globalisation pour un composant qui hérite du mode de rendu Auto global. Ajoutez le composant CultureExample1 au dossier .Client du projet Pages.

Ajoutez les composants CultureClient, CultureServer et CultureExample1 à la navigation de la barre latérale dans 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>

Mise à jour du projet serveur

Ajoutez le package Microsoft.Extensions.Localization au projet serveur.

Note

Pour obtenir des conseils sur l'ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

Les applications côté serveur sont localisées à l’aide d’un intergiciel de localisation. Ajoutez des services de localisation à l’application avec AddLocalization.

Dans le fichier Program du projet serveur où les services sont enregistrés :

builder.Services.AddLocalization();

Définissez les cultures par défaut et prises en charge de l’application avec RequestLocalizationOptions.

Avant l’appel à MapRazorComponents dans le pipeline de traitement des requêtes, placez le code suivant :

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

app.UseRequestLocalization(localizationOptions);

L’exemple suivant montre comment définir la culture actuelle dans un cookie qui peut être lu par l’intergiciel de localisation.

Les espaces de noms suivants sont requis pour le composant App :

Ajoutez ce qui suit au début du fichier de composant App (Components/App.razor) :

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

La culture de l’application pour le rendu côté client est définie à l’aide de l’API de l’infrastructure Blazor. La sélection de culture d’un utilisateur peut être conservée dans le stockage local du navigateur pour les composants CSR.

Après la balise Blazor de <script>, fournissez des fonctions JS pour obtenir et définir la sélection de la culture de l’utilisateur avec le stockage local du navigateur :

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

Note

L’exemple précédent pollue le client avec des fonctions globales. Pour une meilleure approche dans les applications de production, consultez Isolation JavaScript dans les modules JavaScript.

Ajoutez le bloc @code suivant au bas du fichier de composant App :

@code {
    [CascadingParameter]
    private HttpContext? HttpContext { get; set; }

    protected override void OnInitialized()
    {
        HttpContext?.Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(
                new RequestCulture(
                    CultureInfo.CurrentCulture,
                    CultureInfo.CurrentUICulture)));
    }
}

Si projet serveur n’est pas configuré pour traiter les actions du contrôleur :

  • Ajoutez des services MVC en appelant AddControllers sur la collection de services dans le fichier Program :

    builder.Services.AddControllers();
    
  • Ajoutez le routage du point de terminaison du contrôleur dans le fichier Program en appelant MapControllers sur IEndpointRouteBuilder (app) :

    app.MapControllers();
    

Pour permettre à un utilisateur de sélectionner une culture pour les composants SSR, utilisez une approche basée sur la redirection avec un cookie de localisation. L’application conserve la culture sélectionnée de l’utilisateur via une redirection vers un contrôleur. Le contrôleur définit la culture sélectionnée de l’utilisateur dans un cookie et redirige l’utilisateur vers l’URI d’origine. Le processus est similaire à ce qui se produit dans une application web lorsqu’un utilisateur tente d’accéder à une ressource sécurisée, où l’utilisateur est redirigé vers une page de connexion, puis vers la ressource d’origine.

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

Warning

Utilisez le résultat de l’action LocalRedirect, comme indiqué dans l’exemple précédent, pour empêcher les attaques de redirection ouvertes. Pour plus d’informations, consultez Empêcher les attaques par redirection ouverte dans ASP.NET Core.

Composants automatiques interactifs

Les recommandations de cette section s’appliquent également aux composants dans les applications qui adoptent un rendu par page/composant et spécifient le mode de rendu Interactive Auto :

@rendermode InteractiveAuto

Localisation

Si l’application ne prend pas déjà en charge la sélection de culture dynamique, ajoutez le package Microsoft.Extensions.Localization à l’application.

Note

Pour obtenir des conseils sur l'ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

Localisation côté client

Définissez la propriété BlazorWebAssemblyLoadAllGlobalizationData sur true dans le fichier projet de l’application (.csproj) :

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

Dans le fichier Program, ajoutez l’espace de noms pour System.Globalization en haut du fichier :

using System.Globalization;

Ajoutez le service de localisation de Blazor à la collection de services de l’application avec AddLocalization :

builder.Services.AddLocalization();

Localisation côté serveur

Utilisez l’intergiciel de localisation pour définir la culture de l’application.

Si l’application ne prend pas déjà en charge la sélection de culture dynamique :

  • Ajoutez des services de localisation à l’application avec AddLocalization.
  • Spécifiez les cultures par défaut et prises en charge de l’application dans le fichier Program. L’exemple suivant configure les cultures prises en charge pour l’anglais des États-Unis et l’espagnol costaricain.
builder.Services.AddLocalization();

Placez l’intergiciel de localisation des requêtes avant tout intergiciel qui peut vérifier la culture de la requête. En règle générale, placez l’intergiciel immédiatement avant d’appeler MapRazorComponents :

Immédiatement après l’ajout de l’intergiciel de routage (UseRouting) au pipeline de traitement :

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

app.UseRequestLocalization(localizationOptions);

Pour plus d’informations sur la commande d’intergiciels de localisation dans le pipeline d’intergiciels, consultez Intergiciel ASP.NET Core.

  • Ajoutez des services de localisation à l’application avec AddLocalization.
  • Spécifiez les cultures par défaut et prises en charge de l’application dans Startup.Configure (Startup.cs). L’exemple suivant configure les cultures prises en charge pour l’anglais des États-Unis et l’espagnol costaricain.

Dans Startup.ConfigureServices (Startup.cs) :

services.AddLocalization();

Dans Startup.Configure, immédiatement après l’ajout de l’intergiciel de routage (UseRouting) au pipeline de traitement :

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

app.UseRequestLocalization(localizationOptions);

Pour plus d’informations sur la commande d’intergiciels de localisation dans le pipeline d’intergiciel de Startup.Configure, consultez Intergiciels ASP.NET Core.

Si l’application doit localiser des ressources en fonction du stockage du paramètre de culture d’un utilisateur, utilisez un cookie de culture de localisation. L’utilisation d’un cookie garantit que la connexion WebSocket peut propager correctement la culture. Si les schémas de localisation sont basés sur le chemin d’URL ou la chaîne de requête, le schéma peut ne pas être en mesure de fonctionner avec WebSockets pour conserver la culture. Par conséquent, l’approche recommandée consiste à utiliser un cookie de culture de localisation. Consultez la section Définir dynamiquement la culture côté serveur par préférence utilisateur de cet article pour voir un exemple d’expression Razor qui conserve la sélection de culture de l’utilisateur.

Exemple de ressources localisées

L’exemple de ressources localisées dans cette section fonctionne avec les exemples précédents de cet article, où les cultures prises en charge de l’application sont l’anglais (en) comme paramètre régional par défaut et l’espagnol (es) comme paramètre régional alternatif sélectionnable par l’utilisateur ou spécifié par le navigateur.

Créez un fichier de ressources pour chacun des paramètres régionaux. Dans l’exemple suivant, des ressources sont créées pour une chaîne Greeting en anglais et en espagnol :

  • Anglais (en) : Hello, World!
  • Espagnol (es) : ¡Hola, Mundo!

Note

Vous pouvez ajouter le fichier de ressources suivant dans Visual Studio en cliquant avec le bouton droit sur le dossier Pages et en sélectionnant Ajouter>Nouvel élément>Fichier de ressources. Nommez le fichier CultureExample2.resx. Lorsque l’éditeur s’affiche, fournissez des données pour une nouvelle entrée. Définissez le Nom sur Greeting et la Valeur sur Hello, World!. Enregistrez le fichier.

Si vous utilisez Visual Studio Code, nous vous recommandons d’installer l’outil ResX Viewer and Editor de Tim Heuer. Ajoutez un fichier CultureExample2.resx vide au dossier Pages. L’extension prend automatiquement en charge la gestion du fichier dans l’interface utilisateur. Sélectionnez le bouton Ajouter une nouvelle ressource. Suivez les instructions pour ajouter une entrée pour Greeting (clé), Hello, World! (valeur) et None (commentaire). Enregistrez le fichier. Si vous fermez et rouvrez le fichier, vous pouvez voir la ressource Greeting.

L’outil ResX Viewer and Editor de Tim Heuer n’est ni détenu ni géré par Microsoft et n’est couvert par aucun contrat de support ou licence Microsoft.

L’exemple suivant illustre un fichier de ressources standard. Vous pouvez placer manuellement les fichiers de ressources dans le dossier Pages de l’application si vous préférez ne pas utiliser d’outils intégrés avec un environnement de développement intégré (IDE), tel que l’éditeur de fichiers de ressources intégré de Visual Studio ou Visual Studio Code avec une extension pour créer et éditer des fichiers de ressources.

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>

Note

Vous pouvez ajouter le fichier de ressources suivant dans Visual Studio en cliquant avec le bouton droit sur le dossier Pages et en sélectionnant Ajouter>Nouvel élément>Fichier de ressources. Nommez le fichier CultureExample2.es.resx. Lorsque l’éditeur s’affiche, fournissez des données pour une nouvelle entrée. Définissez le Nom sur Greeting et la Valeur sur ¡Hola, Mundo!. Enregistrez le fichier.

Si vous utilisez Visual Studio Code, nous vous recommandons d’installer l’outil ResX Viewer and Editor de Tim Heuer. Ajoutez un fichier CultureExample2.resx vide au dossier Pages. L’extension prend automatiquement en charge la gestion du fichier dans l’interface utilisateur. Sélectionnez le bouton Ajouter une nouvelle ressource. Suivez les instructions pour ajouter une entrée pour Greeting (clé), ¡Hola, Mundo! (valeur) et None (commentaire). Enregistrez le fichier. Si vous fermez et rouvrez le fichier, vous pouvez voir la ressource Greeting.

L’exemple suivant illustre un fichier de ressources standard. Vous pouvez placer manuellement les fichiers de ressources dans le dossier Pages de l’application si vous préférez ne pas utiliser d’outils intégrés avec un environnement de développement intégré (IDE), tel que l’éditeur de fichiers de ressources intégré de Visual Studio ou Visual Studio Code avec une extension pour créer et éditer des fichiers de ressources.

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>

Le composant suivant illustre l’utilisation de la chaîne localisée Greeting avec IStringLocalizer<T>. Le balisage Razor@Loc["Greeting"] de l’exemple suivant localise la chaîne clé de la valeur Greeting, qui est définie dans les fichiers de ressources précédents.

Ajoutez l’espace de noms pour Microsoft.Extensions.Localization au fichier _Imports.razor de l’application :

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

Si vous le souhaitez, ajoutez un élément de menu pour le composant CultureExample2 à la navigation pour le composant NavMenu (NavMenu.razor).

Source de référence du fournisseur de culture WebAssembly

Pour mieux comprendre comment le framework Blazor traite la localisation, consultez la classe WebAssemblyCultureProvider dans la source de référence ASP.NET Core.

Note

Les liens de documentation vers la source de référence .NET chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment sélectionner une balise de version du code source ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Ressources partagées

Pour créer des ressources partagées de localisation, adoptez l’approche suivante.

  • Vérifiez que le package Microsoft.Extensions.Localization est référencé par le projet.

    Note

    Pour obtenir des conseils sur l'ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

  • Vérifiez que le Microsoft.Extensions.Localizationnamespace est disponible pour les composants Razor du projet via une entrée dans le fichier _Imports du projet :

    @using Microsoft.Extensions.Localization
    
  • Créez une classe factice avec un nom de classe arbitraire. Dans l’exemple suivant :

    • L’application utilise l’espace de noms BlazorSample et les ressources de localisation utilisent l’espace de noms BlazorSample.Localization.
    • La classe factice est nommée SharedResource.
    • Le fichier de classe est placé dans un dossier Localization à la racine de l’application.

    Note

    N’utilisez pas un fichier de designer généré automatiquement (par exemple, SharedResources.Designer.cs). La classe fictive est destinée à agir comme la classe de ressource partagée. La présence d’un fichier de conception provoque un conflit au niveau des espaces de noms.

    Localization/SharedResource.cs :

    namespace BlazorSample.Localization;
    
    public class SharedResource
    {
    }
    
  • Créez les fichiers de ressources partagées avec une Action de génération de Embedded resource. Dans l’exemple suivant :

    • Les fichiers sont placés dans le dossier Localization avec la classe SharedResource factice (Localization/SharedResource.cs).

    • Nommez les fichiers de ressources pour qu’ils correspondent au nom de la classe factice. Les exemples de fichiers suivants incluent un fichier de localisation par défaut et un fichier pour la localisation en espagnol (es).

    • Localization/SharedResource.resx

    • Localization/SharedResource.es.resx

    Warning

    Lorsque vous suivez l’approche décrite dans cette section, vous ne pouvez pas définir simultanément LocalizationOptions.ResourcesPath et utiliser IStringLocalizerFactory.Create pour charger des ressources.

  • Pour référencer la classe factice pour un IStringLocalizer<T> injecté dans un composant Razor, placez une directive @using pour l’espace de noms de localisation ou incluez l’espace de noms de localisation dans la référence de classe factice. Dans les exemples suivants :

    • Le premier exemple indique l’espace de noms Localization pour la classe factice SharedResource avec une directive @using.
    • Le deuxième exemple indique explicitement l’espace de noms de la classe factice SharedResource.

    Dans un composant Razor, utilisez l’une des approches suivantes :

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

Pour plus d’instructions, consultez Globalisation et localisation dans ASP.NET Core.

Remplacement de l’emplacement en utilisant le volet « Capteurs » dans les outils de développement

Lorsque vous utilisez le remplacement de l’emplacement en tirant parti du volet Capteurs dans les outils de développement Google Chrome ou Microsoft Edge, la langue de secours est réinitialisée après le prérendu. Évitez de définir la langue en utilisant le volet Capteurs lors de tests. Définissez la langue en tirant parti des paramètres de langue du navigateur.

Pour plus d’informations, consultez La localisation de Blazor ne fonctionne pas avec InteractiveServer (dotnet/aspnetcore #53707).

Ressources supplémentaires