Включение языка ASP.NET приложение, использующее главную страницу

#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.