Локализация ASP.NET MVC 3 с помощью DisplayAttribute и пользовательского поставщика ресурсов

Я использую собственный поставщик ресурсов для получения строк ресурсов из базы данных. Это отлично работает с ASP.NET, где я могу определить тип ресурса как строку. Атрибуты метаданных для свойств модели в MVC 3 (например, [Range], [Display], [Required]) требуют типа ресурса в качестве параметра, где ResourceType - это тип сгенерированного класса кода .resx файла.

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

Поскольку у меня нет файлов .resx, такого класса не существует. Как я могу использовать атрибуты модели с помощью специализированного поставщика ресурсов?

Я хотел бы иметь что-то вроде этого:

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

В DisplayNameAttribute из System.ComponentModel для этой цели было переопределяемое свойство DisplayName, но класс DisplayAttribute запечатан. Для атрибутов проверки не существует соответствующих классов.

Ответы

Ответ 1

Вы можете расширить атрибут 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. Подробнее здесь

При этом вы затем украшаете свою модель новым атрибутом, передавая ключ ресурса, из которого вы хотите получить значение, например

[LocalizedDisplayName("Title")]

Затем Html.LabelFor автоматически отобразит локализованный текст.

Ответ 3

Я думаю, вам придется переопределить свойства DataAnnotations, чтобы локализовать их с поставщиком ресурсов DB. Вы можете наследовать от текущих, а затем указать дополнительные свойства, такие как строка подключения к DB, которая будет использоваться при получении ресурсов у вашего настраиваемого поставщика.