我已经四处寻找,但却无法找到适合我的答案。
我的问题是:如何在控制器方法中设置当前响应的文化。
方案如下。我们有一个Web应用程序的一般区域,它通过cookie来处理文化集,工作正常。
但是,网站的一小部分需要始终使用丹麦语,除非查询参数设置为例如en-GB。
在接收请求的控制器方法中,我将文化更改添加到cookie,但返回的视图仍然以前一种语言显示。然后刷新页面将以正确的语言显示视图,因为cookie现在具有正确的值。
我想要的是除了cookie之外还要更改当前请求的文化,以便以正确的语言显示返回的视图。
我的控制器代码如下:
[Route("{organizationId}/{arrangementId}")]
public IActionResult LandingPage(int organizationId, int arrangementId, [FromQuery] string lang, [FromQuery] bool? allowup)
{
if (organizationId <= 0 || arrangementId <= 0)
{
return RedirectToAction("Index");
}
_utils.SetLoginRedirectUrl($"/Skolevaccination/Questionnaire/{organizationId}/{arrangementId}", Response);
SetLanguage(!string.IsNullOrWhiteSpace(lang) ? lang : "da-DK");
ViewBag.allowup = allowup ?? false;
return View("Index");
}
private void SetLanguage(string lang)
{
string cultureCookieValue;
switch (lang)
{
case "gb":
case "en-GB":
cultureCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture("en-GB"));
_cultureService.SetCulture(new CultureInfo("en-GB"));
break;
case "dk":
case "da-DK":
cultureCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture("da-DK"));
_cultureService.SetCulture(new CultureInfo("da-DK"));
break;
default:
_logger.LogInformation($"Trying to set a language {lang}, which isn't supported.");
return;
}
Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, cultureCookieValue);
}
对_cultureService.SetCulture的调用(new CultureInfo(&#34; da-DK&#34;))使用以下代码,这是我尝试解决问题的方法:
public void SetCulture(CultureInfo cultureInfo)
{
if (!GetSupportedCultures().Contains(cultureInfo))
{
throw new CultureNotFoundException("The given culture is not supported.");
}
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = cultureInfo;
//CultureInfo.CurrentCulture = cultureInfo;
//CultureInfo.CurrentUICulture = cultureInfo;
}
如图所示,我尝试设置线程的当前文化并使用CultureInfo上的静态方法(注释掉的行)。
我在网上发现的很多帖子都提到设置线程的文化是ASP.Net 5(ASP.Net核心)之前使用过的东西,所有文化设置现在都在启动文件中设置。但是如果我在启动文件中更改它,我会为整个网站更改它,这不是我们想要的。我也需要设置cookie,因为整个网站的一小部分后续页面需要使用通过URL或默认语言设置的语言,但是他们的网址不会在那里定义语言。
如果无法通过直接设置当前文化来解决这个问题,是否可以通过为Web应用程序的这个特定部分设置路由区域来解决这个问题?
提前致谢!
编辑2018/10/05
在仔细观察视图及其IViewLocalizer之后,我找到了一个解决方案。
仔细查看本地化程序类的文档后,我发现您可以使用他们的方法WithCulture
。这将为相同的字符串返回一个新的本地化程序,但是对于给定的文化。
但是在视图没有正确本地化后仍然遇到麻烦之后,我发现视图中注入的定位器与注入控制器的注册器不同,所以为了完全本地化请求,定位器在需要使用WithCulture
方法交换控制器和视图。
我的解决方案最终如下:
在控制器中:
private void SetLanguage(string lang, string defaultLang)
{
if (string.IsNullOrWhiteSpace(lang) || !_cultureService.IsSupportedCulture(lang)) {
_logger.LogInformation($"Tried to change culture to unsupported culture (to {lang}). Culture has been set to default culture {defaultLang}.");
lang = defaultLang;
}
string cultureCookieValue;
switch (lang)
{
case "gb":
case "en-GB":
cultureCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture("en-GB"));
_localizer = _localizer.WithCulture(new CultureInfo("en-GB"));
ViewBag.changeCulture = true;
ViewBag.lang = "en-GB";
break;
case "dk":
case "da-DK":
cultureCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture("da-DK"));
_localizer = _localizer.WithCulture(new CultureInfo("da-DK"));
ViewBag.changeCulture = true;
ViewBag.lang = "da-DK";
break;
default:
_logger.LogInformation($"Trying to set a language {lang}, which isn't supported.");
return;
}
Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, cultureCookieValue);
}
在控制器中调用此方法时,我在视图包中设置了一些数据,在视图中使用它还可以在那里创建一个新的定位器:
@inject IViewLocalizer ViewLocalizer
@{
IHtmlLocalizer Localizer = ViewLocalizer;
if (ViewBag.changeCulture) {
var lang = ViewBag.lang;
Localizer = Localizer.WithCulture(new CultureInfo(lang));
}
var allowUserPasswordLogin = ViewBag.allowup;
}
当调用WithCulture
方法时,返回的类型是IHtmlLocalizer,它不能被强制转换回IViewLocalizer,但是IViewLocalizer扩展了IHtmlLocalizer接口,所以这一切都可以用几行代码完成。