【问题标题】:Unable to change current threads UICulture - stuck on en-US无法更改当前线程 UICulture - 卡在 en-US
【发布时间】:2014-03-04 12:23:03
【问题描述】:

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

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>

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

我在这里可能做错了什么?

【问题讨论】:

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


    【解决方案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();
    }
    

    啊,我不知道您想在母版页上使用它。无论如何,您可以创建一个模块并将其注册到您的 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>
    

    【讨论】:

    • 虽然这对普通页面完全有效,但不适用于 MasterPages;不幸的是,它不能从 BasePage 类继承,而后者又会从 System.Web.UI.Page 派生。
    • 您的自定义处理程序本身可以在我的母版页上工作,但翻译不能在正常的 0815 页面上工作。我可以即时翻译主站点上的所有内容,但是 f.e. default.aspx 中的内容拒绝从 meta:resourcekey="" values 获取其值
    【解决方案2】:

    我也遇到了同样的问题。 看看这个 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);
    

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

    您需要在上面的代码中为您拥有的每种文化添加一行。 不过,我不确定将这段代码放在 ASP.NET non MVC 应用程序中的什么位置。只需找到应用程序的起点并将其放在那里即可。

    【讨论】:

    • WebFroms Web 应用程序也有一个 Global.asax 文件,不用担心。我试试看。
    • 不。我能够在母版页上进行全球化,但每个 .aspx 页面都忽略了全球化提供者
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 2011-01-31
    • 2013-12-05
    • 1970-01-01
    相关资源
    最近更新 更多