按会话最佳选择的ASP.NET MVC本地化 [英] ASP.NET MVC localization by session best choice

查看:88
本文介绍了按会话最佳选择的ASP.NET MVC本地化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I created the current solution some time ago with the help of a tutorial. At the time it looked like a best solution. I created the solution by adding Application event Listener AcquireRequestState into global.asax. Here I than checked , through simple condition, if there is a Session running. If there was one, I adjusted according to it. (see code below)

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的情况下根据浏览器的设置来设置区域性. 不幸的是,该事件被称为约".三遍,并在一次通话中:

Back to my question. I need to, when there is no existing Session, to set culture according to the settings of the browser. Unfortunately, the event is being called approx. three times and during one of the calls:

if(Session[sessionNameCulture] == null)

最终以异常结束. 我找到了一个替代解决方案,其中包括将逻辑移入BaseController,在这里我可以捕获Page_load事件或使用类似.

It ends up with exception. I found an alternative solution, which would consist of moving the logic into BaseController, where I could catch the Page_load event or use something like this.

在开始重做整个项目之前,我想确保没有办法通过捕获应用程序事件来解决此问题.我想到的是这样的:

Before I start redoing the whole project, I would like to make sure there isn’t a way to solve this through catching Application events. I have in mind something like:

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)
    {
     ...    }

另外,对于未登录的用户来说,这应该可以工作.

Also, it might be a problem that this is supposed to work for a not logged in user.

推荐答案

对于跨领域的问题(例如本地化),您通常应该避免使用旧的ASP.NET事件模型.

For cross-cutting concerns such as localization, you should generally avoid using the old ASP.NET event model.

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

You should also avoid using base classes for controllers, because that will tightly bind your controllers to the base class, and make it difficult to deal with if the shared base class needs an injected service to run some business logic or access the database.

从MVC 3开始,现在有过滤器可以(并且应该)用于实现跨领域关注点.您可以在自己的过滤器中实现每个逻辑(遵循单一责任原则) ,注入依赖项,甚至是

Since MVC 3 there are now filters that can (and should) be used to implement cross-cutting concerns. You can implement each piece of logic in its own filter (which adhere to the Single Responsibility Principle), inject dependencies, and even make the filter conditional by using custom attributes.

专门针对本地化,请参见此示例使用路由而不是会话状态来跟踪区域性,并使用一个过滤器根据路由来设置当前线程的区域性.

Specifically for localization, see this example that uses routing rather than session state to track the culture, and a filter to set the culture of the current thread based on the routing.

相关:对使用会话状态进行三思

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

The official way to get the settings from the user's browser is to use 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

那是我强烈建议您远离这种方法.这些设置(来自页面标题)可以由任意数量的防火墙操纵,因此不一定反映用户请求的语言".它们甚至可能包含无效值(因此,在上面尝试了捕获).

That said I strongly recommend you stay away from this approach. These settings (which come from page headers) could be manipulated by any number of firewalls, and therefore don't necessarily reflect the "user's requested language". They may even contain invalid values (hence the try-catch above).

此外,如果您的站点面向Internet,那么就SEO而言,您在本地化方面的工作将完全浪费. Google的官方

Also, if your site is Internet facing, your efforts for localization will be entirely wasted as far as SEO is concerned. Google's official recommendations are:

  • 如果要本地化,请使其在搜索结果中可见
  • 将每种语言的内容保留在单独的URL上
  • Google尝试确定您每个页面的主要语言.如果您每页只使用一种语言,则可以帮助简化语言识别
  • if you’re going to localize, make it visible in the search results
  • keep the content for each language on separate URLs
  • Google tries to determine the main languages of each one of your pages. You can help to make language recognition easier if you stick to only one language per page

奇怪的是,如果您通过使用标题切换显示在单个URL上的页面语言,则会丢失来自搜索引擎的任何通信,而使用默认语言以外的任何语言,因为其他任何语言都不会被索引.您甚至可能使用户无法以他们选择的语言查看站点(因为某些防火墙决定用户语言标头应默认为特定语言).

Odds are that if you switch the page language that is displayed on a single URL by using headers, you are missing out on any traffic coming from search engines in anything but the default language because none of the other languages will be indexed. You may even make it impossible for users to view the site in their language of choice (because some firewall decides that the user languages header should default to a specific language).

真实故事

我将浏览器的主页设置为MSN已有几年了.但是,当我突然搬到泰国时,页面以泰文显示.当时我看不懂泰语.

I had my browser's home page set to MSN for several years. However, when I moved to Thailand suddenly the page was displayed in Thai. At that time, I could not read Thai.

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

Even worse, there was no (obvious) way to select the language from the user interface. When I tried to change the URL to en-us, it redirected me back to the page in Thai language. I hunted for quite some time, but couldn't find a solution to switch the page back to English. While I don't know the specific reason why I couldn't change to English, I do know that some programmer at Microsoft made a bad decision about how to localize MSN.com and it was preventing me from accessing the site.

那是7年前.从那时起,我的主页已设置为Google.最近,我尝试使用MSN网站,并且它 still 尚无法将其切换为英语.

That was 7 years ago. Since then, my home page has been set to Google. Recently, I tried to use the MSN site, and it still does not have a way to switch it to English.

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

The point: Always give the user a choice of what language to view. The best way is by putting each language on a different URL.

这篇关于按会话最佳选择的ASP.NET MVC本地化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