让我对这个问题有一个全面的回答,并描述我在阅读.net核心源代码后是如何想出解决方案的。
在任何进一步的描述之前,首先使用 NuGet Microsoft.Extensions.Localization 安装这个包
你们可能还记得在 asp.net 完整框架中,文化之间的切换非常简单
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
但在 .net 核心中,文化不再与当前线程相关联。 asp.net 核心引擎有一个管道,我们可以在这个管道中添加不同的中间件,所以 RequestLocalizationMiddleware 是用于处理本地化的中间件类,我们可能有多个提供程序,因此它将遍历所有文化提供程序,如 QueryStringRequestCultureProvider ,CookieRequestCultureProvider,AcceptLanguageHeaderRequestCultureProvider,……
只要请求本地化中间件可以从第一个提供者那里获取当前语言环境,它就会忽略其他的并将请求传递给管道中的下一个中间件,因此列表中提供者的顺序非常重要。
我个人更喜欢将文化存储在浏览器cookie中,因此由于CookieRequestCultureProvider不是列表中的第一个文化提供者,我将其移至列表顶部,这部分的配置在Startup.cs中>配置服务如下
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
});
});
让我描述一下上面的代码,我们的应用默认文化是en-US,我们只支持英语、波斯语、德国,所以如果浏览器有不同的语言环境或者你设置语言不是这 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 中添加以下代码 sn-p 用于指定资源路径和其余部分。
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 文件夹中拥有 Views 的资源文件,对于 ViewModels,因为我们将文件夹命名为 Models,请将所有 ViewModels 放在预先创建的文件夹中名称为 Models 的 Web 项目根路径,如果文件夹有其他名称或者您更喜欢其他名称,请不要忘记重命名 Resource 文件夹下的 Models 文件夹。那么你只需要对模型进行注解,例如,用 [DisplayName("User Emailaddress")] 对 ViewModel 属性进行注解,然后在模型内部的相应资源文件中创建资源(文件名必须与模型类名匹配)使用相同的密钥(“用户电子邮件地址”)。
让我们从已经开始的地方结束,我的意思是 CookieRequestCultureProvider。正如我之前所说,我更喜欢将其存储在 cookie 中,但这有点棘手,因为 cookie parsing 与您的预期有些不同,只需在您想要更改文化的地方添加以下代码,只需将 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 核心网络应用程序现已本地化 :)