Globalisation et localisation dans ASP.NET Core

Par Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana et Hisham Bin Ateya

Un site web multilingue permet à un site web d’atteindre un public plus large. ASP.NET Core offre des services et des intergiciels (middleware) de traduction dans différentes langues et cultures.

Conditions

  • Globalisation (G11N) : Processus permettant de faire prendre en charge différentes langues et régions à une application. L’abréviation provient de la première et de la dernière lettres et du nombre de lettres qui les séparent.
  • Localisation (L10N) : processus de personnalisation d’une application globalisée pour des langues et régions spécifiques.
  • Internationalisation (I18N) : à la fois la globalisation et la localisation.
  • Culture : langue et, éventuellement, région.
  • Culture neutre : Culture dont la langue est spécifiée, mais pas la région (par exemple « en », « es »).
  • Culture spécifique : culture qui a une langue et une région spécifiées (par exemple, « en-US », « en-GB », « es-CL »).
  • Culture parente : culture neutre qui contient une culture spécifique (par exemple, « en » est la culture parente d’« en-US » et « en-GB »).
  • Paramètres régionaux : Synonyme de culture.

Codes de langue et de pays/région

Le format RFC 4646 du nom de la culture est <language code>-<country/region code>, où <language code> correspond au code de la langue et <country/region code> à celui de la sous-culture. Par exemple, es-CL pour l’espagnol (Chili), en-US pour l’anglais (États-Unis) et en-AU pour l’anglais (Australie). Le format RFC 4646 est la combinaison d’un code de culture à deux lettres minuscules de norme ISO 639 associé à une langue et d’un code de sous-culture à deux lettres majuscules de norme ISO 3166 associé à un pays ou une région. Pour plus d’informations, consultez System.Globalization.CultureInfo.

Tâches de localisation d’une application

La globalisation et la localisation d’une application impliquent les tâches suivantes :

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

Ressources supplémentaires

Par Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana et Hisham Bin Ateya

Un site web multilingue permet à un site web d’atteindre un public plus large. ASP.NET Core offre des services et des intergiciels (middleware) de traduction dans différentes langues et cultures.

Conditions

  • Globalisation (G11N) : Processus permettant de faire prendre en charge différentes langues et régions à une application. L’abréviation provient de la première et de la dernière lettres et du nombre de lettres qui les séparent.
  • Localisation (L10N) : processus de personnalisation d’une application globalisée pour des langues et régions spécifiques.
  • Internationalisation (I18N) : à la fois la globalisation et la localisation.
  • Culture : langue et, éventuellement, région.
  • Culture neutre : Culture dont la langue est spécifiée, mais pas la région (par exemple « en », « es »).
  • Culture spécifique : culture qui a une langue et une région spécifiées (par exemple, « en-US », « en-GB », « es-CL »).
  • Culture parente : culture neutre qui contient une culture spécifique (par exemple, « en » est la culture parente d’« en-US » et « en-GB »).
  • Paramètres régionaux : Synonyme de culture.

Codes de langue et de pays/région

Le format RFC 4646 du nom de la culture est <language code>-<country/region code>, où <language code> correspond au code de la langue et <country/region code> à celui de la sous-culture. Par exemple, es-CL pour l’espagnol (Chili), en-US pour l’anglais (États-Unis) et en-AU pour l’anglais (Australie). Le format RFC 4646 est la combinaison d’un code de culture à deux lettres minuscules de norme ISO 639 associé à une langue et d’un code de sous-culture à deux lettres majuscules de norme ISO 3166 associé à un pays ou une région. Pour plus d’informations, consultez System.Globalization.CultureInfo.

Tâches de localisation d’une application

La globalisation et la localisation d’une application impliquent les tâches suivantes :

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

Ressources supplémentaires

Par Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana et Hisham Bin Ateya

Un site web multilingue permet au site d’atteindre un public plus large. ASP.NET Core offre des services et des intergiciels (middleware) de traduction dans différentes langues et cultures.

L’internationalisation implique la System.Globalization et la localisation. La globalisation est le processus de conception d’applications qui prennent en charge des cultures différentes. La globalisation ajoute la prise en charge de l’entrée, de l’affichage et de la sortie d’un ensemble défini de jeux de caractères liés à des zones géographiques spécifiques.

