Globalisation et localisation dans ASP.NET CoreGlobalization and localization in ASP.NET Core

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

Créer un site web multilingue avec ASP.NET Core permet d’atteindre un plus large public.Creating a multilingual website with ASP.NET Core will allow your site to reach a wider audience. ASP.NET Core offre des services et des intergiciels (middleware) de traduction dans différentes langues et cultures.ASP.NET Core provides services and middleware for localizing into different languages and cultures.

L’internationalisation implique la globalisation et la localisation.Internationalization involves Globalization and Localization. La globalisation est le processus de conception d’applications qui prennent en charge des cultures différentes.Globalization is the process of designing apps that support different cultures. 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.Globalization adds support for input, display, and output of a defined set of language scripts that relate to specific geographic areas.

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.Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. Pour plus d’informations, consultez Terminologie de la globalisation et de la localisation à la fin du présent document.For more information see Globalization and localization terms near the end of this document.

La localisation d’une application implique les étapes suivantes :App localization involves the following:

  1. Rendre le contenu de l’application localisableMake the app's content localizable

  2. Fournir des ressources localisées aux langues et cultures prises en chargeProvide localized resources for the languages and cultures you support

  3. Implémenter une stratégie de sélection de la langue/culture pour chaque requêteImplement a strategy to select the language/culture for each request

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)View or download sample code (how to download)

Rendre le contenu de l’application localisableMake the app's content localizable

Introduits dans ASP.NET Core, IStringLocalizer et IStringLocalizer<T> ont été conçus pour améliorer la productivité lors du développement d’applications localisées.Introduced in ASP.NET Core, IStringLocalizer and IStringLocalizer<T> were architected to improve productivity when developing localized apps. IStringLocalizer utilise ResourceManager et ResourceReader pour fournir les ressources propres à la culture au moment de l’exécution.IStringLocalizer uses the ResourceManager and ResourceReader to provide culture-specific resources at run time. L’interface simple possède un indexeur et un IEnumerable pour retourner des chaînes localisées.The simple interface has an indexer and an IEnumerable for returning localized strings. IStringLocalizer n’exige pas de stocker les chaînes de langue par défaut dans un fichier de ressources.IStringLocalizer doesn't require you to store the default language strings in a resource file. 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.You can develop an app targeted for localization and not need to create resource files early in development. Le code ci-dessous montre comment inclure dans un wrapper la chaîne « About Title » à des fins de localisation.The code below shows how to wrap the string "About Title" for localization.

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 ci-dessus, l’implémentation de IStringLocalizer<T> vient de l’injection de dépendances.In the code above, the IStringLocalizer<T> implementation comes from Dependency Injection. 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 ».If the localized value of "About Title" isn't found, then the indexer key is returned, that is, the string "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.You can leave the default language literal strings in the app and wrap them in the localizer, so that you can focus on developing the app. 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.You develop your app with your default language and prepare it for the localization step without first creating a default resource file. Vous pouvez également utiliser l’approche traditionnelle et fournir une clé pour récupérer la chaîne de la langue par défaut.Alternatively, you can use the traditional approach and provide a key to retrieve the default language string. 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.For many developers the new workflow of not having a default language .resx file and simply wrapping the string literals can reduce the overhead of localizing an app. 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.Other developers will prefer the traditional work flow as it can make it easier to work with longer string literals and make it easier to update localized strings.

Utilisez l’implémentation de IHtmlLocalizer<T> pour les ressources qui contiennent du HTML.Use the IHtmlLocalizer<T> implementation for resources that contain 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.IHtmlLocalizer HTML encodes arguments that are formatted in the resource string, but doesn't HTML encode the resource string itself. Dans l’exemple mis en surbrillance ci-dessous, seule la valeur du paramètre name est encodé en HTML.In the sample highlighted below, only the value of name parameter is HTML encoded.

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 général, seul le texte (et non le code HTML) doit être localisé.Note: You generally want to only localize text and not HTML.

