如何在 Blazor 服务器端本地化验证消息 (DataAnnotationsValidator)

How to Localize validation message (DataAnnotationsValidator) in blazor server side

我在最新版本的 VS 2019 中使用 blazor 3.1。

到目前为止,我能够本地化页面标签(标题、table 字段等)。

ListEmployee.razor 页面上,我可以本地化 table 标题等。在 AddEmplyeeValidation.razor 页面上,我可以本地化表单标签,但在本地化验证消息。

对于 Employee.cs 文件的验证消息,验证消息在文件 Data.Employee.resxData.Employee.ar.resxResources/Data 文件夹中定义,但这似乎不起作用.

    using System.ComponentModel.DataAnnotations;

    namespace BlazorSPA1.Data
    {
        public class Employee
        {
            [MaxLength(50)]
            public string Id { get; set; }

            [Required (ErrorMessage ="Name is RRRequired")]
            [StringLength(20, ErrorMessage = "Name is too long.")]
            public string Name { get; set; }

            [Required]
            [StringLength(20)]
            public string Department { get; set; }
            [MaxLength(100)]
            public string Designation { get; set; }
            [MaxLength(100)]
            public string Company { get; set; }
            [MaxLength(100)]
            public string City { get; set; }
        }
    }

如何根据 AddEmployeForm 的语言从资源文件加载验证消息?

    @page "/addemployeeValidation"
    @inject NavigationManager NavigationManager
    @inject IEmployeeService EmployeeService
    @inject IStringLocalizer<AddEmployeeValidation> L

    <h2>Create Employee</h2>
    <hr />
    <EditForm Model="@employee" OnValidSubmit="@CreateEmployee">
        <DataAnnotationsValidator />
        <ValidationSummary />
        <div class="row">
            <div class="col-md-8">
                <div class="form-group">
                    <label for="Name" class="control-label">@L["Name"]</label>
                    <input for="Name" class="form-control" @bind="@employee.Name" />
                    <ValidationMessage For="@(()=> employee.Name)" />
                </div>
                <div class="form-group">
                    <label for="Department" class="control-label">@L["Department"]</label>
                    <input for="Department" class="form-control" @bind="@employee.Department" />
                </div>
                <div class="form-group">
                    <label for="Designation" class="control-label">@L["Designation"]</label>
                    <input for="Designation" class="form-control" @bind="@employee.Designation" />
                </div>
                <div class="form-group">
                    <label for="Company" class="control-label">@L["Company"]</label>
                    <input for="Company" class="form-control" @bind="@employee.Company" />
                </div>
                <div class="form-group">
                    <label for="City" class="control-label">@L["City"]</label>
                    <input for="City" class="form-control" @bind="@employee.City" />
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-4">
                <div class="form-group">
                    <input type="submit" class="btn btn-primary" value="Save" />
                    <input type="button" class="btn" @onclick="@Cancel" value="Cancel" />
                </div>
            </div>
        </div>
    </EditForm>

    @code {

        Employee employee = new Employee();

        protected async Task CreateEmployee()
        {
            await EmployeeService.CreateEmployee(employee);
            NavigationManager.NavigateTo("listemployees");
        }


        void Cancel()
        {
            NavigationManager.NavigateTo("listemployees");
        }
    }   

我已经阅读了几篇文章并尝试了一些方法,但似乎没有任何效果。

这是我的 Startup.cs 代码:

        services.AddServerSideBlazor(options => options.DetailedErrors = true);
        services.AddLocalization(options => options.ResourcesPath = "Resources");
        var supportedCultures = new List<CultureInfo> { new CultureInfo("en"), new CultureInfo("ar") };
        services.Configure<RequestLocalizationOptions>(options =>
        {
            options.DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture("en");
            options.SupportedUICultures = supportedCultures;
        });

我正在使用以下示例进行本地化,但它没有显示如何本地化错误消息: https://www.c-sharpcorner.com/article/localization-in-blazor-server/

文件夹结构图片供参考:

英文版的资源文件示例,我也有阿拉伯文文件:

在下面的屏幕截图中,您会看到正在从资源文件中正确提取字段名称,但验证消息不起作用并且仅以英文显示。

这是我的本地化数据注释错误消息的解决方案。我创建了两个资源文件,一个用于字段,另一个用于错误消息。

  • DisplayNameResource 用于本地化字段
  • ErrorMessageResource 用于本地化错误消息

在视图模型中 class 使用 Display 属性来本地化字段名称。要指定资源文件,请在 Display 属性上使用 ResourceType 属性:

[Display(Name = "Address", ResourceType = typeof(DisplayNameResource))]

并且在验证属性上使用ErrorMessageResourceNameErrorMessageResourceType来指定资源文件:

[Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]

这是完整的例子:

public class SomeViewModel
{
    [Display(Name = "Address", ResourceType = typeof(DisplayNameResource))]
    [Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    [StringLength(256, ErrorMessageResourceName = "MaxLengthError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    public string Address { get; set; }

    [Display(Name = "Phone", ResourceType = typeof(DisplayNameResource))]
    [Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    [RegularExpression("^09([0-9]{9})$", ErrorMessageResourceName = "PhoneLengthError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    public string Phone { get; set; }

    [Display(Name = "Password", ResourceType = typeof(DisplayNameResource))]
    [Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    [StringLength(50, MinimumLength = 6, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MinxMaxLengthError")]
    public string Password { get; set; }

    [Display(Name = "ConfirmPassword", ResourceType = typeof(DisplayNameResource))]
    [Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    [StringLength(50, MinimumLength = 6, ErrorMessageResourceType = typeof(ErrorMessageResource), ErrorMessageResourceName = "MinxMaxLengthError")]
    [Compare("Password", ErrorMessageResourceName = "PasswordConfirmMisMatch", ErrorMessageResourceType = typeof(ErrorMessageResource))]
    public string ConfirmPassword { get; set; }
}

MaxLengthError 的错误消息是 {0} cannot be longer than {1} character,因此 {0} 将替换为本地化的文件名,{1} 将替换为您的 256在属性 [StringLength(256,...

上指定

之前有人问过这个问题:

我建议使用 FluentValidation 是更好的方法。这是我的 Github 存储库的 link,演示了它是如何工作的:

https://github.com/conficient/BlazorValidationLocalization

我没试过!

在 asp.net 核心的官方文档中有如何本地化的部分 DataAnnotations 也许你会发现一些 clues there.