La localisation est le processus d’adaptation d’une application globalisée, dont vous avez déjà traitée l’adaptabilité, à une culture/des paramètres régionaux spécifiques. Pour plus d’informations, consultez Terminologie de la globalisation et de la localisation à la fin du présent document.

La localisation d’une application implique les étapes suivantes :

  1. Rendre le contenu de l’application localisable
  2. Fournir des ressources localisées aux langues et cultures prises en charge
  3. Implémenter une stratégie de sélection de la langue/culture pour chaque requête

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

Rendre le contenu de l’application localisable

IStringLocalizer et IStringLocalizer<T> ont été conçus pour améliorer la productivité lors du développement d’applications localisées. IStringLocalizer utilise ResourceManager et ResourceReader pour fournir des ressources spécifiques à la culture au moment de l’exécution. L’interface possède un indexeur et un IEnumerable pour retourner des chaînes localisées. IStringLocalizer n’exige pas de stocker les chaînes de langue par défaut dans un fichier de ressources. Vous pouvez développer une application ciblée pour la localisation sans avoir besoin de créer des fichiers de ressources au tout début du développement. Le code ci-dessous montre comment inclure dans un wrapper la chaîne « About Title » à des fins de localisation.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;

namespace Localization.Controllers
{
    [Route("api/[controller]")]
    public class AboutController : Controller
    {
        private readonly IStringLocalizer<AboutController> _localizer;

        public AboutController(IStringLocalizer<AboutController> localizer)
        {
            _localizer = localizer;
        }

        [HttpGet]
        public string Get()
        {
            return _localizer["About Title"];
        }
    }
}

Dans le code précédent, l’implémentation de IStringLocalizer<T> vient de l’injection de dépendances. Si la valeur localisée de « About Title » est introuvable, alors la clé de l’indexeur est retournée, autrement dit, la chaîne « About Title ». Vous pouvez laisser les chaînes littérales de la langue par défaut dans l’application et les inclure dans un wrapper dans le localisateur, afin de pouvoir vous concentrer sur le développement de l’application. Vous développez votre application avec votre langue par défaut et vous la préparez à l’étape de localisation sans créer au préalable un fichier de ressources par défaut. Vous pouvez également utiliser l’approche traditionnelle et fournir une clé pour récupérer la chaîne de la langue par défaut. Pour de nombreux développeurs, le nouveau workflow qui n’inclut pas de fichier .resx de langue par défaut et qui consiste à simplement inclure dans un wrapper les littéraux de chaîne permet de réduire la surcharge de la localisation d’une application. D’autres développeurs préfèrent le workflow traditionnel, car il facilite l’utilisation de longs littéraux de chaîne ainsi que la mise à jour des chaînes localisées.

Utilisez l’implémentation de IHtmlLocalizer<T> pour les ressources qui contiennent du HTML. IHtmlLocalizer encode en HTML les arguments formatés dans la chaîne de ressource, mais pas la chaîne de ressource elle-même. Dans l’exemple mis en surbrillance ci-dessous, seule la valeur du paramètre name est encodé en HTML.

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;

namespace Localization.Controllers
{
    public class BookController : Controller
    {
        private readonly IHtmlLocalizer<BookController> _localizer;

        public BookController(IHtmlLocalizer<BookController> localizer)
        {
            _localizer = localizer;
        }