Au niveau le plus bas, vous pouvez sortir IStringLocalizerFactory de l’injection de dépendances :At the lowest level, you can get IStringLocalizerFactory out of Dependency Injection:

{
    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.The code above demonstrates each of the two factory create methods.

Vous pouvez partitionner vos chaînes localisées par contrôleur, par zone ou avoir un seul conteneur.You can partition your localized strings by controller, area, or have just one container. Dans l’exemple d’application, une classe fictive nommée SharedResource est utilisée pour les ressources partagées.In the sample app, a dummy class named SharedResource is used for shared resources.

// 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.Some developers use the Startup class to contain global or shared strings. Dans l’exemple ci-dessous, les localiseurs InfoController et SharedResource sont utilisés :In the sample below, the InfoController and the SharedResource localizers are used:

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’affichageView localization

Le service IViewLocalizer fournit des chaînes localisées à une vue.The IViewLocalizer service provides localized strings for a view. La classe ViewLocalizer implémente cette interface et recherche l’emplacement de la ressource à partir du chemin du fichier de la vue.The ViewLocalizer class implements this interface and finds the resource location from the view file path. Le code suivant montre comment utiliser l’implémentation par défaut de IViewLocalizer :The following code shows how to use the default implementation of 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.The default implementation of IViewLocalizer finds the resource file based on the view's file name. Il n’existe aucune option pour utiliser un fichier de ressources partagées globales.There's no option to use a global shared resource file. ViewLocalizer implémente le localiseur en utilisant IHtmlLocalizer, si bien que Razor n’encode pas en HTML la chaîne localisée.ViewLocalizer implements the localizer using IHtmlLocalizer, so Razor doesn't HTML encode the localized string. 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.You can parameterize resource strings and IViewLocalizer will HTML encode the parameters, but not the resource string. Examinez le balisage Razor suivant :Consider the following Razor markup:

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

Un fichier de ressources en français peut contenir ce qui suit :A French resource file could contain the following:

ToucheKey ValueValue
<i>Hello</i> <b>{0}!</b> <i>Bonjour</i> <b>{0} !</b>

La vue contient le balisage HTML provenant du fichier de ressources.The rendered view would contain the HTML markup from the resource file.

Remarque : en général, seul le texte (et non le code HTML) doit être localisé.Note: You generally want to only localize text and not HTML.

Pour utiliser un fichier de ressources partagées dans une vue, injectez IHtmlLocalizer<T> :To use a shared resource file in a view, inject 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 DataAnnotationsDataAnnotations localization

Les messages d’erreur DataAnnotations sont localisés avec IStringLocalizer<T>.DataAnnotations error messages are localized with IStringLocalizer<T>. En utilisant l’option ResourcesPath = "Resources", les messages d’erreur inclus dans RegisterViewModel peuvent être stockés dans les chemins suivants :Using the option ResourcesPath = "Resources", the error messages in RegisterViewModel can be stored in either of the following paths:

  • Resources/ViewModels.Account.RegisterViewModel.fr.resxResources/ViewModels.Account.RegisterViewModel.fr.resx
  • Resources/ViewModels/Account/RegisterViewModel.fr.resxResources/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; }
}

Dans ASP.NET Core MVC 1.1.0 et version supérieure, les attributs de non-validation sont localisés.In ASP.NET Core MVC 1.1.0 and higher, non-validation attributes are localized. ASP.NET Core MVC 1.0 ne recherche pas de chaînes localisées pour des attributs de non-validation.ASP.NET Core MVC 1.0 does not look up localized strings for non-validation attributes.

Utilisation d’une seule chaîne de ressource pour plusieurs classesUsing one resource string for multiple classes

