#asp.net #localization #master-pages #cultureinfo
#asp.net #локализация #мастер-страницы #cultureinfo
Вопрос:
Я использую Visual Studio 2008 и ASP.NET для создания веб-приложения. Большинство моих веб-страниц основаны на одной главной странице. Эта главная страница содержит три ссылки на кнопки, которые действуют как переключатели языков; Click
обработчики событий выглядят следующим образом:
protected void lbuLangEN_Click(object sender, EventArgs e)
{
this.SwitchLanguage(string.Empty);
}
protected void lbuLangES_Click(object sender, EventArgs e)
{
this.SwitchLanguage("es");
}
Тогда у меня есть свой частный метод SwitchLanguage
:
private void SwitchLanguage(string culture)
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture);
}
Насколько я понимаю, этого должно быть достаточно, чтобы страницы, основанные на моей главной странице, демонстрировали локализованное поведение, т. Е. получали свои ресурсы из соответствующего локального resx
файла в соответствии с культурой. Однако это не работает. Они всегда отображаются на испанском, который является языком моего браузера по умолчанию. Я установил некоторые сообщения трассировки в точках входа и выхода SwitchLanguage
, и, по-видимому, текущий поток не меняет информацию о своей культуре: при каждом SwitchLanguage
вызове язык текущего потока «es-ES», независимо от того, что только что установил мой код.
Есть ли какие-либо проблемы с моим кодом или с подходом, который я использую? Спасибо.
Комментарии:
1. Проблема в том, что вы меняете язык только в текущем потоке, и каждый запрос является отдельным потоком.
2. @vcsjones: Я понимаю. Итак, мне нужно было бы сохранить языковые настройки и каким-то образом установить их для каждого запроса, верно? Существует ли какой-либо обычно используемый метод для этого?
3. вы могли бы добиться успеха, установив cookie, передав запрос по тому же пути, что и в запросе was, создав httpmodule и прочитав там cookie, и установив пользовательский интерфейс в потоке
Ответ №1:
Вы могли бы использовать OnAcquireRequestState
in Global.asax
для изменения культуры. Вызывается сразу после загрузки сеанса, но перед любым событием главной страницы.
Итак, в обработчике событий button вы устанавливаете переменной сеанса желаемый текущий язык. Затем вы перенаправляетесь на текущую страницу. Global.asax
Событие может затем выбрать новый язык прямо перед загрузкой главной страницы:
protected void OnAcquireRequestState(object sender, EventArgs e)
{
string cultureName = "en-GB";
if (HttpContext.Current.Session != null amp;amp;
HttpContext.Current.Session["CultureName"] is string)
cultureName = HttpContext.Current.Session["CultureName"];
if (Thread.CurrentThread.CurrentUICulture.Name == cultureName)
return;
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureName);
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;
}
Комментарии:
1. Спасибо; это звучит как хороший подход. Куда мне подключить обработчик события OnAcquireRequestState?
2. @CesarGon: Буквально в файле с именем
Global.asax
. Оно уже должно быть там, в противном случае вы можете скопировать его из недавно созданного ASP.NET веб-приложение.3. @Andomar: Этого там не было (я использую VS 2008), но я добавил это, плюс строка в Application_Start, подобная этой:
this.AcquireRequestState = Application_OnAcquireRequestState;
Звучит хорошо?4. @Andomar: Кстати, я получаю исключение, потому что, по-видимому, состояние сеанса недоступно внутри
OnAcquireRequestState
, по крайней мере, при одном из первых нескольких вызовов при запуске приложения. Есть идеи, как это обойти?5. @CesarGon: Верно, это звучит знакомо, всегда есть запросы, для которых нет сеанса. Чтобы избежать исключения, используйте
HttpContext.Current.Session
вместоRequest.Session
(отредактировано в ответе)
Ответ №2:
Для любого тела, использующего решение @Andomar, метод должен иметь имя Application_AcquireRequestState, расположенное в глобальном коде.ascx (например, под Application_Start), и не требуется прикреплять обработчики событий. (Если вы сделаете что-либо другое, кроме этого, вы можете столкнуться с NullReferenceException даже при отсутствии кода в теле метода! или ваш метод вообще не будет выполняться)
Таким образом, код будет примерно таким:
void Application_AcquireRequestState(object sender, EventArgs e)
{
string cultureName = "en-GB";
if (HttpContext.Current.Session != null amp;amp;
HttpContext.Current.Session["CultureName"] is string)
cultureName = HttpContext.Current.Session["CultureName"];
if (Thread.CurrentThread.CurrentUICulture.Name == cultureName)
return;
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureName);
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;
}
Ответ №3:
переопределите метод InitializeCulture на уровне страницы, чтобы задать пользовательский интерфейс
Комментарии:
1. Я работаю с главными страницами;
MasterPage
уInitializeCulture
этого метода нет.2. вот почему я сказал, делайте это на уровне страницы, неважно, просто дайте мне -1, господи 🙂 🙂
3. Ну, я бы не хотел, чтобы один и тот же код повторялся на каждой странице. Я уверен, что есть решение, которое позволяет избежать этого.
4. подумайте немного усерднее о том, как вы могли бы избежать этого, и у вас есть свое решение 🙂 кстати, следите за настройкой CurrentCulture также, если вам нужны только переводы!
5. Я согласен с Тимом; наследуйте от вашей собственной «Страницы» вместо System.Web.Page.