以某种方式,您必须将所选区域性绑定到用户,因此如果您不想在URL中携带它,则必须找到另一种方法在请求之间保留此信息。您的选择:
正常情况下
使用cookie存储语言首选项是一个完美的选择
.
在ASP.NET内核中
为当前请求检索和设置区域性的最佳位置是中间件
. 幸运的是,框架包含一个,可以通过调用
app.UseRequestLocalization(…)
在你的
启动。配置
方法。默认情况下,此中间件将尝试按此顺序从请求URL、cookies和接受语言HTTP头中获取当前区域性。
因此,总结一下:您需要利用请求本地化中间件,将用户的文化偏好存储在一个cookie中,格式如下
c=%LANGCODE%|uic=%LANGCODE%
(例如。
c=en-US|uic=en-US
)你就完了。
你可以在
this MSDN article
.
奖金:
然后它将这些字符串资源映射到ViewData,我的视图就是从ViewData
以正确的语言获取文本(不确定这是否是最好的
方法,但现在我不想在这上面花更多的时间)。
将本地化文本传递到ViewData中的视图是繁琐且容易出错的。在ASP.NET内核中,我们有
view localization
为此目的。你只需要注射
IViewLocalizer公司
组件,以获得访问本地化文本资源的方便方法。(在引擎盖下面
IViewLocalizer公司
使用
IStringLocalizer公司
.)
关于编辑2
MakeCookieValue方法未生成任何.AspNetCore.Culture cookie
CookierEquiestCultureProvider.MakeCookieValue
方法只是生成正确格式的cookie值的助手。它只返回一个字符串,仅此而已。但即使它是要将cookie添加到响应中,调用它
启动。配置
当您在那里配置请求管道时将完全错误。(在我看来,你对ASP.NET内核中的请求处理和中间件有些困惑,所以我建议你研究一下
this topic
.)
所以正确的
请求管道的设置
是这样的:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
#region Localization
// REMARK: you may refactor this into a separate method as it's better to avoid long methods with regions
var supportedCultures = new[]
{
new CultureInfo(defaultCultureName),
new CultureInfo("pl-PL")
};
var localizationOptions = new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(defaultCultureName, defaultCultureName),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures,
// you can change the list of providers, if you don't want the default behavior
// e.g. the following line enables to pick up culture ONLY from cookies
RequestCultureProviders = new[] { new CookieRequestCultureProvider() }
};
app.UseRequestLocalization(localizationOptions);
#endregion
app.UseStaticFiles();
app.UseMvc(ConfigureRoutes);
}
(上面一句话:不必登记
请求本地化选项
在DI容器中。)
那你可以吃点
控制器动作
设置区域性cookie:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult SetCulture(string culture, string returnUrl)
{
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
// making cookie valid for the actual app root path (which is not necessarily "/" e.g. if we're behind a reverse proxy)
new CookieOptions { Path = Url.Content("~/") });
return Redirect(returnUrl);
}
最后,一个如何从
看法
:
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Http.Extensions
@{
var httpContext = ViewContext.HttpContext;
var currentCulture = httpContext.Features.Get<IRequestCultureFeature>().RequestCulture.UICulture;
var currentUrl = UriHelper.BuildRelative(httpContext.Request.PathBase, httpContext.Request.Path, httpContext.Request.QueryString);
}
<form asp-action="SetCulture" method="post">
Culture: <input type="text" name="culture" value="@currentCulture">
<input type="hidden" name="returnUrl" value="@currentUrl">
<input type="submit" value="Submit">
</form>
语言设置为PL的Chrome浏览器正确地使用了PL-PL区域性,而Firefox使用的是语言设置为PL-in选项的en-US区域性(尽管注释掉了options.DefaultRequestCulture=
新的请求区域性(defaultCulutreName、defaultCulutreName)行
我怀疑Chrome浏览器在接受语言头中发送了语言首选项,而FF没有。
不知怎的,我的本地化在默认情况下工作,没有使用查询字符串或cookie为应用程序提供区域性,但这不是我希望它工作的方式,因为我对它没有任何控制权
我重复:
默认情况下,此中间件将尝试从请求URL、cookies和
接受语言HTTP头
,按此顺序。
您可以通过更改或替换
RequestLocalizationOptions.RequestCultureProviders
列表。