Le code suivant montre comment utiliser une seule chaîne de ressource pour les attributs de validation avec plusieurs classes :The following code shows how to use one resource string for validation attributes with multiple 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.In the preceding code, SharedResource is the class corresponding to the resx where your validation messages are stored. Cette approche permet à DataAnnotations d’utiliser uniquement SharedResource, au lieu de la ressource de chaque classe.With this approach, DataAnnotations will only use SharedResource, rather than the resource for each class.

Fournir des ressources localisées aux langues et cultures prises en chargeProvide localized resources for the languages and cultures you support

SupportedCultures et SupportedUICulturesSupportedCultures and SupportedUICultures

ASP.NET Core vous permet de spécifier deux valeurs de culture, SupportedCultures et SupportedUICultures.ASP.NET Core allows you to specify two culture values, SupportedCultures and SupportedUICultures. L’objet CultureInfo de SupportedCultures détermine les résultats des fonctions qui dépendent de la culture, comme la mise en forme des dates, de l’heure, des nombres et des devises.The CultureInfo object for SupportedCultures determines the results of culture-dependent functions, such as date, time, number, and currency formatting. SupportedCultures détermine également l’ordre de tri du texte, les conventions de casse et les comparaisons de chaînes.SupportedCultures also determines the sorting order of text, casing conventions, and string comparisons. Consultez CultureInfo.CurrentCulture pour plus d’informations sur la façon dont le serveur obtient la culture.See CultureInfo.CurrentCulture for more info on how the server gets the Culture. SupportedUICultures détermine les chaînes traduites (à partir de fichiers .resx) qui sont recherchées par ResourceManager.The SupportedUICultures determines which translates strings (from .resx files) are looked up by the ResourceManager. ResourceManager recherche simplement les chaînes propres à la culture déterminée par CurrentUICulture.The ResourceManager simply looks up culture-specific strings that's determined by CurrentUICulture. Chaque thread dans .NET a des objets CurrentCulture et CurrentUICulture.Every thread in .NET has CurrentCulture and CurrentUICulture objects. ASP.NET Core inspecte ces valeurs lors du rendu des fonctions qui dépendent de la culture.ASP.NET Core inspects these values when rendering culture-dependent functions. Par exemple, si la culture du thread actuel a la valeur « en-US » (anglais, États-Unis), DateTime.Now.ToLongDateString() affiche « Thursday, February 18, 2016 », mais si CurrentCulture a la valeur « es-ES » (espagnol, Espagne), la sortie est « jueves, 18 de febrero de 2016 ».For example, if the current thread's culture is set to "en-US" (English, United States), DateTime.Now.ToLongDateString() displays "Thursday, February 18, 2016", but if CurrentCulture is set to "es-ES" (Spanish, Spain) the output will be "jueves, 18 de febrero de 2016".

Fichiers de ressourcesResource files

Un fichier de ressources est un mécanisme utile pour séparer les chaînes localisables du code.A resource file is a useful mechanism for separating localizable strings from code. Les chaînes traduites pour la langue autre que celle par défaut sont des fichiers de ressources .resx isolés.Translated strings for the non-default language are isolated .resx resource files. Par exemple, vous pouvez avoir besoin de créer un fichier de ressources nommé Welcome.es.resx qui contient des chaînes traduites.For example, you might want to create Spanish resource file named Welcome.es.resx containing translated strings. « es » correspond au code de langue pour l’espagnol."es" is the language code for Spanish. Pour créer ce fichier de ressources dans Visual Studio :To create this resource file in 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.In Solution Explorer, right click on the folder which will contain the resource file > Add > New Item.

    Menu contextuel imbriqué : dans l’Explorateur de solutions, un menu contextuel est ouvert pour les ressources.

  2. Dans la zone Rechercher dans les modèles installés, entrez « ressource » et nommez le fichier.In the Search installed templates box, enter "resource" and name the file.

    Boîte de dialogue Ajouter un nouvel élément

  3. Entrez la valeur de la clé (chaîne native) dans la colonne Nom et la chaîne traduite dans la colonne Valeur.Enter the key value (native string) in the Name column and the translated string in the Value column.

    Le fichier Welcome.es.resx (le fichier de ressources Welcome pour l’espagnol) avec le mot Hello dans la colonne Nom et le mot Hola (bonjour en espagnol) dans la colonne Valeur

    Visual Studio présente le fichier Welcome.es.resx.Visual Studio shows the Welcome.es.resx file.

    L’Explorateur de solutions montrant le fichier de ressources Welcome pour l’espagnol (es)

