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í:

  1. MessageService.sr-Cyrl-RS.resx
  2. MessageService.sr-Cyrl.resx
  3. MessageService.sr.resx
  4. 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í:

  1. MessageService.sr-Latn-BA.resx
  2. MessageService.sr-Latn.resx
  3. MessageService.sr.resx
  4. 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ů:

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#:

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> _localizer deklarováno pole.
  • Konstruktor přebírá parametr a IStringLocalizer<MessageService> přiřaďte ho k _localizer poli .
  • Metoda GetGreetingMessage vyvolá 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 _localizer deklarováno pole.
  • Konstruktor přebírá parametr , který se používá k vytvoření objektu z typu , a přiřadí IStringLocalizerFactory IStringLocalizer jej k ParameterizedMessageService _localizer poli.
  • GetFormattedMessageMetoda vyvolá IStringLocalizer.Item[String, Object[]] , projde "DinnerPriceFormat" , dateTime objekt a dinnerPrice jako 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#:

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 $.

Viz také