Я искал вокруг и не смог найти ответ, который работал для меня.
Мой вопрос: как установить культуру текущего ответа в методе контроллера.
Сценарий выглядит следующим образом.У нас есть общая область веб-приложения, которая работает с культурой, установленной через 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 ("da-DK")) используетсяследующий код, который является моей попыткой решить проблему:
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-адреса, или язык по умолчанию, но в их URL-адресах язык не будет определен там.
Если это невозможно решить, установив текущую культуру напрямую, возможно, это можно решить, настроив область маршрутизации для этой конкретной части веб-приложения?
Заранее спасибо!
РЕДАКТИРОВАТЬ 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, поэтому все работает с несколькими строками кода.