Nommage du fichier de ressourcesResource file naming

Les ressources sont nommées selon le nom de type complet de leur classe moins le nom de l’assembly.Resources are named for the full type name of their class minus the assembly name. 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.For example, a French resource in a project whose main assembly is LocalizationWebsite.Web.dll for the class LocalizationWebsite.Web.Startup would be named Startup.fr.resx. Une ressource pour la classe LocalizationWebsite.Web.Controllers.HomeController serait nommée Controllers.HomeController.fr.resx.A resource for the class LocalizationWebsite.Web.Controllers.HomeController would be named 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.If your targeted class's namespace isn't the same as the assembly name you will need the full type name. Par exemple, dans l’exemple de projet, une ressource pour le type ExtraNamespace.Tools serait nommée ExtraNamespace.Tools.fr.resx.For example, in the sample project a resource for the type ExtraNamespace.Tools would be named ExtraNamespace.Tools.fr.resx.

Dans l’exemple de projet, la méthode ConfigureServices affecte à ResourcesPath la valeur « Resources », si bien que le chemin relatif du projet pour le fichier de ressources en français du contrôleur Home est Resources/Controllers.HomeController.fr.resx.In the sample project, the ConfigureServices method sets the ResourcesPath to "Resources", so the project relative path for the home controller's French resource file is Resources/Controllers.HomeController.fr.resx. Vous pouvez également utiliser des dossiers pour organiser les fichiers de ressources.Alternatively, you can use folders to organize resource files. Pour le contrôleur Home, le chemin serait Resources/Controllers/HomeController.fr.resx.For the home controller, the path would be 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.If you don't use the ResourcesPath option, the .resx file would go in the project base directory. Le fichier de ressources pour HomeController serait nommé Controllers.HomeController.fr.resx.The resource file for HomeController would be named 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.The choice of using the dot or path naming convention depends on how you want to organize your resource files.

Nom de la ressourceResource name Affectation de noms avec des points ou un cheminDot or path naming
Resources/Controllers.HomeController.fr.resxResources/Controllers.HomeController.fr.resx PointsDot
Resources/Controllers/HomeController.fr.resxResources/Controllers/HomeController.fr.resx Chemin d’accèsPath

Les fichiers de ressources qui utilisent @inject IViewLocalizer dans les vues Razor suivent un modèle similaire.Resource files using @inject IViewLocalizer in Razor views follow a similar pattern. Le fichier de ressources d’une vue peut être nommé selon la convention avec des points ou un chemin.The resource file for a view can be named using either dot naming or path naming. Les fichiers de ressources d’une vue Razor imitent le chemin de son fichier de vue associé.Razor view resource files mimic the path of their associated view file. Si nous affectons à ResourcesPath la valeur « Resources », le fichier de ressources en français associé à l’affichage Views/Home/About.cshtml peut porter l’un des noms suivants :Assuming we set the ResourcesPath to "Resources", the French resource file associated with the Views/Home/About.cshtml view could be either of the following:

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

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

Si vous n’utilisez pas l’option ResourcesPath, le fichier .resx d’une vue se trouve dans le même dossier que la vue.If you don't use the ResourcesPath option, the .resx file for a view would be located in the same folder as the view.

RootNamespaceAttributeRootNamespaceAttribute

L’attribut RootNamespace fournit l’espace de noms racine d’un assembly quand il est différent du nom de l’assembly.The RootNamespace attribute provides the root namespace of an assembly when the root namespace of an assembly is different than the assembly name.

