Globalizacja i lokalizacja w ASP.NET Core

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. W celu uzyskania więcej informacji, zobacz następujący temat: System.Globalization.CultureInfo.

Zadania lokalizowania aplikacji

Globalizacja i lokalizowanie aplikacji obejmuje następujące zadania:

Wyświetl lub pobierz przykładowy kod (jak pobrać)

Dodatkowe zasoby

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. W celu uzyskania więcej informacji, zobacz następujący temat: System.Globalization.CultureInfo.

Zadania lokalizowania aplikacji

Globalizacja i lokalizowanie aplikacji obejmuje następujące zadania:

Wyświetl lub pobierz przykładowy kod (jak pobrać)

Dodatkowe zasoby

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:

  1. Lokalizuj zawartość aplikacji
  2. Udostępnianie zlokalizowanych zasobów dla obsługiwanych języków i kultur
  3. 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 SupportedCulturesSupportedUICultures. 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:

  1. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder, który będzie zawierać plik> zasobu Dodaj>nowy element.

    Nested contextual menu: In Solution Explorer, a contextual menu is open for Resources. A second contextual menu is open for Add showing the New Item command highlighted.

  2. W polu Wyszukaj zainstalowane szablony wprowadź "zasób" i nadaj plikowi nazwę.

    Add New Item dialog

  3. Wprowadź wartość klucza (ciąg natywny) w kolumnie Nazwa i przetłumaczony ciąg w kolumnie Wartość .

    Welcome.es.resx file (the Welcome resource file for Spanish) with the word Hello in the Name column and the word Hola (Hello in Spanish) in the Value column

    Program Visual Studio wyświetla plik Welcome.es.resx .

    Solution Explorer showing the Welcome Spanish (es) resource file

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 dla klasy LocalizationWebsite.Web.Controllers.HomeController będzie miał nazwę Kontrolery.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 francuskiego pliku zasobu kontrolera domu to Resources/Controllers.HomeController.fr.resx. Alternatywnie można użyć folderów do organizowania plików zasobów. W przypadku kontrolera macierzystego ś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 dla elementu HomeController będzie miał nazwę Kontrolery.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
Zasoby/kontrolery.HomeController.fr.resx Dot
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 AssemblyNameelementu , 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" w Index.fr.cshtml pliku.

  • AddDataAnnotationsLocalization Dodaje obsługę zlokalizowanych DataAnnotations komunikatów weryfikacji za pośrednictwem IStringLocalizer 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:

  1. QueryStringRequestCultureProvider
  2. CookieRequestCultureProvider
  3. 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 CookieRequestCultureProviderDefaultCookieName 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 UICulturewartość , 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

  1. Z ikony koła zębatego naciśnij pozycję Opcje internetowe.

  2. Naciśnij pozycję Języki.

    Internet Options

  3. Naciśnij pozycję Ustaw preferencje językowe.

  4. Naciśnij pozycję Dodaj język.

  5. Dodaj język.

  6. 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 szuka kultur z cookiepierwszego, a następnie ciągu 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>&copy; @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. W celu uzyskania więcej informacji, zobacz następujący temat: 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.

Dodatkowe zasoby