Globalizacja i lokalizacja w ASP.NET Core
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Przez Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana i Hisham Bin Ateya
Wielojęzyczna witryna internetowa umożliwia witrynie internetowej dotarcie do szerszej grupy odbiorców. ASP.NET Core udostępnia usługi i oprogramowanie pośredniczące do lokalizowania w różnych językach i kulturach.
Aby uzyskać Blazor wskazówki dotyczące lokalizacji, które dodaje lub zastępuje wskazówki zawarte w tym artykule, zobacz ASP.NET Core Blazor globalizacji i lokalizacji.
Terminy
- Globalizacja (G11N): proces tworzenia aplikacji obsługuje różne języki i regiony. Skrót pochodzi od pierwszych i ostatnich liter oraz liczby liter między nimi.
- Lokalizacja (L10N): proces dostosowywania zglobalizowanej aplikacji dla określonych języków i regionów.
- Internationalization (I18N): Globalizacja i lokalizacja.
- Kultura: język i, opcjonalnie, region.
- Kultura neutralna: kultura, która ma określony język, ale nie region (na przykład "en", "es").
- Określona kultura: kultura z określonym językiem i regionem (na przykład "en-US", "en-GB", "es-CL").
- Kultura nadrzędna: neutralna kultura zawierająca określoną kulturę (na przykład "en" jest kulturą nadrzędną "en-US" i "en-GB").
- Ustawienia regionalne: ustawienia regionalne są takie same jak kultura.
Kody języków i krajów/regionów
Format RFC 4646 dla nazwy kultury to <language code>-<country/region code>
, gdzie <language code>
identyfikuje język i <country/region code>
identyfikuje podkulturę. Na przykład es-CL
w przypadku języka hiszpańskiego (Chile), en-US
angielskiego (Stany Zjednoczone) i en-AU
angielskiego (Australia). RFC 4646 to kombinacja dwuliterowego dwuliterowego kodu kultury ISO 639 skojarzonego z językiem i dwuliterowego kodu subkultury ISO 3166 skojarzonego z krajem lub regionem. Aby uzyskać więcej informacji, zobacz System.Globalization.CultureInfo.
Zadania lokalizowania aplikacji
Globalizacja i lokalizowanie aplikacji obejmuje następujące zadania:
- Utwórz lokalną zawartość aplikacji ASP.NET Core.
- Udostępnianie zlokalizowanych zasobów dla kultur, które obsługuje aplikacja
- Implementowanie strategii wybierania kultury dla każdego żądania
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Dodatkowe zasoby
- Dostawca kultury adresu URL korzystający z oprogramowania pośredniczącego jako filtry w programie ASP.NET Core
- Globalne stosowanie elementu RouteDataRequest CultureProvider z oprogramowaniem pośredniczącym jako filtrami
IStringLocalizer
: używa elementu ResourceManager i ResourceReader do udostępniania zasobów specyficznych dla kultury w czasie wykonywania. Interfejs zawiera indeksator i elementIEnumerable
do zwracania zlokalizowanych ciągów.IHtmlLocalizer
: w przypadku zasobów zawierających kod HTML.- Wyświetlanie i adnotacje danych
- Rozwiązywanie problemów z lokalizacją ASP.NET Core
- Globalizowanie i lokalizowanie aplikacji platformy .NET
- Zasoby w plikach resx
- Microsoft Multilingual App Toolkit
- Lokalizacja i typy ogólne
Przez Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana i Hisham Bin Ateya
Wielojęzyczna witryna internetowa umożliwia witrynie internetowej dotarcie do szerszej grupy odbiorców. ASP.NET Core udostępnia usługi i oprogramowanie pośredniczące do lokalizowania w różnych językach i kulturach.
Terminy
- Globalizacja (G11N): proces tworzenia aplikacji obsługuje różne języki i regiony. Skrót pochodzi od pierwszych i ostatnich liter oraz liczby liter między nimi.
- Lokalizacja (L10N): proces dostosowywania zglobalizowanej aplikacji dla określonych języków i regionów.
- Internationalization (I18N): Globalizacja i lokalizacja.
- Kultura: język i, opcjonalnie, region.
- Kultura neutralna: kultura, która ma określony język, ale nie region (na przykład "en", "es").
- Określona kultura: kultura z określonym językiem i regionem (na przykład "en-US", "en-GB", "es-CL").
- Kultura nadrzędna: neutralna kultura zawierająca określoną kulturę (na przykład "en" jest kulturą nadrzędną "en-US" i "en-GB").
- Ustawienia regionalne: ustawienia regionalne są takie same jak kultura.
Kody języków i krajów/regionów
Format RFC 4646 dla nazwy kultury to <language code>-<country/region code>
, gdzie <language code>
identyfikuje język i <country/region code>
identyfikuje podkulturę. Na przykład es-CL
w przypadku języka hiszpańskiego (Chile), en-US
angielskiego (Stany Zjednoczone) i en-AU
angielskiego (Australia). RFC 4646 to kombinacja dwuliterowego dwuliterowego kodu kultury ISO 639 skojarzonego z językiem i dwuliterowego kodu subkultury ISO 3166 skojarzonego z krajem lub regionem. Aby uzyskać więcej informacji, zobacz System.Globalization.CultureInfo.
Zadania lokalizowania aplikacji
Globalizacja i lokalizowanie aplikacji obejmuje następujące zadania:
- Utwórz lokalną zawartość aplikacji ASP.NET Core.
- Udostępnianie zlokalizowanych zasobów dla kultur, które obsługuje aplikacja
- Implementowanie strategii wybierania kultury dla każdego żądania
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Dodatkowe zasoby
- Lokalizacja zawartości aplikacji ASP.NET Core
- Udostępnianie zlokalizowanych zasobów dla języków i kultur w aplikacji ASP.NET Core
- Strategie wybierania języka i kultury w zlokalizowanej aplikacji ASP.NET Core
- Rozwiązywanie problemów z lokalizacją ASP.NET Core
- Globalizowanie i lokalizowanie aplikacji platformy .NET
- Localization.StarterWeb projektu użytego w artykule.
- Zasoby w plikach resx
- Microsoft Multilingual App Toolkit
- Lokalizacja i typy ogólne
Przez Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana i Hisham Bin Ateya
Wielojęzyczna witryna internetowa umożliwia witrynie dotarcie do szerszej grupy odbiorców. ASP.NET Core udostępnia usługi i oprogramowanie pośredniczące do lokalizowania w różnych językach i kulturach.
Internacjonalizacja obejmuje System.Globalization i lokalizację. Globalizacja to proces projektowania aplikacji obsługujących różne kultury. Globalizacja dodaje obsługę danych wejściowych, wyświetlania i danych wyjściowych zdefiniowanego zestawu skryptów języka odnoszących się do określonych obszarów geograficznych.
Lokalizacja to proces dostosowywania zglobalizowanej aplikacji, która została już przetworzona pod kątem lokalizacji, do określonej kultury/ustawień regionalnych. Aby uzyskać więcej informacji, zobacz Warunki globalizacji i lokalizacji na końcu tego dokumentu.
Lokalizacja aplikacji obejmuje następujące elementy:
- Lokalizuj zawartość aplikacji
- Udostępnianie zlokalizowanych zasobów dla obsługiwanych języków i kultur
- Implementowanie strategii wybierania języka/kultury dla każdego żądania
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Lokalizuj zawartość aplikacji
IStringLocalizer zostały IStringLocalizer<T> zaprojektowane tak, aby zwiększyć produktywność podczas tworzenia zlokalizowanych aplikacji. IStringLocalizer
używa elementów ResourceManager i ResourceReader do udostępniania zasobów specyficznych dla kultury w czasie wykonywania. Interfejs zawiera indeksator i element IEnumerable
do zwracania zlokalizowanych ciągów. IStringLocalizer
Program nie wymaga przechowywania domyślnych ciągów językowych w pliku zasobu. Możesz opracować aplikację przeznaczoną do lokalizacji i nie trzeba tworzyć plików zasobów na wczesnym etapie programowania. Poniższy kod pokazuje, jak opakowować ciąg "About Title" (Informacje o tytule) dla lokalizacji.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
namespace Localization.Controllers
{
[Route("api/[controller]")]
public class AboutController : Controller
{
private readonly IStringLocalizer<AboutController> _localizer;
public AboutController(IStringLocalizer<AboutController> localizer)
{
_localizer = localizer;
}
[HttpGet]
public string Get()
{
return _localizer["About Title"];
}
}
}
W poprzednim kodzie implementacja IStringLocalizer<T>
pochodzi z wstrzykiwania zależności. Jeśli zlokalizowana wartość "About Title" (Informacje o tytule) nie zostanie znaleziona, zostanie zwrócony klucz indeksatora, czyli ciąg "About Title" (Informacje o tytule). Możesz pozostawić domyślne ciągi literału języka w aplikacji i opakowować je w lokalizatorze, aby skoncentrować się na tworzeniu aplikacji. Tworzysz aplikację przy użyciu języka domyślnego i przygotowujesz ją do kroku lokalizacji bez uprzedniego utworzenia domyślnego pliku zasobu. Alternatywnie możesz użyć tradycyjnego podejścia i podać klucz do pobrania domyślnego ciągu języka. Dla wielu deweloperów nowy przepływ pracy nie ma domyślnego pliku resx języka i po prostu zawijanie literałów ciągu może zmniejszyć obciążenie związane z lokalizacją aplikacji. Inni deweloperzy wolą tradycyjny przepływ pracy, ponieważ może ułatwić pracę z dłuższymi literałami ciągów i ułatwić aktualizowanie zlokalizowanych ciągów.
Użyj implementacji IHtmlLocalizer<T>
dla zasobów zawierających kod HTML. IHtmlLocalizer
Html koduje argumenty sformatowane w ciągu zasobu, ale nie koduje samego ciągu zasobu w języku HTML. W przykładzie wyróżnionym poniżej tylko wartość parametru name
jest zakodowana w formacie HTML.
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
namespace Localization.Controllers
{
public class BookController : Controller
{
private readonly IHtmlLocalizer<BookController> _localizer;
public BookController(IHtmlLocalizer<BookController> localizer)
{
_localizer = localizer;
}
public IActionResult Hello(string name)
{
ViewData["Message"] = _localizer["<b>Hello</b><i> {0}</i>", name];
return View();
}
Uwaga
Ogólnie rzecz biorąc, lokalizuj tylko tekst, a nie HTML.
Na najniższym poziomie można wydostać się IStringLocalizerFactory
z wstrzykiwania zależności:
{
public class TestController : Controller
{
private readonly IStringLocalizer _localizer;
private readonly IStringLocalizer _localizer2;
public TestController(IStringLocalizerFactory factory)
{
var type = typeof(SharedResource);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create(type);
_localizer2 = factory.Create("SharedResource", assemblyName.Name);
}
public IActionResult About()
{
ViewData["Message"] = _localizer["Your application description page."]
+ " loc 2: " + _localizer2["Your application description page."];
Powyższy kod demonstruje każdą z dwóch metod tworzenia fabryki.
Zlokalizowane ciągi można podzielić na partycje według kontrolera, obszaru lub tylko jednego kontenera. W przykładowej aplikacji fikcyjna klasa o nazwie SharedResource
jest używana dla zasobów udostępnionych.
// Dummy class to group shared resources
namespace Localization
{
public class SharedResource
{
}
}
Niektórzy deweloperzy używają Startup
klasy do przechowywania ciągów globalnych lub udostępnionych. W poniższym InfoController
przykładzie używane są lokalizatory i SharedResource
:
public class InfoController : Controller
{
private readonly IStringLocalizer<InfoController> _localizer;
private readonly IStringLocalizer<SharedResource> _sharedLocalizer;
public InfoController(IStringLocalizer<InfoController> localizer,
IStringLocalizer<SharedResource> sharedLocalizer)
{
_localizer = localizer;
_sharedLocalizer = sharedLocalizer;
}
public string TestLoc()
{
string msg = "Shared resx: " + _sharedLocalizer["Hello!"] +
" Info resx " + _localizer["Hello!"];
return msg;
}
Wyświetlanie lokalizacji
Usługa IViewLocalizer
udostępnia zlokalizowane ciągi dla widoku. Klasa ViewLocalizer
implementuje ten interfejs i znajduje lokalizację zasobu ze ścieżki pliku widoku. Poniższy kod pokazuje, jak używać domyślnej implementacji programu IViewLocalizer
:
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<p>@Localizer["Use this area to provide additional information."]</p>
Domyślna implementacja IViewLocalizer
pliku zasobu znajduje plik na podstawie nazwy pliku widoku. Nie ma możliwości użycia globalnego pliku zasobów udostępnionych. ViewLocalizer
implementuje lokalizator przy użyciu metody IHtmlLocalizer
, więc Razor nie koduje zlokalizowanego ciągu HTML. Parametry można sparametryzować i IViewLocalizer
kodować parametry w formacie HTML, ale nie ciąg zasobu. Rozważmy następujące Razor znaczniki:
@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]
Francuski plik zasobów może zawierać następujące elementy:
Key | Wartość |
---|---|
<i>Hello</i> <b>{0}!</b> |
<i>Bonjour</i> <b>{0} !</b> |
Renderowany widok będzie zawierać znaczniki HTML z pliku zasobu.
Uwaga
Ogólnie rzecz biorąc, lokalizuj tylko tekst, a nie HTML.
Aby użyć udostępnionego pliku zasobów w widoku, należy wstrzyknąć IHtmlLocalizer<T>
polecenie :
@using Microsoft.AspNetCore.Mvc.Localization
@using Localization.Services
@inject IViewLocalizer Localizer
@inject IHtmlLocalizer<SharedResource> SharedLocalizer
@{
ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h1>@SharedLocalizer["Hello!"]</h1>
Lokalizacja danychAnnotations
Komunikaty o błędach DataAnnotations są zlokalizowane za pomocą polecenia IStringLocalizer<T>
. Korzystając z opcji ResourcesPath = "Resources"
, komunikaty o błędach w pliku RegisterViewModel
mogą być przechowywane w jednej z następujących ścieżek:
- Resources/ViewModels.Account.RegisterViewModel.fr.resx
- Resources/ViewModels/Account/RegisterViewModel.fr.resx
public class RegisterViewModel
{
[Required(ErrorMessage = "The Email field is required.")]
[EmailAddress(ErrorMessage = "The Email field is not a valid email address.")]
[Display(Name = "Email")]
public string Email { get; set; }
[Required(ErrorMessage = "The Password field is required.")]
[StringLength(8, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
Atrybuty niewalidacyjne są zlokalizowane.
Używanie jednego ciągu zasobu dla wielu klas
Poniższy kod pokazuje, jak używać jednego ciągu zasobu do sprawdzania poprawności atrybutów z wieloma klasami:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddDataAnnotationsLocalization(options => {
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResource));
});
}
W poprzednim kodzie SharedResource
jest klasą odpowiadającą resx, w której są przechowywane komunikaty sprawdzania poprawności. W przypadku tego podejścia adnotacje danych będą używać tylko elementu SharedResource
, a nie zasobu dla każdej klasy.
Udostępnianie zlokalizowanych zasobów dla obsługiwanych języków i kultur
Obsługiwanecultures i SupportedUICultures
ASP.NET Core umożliwia określenie dwóch wartości kultury i SupportedCultures SupportedUICultures. Obiekt CultureInfo dla SupportedCultures
określa wyniki funkcji zależnych od kultury, takich jak data, godzina, liczba i formatowanie waluty. SupportedCultures
Określa również kolejność sortowania tekstu, konwencji wielkości liter i porównań ciągów. Aby uzyskać więcej informacji na temat sposobu uzyskiwania kultury przez serwer, zobacz CultureInfo.CurrentCulture i CultureInfo.CurrentUICulture. Określa SupportedUICultures
, które przetłumaczone ciągi (z .resx
plików) są sprawdzane przez element ResourceManager. Wyszukuje ResourceManager
ciągi specyficzne dla kultury, które są określane przez CurrentUICulture
. Każdy wątek na platformie .NET ma CurrentCulture
obiekty i CurrentUICulture
. Platforma sprawdza te wartości podczas renderowania funkcji zależnych od kultury. Jeśli kultura bieżącego wątku jest ustawiona na en-US
(angielski, Stany Zjednoczone), wyświetla wartość Thursday, February 18, 2016
; ale jeśli CurrentCulture
ustawiono es-ES
wartość (hiszpański, Hiszpania), DateTime.Now.ToLongDateString()
dane wyjściowe to jueves, 18 de febrero de 2016
.
Pliki zasobów
Plik zasobu jest przydatnym mechanizmem oddzielania ciągów lokalizowalnych od kodu. Przetłumaczone ciągi dla języka innego niż domyślny są izolowane w plikach zasobów resx . Na przykład możesz utworzyć hiszpański plik zasobów o nazwie Welcome.es.resx zawierający przetłumaczone ciągi. "es" to kod języka hiszpańskiego. Aby utworzyć ten plik zasobów w programie Visual Studio:
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder, który będzie zawierać plik> zasobu Dodaj>nowy element.
W polu Wyszukaj zainstalowane szablony wprowadź "zasób" i nadaj plikowi nazwę.
Wprowadź wartość klucza (ciąg natywny) w kolumnie Nazwa i przetłumaczony ciąg w kolumnie Wartość .
Program Visual Studio wyświetla plik Welcome.es.resx .
Nazewnictwo plików zasobów
Zasoby są nazwane jako pełna nazwa typu ich klasy minus nazwa zestawu. Na przykład zasób francuski w projekcie, którego głównym zestawem jest LocalizationWebsite.Web.dll
klasa LocalizationWebsite.Web.Startup
, będzie mieć nazwę Startup.fr.resx. Zasób klasy LocalizationWebsite.Web.Controllers.HomeController
ma nazwę Controllers.HomeController.fr.resx. Jeśli przestrzeń nazw klasy docelowej nie jest taka sama jak nazwa zestawu, potrzebna będzie pełna nazwa typu. Na przykład w przykładowym projekcie zasób dla typu ExtraNamespace.Tools
będzie miał nazwę ExtraNamespace.Tools.fr.resx.
W przykładowym projekcie ConfigureServices
metoda ustawia ResourcesPath
wartość "Resources", więc ścieżka względna projektu dla home francuskiego pliku zasobu kontrolera to Resources/Controllers.HomeController.fr.resx. Alternatywnie można użyć folderów do organizowania plików zasobów. home W przypadku kontrolera ścieżka to Resources/Controllers/HomeController.fr.resx. Jeśli nie używasz ResourcesPath
tej opcji, plik resx zostanie wyświetlony w katalogu podstawowym projektu. Plik zasobu będzie HomeController
miał nazwę Controllers.HomeController.fr.resx. Wybór konwencji nazewnictwa kropki lub ścieżki zależy od sposobu organizowania plików zasobów.
Nazwa zasobu | Nazewnictwo kropki lub ścieżki |
---|---|
Resources/Controllers.HomeController.fr.resx | Kropka |
Resources/Controllers/HomeController.fr.resx | Ścieżka |
Pliki zasobów używane @inject IViewLocalizer
w Razor widokach są zgodne z podobnym wzorcem. Plik zasobu widoku może mieć nazwę przy użyciu nazewnictwa kropki lub nazewnictwa ścieżek. Razor wyświetl pliki zasobów naśladują ścieżkę skojarzonego pliku widoku. Zakładając, że ustawiliśmy ResourcesPath
wartość "Resources", francuski plik zasobów skojarzony z widokiem może być jednym z Views/Home/About.cshtml
następujących elementów:
Resources/Views/Home/About.fr.resx
Resources/Views.Home. About.fr.resx
Jeśli nie używasz ResourcesPath
tej opcji, plik resx dla widoku będzie znajdować się w tym samym folderze co widok.
RootNamespaceAttribute
Atrybut RootNamespaceAttribute udostępnia przestrzeń nazw głównego zestawu, gdy główna przestrzeń nazw zestawu jest inna niż nazwa zestawu.
Ostrzeżenie
Taka sytuacja może wystąpić, gdy nazwa projektu nie jest prawidłowym identyfikatorem platformy .NET. Na przykład my-project-name.csproj
użyje głównej przestrzeni nazw my_project_name
i nazwy my-project-name
zestawu prowadzącego do tego błędu.
Jeśli główna przestrzeń nazw zestawu różni się od nazwy zestawu:
- Lokalizacja nie działa domyślnie.
- Lokalizacja kończy się niepowodzeniem ze względu na sposób wyszukiwania zasobów w zestawie.
RootNamespace
to wartość czasu kompilacji, która nie jest dostępna dla procesu wykonywania.
Jeśli parametr RootNamespace
różni się od AssemblyName
elementu , uwzględnij następujące wartości w AssemblyInfo.cs
pliku (z wartościami parametrów zastąpionymi rzeczywistymi wartościami):
using System.Reflection;
using Microsoft.Extensions.Localization;
[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]
Powyższy kod umożliwia pomyślne rozwiązanie plików resx.
Zachowanie rezerwowe kultury
Podczas wyszukiwania zasobu lokalizacja angażuje się w "rezerwowanie kultury". Począwszy od żądanej kultury, jeśli nie zostanie znaleziona, przywraca kulturę nadrzędną tej kultury. Na bok CultureInfo.Parent właściwość reprezentuje kulturę nadrzędną. Zwykle (ale nie zawsze) oznacza usunięcie oznaczenia narodowego z ISO. Na przykład dialekt hiszpański mówiony w Meksyku to "es-MX". Ma element nadrzędny "es" — hiszpański, nieokreślony dla dowolnego kraju.
Załóżmy, że witryna otrzymuje żądanie zasobu "Powitanie" przy użyciu kultury "fr-CA". System lokalizacji wyszukuje następujące zasoby w kolejności i wybiera pierwsze dopasowanie:
- Welcome.fr-CA.resx
- Witamy.fr.resx
- Welcome.resx (jeśli
NeutralResourcesLanguage
jest to "fr-CA")
Jeśli na przykład usuniesz projektant kultury ".fr" i masz ustawioną kulturę na język francuski, domyślny plik zasobu jest odczytywany, a ciągi są zlokalizowane. Usługa Resource Manager wyznacza domyślny lub rezerwowy zasób, jeśli nic nie spełnia żądanej kultury. Jeśli chcesz po prostu zwrócić klucz, gdy brakuje zasobu dla żądanej kultury, nie musisz mieć domyślnego pliku zasobu.
Generowanie plików zasobów za pomocą programu Visual Studio
Jeśli utworzysz plik zasobu w programie Visual Studio bez kultury w nazwie pliku (na przykład Welcome.resx), program Visual Studio utworzy klasę języka C# z właściwością dla każdego ciągu. Zwykle nie jest to to, czego potrzebujesz z ASP.NET Core. Zazwyczaj nie masz domyślnego pliku zasobu resx (pliku resx bez nazwy kultury). Zalecamy utworzenie pliku resx o nazwie kultury (na przykład Welcome.fr.resx). Podczas tworzenia pliku resx o nazwie kultury program Visual Studio nie wygeneruje pliku klasy.
Dodawanie innych kultur
Każda kombinacja języka i kultury (inna niż język domyślny) wymaga unikatowego pliku zasobu. Pliki zasobów dla różnych kultur i ustawień regionalnych można tworzyć, tworząc nowe pliki zasobów, w których kody języka ISO są częścią nazwy pliku (na przykład en-us, fr-ca i en-gb). Te kody ISO są umieszczane między nazwą pliku a rozszerzeniem pliku resx , jak w pliku Welcome.es-MX.resx (Hiszpański/Meksyk).
Implementowanie strategii wybierania języka/kultury dla każdego żądania
Konfigurowanie lokalizacji
Lokalizacja jest skonfigurowana w metodzie Startup.ConfigureServices
:
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
AddLocalization
dodaje usługi lokalizacji do kontenera usług. Powyższy kod ustawia również ścieżkę zasobów na "Zasoby".AddViewLocalization
Dodaje obsługę zlokalizowanych plików widoku. W tym przykładowym widoku lokalizacja jest oparta na sufiksie pliku widoku. Na przykład "fr" wIndex.fr.cshtml
pliku.AddDataAnnotationsLocalization
Dodaje obsługę zlokalizowanychDataAnnotations
komunikatów weryfikacji za pośrednictwemIStringLocalizer
abstrakcji.
Oprogramowanie pośredniczące lokalizacji
Bieżąca kultura żądania jest ustawiona w oprogramowania pośredniczącego lokalizacji. Oprogramowanie pośredniczące lokalizacji jest włączone w metodzie Startup.Configure
. Oprogramowanie pośredniczące lokalizacji musi być skonfigurowane przed każdym oprogramowaniem pośredniczącym, które może sprawdzać kulturę żądania (na przykład app.UseMvcWithDefaultRoute()
). Oprogramowanie pośredniczące lokalizacji musi pojawić się po użyciu oprogramowania pośredniczącego routingu, jeśli jest używany program RouteDataRequestCultureProvider. Aby uzyskać więcej informacji na temat kolejności oprogramowania pośredniczącego, zobacz ASP.NET Core Middleware.
var supportedCultures = new[] { "en-US", "fr" };
var localizationOptions = new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Jeśli chcesz zobaczyć komentarze kodu przetłumaczone na języki inne niż angielski, poinformuj nas o tym w tym problemie z dyskusją w usłudze GitHub.
UseRequestLocalization
inicjuje RequestLocalizationOptions
obiekt. Na każdym żądaniu lista RequestCultureProvider
w obiekcie RequestLocalizationOptions
jest wyliczana, a pierwszy dostawca, który może pomyślnie określić kulturę żądania, jest używana. Domyślni RequestLocalizationOptions
dostawcy pochodzą z klasy:
QueryStringRequestCultureProvider
CookieRequestCultureProvider
AcceptLanguageHeaderRequestCultureProvider
Lista domyślna przechodzi od najbardziej specyficznych do najmniej określonych. W dalszej części artykułu zobaczymy, jak można zmienić kolejność, a nawet dodać niestandardowego dostawcę kultury. Jeśli żaden z dostawców nie może określić kultury żądania, DefaultRequestCulture
zostanie użyty.
QueryStringRequestCultureProvider
Niektóre aplikacje będą używać ciągu zapytania, aby ustawić CultureInfowartość . W przypadku aplikacji korzystających z metody nagłówka cookie lub Accept-Language dodanie ciągu zapytania do adresu URL jest przydatne do debugowania i testowania kodu. Domyślnie element QueryStringRequestCultureProvider
jest zarejestrowany jako pierwszy dostawca lokalizacji na RequestCultureProvider
liście. Należy przekazać parametry culture
ciągu zapytania i ui-culture
. W poniższym przykładzie ustawiono konkretną kulturę (język i region) na hiszpański/Meksyk:
http://localhost:5000/?culture=es-MX&ui-culture=es-MX
Jeśli przekażesz tylko jedną z dwóch wartości (culture
lub ui-culture
), dostawca ciągu zapytania ustawi obie wartości przy użyciu przekazanej wartości. Na przykład ustawienie tylko kultury spowoduje ustawienie zarówno wartości , jak Culture
i UICulture
:
http://localhost:5000/?culture=es-MX
CookieRequestCultureProvider
Aplikacje produkcyjne często udostępniają mechanizm ustawiania kultury przy użyciu kultury cookieASP.NET Core. Użyj metody , MakeCookieValue
aby utworzyć element cookie.
Zwraca CookieRequestCultureProvider
DefaultCookieName
domyślną cookie nazwę używaną do śledzenia preferowanych informacji o kulturze użytkownika. Domyślna cookie nazwa to .AspNetCore.Culture
.
Format cookie to c=%LANGCODE%|uic=%LANGCODE%
, gdzie c
to Culture
i uic
ma UICulture
wartość , na przykład:
c=en-UK|uic=en-US
Jeśli określisz tylko jedną z informacji o kulturze i kultury interfejsu użytkownika, określona kultura będzie używana zarówno dla informacji o kulturze, jak i kultury interfejsu użytkownika.
Nagłówek HTTP accept-language
Nagłówek Accept-Language jest ustawiany w większości przeglądarek i pierwotnie miał na celu określenie języka użytkownika. To ustawienie wskazuje, które ustawienia przeglądarki zostały ustawione do wysyłania lub dziedziczone z bazowego systemu operacyjnego. Nagłówek HTTP accept-language z żądania przeglądarki nie jest nieomylnym sposobem wykrywania preferowanego języka użytkownika (zobacz Ustawianie preferencji języka w przeglądarce). Aplikacja produkcyjna powinna zawierać sposób dostosowywania wybranej kultury przez użytkownika.
Ustawianie nagłówka HTTP accept-language w programie IE
Z ikony koła zębatego naciśnij pozycję Opcje internetowe.
Naciśnij pozycję Języki.
Naciśnij pozycję Ustaw preferencje językowe.
Naciśnij pozycję Dodaj język.
Dodaj język.
Naciśnij język, a następnie naciśnij pozycję Przenieś w górę.
Używanie dostawcy niestandardowego
Załóżmy, że chcesz umożliwić klientom przechowywanie ich języka i kultury w bazach danych. Możesz napisać dostawcę, aby wyszukać te wartości dla użytkownika. Poniższy kod pokazuje, jak dodać dostawcę niestandardowego:
private const string enUSCulture = "en-US";
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo(enUSCulture),
new CultureInfo("fr")
};
options.DefaultRequestCulture = new RequestCulture(culture: enUSCulture, uiCulture: enUSCulture);
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context =>
{
// My custom request culture logic
return await Task.FromResult(new ProviderCultureResult("en"));
}));
});
Służy RequestLocalizationOptions
do dodawania lub usuwania dostawców lokalizacji.
Zmiana kolejności dostawców kultury żądań
RequestLocalizationOptions Ma trzech domyślnych dostawców kultury żądań: QueryStringRequestCultureProvider, CookieRequestCultureProvideri AcceptLanguageHeaderRequestCultureProvider. Użyj właściwości [RequestLocalizationOptions.RequestCultureProviders
]](xref:Microsoft.AspNetCore.Builder.RequestLocalizationOptions.RequestCultureProviders), aby zmienić kolejność tych dostawców, jak pokazano poniżej:
app.UseRequestLocalization(options =>
{
var questStringCultureProvider = options.RequestCultureProviders[0];
options.RequestCultureProviders.RemoveAt(0);
options.RequestCultureProviders.Insert(1, questStringCultureProvider);
});
W poprzednim przykładzie kolejność QueryStringRequestCultureProvider
i CookieRequestCultureProvider
jest przełączana, więc RequestLocalizationMiddleware
najpierw wyszukuje kultury z plików cookie, a następnie ciąg zapytania.
Jak wspomniano wcześniej, dodaj dostawcę niestandardowego, za pomocą AddInitialRequestCultureProvider którego ustawiono kolejność na 0
, więc ten dostawca ma pierwszeństwo przed innymi.
Programowe ustawianie kultury
Ten przykładowy projekt Localization.StarterWeb w witrynie GitHub zawiera interfejs użytkownika do ustawienia elementu Culture
. Plik Views/Shared/_SelectLanguagePartial.cshtml
umożliwia wybranie kultury z listy obsługiwanych kultur:
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options
@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var cultureItems = LocOptions.Value.SupportedUICultures
.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
.ToList();
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}
<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
<form id="selectLanguage" asp-controller="Home"
asp-action="SetLanguage" asp-route-returnUrl="@returnUrl"
method="post" class="form-horizontal" role="form">
<label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label> <select name="culture"
onchange="this.form.submit();"
asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
</select>
</form>
</div>
Plik Views/Shared/_SelectLanguagePartial.cshtml
zostanie dodany do footer
sekcji pliku układu, aby był dostępny dla wszystkich widoków:
<div class="container body-content" style="margin-top:60px">
@RenderBody()
<hr>
<footer>
<div class="row">
<div class="col-md-6">
<p>© @System.DateTime.Now.Year - Localization</p>
</div>
<div class="col-md-6 text-right">
@await Html.PartialAsync("_SelectLanguagePartial")
</div>
</div>
</footer>
</div>
Metoda SetLanguage
ustawia kulturę cookie.
[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
);
return LocalRedirect(returnUrl);
}
Nie można podłączyć kodu do przykładowego _SelectLanguagePartial.cshtml
kodu dla tego projektu. Projekt Localization.StarterWeb w witrynie GitHub zawiera kod umożliwiający przepływ RequestLocalizationOptions
do częściowego Razor kontenera wstrzykiwania zależności.
Modelowanie powiązania danych trasy i ciągów zapytań
Zobacz Zachowanie globalizacji danych trasy powiązania modelu i ciągów zapytań.
Terminy globalizacji i lokalizacji
Proces lokalizowania aplikacji wymaga również podstawowego zrozumienia odpowiednich zestawów znaków powszechnie używanych w nowoczesnym tworzeniu oprogramowania oraz zrozumienia związanych z nimi problemów. Mimo że wszystkie komputery przechowują tekst jako liczby (kody), różne systemy przechowują ten sam tekst przy użyciu różnych liczb. Proces lokalizacji odnosi się do tłumaczenia interfejsu użytkownika aplikacji dla określonej kultury/ustawień regionalnych.
Lokalizowanie to pośredni proces sprawdzania, czy globalizowana aplikacja jest gotowa do lokalizacji.
Format RFC 4646 dla nazwy kultury to <languagecode2>-<country/regioncode2>
, gdzie <languagecode2>
jest kodem języka i <country/regioncode2>
jest kodem subkultury. Na przykład es-CL
w przypadku języka hiszpańskiego (Chile), en-US
angielskiego (Stany Zjednoczone) i en-AU
angielskiego (Australia). RFC 4646 to kombinacja dwuliterowego dwuliterowego kodu kultury ISO 639 skojarzonego z językiem i dwuliterowego kodu subkultury ISO 3166 skojarzonego z krajem lub regionem. Aby uzyskać więcej informacji, zobacz System.Globalization.CultureInfo.
Internacjonalizacja jest często skracana do "I18N". Skrót przyjmuje pierwsze i ostatnie litery i liczbę liter między nimi, więc 18 oznacza liczbę liter między pierwszym "I" a ostatnim "N". Dotyczy to również globalizacji (G11N) i lokalizacji (L10N).
Warunki:
- Globalizacja (G11N): proces tworzenia aplikacji obsługuje różne języki i regiony.
- Lokalizacja (L10N): proces dostosowywania aplikacji dla danego języka i regionu.
- Internationalization (I18N): opisuje zarówno globalizację, jak i lokalizację.
- Kultura: jest to język i, opcjonalnie, region.
- Kultura neutralna: kultura, która ma określony język, ale nie region. (na przykład "en", "es")
- Konkretna kultura: kultura, która ma określony język i region. (na przykład "en-US", "en-GB", "es-CL")
- Kultura nadrzędna: neutralna kultura zawierająca konkretną kulturę. (na przykład "en" jest kulturą nadrzędną "en-US" i "en-GB")
- Ustawienia regionalne: ustawienia regionalne są takie same jak kultura.
Uwaga
Może nie być możliwe wprowadzenie przecinków dziesiętnych w polach dziesiętnych. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla przecinka dziesiętnego i formatów dat innych niż angielskie stany USA, należy wykonać kroki w celu globalizacji aplikacji. Zobacz ten komentarz usługi GitHub 4076 , aby uzyskać instrukcje dotyczące dodawania przecinka dziesiętnego.
Uwaga
Przed ASP.NET Core 3.0 aplikacje internetowe zapisują jeden dziennik typu LogLevel.Warning
na żądanie, jeśli żądana kultura nie jest obsługiwana. Rejestrowanie jedno na żądanie może sprawić, LogLevel.Warning
że duże pliki dziennika będą zawierać nadmiarowe informacje. To zachowanie zostało zmienione w ASP.NET 3.0. Zapisuje RequestLocalizationMiddleware
dziennik typu LogLevel.Debug
, co zmniejsza rozmiar dzienników produkcyjnych.