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.
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 SharedResource
tylko 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>
iIStringLocalizerFactory
. 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średnictwemIStringLocalizer
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:
- Udostępnianie zlokalizowanych zasobów dla języków i kultur obsługiwanych przez aplikację
- Implementowanie strategii wybierania języka/kultury dla każdego żądania
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
- Globalizacja i lokalizacja w 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
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 SharedResource
tylko 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 dlaIStringLocalizer<T>
iIStringLocalizerFactory
. 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" wIndex.fr.cshtml
pliku.AddDataAnnotationsLocalization
Dodaje obsługę zlokalizowanychDataAnnotations
komunikatów weryfikacji za pośrednictwemIStringLocalizer
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:
- Udostępnianie zlokalizowanych zasobów dla języków i kultur obsługiwanych przez aplikację
- Implementowanie strategii wybierania języka/kultury dla każdego żądania
Dodatkowe zasoby
- Globalizacja i lokalizacja w 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