【问题标题】:ASP.NET MVC localization by session best choiceASP.NET MVC 本地化按会话最佳选择
【发布时间】:2016-04-08 07:49:51
【问题描述】:

我前段时间在教程的帮助下创建了当前解决方案。当时它看起来是一个最好的解决方案。 我通过将应用程序事件侦听器 AcquireRequestState 添加到 global.asax 中来创建解决方案。在这里,我通过简单的条件检查了是否有 Session 正在运行。 如果有的话,我根据它进行调整。 (见下面的代码)

protected void Application_AcquireRequestState(object sender, EventArgs e)
{
    HttpContext context = HttpContext.Current;
    if (context != null && context.Session != null && Session[sessionNameCulture] != null)
    {
        string culture = Session[sessionNameCulture].ToString();
        try
        {
            culture = culture.ToLower();
            Thread.CurrentThread.CurrentCulture = new CultureInfo(culture); ;
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture); ;
        }
        catch (Exception ex)
        {
            ErrorHandler.HandleError("Culture info setup failure.", ex);
        }
    }

}

回到我的问题。我需要,当没有现有的 Session 时,根据浏览器的设置来设置文化。 不幸的是,该事件被称为大约。三次,在其中一次通话期间:

if(Session[sessionNameCulture] == null)

它以异常结束。 我找到了一个替代解决方案,其中包括将逻辑移动到 BaseController 中,在那里我可以捕获 Page_load 事件或使用类似 this 的东西。

在我开始重做整个项目之前,我想确保没有办法通过捕获应用程序事件来解决这个问题。我想到了类似的东西:

protected void Application_AcquireRequestState(object sender, EventArgs e) {
    HttpContext context = HttpContext.Current; if(Session[sessionNameCulture] == null)
           Session[SessionNameCulture] = new System.Globalization.CultureInfo(Request.UserLanguages[0]);

    if (context != null && context.Session != null && Session[sessionNameCulture] != null)
    {
     ...    }

另外,这可能是一个问题,这应该适用于未登录的用户。

【问题讨论】:

    标签: asp.net asp.net-mvc session localization


    【解决方案1】:

    对于cross-cutting concerns等本地化,一般应避免使用旧的ASP.NET事件模型。

    您还应该避免为控制器使用基类,因为这会将您的控制器紧密绑定到基类,并且如果共享基类需要注入服务来运行某些业务逻辑或访问数据库,则难以处理.

    自 MVC 3 以来,现在有 filters 可以(并且应该)用于实现横切关注点。您可以在自己的过滤器(遵循Single Responsibility Principle)、inject dependencies 甚至make the filter conditional by using custom attributes 中实现每条逻辑。

    专门针对本地化,请参阅this example,它使用路由而不是会话状态来跟踪文化,以及根据路由设置当前线程文化的过滤器。

    相关:Think twice about using session state

    根据浏览器设置语言

    从用户浏览器获取设置的官方方法是使用Request.UserLanguages

    例子:

    // Get Browser languages.
    var defaultCulture = "en-us";
    var userLanguages = Request.UserLanguages;
    CultureInfo ci;
    if (userLanguages.Count() > 0)
    {
        try
        {
            ci = new CultureInfo(userLanguages[0]);
        }
        catch(CultureNotFoundException)
        {
             ci = new CultureInfo(defaultCulture);
        }
    }
    else
    {
        ci = new CultureInfo(defaultCulture);
    }
    // Here CultureInfo should already be set to either user's prefereable language
    // or to defaultCulture if user transmitted invalid culture ID
    

    也就是说,我强烈建议您远离这种方法。这些设置(来自页面标题)可以被任意数量的防火墙操纵,因此不一定反映“用户请求的语言”。它们甚至可能包含无效值(因此是上面的 try-catch)。

    此外,如果您的网站面向 Internet,那么就 SEO 而言,您在本地化方面的努力将完全付诸东流。 Google 的 official recommendations 是:

    • 如果您要进行本地化,请将其显示在搜索结果中
    • 将每种语言的内容保留在单独的 URL 上
    • Google 会尝试确定您的每个网页的主要语言。如果您坚持每页只使用一种语言,则可以帮助您更轻松地识别语言

    很可能,如果您使用标题切换显示在单个 URL 上的页面语言,您将错过来自搜索引擎的任何流量,而不是默认语言,因为其他语言都不会被编入索引。您甚至可能使用户无法以他们选择的语言查看网站(因为某些防火墙决定用户语言标题应默认为特定语言)。


    真实故事

    多年来,我一直将浏览器的主页设置为 MSN。但是,当我突然搬到泰国时,页面显示为泰语。那时,我不懂泰语。

    更糟糕的是,没有(明显的)方法可以从用户界面中选择语言。当我尝试将 URL 更改为 en-us 时,它会将我重定向回泰语页面。我找了很长一段时间,但找不到将页面切换回英文的解决方案。虽然我不知道我不能改成英语的具体原因,但我知道微软的一些程序员在如何本地化 MSN.com 方面做出了错误的决定,这阻止了我访问该网站。

    那是 7 年前的事了。从那时起,我的主页就被设置为 Google。最近尝试使用MSN网站,还是没办法切换成英文。

    要点:始终让用户选择要查看的语言。最好的方法是将每种语言放在不同的 URL 上。

    【讨论】:

    • 对不起,也许我没有准确解释这个问题。我正在寻找如何根据网络浏览器的设置本地化网站的解决方案。
    猜你喜欢
    • 2010-12-14
    • 2013-10-09
    • 2012-04-20
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多