Đây là một câu hỏi cũ, nhưng tôi nghĩ rằng đây là một vấn đề rất phổ biến, và đây là giải pháp của tôi trong MVC 3.
Đầu tiên, một mẫu T4 là cần thiết để tạo các hằng số để tránh các chuỗi khó chịu. Chúng tôi có một tệp tài nguyên 'Labels.resx' chứa tất cả các chuỗi nhãn. Do đó, mẫu T4 sử dụng trực tiếp tệp tài nguyên,
<#@ template debug="True" hostspecific="True" language="C#" #>
<#@ output extension=".cs" #>
<#@ Assembly Name="C:\Project\trunk\Resources\bin\Development\Resources.dll" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Resources" #>
<#
var resourceStrings = new List<string>();
var manager = Resources.Labels.ResourceManager;
IDictionaryEnumerator enumerator = manager.GetResourceSet(CultureInfo.CurrentCulture, true, true)
.GetEnumerator();
while (enumerator.MoveNext())
{
resourceStrings.Add(enumerator.Key.ToString());
}
#>
// This file is generated automatically. Do NOT modify any content inside.
namespace Lib.Const{
public static class LabelNames{
<#
foreach (String label in resourceStrings){
#>
public const string <#=label#> = "<#=label#>";
<#
}
#>
}
}
Sau đó, một phương thức tiện ích mở rộng được tạo để bản địa hóa 'Tên hiển thị',
using System.ComponentModel.DataAnnotations;
using Resources;
namespace Web.Extensions.ValidationAttributes
{
public static class ValidationAttributeHelper
{
public static ValidationContext LocalizeDisplayName(this ValidationContext context)
{
context.DisplayName = Labels.ResourceManager.GetString(context.DisplayName) ?? context.DisplayName;
return context;
}
}
}
Thuộc tính 'DisplayName' được thay thế bằng thuộc tính 'DisplayLabel' để tự động đọc từ 'Labels.resx',
namespace Web.Extensions.ValidationAttributes
{
public class DisplayLabelAttribute :System.ComponentModel.DisplayNameAttribute
{
private readonly string _propertyLabel;
public DisplayLabelAttribute(string propertyLabel)
{
_propertyLabel = propertyLabel;
}
public override string DisplayName
{
get
{
return _propertyLabel;
}
}
}
}
Sau tất cả những công việc chuẩn bị đó, đã đến lúc chạm vào các thuộc tính xác thực mặc định đó. Tôi đang sử dụng thuộc tính 'Bắt buộc' làm ví dụ,
using System.ComponentModel.DataAnnotations;
using Resources;
namespace Web.Extensions.ValidationAttributes
{
public class RequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute
{
public RequiredAttribute()
{
ErrorMessageResourceType = typeof (Errors);
ErrorMessageResourceName = "Required";
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
return base.IsValid(value, validationContext.LocalizeDisplayName());
}
}
}
Bây giờ, chúng tôi có thể áp dụng các thuộc tính đó trong mô hình của mình,
using Web.Extensions.ValidationAttributes;
namespace Web.Areas.Foo.Models
{
public class Person
{
[DisplayLabel(Lib.Const.LabelNames.HowOldAreYou)]
public int Age { get; set; }
[Required]
public string Name { get; set; }
}
}
Theo mặc định, tên thuộc tính được sử dụng làm khóa để tra cứu 'Label.resx', nhưng nếu bạn đặt nó thông qua 'DisplayLabel', nó sẽ sử dụng nó thay thế.