Lokalizace v .NET
Lokalizace je proces překladu prostředků aplikace do lokalizovaných verzí pro každou jazykovou verzi, kterou bude aplikace podporovat. Ke kroku lokalizace byste měli přejít až po dokončení kroku revize lokalizovatelnosti a ověřit, že je globalizovaná aplikace připravená k lokalizaci.
Aplikace, která je připravená k lokalizaci, je rozdělená do dvou koncepčních bloků: bloku, který obsahuje všechny prvky uživatelského rozhraní, a bloku, který obsahuje spustitelný kód. Blok uživatelského rozhraní obsahuje pouze lokalizovatelné prvky uživatelského rozhraní, jako jsou řetězce, chybové zprávy, dialogová okna, nabídky, prostředky vložených objektů atd. pro neutrální jazykovou verzi. Blok kódu obsahuje pouze kód aplikace, který budou používat všechny podporované jazykové verze. Modul CLR (Common Language Runtime) podporuje model prostředků satelitního sestavení, který odděluje spustitelný kód aplikace od prostředků. Další informace o implementaci tohoto modelu najdete v tématu Prostředky v .NET.
Pro každou lokalizovaná verze vaší aplikace přidejte nové satelitní sestavení, které obsahuje lokalizovaný blok uživatelského rozhraní přeložený do příslušného jazyka pro cílovou jazykovou verzi. Blok kódu pro všechny jazykové verze by měl zůstat stejný. Kombinací lokalizované verze bloku uživatelského rozhraní s blokem kódu se vytvoří lokalizovaná verze vaší aplikace.
V tomto článku se dozvíte, jak používat IStringLocalizer<T> IStringLocalizerFactory implementace a . Veškerý příklad zdrojového kódu v tomto článku závisí na balíčcích Microsoft.Extensions.Localization Microsoft.Extensions.Hosting a NuGet kódu. Další informace o hostování najdete v tématu Obecný hostitel .NET.
Soubory prostředků
Primárním mechanismem pro izolování lokalizovatelných řetězců jsou soubory prostředků. Soubor prostředků je soubor XML s příponou souboru .resx. Soubory prostředků se překládají před provedením spotřebovávající aplikace, jinými slovy, představují — přeložený obsah v klidové době. Název souboru prostředků obvykle obsahuje identifikátor národního prostředí a má následující formu:
<FullTypeName><.Locale>.resx
Kde:
- představuje
<FullTypeName>lokalizovatelné prostředky pro konkrétní typ. - Volitelné
<.Locale>představuje národní prostředí obsahu souboru prostředků.
Určení národního prostředí
Národní prostředí by mělo definovat jazyk minimálně, ale může také definovat jazykovou verzi (dialekt) a dokonce zemi. Tyto segmenty jsou obvykle odděleny - znakem . S přidanou specifikitou jazykové verze se pravidla pro "návratovou verzi jazykové verze" použijí tam, kde jsou nejlepší shody seřazeny podle priority. Národní prostředí by se mělo namapovat na dobře známou značku jazyka. Další informace naleznete v tématu CultureInfo.Name.
Scénáře pro použití v záložní jazykové verzi
Imagine, že lokalizovaná aplikace podporuje různá srbština národní prostředí a má následující soubory prostředků pro své MessageService :
| Soubor | Dialekt | Kód země |
|---|---|---|
| MessageService.sr-Cyrl-RS.resx | (Cyrilice, Portugalsko) | RS |
| MessageService.sr-Cyrl.resx | Cyrilice | |
| MessageService.sr-Latn-BA.resx | (Latinka, & Sádro) | BA |
| MessageService.sr-Latn-ME.resx | (Latinka, Kaskády) | ME |
| MessageService.sr-Latn-RS.resx | (Latinka, Portugalsko) | RS |
| MessageService.sr-Latn.resx | Latinské | |
| MessageService.sr.resx | † Latinské | |
| MessageService.resx |
† Výchozí dialekt jazyka.
Když je vaše aplikace spuštěná s CultureInfo.CurrentCulture nastavenou jazykovou verzí lokalizace, pokusí se soubory přeložit v následujícím "sr-Cyrl-RS" pořadí:
- MessageService.sr-Cyrl-RS.resx
- MessageService.sr-Cyrl.resx
- MessageService.sr.resx
- MessageService.resx
Pokud ale vaše aplikace běžela s nastavenou jazykovou verzí lokalizace, pokusí se soubory přeložit CultureInfo.CurrentCulture "sr-Latn-BA" v následujícím pořadí:
- MessageService.sr-Latn-BA.resx
- MessageService.sr-Latn.resx
- MessageService.sr.resx
- MessageService.resx
Pravidlo "záložní jazykové verze" bude ignorovat národní prostředí, pokud neexistují žádné odpovídající shody, což znamená, že je vybrán soubor prostředků číslo čtyři, pokud nemůže najít shodu. Pokud byla jazyková verze nastavená na , lokalizace by nakonec spadla na soubor "fr-FR" MessageService.resx, který může být problematický. Další informace najdete v tématu Záložní proces prostředků.
Vyhledávání prostředků
Soubory prostředků jsou automaticky vyřešeny v rámci rutiny vyhledávání. Pokud se název souboru projektu liší od kořenového oboru názvů projektu, název sestavení se může lišit. To může bránit tomu, aby vyhledávání prostředků bylo jinak úspěšné. K řešení této neshody použijte RootNamespaceAttribute k poskytnutí nápovědy lokalizačním službám . Pokud je k dispozici, použije se během vyhledávání prostředků.
Příklad projektu má název example.csproj, který vytvoří example.dll a example.exe ale použije — obor názvů Localization.Example . K assembly opravě této neshody použijte atribut úrovně:
[assembly: RootNamespace("Localization.Example")]
Registrace lokalizačních služeb
Pokud chcete zaregistrovat lokalizační služby, zavolejte během konfigurace AddLocalization služeb jednu z rozšiřujících metod. Tím se povolí injektáž závislostí (DI) následujících typů:
- Microsoft.Extensions.Localization.IStringLocalizer<T>
- Microsoft.Extensions.Localization.IStringLocalizerFactory
Konfigurace možností lokalizace
Přetížení AddLocalization(IServiceCollection, Action<LocalizationOptions>) přijímá parametr typu setupAction Action<LocalizationOptions> . To vám umožní nakonfigurovat možnosti lokalizace.
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
});
// Omitted for brevity.
Soubory prostředků mohou být v projektu kdekoli, ale existují běžné postupy, které se osvědčily jako úspěšné. Častěji než ne, dodržuje se cesta nejmenšího odolnosti. Předchozí kód jazyka C#:
- Vytvoří výchozího tvůrce hostitelů.
- Volá HostBuilder.ConfigureServices s
IServiceCollectionpřetížením. - Zavolá
AddLocalizationkolekci služby a zadá jako LocalizationOptions.ResourcesPath"Resources".
To by způsobilo, že lokalizační služby hledejí v adresáři Resources (Prostředky) soubory prostředků.
Použití IStringLocalizer<T> a IStringLocalizerFactory
Po registraci (a volitelně konfiguraci) lokalizačních služeb můžete u diody použít následující typy:
Pokud chcete vytvořit službu zpráv, která je schopná vracet lokalizované řetězce, zvažte MessageService následující:
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Localization;
namespace Localization.Example;
public class MessageService
{
private readonly IStringLocalizer<MessageService> _localizer = null!;
public MessageService(IStringLocalizer<MessageService> localizer) =>
_localizer = localizer;
[return: NotNullIfNotNull("_localizer")]
public string? GetGreetingMessage()
{
LocalizedString localizedString = _localizer["GreetingMessage"];
return localizedString;
}
}
V předchozím kódu jazyka C#:
- Je
IStringLocalizer<MessageService> _localizerdeklarováno pole. - Konstruktor přebírá parametr a
IStringLocalizer<MessageService>přiřaďte ho k_localizerpoli . - Metoda
GetGreetingMessagevyvolá předávání jako IStringLocalizer.Item[String]"GreetingMessage"argument.
Podporuje IStringLocalizer také parametrizované řetězcové prostředky. Vezměte v úvahu ParameterizedMessageService následující:
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Localization;
namespace Localization.Example;
public class ParameterizedMessageService
{
private readonly IStringLocalizer _localizer = null!;
public ParameterizedMessageService(IStringLocalizerFactory factory) =>
_localizer = factory.Create(typeof(ParameterizedMessageService));
[return: NotNullIfNotNull("_localizer")]
public string? GetFormattedMessage(DateTime dateTime, double dinnerPrice)
{
LocalizedString localizedString = _localizer["DinnerPriceFormat", dateTime, dinnerPrice];
return localizedString;
}
}
V předchozím kódu jazyka C#:
- Je
IStringLocalizer _localizerdeklarováno pole. - Konstruktor přebírá parametr , který se používá k vytvoření objektu z typu , a přiřadí
IStringLocalizerFactoryIStringLocalizerjej kParameterizedMessageService_localizerpoli. GetFormattedMessageMetoda vyvolá IStringLocalizer.Item[String, Object[]] , projde"DinnerPriceFormat",dateTimeobjekt adinnerPricejako argumenty.
Důležité
IStringLocalizerFactoryNení vyžadováno. Místo toho je vhodnější pro využívání služeb, které vyžadují IStringLocalizer<T> .
IStringLocalizer.Item[]Indexer vrací a LocalizedString , který má implicitní převod na string? .
Spojení všech součástí dohromady
Pokud chcete aplikaci exemplify pomocí obou služeb zpráv, společně s lokalizací a soubory prostředků, vezměte v úvahu následující soubor programu. cs :
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 { Length: 1 })
{
CultureInfo.CurrentCulture =
CultureInfo.CurrentUICulture =
CultureInfo.GetCultureInfo(args[0]);
}
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddLocalization();
services.AddTransient<MessageService>();
services.AddTransient<ParameterizedMessageService>();
})
.ConfigureLogging(options => options.SetMinimumLevel(LogLevel.Warning))
.Build();
IServiceProvider services = host.Services;
ILogger logger =
services.GetRequiredService<ILoggerFactory>()
.CreateLogger("Localization.Example");
MessageService messageService =
services.GetRequiredService<MessageService>();
logger.LogWarning(
messageService.GetGreetingMessage());
ParameterizedMessageService parameterizedMessageService =
services.GetRequiredService<ParameterizedMessageService>();
logger.LogWarning(
parameterizedMessageService.GetFormattedMessage(
DateTime.Today.AddDays(-3), 37.63));
await host.RunAsync();
V předchozím kódu jazyka C#:
- RootNamespaceAttributeSady
"Localization.Example"jako kořenový obor názvů. - Console.OutputEncodingJe přiřazen k Encoding.Unicode .
- Pokud je předán jeden argument
args, CultureInfo.CurrentCulture a CultureInfo.CurrentUICulture jsou přiřazeny výsledek CultureInfo.GetCultureInfo(String) danéhoarg[0]. - HostVytvoří se s výchozími hodnotami.
- Lokalizační služby,
MessageServiceaParameterizedMessageServicejsou registrovány vIServiceCollectionpro di. - Pokud chcete odebrat šum, protokolování je nakonfigurované tak, aby ignorovalo všechny úrovně protokolu, které jsou nižší než upozornění.
MessageServiceJe vyřešen zIServiceProviderinstance a jeho Výsledná zpráva je zaznamenána.- Je
ParameterizedMessageServicepřeložen zIServiceProviderinstance a jeho výsledná formátovaná zpráva je protokolována.
Každá z *MessageService tříd definuje sadu souborů . resx , z nichž každá má jednu položku. Zde je příklad obsahu pro MessageService soubory prostředků, počínaje 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>
Zde je příklad obsahu pro ParameterizedMessageService soubory prostředků, počínaje 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
Všechny komentáře, schéma a prvky XML souboru prostředků <resheader> jsou záměrně vynechány pro zkrácení.
Příklady spuštění
Následující příklad spustí zobrazení různých lokalizovaných výstupů s danými cílovými národními prostředími.
Zvažte "sr-Latn" následující:
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 ¤.
Při vynechání argumentu rozhraní příkazového řádku .NET pro spuštění projektu se v tomto případě použije výchozí jazyková verze systému — "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.
Při předání "sr-Cryl-RS" budou nalezeny správné odpovídající soubory prostředků a byla použita lokalizace:
dotnet run --project .\example\example.csproj sr-Cryl-RS
warn: Localization.Example[0]
Здраво пријатељи, ".NЕТ" девелопер заједница је узбуђена што вас види овде!
warn: Localization.Example[0]
У уторак, 03. август 2021. моја вечера је коштала 38 RSD.
Ukázková aplikace neposkytuje soubory prostředků pro "fr-CA" , ale při volání s touto jazykovou verzí jsou použity nelokalizované soubory prostředků.
Upozornění
Vzhledem k tomu, že je jazyková verze nalezena, ale správné soubory prostředků nejsou, při použití formátování, které končí částečnou lokalizací, je třeba použít následující:
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 $.