        public IActionResult Hello(string name)
        {
            ViewData["Message"] = _localizer["<b>Hello</b><i> {0}</i>", name];

            return View();
        }

Remarque

En règle générale, localisez uniquement le texte et non le code HTML.

Au niveau le plus bas, vous pouvez sortir IStringLocalizerFactory de l’injection de dépendances :

{
    public class TestController : Controller
    {
        private readonly IStringLocalizer _localizer;
        private readonly IStringLocalizer _localizer2;

        public TestController(IStringLocalizerFactory factory)
        {
            var type = typeof(SharedResource);
            var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
            _localizer = factory.Create(type);
            _localizer2 = factory.Create("SharedResource", assemblyName.Name);
        }       

        public IActionResult About()
        {
            ViewData["Message"] = _localizer["Your application description page."] 
                + " loc 2: " + _localizer2["Your application description page."];

Le code ci-dessus illustre chacune des deux méthodes de création.

Vous pouvez partitionner vos chaînes localisées par contrôleur, par zone ou avoir un seul conteneur. Dans l’exemple d’application, une classe fictive nommée SharedResource est utilisée pour les ressources partagées.

// Dummy class to group shared resources

namespace Localization
{
    public class SharedResource
    {
    }
}

Certains développeurs utilisent la classe Startup pour contenir des chaînes globales ou partagées. Dans l’exemple ci-dessous, les localiseurs InfoController et SharedResource sont utilisés :

public class InfoController : Controller
{
    private readonly IStringLocalizer<InfoController> _localizer;
    private readonly IStringLocalizer<SharedResource> _sharedLocalizer;

    public InfoController(IStringLocalizer<InfoController> localizer,
                   IStringLocalizer<SharedResource> sharedLocalizer)
    {
        _localizer = localizer;
        _sharedLocalizer = sharedLocalizer;
    }

    public string TestLoc()
    {
        string msg = "Shared resx: " + _sharedLocalizer["Hello!"] +
                     " Info resx " + _localizer["Hello!"];
        return msg;
    }

Localisation de l’affichage

Le service IViewLocalizer fournit des chaînes localisées à une vue. La classe ViewLocalizer implémente cette interface et recherche l’emplacement de la ressource à partir du chemin du fichier de la vue. Le code suivant montre comment utiliser l’implémentation par défaut de IViewLocalizer :

@using Microsoft.AspNetCore.Mvc.Localization

@inject IViewLocalizer Localizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>@Localizer["Use this area to provide additional information."]</p>

L’implémentation par défaut de IViewLocalizer recherche le fichier de ressources en fonction du nom de fichier de l’affichage. Il n’existe aucune option pour utiliser un fichier de ressources partagées globales. ViewLocalizer implémente le localiseur en utilisant IHtmlLocalizer, si bien que Razor n’encode pas en HTML la chaîne localisée. Vous pouvez paramétrer des chaînes de ressources pour que IViewLocalizer encode en HTML les paramètres, mais pas les chaînes de ressources. Examinons le balisage Razor suivant :

@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]

Un fichier de ressources en français peut contenir ce qui suit :

Clé Valeur
<i>Hello</i> <b>{0}!</b> <i>Bonjour</i> <b>{0} !</b>

L’affichage contient le balisage HTML provenant du fichier de ressources.

Remarque

En règle générale, localisez uniquement le texte et non le code HTML.

Pour utiliser un fichier de ressources partagées dans un affichage, injectez IHtmlLocalizer<T> :

@using Microsoft.AspNetCore.Mvc.Localization
@using Localization.Services

@inject IViewLocalizer Localizer
@inject IHtmlLocalizer<SharedResource> SharedLocalizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>

<h1>@SharedLocalizer["Hello!"]</h1>

Localisation de DataAnnotations

Les messages d’erreur DataAnnotations sont localisés avec IStringLocalizer<T>. En utilisant l’option ResourcesPath = "Resources", les messages d’erreur inclus dans RegisterViewModel peuvent être stockés dans les chemins suivants :

  • Resources/ViewModels.Account.RegisterViewModel.fr.resx
  • Resources/ViewModels/Account/RegisterViewModel.fr.resx
public class RegisterViewModel
{
    [Required(ErrorMessage = "The Email field is required.")]
    [EmailAddress(ErrorMessage = "The Email field is not a valid email address.")]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required(ErrorMessage = "The Password field is required.")]
    [StringLength(8, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

Les attributs hors validation sont localisés.

Utilisation d’une seule chaîne de ressource pour plusieurs classes

Le code suivant montre comment utiliser une seule chaîne de ressource pour les attributs de validation avec plusieurs classes :

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddDataAnnotationsLocalization(options => {
            options.DataAnnotationLocalizerProvider = (type, factory) =>
                factory.Create(typeof(SharedResource));
        });
}

Dans le code précédent, SharedResource est la classe correspondant au resx où sont stockés vos messages de validation. Cette approche permet à DataAnnotations d’utiliser uniquement SharedResource, au lieu de la ressource de chaque classe.

Fournir des ressources localisées aux langues et cultures prises en charge

SupportedCultures et SupportedUICultures

ASP.NET Core vous permet de spécifier deux valeurs de culture, SupportedCultures et SupportedUICultures. L’objet CultureInfo pour SupportedCultures détermine les résultats des fonctions qui dépendent de la culture, par exemple la mise en forme des dates, des heures, des nombres et des devises. SupportedCultures détermine également l’ordre de tri du texte, les conventions de casse et les comparaisons de chaînes. Pour plus d’informations sur la façon dont le serveur obtient la culture, consultez CultureInfo.CurrentCulture et CultureInfo.CurrentUICulture. SupportedUICultures détermine quelles chaînes traduites (à partir de fichiers .resx) sont recherchées par ResourceManager. ResourceManager recherche les chaînes propres à la culture déterminées par CurrentUICulture. Chaque thread dans .NET a des objets CurrentCulture et CurrentUICulture. Le framework inspecte ces valeurs lors du rendu des fonctions qui dépendent de la culture. Si la culture du thread actuel est définie sur en-US (Anglais, États-Unis), DateTime.Now.ToLongDateString() affiche Thursday, February 18, 2016 ; mais si CurrentCulture est défini sur es-ES (Espagnol, Espagne), la sortie est jueves, 18 de febrero de 2016.

Fichiers de ressources

Un fichier de ressources est un mécanisme utile pour séparer les chaînes localisables du code. Les chaînes traduites spécifiques aux autres langues que la langue par défaut sont isolées dans des fichiers de ressources .resx. Par exemple, vous pouvez avoir besoin de créer un fichier de ressources nommé Welcome.es.resx qui contient des chaînes traduites. « es » correspond au code de langue pour l’espagnol. Pour créer ce fichier de ressources dans Visual Studio :

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier qui contient le fichier de ressources >Ajouter>Nouvel élément.

    Nested contextual menu: In Solution Explorer, a contextual menu is open for Resources. A second contextual menu is open for Add showing the New Item command highlighted.

  2. Dans la zone Rechercher dans les modèles installés, entrez « ressource » et nommez le fichier.

    Add New Item dialog

  3. Entrez la valeur de la clé (chaîne native) dans la colonne Nom et la chaîne traduite dans la colonne Valeur.

    Welcome.es.resx file (the Welcome resource file for Spanish) with the word Hello in the Name column and the word Hola (Hello in Spanish) in the Value column

    Visual Studio présente le fichier Welcome.es.resx.

    Solution Explorer showing the Welcome Spanish (es) resource file

Nommage du fichier de ressources

Les ressources sont nommées selon le nom de type complet de leur classe moins le nom de l’assembly. Par exemple, une ressource en français dans un projet dont l’assembly principal est LocalizationWebsite.Web.dll pour la classe LocalizationWebsite.Web.Startup serait nommée Startup.fr.resx. Une ressource pour la classe LocalizationWebsite.Web.Controllers.HomeController doit être nommée Controllers.HomeController.fr.resx. Si l’espace de noms de votre classe ciblée n’est pas identique au nom de l’assembly, vous aurez besoin du nom de type complet. Par exemple, dans l’exemple de projet, une ressource pour le type ExtraNamespace.Tools serait nommée ExtraNamespace.Tools.fr.resx.

Dans l’exemple de projet, la méthode ConfigureServices affecte la valeur « Resources » à ResourcesPath. Ainsi, le chemin relatif du projet pour le fichier de ressources en français du contrôleur Home est Resources/Controllers.HomeController.fr.resx. Vous pouvez également utiliser des dossiers pour organiser les fichiers de ressources. Pour le contrôleur Home, le chemin doit être Resources/Controllers/HomeController.fr.resx. Si vous n’utilisez pas l’option ResourcesPath, le fichier .resx se trouve dans le répertoire de base du projet. Le fichier de ressources pour HomeController doit être nommé Controllers.HomeController.fr.resx. Le choix de l’utilisation de la convention d’affectation de noms avec des points ou un chemin dépend de la façon dont vous souhaitez organiser vos fichiers de ressources.

Nom de la ressource Affectation de noms avec des points ou un chemin
Resources/Controllers.HomeController.fr.resx Points
Resources/Controllers/HomeController.fr.resx Chemin d’accès

Les fichiers de ressources qui utilisent @inject IViewLocalizer dans les vues Razor suivent un modèle similaire. Le fichier de ressources d’une vue peut être nommé selon la convention avec des points ou un chemin. Les fichiers de ressources d’une vue Razor imitent le chemin de son fichier de vue associé. Si nous affectons à ResourcesPath la valeur « Resources », le fichier de ressources en français associé à la vue Views/Home/About.cshtml peut porter l’un des noms suivants :

  • Resources/Views/Home/About.fr.resx

  • Resources/Views.Home.About.fr.resx

Si vous n’utilisez pas l’option ResourcesPath, le fichier .resx d’un affichage se trouve dans le même dossier que l’affichage.

RootNamespaceAttribute

L’attribut RootNamespaceAttribute fournit l’espace de noms racine d’un assembly quand il est différent du nom de l’assembly.

Avertissement

Cela peut se produire quand le nom d’un projet n’est pas un identificateur .NET valide. Par exemple, my-project-name.csproj utilise l’espace de noms racine my_project_name et le nom d’assembly my-project-name, ce qui entraîne cette erreur.

Si l’espace de noms racine d’un assembly est différent du nom de l’assembly :

  • La localisation ne fonctionne pas par défaut.
  • La localisation échoue en raison du mode de recherche des ressources dans l’assembly. RootNamespace est une valeur de build qui n’est pas accessible au processus exécutant.

Si RootNamespace est différent de AssemblyName, incluez ce qui suit dans AssemblyInfo.cs (en remplaçant les valeurs de paramètre par les valeurs réelles) :

using System.Reflection;
using Microsoft.Extensions.Localization;

[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]

Le code précédent permet de résoudre correctement les fichiers resx.

Comportement de secours pour la culture

Lors de la recherche d’une ressource, la localisation met en œuvre une « alternative de secours pour la culture ». Elle commence par la culture demandée : si elle est introuvable, il revient à la culture parente de cette culture. Notez que la propriété CultureInfo.Parent représente la culture parente. Cela signifie généralement (mais pas toujours) supprimer l’indicateur national du code ISO. Par exemple, le dialecte de l’espagnol parlé au Mexique est « es-MX ». Le parent est « es » (espagnol), qui n’est spécifique à aucun pays.

Imaginez que votre site reçoive une demande pour une ressource « Bienvenue » avec la culture « fr-CA ». Le système de localisation recherche les ressources suivantes, dans l’ordre, et sélectionne la première correspondance :

  • Welcome.fr-CA.resx
  • Welcome.fr.resx
  • Welcome.resx (si NeutralResourcesLanguage est « fr-CA »)

Par exemple, si vous supprimez l’indicateur de culture « .fr » alors que la culture définie est le français, le fichier de ressources par défaut est lu et les chaînes sont localisées. Le gestionnaire de ressources désigne une ressource par défaut ou de secours pour les cas où rien ne correspond à la culture demandée. Si vous voulez simplement retourner la clé quand une ressource est manquante pour la culture demandée, vous ne devez pas avoir de fichier de ressources par défaut.

Générer des fichiers de ressources avec Visual Studio

Si vous créez un fichier de ressources dans Visual Studio sans culture dans le nom de fichier (par exemple, Welcome.resx), Visual Studio crée une classe C# avec une propriété pour chaque chaîne. Ce n’est généralement pas ce que vous souhaitez avec ASP.NET Core. Vous n’avez habituellement pas de fichier de ressources .resx par défaut (un fichier .resx sans nom de culture). Nous vous suggérons donc de créer le fichier .resx avec un nom de culture (par exemple, Welcome.fr.resx). Lorsque vous créez un fichier .resx avec un nom de culture, Visual Studio ne génère pas le fichier de classe.

Ajouter d’autres cultures

Chaque combinaison de langue et de culture (autres que la langue par défaut) nécessite un fichier de ressources unique. Vous créez des fichiers de ressources pour différentes cultures et différents paramètres régionaux en créant des fichiers de ressources dans lesquels les codes de langue ISO font partie du nom de fichier (par exemple, en-us, fr-ca et en gb). Ces codes ISO sont placés entre le nom de fichier et l’extension de fichier .resx, comme dans Welcome.es-MX.resx (Espagnol/Mexique).

Implémenter une stratégie de sélection de la langue/culture pour chaque requête

Configurer la localisation

La localisation est configurée dans la méthode Startup.ConfigureServices :

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
  • AddLocalization ajoute les services de localisation au conteneur de services. Le code ci-dessus affecte également au chemin des ressources la valeur « Resources ».

  • AddViewLocalization ajoute la prise en charge des fichiers de vues localisées. Dans cet exemple de vue, la localisation se base sur le suffixe du fichier de la vue. Par exemple, « fr » dans le fichier Index.fr.cshtml.

  • AddDataAnnotationsLocalization ajoute la prise en charge des messages de validation DataAnnotations localisés par le biais d’abstractions IStringLocalizer.

Intergiciel (middleware) de localisation

La culture actuelle sur une requête est définie dans l’intergiciel (middleware) de localisation. L’intergiciel de localisation est activé dans la méthode Startup.Configure. L’intergiciel de localisation doit être configuré avant tout intergiciel susceptible de vérifier la culture de la requête (par exemple, app.UseMvcWithDefaultRoute()). L’intergiciel de localisation doit apparaître après l’intergiciel de routage si vous utilisez RouteDataRequestCultureProvider. Pour plus d’informations sur la commande d’intergiciels, consultez Intergiciels ASP.NET Core.

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

app.UseRequestLocalization(localizationOptions);

Si vous souhaitez voir les commentaires de code traduits dans une langue autre que l’anglais, dites-le nous dans cette discussion GitHub.

UseRequestLocalization initialise un objet RequestLocalizationOptions. Sur chaque requête, la liste de RequestCultureProvider dans RequestLocalizationOptions est énumérée et le premier fournisseur capable de déterminer correctement la culture de la requête est utilisé. Les fournisseurs par défaut proviennent de la classe RequestLocalizationOptions :

  1. QueryStringRequestCultureProvider
  2. CookieRequestCultureProvider
  3. AcceptLanguageHeaderRequestCultureProvider

La liste par défaut va du plus spécifique au moins spécifique. Plus loin dans l’article, nous verrons comment vous pouvez modifier l’ordre et même ajouter un fournisseur de culture personnalisé. Si aucun des fournisseurs ne peut déterminer la culture de la requête, DefaultRequestCulture est utilisé.

QueryStringRequestCultureProvider

Certaines applications utilisent une chaîne de requête pour définir la CultureInfo. Pour les applications qui utilisent l’approche du cookie ou de l’en-tête Accept-Language, l’ajout d’une chaîne de requête à l’URL s’avère utile pour déboguer et tester le code. Par défaut, QueryStringRequestCultureProvider est inscrit en tant que premier fournisseur de localisation dans la liste RequestCultureProvider. Vous passez les paramètres de chaîne de requête culture et ui-culture. L’exemple suivant affecte à la culture spécifique (langue et région) la valeur espagnol/Mexique :

http://localhost:5000/?culture=es-MX&ui-culture=es-MX

Si vous passez uniquement l’une des deux (culture ou ui-culture), le fournisseur de chaîne de requête définit les deux valeurs à l’aide de celle que vous avez passée. Par exemple, la seule définition de la culture définit à la fois Culture et UICulture :

http://localhost:5000/?culture=es-MX

CookieRequestCultureProvider

Les applications de production fournissent souvent un mécanisme permettant de définir la culture à l’aide du cookie de culture ASP.NET Core. Utilisez la méthode MakeCookieValue pour créer un cookie.

CookieRequestCultureProviderDefaultCookieName retourne le nom de cookie par défaut utilisé pour effectuer le suivi des informations de culture préférée de l’utilisateur. Le nom cookie par défaut est .AspNetCore.Culture.

Le format du cookie est c=%LANGCODE%|uic=%LANGCODE%, où c correspond à Culture et uic correspond à UICulture, par exemple :

c=en-UK|uic=en-US

Si vous spécifiez uniquement les informations de culture ou la culture d’interface utilisateur, la culture spécifiée est utilisée à la fois pour les informations de culture et la culture d’interface utilisateur.

En-tête HTTP Accept-Language

L’en-tête Accept-Language peut être défini dans la plupart des navigateurs et a d’abord été conçu pour spécifier la langue de l’utilisateur. Ce paramètre indique ce que le navigateur doit envoyer ou ce dont il a hérité du système d’exploitation sous-jacent. L’en-tête HTTP Accept-Language d’une requête de navigateur n’est pas un moyen infaillible de détecter la langue préférée de l’utilisateur (consultez Définition des préférences de langue dans un navigateur). Une application de production doit inclure un moyen permettant à l’utilisateur de personnaliser son choix de culture.

Définir l’en-tête HTTP Accept-Language dans IE

  1. À partir de l’icône d’engrenage, appuyez sur Options Internet.

  2. Appuyez sur Langues.

    Internet Options

  3. Appuyez sur Définir les langues.

  4. Appuyez sur Ajouter une langue.

  5. Ajoutez la langue.

  6. Tapez sur la langue, puis sur Monter.

Utiliser un fournisseur personnalisé

Supposons que vous vouliez permettre à vos clients de stocker leur langue et leur culture dans vos bases de données. Vous pouvez écrire un fournisseur pour rechercher ces valeurs pour l’utilisateur. Le code suivant illustre l’ajout d’un fournisseur personnalisé :

private const string enUSCulture = "en-US";

services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo(enUSCulture),
        new CultureInfo("fr")
    };

    options.DefaultRequestCulture = new RequestCulture(culture: enUSCulture, uiCulture: enUSCulture);
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context =>
    {
        // My custom request culture logic
        return await Task.FromResult(new ProviderCultureResult("en"));
    }));
});

Utilisez RequestLocalizationOptions pour ajouter ou supprimer des fournisseurs de localisation.

Modifier l’ordre des fournisseurs de culture de requête

RequestLocalizationOptions a trois fournisseurs de culture de requête par défaut : QueryStringRequestCultureProvider, CookieRequestCultureProvider et AcceptLanguageHeaderRequestCultureProvider. Utilisez la propriété [RequestLocalizationOptions.RequestCultureProviders]](xref:Microsoft.AspNetCore.Builder.RequestLocalizationOptions.RequestCultureProviders) pour modifier l’ordre de ces fournisseurs, comme indiqué ci-dessous :

    app.UseRequestLocalization(options =>
    {
        var questStringCultureProvider = options.RequestCultureProviders[0];    
        options.RequestCultureProviders.RemoveAt(0);
        options.RequestCultureProviders.Insert(1, questStringCultureProvider);
    });

