使用自定义本地化程序进行Asp .NET 5数据注释本地化

时间:2016-03-27 18:41:54

标签: c# asp.net-mvc-5 asp.net-core

我通过覆盖IStringLocalizerFactoryIStringLocalizer创建了自己的缓存JSON字符串本地化程序,它就像一个魅力。

唯一的问题是我无法本地化数据注释,因为它们似乎无法使用自定义字符串本地化程序。我尝试使用ResourceType属性,这个属性应该用于这种情况(至少就我而言),但不是使用我的IStringLocalizer而是尝试访问属性。这可能适用于默认的resx - 本地化程序,但不适用于自定义程序。

我可以在我的班级中创建属性,重新路由到我的IStringLocalizer,但这很麻烦,如果必须的话,只想这样做。

我的观点模型:

public class RegisterViewModel
{
    [Required]
    [Display(Name = "test", ResourceType = typeof(Lang))]
    public string Username { get; set; }
}

cshtml内部使用,如下所示:

<div class="form-group">
    <label asp-for="Username" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="Username" class="form-control" />
        <span asp-validation-for="Username" class="text-danger"></span>
    </div>
</div>

应自动生成labeltextbox。但相反:

InvalidOperationException: Cannot retrieve property 'Name' because localization failed. Type 'Test.Models.Lang.Lang' is not public or does not contain a public static string property with the name 'test'.

booom。那是我的Lang课程:

public class Lang
{
}

而不是通过索引器获取IStringLocalizer<Lang>并搜索test属性(这就是我试图让他做的事情),它试图找到不存在的属性test

有没有办法改变查找的工作方式?我尝试通过MvcDataAnnotationsLocalizationOptions更改services.Configure(),但没有效果。

或者是否可以直接更改从这些数据注释生成HTML代码的方式?

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

编辑:这当然不起作用,因为CreateDisplayMetadata()只调用一次然后缓存,导致第一个“翻译”成为唯一的一个!我确实有另一个扩展DefaultModelMetadataProvider或添加IDisplayMetadataProvider的解决方案(仍然不确定它是正确的或最好的方式......),所以如果有人仍然需要帮助,请告诉我:)

陈旧错误答案: 不知道是否有任何“更正确”(请告诉我,如果是这样)解决方案,但这里有一个适用于RC2:

public class LocalizedDisplayMetadataProvider : IDisplayMetadataProvider
{
    public String Translate(String key)
    {
        if(key != null && key.StartsWith("#"))
        {
            return key.TrimStart('#').ToUpper(); // Todo: Replace with real localization code (e.g. fetch from json)...
        }
        else
        {
            return key;
        }
    }

    public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
    {
        foreach(var attr in context.Attributes.OfType<DisplayAttribute>().Where(a => a.ResourceType == null))
        {
            attr.Name = this.Translate(attr.Name);
            attr.Description = this.Translate(attr.Description);
            attr.GroupName = this.Translate(attr.GroupName);
            attr.Prompt = this.Translate(attr.Prompt);
            attr.ShortName = this.Translate(attr.ShortName);
        }
    }
}

然后在ConfigureServices方法中注册:

services.Configure<MvcOptions>(m =>
        {
            m.ModelMetadataDetailsProviders.Add(new LocalizedDisplayMetadataProvider());

        });

这将在DisplayAttribute上本地化所有以'#'开头(而不是ResourceType集)的字符串,并且可以轻松扩展以处理ValidationAttribute。