Sdílet prostřednictvím


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 prvky uživatelského rozhraní, které lze lokalizovat, jako jsou řetězce, chybové zprávy, dialogová okna, nabídky, vložené prostředky objektů atd. pro neutrální kulturu. Blok kódu obsahuje pouze kód aplikace, který se má používat ve všech podporovaných jazykových verzích. CLR (Common Language Runtime) podporuje model prostředků satelitního sestavení, který odděluje spustitelný kód aplikace od její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ý prvek uživatelského rozhraní přeložený do příslušného jazyka pro cílovou kulturu. 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 implementace. Veškerý ukázkový zdrojový kód v tomto článku závisí na balíčcích Microsoft.Extensions.Localization a Microsoft.Extensions.Hosting NuGet. 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 XML soubor s příponou .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 má následující formát:

<FullTypeName><.Locale>.resx

Kde:

  • <FullTypeName> představuje lokalizovatelné prostředky pro určitý typ.
  • Volitelné <.Locale> představuje národní prostředí obsahu souboru prostředku.

Určení jazykových a regionálních nastavení

Lokalita by měla definovat jazyk alespoň minimálně, ale může také definovat kulturu (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. Jazykové prostředí by se mělo mapovat na dobře známý jazykový kód. Další informace najdete v tématu CultureInfo.Name.

Kulturní záložní scénáře

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 Regionální 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) bakalář umění
MessageService.sr-Latn-ME.resx (latinka, Černá Hora)
MessageService.sr-Latn-RS.resx (latinka, Srbsko) RS
MessageService.sr-Latn.resx Latina
MessageService.sr.resx Latina
MessageService.resx

Výchozí jazyk oblasti pro jazyk.

Když je vaše aplikace spuštěná s CultureInfo.CurrentCulture nastavenou na jazykovou kulturu "sr-Cyrl-RS", pokusy o lokalizaci se pokusí vyřešit soubory v následujícím 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 CultureInfo.CurrentCulture nastaveným na kulturu "sr-Latn-BA", lokalizace se pokusí vyřešit soubory 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í odpovídající shody, což znamená, že je vybráno číslo souboru prostředku čtyři, pokud nemůže najít shodu. Pokud by jazyková verze byla nastavena na "fr-FR", lokalizace by nakonec využívala soubor MessageService.resx, což může být problémové. Další informace naleznete v tématu Proces náhradního zdroje.

Vyhledávání prostředků

Soubory prostředků se automaticky vyhledávají jako součást postupu vyhledávání. Pokud se pojmenování souboru projektu liší od kořenového oboru názvů vašeho 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ě. K vyřešení této neshody použijte RootNamespaceAttribute pro poskytnutí nápovědy 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 Localization.Example se používá 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ů:

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í osvědčené 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#:

To by způsobilo, že lokalizační služby vyhledávaly 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#:

  • IStringLocalizer<MessageService> localizer pole je deklarováno.
  • Primární konstruktor definuje IStringLocalizer<MessageService> parametr a zachytí ho localizer jako argument.
  • Metoda GetGreetingMessage vyvolá IStringLocalizer.Item[String] předáním "GreetingMessage" jako argumentu.

IStringLocalizer také podporuje 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#:

  • IStringLocalizer _localizer pole je deklarováno.
  • Primární konstruktor přebírá parametr IStringLocalizerFactory, který se používá k vytvoření IStringLocalizer z typu ParameterizedMessageService a přiřazuje ho do pole _localizer.
  • Metoda GetFormattedMessage vyvolá IStringLocalizer.Item[String, Object[]], předávaje "DinnerPriceFormat", dateTime objekt, a dinnerPrice 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 vracejí LocalizedString, který má implicitní konverze na string?.

Dejte to všechno dohromady

Pokud chcete aplikaci demonstrovat pomocí obou služeb zasílání zpráv spolu s lokalizací a soubory prostředků, zvažte následující soubor Program.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 [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#:

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>

Návod

Všechny komentáře, schéma a elementy <resheader> v 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 pro cílové regiony.

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

Pokud je v rozhraní .NET CLI pro spuštění projektu vynechán argument, je použita 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 pokud je zavolána s danou jazykovou verzí, používají se nelokalizované soubory prostředků.

Výstraha

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

Viz také