MVC数据注释层:在哪里放置设置CurrentUICulture语句?

时间:2009-10-01 08:50:57

标签: asp.net-mvc localization data-annotations

我对MVC应用程序的本地化感到疯狂。

a recent question of mine之后我采用了这种方法:

  1. 语言存储在Session [“lang”]
  2. 每个控制器都继承自我自己的BaseController,它覆盖OnActionExecuting,并在此方法中读取Session并设置CurrentCulture和CurrentUICulture
  3. 这很好用,直到Data Annotation Layer进来。它似乎在执行动作之前被调用,因此它总是以默认语言获取错误消息!

    字段声明如下:

    [Required(ErrorMessageResourceName = "validazioneRichiesto", ErrorMessageResourceType = typeof(Resources.Resources))]
    public string nome { get; set; }
    

    那么,有什么合理的地方可以拨打电话吗?

    我在Controller构造函数中初始化Data Annotation Model Binder。

    public CardController() : base() {
        ModelBinders.Binders.DefaultBinder =
        new Microsoft.Web.Mvc.DataAnnotations.DataAnnotationsModelBinder();
    }
    

    因此,由于Session在控制器的构造函数中始终为null,并且在数据注释验证了字段之后调用了操作覆盖,我可以在哪里设置CurrentCulture和CurrentUICulture来获取本地化错误?

    我尝试将CurrentCulture和CurrentUiCulture放在Application_ *中(例如Application_AcquireRequestState或Application_PreRequestHandlerExecute)似乎没有效果......

4 个答案:

答案 0 :(得分:2)

由于文化是全局用户设置,我在Application_BeginRequest方法的global.asax.cs文件中使用它。

它为我工作(使用cookie),但会话也在那里。

编辑:

  布罗克·艾伦:   http://www.velocityreviews.com/forums/t282576-aspnet-20-session-availability-in-globalasax.html/

会话在PreRequesthandlerExecute中可用。

问题是您的代码是针对服务器的每个请求执行的,而某些请求(例如WebResourxe.axd的请求)不会发出声音 会话(因为处理程序不实现IRequireSessionState)。因此,如果该请求可以访问Session,则将代码更改为仅访问Session。

更改您的代码以执行此操作:

protected void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
    if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
        SetCulture();    
}

无论如何,不​​确定它是否适用于mvc

答案 1 :(得分:1)

在更仔细地阅读您的问题之后,我认为您的问题更多地是资源编译的方式。

签入Resource.resx媒体资源,找到Build Action并将其设为Embedded Resource 同时将Custom Tool更改为PublicResXFileCodeGenerator

alt text http://img208.imageshack.us/img208/2126/captuream.png

我测试了一个迷你解决方案并且运行得很好。 如果您有更多问题,我可以将示例发送给您。

答案 2 :(得分:0)

您可以使用的另一种方法是将lang放在URL中,具有以下好处:

  • 该网站由不同语言的搜索引擎引导
  • 用户可以使用所选语言向朋友发送网址

为此,请使用Application_BeginRequest

中的Global.asax方法
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    Dim lang As String
    If HttpContext.Current.Request.Path.Contains("/en/") Then
        lang = "en"
    Else
        lang = "es"
    End If
    Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang)
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(lang)
End Sub

有关如何实施的更多信息,请参阅this question

答案 3 :(得分:0)

由于twk接受了答案,OP发布了最终解决方案如下:

void Application_PreRequestHandlerExecute(object sender, EventArgs e) {
  if (Context.Handler is IRequiresSessionState || 
      Context.Handler is IReadOnlySessionState) {
    if (Session["lang"] == null) {
      Session["lang"] = "it";
    }

    if (Request.QueryString["lang"] == "it" || Request.QueryString["lang"] == "en") {
      Session["lang"] = Request.QueryString["lang"];
    }

    string lang1 = Session["lang"].ToString();
    string lang2 = Session["lang"].ToString().ToUpper();

    if (lang2 == "EN")
      lang2 = "GB";

    System.Threading.Thread.CurrentThread.CurrentCulture = 
        System.Globalization.CultureInfo.CreateSpecificCulture(lang1 + "-" + lang2);
    System.Threading.Thread.CurrentThread.CurrentUICulture = 
        System.Globalization.CultureInfo.CreateSpecificCulture(lang1 + "-" + lang2);
  }
}