Dans l’exemple précédent, l’ordre de QueryStringRequestCultureProvider et CookieRequestCultureProvider étant commuté, RequestLocalizationMiddleware recherche d’abord les cultures dans les cookies, puis dans la chaîne de requête.

Comme mentionné précédemment, ajoutez un fournisseur personnalisé via AddInitialRequestCultureProvider, qui définit l’ordre de 0, de sorte que ce fournisseur est prioritaire sur les autres.

Définir la culture par programmation

Cet exemple de projet Localization.StarterWeb sur GitHub contient l’interface utilisateur permettant de définir Culture. Le fichier Views/Shared/_SelectLanguagePartial.cshtml vous permet de sélectionner la culture dans la liste des cultures prises en charge :

@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
    var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}

<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
    <form id="selectLanguage" asp-controller="Home" 
          asp-action="SetLanguage" asp-route-returnUrl="@returnUrl" 
          method="post" class="form-horizontal" role="form">
        <label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label> <select name="culture"
          onchange="this.form.submit();"
          asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
        </select>
    </form>
</div>

Le fichier Views/Shared/_SelectLanguagePartial.cshtml est ajouté à la section footer du fichier de disposition afin d’être disponible pour toutes les vues :

<div class="container body-content" style="margin-top:60px">
    @RenderBody()
    <hr>
    <footer>
        <div class="row">
            <div class="col-md-6">
                <p>&copy; @System.DateTime.Now.Year - Localization</p>
            </div>
            <div class="col-md-6 text-right">
                @await Html.PartialAsync("_SelectLanguagePartial")
            </div>
        </div>
    </footer>
