让我对这个问题有一个全面的回答,并描述我在阅读.net核心源代码后是如何想出解决方案的。
在任何进一步的描述之前,首先使用 NuGet Microsoft.Extensions.Localization安装这个包
你们可能还记得在 asp.net 完整框架中,文化之间的切换非常简单
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
但在 .net 核心中,文化不再与当前线程相关联。asp.net 核心引擎有一个管道,我们可以在这个管道中添加不同的中间件,所以RequestLocalizationMiddleware是处理本地化的中间件类,我们可能有多个提供者,所以它将遍历所有文化提供者,如QueryStringRequestCultureProvider、CookieRequestCultureProvider、AcceptLanguageHeaderRequestCultureProvider,……</p>
一旦请求本地化中间件可以从第一个提供者那里获取当前语言环境,它就会忽略其他提供者并将请求传递给管道中的下一个中间件,因此列表中提供者的顺序非常重要。
我个人更喜欢将文化存储在浏览器 cookie 中,因此由于CookieRequestCultureProvider不是列表中的第一个文化提供者,我将其移至列表顶部,因此 Startup.cs > ConfigureServices 中这部分的配置如下
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("fa-IR"),
new CultureInfo("de-DE")
};
options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
var defaultCookieRequestProvider =
options.RequestCultureProviders.FirstOrDefault(rcp =>
rcp.GetType() == typeof(CookieRequestCultureProvider));
if (defaultCookieRequestProvider != null)
options.RequestCultureProviders.Remove(defaultCookieRequestProvider);
options.RequestCultureProviders.Insert(0,
new CookieRequestCultureProvider()
{
CookieName = ".AspNetCore.Culture",
Options = options
});
});
让我描述一下上面的代码,我们的应用默认文化是美国,我们只支持英语、波斯语、德国,所以如果浏览器有不同的区域设置或者你设置的语言不是这 3 种语言,那么应用必须切换到默认文化。在上面的代码中,我只是从列表中删除 CookieCultureProvider 并将其添加为列表中的第一个提供者(* 我已经描述了它必须是第一个的原因*)。默认的 CookieName 对我有用,您可以根据需要更改它。
不要忘记在 Startup.cs的Configure(IApplicationBuilder app, IHostingEnvironment env)下面添加以下代码
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
到目前为止,一切都很好。要拥有资源文件,您必须指定资源的路径,我在 Web 项目根路径中分别指定 Controller、Views、ViewModels 和 SharedResources 的资源,层次结构如下所示
|-Resoures
|---Controllers
|---Views
|---Models
|---SharedResource.resx
|---SharedResource.fa-IR.resx
|---SharedResource.de-DE.resx
请记住,对于 SharedResource,在 Web 项目根路径中创建一个具有相同名称的空类,我的意思是一个SharedResource.cs,其中包含一个内部具有相同名称的类。
在 Startup.cs 中添加以下代码片段以指定资源路径和其余部分。
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddMvc()
AddViewLocalization(
LanguageViewLocationExpanderFormat.Suffix,
opts => { opts.ResourcesPath = "Resources/Views"; }) // this line is not required, it is just for more clarification
.AddDataAnnotationsLocalization();
使用此配置,例如,当您在控制器中注入IStringLocalizer时,您必须在 Resources > Controllers 文件夹中拥有相应的资源文件(即 HomeController.resx、HomeController.fa-IR.resx、HomeController.de-DE.resx),我们也可以用 分隔路径。(比如说点)在文件名中我的意思是 Resources/Controllers/HomeController.resx 可以是 Resources/Controllers.HomeController.resx 中的一个文件,您必须将 IViewLocalizer 注入视图才能在视图中进行相应的本地化,您必须拥有资源文件Resources/Views 文件夹中的视图,对于 ViewModels,因为我们将文件夹命名为 Models,请将所有 ViewModels 放在 Web 项目根路径中名为 Models 的预先创建的文件夹中,如果文件夹有其他名称或者您更喜欢其他名称,请不要不要忘记重命名 Resource 文件夹下的 Models 文件夹。那么您只需要对模型进行注释,例如,使用 [DisplayName("User Emailaddress"“用户电子邮件地址”)。
让我们从已经开始的地方结束,我的意思是CookieRequestCultureProvider。正如我之前所说,我更喜欢将其存储在 cookie 中,但这有点棘手,因为cookie 解析与您的预期有些不同,只需在您想要更改文化的地方添加下面的代码,只需将 preferedCulture 替换为您的文化偏好
var preferedCulture = "fa-IR"; // get the culture from user, i just mock it here in a variable
if (HttpContext.Response.Cookies.ContainsKey(".AspNetCore.Culture"))
{
HttpContext.Response.Cookies.Delete(".AspNetCore.Culture");
}
HttpContext.Response.Cookies.Append(".AspNetCore.Culture",
$"c={preferedCulture}|uic={preferedCulture}", new CookieOptions {Expires = DateTime.UtcNow.AddYears(1)});
好了,我们的 sp.net 核心网络应用程序现在已经本地化了 :)