讓 ASP.NET Core 應用程式的內容可當地語系化
注意
這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本。
作者:Hisham Bin Ateya、Damien Bowden、Bart Calixto 和 Nadeem Afana
當地語系化應用程式的其中一項工作是使用程式碼包裝可當地語系化的內容,協助為不同的文化特性取代該內容。
IStringLocalizer
IStringLocalizer 和 IStringLocalizer<T> 的設計用意是,提高開發當地語系化應用程式時的生產力。 IStringLocalizer
會使用 ResourceManager 和 ResourceReader,在執行階段提供特定文化特性的資源。 這個介面具有的索引子和 IEnumerable
可傳回當地語系化字串。 IStringLocalizer
不需要您將預設語言字串儲存在資源檔中。 您不必在開發初期建立資源檔,即可開發以當地語系化為目標的應用程式。
下列程式碼範例示範如何包裝 "About Title" 字串以進行當地語系化。
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"];
}
}
在上述程式碼中,IStringLocalizer<T>
實作是來自相依性插入。 如果找不到 "About Title" 的當地語系化值,即會傳回索引子的索引鍵,也就是 "About Title" 字串。
您可以保留應用程式中的預設語言常值字串,並將其包裝在當地語系化工具中,以便專注於開發應用程式。 您不用先建立預設資源檔,即可使用預設語言來開發應用程式,並針對當地語系化步驟進行應用程式的準備。
或者,您可以使用傳統方法,並提供索引鍵以擷取預設語言字串。 對許多開發人員來說,新的工作流程 (單純包裝字串常值而不使用預設語言的 .resx 檔案) 可以降低當地語系化應用程式的額外負荷。 其他開發人員則偏好傳統的工作流程,因為這種方法更便於使用較長的字串常值,且更易於更新當地語系化的字串。
IHtmlLocalizer
若是包含 HTML 的資源,請使用 IHtmlLocalizer<TResource> 實作。 IHtmlLocalizer 會對資源字串中經過格式化的引數進行 HTML 編碼,但不會對資源字串本身進行 HTML 編碼。 在下列醒目提示的程式碼中,只有 name
參數的值會以 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();
}
注意:一般而言,只會將文字當地語系化,而不是 HTML。
IStringLocalizerFactory
在最低層級,可以從相依性插入擷取 IStringLocalizerFactory:
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();
}
上述程式碼示範這兩個 Factory Create 方法。
共用的資源
您可以依據控制器或區域來分割當地語系化的字串,也可以只用一個容器。 在範例應用程式中,針對共用資源使用名為 SharedResource
的標記類別。 永遠不會呼叫標記類別:
// Dummy class to group shared resources
namespace Localization;
public class SharedResource
{
}
下列範例會使用 InfoController
和 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;
}
檢視當地語系化
IViewLocalizer 服務可提供檢視的當地語系化字串。 ViewLocalizer
類別會實作這個介面,並透過檢視檔案路徑來找出資源的位置。 下列程式碼示範如何使用 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>
IViewLocalizer
的預設實作會依據檢視的檔案名稱來找出資源檔。 其中並沒有任何選項可以使用全域共用的資源檔。 ViewLocalizer
會使用 IHtmlLocalizer
來實作當地語系化工具,因此 Razor 不會對當地語系化的字串進行 HTML 編碼。 您可以參數化資源字串,IViewLocalizer
即會對參數 (而不是資源字串) 進行 HTML 編碼。 請考慮下列 Razor 標記:
@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]
法文資源檔可能包含下列值:
Key | 值 |
---|---|
<i>Hello</i> <b>{0}!</b> |
<i>Bonjour</i> <b>{0} !</b> |
轉譯的檢視內容可能包含來自資源檔的 HTML 標記。
一般而言,只會將文字當地語系化,而不是 HTML。
若要在檢視中使用共用的資源檔,請插入 IHtmlLocalizer<T>
:
@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>
DataAnnotations 當地語系化
DataAnnotations 錯誤訊息會使用 IStringLocalizer<T>
來當地語系化。 使用 ResourcesPath = "Resources"
選項時,RegisterViewModel
中的錯誤訊息會儲存在下列路徑之一:
- 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; }
}
無驗證屬性已當地語系化。
如何針對多個類別使用一個資源字串
下列程式碼會示範如何針對含有多個類別的驗證屬性使用同一個資源字串:
services.AddMvc()
.AddDataAnnotationsLocalization(options => {
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResource));
});
在先前的程式碼中,SharedResource
是與儲存驗證訊息的 .resx 檔案對應的類別。 使用這個方法時,DataAnnotations 只會使用 SharedResource
,而不是每個類別的資源。
設定當地語系化服務
當地語系化服務設定於 Program.cs
中:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
AddLocalization 會將當地語系化服務新增至服務容器,包括
IStringLocalizer<T>
和IStringLocalizerFactory
的實作。 上述程式碼也會將資源路徑設為 "Resources"。AddViewLocalization 可支援當地語系化的檢視檔案。 在此範例中,檢視的當地語系化會以檢視檔案的後置詞為依據。 例如
Index.fr.cshtml
檔案中的 "fr"。AddDataAnnotationsLocalization 可支援透過
IStringLocalizer
抽象概念而來的當地語系化DataAnnotations
驗證訊息。
注意
您可能無法在小數欄位中輸入小數逗號。 若要對使用逗號 (",") 作為小數點的非英文地區設定和非英文日期欄位支援 jQuery 驗證,您必須採取將應用程式全球化的步驟。 請參閱此 GitHub 問題 4076,以取得加入十進位逗號的指示。
下一步
當地語系化應用程式也涉及下列工作:
其他資源
- 在 ASP.NET Core 中使用中介軟體作為篩選的 URL 文化特性提供者
- 使用中介軟體作為篩選全域套用 RouteDataRequest CultureProvider
- ASP.NET Core 中的全球化和當地語系化
- 在 ASP.NET Core 應用程式中提供語言和文化特性的當地語系化資源
- 在當地語系化的 ASP.NET Core 應用程式中選取語言和文化特性的策略
- 針對 ASP.NET Core 當地語系化進行疑難排解
- 全球化與當地語系化 .NET 應用程式
- 本文使用的 Localization.StarterWeb 專案。
- .resx 檔案中的資源
- Microsoft 多語應用程式工具組
- 當地語系化和泛型
由 Rick Anderson、Damien Bowden、Bart Calixto、Nadeem Afana 和 Hisham Bin Ateya 提供
當地語系化應用程式的其中一項工作是使用程式碼包裝可當地語系化的內容,協助為不同的文化特性取代該內容。
IStringLocalizer
IStringLocalizer 和 IStringLocalizer<T> 的設計用意是,提高開發當地語系化應用程式時的生產力。 IStringLocalizer
會使用 ResourceManager 和 ResourceReader,在執行階段提供特定文化特性的資源。 這個介面具有的索引子和 IEnumerable
可傳回當地語系化字串。 IStringLocalizer
不需要您將預設語言字串儲存在資源檔中。 您不必在開發初期建立資源檔,即可開發以當地語系化為目標的應用程式。
下列程式碼範例示範如何包裝 "About Title" 字串以進行當地語系化。
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"];
}
}
}
在上述程式碼中,IStringLocalizer<T>
實作是來自相依性插入。 如果找不到 "About Title" 的當地語系化值,即會傳回索引子的索引鍵,也就是 "About Title" 字串。
您可以保留應用程式中的預設語言常值字串,並將其包裝在當地語系化工具中,以便專注於開發應用程式。 您不用先建立預設資源檔,即可使用預設語言來開發應用程式,並針對當地語系化步驟進行應用程式的準備。
或者,您可以使用傳統方法,並提供索引鍵以擷取預設語言字串。 對許多開發人員來說,新的工作流程 (單純包裝字串常值而不使用預設語言的 .resx 檔案) 可以降低當地語系化應用程式的額外負荷。 其他開發人員則偏好傳統的工作流程,因為這種方法更便於使用較長的字串常值,且更易於更新當地語系化的字串。
IHtmlLocalizer
若是包含 HTML 的資源,請使用 IHtmlLocalizer<T>
實作。 IHtmlLocalizer
會對資源字串中經過格式化的引數進行 HTML 編碼,但不會對資源字串本身進行 HTML 編碼。 在下列醒目提示的程式碼中,只有 name
參數的值會以 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();
}
注意
一般而言,只會將文字當地語系化,而不是 HTML。
IStringLocalizerFactory
您可以在最底層的相依性插入中,將 IStringLocalizerFactory
移出:
{
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."];
上述程式碼示範這兩個 Factory Create 方法。
共用的資源
您可以依據控制器或區域來分割當地語系化的字串,也可以只用一個容器。 在範例應用程式中,會針對共用資源使用名為 SharedResource
的虛擬類別。
// Dummy class to group shared resources
namespace Localization
{
public class SharedResource
{
}
}
有些開發人員會使用 Startup
類別來包含全域或共用字串。 下列範例會使用 InfoController
和 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;
}
檢視當地語系化
IViewLocalizer
服務可提供檢視的當地語系化字串。 ViewLocalizer
類別會實作這個介面,並透過檢視檔案路徑來找出資源的位置。 下列程式碼示範如何使用 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>
IViewLocalizer
的預設實作會依據檢視的檔案名稱來找出資源檔。 其中並沒有任何選項可以使用全域共用的資源檔。 ViewLocalizer
會使用 IHtmlLocalizer
來實作當地語系化工具,因此 Razor 不會對當地語系化的字串進行 HTML 編碼。 您可以參數化資源字串,IViewLocalizer
即會對參數 (而不是資源字串) 進行 HTML 編碼。 請考慮下列 Razor 標記:
@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]
法文資源檔可能包含下列值:
Key | 值 |
---|---|
<i>Hello</i> <b>{0}!</b> |
<i>Bonjour</i> <b>{0} !</b> |
轉譯的檢視內容可能包含來自資源檔的 HTML 標記。
注意
一般而言,只會將文字當地語系化,而不是 HTML。
若要在檢視中使用共用的資源檔,請插入 IHtmlLocalizer<T>
:
@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>
DataAnnotations 當地語系化
DataAnnotations 錯誤訊息會使用 IStringLocalizer<T>
來當地語系化。 使用 ResourcesPath = "Resources"
選項時,RegisterViewModel
中的錯誤訊息會儲存在下列路徑之一:
- 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; }
}
在 ASP.NET Core MVC 1.1.0 和更新版本中,系統會將非驗證屬性當地語系化。
如何針對多個類別使用一個資源字串
下列程式碼會示範如何針對含有多個類別的驗證屬性使用同一個資源字串:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddDataAnnotationsLocalization(options => {
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResource));
});
}
在先前的程式碼中,SharedResource
是與儲存驗證訊息的 .resx 檔案對應的類別。 使用這個方法時,DataAnnotations 只會使用 SharedResource
,而不是每個類別的資源。
設定當地語系化服務
當地語系化服務設定於 Startup.ConfigureServices
方法中:
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
AddLocalization
會將當地語系化服務新增至服務容器,包括IStringLocalizer<T>
和IStringLocalizerFactory
的實作。 上述程式碼也會將資源路徑設為 "Resources"。AddViewLocalization
可支援當地語系化的檢視檔案。 在此範例中,檢視的當地語系化會以檢視檔案的後置詞為依據。 例如Index.fr.cshtml
檔案中的 "fr"。AddDataAnnotationsLocalization
可支援透過IStringLocalizer
抽象概念而來的當地語系化DataAnnotations
驗證訊息。
注意
您可能無法在小數欄位中輸入小數逗號。 若要對使用逗號 (",") 作為小數點的非英文地區設定和非英文日期欄位支援 jQuery 驗證,您必須採取將應用程式全球化的步驟。 請參閱此 GitHub 問題 4076,以取得加入十進位逗號的指示。
下一步
當地語系化應用程式也涉及下列工作: