无法更改当前线程UICulture - 卡在en-US上

时间:2014-03-04 12:23:03

标签: c# asp.net .net webforms globalization

我正在尝试在网站上为用户实施文化切换,他可以从下拉列表中选择他喜欢的语言。

problem and solution posted here似乎是一个很好的起点,所以我将代码实现到我的global.asax中:

    void Application_BeginRequest(Object sender, EventArgs e)
    {
        // Code that runs on application startup                                                            
        HttpCookie cookie = HttpContext.Current.Request.Cookies["CultureInfo"];
        if (cookie != null && cookie.Value != null)
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(cookie.Value);
            Thread.CurrentThread.CurrentCulture = new CultureInfo(cookie.Value);
        }
        else
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
            Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
        }
    }

因此,如果未设置cookie,请将文化设置为de-DE。在此之后,我将第二段代码复制到我的主站点的Page_Load方法中:

if (!Page.IsPostBack)
{
    if (Session["ddindex"] != null)
    {
        ddlanguage.SelectedValue = Session["ddindex"].ToString();
        ddlanguage.SelectedIndex = Convert.ToInt32(Session["ddindex"].ToString());
        //display current values in dummy label - remove later on.
        currentCulture.Text = Thread.CurrentThread.CurrentCulture.ToString() + " " + Thread.CurrentThread.CurrentUICulture;
    }
    else
    {
        ddlanguage.SelectedValue = Thread.CurrentThread.CurrentCulture.Name;
    }
}

加上DropdDownBox的SelectedIndexChanged方法:

protected void ddlanguage_SelectedIndexChanged(object sender, EventArgs e)
{
    Session["language"] = ddlanguage.SelectedValue;
    //Sets the cookie that is to be used by Global.asax
    HttpCookie cookie = new HttpCookie("CultureInfo");
    cookie.Value = ddlanguage.SelectedValue;
    Response.Cookies.Add(cookie);
    //Set the culture and reload for immediate effect.
    //Future effects are handled by Global.asax
    Thread.CurrentThread.CurrentCulture = new CultureInfo(ddlanguage.SelectedValue);
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(ddlanguage.SelectedValue);

    if (cookie.Value == "en-US")
    {
        Session["ddindex"] = "0";
    }
    else if (cookie.Value == "de-DE")
    {
        Session["ddindex"] = "1";
    }
    Server.Transfer(Request.Path);
}

标记:

<asp:DropDownList ID="ddlanguage" runat="server" 
                  OnSelectedIndexChanged="ddlanguage_SelectedIndexChanged" 
                  AutoPostBack="true">
    <asp:ListItem Selected="False" Value="en-US" Text="English"></asp:ListItem>
    <asp:ListItem Selected="False" Value="de-DE" Text="Deutsch"></asp:ListItem>
</asp:DropDownList>

我的资源中为某些<asp:Hyperlinks>设置了一些值,这些值在调用网站后可以从德语正确翻译成英语。 但是,在通过asp:dropdownbox切换当前选定的文化时,文化保留在en-US(我的开发机器上的默认浏览器文化)。标签currentCulture.Text也保留在en-US上,所有翻译仍为英文。

我在这里做错了什么?

2 个答案:

答案 0 :(得分:1)

重写InitializeCulture并在那里从Page_Load中执行。

protected override void InitializeCulture()
{
    var culture = new System.Globalization.CultureInfo("<Culture Name Here>");

    Thread.CurrentThread.CurrentCulture = culture;
    Thread.CurrentThread.CurrentUICulture = culture;

    base.InitializeCulture();
}

啊,我不知道你想在Masterpage上使用它。无论如何,您可以创建一个模块并在web.config中注册它。

namespace YourNameSpaceHere
{
    public class LanguageModule : IHttpModule
    {

        public void Init(System.Web.HttpApplication context)
        {
            context.AcquireRequestState += OnAcquireRequestState;
        }

        public void OnAcquireRequestState(object sender, EventArgs eventArgs)
        {
            HttpApplication httpApplication = sender as HttpApplication;

            string lang = null;
            if (httpApplication.Request.Cookies["<CookieNameHere>"] == null)
            {
                lang = Thread.CurrentThread.CurrentCulture.Name;
                httpApplication.Response.Cookies["<CookieNameHere>"].Value = lang;
            }
            else
            {
                lang = httpApplication.Request.Cookies["<CookieNameHere>"].Value;
            }

            if (lang != Thread.CurrentThread.CurrentCulture.Name)
            {
                if (Language.IsValidCultureInfoName(lang))
                {
                    var culture = new System.Globalization.CultureInfo(lang);

                    Thread.CurrentThread.CurrentCulture = culture;
                    Thread.CurrentThread.CurrentUICulture = culture;

                    httpApplication.Response.Cookies["<CookieNameHere>"].Value = lang;
                }
            }
        }

        public void Dispose()
        {
        }

    }
}
system.web下的

web.config,我认为是system.webServer

<httpModules>
    <add type="YourNameSpaceHere.LanguageModule, YourNameSpaceHere" name="LanguageHandlerModule" />
</httpModules>

答案 1 :(得分:0)

我遇到了同样的问题。 看看这个Microsoft Bug:Race condition in System.Resources.ResourceManager leads to incorrect resources being loaded

看看我在那里发布的解决方法。

基本上,资源管理器存在一个问题,即内部竞争条件导致它将所有文化加载为en-US文化。

我在MVC项目中所做的是在应用程序启动时“初始化”所有资源集。以下代码来自我的Global.asax文件,MvcApplication类的Application_Start()方法:

Resources.ResourceManager.GetResourceSet(new System.Globalization.CultureInfo("en-US"), true, true);
Resources.ResourceManager.GetResourceSet(new System.Globalization.CultureInfo("es-ES"), true, true);
Resources.ResourceManager.GetResourceSet(new System.Globalization.CultureInfo("tr-TR"), true, true);
Resources.ResourceManager.GetResourceSet(new System.Globalization.CultureInfo("he-IL"), true, true);

这将强制资源管理器正确加载。它很糟糕,但似乎微软并没有给这个bug任何关注。

您需要为上面的代码添加一条代码,用于您拥有的每种文化。 不过,我不确定将此代码放在ASP.NET 非MVC 应用程序中的哪个位置。只需找到应用程序的起点并将其放在那里。