Si l’espace de noms racine d’un assembly est différent du nom de l’assembly :If the root namespace of an assembly is different than the assembly name:

  • La localisation ne fonctionne pas par défaut.Localization does not work by default.
  • La localisation échoue en raison du mode de recherche des ressources dans l’assembly.Localization fails due to the way resources are searched for within the assembly. RootNamespace est une valeur de build qui n’est pas accessible au processus exécutant.RootNamespace is a build-time value which is not available to the executing process.

Si RootNamespace est différent de AssemblyName, incluez ce qui suit dans AssemblyInfo.cs (en remplaçant les valeurs des paramètres par les valeurs réelles) :If the RootNamespace is different from the AssemblyName, include the following in AssemblyInfo.cs (with parameter values replaced with the actual values):

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.The preceding code enables the successful resolution of resx files.

Comportement de secours pour la cultureCulture fallback behavior

Lors de la recherche d’une ressource, la localisation met en œuvre une « alternative de secours pour la culture ».When searching for a resource, localization engages in "culture fallback". Elle commence par la culture demandée : si elle est introuvable, il revient à la culture parente de cette culture.Starting from the requested culture, if not found, it reverts to the parent culture of that culture. Par ailleurs, la propriété CultureInfo.Parent représente la culture parente.As an aside, the CultureInfo.Parent property represents the parent culture. Cela signifie généralement (mais pas toujours) supprimer l’indicateur national du code ISO.This usually (but not always) means removing the national signifier from the ISO. Par exemple, le dialecte de l’espagnol parlé au Mexique est « es-MX ».For example, the dialect of Spanish spoken in Mexico is "es-MX". Il contient l’espagnol parent « es », qui n’est spécifique à aucun pays.It has the parent "es"—Spanish non-specific to any country.

Imaginez que votre site reçoive une demande pour une ressource « Bienvenue » avec la culture « fr-CA ».Imagine your site receives a request for a "Welcome" resource using culture "fr-CA". Le système de localisation recherche les ressources suivantes, dans l’ordre, et sélectionne la première correspondance :The localization system looks for the following resources, in order, and selects the first match:

  • Welcome.fr-CA.resxWelcome.fr-CA.resx
  • Welcome.fr.resxWelcome.fr.resx
  • Welcome.resx (si NeutralResourcesLanguage est « fr-CA »)Welcome.resx (if the NeutralResourcesLanguage is "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.As an example, if you remove the ".fr" culture designator and you have the culture set to French, the default resource file is read and strings are localized. 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.The Resource manager designates a default or fallback resource for when nothing meets your requested culture. 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.If you want to just return the key when missing a resource for the requested culture you must not have a default resource file.

Générer des fichiers de ressources avec Visual StudioGenerate resource files with 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.If you create a resource file in Visual Studio without a culture in the file name (for example, Welcome.resx), Visual Studio will create a C# class with a property for each string. Ce n’est généralement pas ce que vous souhaitez avec ASP.NET Core.That's usually not what you want with ASP.NET Core. Vous n’avez habituellement pas de fichier de ressources .resx par défaut (un fichier .resx sans nom de culture).You typically don't have a default .resx resource file (a .resx file without the culture name). Nous vous suggérons donc de créer le fichier .resx avec un nom de culture (par exemple, Welcome.fr.resx).We suggest you create the .resx file with a culture name (for example 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.When you create a .resx file with a culture name, Visual Studio won't generate the class file. Nous pensons que beaucoup de développeurs ne vont pas créer de fichier de ressources de langue par défaut.We anticipate that many developers won't create a default language resource file.

Ajouter d’autres culturesAdd other cultures

Chaque combinaison de langue et de culture (autres que la langue par défaut) nécessite un fichier de ressources unique.Each language and culture combination (other than the default language) requires a unique resource file. 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).You create resource files for different cultures and locales by creating new resource files in which the ISO language codes are part of the file name (for example, en-us, fr-ca, and 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).These ISO codes are placed between the file name and the .resx file extension, as in Welcome.es-MX.resx (Spanish/Mexico).

