Localisation dans .NET
La localisation correspond au processus de traduction des ressources d’une application dans des versions localisées pour chaque culture prise en charge par l’application. Vous devez passer à l’étape de localisation uniquement après avoir effectué l’étape Révision de l’adaptabilité pour vérifier que l’application globalisée est prête pour la localisation.
Une application prête pour la localisation est divisée en deux blocs conceptuels, un bloc qui contient tous les éléments d’interface utilisateur et un bloc qui contient le code exécutable. Le bloc d’interface utilisateur contient uniquement les éléments d’interface utilisateur localisables, comme les chaînes, les messages d’erreur, les boîtes de dialogue, les menus, les ressources d’objet incorporées, etc. relatifs à la culture neutre. Le bloc de code contient uniquement le code d’application à utiliser par toutes les cultures prises en charge. Le CLR prend en charge un modèle de ressource d’assembly satellite qui sépare le code exécutable d’une application de ses ressources. Pour plus d’informations sur l’implémentation de ce modèle, consultez Ressources dans .NET.
Pour chaque version localisée de votre application, ajoutez un nouvel assembly satellite contenant le bloc d’interface utilisateur localisée traduit dans la langue appropriée pour la culture cible. Le bloc de code pour toutes les cultures doit rester le même. La combinaison d’une version localisée du bloc d’interface utilisateur et du bloc de code produit une version localisée de votre application.
Dans cet article, vous allez apprendre à utiliser les implémentations IStringLocalizer<T> et IStringLocalizerFactory. Tous les exemples de code source de cet article s’appuie sur les packages NuGet Microsoft.Extensions.Localization
et Microsoft.Extensions.Hosting
. Pour plus d’informations sur l’hébergement, consultez Hôte générique .NET.
Fichiers de ressources
Le mécanisme principal pour isoler les chaînes localisables consiste à utiliser des fichiers de ressources. Un fichier de ressources est un fichier XML avec l’extension de fichier .resx. Les fichiers de ressources sont traduits avant l’exécution de l’application consommatrice. En d’autres termes, ils représentent le contenu traduit au repos. Un nom de fichier de ressources contient généralement un identificateur de paramètres régionaux et prend la forme suivante :
<FullTypeName><.Locale>.resx
Où :
- Le
<FullTypeName>
représente des ressources localisables pour un type spécifique. - L’argument facultatif
<.Locale>
représente les paramètres régionaux du contenu du fichier de ressources.
Spécification des paramètres régionaux
Les paramètres régionaux doivent définir la langue, au minimum, mais elles peuvent également définir la culture (langue régionale) et même le pays ou la région. Ces segments sont généralement délimités par le caractère -
. Avec la spécificité supplémentaire d’une culture, les règles de « secours pour la culture » sont appliquées où les meilleures correspondances sont hiérarchisées. Les paramètres régionaux doivent être mappés à une balise de langue connue. Pour plus d’informations, consultez CultureInfo.Name.
Scénarios de secours pour la culture
Imagine que votre application localisée prend en charge différents paramètres régionaux serbe et dispose des fichiers de ressources suivants pour son MessageService
:
Fichier | Langue régionale | Indicatif de pays |
---|---|---|
MessageService.sr-Cyrl-RS.resx | (Cyrillique, Serbie) | RS |
MessageService.sr-Cyrl.resx | Cyrillique | |
MessageService.sr-Latn-BA.resx | (Latin, Bosnie-Herzégovine) | BA |
MessageService.sr-Latn-ME.resx | (Latin, Monténégro) | ME |
MessageService.sr-Latn-RS.resx | (Latin, Serbie) | RS |
MessageService.sr-Latn.resx | Latin | |
MessageService.sr.resx | † Latin | |
MessageService.resx |
† La langue régionale par défaut pour la langue.
Lorsque votre application s’exécute avec le CultureInfo.CurrentCulture défini sur une culture de "sr-Cyrl-RS"
localisation tente de résoudre les fichiers dans l’ordre suivant :
- MessageService.sr-Cyrl-RS.resx
- MessageService.sr-Cyrl.resx
- MessageService.sr.resx
- MessageService.resx
Toutefois, si votre application s’exécutait avec le CultureInfo.CurrentCulture défini sur une culture de "sr-Latn-BA"
localisation tente de résoudre les fichiers dans l’ordre suivant :
- MessageService.sr-Latn-BA.resx
- MessageService.sr-Latn.resx
- MessageService.sr.resx
- MessageService.resx
La règle de « secours pour la culture » ignore les paramètres régionaux lorsqu’il n’existe aucune correspondance correspondante, ce qui signifie que le numéro de fichier de ressource quatre est sélectionné s’il ne parvient pas à trouver une correspondance. Si la culture était définie sur "fr-FR"
, la localisation finirait par tomber dans le fichier MessageService.resx, ce qui peut être problématique. Pour plus d’informations, consultez Le processus de secours pour les ressources.
Recherche de ressources
Les fichiers de ressources sont automatiquement résolus dans le cadre d’une routine de recherche. Si le nom de votre fichier de projet est différent de l’espace de noms racine de votre projet, le nom de l’assembly peut différer. Cela peut empêcher la recherche de ressources de réussir autrement. Pour résoudre ce problème, utilisez le RootNamespaceAttribute pour fournir un indicateur aux services de localisation. Lorsqu’il est fourni, il est utilisé lors de la recherche de ressources.
L’exemple de projet est nommé example.csproj, qui crée un example.dll et un example.exe. Toutefois, l’espace de noms Localization.Example
est utilisé. Appliquez un attribut assembly
de niveau pour corriger cette incompatibilité :
[assembly: RootNamespace("Localization.Example")]
Inscrire les services de localisation
Pour inscrire les services de localisation, appelez l’une des méthodes d’extension AddLocalization lors de la configuration des services. Cela permet l’injection de dépendances (DI) des types suivants :
- Microsoft.Extensions.Localization.IStringLocalizer<T>
- Microsoft.Extensions.Localization.IStringLocalizerFactory
Configurer les options de localisation
La surcharge AddLocalization(IServiceCollection, Action<LocalizationOptions>) accepte un paramètre setupAction
de type Action<LocalizationOptions>
. Cela vous permet de configurer les options de localisation.
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
// Omitted for brevity.
Les fichiers de ressources peuvent se trouver n’importe où dans un projet, mais il existe des pratiques courantes qui se sont avérées efficaces. Le plus souvent, la voie de la moindre résistance est suivie. Le code C# précédent :
- Crée le générateur d’applications hôtes par défaut.
- Appelle
AddLocalization
sur la collection de services, en spécifiant LocalizationOptions.ResourcesPath en tant que"Resources"
.
Cela entraînerait la recherche de fichiers de ressources par les services de localisation dans le répertoire Ressources.
Utiliser IStringLocalizer<T>
et IStringLocalizerFactory
Une fois que vous avez inscrit (et éventuellement configuré) les services de localisation, vous pouvez utiliser les types suivants avec DI :
Pour créer un service de message capable de retourner des chaînes localisées, tenez compte des points suivants MessageService
:
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Localization;
namespace Localization.Example;
public sealed class MessageService(IStringLocalizer<MessageService> localizer)
{
[return: NotNullIfNotNull(nameof(localizer))]
public string? GetGreetingMessage()
{
LocalizedString localizedString = localizer["GreetingMessage"];
return localizedString;
}
}
Dans le code C# précédent :
- Un champ
IStringLocalizer<MessageService> localizer
est déclaré. - Le constructeur principal définit un paramètre
IStringLocalizer<MessageService>
et le capture en tant qu’argumentlocalizer
. - La méthode
GetGreetingMessage
appelle IStringLocalizer.Item[String] transférant"GreetingMessage"
en tant qu’argument.
IStringLocalizer
prend également en charge les ressources de chaîne paramétrable, à prendre en compte le ParameterizedMessageService
suivant :
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Localization;
namespace Localization.Example;
public class ParameterizedMessageService(IStringLocalizerFactory factory)
{
private readonly IStringLocalizer _localizer =
factory.Create(typeof(ParameterizedMessageService));
[return: NotNullIfNotNull(nameof(_localizer))]
public string? GetFormattedMessage(DateTime dateTime, double dinnerPrice)
{
LocalizedString localizedString = _localizer["DinnerPriceFormat", dateTime, dinnerPrice];
return localizedString;
}
}
Dans le code C# précédent :
- Un champ
IStringLocalizer _localizer
est déclaré. - Le constructeur principal prend un paramètre
IStringLocalizerFactory
, qui est utilisé pour créer unIStringLocalizer
à partir du typeParameterizedMessageService
et l’affecte au champ_localizer
. - La méthode
GetFormattedMessage
appelle IStringLocalizer.Item[String, Object[]], en transférant"DinnerPriceFormat"
, un objetdateTime
etdinnerPrice
comme arguments.
Important
Le IStringLocalizerFactory
n’est pas obligatoire. Au lieu de cela, il est préférable que les services consommatrices requièrent le IStringLocalizer<T>.
Les deux indexeurs IStringLocalizer.Item[] retournent un LocalizedString, qui a des conversions implicites en string?
.
Assemblage
Pour illustrer une application utilisant à la fois les services de message, ainsi que les fichiers de localisation et de ressources, considérez le fichier Program. cs suivant :
using System.Globalization;
using Localization.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using static System.Console;
using static System.Text.Encoding;
[assembly: RootNamespace("Localization.Example")]
OutputEncoding = Unicode;
if (args is [var cultureName])
{
CultureInfo.CurrentCulture =
CultureInfo.CurrentUICulture =
CultureInfo.GetCultureInfo(cultureName);
}
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddLocalization();
builder.Services.AddTransient<MessageService>();
builder.Services.AddTransient<ParameterizedMessageService>();
builder.Logging.SetMinimumLevel(LogLevel.Warning);
using IHost host = builder.Build();
IServiceProvider services = host.Services;
ILogger logger =
services.GetRequiredService<ILoggerFactory>()
.CreateLogger("Localization.Example");
MessageService messageService =
services.GetRequiredService<MessageService>();
logger.LogWarning(
"{Msg}",
messageService.GetGreetingMessage());
ParameterizedMessageService parameterizedMessageService =
services.GetRequiredService<ParameterizedMessageService>();
logger.LogWarning(
"{Msg}",
parameterizedMessageService.GetFormattedMessage(
DateTime.Today.AddDays(-3), 37.63));
await host.RunAsync();
Dans le code C# précédent :
- Le RootNamespaceAttribute définit
"Localization.Example"
en tant qu’espace de noms racine. - Le Console.OutputEncoding est affecté à Encoding.Unicode.
- Lorsqu’un argument unique est passé à
args
, le CultureInfo.CurrentCulture et le CultureInfo.CurrentUICulture se voient attribuer le résultat de CultureInfo.GetCultureInfo(String) compte tenu learg[0]
. - Le Host est créé avec les valeurs par défaut.
- Les services de localisation,
MessageService
etParameterizedMessageService
sont inscrits auprès deIServiceCollection
pour l’injection de dépendances. - Pour supprimer le bruit, la journalisation est configurée pour ignorer tout niveau de journal inférieur à un avertissement.
- Le
MessageService
est résolu à partir de l’instanceIServiceProvider
et son message résultant est journalisé. - Le
ParameterizedMessageService
est résolu à partir de l’instanceIServiceProvider
et son message mis en forme résultant est journalisé.
Chacune des classes *MessageService
définit un ensemble de fichiers .resx, chacun avec une seule entrée. Voici l’exemple de contenu des fichiers de ressources MessageService
, en commençant par MessageService.resx :
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="GreetingMessage" xml:space="preserve">
<value>Hi friends, the ".NET" developer community is excited to see you here!</value>
</data>
</root>
MessageService.sr-Cyrl-RS.resx :
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="GreetingMessage" xml:space="preserve">
<value>Здраво пријатељи, ".NЕТ" девелопер заједница је узбуђена што вас види овде!</value>
</data>
</root>
MessageService.sr-Latn.resx :
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="GreetingMessage" xml:space="preserve">
<value>Zdravo prijatelji, ".NET" developer zajednica je uzbuđena što vas vidi ovde!</value>
</data>
</root>
Voici l’exemple de contenu des fichiers de ressources ParameterizedMessageService
, en commençant par ParameterizedMessageService.resx :
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="DinnerPriceFormat" xml:space="preserve">
<value>On {0:D} my dinner cost {1:C}.</value>
</data>
</root>
ParameterizedMessageService.sr-Cyrl-RS.resx :
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="DinnerPriceFormat" xml:space="preserve">
<value>У {0:D} моја вечера је коштала {1:C}.</value>
</data>
</root>
ParameterizedMessageService.sr-Latn.resx :
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="DinnerPriceFormat" xml:space="preserve">
<value>U {0:D} moja večera je koštala {1:C}.</value>
</data>
</root>
Conseil
Tous les commentaires, schémas et éléments XML <resheader>
du fichier de ressources sont intentionnellement omis par souci de concision.
Exemples d’exécutions
L’exemple d’exécution suivant montre les différentes sorties localisées, en fonction des paramètres régionaux ciblés.
Prenez le cas de "sr-Latn"
:
dotnet run --project .\example\example.csproj sr-Latn
warn: Localization.Example[0]
Zdravo prijatelji, ".NET" developer zajednica je uzbuđena što vas vidi ovde!
warn: Localization.Example[0]
U utorak, 03. avgust 2021. moja večera je koštala 37,63 ¤.
Lorsque vous omettez un argument dans l’interface de ligne de commande .NET pour exécuter le projet, la culture système par défaut est utilisée, dans ce cas "en-US"
:
dotnet run --project .\example\example.csproj
warn: Localization.Example[0]
Hi friends, the ".NET" developer community is excited to see you here!
warn: Localization.Example[0]
On Tuesday, August 3, 2021 my dinner cost $37.63.
Lors du transfert de "sr-Cryl-RS"
, les fichiers de ressources correspondants appropriés sont trouvés et la localisation est appliquée :
dotnet run --project .\example\example.csproj sr-Cryl-RS
warn: Localization.Example[0]
Здраво пријатељи, ".NЕТ" девелопер заједница је узбуђена што вас види овде!
warn: Localization.Example[0]
У уторак, 03. август 2021. моја вечера је коштала 38 RSD.
L’exemple d’application ne fournit pas de fichiers de ressources pour "fr-CA"
, mais lorsqu’il est appelé avec cette culture, les fichiers de ressources non localisés sont utilisés.
Avertissement
Puisque la culture est trouvée, mais que les fichiers de ressources corrects ne le sont pas, lorsque la mise en forme est appliquée, vous vous retrouvez avec une localisation partielle :
dotnet run --project .\example\example.csproj fr-CA
warn: Localization.Example[0]
Hi friends, the ".NET" developer community is excited to see you here!
warn: Localization.Example[0]
On mardi 3 août 2021 my dinner cost 37,63 $.