【问题标题】:How to localize ASP.NET Identity UserName and Password error messages?如何本地化 ASP.NET 标识用户名和密码错误消息?
【发布时间】:2013-11-26 12:26:53
【问题描述】:

是否可以为“系统”ASP.NET Identity v1 错误消息提供本地化字符串,例如“名称 XYZ 已被占用”或“用户名 XYZ 无效,可以只包含字母或数字”?

【问题讨论】:

  • 还没有,我们有一个跟踪此工作项的错误,以允许指定资源的来源:github.com/aspnet/Identity/issues/86。对于 3.0,我们有一些粗略的想法和原型,但还没有完全准备好签入。

标签: asp.net-identity


【解决方案1】:

对于 ASP.NET Core:(Microsoft.AspNetCore.Identity 1.0.0)

创建一个继承 IdentityErrorDescriber 的类并覆盖所需的错误消息。

public class CustomIdentityErrorDescriber : IdentityErrorDescriber
{
    public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"An unknown failure has occurred." }; }
    public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Optimistic concurrency failure, object has been modified." }; }
    public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Incorrect password." }; }
    public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Invalid token." }; }
    public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "A user with this login already exists." }; }
    public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"User name '{userName}' is invalid, can only contain letters or digits." }; }
    public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"Email '{email}' is invalid."  }; }
    public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"User Name '{userName}' is already taken."  }; }
    public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"Email '{email}' is already taken."  }; }
    public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"Role name '{role}' is invalid."  }; }
    public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"Role name '{role}' is already taken."  }; }
    public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "User already has a password set." }; }
    public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Lockout is not enabled for this user." }; }
    public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"User already in role '{role}'."  }; }
    public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"User is not in role '{role}'."  }; }
    public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"Passwords must be at least {length} characters."  }; }
    public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Passwords must have at least one non alphanumeric character." }; }
    public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Passwords must have at least one digit ('0'-'9')." }; }
    public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Passwords must have at least one lowercase ('a'-'z')." }; }
    public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Passwords must have at least one uppercase ('A'-'Z')." }; }
}

在您的 Startup 类中,在 ConfigureServices 中注册自定义 ErrorDescriber:

services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddErrorDescriber<CustomIdentityErrorDescriber>(); // Add this line

更新: 您可以在下面找到已翻译的西班牙语和葡萄牙语版本。仔细检查它们!

public class SpanishIdentityErrorDescriber : IdentityErrorDescriber
{
    public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"Ha ocurrido un error." }; }
    public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Ha ocurrido un error, el objeto ya ha sido modificado (Optimistic concurrency failure)." }; }
    public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Password Incorrecta." }; }
    public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Ha ingresado un código Inválido." }; }
    public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "Un usuario con ese nombre ya existe." }; }
    public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"El nombre de usuario '{userName}' es inválido. Solo puede contener letras y números." }; }
    public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"La dirección de email '{email}' es incorrecta."  }; }
    public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"El usuario '{userName}' ya existe, por favor ingrese un nombre diferente."  }; }
    public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"La direccion de email '{email}' ya se encuentra registrada. Puede recupar su contraseña para ingresar nuevamente al sistema."  }; }
    public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"El nombre de rol '{role}' es inválido."  }; }
    public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"El nombre de rol '{role}' ya existe."  }; }
    public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "El usuario ya tiene contraseña." }; }
    public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "El bloqueo no esta habilitado para este usuario." }; }
    public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"El usuario ya es parte del rol '{role}'."  }; }
    public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"El usuario no es parte del rol '{role}'."  }; }
    public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"La contraseña deben tener un largo mínimo de {length} caracteres."  }; }
    public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "La contraseña debe contener al menos un caracter alfanumérico." }; }
    public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "La contraseña debe incluir al menos un dígito ('0'-'9')." }; }
    public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "La contraseña debe incluir al menos una letra minúscula ('a'-'z')." }; }
    public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "La contraseña debe incluir al menos una letra MAYÚSCULA ('A'-'Z')." }; }
}

葡萄牙语:(非常感谢furlanrapha

public class PortugueseIdentityErrorDescriber : IdentityErrorDescriber
{
    public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"Um erro desconhecido ocorreu." }; }
    public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Falha de concorrência otimista, o objeto foi modificado." }; }
    public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Senha incorreta." }; }
    public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Token inválido." }; }
    public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "Já existe um usuário com este login." }; }
    public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"Login '{userName}' é inválido, pode conter apenas letras ou dígitos." }; }
    public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"Email '{email}' é inválido." }; }
    public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"Login '{userName}' já está sendo utilizado." }; }
    public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"Email '{email}' já está sendo utilizado." }; }
    public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"A permissão '{role}' é inválida." }; }
    public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"A permissão '{role}' já está sendo utilizada." }; }
    public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "Usuário já possui uma senha definida." }; }
    public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Lockout não está habilitado para este usuário." }; }
    public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"Usuário já possui a permissão '{role}'." }; }
    public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"Usuário não tem a permissão '{role}'." }; }
    public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"Senhas devem conter ao menos {length} caracteres." }; }
    public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Senhas devem conter ao menos um caracter não alfanumérico." }; }
    public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Senhas devem conter ao menos um digito ('0'-'9')." }; }
    public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Senhas devem conter ao menos um caracter em caixa baixa ('a'-'z')." }; }
    public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Senhas devem conter ao menos um caracter em caixa alta ('A'-'Z')." }; }
}

【讨论】:

  • 这是使用 MVC Core 时的好方法。
  • 如果我需要支持多种语言怎么办?是否有内置方法来区分不同的 ErrorDescriber,还是我需要自己做一些奇怪的修补?
  • @gilmishal 很好的问题。我没有这个要求,所以我不确定。我猜想检查 IdentityErrorDescriber 中的CurrentCulture 并相应地返回本地化错误消息,但这是混乱代码的秘诀。资源文件应该是正确的方式。看起来原始实现不可扩展(如果我错了,请纠正我)但使用 res 文件。克隆原始的originalErrorDescr + 它的资源文件,并为您的语言添加新资源,也许?
  • @gilmishal 尚无官方解决方案,请查看此问题以获取来自 MS 的更新:github.com/aspnet/Identity/issues/991#issuecomment-256516328
  • @gilmishal 你可以用IStringLocalizer 注入这个IdentityErrorDescriber 的构造函数。有关本地化,请参阅:docs.microsoft.com/en-us/aspnet/core/fundamentals/localization
【解决方案2】:

从 2014 年 3 月 20 日发布的身份版本 2 开始,您现在可以有本地化错误消息。

首先安装身份本地化包。

Install-Package Microsoft.AspNet.Identity.Core.fr

然后必须设置适当的文化才能获得本地化消息,例如设置文化的一种方法是在 web.config 中

<system.web>
      <globalization culture="fr-FR" uiCulture="fr"/>
</system.web>

【讨论】:

  • 很遗憾似乎没有瑞典语版本?不知道是否可以自己获取源并为瑞典语进行翻译?
  • 可以使用 .netReflector 等工具对 dll 进行反编译和重新编译以访问资源文件
  • @1AmirJaliali 我试过这个但失败了:(stackoverflow.com/questions/22835981/…任何指针?
  • 关于 Identity 2.0 多语言支持的任何更新?这样的库没有多语言支持简直荒谬!以您要使用的语言下载库的解决方法并不适合开发人员的所有需求,因为也许我还想根据我的应用程序的用户目标更改消息。加油女士!
  • 这个答案应该在顶部,因为所有其他答案都是相同的,即自定义实现,但这是某些语言的内置实现
【解决方案3】:

ASP NET Core 解决方法 (25.11.2016)

您可以将 IStringLocalizer 注入自定义 IdentityErrorDescriber

1) 创建自定义 IdentityErrorDescriber(请参阅 Gerardo Grignoli 答案)

public class MultilanguageIdentityErrorDescriber : IdentityErrorDescriber
{
    private readonly IStringLocalizer<SharedResource> _localizer;

    public MultilanguageIdentityErrorDescriber(IStringLocalizer<SharedResource> localizer)
    {
        _localizer = localizer;
    }