</div>

La méthode SetLanguage définit le cookie de la culture.

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    return LocalRedirect(returnUrl);
}

Vous ne pouvez pas connecter _SelectLanguagePartial.cshtml pour obtenir un exemple de code pour ce projet. Le projet Localization.StarterWeb sur GitHub comporte du code pour faire passer RequestLocalizationOptions à une ligne de code partiellement exécutée Razor par le biais du conteneur Injection de dépendances.

Données de routage et chaînes de requête de liaison de modèle

Consultez Comportement de globalisation des données de routage et des chaînes de requête de liaison de modèle.

Terminologie de la globalisation et de la localisation

Le processus de localisation de votre application exige également une compréhension élémentaire des jeux de caractères appropriés couramment utilisés dans le développement de logiciels moderne ainsi qu’une compréhension des problèmes qui y sont associés. Bien que tous les ordinateurs stockent le texte sous forme de nombres (codes), les différents systèmes stockent ce même texte en utilisant des nombres différents. Le processus de localisation consiste à traduire l’interface utilisateur de l’application pour une culture/des paramètres régionaux spécifiques.

L’adaptabilité est un processus intermédiaire permettant de vérifier qu’une application globalisée est prête à être localisée.

Le format RFC 4646 du nom de la culture est <languagecode2>-<country/regioncode2>, où <languagecode2> correspond au code de la langue et <country/regioncode2> au code de la sous-culture. Par exemple, es-CL pour l’espagnol (Chili), en-US pour l’anglais (États-Unis) et en-AU pour l’anglais (Australie). Le format RFC 4646 est la combinaison d’un code de culture à deux lettres minuscules de norme ISO 639 associé à une langue et d’un code de sous-culture à deux lettres majuscules de norme ISO 3166 associé à un pays ou une région. Pour plus d’informations, consultez System.Globalization.CultureInfo.

