Lokalizace v .NET
Lokalizace je proces překladu prostředků aplikace do lokalizovaných verzí pro každou jazykovou verzi, kterou bude aplikace podporovat. K kroku lokalizace byste měli přejít až po dokončení kroku kontroly lokalizovatelnosti, abyste ověřili, že je globalizovaná aplikace připravená k lokalizaci.
Aplikace připravená k lokalizaci je oddělená do dvou koncepčních bloků: blok, který obsahuje všechny prvky uživatelského rozhraní a blok obsahující 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, vložené prostředky objektů atd. pro neutrální jazykovou verzi. Blok kódu obsahuje pouze kód aplikace, který se má používat ve všech podporovaných jazykových verzích. Modul CLR (Common Language Runtime) podporuje model prostředků satelitního sestavení, který odděluje spustitelný kód aplikace od svých prostředků. Další informace o implementaci tohoto modelu naleznete v tématu Prostředky v .NET.
Pro každou lokalizovanou verzi 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ý. Kombinace lokalizované verze bloku uživatelského rozhraní s blokem kódu vytvoří lokalizovanou verzi vaší aplikace.
V tomto článku se dozvíte, jak používat IStringLocalizer<T> a IStringLocalizerFactory implementovat. Veškerý ukázkový zdrojový kód v tomto článku závisí na Microsoft.Extensions.Localization
balíčcích NuGet.Microsoft.Extensions.Hosting
Další informace o hostování naleznete v tématu .NET Generic Host.
Soubory prostředků
Primárním mechanismem izolace lokalizovatelných řetězců jsou soubory prostředků. Soubor prostředků je soubor XML s příponou souboru .resx . Soubory prostředků se přeloží před spuštěním aplikace, jinými slovy, představují přeložený obsah v klidovém stavu. Název souboru prostředku nejčastěji obsahuje identifikátor národního prostředí a přebírá následující formulář:
<FullTypeName><.Locale>.resx
Kde:
- Představuje
<FullTypeName>
lokalizovatelné prostředky pro určitý typ. - Volitelné
<.Locale>
představuje národní prostředí obsahu souboru prostředku.
Určení národních prostředí
Národní prostředí by mělo definovat jazyk na úplné minimum, ale může také definovat jazykovou verzi (regionální jazyk) a dokonce i zemi nebo oblast. Tyto segmenty jsou obvykle oddělené znakem -
. S přidanou specificitou jazykové verze se použijí pravidla "záložní verze" tam, kde jsou upřednostňovány nejlepší shody. Národní prostředí by se mělo mapovat na známou značku jazyka. Další informace najdete na webu CultureInfo.Name.
Záložní scénáře jazykové verze
Představte si, že vaše lokalizovaná aplikace podporuje různé srbské národní prostředí a má následující soubory prostředků:MessageService
Soubor | Místní jazyk | Kód země |
---|---|---|
MessageService.sr-Cyrl-RS.resx | (cyrilice, Srbsko) | RS |
MessageService.sr-Cyrl.resx | Cyrilice | |
MessageService.sr-Latn-BA.resx | (latinka, Bosna a Hercegovina) | BA |
MessageService.sr-Latn-ME.resx | (latinka, Černá Hora) | ME |
MessageService.sr-Latn-RS.resx | (latinka, Srbsko) | RS |
MessageService.sr-Latn.resx | Latinské | |
MessageService.sr.resx | † latinka | |
MessageService.resx |
† výchozí místní jazyk jazyka.
Když je vaše aplikace spuštěná se CultureInfo.CurrentCulture sadou na jazykovou "sr-Cyrl-RS"
verzi lokalizace, pokusí se vyřešit soubory v následujícím pořadí:
- MessageService.sr-Cyrl-RS.resx
- MessageService.sr-Cyrl.resx
- MessageService.sr.resx
- MessageService.resx
Pokud ale vaše aplikace běžela s CultureInfo.CurrentCulture nastavenou jazykovou "sr-Latn-BA"
verzí lokalizace, pokusí se vyřešit soubory 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í odpovídající shody, což znamená, že je vybráno číslo souboru prostředku čtyři, pokud nemůže najít shodu. Pokud byla jazyková verze nastavena na "fr-FR"
, lokalizace by skončila v souboru MessageService.resx , který může být problematický. Další informace naleznete v tématu Záložní proces prostředku.
Vyhledávání prostředků
Soubory prostředků se automaticky překládají jako součást rutiny vyhledávání. Pokud se název souboru projektu liší od kořenového oboru názvů projektu, může se název sestavení lišit. To může zabránit tomu, aby vyhledávání prostředků jinak proběhlo úspěšně. Pokud chcete tuto neshodu RootNamespaceAttribute vyřešit, použijte nápovědu k lokalizačním službám. Po zadání se použije při vyhledávání prostředků.
Ukázkový projekt má název example.csproj, který vytvoří example.dll a example.exe – ale použije se Localization.Example
obor názvů. Pomocí atributu úrovně opravte tuto neshodu assembly
:
[assembly: RootNamespace("Localization.Example")]
Registrace lokalizačních služeb
Pokud chcete zaregistrovat lokalizační služby, zavolejte jednu z AddLocalization metod rozšíření během konfigurace služeb. 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á setupAction
parametr typu Action<LocalizationOptions>
. To vám umožní nakonfigurovat možnosti lokalizace.
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
// Omitted for brevity.
Soubory prostředků se můžou nacházet kdekoli v projektu, ale existují běžné postupy, které se ukázaly jako úspěšné. Častěji než ne, cesta nejmenšího odporu je sledována. Předchozí kód jazyka C#:
- Vytvoří výchozí tvůrce hostitelských aplikací.
- Volá
AddLocalization
kolekci služeb, která určuje LocalizationOptions.ResourcesPath jako"Resources"
.
To by způsobilo, že lokalizační služby vyhledávají soubory prostředků v adresáři Resources .
Použití IStringLocalizer<T>
a IStringLocalizerFactory
Jakmile zaregistrujete(a volitelně nakonfigurujete) lokalizační služby, můžete s DI použít následující typy:
Pokud chcete vytvořit službu zpráv, která dokáže vrátit lokalizované řetězce, zvažte následující 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;
}
}
V předchozím kódu jazyka C#:
- Deklaruje
IStringLocalizer<MessageService> localizer
se pole. - Primární konstruktor definuje
IStringLocalizer<MessageService>
parametr a zachytí holocalizer
jako argument. - Metoda
GetGreetingMessage
vyvolá IStringLocalizer.Item[String] předávání"GreetingMessage"
jako argument.
Podporuje IStringLocalizer
také parametrizované řetězcové prostředky, zvažte následující 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;
}
}
V předchozím kódu jazyka C#:
- Deklaruje
IStringLocalizer _localizer
se pole. - Primární konstruktor přebírá
IStringLocalizerFactory
parametr, který se používá k vytvořeníIStringLocalizer
typuParameterizedMessageService
a přiřadí ho_localizer
k poli. - Metoda
GetFormattedMessage
vyvolá IStringLocalizer.Item[String, Object[]], předávání"DinnerPriceFormat"
,dateTime
objekt adinnerPrice
jako argumenty.
Důležité
Není IStringLocalizerFactory
to povinné. Místo toho je upřednostňované pro využívání služeb, které vyžadují IStringLocalizer<T>.
Oba IStringLocalizer.Item[] indexery vrací LocalizedString, které mají implicitní převody na string?
.
Spojení všech součástí dohromady
Pokud chcete aplikaci exemplizovat pomocí obou služeb zpráv spolu s lokalizací a soubory prostředků, zvažte následující Program.cs soubor:
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();
V předchozím kódu jazyka C#:
"Localization.Example"
Nastaví RootNamespaceAttribute se jako kořenový obor názvů.- Je Console.OutputEncoding přiřazeno .Encoding.Unicode
- Při předání
args
jednoho argumentu CultureInfo.CurrentCulture , a CultureInfo.CurrentUICulture jsou přiřazeny výsledek CultureInfo.GetCultureInfo(String) danéarg[0]
. - Vytvoří se Host s výchozími nastaveními.
- Lokalizační služby
MessageService
aParameterizedMessageService
jsou registrovány doIServiceCollection
di di. - Pokud chcete odebrat šum, protokolování je nakonfigurované tak, aby ignoroval jakoukoli úroveň protokolu nižší než upozornění.
- Tento
MessageService
problém se vyřeší zIServiceProvider
instance a výsledná zpráva se zaprotokoluje. - Tento
ParameterizedMessageService
problém se vyřeší zIServiceProvider
instance a zaprotokoluje se výsledná formátovaná zpráva.
Každá z *MessageService
tříd definuje sadu souborů .resx , každý s jedinou položkou. Tady 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>
Tady je příklad obsahu pro ParameterizedMessageService
soubory prostředků počínaje ParametrizedMessageService.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>
ParametrizedMessageService.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émata a <resheader>
elementy souboru prostředků xml jsou záměrně vynechány pro stručnost.
Příklady spuštění
Následující příklad ukazuje různé lokalizované výstupy vzhledem k cílovým národním prostředím.
Zvažte "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 ¤.
Při vynechání argumentu rozhraní .NET CLI ke spuštění projektu se použije výchozí systémová jazyková verze – v tomto případě "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ávání "sr-Cryl-RS"
se najdou správné odpovídající soubory prostředků a použije se 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 zavolání s danou jazykovou verzí se používají nelokalizovány soubory prostředků.
Upozorňující
Vzhledem k tomu, že se jazyková verze najde, ale správné soubory prostředků nejsou, při formátování se nakonec použije částečná lokalizace:
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 $.