【问题标题】:ASP.NET MVC 3 localization with DisplayAttribute and custom resource provider带有 DisplayAttribute 和自定义资源提供程序的 ASP.NET MVC 3 本地化
【发布时间】:2011-06-19 19:53:04
【问题描述】:

我使用自定义资源提供程序从数据库中获取资源字符串。这适用于 ASP.NET,我可以将资源类型定义为字符串。 MVC 3 中模型属性的元数据属性(如 [Range]、[Display]、[Required] 需要 Resource 的类型作为参数,其中 ResourceType 是生成的 .resx 文件的代码隐藏类的类型.

    [Display(Name = "Phone", ResourceType = typeof(MyResources))]
    public string Phone { get; set; }

因为我没有 .resx 文件,所以不存在这样的类。如何将模型属性与自定义资源提供程序一起使用?

我想要这样的东西:

    [Display(Name = "Telefon", ResourceTypeName = "MyResources")]
    public string Phone { get; set; }

来自 System.ComponentModel 的 DisplayNameAttribute 有一个可覆盖的 DisplayName 属性用于此目的,但 DisplayAttribute 类是密封的。对于验证属性,不存在相应的类。

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 localization internationalization displayattribute


    【解决方案1】:

    我想出的最干净的方法是覆盖DataAnnotationsModelMetadataProvider。这是一篇关于如何做到这一点的非常简洁的文章。

    http://buildstarted.com/2010/09/14/creating-your-own-modelmetadataprovider-to-handle-custom-attributes/

    【讨论】:

    • 你能告诉我们你是怎么写出来的吗?这篇文章展示了如何添加新的数据符号,但没有展示任何关于本地化的内容
    【解决方案2】:

    您可以扩展 DisplayNameAttribute 并覆盖 DisplayName 字符串属性。我有这样的东西

        public class LocalizedDisplayName : DisplayNameAttribute
        {
            private string DisplayNameKey { get; set; }   
            private string ResourceSetName { get; set; }   
    
            public LocalizedDisplayName(string displayNameKey)
                : base(displayNameKey)
            {
                this.DisplayNameKey = displayNameKey;
            }
    
    
            public LocalizedDisplayName(string displayNameKey, string resourceSetName)
                : base(displayNameKey)
            {
                this.DisplayNameKey = displayNameKey;
                this.ResourceSetName = resourceSetName;
            }
    
            public override string DisplayName
            {
                get
                {
                    if (string.IsNullOrEmpty(this.GlobalResourceSetName))
                    {
                        return MyHelper.GetLocalLocalizedString(this.DisplayNameKey);
                    }
                    else
                    {
                        return MyHelper.GetGlobalLocalizedString(this.DisplayNameKey, this.ResourceSetName);
                    }
                }
            }
        }
    }
    

    对于MyHelper,方法可以是这样的:

    public string GetLocalLocalizedString(string key){
        return _resourceSet.GetString(key);
    }
    

    显然您需要添加错误处理并设置resourceReader。更多信息here

    有了这个,你然后用新属性装饰你的模型,传递你想要从中获取值的资源的键,就像这样

    [LocalizedDisplayName("Title")]
    

    然后Html.LabelFor会自动显示本地化文本。

    【讨论】:

    • 我想你忘了输入“MyHelper.GetLocalLocalizedString”的代码
    • 我知道这会变成僵尸,但你应该为此拥有更多的互联网。
    【解决方案3】:

    我认为您必须覆盖 DataAnnotations 属性才能使用数据库资源提供程序对它们进行本地化。您可以从当前的继承,然后指定进一步的属性,例如从自定义提供程序获取资源时要使用的数据库连接字符串。

    【讨论】:

    • 不幸的是,这不起作用,因为 DisplayAttribute 是一个密封类。即使我自己实现属性,我也必须覆盖 Html 扩展方法(例如 Html.LabelFor)。
    • 我做了进一步的调查:我可以从具有可覆盖属性 DisplayName 的 DisplayNameAttribute 派生。最后我使用了一个 T4 模板来生成 Resources 类,因为我不必实现所有的数据注释属性。
    猜你喜欢
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多