Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Lokalizacja to proces tłumaczenia zasobów aplikacji na zlokalizowane wersje dla każdej kultury obsługiwanej przez aplikację. Należy przejść do kroku lokalizacji dopiero po wykonaniu kroku Przegląd możliwości lokalizacji , aby sprawdzić, czy zglobalizowana aplikacja jest gotowa do lokalizacji.
Aplikacja gotowa do lokalizacji jest podzielona na dwa bloki koncepcyjne: blok zawierający wszystkie elementy interfejsu użytkownika i blok zawierający kod wykonywalny. Blok interfejsu użytkownika zawiera tylko lokalizowalne elementy interfejsu użytkownika, takie jak ciągi, komunikaty o błędach, okna dialogowe, menu, zasoby obiektów osadzonych itd. dla kultury neutralnej. Blok kodu zawiera tylko kod aplikacji, który ma być używany przez wszystkie obsługiwane kultury. Środowisko uruchomieniowe języka wspólnego obsługuje model zasobów zestawu satelitarnego oddzielający kod wykonywalny aplikacji od jej zasobów. Aby uzyskać więcej informacji na temat implementowania tego modelu, zobacz Zasoby na platformie .NET.
Dla każdej zlokalizowanej wersji aplikacji dodaj nowy zestaw satelitarny zawierający zlokalizowany blok interfejsu użytkownika przetłumaczony na odpowiedni język kultury docelowej. Blok kodu dla wszystkich kultur powinien pozostać taki sam. Kombinacja zlokalizowanej wersji bloku interfejsu użytkownika z blokiem kodu tworzy zlokalizowaną wersję aplikacji.
W tym artykule dowiesz się, jak używać implementacji IStringLocalizer<T> i IStringLocalizerFactory. Cały przykładowy kod źródłowy w tym artykule opiera się na pakietach Microsoft.Extensions.Localization NuGet i Microsoft.Extensions.Hosting . Aby uzyskać więcej informacji na temat hostingu, zobacz Ogólny host .NET.
Pliki zasobów
Podstawowym mechanizmem izolowania ciągów lokalizowalnych jest użycie plików zasobów. Plik zasobu to plik XML z rozszerzeniem .resx. Pliki zasobów są tłumaczone przed uruchomieniem aplikacji docelowej — innymi słowy reprezentują przetłumaczoną treść w stanie spoczynku. Nazwa pliku zasobu najczęściej zawiera kody lokalizacji i przyjmuje następujący format:
<FullTypeName><.Locale>.resx
Gdzie:
- Reprezentuje
<FullTypeName>zasoby lokalizowalne dla określonego typu. - Opcjonalnie
<.Locale>oznacza ustawienia regionalne zawartości pliku zasobu.
Określanie ustawień regionalnych
Ustawienia regionalne powinny definiować język na minimalnym poziomie, ale może również definiować kulturę (język regionalny), a nawet kraj lub region. Te segmenty są często rozdzielane znakiem - . Dzięki dodatkowej specyfiki kultury reguły "powrotu kultury" są stosowane w przypadku określania priorytetów najlepszych dopasowań. Ustawienia regionalne powinny być mapowane na dobrze znany tag języka. Aby uzyskać więcej informacji, zobacz CultureInfo.Name.
Scenariusze rezerwowe dotyczące kultury
Załóżmy, że zlokalizowana aplikacja obsługuje różne serbskie ustawienia regionalne i ma następujące pliki zasobów dla tej MessageServiceaplikacji:
| Plik | Język regionalny | Kod kraju |
|---|---|---|
| MessageService.sr-Cyrl-RS.resx | (Cyrylica, Serbia) | RS |
| MessageService.sr-Cyrl.resx | Cyrylica | |
| MessageService.sr-Latn-BA.resx | (Łaciński, Bośnia i Hercegowina) | BA |
| MessageService.sr-Latn-ME.resx | (Łaciński, Czarnogóra) | MNIE |
| MessageService.sr-Latn-RS.resx | (Łaciński, Serbia) | RS |
| MessageService.sr-Latn.resx | Łacina | |
| MessageService.sr.resx | † Łacina | |
| MessageService.resx |
† Domyślny język regionalny dla języka.
Gdy aplikacja jest uruchomiona z CultureInfo.CurrentCulture ustawieniem kultury "sr-Cyrl-RS", lokalizacja próbuje odnaleźć pliki w następującej kolejności:
- MessageService.sr-Cyrl-RS.resx
- MessageService.sr-Cyrl.resx
- MessageService.sr.resx
- MessageService.resx
Jeśli jednak aplikacja była uruchomiona z CultureInfo.CurrentCulture ustawieniem na kulturę "sr-Latn-BA", lokalizacja próbuje rozwiązać pliki w następującej kolejności:
- MessageService.sr-Latn-BA.resx
- MessageService.sr-Latn.resx
- MessageService.sr.resx
- MessageService.resx
Reguła 'culture fallback' będzie ignorować ustawienia regionalne, jeśli brak odpowiednich dopasowań, oznacza to, że jest wybierany plik zasobu numer cztery, gdy nie można znaleźć dopasowania. Jeśli kultura została ustawiona na "fr-FR", lokalizacja przypada na plik MessageService.resx, co może być problematyczne. Aby uzyskać więcej informacji, zobacz Proces awaryjnego przełączania zasobów.
Wyszukiwanie zasobów
Pliki zasobów są automatycznie rozwiązywane jako część rutyny wyszukiwania. Jeśli nazwa pliku projektu różni się od głównej przestrzeni nazw projektu, nazwa zestawu może się różnić. Może to uniemożliwić pomyślne wyszukiwanie zasobów. Aby rozwiązać ten problem, użyj elementu , RootNamespaceAttribute aby podać wskazówkę dla usług lokalizacji. Po podaniu jest on używany podczas wyszukiwania zasobów.
Przykładowy projekt ma nazwę example.csproj, który tworzy example.dll i example.exe—jednak przestrzeń nazw Localization.Example jest używana.
assembly Zastosuj atrybut poziomu, aby poprawić tę niezgodność:
[assembly: RootNamespace("Localization.Example")]
Rejestrowanie usług lokalizacji
Aby zarejestrować usługi lokalizacyjne, należy wywołać jedną z AddLocalization metod rozszerzenia podczas konfiguracji usług. Umożliwi to wstrzyknięcie zależności (DI) dla poniższych typów:
- Microsoft.Extensions.Localization.IStringLocalizer<T>
- Microsoft.Extensions.Localization.IStringLocalizerFactory
Konfigurowanie opcji lokalizacji
Przeciążona funkcja AddLocalization(IServiceCollection, Action<LocalizationOptions>) przyjmuje parametr setupAction typu Action<LocalizationOptions>. Umożliwia to skonfigurowanie opcji lokalizacji.
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
// Omitted for brevity.
Pliki zasobów mogą działać w dowolnym miejscu w projekcie, ale istnieją typowe rozwiązania, które okazały się skuteczne. Często wybierana jest ścieżka najmniejszego oporu. Poprzedni kod języka C#:
- Tworzy domyślnego konstruktora aplikacji hosta.
- Wywołuje
AddLocalizationdla kolekcji usług, określając LocalizationOptions.ResourcesPath jako"Resources".
Spowoduje to, że usługi lokalizacyjne będą szukać plików zasobów w katalogu Resources.
Używanie i IStringLocalizer<T>IStringLocalizerFactory
Po zarejestrowaniu (i opcjonalnie skonfigurowaniu) usługi lokalizacji można użyć następujących typów z DI.
Aby utworzyć usługę komunikatów, która może zwracać zlokalizowane ciągi, rozważ następujące kwestie 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;
}
}
W poprzednim kodzie języka C#:
- Pole
IStringLocalizer<MessageService> localizerjest zadeklarowane. - Podstawowy konstruktor definiuje
IStringLocalizer<MessageService>parametr i przechwytuje go jakolocalizerargument. - Metoda
GetGreetingMessagewywołuje IStringLocalizer.Item[String], przekazując"GreetingMessage"jako argument.
Obiekt IStringLocalizer obsługuje również sparametryzowane zasoby ciągów, rozważ następujące 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;
}
}
W poprzednim kodzie języka C#:
- Pole
IStringLocalizer _localizerjest zadeklarowane. - Podstawowy konstruktor przyjmuje
IStringLocalizerFactoryparametr , który jest używany do utworzenia elementuIStringLocalizerna podstawieParameterizedMessageServicetypu i przypisuje go do_localizerpola. - Metoda
GetFormattedMessagewywołuje IStringLocalizer.Item[String, Object[]], przekazując"DinnerPriceFormat", obiektdateTimeidinnerPricejako argumenty.
Ważne
Element IStringLocalizerFactory nie jest wymagany. Zamiast tego preferuje się, aby usługi wymagały IStringLocalizer<T>.
Oba IStringLocalizer.Item[] indeksatory zwracają element LocalizedString, który ma niejawne konwersje na string?.
Połącz wszystko
Aby zilustrować przykład aplikacji wykorzystującej obie usługi wiadomości, wraz z lokalizacją i plikami zasobów, rozważ następujący plik 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();
W poprzednim kodzie języka C#:
-
RootNamespaceAttribute ustawia
"Localization.Example"jako główną przestrzeń nazw. - Console.OutputEncoding jest przypisywana do Encoding.Unicode.
- Po przekazaniu pojedynczego argumentu do elementu
args, CultureInfo.CurrentCulture i CultureInfo.CurrentUICulture są przypisywane wyniki działania CultureInfo.GetCultureInfo(String), biorąc pod uwagęarg[0]. - Zostanie Host utworzony z wartościami domyślnymi.
- Usługi lokalizacyjne,
MessageServiceiParameterizedMessageServicesą zarejestrowane wIServiceCollectiondla DI. - Aby usunąć szum, rejestrowanie jest skonfigurowane do ignorowania dowolnego poziomu dziennika niższego niż ostrzeżenie.
- Element
MessageServicejest rozwiązany z wystąpieniaIServiceProvider, a komunikat wynikowy jest rejestrowany. - Element
ParameterizedMessageServicejest rozwiązywany z instancjiIServiceProvider, a jego wynikowy sformatowany komunikat jest zapisywany.
Każda z *MessageService klas definiuje zestaw plików resx z jednym wpisem. Oto przykładowa zawartość MessageService plików zasobów rozpoczynająca się od 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>
Oto przykładowa zawartość ParameterizedMessageService plików zasobów, począwszy od 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>
ParametrizedMessageService.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>
Wskazówka
Wszystkie komentarze XML, schemat i elementy <resheader> w pliku zasobów są celowo pominięte dla zwięzłości.
Przykładowe uruchomienia
W poniższym przykładzie pokazano różne zlokalizowane dane wyjściowe, biorąc pod uwagę docelowe ustawienia regionalne.
Rozważ "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 ¤.
W przypadku pominięcia argumentu do interfejsu wiersza polecenia platformy .NET w celu uruchomienia projektu używana jest domyślna kultura systemowa — w tym przypadku "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.
Podczas przekazywania "sr-Cryl-RS" polecenia, zostaną odnalezione odpowiednie pliki zasobów i zastosowana będzie lokalizacja.
dotnet run --project .\example\example.csproj sr-Cryl-RS
warn: Localization.Example[0]
Здраво пријатељи, ".NЕТ" девелопер заједница је узбуђена што вас види овде!
warn: Localization.Example[0]
У уторак, 03. август 2021. моја вечера је коштала 38 RSD.
Przykładowa aplikacja nie udostępnia plików zasobów dla "fr-CA", ale gdy jest wywoływana w tym języku, używane są nielokalizowane pliki zasobów.
Ostrzeżenie
Ponieważ kultura została odnaleziona, ale pliki zasobów są niepoprawne, podczas stosowania formatowania uzyskujesz częściową lokalizację.
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 $.