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

  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 nastavenou jazykovou "sr-Latn-BA" verzí lokalizace, pokusí se 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 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ů:

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

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í ho localizer 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 typu ParameterizedMessageService a přiřadí ho _localizer k poli.
  • Metoda GetFormattedMessage vyvolá IStringLocalizer.Item[String, Object[]], předávání "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 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#:

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

Viz také