    public override IdentityError DuplicateEmail(string email)
    {
        return new IdentityError()
        {
            Code = nameof(DuplicateEmail),
            Description = string.Format(_localizer["Email {0} is already taken."], email)
        };
    }

    // DuplicateUserName, InvalidEmail, DuplicateUserName etc
}

2) 在 Startup.cs 中注册 MultilanguageIdentityErrorDescriber

services.AddIdentity<IdentityUser, IdentityRole>()
            .AddErrorDescriber<MultilanguageIdentityErrorDescriber>()
            .AddDefaultTokenProviders();

3) 向 SharedResource.language.resx 添加错误消息。

【讨论】:

  • 优秀的安德里尔!总是最好将资源放在资源文件中。也许我们可以合作把这段代码和一些常用语言的资源放在 github 甚至 NuGet 上。
  • @GerardoGrignoli 我对这种方法很满意,并在生产中使用它。不幸的是,我没有空闲时间来研究这个,但我在 github 上提交了这个想法。 github.com/aspnet/Identity/issues/991,也许它会帮助某人或 .NET Core 开发团队会接受这个想法。
  • 优秀的答案。也许我会补充说localizer不需要string.Format,你可以在[]中添加参数
【解决方案4】:

这是给亲爱的波斯语(波斯语)使用者的

using Microsoft.AspNetCore.Identity;

namespace WebApplication.Admin.Helpers
{
    public class CustomIdentityErrorDescriber : IdentityErrorDescriber
    {
        public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"یک خطای ناشناخته رخ داده است." }; }
        public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "رکورد جاری پیشتر ویرایش شده‌است و تغییرات شما آن‌را بازنویسی خواهد کرد." }; }
        public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "کلمه عبور نادرست است." }; }
        public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "کلمه عبور نامعتبر است." }; }
        public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "این کاربر قبلأ اضافه شده‌است." }; }
        public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"نام کاربری '{userName}' نامعتبر است، فقط می تواند حاوی حروف ویا اعداد باشد." }; }
        public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"ایمیل '{email}' نامعتبر است." }; }
        public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"این نام کاربری '{userName}' به کاربر دیگری اختصاص یافته است." }; }
        public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"ایمیل '{email}' به کاربر دیگری اختصاص یافته است." }; }
        public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"نام نقش '{role}' نامعتبر است." }; }
        public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"این نام نقش '{role}' به کاربر دیگری اختصاص یافته است." }; }
        public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "کلمه‌ی عبور کاربر قبلأ تنظیم شده‌است." }; }
        public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "این کاربر فعال است." }; }
        public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"این نقش '{role}' قبلأ به این کاربر اختصاص یافته است." }; }
        public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"این نقش '{role}' قبلأ به این کاربر اختصاص نیافته است." }; }
        public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"کلمه عبور باید حداقل {length} کاراکتر باشد." }; }
        public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "کلمه عبور باید حداقل یک کاراکتر غیر از حروف الفبا داشته باشد." }; }
        public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "کلمه عبور باید حداقل یک عدد داشته باشد." }; }
        public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "کلمه عبور باید حداقل یک حرف کوچک داشته باشد." }; }
        public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "کلمه عبور باید حداقل یک حرف بزرگ داشته باشد." }; }
        public override IdentityError RecoveryCodeRedemptionFailed() { return new IdentityError { Code = nameof(RecoveryCodeRedemptionFailed), Description = "بازیابی ناموفق بود." }; }
        public override IdentityError PasswordRequiresUniqueChars(int uniqueChars) { return new IdentityError { Code = nameof(PasswordRequiresUniqueChars), Description = $"کلمه عبور باید حداقل داراى {uniqueChars} حرف متفاوت باشد." }; }
    }
}

【讨论】:

  • 我们如何使用它?
【解决方案5】:

我遇到了同样的问题,并找到了一个快速而肮脏的解决方法。我使用 DotPeek 查看了 Microsoft.AspNet.Identity.Core 程序集(我假设任何 C# 反编译器都可以),并发现了两个负责此类消息的类:

  • Microsoft.AspNet.Identity.UserValidator&lt;TUser&gt;(用户名相关)
  • Microsoft.AspNet.Identity.MinimumLengthValidator(密码相关)

这些类不包含任何外部引用(除了要替换的字符串资源),因此在您自己的代码中重新实现它们应该相当简单。

这样做之后,别忘了在你的UserManager中正确使用它们:

UserManager.UserValidator = new MyCustomUserValidator<MyUserType>(UserManager);
UserManager.PasswordValidator = new MyCustomMinimumLengthValidator(6);

【讨论】:

【解决方案6】:

德语版@GerardoGrignoli 的解决方案

public class CustomIdentityErrorDescriber : IdentityErrorDescriber
{
    public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"Ein unbekannter Fehler ist aufgetreten." }; }
    public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Fehler bzgl. der Optimistischen Nebenläufigkeit, das Objekt wurde verändert." }; }
    public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Ungültiges Passwort." }; }
    public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Ungültiger Token." }; }
    public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "Es ist bereits ein Nutzer mit diesem Login vorhanden." }; }
    public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"Nutzername '{userName}' ist ungültig. Erlaubt sind nur Buchstaben und Zahlen." }; }
    public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"E-Mail '{email}' ist ungültig." }; }
    public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"Nutzername '{userName}' ist bereits vergeben." }; }
    public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"E-Mail '{email}' ist bereits vergeben." }; }
    public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"Rollen-Name '{role}' ist ungültig." }; }
    public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"Rollen-Name '{role}' ist bereits vergeben." }; }
    public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "Nutzer hat bereits ein Passwort gesetzt." }; }
    public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Aussperrung ist für diesen Nutzer nicht aktiviert." }; }
    public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"Nutzer ist bereits in Rolle '{role}'." }; }
    public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"Nutzer ist nicht in Rolle '{role}'." }; }
    public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"Passwörter müssen mindestens {length} Zeichen lang sein." }; }
    public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Passwörter müssen mindestens ein Sonderzeichen enthalten." }; }
    public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Passwörter müssen mindestens eine Ziffer enthalten ('0'-'9')." }; }
    public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Passwörter müssen mindestens einen Kleinbuchstaben enthalten ('a'-'z')." }; }
    public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Passwörter müssen mindestens einen Großbuchstaben enthalten ('A'-'Z')." }; }
}