Implémenter une stratégie de sélection de la langue/culture pour chaque requêteImplement a strategy to select the language/culture for each request

Configurer la localisationConfigure localization

La localisation est configurée dans la méthode Startup.ConfigureServices :Localization is configured in the Startup.ConfigureServices method:

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

services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
  • AddLocalization ajoute les services de localisation au conteneur de services.AddLocalization Adds the localization services to the services container. Le code ci-dessus affecte également au chemin des ressources la valeur « Resources ».The code above also sets the resources path to "Resources".

  • AddViewLocalization ajoute la prise en charge des fichiers d’affichage localisés.AddViewLocalization Adds support for localized view files. Dans cet exemple d’affichage, la localisation se base sur le suffixe du fichier d’affichage.In this sample view localization is based on the view file suffix. Par exemple, « fr » dans le fichier Index.fr.cshtml.For example "fr" in the Index.fr.cshtml file.

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

Intergiciel (middleware) de localisationLocalization middleware

La culture actuelle sur une requête est définie dans l’intergiciel (middleware) de localisation.The current culture on a request is set in the localization Middleware. L’intergiciel de localisation est activé dans la méthode Startup.Configure.The localization middleware is enabled in the Startup.Configure method. L’intergiciel de localisation doit être configuré avant tout intergiciel susceptible de vérifier la culture de la requête (par exemple, app.UseMvcWithDefaultRoute()).The localization middleware must be configured before any middleware which might check the request culture (for example, app.UseMvcWithDefaultRoute()).

var supportedCultures = new[]
{
    new CultureInfo("en-US"),
    new CultureInfo("fr"),
};

app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("en-US"),
    // Formatting numbers, dates, etc.
    SupportedCultures = supportedCultures,
    // UI strings that we have localized.
    SupportedUICultures = supportedCultures
});

app.UseStaticFiles();
// To configure external authentication, 
// see: http://go.microsoft.com/fwlink/?LinkID=532715
app.UseAuthentication();
app.UseMvcWithDefaultRoute();

UseRequestLocalization initialise un objet RequestLocalizationOptions.UseRequestLocalization initializes a RequestLocalizationOptions object. 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é.On every request the list of RequestCultureProvider in the RequestLocalizationOptions is enumerated and the first provider that can successfully determine the request culture is used. Les fournisseurs par défaut proviennent de la classe RequestLocalizationOptions :The default providers come from the RequestLocalizationOptions class:

  1. QueryStringRequestCultureProvider
  2. CookieRequestCultureProvider
  3. AcceptLanguageHeaderRequestCultureProvider

La liste par défaut va du plus spécifique au moins spécifique.The default list goes from most specific to least specific. Plus loin dans l’article, nous verrons comment vous pouvez modifier l’ordre et même ajouter un fournisseur de culture personnalisé.Later in the article we'll see how you can change the order and even add a custom culture provider. Si aucun des fournisseurs ne peut déterminer la culture de la requête, DefaultRequestCulture est utilisé.If none of the providers can determine the request culture, the DefaultRequestCulture is used.

QueryStringRequestCultureProviderQueryStringRequestCultureProvider

Certaines applications utilisent une chaîne de requête pour définir la culture et la culture d’interface utilisateur.Some apps will use a query string to set the culture and UI culture. 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.For apps that use the cookie or Accept-Language header approach, adding a query string to the URL is useful for debugging and testing code. Par défaut, QueryStringRequestCultureProvider est inscrit en tant que premier fournisseur de localisation dans la liste RequestCultureProvider.By default, the QueryStringRequestCultureProvider is registered as the first localization provider in the RequestCultureProvider list. Vous passez les paramètres de chaîne de requête culture et ui-culture.You pass the query string parameters culture and ui-culture. L’exemple suivant affecte à la culture spécifique (langue et région) la valeur espagnol/Mexique :The following example sets the specific culture (language and region) to Spanish/Mexico:

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.If you only pass in one of the two (culture or ui-culture), the query string provider will set both values using the one you passed in. Par exemple, la seule définition de la culture définit à la fois Culture et UICulture :For example, setting just the culture will set both the Culture and the UICulture:

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

