【问题标题】:DataAnnotations Localization in aspnet coreaspnet 核心中的 DataAnnotations 本地化
【发布时间】:2017-02-06 09:11:18
【问题描述】:

我在一个解决方案中有 2 个项目。其中一个名为 UICORE,另一个名为 DomainCore。 UICore 是一个 ASPNETCORE 项目,它有我的控制器和视图。 DomainCore 是一个类库,其中包含我所有的实体类。我想使用本地化的 DataAnnotations。我研究了“https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization”,但我无法让它为我工作。

【问题讨论】:

    标签: asp.net-core


    【解决方案1】:

    如果域和视图模型的 DataAnnotations 遇到您的问题(或部分问题),我建议使用此方法。

    如果没有,请不要投反对票。它可能对 DataAnnotations 标签有用。

    为了编写一次 DataAnnotations,请使用抽象类。在这个 New 实体示例中,我将抽象类命名为 NewMetaData。

    DomainCore 项目:

    namespace myProject.DomainCore
    {
        public class New : NewMetaData
        {
            public Guid Id { get; set; }
            public string Title { get; set; }
            public string Content { get; set; }
            public DateTime Date { get; set; }
        }
    
        public abstract class NewMetaData
        {
            [Required(ErrorMessage = "New Title is required")]
            [StringLength(maximumLength:150, ErrorMessage = "New Title length must not exceed 150 characters")]
            [Display(Name = "Title on New")]
            private string Title { get; set; }  //pay attention to privates
    
            [Required(ErrorMessage = "New Content is required")]
            [Display(Name = "Content of New")]
            private string Content { get; set; }
    
            [Required]
            [Display(Name = "Publish Date")]
            private DateTime Date { get; set; }        
    
        }
    }
    

    并且UICore项目中的viewmodel类也必须继承NewMetaData类:

    namespace myProject.UICore.Models.News
    {
        public class NewCreateModel: NewMetaData
        {
            public string Title { get; set; }
            [AllowHtml]
            public string Content { get; set; }
        }
    
        public class NewDetailsModel :NewMetaData
        {
            [HiddenInput(DisplayValue = false)]
            public Guid Id { get; set; }
            public string Url { get; set; }
            public string Title { get; set; }
            public string Content { get; set; } 
        }
    }
    

    如您所见,您可以向 UICore 内的 AllowHtml、HiddenInput 和 ... 等属性添加额外的 DataAnotations,并且仍然保持基本 Annotations 不变。

    这是对模型进行一次注释并多次使用它们的最简单的跨项目方法。

    希望对你有帮助。

    【讨论】:

      【解决方案2】:

      也许这会有所帮助: https://damienbod.com/2015/10/24/using-dataannotations-and-localization-in-asp-net-5-mvc-6/

      您需要将数据注释本地化添加到共享资源,并将其添加到每个控制器,查看本地化响应的使用位置。

      【讨论】:

        【解决方案3】:

        您必须在启动文件中配置本地化,并添加 DataAnnotations 本地化选项;

        services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddViewLocalization(o=>o.ResourcesPath = "ResourcesFolder")
        .AddDataAnnotationsLocalization(o=> {
            var type = typeof(MyResource);
            var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
            var factory = services.BuildServiceProvider().GetService<IStringLocalizerFactory>();
            var localizer = factory.Create("MyResource", assemblyName.Name);
            o.DataAnnotationLocalizerProvider = (t, f) => localizer;
        })
        

        这将本地化数据属性,例如:

        [Required(ErrorMessage= "...")]
        [StringLength(ErrorMessage= "...")]
        [Range(ErrorMessage= "...")]
        

        等等..

        但您仍然需要配置 ModelBinding 错误消息(例如:检查数字、空值等)

        services.AddMvc()
        .AddMvcOptions(o =>
                {
                    var type = typeof(MyResource);
                    var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
                    var factory = services.BuildServiceProvider().GetService<IStringLocalizerFactory>();
                    var localizer = factory.Create("MyResource", assemblyName.Name);
        
                    o.ModelBindingMessageProvider
                        .SetAttemptedValueIsInvalidAccessor((x, y) => localizer["'{0}' is not a valid value for '{1}'", x, y]);
        
                    o.ModelBindingMessageProvider
                        .SetValueMustBeANumberAccessor((x) => localizer["'{0}' must be a number.", x]);
                });
        

        如果您已实施身份系统,则必须通过覆盖 IdentityErrorDescriber 方法来本地化身份错误消息(重复的电子邮件、密码策略等);

        public class LocalizedIdentityErrorDescriber : IdentityErrorDescriber
        {
            public override IdentityError DuplicateEmail(string email)
            {
                return new IdentityError
                {
                    Code = nameof(DuplicateEmail),
                    Description = string.Format(LocalizedIdentityErrorMessages.DuplicateEmail, email)
                };
            }
        
            public override IdentityError DuplicateUserName(string userName)
            {
                return new IdentityError
                {
                    Code = nameof(DuplicateUserName),
                    Description = string.Format(LocalizedIdentityErrorMessages.DuplicateUserName, userName)
                };
            }
        
            public override IdentityError InvalidEmail(string email)
            {
                return new IdentityError
                {
                    Code = nameof(InvalidEmail),
                    Description = string.Format(LocalizedIdentityErrorMessages.InvalidEmail, email)
                };
            }
        
            public override IdentityError DuplicateRoleName(string role)
            {
                return new IdentityError
                {
                    Code = nameof(DuplicateRoleName),
                    Description = string.Format(LocalizedIdentityErrorMessages.DuplicateRoleName, role)
                };
            }
        
            public override IdentityError InvalidRoleName(string role)
            {
                return new IdentityError
                {
                    Code = nameof(InvalidRoleName),
                    Description = string.Format(LocalizedIdentityErrorMessages.InvalidRoleName, role)
                };
            }
        
            public override IdentityError InvalidToken()
            {
                return new IdentityError
                {
                    Code = nameof(InvalidToken),
                    Description = LocalizedIdentityErrorMessages.InvalidToken
                };
            }
        
            public override IdentityError InvalidUserName(string userName)
            {
                return new IdentityError
                {
                    Code = nameof(InvalidUserName),
                    Description = string.Format(LocalizedIdentityErrorMessages.InvalidUserName, userName)
                };
            }
        
            public override IdentityError LoginAlreadyAssociated()
            {
                return new IdentityError
                {
                    Code = nameof(LoginAlreadyAssociated),
                    Description = LocalizedIdentityErrorMessages.LoginAlreadyAssociated
                };
            }
        
            public override IdentityError PasswordMismatch()
            {
                return new IdentityError
                {
                    Code = nameof(PasswordMismatch),
                    Description = LocalizedIdentityErrorMessages.PasswordMismatch
                };
            }
        
            public override IdentityError PasswordRequiresDigit()
            {
                return new IdentityError
                {
                    Code = nameof(PasswordRequiresDigit),
                    Description = LocalizedIdentityErrorMessages.PasswordRequiresDigit
                };
            }
        
            public override IdentityError PasswordRequiresLower()
            {
                return new IdentityError
                {
                    Code = nameof(PasswordRequiresLower),
                    Description = LocalizedIdentityErrorMessages.PasswordRequiresLower
                };
            }
        
            public override IdentityError PasswordRequiresNonAlphanumeric()
            {
                return new IdentityError
                {
                    Code = nameof(PasswordRequiresNonAlphanumeric),
                    Description = LocalizedIdentityErrorMessages.PasswordRequiresNonAlphanumeric
                };
            }
        
            public override IdentityError PasswordRequiresUniqueChars(int uniqueChars)
            {
                return new IdentityError
                {
                    Code = nameof(PasswordRequiresUniqueChars),
                    Description = string.Format(LocalizedIdentityErrorMessages.PasswordRequiresUniqueChars, uniqueChars)
                };
            }
        
            public override IdentityError PasswordRequiresUpper()
            {
                return new IdentityError
                {
                    Code = nameof(PasswordRequiresUpper),
                    Description = LocalizedIdentityErrorMessages.PasswordRequiresUpper
                };
            }
        
            public override IdentityError PasswordTooShort(int length)
            {
                return new IdentityError
                {
                    Code = nameof(PasswordTooShort),
                    Description = string.Format(LocalizedIdentityErrorMessages.PasswordTooShort, length)
                };
            }
        
            public override IdentityError UserAlreadyHasPassword()
            {
                return new IdentityError
                {
                    Code = nameof(UserAlreadyHasPassword),
                    Description = LocalizedIdentityErrorMessages.UserAlreadyHasPassword
                };
            }
        
            public override IdentityError UserAlreadyInRole(string role)
            {
                return new IdentityError
                {
                    Code = nameof(UserAlreadyInRole),
                    Description = string.Format(LocalizedIdentityErrorMessages.UserAlreadyInRole, role)
                };
            }
        
            public override IdentityError UserNotInRole(string role)
            {
                return new IdentityError
                {
                    Code = nameof(UserNotInRole),
                    Description = string.Format(LocalizedIdentityErrorMessages.UserNotInRole, role)
                };
            }
        
            public override IdentityError UserLockoutNotEnabled()
            {
                return new IdentityError
                {
                    Code = nameof(UserLockoutNotEnabled),
                    Description = LocalizedIdentityErrorMessages.UserLockoutNotEnabled
                };
            }
        
            public override IdentityError RecoveryCodeRedemptionFailed()
            {
                return new IdentityError
                {
                    Code = nameof(RecoveryCodeRedemptionFailed),
                    Description = LocalizedIdentityErrorMessages.RecoveryCodeRedemptionFailed
                };
            }
        
            public override IdentityError ConcurrencyFailure()
            {
                return new IdentityError
                {
                    Code = nameof(ConcurrencyFailure),
                    Description = LocalizedIdentityErrorMessages.ConcurrencyFailure
                };
            }
        
            public override IdentityError DefaultError()
            {
                return new IdentityError
                {
                    Code = nameof(DefaultError),
                    Description = LocalizedIdentityErrorMessages.DefaultIdentityError
                };
            }
        }
        

        在此示例中,所有本地化身份错误消息都在名为 LocalizedIdentityErrorMessages 的资源文件中提供,并带有公共访问修饰符。

        您可以查看这些关于本地化的文章,它包含 GitHub 上的实时演示和示例项目。

        开发多元文化的网络应用程序: http://www.ziyad.info/en/articles/10-Developing_Multicultural_Web_Application

        本地化数据注释: http://www.ziyad.info/en/articles/16-Localizing_DataAnnotations

        本地化身份错误消息: http://www.ziyad.info/en/articles/20-Localizing_Identity_Error_Messages

        本地化 ModelBinding 错误消息: http://www.ziyad.info/en/articles/18-Localizing_ModelBinding_Error_Messages

        客户端验证: http://www.ziyad.info/en/articles/19-Client_Side_Validation

        【讨论】:

          猜你喜欢
          • 2021-08-13
          • 1970-01-01
          • 2023-04-06
          • 1970-01-01
          • 2022-12-03
          • 1970-01-01
          • 2022-10-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多