【讨论】:

    【解决方案7】:

    1AmirJalali 的方法非常有效。虽然在 web.config 中设置文化是有效的,但如果需要,它也可以动态设置,这是如何实现的:

    Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName);
    Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
    

    在上面的代码示例中,cultureName 是要设置的文化名称。可以在此处的“备注”标题下找到文化列表: http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo%28v=vs.80%29.aspx

    希望这会有所帮助。

    【讨论】:

      【解决方案8】:

      您好,这是我翻译身份错误的解决方案:

       public string TranslateIdentityResult(string massage)
          {
      
              var list = new List<KeyValuePair<string, string>>() {
                  new KeyValuePair<string, string>("An unknown failure has occured.", "حدث خطأ غير معروف"),
                  new KeyValuePair<string, string>("Email '{0}' is already taken.", "هذا البريد '{0}' موجود بالفعل"),
                  new KeyValuePair<string, string>("Name {0} is already taken.", "الاسم {0} مأخوذ بالفعل."),
                  new KeyValuePair<string, string>("A user with that external login already exists.", "يوجد بالفعل مستخدم له معلومات تسجيل الدخول الخارجية."),
                  new KeyValuePair<string, string>("Email '{0}' is invalid.", "البريد الإلكتروني '{0}' غير صحيح."),
                  new KeyValuePair<string, string>("Invalid token.", "المفتاح غير صالح"),
                  new KeyValuePair<string, string>("User name {0} is invalid, can only contain letters or digits.", "اسم المستخدم {0} غير صالح ، يمكن أن يحتوي فقط على أحرف أو أرقام."),
                  new KeyValuePair<string, string>("Lockout is not enabled for this user.", "تأمين المستخدم غير متاح لهذا المستخدم"),
                  new KeyValuePair<string, string>("Incorrect password.", "الرقم السري غير صحيح"),
                  new KeyValuePair<string, string>("Passwords must have at least one digit ('0'-'9').", "الرقم السري يجب أ،ن يحتوي على الأقل رقم واحد (0-9)"),
                  new KeyValuePair<string, string>("Passwords must have at least one lowercase ('a'-'z').", "يجب أن تحتوي كلمات المرور على حرف صغير واحد على الأقل ('a' - 'z')."),
                  new KeyValuePair<string, string>("Passwords must have at least one non letter or digit character.", "يجب أن يكون لكلمة مرور حرف واحد على الأقل غير الحرف أو الرقم."),
                  new KeyValuePair<string, string>("Passwords must have at least one uppercase ('A'-'Z').", "يجب أن تحتوي كلمات المرور على حرف كبير واحد على الأقل ('A' - 'Z')."),
                  new KeyValuePair<string, string>("Passwords must be at least {0} characters.", "يجب أن تكون كلمات المرور على الأقل {0} حرفًا."),
                  new KeyValuePair<string, string>("{0} cannot be null or empty.", "لا يمكن أن يكون {0} خاليًا أو فارغًا."),
                  new KeyValuePair<string, string>("Role {0} does not exist.", "صلاحية {0} غير موجود."),
                  new KeyValuePair<string, string>("User already has a password set.", "المستخدم لديه بالفعل كلمة مرور محددة."),
                  new KeyValuePair<string, string>("User already in role.", "المستخدم بالفعل لديه هذي الصلاحية."),
                  new KeyValuePair<string, string>("UserId not found.", "لم يتم العثور على هوية المستخدم."),
                  new KeyValuePair<string, string>("User {0} does not exist.", "المستخدم {0} غير موجود."),
                  new KeyValuePair<string, string>("User is not in role.", "المستخدم ليس لديه صلاحية.")
              };
      
              return list.Find(x => x.Key.Equals(massage)).Value;
          }
      

       private void AddErrors(IdentityResult result)
          {
              foreach (var error in result.Errors)
              {
                  //if my function is not found error it will print it as it's
                  foreach(var msg in error.Split('.'))
                  {
                      ModelState.AddModelError("", accBClass.TranslateIdentityResult(msg.TrimStart(' ')) ?? msg);
                  }
              }
          }
      

      Example

      【讨论】:

        【解决方案9】:

        根据此处的答案,我为我们基于 MVC Core 2.2 构建的多语言网站制作了自己的实现,其中的字符串无法硬编码。

        我正在使用带有自动生成设计器的基本资源文件来获取字符串,执行此操作的代码如下所示:

        public class LocalizedIdentityErrorDescriber : IdentityErrorDescriber
        {
            private ResourceManager ResourceManager { get; set; }
        
            public LocalizedIdentityErrorDescriber()
            {
                ResourceManager = Translations.ResourceManager;
            }
        
            public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = Translations.Validation_DefaultError }; }
            public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = Translations.Validation_ConcurrencyFailure }; }
            public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = Translations.Validation_PasswordMismatch }; }
            public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = Translations.Validation_InvalidToken }; }
            public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = Translations.Validation_LoginAlreadyAssociated }; }
            public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = string.Format(Translations.Validation_InvalidUserName, userName) }; }
            public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = string.Format(Translations.Validation_InvalidEmail, email) }; }
            public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = string.Format(Translations.Validation_DuplicateUserName, userName) }; }
            public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = string.Format(Translations.Validation_DuplicateEmail, email) }; }
            public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = string.Format(Translations.Validation_InvalidRoleName, role) }; }
            public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = string.Format(Translations.Validation_DuplicateRoleName, role) }; }
            public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = Translations.Validation_UserAlreadyHasPassword }; }
            public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = Translations.Validation_UserLockoutNotEnabled }; }
            public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = string.Format(Translations.Validation_UserAlreadyInRole, role) }; }
            public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = string.Format(Translations.Validation_UserNotInRole, role) }; }
            public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = string.Format(Translations.Validation_PasswordTooShort, length) }; }
            public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = Translations.Validation_PasswordRequiresNonAlphanumeric }; }
            public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = Translations.Validation_PasswordRequiresDigit }; }
            public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = Translations.Validation_PasswordRequiresLower }; }
            public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = Translations.Validation_PasswordRequiresUpper }; }
        }
        

        然后将其集成到 Startup.cs 中的 Identity 管道中

        services.AddDefaultIdentity<User>()
            .AddErrorDescriber<LocalizedIdentityErrorDescriber>()
            .AddDefaultTokenProviders();
        

        最后,我在 Translations.resx 和子资源文件中定义了字符串,其中的键名为 Validation_DefaultError、Validation_PasswordMismatch 等。

        【讨论】:

          【解决方案10】:

          这个问题已经困扰了我很长一段时间,所以我试图想出一些通用的东西,因为为特定文化安装 Identity.Core 的解决方案只有在包完全可用的情况下才有效:)

          以下是我实现正确本地化的步骤:

          1. 使用ApplicationUserManager默认使用的dotPeak查看Microsoft.AspNet.Identity.PasswordValidator的实现,
          2. 然后我想出了我自己的class CustomPasswordValidator : PasswordValidator 实现并覆盖ValidateAsync 方法以不返回带有错误消息的IdentityResult,而是使用这些错误消息的“代码”,所有这些错误消息都以“CustomValidator”为前缀字符串。
          3. 然后在AccountController 中,我更改了AddErrors,它是从Register 帖子中调用的,以根据错误代码从我自己的资源文件中提供本地化错误消息。

          这里是 CustomPasswordValidator 和实用程序类 PasswordValidatorCodes,包含错误代码和根据这些代码检索本地化错误消息的方法(AccountStrings 是一个资源文件):

          public static class PasswordValidatorCodes
          {
              public const string ErrorCodePrefix = "CustomPassword";
              public const string PasswordTooShort = ErrorCodePrefix + "TooShort";
              public const string PasswordRequireNonLetterOrDigit = ErrorCodePrefix + "RequireNonLetterOrDigit";
              public const string PasswordRequireDigit = ErrorCodePrefix + "RequireDigit";
              public const string PasswordRequireLower = ErrorCodePrefix + "RequireLower";
              public const string PasswordRequireUpper = ErrorCodePrefix + "RequireUpper";
          
              public static string GetLocalizedMessageForCode(string code)
              {
                  switch (code)
                  {
                      case PasswordTooShort:
                          return string.Format(AccountStrings.ValidationPasswordTooShort, CustomPasswordValidator.RequiredPasswordLength);
                      case PasswordRequireNonLetterOrDigit:
                          return AccountStrings.ValidationPasswordRequireNonLetterOrDigit;
                      case PasswordRequireDigit:
                          return AccountStrings.ValidationPasswordRequireDigit;
                      case PasswordRequireLower:
                          return AccountStrings.ValidationPasswordRequireLower;
                      case PasswordRequireUpper:
                          return AccountStrings.ValidationPasswordRequireUpper;
                      default:
                          throw new ArgumentException("code");
                  }
              }
          }
          
          public class CustomPasswordValidator : PasswordValidator
          {
              public const int RequiredPasswordLength = 6;
          
              public CustomPasswordValidator()
              {
                  RequiredLength = RequiredPasswordLength;
                  RequireNonLetterOrDigit = false;
                  RequireDigit = true;
                  RequireLowercase = true;
                  RequireUppercase = false;
              }
          
              public override Task<IdentityResult> ValidateAsync(string item)
              {
                  if (item == null) throw new ArgumentNullException("item");
                  var list = new List<string>();
          
                  if (string.IsNullOrWhiteSpace(item) || item.Length < RequiredLength)
                  {
                      list.Add(PasswordValidatorCodes.PasswordTooShort);
                  }
          
                  if (RequireNonLetterOrDigit && item.All(IsLetterOrDigit))
                  {
                      list.Add(PasswordValidatorCodes.PasswordRequireNonLetterOrDigit);
                  }
          
                  if (RequireDigit && item.All(c => !IsDigit(c)))
                  {
                      list.Add(PasswordValidatorCodes.PasswordRequireDigit);
                  }
          
                  if (RequireLowercase && item.All(c => !IsLower(c)))
                  {
                      list.Add(PasswordValidatorCodes.PasswordRequireLower);
                  }
          
                  if (RequireUppercase && item.All(c => !IsUpper(c)))
                  {
                      list.Add(PasswordValidatorCodes.PasswordRequireUpper);
                  }
          
                  return Task.FromResult(list.Count == 0
                      ? IdentityResult.Success
                      : new IdentityResult(list));
              }
          }
          

          这里是修改后的AccountController.AddErrors 方法。如您所见,我正在为属性Password 的模型添加一个错误,因为如果Password 未通过验证,那么我希望Password 字段而不是验证摘要中显示错误消息。这是我的CustomPasswordValidator 直接生成错误代码而不是错误消息的唯一原因:

          private void AddErrors(IdentityResult result)
          {
              foreach (var error in result.Errors)
              {
                  if (error.StartsWith(PasswordValidatorCodes.ErrorCodePrefix))
                  {
                      ModelState.AddModelError("Password", PasswordValidatorCodes.GetLocalizedMessageForCode(error));
                      continue;
                  }
                  ModelState.AddModelError(string.Empty, error);
              }
          }
          

          最后,别忘了修改IdentityConfig文件,即:

          manager.PasswordValidator = new CustomPasswordValidator();
          

          更新:

          直到现在我才注意到 Marselus Chia(请参阅其他答案)提出了类似的解决方案,但针对 VB。

          【讨论】:

            【解决方案11】:

            我不想重写逻辑(即重新发明轮子),也不想切换到 ASP NET Core。我想要做的就是覆盖错误消息并使用多个资源文件(每种语言)来根据他们选择的语言定制用户体验。

            这是我的解决方案:

            1. 我使用以下内容创建了一个“IdentityErrors.resx”资源文件:

              <data name="DefaultError" xml:space="preserve">
                  <value>An unknown failure has occured.</value>
              </data>
              <data name="DuplicateEmail" xml:space="preserve">
                  <value>Email '{0}' is already taken.</value>
              </data>
              <data name="DuplicateName" xml:space="preserve">
                  <value>Name {0} is already taken.</value>
              </data>
              <data name="ExternalLoginExists" xml:space="preserve">
                  <value>A user with that external login already exists.</value>
              </data>
              <data name="InvalidEmail" xml:space="preserve">
                  <value>Email '{0}' is invalid.</value>
              </data>
              <data name="InvalidToken" xml:space="preserve">
                  <value>Invalid token.</value>
              </data>
              <data name="InvalidUserName" xml:space="preserve">
                  <value>User name {0} is invalid, can only contain letters or digits.</value>
              </data>
              <data name="LockoutNotEnabled" xml:space="preserve">
                  <value>Lockout is not enabled for this user.</value>
              </data>
              <data name="NoTokenProvider" xml:space="preserve">
                  <value>No IUserTokenProvider is registered.</value>
              </data>
              <data name="NoTwoFactorProvider" xml:space="preserve">
                  <value>No IUserTwoFactorProvider for '{0}' is registered.</value>
              </data>
              <data name="PasswordMismatch" xml:space="preserve">
                  <value>Incorrect password.</value>
              </data>
              <data name="PasswordRequireDigit" xml:space="preserve">
                  <value>Passwords must have at least one digit ('0'-'9').</value>
              </data>
              <data name="PasswordRequireLower" xml:space="preserve">
                  <value>Passwords must have at least one lowercase ('a'-'z').</value>
              </data>
              <data name="PasswordRequireNonLetterOrDigit" xml:space="preserve">
                  <value>Passwords must have at least one non letter or digit character.</value>
              </data>
              <data name="PasswordRequireUpper" xml:space="preserve">
                  <value>Passwords must have at least one uppercase ('A'-'Z').</value>
              </data>
              <data name="PasswordTooShort" xml:space="preserve">
                  <value>Passwords must be at least {0} characters.</value>
              </data>
              <data name="PropertyTooShort" xml:space="preserve">
                  <value>{0} cannot be null or empty.</value>
              </data>
              <data name="RoleNotFound" xml:space="preserve">
                  <value>Role {0} does not exist.</value>
              </data>
              <data name="StoreNotIQueryableRoleStore" xml:space="preserve">
                  <value>Store does not implement IQueryableRoleStore&amp;lt;TRole&amp;gt;.</value>
              </data>
              <data name="StoreNotIQueryableUserStore" xml:space="preserve">
                  <value>Store does not implement IQueryableUserStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserClaimStore" xml:space="preserve">
                  <value>Store does not implement IUserClaimStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserConfirmationStore" xml:space="preserve">
                  <value>Store does not implement IUserConfirmationStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserEmailStore" xml:space="preserve">
                  <value>Store does not implement IUserEmailStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserLockoutStore" xml:space="preserve">
                  <value>Store does not implement IUserLockoutStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserLoginStore" xml:space="preserve">
                  <value>Store does not implement IUserLoginStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserPasswordStore" xml:space="preserve">
                  <value>Store does not implement IUserPasswordStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserPhoneNumberStore" xml:space="preserve">
                  <value>Store does not implement IUserPhoneNumberStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserRoleStore" xml:space="preserve">
                  <value>Store does not implement IUserRoleStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserSecurityStampStore" xml:space="preserve">
                  <value>Store does not implement IUserSecurityStampStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="StoreNotIUserTwoFactorStore" xml:space="preserve">
                  <value>Store does not implement IUserTwoFactorStore&amp;lt;TUser&amp;gt;.</value>
              </data>
              <data name="UserAlreadyHasPassword" xml:space="preserve">
                  <value>User already has a password set.</value>
              </data>
              <data name="UserAlreadyInRole" xml:space="preserve">
                  <value>User already in role.</value>
              </data>
              <data name="UserIdNotFound" xml:space="preserve">
                  <value>UserId not found.</value>
              </data>
              <data name="UserNameNotFound" xml:space="preserve">
                  <value>User {0} does not exist.</value>
              </data>
              <data name="UserNotInRole" xml:space="preserve">
                  <value>User is not in role.</value>
              </data>
              
            2. 我创建了一个“IdentityResultErrorMessages.cs”类:

              public class IdentityResultErrorMessages
              {
                public static List<String> GetResourceEquivalent(IEnumerable<string> errors)
                {
                  List<String> errorList = new List<String>();
                  if (errors != null)
                  {
                    foreach (String error in errors)
                    {
                      if (error.StartsWith("An unknown failure has occured."))
                      {
                        errorList.Add(IdentityErrors.DefaultError);
                      }
                      else if (error.StartsWith("Email '") && error.EndsWith("' is already taken."))
                      {
                        errorList.Add(String.Format(IdentityErrors.DuplicateEmail, error.Replace("Email '", "").Replace("' is already taken.", "")));
                      }
                      else if (error.StartsWith("Name ") && error.EndsWith(" is already taken."))
                      {
                        errorList.Add(String.Format(IdentityErrors.DuplicateName, error.Replace("Name ", "").Replace(" is already taken.", "")));
                      }
                      else if (error.StartsWith("A user with that external login already exists."))
                      {
                        errorList.Add(IdentityErrors.ExternalLoginExists);
                      }
                      else if (error.StartsWith("Email '") && error.EndsWith("' is invalid."))
                      {
                        errorList.Add(String.Format(IdentityErrors.InvalidEmail, error.Replace("Email '", "").Replace("' is invalid.", "")));
                      }
                      else if (error.StartsWith("Invalid token."))
                      {
                        errorList.Add(IdentityErrors.InvalidToken);
                      }
                      else if (error.StartsWith("User name ") && error.EndsWith(" is invalid, can only contain letters or digits."))
                      {
                        errorList.Add(String.Format(IdentityErrors.InvalidUserName, error.Replace("User name ", "").Replace(" is invalid, can only contain letters or digits.", "")));
                      }
                      else if (error.StartsWith("Lockout is not enabled for this user."))
                      {
                        errorList.Add(IdentityErrors.LockoutNotEnabled);
                      }
                      else if (error.StartsWith("No IUserTokenProvider is registered."))
                      {
                        errorList.Add(IdentityErrors.NoTokenProvider);
                      }
                      else if (error.StartsWith("No IUserTwoFactorProvider for '") && error.EndsWith("' is registered."))
                      {
                        errorList.Add(String.Format(IdentityErrors.NoTwoFactorProvider, error.Replace("No IUserTwoFactorProvider for '", "").Replace("' is registered.", "")));
                      }
                      else if (error.StartsWith("Incorrect password."))
                      {
                        errorList.Add(IdentityErrors.PasswordMismatch);
                      }
                      else if (error.StartsWith("Passwords must have at least one digit ('0'-'9')."))
                      {
                        errorList.Add(IdentityErrors.PasswordRequireDigit);
                      }
                      else if (error.StartsWith("Passwords must have at least one lowercase ('a'-'z')."))
                      {
                        errorList.Add(IdentityErrors.PasswordRequireLower);
                      }
                      else if (error.StartsWith("Passwords must have at least one non letter or digit character."))
                      {
                        errorList.Add(IdentityErrors.PasswordRequireNonLetterOrDigit);
                      }
                      else if (error.StartsWith("Passwords must have at least one uppercase ('A'-'Z')."))
                      {
                        errorList.Add(IdentityErrors.PasswordRequireUpper);
                      }
                      else if (error.StartsWith("Passwords must be at least ") && error.EndsWith(" characters."))
                      {
                        errorList.Add(String.Format(IdentityErrors.PasswordTooShort, error.Replace("Passwords must be at least ", "").Replace(" characters.", "")));
                      }
                      else if (error.EndsWith(" cannot be null or empty."))
                      {
                        errorList.Add(String.Format(IdentityErrors.PropertyTooShort, error.Replace(" cannot be null or empty.", "")));
                      }
                      else if (error.StartsWith("Role ") && error.EndsWith(" does not exist."))
                      {
                        errorList.Add(String.Format(IdentityErrors.RoleNotFound, error.Replace("Role ", "").Replace(" does not exist.", "")));
                      }
                      else if (error.StartsWith("Store does not implement IQueryableRoleStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIQueryableRoleStore);
                      }
                      else if (error.StartsWith("Store does not implement IQueryableUserStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIQueryableUserStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserClaimStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserClaimStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserConfirmationStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserConfirmationStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserEmailStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserEmailStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserLockoutStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserLockoutStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserLoginStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserLoginStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserPasswordStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserPasswordStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserPhoneNumberStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserPhoneNumberStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserRoleStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserRoleStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserSecurityStampStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserSecurityStampStore);
                      }
                      else if (error.StartsWith("Store does not implement IUserTwoFactorStore"))
                      {
                        errorList.Add(IdentityErrors.StoreNotIUserTwoFactorStore);
                      }
                      else if (error.StartsWith("User already has a password set."))
                      {
                        errorList.Add(IdentityErrors.UserAlreadyHasPassword);
                      }
                      else if (error.StartsWith("User already in role."))
                      {
                        errorList.Add(IdentityErrors.UserAlreadyInRole);
                      }
                      else if (error.StartsWith("UserId not found."))
                      {
                        errorList.Add(IdentityErrors.UserIdNotFound);
                      }
                      else if (error.StartsWith("User ") && error.EndsWith(" does not exist."))
                      {
                        errorList.Add(String.Format(IdentityErrors.UserNameNotFound, error.Replace("User ", "").Replace(" does not exist.", "")));
                      }
                      else if (error.StartsWith("User is not in role."))
                      {
                        errorList.Add(IdentityErrors.UserNotInRole);
                      }
                    }
                  }
                  return errorList;
                }
              }
              
            3. 我将 Controller 的 AddErrors 方法更改为以下内容:

              private void AddErrors(IdentityResult result)
              {
                foreach (var error in IdentityResultErrorMessages.GetResourceEquivalent(result.Errors))
                {
                  ModelState.AddModelError("", error);
                }
              }
              

            现在,我可以为我想在我的网站上提供的其他语言内容创建资源文件。

            【讨论】:

            • 一旦有人更改原始英文错误消息,此解决方案就会失败。我不建议这样做..
            【解决方案12】:

            这里是Gerardo Grignoli's answer 法语翻译

            /// <inheritdoc />
            /// <summary>
            /// Service to enable localization (french) for application facing identity errors.
            /// </summary>
            public class FrenchIdentityErrorDescriber : IdentityErrorDescriber
            {
                /// <inheritdoc />
                public override IdentityError DefaultError() => new IdentityError { Code = nameof(DefaultError), Description = "Une erreur inconnue est survenue." };
            
                /// <inheritdoc />
                public override IdentityError ConcurrencyFailure() => new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Erreur de concurrence simultanée optimiste, l'objet a été modifié." };
            
                /// <inheritdoc />
                public override IdentityError PasswordMismatch() => new IdentityError { Code = nameof(PasswordMismatch), Description = "Mot de passe incorrect." };
            
                /// <inheritdoc />
                public override IdentityError InvalidToken() => new IdentityError { Code = nameof(InvalidToken), Description = "Jeton invalide." };
            
                /// <inheritdoc />
                public override IdentityError LoginAlreadyAssociated() => new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "Un utilisateur avec ce nom de compte existe déjà." };
            
                /// <inheritdoc />
                public override IdentityError InvalidUserName(string userName) => new IdentityError { Code = nameof(InvalidUserName), Description = $"Le nom de compte '{userName}' est invalide. Seuls les lettres et chiffres sont autorisés." };
            
                /// <inheritdoc />
                public override IdentityError InvalidEmail(string email) => new IdentityError { Code = nameof(InvalidEmail), Description = $"L'email '{email}' est invalide." };
            
                /// <inheritdoc />
                public override IdentityError DuplicateUserName(string userName) => new IdentityError { Code = nameof(DuplicateUserName), Description = $"Le nom de compte '{userName}' est déjà utilisé." };
            
                /// <inheritdoc />
                public override IdentityError DuplicateEmail(string email) => new IdentityError { Code = nameof(DuplicateEmail), Description = $"L'email '{email} est déjà utilisée." };
            
                /// <inheritdoc />
                public override IdentityError InvalidRoleName(string role) => new IdentityError { Code = nameof(InvalidRoleName), Description = $"Le nom du rôle '{role}' est invalide." };
            
                /// <inheritdoc />
                public override IdentityError DuplicateRoleName(string role) => new IdentityError { Code = nameof(DuplicateRoleName), Description = $"Le nom du rôle '{role}' est déjà utilisé." };
            
                /// <inheritdoc />
                public override IdentityError UserAlreadyHasPassword() => new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "L'utilisateur a déjà un mot de passe." };
            
                /// <inheritdoc />
                public override IdentityError UserLockoutNotEnabled() => new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Le verouillage n'est pas activé pour cet utilisateur." };
            
                /// <inheritdoc />
                public override IdentityError UserAlreadyInRole(string role) => new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"L'utilisateur a déjà le rôle '{role}'." };
            
                /// <inheritdoc />
                public override IdentityError UserNotInRole(string role) => new IdentityError { Code = nameof(UserNotInRole), Description = $"L'utilisateur n'a pas le rôle '{role}'." };
            
                /// <inheritdoc />
                public override IdentityError PasswordTooShort(int length) => new IdentityError { Code = nameof(PasswordTooShort), Description = $"Le mot de passe doit contenir au moins {length} caractères." };
            
                /// <inheritdoc />
                public override IdentityError PasswordRequiresNonAlphanumeric() => new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Le mot de passe doit contenir au moins un caractère non alpha-numérique." };
            
                /// <inheritdoc />
                public override IdentityError PasswordRequiresDigit() => new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Le mot de passe doit contenir au moins un chiffre ('0'-'9')." };
            
                /// <inheritdoc />
                public override IdentityError PasswordRequiresLower() => new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Le mot de passe doit contenir au moins un charactère minuscule ('a'-'z')." };
            
                /// <inheritdoc />
                public override IdentityError PasswordRequiresUpper() => new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Le mot de passe doit contenir au moins un charactère majuscule ('A'-'Z')." };
            }
            

            【讨论】:

              【解决方案13】:

              除了@Gerardo Grinolli 回答这个俄语翻译版本:

              public class CustomIdentityErrorDescriber : IdentityErrorDescriber
              {
                  public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"Произошла неизвестная ошибка" }; }
                  public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Ошибка оптимистичного контроля параллелизма, объект был изменён" }; }
                  public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Некорретный пароль" }; }
                  public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Недействительный токен" }; }
                  public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "Пользователь с таким логином уже существует" }; }
                  public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"Имя пользователя '{userName}' некорректно, может содержать только буквы и цифры" }; }
                  public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"Email '{email}' некорректен" }; }
                  public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"Пользователь с именем '{userName}' уже существует" }; }
                  public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"Email '{email}' уже используется" }; }
                  public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"Имя роли '{role}' некорректно" }; }
                  public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"Имя роли '{role}' уже используется" }; }
                  public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "Пользователь уже установил пароль" }; }
                  public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Блокировка недоступна для этого пользователя" }; }
                  public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"Пользователю уже присвоена роль '{role}'." }; }
                  public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"У пользователя нет роли '{role}'." }; }
                  public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"Пароль должен быть длиной не менее {length} символов" }; }
                  public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Пароль должен быть содержать хотя бы один не буквенно-цифровой символ" }; }
                  public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Пароль должен содержать хотя бы одну цифру ('0'-'9')." }; }
                  public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Пароль должен содержать хотя бы один символ в нижнем регистре ('a'-'z')." }; }
                  public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Пароль должен содержать хотя бы один символ в верхнем регистре ('A'-'Z')" }; }
              }
              

              【讨论】:

                【解决方案14】:

                波兰语版本

                public class CustomErrorDescriber : IdentityErrorDescriber
                {
                    public override IdentityError DefaultError() {      return new IdentityError { Code = nameof(DefaultError), Description = $"Wystąpił nieanany błąd." }; }
                    public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Błąd współbieżności, obiekt został zmodyfikowany." }; }
                    public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Nieprawidłowe hasło." }; }
                    public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Nieprawidłowy token." }; }
                    public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "Użytkownik o takiej nazwie już istnieje." }; }
                    public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"Nazwa użytkownika \"'{userName}'\" jest nieprawidłowa, może posiadać tylko znaki i cyfry." }; }
                    public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"Email \"'{email}'\" jest nieprawidłowy." }; }
                    public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"Nazwa użytkownika \"'{userName}'\" jest zajęta." }; }
                    public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"Adres \"'{email}'\" jest zajęty." }; }
                    public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"Grupa \"'{role}'\" jest nieprawidłowa." }; }
                    public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"Nazwa grupy \"'{role}'\" jest zajęta." }; }
                    public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "Hasło użytkownika jest już ustawione." }; }
                    public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Blokada nie jest ustawiona dla tego użytkownika." }; }
                    public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"Użytkownik ma już przypisaną grupę \"'{role}'\"." }; }
                    public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"Użytkownik nie należy do grupy \"'{role}'\"." }; }
                    public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"Hasło musi posiadać conajmniej {length} znaków." }; }
                    public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Hasło musi posiadać przynajmniej jeden znak alfanumeryczny." }; }
                    public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Hasło musi posiadać przynajmniej jedną cyfrę ('0'-'9')." }; }
                    public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Hasło musi posiadać przynajmniej jedną małą literę ('a'-'z')." }; }
                    public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Hasło musi posiadać przynajmniej jedną wielką literę ('A'-'Z')." }; }
                    public override IdentityError PasswordRequiresUniqueChars(int uniqueChars) { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Hasło musi posiadać przynajmniej jeden znak specjalny." }; }
                }
                

                【讨论】:

                  【解决方案15】:

                  这是 IdentityErrorDescriber 的土耳其语翻译

                  using Microsoft.AspNetCore.Identity;
                  
                  
                  public class TurkishIdentityErrorDescriber : IdentityErrorDescriber
                  {
                      public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"Bilinmeyen bir hata meydana geldi." }; }
                      public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Bir eşzamanlılık hatası meydana geldi lütfen tekrar deneyin." }; }
                      public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Şifreler eşleşmiyor." }; }
                      public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Üretilen eşleştirme kodu geçerli değil." }; }
                      public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "Bu bilgilere sahip bir kullanıcı sistemde zaten var." }; }
                      public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"'{userName}', bu kullanıcı adı geçersiz; sadece harf ve sayı kullanın." }; }
                      public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"'{email}', bu e-posta adresi geçersiz." }; }
                      public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"'{userName}', bu kullanıcı adı zaten kullanımda." }; }
                      public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"'{email}', bu e-posta adresi zaten kullanımda." }; }
                      public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"'{role}', bu rol adı geçerli değil." }; }
                      public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"'{role}', bu rol adı zaten kullanımda." }; }
                      public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "Bu kullanıcı için zaten bir şifre atanmış durumda." }; }
                      public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Bu kullanıcı için giriş engelleme özelliği aktif değil." }; }
                      public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"Kullanıcı zaten '{role}' adlı role sahip." }; }
                      public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"Kullanıcı '{role}' adlı role sahip değil." }; }
                      public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"Parola en az {length} uzunluğunda olmalı." }; }
                      public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Parola en az bir özel karakter içermelidir (örn. *,!_- vb.)." }; }
                      public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Parola en az bir rakam içermelidir." }; }
                      public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Parola en az bir küçük harf içermelidir. ('a'-'z')." }; }
                      public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Parola en az bir büyük harf içermelidir. ('A'-'Z')." }; }
                  
                  }
                  

                  【讨论】:

                    【解决方案16】:

                    让我用西班牙语与您分享我为实现这一目标所做的工作。在那里您可以轻松自定义消息!

                    string Errores = result.Errors.FirstOrDefault();
                    Errores = Errores.Replace("Name " + Email.Text + " is already taken.", "- El mail " + Email.Text + " ya fue registrado. Intente recuperar la clave.<br/>");
                    Errores = Errores.Replace("Passwords must be at least 6 characters.", "- La clave debe contener por lo menos 6 caracteres.<br/>");
                    Errores = Errores.Replace("Passwords must have at least one non letter or digit character.", "- La clave debe contener por lo menos un caracter que no sea letra ni dígito. Por ejemplo: un punto.<br/>");
                    Errores = Errores.Replace("Passwords must have at least one digit ('0'-'9').", "- La clave debe contener al menos un dígito (entre 0 y 9).<br/>");
                    Errores = Errores.Replace("Passwords must have at least one uppercase ('A'-'Z').", "- La clave debe contener al menos una letra (entre A y Z).<br/>");
                    ErrorMessage.Text = "Errores:<br/><br/>" + Errores;
                    

                    【讨论】:

                      【解决方案17】:

                      乌克兰语翻译Andrew Basarab answer

                      资源文件数据:

                      <data name="ConcurrencyFailure" xml:space="preserve">
                        <value>Помилка паралельності, об’єкт змінено.</value>
                      </data>
                      <data name="DefaultError" xml:space="preserve">
                        <value>Сталася невідома помилка.</value>
                      </data>
                      <data name="DuplicateEmail" xml:space="preserve">
                        <value>Адреса '{0}' зайнята.</value>
                      </data>
                      <data name="DuplicateRoleName" xml:space="preserve">
                        <value>Ім'я групи '{0}' зайняте.</value>
                      </data>
                      <data name="DuplicateUserName" xml:space="preserve">
                        <value>Ім'я користувача '{0}' зайняте.</value>
                      </data>
                      <data name="InvalidEmail" xml:space="preserve">
                        <value>Неприпустима адреса Email '{0}'.</value>
                      </data>
                      <data name="InvalidRoleName" xml:space="preserve">
                        <value>Неприпустима назва групи '{0}'.</value>
                      </data>
                      <data name="InvalidToken" xml:space="preserve">
                        <value>Недійсний або невірний токен.</value>
                      </data>
                      <data name="InvalidUserName" xml:space="preserve">
                        <value>Неприпустиме ім'я користувача '{0}', ім'я може містити тільки символи і цифри.</value>
                      </data>
                      <data name="LoginAlreadyAssociated" xml:space="preserve">
                        <value>Користувач з таким іменем вже існує.</value>
                      </data>
                      <data name="PasswordMismatch" xml:space="preserve">
                        <value>Невірний пароль.</value>
                      </data>
                      <data name="PasswordRequiresDigit" xml:space="preserve">
                        <value>Пароль повинен мати хоча б одну цифру ('0'-'9').</value>
                      </data>
                      <data name="PasswordRequiresLower" xml:space="preserve">
                        <value>Пароль повинен мати як мінімум одну малу літеру ('a'-'z').</value>
                      </data>
                      <data name="PasswordRequiresNonAlphanumeric" xml:space="preserve">
                        <value>Пароль повинен мати хоча б один буквенно-цифровий символ.</value>
                      </data>
                      <data name="PasswordRequiresUniqueChars" xml:space="preserve">
                        <value>Пароль повинен мати {0} спеціальних символів.</value>
                      </data>
                      <data name="PasswordRequiresUpper" xml:space="preserve">
                        <value>Пароль повинен мати хоча б одну велику літеру ('A'-'Z').</value>
                      </data>
                      <data name="PasswordTooShort" xml:space="preserve">
                        <value>Пароль повинен містити як мінімум {0} символів.</value>
                      </data>
                      <data name="UserAlreadyHasPassword" xml:space="preserve">
                        <value>Пароль користувача вже встановлений.</value>
                      </data>
                      <data name="UserAlreadyInRole" xml:space="preserve">
                        <value>Користувач вже має призначену групу '{0}'.</value>
                      </data>
                      <data name="UserLockoutNotEnabled" xml:space="preserve">
                        <value>Блокування не встановлено для цього користувача.</value>
                      </data>
                      <data name="UserNotInRole" xml:space="preserve">
                        <value>Користувач не входить до групи '{0}'.</value>
                      </data>
                      

                      【讨论】:

                        【解决方案18】:

                        我的解决方案是创建新的自定义密码验证类,继承自 Microsoft.AspNet.Identity.PasswordValidator,覆盖发出错误消息的 ValidateAsync。 在此处自定义错误消息,它对我有用...

                        这些类假定您有一个全局资源文件名验证器。 这些类的脚本和资源文件示例可以在这里找到ASP.NET Identity - Codeplex Sample Code

                        这是我在 vb.net 中的示例工作代码


                        Imports System.Threading.Tasks 
                        
                        Imports Microsoft.AspNet.Identity
                        
                        Namespace MyNameSpace
                        
                        Public Class MyPasswordValidator
                            Inherits PasswordValidator
                            Public Overrides Function ValidateAsync(item As String) As Task(Of IdentityResult)
                                Dim errorMessage As String = String.Empty
                                Dim bolminChar As Boolean = True
                                Dim bolminDigit As Boolean = True
                                Dim bolminLcase As Boolean = True
                                Dim bolminUCase As Boolean = True
                                Dim bolminNonAlfanum As Boolean = True
                        
                                If Not String.IsNullOrWhiteSpace(item) AndAlso item.Length >= Me.RequiredLength Then
                                    bolminChar = True
                                Else
                                    bolminChar = False
                                    errorMessage = String.Format(CultureInfo.CurrentCulture, Resources.validator.PasswordTooShort & "<br/>", RequiredLength)
                                End If
                        
                                If Me.RequireDigit Then
                                    Dim regex As New Regex("^(?=.*\d).+$")
                                    Dim match As Match = regex.Match(item)
                                    If match.Success Then
                                        bolminDigit = True
                                    Else
                                        bolminDigit = False
                                        errorMessage &= Resources.validator.PasswordRequireDigit & ".<br/>"
                                    End If
                                End If
                        
                                If Me.RequireLowercase Then
                                    Dim LCrex As New Regex("^(?=.*[a-z]).+$")
                                    Dim LCMatch As Match = LCrex.Match(item)
                                    If LCMatch.Success Then
                                        bolminLcase = True
                                    Else
                                        bolminLcase = False
                                        errorMessage &= Resources.validator.PasswordRequireLower & "<br/>"
                                    End If
                                End If
                        
                                If Me.RequireNonLetterOrDigit Then
                                    Dim NAFRex As New Regex("^(?=.*[-+_!@#$%=^\[\]\{\}()&*.,?]).+$")
                                    Dim NAFMatch As Match = NAFRex.Match(item)
                                    If NAFMatch.Success Then
                                        bolminNonAlfanum = True
                                    Else
                                        bolminNonAlfanum = False
                                        errorMessage &= Resources.validator.PasswordRequireNonLetterOrDigit & "<br/>"
                                    End If
                                End If
                        
                                If Me.RequireUppercase Then
                                    Dim UCrex As New Regex("^(?=.*[A-Z]).+$")
                                    Dim UCMatch As Match = UCrex.Match(item)
                                    If UCMatch.Success Then
                                        bolminUCase = True
                                    Else
                                        bolminUCase = False
                                        errorMessage &= Resources.validator.PasswordRequireUpper & "<br/>"
                                    End If
                                End If
                        
                                If bolminChar And bolminDigit And bolminLcase And bolminNonAlfanum And bolminUCase Then
                                    Return Task.FromResult(Of IdentityResult)(IdentityResult.Success)
                                Else
                                    Return Task.FromResult(Of IdentityResult)(IdentityResult.Failed(New String() {errorMessage}))
                                End If
                                'Return MyBase.ValidateAsync(item)
                            End Function
                        End Class
                        
                        Public Class MyUserValidator
                            Inherits UserValidator(Of applicationUser, int64)
                            Private _manager As ApplicationUserManager
                        
                            Public Sub New(manager As ApplicationUserManager)
                                MyBase.New(manager)
                                _manager = manager
                            End Sub
                        
                            Public Overrides Function ValidateAsync(item As applicationUser) As Task(Of IdentityResult)
                                If item Is Nothing Then
                                    Throw New ArgumentNullException("item")
                                End If
                        
                                Dim errors As New List(Of String)()
                                Validateusername(item, errors)
                        
                                If Me.RequireUniqueEmail Then
                                    ValidateEmail(item, errors)
                                End If
                        
                                If errors.Count > 0 Then
                                    Return Task.FromResult(Of IdentityResult)(IdentityResult.Failed(errors.ToArray()))
                                End If
                                Return Task.FromResult(Of IdentityResult)(IdentityResult.Success)
                            End Function
                        
                            Private Sub Validateusername(User As applicationUser, errors As List(Of String))
                                If String.IsNullOrWhiteSpace(User.UserName) Then
                                    errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.validator.PropertyTooShort, "Email")) '
                                ElseIf Me.AllowOnlyAlphanumericUserNames AndAlso Not Regex.IsMatch(User.UserName, "^[A-Za-z0-9@_\.]+$") Then
                                    ' If any characters are not letters or digits, its an illegal user name
                                    errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.validator.InvalidUserName, User.UserName))
                                Else
                                    Dim owner = _manager.FindByName(User.UserName)
                                    If owner IsNot Nothing AndAlso Not EqualityComparer(Of applicationUser).ReferenceEquals(owner.Id, User.Id) Then
                                        errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.validator.DuplicateName, User.UserName))
                                    End If
                                End If
                            End Sub
                        
                            Private Sub ValidateEmail(User As ApplicationUser, errors As List(Of String))
                                Dim email As String = String.Empty
                        
                                If User.Id > 0 Then
                                    email = _manager.GetEmail(User.Id)
                                End If
                                If String.IsNullOrWhiteSpace(email) Then
                                    errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.validator.PropertyTooShort, "Email"))
                                    Return
                                End If
                        
                                Try
                                    Dim m As New MailAddress(email)
                                Catch ex As Exception
                                    errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.validator.InvalidEmail, email))
                                    Return
                                End Try
                                Dim owner = _manager.FindByEmail(email)
                                If owner IsNot Nothing AndAlso Not EqualityComparer(Of ApplicationUser).ReferenceEquals(owner.Id, User.Id) Then
                                    errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.validator.DuplicateName, email))
                                End If
                            End Sub
                        End Class
                        

                        记得更新 identityConfig.vb 文件中的设置以使用这些类。

                        【讨论】:

                          【解决方案19】:

                          我的解决方案有点脏,但它按预期工作。我们的想法是分配 IdentityResult 对象 result 在我们注册新用户时带来的所有错误:

                          var result = await UserManager.CreateAsync(user, model.Password);
                          

                          我们将创建一个新的。首先,我们需要创建一个包含自定义错误的列表:

                          var erroresEspanol = new List<string>();
                          

                          然后,我们需要遍历 result 中的错误,并根据导致错误的原因(重复用户、电子邮件等)为每个错误添加一个新的自定义错误:

                          foreach (var error in result.Errors)
                                      {
                                          if (error == ("Name " + model.Usuario + " is already taken."))
                                          {
                                              erroresEspanol.Add("El Usuario " + model.Usuario + " ya existe.");
                                          }
                                          if (error.Substring(0, error.IndexOf(" ")) == "Email")
                                          {
                                              erroresEspanol.Add("El Email " + model.Email + " ya fue ingresado.");
                                          }
                                          if (error.Substring(0, error.IndexOf(" ")) == "Passwords")
                                          {
                                              erroresEspanol.Add("La contraseña debe contener mayúscula, minúscula y al menos 6 caracteres de longitud.");
                                          }
                                      }
                          

                          所以之后我们只需创建一个新的 IdentityResult 对象:

                          var resultado = new IdentityResult(erroresEspanol);
                          

                          并在我们的注册操作结束时将其传递给 AddErrors 方法:

                          AddErrors(resultado);
                          

                          【讨论】:

                            【解决方案20】:

                            遇到同样的问题,可以提供自己的资源文件来实现这一点。当然,它需要一些反射黑客! 首先,您需要在完全安全的情况下运行,即在您的 web.config 中设置:

                            <system.web>
                              <securityPolicy>
                                 <trustLevel name="Full" policyFile="internal"/>
                              </securityPolicy>
                            ...
                            

                            您的应用启动代码中的下一步:

                            var ass = Assembly.Load("Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
                            Type hack = ass.GetType("Microsoft.AspNet.Identity.Resources");
                            var field = hack.GetField("resourceMan",
                                                    BindingFlags.Static |
                                                    BindingFlags.NonPublic);
                            // NOTE: this is where you set you own resource manager!
                            field.SetValue(null, new global::System.Resources.ResourceManager("WebApplication1.Resources", typeof(WebApplication1.Resources).Assembly));
                            

                            任务完成!

                            【讨论】:

                            • 老兄,非常感谢!对于那些不能使用 .NET Core 并且想要翻译消息的人来说,这是我迄今为止找到的最佳解决方案。
                            【解决方案21】:

                            我设法找到了一种解决方案,为没有现成可用包的文化创建本地化版本的 AspNet.Identity。步骤是:

                            1. GitHub 下载源代码并在Visual Studio 中打开src/Microsoft.AspNet.Identity.Core 项目。
                            2. 向项目中添加一个新项目(资源文件)。将其命名为Resources.aa-BB.resx,其中aa-BB 是您需要为其本地化程序集的文化。例如:Resources.fa-IR.resx
                            3. 打开新创建的文件并将Resources.resx中的资源项复制到其中。
                            4. 根据需要对文本进行本地化。
                            5. 构建项目。
                            6. 转到bin 文件夹,在DebugRelease 目录下,您将看到一个名为aa-BB(您之前输入的文化)的文件夹。将该文件夹复制到项目的bin 目录中。
                            7. 进行@1AmirJalali 所说的更改 (this post)。
                            8. 干得好!本地化完成。尝试分享您的本地化包:)

                            【讨论】:

                              【解决方案22】:

                              法文版(使用 C# 9 语法):

                              public class FrenchIdentityErrorDescriber : IdentityErrorDescriber
                              {
                                  public override IdentityError DefaultError() => new() { Code = nameof(DefaultError), Description = "Une erreur est survenue." };
                                  public override IdentityError ConcurrencyFailure() => new() { Code = nameof(ConcurrencyFailure), Description = "Erreur de concurrence optimiste, l'objet a été modifié." };
                                  public override IdentityError PasswordMismatch() => new() { Code = nameof(PasswordMismatch), Description = "Mot de passe incorrect." };
                                  public override IdentityError InvalidToken() => new() { Code = nameof(InvalidToken), Description = "Jeton invalide." };
                                  public override IdentityError LoginAlreadyAssociated() => new() { Code = nameof(LoginAlreadyAssociated), Description = "Un utilisateur est déjà enregistré avec cet identifiant." };
                                  public override IdentityError InvalidUserName(string userName) => new() { Code = nameof(InvalidUserName), Description = $"Le nom d'utilisateur '{userName}' est invalide. Il ne peut contenir que des caractères alphanumériques." };
                                  public override IdentityError InvalidEmail(string email) => new() { Code = nameof(InvalidEmail), Description = $"L'email '{email}' est invalide" };
                                  public override IdentityError DuplicateUserName(string userName) => new() { Code = nameof(DuplicateUserName), Description = $"Le nom d'utilisateur '{userName}' est déjà pris." };
                                  public override IdentityError DuplicateEmail(string email) => new() { Code = nameof(DuplicateEmail), Description = $"L'adresse email '{email}' est déjà enregistrée." };
                                  public override IdentityError InvalidRoleName(string role) => new() { Code = nameof(InvalidRoleName), Description = $"Le rôle '{role}' est invalide." };
                                  public override IdentityError DuplicateRoleName(string role) => new() { Code = nameof(DuplicateRoleName), Description = $"Le rôle '{role}' existe déjà." };
                                  public override IdentityError UserAlreadyHasPassword() => new() { Code = nameof(UserAlreadyHasPassword), Description = "L'utilisateur possède déjà un mot de passe." };
                                  public override IdentityError UserLockoutNotEnabled() => new() { Code = nameof(UserLockoutNotEnabled), Description = "Le verrou de compte n'est pas actif pour l'utilisateur." };
                                  public override IdentityError UserAlreadyInRole(string role) => new() { Code = nameof(UserAlreadyInRole), Description = $"L'utilisateur possède déjà le rôle '{role}'." };
                                  public override IdentityError UserNotInRole(string role) => new() { Code = nameof(UserNotInRole), Description = $"L'utilisateur ne possède pas le rôle '{role}'." };
                                  public override IdentityError PasswordTooShort(int length) => new() { Code = nameof(PasswordTooShort), Description = $"Le mot de passe doit faire minimum {length} caractères." };
                                  public override IdentityError PasswordRequiresNonAlphanumeric() => new() { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Le mot de passe doit contenir au moins un caractère non alphanumérique." };
                                  public override IdentityError PasswordRequiresDigit() => new() { Code = nameof(PasswordRequiresDigit), Description = "Le mot de passe doit contenir au moins un chiffre ('0'-'9')." };
                                  public override IdentityError PasswordRequiresLower() => new() { Code = nameof(PasswordRequiresLower), Description = "Le mot de passe doit contenir au moins une minuscule ('a'-'z')." };
                                  public override IdentityError PasswordRequiresUpper() => new() { Code = nameof(PasswordRequiresUpper), Description = "Le mot de passe doit contenir au moins une majuscule ('A'-'Z')." };
                              }
                              

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 2022-11-25
                                • 2022-01-15
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2020-04-04
                                相关资源
                                最近更新 更多