CookieRequestCultureProviderCookieRequestCultureProvider

Les applications de production fournissent souvent un mécanisme permettant de définir la culture à l’aide du cookie de culture ASP.NET Core.Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. Utilisez la méthode MakeCookieValue pour créer un cookie.Use the MakeCookieValue method to create a cookie.

CookieRequestCultureProvider DefaultCookieName retourne le nom de cookie par défaut utilisé pour effectuer le suivi des informations de culture préférée de l’utilisateur.The CookieRequestCultureProvider DefaultCookieName returns the default cookie name used to track the user's preferred culture information. Le nom du cookie par défaut est .AspNetCore.Culture.The default cookie name is .AspNetCore.Culture.

Le format du cookie est c=%LANGCODE%|uic=%LANGCODE%, où c correspond à Culture et uic correspond à UICulture, par exemple :The cookie format is c=%LANGCODE%|uic=%LANGCODE%, where c is Culture and uic is UICulture, for example:

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.If you only specify one of culture info and UI culture, the specified culture will be used for both culture info and UI culture.

En-tête HTTP Accept-LanguageThe Accept-Language HTTP header

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.The Accept-Language header is settable in most browsers and was originally intended to specify the user's language. Ce paramètre indique ce que le navigateur doit envoyer ou ce dont il a hérité du système d’exploitation sous-jacent.This setting indicates what the browser has been set to send or has inherited from the underlying operating system. 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).The Accept-Language HTTP header from a browser request isn't an infallible way to detect the user's preferred language (see Setting language preferences in a browser). Une application de production doit inclure un moyen permettant à l’utilisateur de personnaliser son choix de culture.A production app should include a way for a user to customize their choice of culture.

Définir l’en-tête HTTP Accept-Language dans IESet the Accept-Language HTTP header in IE

  1. À partir de l’icône d’engrenage, appuyez sur Options Internet.From the gear icon, tap Internet Options.

  2. Appuyez sur Langues.Tap Languages.

    Options Internet

  3. Appuyez sur Définir les langues.Tap Set Language Preferences.

  4. Appuyez sur Ajouter une langue.Tap Add a language.

  5. Ajoutez la langue.Add the language.

  6. Tapez sur la langue, puis sur Monter.Tap the language, then tap Move Up.

Utiliser un fournisseur personnaliséUse a custom provider

Supposons que vous vouliez permettre à vos clients de stocker leur langue et leur culture dans vos bases de données.Suppose you want to let your customers store their language and culture in your databases. Vous pouvez écrire un fournisseur pour rechercher ces valeurs pour l’utilisateur.You could write a provider to look up these values for the user. Le code suivant illustre l’ajout d’un fournisseur personnalisé :The following code shows how to add a custom provider:

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.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
    {
        // My custom request culture logic
        return new ProviderCultureResult("en");
    }));
});

Utilisez RequestLocalizationOptions pour ajouter ou supprimer des fournisseurs de localisation.Use RequestLocalizationOptions to add or remove localization providers.

Définir la culture par programmationSet the culture programmatically

Cet exemple de projet Localization.StarterWeb sur GitHub contient l’interface utilisateur permettant de définir Culture.This sample Localization.StarterWeb project on GitHub contains UI to set the Culture. Le fichier Views/Shared/_SelectLanguagePartial.cshtml vous permet de sélectionner la culture dans la liste des cultures prises en charge :The Views/Shared/_SelectLanguagePartial.cshtml file allows you to select the culture from the list of supported cultures:

