Lokalisatie in .NET
Lokalisatie is het proces van het vertalen van de resources van een toepassing in gelokaliseerde versies voor elke cultuur die door de toepassing wordt ondersteund. Ga pas verder met de lokalisatiestap nadat u de stap Localizability review hebt voltooid om te controleren of de geglobaliseerde toepassing gereed is voor lokalisatie.
Een toepassing die gereed is voor lokalisatie, is onderverdeeld in twee conceptuele blokken: een blok met alle elementen van de gebruikersinterface en een blok dat uitvoerbare code bevat. Het gebruikersinterfaceblok bevat alleen lokaliseerbare elementen van de gebruikersinterface, zoals tekenreeksen, foutberichten, dialoogvensters, menu's, ingesloten objectresources, enzovoort voor de neutrale cultuur. Het codeblok bevat alleen de toepassingscode die door alle ondersteunde culturen moet worden gebruikt. De algemene taalruntime ondersteunt een resourcemodel voor satellietassembly dat de uitvoerbare code van een toepassing scheidt van de bijbehorende resources. Zie Resources in .NET voor meer informatie over het implementeren van dit model.
Voeg voor elke gelokaliseerde versie van uw toepassing een nieuwe satellietassembly toe die het gelokaliseerde gebruikersinterfaceblok bevat dat is vertaald in de juiste taal voor de doelcultuur. Het codeblok voor alle culturen moet hetzelfde blijven. De combinatie van een gelokaliseerde versie van het gebruikersinterfaceblok met het codeblok produceert een gelokaliseerde versie van uw toepassing.
In dit artikel leert u hoe u de IStringLocalizer<T> en IStringLocalizerFactory implementaties gebruikt. Alle voorbeeldbroncode in dit artikel is afhankelijk van de Microsoft.Extensions.Localization
en Microsoft.Extensions.Hosting
NuGet-pakketten. Zie .NET Generic Host voor meer informatie over hosting.
Bronbestanden
Het primaire mechanisme voor het isoleren van lokaliseerbare tekenreeksen is met resourcebestanden. Een resourcebestand is een XML-bestand met de extensie .resx . Resourcebestanden worden vertaald vóór de uitvoering van de verbruikende toepassing, met andere woorden, ze vertegenwoordigen vertaalde inhoud in rust. Een resourcebestandsnaam bevat meestal een landinstellings-id en krijgt de volgende vorm:
<FullTypeName><.Locale>.resx
Hierin:
- De
<FullTypeName>
vertegenwoordigt lokaliseerbare resources voor een specifiek type. - De optionele
<.Locale>
vertegenwoordigt de landinstelling van de inhoud van het bronbestand.
Landinstellingen opgeven
De landinstelling moet de taal definiëren, minimaal, maar kan ook de cultuur (regionale taal) en zelfs het land of de regio definiëren. Deze segmenten worden meestal gescheiden door het -
teken. Met de toegevoegde specificiteit van een cultuur worden de 'cultuurterugvalregels' toegepast waar de beste overeenkomsten prioriteit krijgen. De landinstelling moet worden toegewezen aan een bekende taaltag. Zie CultureInfo.Name voor meer informatie.
Scenario's voor terugval van cultuur
Stel dat uw gelokaliseerde app verschillende Servische landinstellingen ondersteunt en de volgende bronbestanden voor MessageService
de app heeft:
Bestand | Regionale taal | Landcode |
---|---|---|
MessageService.sr-Cyrl-RS.resx | (Cyrillisch, Servië) | RS |
MessageService.sr-Cyrl.resx | Cyrillisch | |
MessageService.sr-Latn-BA.resx | (Latijns, Bosnië en Herzegovina) | BA |
MessageService.sr-Latn-ME.resx | (Latijns, Montenegro) | ME |
MessageService.sr-Latn-RS.resx | (Latijns, Servië) | RS |
MessageService.sr-Latn.resx | Latijnse | |
MessageService.sr.resx | † Latijns | |
MessageService.resx |
† De standaard regionale taal voor de taal.
Wanneer uw app wordt uitgevoerd met de CultureInfo.CurrentCulture set op een lokalisatiecultuur "sr-Cyrl-RS"
, probeert u bestanden in de volgende volgorde op te lossen:
- MessageService.sr-Cyrl-RS.resx
- MessageService.sr-Cyrl.resx
- MessageService.sr.resx
- MessageService.resx
Als uw app echter werd uitgevoerd met de CultureInfo.CurrentCulture set op een lokalisatiecultuur "sr-Latn-BA"
, probeert u bestanden in de volgende volgorde op te lossen:
- MessageService.sr-Latn-BA.resx
- MessageService.sr-Latn.resx
- MessageService.sr.resx
- MessageService.resx
De regel 'cultuurterugval' negeert landinstellingen wanneer er geen overeenkomende overeenkomsten zijn, wat betekent dat resourcebestand nummer vier is geselecteerd als er geen overeenkomst kan worden gevonden. Als de cultuur is ingesteld "fr-FR"
, zou lokalisatie uiteindelijk vallen in het bestand MessageService.resx , wat problematisch kan zijn. Zie het terugvalproces voor resources voor meer informatie.
Resourcezoekactie
Resourcebestanden worden automatisch opgelost als onderdeel van een opzoekroutine. Als de naam van het projectbestand anders is dan de hoofdnaamruimte van uw project, kan de assemblynaam verschillen. Dit kan voorkomen dat het opzoeken van resources anders lukt. Als u dit niet wilt oplossen, gebruikt u de RootNamespaceAttribute functie om een hint voor de lokalisatieservices te bieden. Wanneer deze is opgegeven, wordt deze gebruikt tijdens het opzoeken van resources.
Het voorbeeldproject heet example.csproj, waarmee een example.dll en example.exe wordt gemaakt, maar de Localization.Example
naamruimte wordt gebruikt. Pas een assembly
niveaukenmerk toe om dit verschil te corrigeren:
[assembly: RootNamespace("Localization.Example")]
Lokalisatieservices registreren
Als u lokalisatieservices wilt registreren, roept u een van de AddLocalization extensiemethoden aan tijdens de configuratie van services. Hiermee wordt afhankelijkheidsinjectie (DI) van de volgende typen ingeschakeld:
- Microsoft.Extensions.Localization.IStringLocalizer<T>
- Microsoft.Extensions.Localization.IStringLocalizerFactory
Lokalisatieopties configureren
De AddLocalization(IServiceCollection, Action<LocalizationOptions>) overbelasting accepteert een setupAction
parameter van het type Action<LocalizationOptions>
. Hiermee kunt u lokalisatieopties configureren.
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
// Omitted for brevity.
Resourcebestanden kunnen zich overal in een project bevinden, maar er zijn veelvoorkomende procedures die succesvol zijn gebleken. Vaker dan niet, wordt het pad van de minste weerstand gevolgd. De voorgaande C#-code:
- Hiermee maakt u de standaard opbouwfunctie voor host-apps.
- Roept
AddLocalization
de serviceverzameling aan, waarbij deze LocalizationOptions.ResourcesPath wordt opgegeven als"Resources"
.
Hierdoor zoeken de lokalisatieservices in de map Resources naar resourcebestanden.
Gebruiken IStringLocalizer<T>
en IStringLocalizerFactory
Nadat u de lokalisatieservices hebt geregistreerd (en optioneel hebt geconfigureerd), kunt u de volgende typen gebruiken met DI:
Als u een berichtenservice wilt maken die gelokaliseerde tekenreeksen kan retourneren, kunt u het volgende MessageService
overwegen:
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;
}
}
In de voorgaande C#-code:
- Een
IStringLocalizer<MessageService> localizer
veld wordt gedeclareerd. - De primaire constructor definieert een
IStringLocalizer<MessageService>
parameter en legt deze vast als argumentlocalizer
. - De
GetGreetingMessage
methode roept het IStringLocalizer.Item[String] doorgeven"GreetingMessage"
als argument aan.
Het IStringLocalizer
biedt ook ondersteuning voor geparameteriseerde tekenreeksresources. Houd rekening met het volgende ParameterizedMessageService
:
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;
}
}
In de voorgaande C#-code:
- Een
IStringLocalizer _localizer
veld wordt gedeclareerd. - De primaire constructor gebruikt een
IStringLocalizerFactory
parameter die wordt gebruikt om eenIStringLocalizer
van hetParameterizedMessageService
type te maken en deze toe te wijzen aan het_localizer
veld. - Met de
GetFormattedMessage
methode wordt IStringLocalizer.Item[String, Object[]]een object aangeroepen, doorgegeven"DinnerPriceFormat"
dateTime
, endinnerPrice
als argumenten.
Belangrijk
Dit IStringLocalizerFactory
is niet vereist. In plaats daarvan heeft het de voorkeur voor het verbruik van services om de IStringLocalizer<T>.
Beide IStringLocalizer.Item[] indexeerfuncties retourneren een LocalizedString, die impliciete conversies naar string?
.
Alles samenvoegen
Als u een app wilt illustreren met behulp van zowel berichtservices als lokalisatie- en resourcebestanden, kunt u het volgende Program.cs-bestand overwegen:
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();
In de voorgaande C#-code:
- De RootNamespaceAttribute sets
"Localization.Example"
als de hoofdnaamruimte. - De Console.OutputEncoding is toegewezen aan Encoding.Unicode.
- Wanneer één argument wordt doorgegeven aan
args
, wordt het CultureInfo.CurrentUICultureCultureInfo.CurrentCulture resultaat van CultureInfo.GetCultureInfo(String) dearg[0]
gegeven . - De Host wordt gemaakt met standaardinstellingen.
- De lokalisatieservices en
MessageService
ParameterizedMessageService
zijn geregistreerd bij deIServiceCollection
for DI. - Als u ruis wilt verwijderen, wordt logboekregistratie geconfigureerd om een logboekniveau lager dan een waarschuwing te negeren.
- De
MessageService
oplossing wordt opgelost vanuit hetIServiceProvider
exemplaar en het resulterende bericht wordt vastgelegd. - De
ParameterizedMessageService
oplossing wordt opgelost vanuit hetIServiceProvider
exemplaar en het resulterende opgemaakte bericht wordt geregistreerd.
Elk van de *MessageService
klassen definieert een set RESX-bestanden , elk met één vermelding. Hier volgt de voorbeeldinhoud voor de MessageService
resourcebestanden, te beginnen met 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>
Hier volgt de voorbeeldinhoud voor de ParameterizedMessageService
resourcebestanden, te beginnen met 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>
Tip
Alle XML-opmerkingen, schema's en <resheader>
elementen van het resourcebestand worden opzettelijk weggelaten ter beknoptheid.
Voorbeelduitvoeringen
In het volgende voorbeeld worden de verschillende gelokaliseerde uitvoer weergegeven, op basis van de doellandinstellingen.
Overweeg "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 ¤.
Wanneer u een argument weglaat bij de .NET CLI om het project uit te voeren , wordt de standaardsysteemcultuur gebruikt, in dit geval "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.
Bij het doorgeven "sr-Cryl-RS"
worden de juiste bijbehorende bronbestanden gevonden en de lokalisatie toegepast:
dotnet run --project .\example\example.csproj sr-Cryl-RS
warn: Localization.Example[0]
Здраво пријатељи, ".NЕТ" девелопер заједница је узбуђена што вас види овде!
warn: Localization.Example[0]
У уторак, 03. август 2021. моја вечера је коштала 38 RSD.
De voorbeeldtoepassing biedt geen bronbestanden voor "fr-CA"
, maar wanneer deze cultuur wordt aangeroepen, worden de niet-gelokaliseerde resourcebestanden gebruikt.
Waarschuwing
Omdat de cultuur wordt gevonden, maar de juiste bronbestanden niet zijn, krijgt u bij het toepassen van opmaak gedeeltelijke lokalisatie:
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 $.