L’internationalisation est souvent abrégée par « I18N ». Cette abréviation prend les première et dernière lettres du mot ainsi que le nombre de lettres entre elles, 18 représentant ainsi le nombre de lettres le « I » initial et le « N » final. Il en va de même pour la globalisation (G11N) et la localisation (L10N).

Termes :

  • Globalisation (G11N) : Processus permettant de faire prendre en charge différentes langues et régions à une application.
  • Localisation (L10N) : Processus permettant de personnaliser une application pour une langue et une région données.
  • Internationalisation (I18N) : Décrit à la fois la globalisation et la localisation.
  • Culture : Correspond à une langue et éventuellement à une région.
  • Culture neutre : Culture dont la langue est spécifiée, mais pas la région. (Exemples : « en », « es ».)
  • Culture spécifique : Culture dont la langue et la région sont spécifiées. (Exemples : « en-US », « en-GB », « es-CL ».)
  • Culture parent : Culture neutre qui contient une culture spécifique. (Exemple : « en » est la culture parent de « en-US » et « en-GB ».)
  • Paramètres régionaux : Synonyme de culture.

Remarque

Vous ne pourrez peut-être pas entrer de virgules décimales dans les champs décimaux. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que l’anglais qui utilisent une virgule (« , ») comme décimale et des formats de date autres que l’anglais des États-Unis, vous devez effectuer des étapes pour localiser votre application. Consultez ce commentaire GitHub 4076 pour savoir comment ajouter une virgule décimale.

Remarque

Pour les applications web antérieures à ASP.NET Core 3.0, écrivez un journal de type LogLevel.Warning par requête si la culture demandée n’est pas prise en charge. La journalisation d’un LogLevel.Warning par requête peut produire des fichiers journaux volumineux avec des informations redondantes. Ce comportement a été modifié dans ASP.NET 3.0. Le RequestLocalizationMiddleware écrit un journal de type LogLevel.Debug, ce qui réduit la taille des journaux de production.

Ressources supplémentaires