@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 tous les affichages :The Views/Shared/_SelectLanguagePartial.cshtml file is added to the footer section of the layout file so it will be available to all views:

<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.The SetLanguage method sets the culture cookie.

[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 incorporer _SelectLanguagePartial.cshtml dans l’exemple de code de ce projet.You can't plug in the _SelectLanguagePartial.cshtml to sample code for this project. 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.The Localization.StarterWeb project on GitHub has code to flow the RequestLocalizationOptions to a Razor partial through the Dependency Injection container.

Terminologie de la globalisation et de la localisationGlobalization and localization terms

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.The process of localizing your app also requires a basic understanding of relevant character sets commonly used in modern software development and an understanding of the issues associated with them. 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.Although all computers store text as numbers (codes), different systems store the same text using different numbers. Le processus de localisation consiste à traduire l’interface utilisateur de l’application pour une culture/des paramètres régionaux spécifiques.The localization process refers to translating the app user interface (UI) for a specific culture/locale.

L’adaptabilité est un processus intermédiaire permettant de vérifier qu’une application globalisée est prête à être localisée.Localizability is an intermediate process for verifying that a globalized app is ready for localization.

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.The RFC 4646 format for the culture name is <languagecode2>-<country/regioncode2>, where <languagecode2> is the language code and <country/regioncode2> is the subculture code. Par exemple, es-CL pour l’espagnol (Chili), en-US pour l’anglais (États-Unis) et en-AU pour l’anglais (Australie).For example, es-CL for Spanish (Chile), en-US for English (United States), and en-AU for English (Australia). 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.RFC 4646 is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region. Consultez Nom de culture de la langue.See Language Culture Name.

L’internationalisation est souvent abrégée par « I18N ».Internationalization is often abbreviated to "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.The abbreviation takes the first and last letters and the number of letters between them, so 18 stands for the number of letters between the first "I" and the last "N". Il en va de même pour la globalisation (G11N) et la localisation (L10N).The same applies to Globalization (G11N), and Localization (L10N).

Termes :Terms:

  • Globalisation (G11N) : processus consistant à faire prendre en charge différentes langues et régions à une application.Globalization (G11N): The process of making an app support different languages and regions.
  • Localisation (L10N) : processus consistant à personnaliser une application pour une langue et une région données.Localization (L10N): The process of customizing an app for a given language and region.
  • Internationalisation (I18N) : globalisation et localisation.Internationalization (I18N): Describes both globalization and localization.
  • Culture : langue et, éventuellement, région.Culture: It's a language and, optionally, a region.
  • Culture neutre : culture dont la langue est spécifiée, mais non la région.Neutral culture: A culture that has a specified language, but not a region. (Exemples : « en », « es ».)(for example "en", "es")
  • Culture spécifique : culture dont la langue et la région sont spécifiées.Specific culture: A culture that has a specified language and region. (Exemples : « en-US », « en-GB », « es-CL ».)(for example "en-US", "en-GB", "es-CL")
  • Culture parente : culture neutre qui contient une culture spécifique.Parent culture: The neutral culture that contains a specific culture. (Exemple : « en » est la culture parent de « en-US » et « en-GB ».)(for example, "en" is the parent culture of "en-US" and "en-GB")
  • Paramètres régionaux : synonyme de culture.Locale: A locale is the same as a culture.

Notes

Vous ne pourrez peut-être pas entrer de virgules décimales dans les champs décimaux.You may not be able to enter decimal commas in decimal fields. 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.To support jQuery validation for non-English locales that use a comma (",") for a decimal point, and non US-English date formats, you must take steps to globalize your app. Consultez la page GitHub problème 4076 pour savoir comment ajouter une virgule décimale.This GitHub issue 4076 for instructions on adding decimal comma.

Ressources supplémentairesAdditional resources