Udostępnij za pośrednictwem


Lokalizacja zawartości aplikacji 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.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. 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 Hisham Bin Ateya, Damien Bowden, Bart Calixto i Nadeem Afana

Jednym z zadań lokalizowania aplikacji jest zawijanie zawartości lokalizowalnej za pomocą kodu, który ułatwia zastąpienie tej zawartości dla różnych kultur.

IStringLocalizer

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.

W poniższym przykładzie kodu pokazano, jak opakować 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 preferują tradycyjny przepływ pracy, ponieważ łatwiej jest pracować z długimi literałami ciągów i łatwiej aktualizować zlokalizowane ciągi.

IHtmlLocalizer

Użyj implementacji IHtmlLocalizer<TResource> dla zasobów zawierających kod HTML. IHtmlLocalizer Koduje argumenty HTML sformatowane w ciągu zasobu, ale nie koduje kodu HTML samego ciągu zasobu. W poniższym wyróżnionym kodzie 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.

IStringLocalizerFactory

Na najniższym poziomie IStringLocalizerFactory można pobrać z iniekcji 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."];

        return View();
    }

Powyższy kod demonstruje każdą z dwóch metod tworzenia fabryki.

Współdzielone zasoby

Zlokalizowane ciągi można podzielić na partycje według kontrolera lub obszaru albo mieć tylko jeden kontener. W przykładowej aplikacji klasa znacznika o nazwie SharedResource jest używana dla zasobów udostępnionych. Klasa znacznika nigdy nie jest wywoływana:

// Dummy class to group shared resources

namespace Localization;

public class SharedResource
{
}

W poniższym przykładzie InfoController 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ć, a IViewLocalizer kodowanie HTML parametrów, 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 wartości:

Key Wartość
<i>Hello</i> <b>{0}!</b> <i>Bonjour</i> <b>{0} !</b>

Renderowany widok będzie zawierać znaczniki HTML z pliku zasobu.

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
using System.ComponentModel.DataAnnotations;

namespace Localization.ViewModels.Account;

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.

Jak używać 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:

    services.AddMvc()
        .AddDataAnnotationsLocalization(options => {
            options.DataAnnotationLocalizerProvider = (type, factory) =>
                factory.Create(typeof(SharedResource));
        });

W poprzednim kodzie jest klasą odpowiadającą plikowi resx, SharedResource w którym są przechowywane komunikaty sprawdzania poprawności. W przypadku tego podejścia funkcja DataAnnotations używa SharedResourcetylko elementu , a nie zasobu dla każdej klasy.

Konfigurowanie usług lokalizacji

Usługi lokalizacji są konfigurowane w programie Program.cs:

builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

builder.Services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
  • AddLocalization Dodaje usługi lokalizacji do kontenera usług, w tym implementacje dla IStringLocalizer<T> i IStringLocalizerFactory. Powyższy kod ustawia również ścieżkę zasobów na "Zasoby".

  • AddViewLocalization Dodaje obsługę zlokalizowanych plików widoku. W tym przykładzie lokalizacja widoku 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.

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.

Następne kroki

Lokalizowanie aplikacji obejmuje również następujące zadania:

Dodatkowe zasoby

Przez Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana i Hisham Bin Ateya

Jednym z zadań lokalizowania aplikacji jest zawijanie zawartości lokalizowalnej za pomocą kodu, który ułatwia zastąpienie tej zawartości dla różnych kultur.

IStringLocalizer

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.

W poniższym przykładzie kodu pokazano, jak opakować 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 preferują tradycyjny przepływ pracy, ponieważ łatwiej jest pracować z długimi literałami ciągów i łatwiej aktualizować zlokalizowane ciągi.

IHtmlLocalizer

Użyj implementacji IHtmlLocalizer<T> dla zasobów zawierających kod HTML. IHtmlLocalizer Koduje argumenty HTML sformatowane w ciągu zasobu, ale nie koduje kodu HTML samego ciągu zasobu. W poniższym wyróżnionym kodzie 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.

IStringLocalizerFactory

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.

Współdzielone zasoby

Zlokalizowane ciągi można podzielić na partycje według kontrolera lub obszaru albo mieć tylko jeden kontener. 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 przykładzie InfoController 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ć, a IViewLocalizer kodowanie HTML parametrów, 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 wartości:

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; }
}

W ASP.NET Core MVC 1.1.0 i nowszych atrybuty niewalidacyjne są zlokalizowane.

Jak używać 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 jest klasą odpowiadającą plikowi resx, SharedResource w którym są przechowywane komunikaty sprawdzania poprawności. W przypadku tego podejścia funkcja DataAnnotations używa SharedResourcetylko elementu , a nie zasobu dla każdej klasy.

Konfigurowanie usług lokalizacji

Usługi lokalizacji są konfigurowane 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, w tym implementacje dla IStringLocalizer<T> i IStringLocalizerFactory. Powyższy kod ustawia również ścieżkę zasobów na "Zasoby".

  • AddViewLocalization Dodaje obsługę zlokalizowanych plików widoku. W tym przykładzie lokalizacja widoku 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.

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.

Następne kroki

Lokalizowanie aplikacji obejmuje również następujące zadania:

Dodatkowe zasoby