16

ASP.Net 核心具有对本地化的新支持

在我的项目中,我只需要一种语言。对于大多数文本和注释,我可以用我的语言指定内容,但对于来自 ASP.Net Core 本身的文本,语言是英语。

例子:

  • 密码必须至少有一个大写字母 ('A'-'Z')。
  • 密码必须至少有一位数字 ('0'-'9')。
  • 用户名“x@x.com”已被占用。
  • E-post 字段不是有效的电子邮件地址。
  • 值 '' 无效。

我试过手动设置文化,但语言仍然是英语。

app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("nb-NO"),
    SupportedCultures = new List<CultureInfo> { new CultureInfo("nb-NO") },
    SupportedUICultures = new List<CultureInfo> { new CultureInfo("nb-NO") }
});

如何更改 ASP.Net Core 的语言,或覆盖其默认文本?

4

8 回答 8

15

列出的错误消息在 ASP.NET Core Identity 中定义并由IdentityErrorDescriber. 到目前为止我还没有找到翻译的资源文件,我认为它们没有本地化。CultureInfo在我的系统(德语语言环境)上,尽管设置正确,但它们也没有被翻译。

您可以配置自定义 IdentityErrorDescriber 以返回您自己的消息及其翻译。例如, 如何更改 MVC Core ValidationSummary 的默认错误消息?

Configure方法中,Startup.cs您可以连接从IdentityErrorDescriberlike继承的错误描述器类

 services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddErrorDescriber<TranslatedIdentityErrorDescriber>();

对于其他默认模型错误消息(如无效号码),您可以在ModelBindingMessageProvider. 此提供程序由 ASP.NET Core MVC 使用,也可以在其中进行配置Startup.cs

services.AddMvc(
            options => 
            options.ModelBindingMessageProvider.ValueIsInvalidAccessor = s => $"My not valid text for {s}");
于 2016-08-30T12:37:41.067 回答
11

让我对这个问题有一个全面的回答,并描述我在阅读.net核心源代码后是如何想出解决方案的。

在任何进一步的描述之前,首先使用 NuGet Microsoft.Extensions.Localization安装这个包

你们可能还记得在 asp.net 完整框架中,文化之间的切换非常简单

System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

但在 .net 核心中,文化不再与当前线程相关联。asp.net 核心引擎有一个管道,我们可以在这个管道中添加不同的中间件,所以RequestLocalizationMiddleware是处理本地化的中间件类,我们可能有多个提供者,所以它将遍历所有文化提供者,如QueryStringRequestCultureProviderCookieRequestCultureProviderAcceptLanguageHeaderRequestCultureProvider,……</p>

一旦请求本地化中间件可以从第一个提供者那里获取当前语言环境,它就会忽略其他提供者并将请求传递给管道中的下一个中间件,因此列表中提供者的顺序非常重要。

我个人更喜欢将文化存储在浏览器 cookie 中,因此由于CookieRequestCultureProvider不是列表中的第一个文化提供者,我将其移至列表顶部,因此 Startup.cs > ConfigureServices 中这部分的配置如下

services.Configure<RequestLocalizationOptions>(options =>
             {
                 var supportedCultures = new[]
                 {
                    new CultureInfo("en-US"),
                    new CultureInfo("fa-IR"),
                    new CultureInfo("de-DE")
                };
                options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
                options.SupportedCultures = supportedCultures;
                options.SupportedUICultures = supportedCultures;

                var defaultCookieRequestProvider =
                    options.RequestCultureProviders.FirstOrDefault(rcp =>
                        rcp.GetType() == typeof(CookieRequestCultureProvider));
                if (defaultCookieRequestProvider != null)
                    options.RequestCultureProviders.Remove(defaultCookieRequestProvider);

                options.RequestCultureProviders.Insert(0,
                    new CookieRequestCultureProvider()
                    {
                        CookieName = ".AspNetCore.Culture",
                        Options = options
                    });
            });

让我描述一下上面的代码,我们的应用默认文化是美国,我们只支持英语、波斯语、德国,所以如果浏览器有不同的区域设置或者你设置的语言不是这 3 种语言,那么应用必须切换到默认文化。在上面的代码中,我只是从列表中删除 CookieCultureProvider 并将其添加为列表中的第一个提供者(* 我已经描述了它必须是第一个的原因*)。默认的 CookieName 对我有用,您可以根据需要更改它。

不要忘记在 Startup.cs的Configure(IApplicationBuilder app, IHostingEnvironment env)下面添加以下代码

   var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
   app.UseRequestLocalization(options.Value);

到目前为止,一切都很好。要拥有资源文件,您必须指定资源的路径,我在 Web 项目根路径中分别指定 Controller、Views、ViewModels 和 SharedResources 的资源,层次结构如下所示

|-Resoures
|---Controllers
|---Views
|---Models
|---SharedResource.resx
|---SharedResource.fa-IR.resx
|---SharedResource.de-DE.resx

请记住,对于 SharedResource,在 Web 项目根路径中创建一个具有相同名称的空类,我的意思是一个SharedResource.cs,其中包含一个内部具有相同名称的类。

在 Startup.cs 中添加以下代码片段以指定资源路径和其余部分。

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
    AddViewLocalization(
                LanguageViewLocationExpanderFormat.Suffix,
                opts => { opts.ResourcesPath = "Resources/Views"; }) // this line is not required, it is just for more clarification
            .AddDataAnnotationsLocalization();

使用此配置,例如,当您在控制器中注入IStringLocalizer时,您必须在 Resources > Controllers 文件夹中拥有相应的资源文件(即 HomeController.resx、HomeController.fa-IR.resx、HomeController.de-DE.resx),我们也可以用 分隔路径(比如说点)在文件名中我的意思是 Resources/Controllers/HomeController.resx 可以是 Resources/Controllers.HomeController.resx 中的一个文件,您必须将 IViewLocalizer 注入视图才能在视图中进行相应的本地化,您必须拥有资源文件Resources/Views 文件夹中的视图,对于 ViewModels,因为我们将文件夹命名为 Models,请将所有 ViewModels 放在 Web 项目根路径中名为 Models 的预先创建的文件夹中,如果文件夹有其他名称或者您更喜欢其他名称,请不要不要忘记重命名 Resource 文件夹下的 Models 文件夹。那么您只需要对模型进行注释,例如,使用 [DisplayName("User Emailaddress"“用户电子邮件地址”)。

让我们从已经开始的地方结束,我的意思是CookieRequestCultureProvider。正如我之前所说,我更喜欢将其存储在 cookie 中,但这有点棘手,因为cookie 解析与您的预期有些不同,只需在您想要更改文化的地方添加下面的代码,只需将 preferedCulture 替换为您的文化偏好

var preferedCulture = "fa-IR"; // get the culture from user, i just mock it here in a variable
if (HttpContext.Response.Cookies.ContainsKey(".AspNetCore.Culture"))
{
    HttpContext.Response.Cookies.Delete(".AspNetCore.Culture");
}

HttpContext.Response.Cookies.Append(".AspNetCore.Culture",
    $"c={preferedCulture}|uic={preferedCulture}", new CookieOptions {Expires = DateTime.UtcNow.AddYears(1)});

好了,我们的 sp.net 核心网络应用程序现在已经本地化了 :)

于 2018-09-25T13:06:29.027 回答
4

基于 rboe 和 Tedd Hansen 的优秀答案,我写了一个IStringLocalizer基础IdentityErrorDescriber供我自己使用,我想我会在这里分享它,以防有人需要多语言支持:)

基本思想是以通常的方式为您的默认语言和任何其他语言创建资源文件。(https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization

位于(如果您保留我的班级名称):

/Resources/ yournamespace .LocalizedIdentityErrorDescriber.resx
/Resources/ yournamespace .LocalizedIdentityErrorDescriber.fr.resx
等...

在这些中,您将使用错误代码(例如:DefaultError、ConcurrencyError)作为键。

然后在下面添加类

LocalizedIdentityErrorDescriber.cs

public class LocalizedIdentityErrorDescriber : IdentityErrorDescriber
{
    /// <summary> 
    /// The <see cref="IStringLocalizer{LocalizedIdentityErrorDescriber}"/>
    /// used to localize the strings
    /// </summary>
    private readonly IStringLocalizer<LocalizedIdentityErrorDescriber> localizer;

    /// <summary>
    /// Initializes a new instance of the <see cref="LocalizedIdentityErrorDescriber"/> class.
    /// </summary>
    /// <param name="localizer">
    /// The <see cref="IStringLocalizer{LocalizedIdentityErrorDescriber}"/>
    /// that we will use to localize the strings
    /// </param>
    public LocalizedIdentityErrorDescriber(IStringLocalizer<LocalizedIdentityErrorDescriber> localizer)
    {
        this.localizer = localizer;
    }

    /// <summary>
    /// Returns the default <see cref="IdentityError" />.
    /// </summary>
    /// <returns>The default <see cref="IdentityError" /></returns>
    public override IdentityError DefaultError()
    {
        return this.GetErrorByCode("DefaultError");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a concurrency failure.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a concurrency failure.</returns>
    public override IdentityError ConcurrencyFailure()
    {
        return this.GetErrorByCode("ConcurrencyFailure");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password mismatch.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password mismatch.</returns>
    public override IdentityError PasswordMismatch()
    {
        return this.GetErrorByCode("PasswordMismatch");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating an invalid token.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating an invalid token.</returns>
    public override IdentityError InvalidToken()
    {
        return this.GetErrorByCode("InvalidToken");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating an external login is already associated with an account.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating an external login is already associated with an account.</returns>
    public override IdentityError LoginAlreadyAssociated()
    {
        return this.GetErrorByCode("LoginAlreadyAssociated");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified user <paramref name="userName" /> is invalid.
    /// </summary>
    /// <param name="userName">The user name that is invalid.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specified user <paramref name="userName" /> is invalid.</returns>
    public override IdentityError InvalidUserName(string userName)
    {
        return this.FormatErrorByCode("InvalidUserName", (object)userName);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="email" /> is invalid.
    /// </summary>
    /// <param name="email">The email that is invalid.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specified <paramref name="email" /> is invalid.</returns>
    public override IdentityError InvalidEmail(string email)
    {
        return this.FormatErrorByCode("InvalidEmail", (object)email);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="userName" /> already exists.
    /// </summary>
    /// <param name="userName">The user name that already exists.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specified <paramref name="userName" /> already exists.</returns>
    public override IdentityError DuplicateUserName(string userName)
    {
        return this.FormatErrorByCode("DuplicateUserName", (object)userName);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="email" /> is already associated with an account.
    /// </summary>
    /// <param name="email">The email that is already associated with an account.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specified <paramref name="email" /> is already associated with an account.</returns>
    public override IdentityError DuplicateEmail(string email)
    {
        return this.FormatErrorByCode("DuplicateEmail", (object)email);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="role" /> name is invalid.
    /// </summary>
    /// <param name="role">The invalid role.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specific role <paramref name="role" /> name is invalid.</returns>
    public override IdentityError InvalidRoleName(string role)
    {
        return this.FormatErrorByCode("InvalidRoleName", (object)role);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="role" /> name already exists.
    /// </summary>
    /// <param name="role">The duplicate role.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specific role <paramref name="role" /> name already exists.</returns>
    public override IdentityError DuplicateRoleName(string role)
    {
        return this.FormatErrorByCode("DuplicateRoleName", (object)role);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a user already has a password.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a user already has a password.</returns>
    public override IdentityError UserAlreadyHasPassword()
    {
        return this.GetErrorByCode("UserAlreadyHasPassword");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating user lockout is not enabled.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating user lockout is not enabled..</returns>
    public override IdentityError UserLockoutNotEnabled()
    {
        return this.GetErrorByCode("UserLockoutNotEnabled");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a user is already in the specified <paramref name="role" />.
    /// </summary>
    /// <param name="role">The duplicate role.</param>
    /// <returns>An <see cref="IdentityError" /> indicating a user is already in the specified <paramref name="role" />.</returns>
    public override IdentityError UserAlreadyInRole(string role)
    {
        return this.FormatErrorByCode("UserAlreadyInRole", (object)role);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a user is not in the specified <paramref name="role" />.
    /// </summary>
    /// <param name="role">The duplicate role.</param>
    /// <returns>An <see cref="IdentityError" /> indicating a user is not in the specified <paramref name="role" />.</returns>
    public override IdentityError UserNotInRole(string role)
    {
        return this.FormatErrorByCode("UserNotInRole", (object)role);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password of the specified <paramref name="length" /> does not meet the minimum length requirements.
    /// </summary>
    /// <param name="length">The length that is not long enough.</param>
    /// <returns>An <see cref="IdentityError" /> indicating a password of the specified <paramref name="length" /> does not meet the minimum length requirements.</returns>
    public override IdentityError PasswordTooShort(int length)
    {
        return this.FormatErrorByCode("PasswordTooShort", (object)length);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password entered does not contain a non-alphanumeric character, which is required by the password policy.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password entered does not contain a non-alphanumeric character.</returns>
    public override IdentityError PasswordRequiresNonAlphanumeric()
    {
        return this.GetErrorByCode("PasswordRequiresNonAlphanumeric");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password entered does not contain a numeric character, which is required by the password policy.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password entered does not contain a numeric character.</returns>
    public override IdentityError PasswordRequiresDigit()
    {
        return this.GetErrorByCode("PasswordRequiresDigit");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password entered does not contain a lower case letter, which is required by the password policy.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password entered does not contain a lower case letter.</returns>
    public override IdentityError PasswordRequiresLower()
    {
        return this.GetErrorByCode("PasswordRequiresLower");
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password entered does not contain an upper case letter, which is required by the password policy.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password entered does not contain an upper case letter.</returns>
    public override IdentityError PasswordRequiresUpper()
    {
        return this.GetErrorByCode("PasswordRequiresUpper");
    }

    /// <summary>Returns a localized <see cref="IdentityError"/> for the provided code.</summary>
    /// <param name="code">The error's code.</param>
    /// <returns>A localized <see cref="IdentityError"/>.</returns>
    private IdentityError GetErrorByCode(string code)
    {
        return new IdentityError()
        {
            Code = code,
            Description = this.localizer.GetString(code)
        };
    }

    /// <summary>Formats a localized <see cref="IdentityError"/> for the provided code.</summary>
    /// <param name="code">The error's code.</param>
    /// <param name="parameters">The parameters to format the string with.</param>
    /// <returns>A localized <see cref="IdentityError"/>.</returns>
    private IdentityError FormatErrorByCode(string code, params object[] parameters)
    {
        return new IdentityError
        {
            Code = code,
            Description = string.Format(this.localizer.GetString(code, parameters))
        };
    }
}

并初始化一切:

启动.cs

    [...]

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddErrorDescriber<LocalizedIdentityErrorDescriber>();

        services.AddLocalization(options => options.ResourcesPath = "Resources");

        // Your service configuration code

        services.AddMvc()
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .AddDataAnnotationsLocalization();

        // Your service configuration code cont.
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        // your configuration code

        app.UseRequestLocalization(
            new RequestLocalizationOptions()
                {
                    DefaultRequestCulture = new RequestCulture("fr"),
                    SupportedCultures = SupportedCultures,
                    SupportedUICultures = SupportedCultures
                });

        app.UseStaticFiles();

        app.UseIdentity();

        // your configuration code
    }

    [...]
于 2017-08-22T20:50:40.500 回答
2

和俄语 IdentityErrorDescriber,以防有人需要。

public class RussianIdentityErrorDescriber : IdentityErrorDescriber
{

    public override IdentityError ConcurrencyFailure()
    {
        return new IdentityError
        {
            Code = "ConcurrencyFailure",
            Description = "Сбой в параллельных запросах. Возможно объект был изменен."
        };
    }
    public override IdentityError DefaultError()
    {
    return new IdentityError
        {
            Code = "DefaultError",
            Description = "Произошла неизвестная ошибка при авторизации."
        };
    }
    public override IdentityError DuplicateEmail(string email)
    {
        return new IdentityError
        {
            Code = "DuplicateEmail",
            Description = $"E-mail '{email}' уже используется."
        };
    }
    public override IdentityError DuplicateRoleName(string role)
    {
        return new IdentityError
        {
            Code = "DuplicateRoleName",
            Description = $"Роль с именем '{role}' уже существует."
        };
    }
    public override IdentityError DuplicateUserName(string userName)
    {
        return new IdentityError
        {
            Code = "DuplicateUserName",
            Description = $"Пользователь '{userName}' уже зарегистрирован."
        };
    }
    public override IdentityError InvalidEmail(string email)
    {
        return new IdentityError
        {
            Code = "InvalidEmail",
            Description = $"E-mail '{email}' содержит неверный формат."
        };
    }
    public override IdentityError InvalidRoleName(string role)
    {
        return new IdentityError
        {
            Code = "InvalidRoleName",
            Description = $"Имя роли '{role}' задано не верно (содержит не допустимые символы либо длину)."
        };
    }
    public override IdentityError InvalidToken()
    {
        return new IdentityError
        {
            Code = "InvalidToken",
            Description = "Неправильно указан код подтверждения (token)."
        };
    }
    public override IdentityError InvalidUserName(string userName)
    {
        return new IdentityError
        {
            Code = "InvalidUserName",
            Description = $"Имя пользователя '{userName}' указано не верно (содержит не допустимые символы либо длину)."
        };
    }
    public override IdentityError LoginAlreadyAssociated()
    {
        return new IdentityError
        {
            Code = "LoginAlreadyAssociated",
            Description = "Данный пользователь уже привязан к аккаунту."
        };
    }
    public override IdentityError PasswordMismatch()
    {
        return new IdentityError
        {
            Code = "PasswordMismatch",
            Description = "Пароли не совпадают."
        };
    }
    public override IdentityError PasswordRequiresDigit()
    {
        return new IdentityError
        {
            Code = "PasswordRequiresDigit",
            Description = "Пароль должен содержать минимум одну цифру."
        };
    }
    public override IdentityError PasswordRequiresLower()
    {
        return new IdentityError
        {
            Code = "PasswordRequiresLower",
            Description = "Пароль должен содержать минимум одну строчную букву."
        };
    }
    public override IdentityError PasswordRequiresNonAlphanumeric()
    {
        return new IdentityError
        {
            Code = "PasswordRequiresNonAlphanumeric",
            Description = "Пароль должен содержать минимум один специальный символ (не буквенно-цифровой)."
        };
    }
    public override IdentityError PasswordRequiresUniqueChars(int uniqueChars)
    {
        return new IdentityError
        {
            Code = "PasswordRequiresUniqueChars",
            Description = $"Пароль должен содержать минимум '{uniqueChars}' не повторяющихся символов."
        };
    }
    public override IdentityError PasswordRequiresUpper()
    {
        return new IdentityError
        {
            Code = "PasswordRequiresUpper",
            Description = "Пароль должен содержать минимум одну заглавную букву."
        };
    }
    public override IdentityError PasswordTooShort(int length)
    {
        return new IdentityError
        {
            Code = "PasswordTooShort",
            Description = $"Пароль слишком короткий. Минимальное количество символов: '{length}'."
        };
    }
    public override IdentityError RecoveryCodeRedemptionFailed()
    {
        return new IdentityError
        {
            Code = "RecoveryCodeRedemptionFailed",
            Description = "Не удалось использовать код восстановления."
        };
    }
    public override IdentityError UserAlreadyHasPassword()
    {
        return new IdentityError
        {
            Code = "UserAlreadyHasPassword",
            Description = "Пароль для пользователя уже задан."
        };
    }
    public override IdentityError UserAlreadyInRole(string role)
    {
        return new IdentityError
        {
            Code = "UserAlreadyInRole",
            Description = $"Роль '{role}' уже привязана к пользователю."
        };
    }
    public override IdentityError UserLockoutNotEnabled()
    {
        return new IdentityError
        {
            Code = "UserLockoutNotEnabled",
            Description = "Блокировка пользователя отключена."
        };
    }
    public override IdentityError UserNotInRole(string role)
    {
        return new IdentityError
        {
            Code = "UserNotInRole",
            Description = $"Пользователь должен иметь роль: '{role}'"
        };
    }
}

In `Startup.cs` set `RussianIdentityErrorDescriber `

public void ConfigureServices(IServiceCollection services)
{
// ...   
    services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddErrorDescriber<RussianIdentityErrorDescriber>();
    // ...   
}
于 2017-08-31T16:45:19.777 回答
1

挪威 IdentityErrorDescriber,以防有人需要。

public class NorwegianIdentityErrorDescriber : IdentityErrorDescriber
{

    public override IdentityError DefaultError()
    {
        return new IdentityError()
        {
            Code = "DefaultError",
            Description = "En ukjent feil har oppstått."
        };
    }

    public override IdentityError ConcurrencyFailure()
    {
        return new IdentityError()
        {
            Code = "ConcurrencyFailure",
            Description = "Optimistisk samtidighet feilet, objektet har blitt endret."
        };
    }

    public override IdentityError PasswordMismatch()
    {
        return new IdentityError()
        {
            Code = "PasswordMismatch",
            Description = "Feil passord."
        };
    }

    public override IdentityError InvalidToken()
    {
        return new IdentityError()
        {
            Code = "InvalidToken",
            Description = "Feil token."
        };
    }

    public override IdentityError LoginAlreadyAssociated()
    {
        return new IdentityError()
        {
            Code = "LoginAlreadyAssociated",
            Description = "En bruker med dette brukernavnet finnes allerede."
        };
    }

    public override IdentityError InvalidUserName(string userName)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "InvalidUserName";
        string str = $"Brkernavnet '{userName}' er ikke gyldig. Det kan kun inneholde bokstaver og tall.";
        identityError.Description = str;
        return identityError;
    }

    public override IdentityError InvalidEmail(string email)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "InvalidEmail";
        string str = $"E-post '{email}' er ugyldig.";
        identityError.Description = str;
        return identityError;
    }

    public override IdentityError DuplicateUserName(string userName)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "DuplicateUserName";
        string str = $"Brukernavn '{userName}' er allerede tatt.";
        identityError.Description = str;
        return identityError;
    }

    public override IdentityError DuplicateEmail(string email)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "DuplicateEmail";
        string str = $"E-post '{email}' er allerede tatt.";
        identityError.Description = str;
        return identityError;
    }

    public override IdentityError InvalidRoleName(string role)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "InvalidRoleName";
        string str = $"Rollenavn '{role}' er ugyldig.";
        identityError.Description = str;
        return identityError;
    }

    public override IdentityError DuplicateRoleName(string role)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "DuplicateRoleName";
        string str = $"Rollenavn '{role}' er allerede tatt.";
        identityError.Description = str;
        return identityError;
    }

    public virtual IdentityError UserAlreadyHasPassword()
    {
        return new IdentityError()
        {
            Code = "UserAlreadyHasPassword",
            Description = "Bruker har allerede passord satt."
        };
    }

    public override IdentityError UserLockoutNotEnabled()
    {
        return new IdentityError()
        {
            Code = "UserLockoutNotEnabled",
            Description = "Utestenging er ikke slått på for denne brukeren."
        };
    }

    public override IdentityError UserAlreadyInRole(string role)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "UserAlreadyInRole";
        string str = $"Brukeren er allerede i rolle '{role}'.";
        identityError.Description = str;
        return identityError;
    }

    public override IdentityError UserNotInRole(string role)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "UserNotInRole";
        string str = $"Bruker er ikke i rolle '{role}'.";
        identityError.Description = str;
        return identityError;
    }

    public override IdentityError PasswordTooShort(int length)
    {
        IdentityError identityError = new IdentityError();
        identityError.Code = "PasswordTooShort";
        string str = $"Passordet må være på minimum {length} tegn.";
        identityError.Description = str;
        return identityError;
    }

    public override IdentityError PasswordRequiresNonAlphanumeric()
    {
        return new IdentityError()
        {
            Code = "PasswordRequiresNonAlphanumeric",
            Description = "Passordet må inneholde minst ett spesialtegn."
        };
    }

    public override IdentityError PasswordRequiresDigit()
    {
        return new IdentityError()
        {
            Code = "PasswordRequiresDigit",
            Description = "Passordet må inneholde minst ett siffer."
        };
    }

    public override IdentityError PasswordRequiresLower()
    {
        return new IdentityError()
        {
            Code = "PasswordRequiresLower",
            Description = "Passordet må inneholde minst en liten bokstav (a-z)."
        };
    }

    public override IdentityError PasswordRequiresUpper()
    {
        return new IdentityError()
        {
            Code = "PasswordRequiresUpper",
            Description = "Passordet må inneholde minst en stor bokstav (A-Z)."
        };
    }
}
于 2016-08-31T07:49:39.823 回答
1

如果您正在寻找波兰语,这里是:

    公共类 PolishLocalizedIdentityErrorDescriber : IdentityErrorDescriber
        {
            公共覆盖 IdentityError DefaultError()
            {
                返回新的身份错误
                {
                    代码 = nameof(DefaultError),
                    Description = "Wystąpił nieznany błąd."
                };
            }

            公共覆盖 IdentityError ConcurrencyFailure()
            {
                返回新的身份错误
                {
                    代码 = nameof(ConcurrencyFailure),
                    Description = "Błąd współbieżności, obiekt został już zmodyfikowany."
                };
            }

            公共覆盖 IdentityError PasswordMismatch()
            {
                返回新的身份错误
                {
                    代码 = nameof(密码不匹配),
                    Description = "Niepoprawne hasło."
                };
            }

            公共覆盖 IdentityError InvalidToken()
            {
                返回新的身份错误
                {
                    代码 = nameof(InvalidToken),
                    Description = "Nieprawidłowy 令牌。"
                };
            }

            公共覆盖 IdentityError RecoveryCodeRedemptionFailed()
            {
                返回新的身份错误
                {
                    代码 = nameof(RecoveryCodeRedemptionFailed),
                    描述 = "Pobranie kodu odzyskiwania nie powiodło się."
                };
            }

            公共覆盖 IdentityError LoginAlreadyAssociated()
            {
                返回新的身份错误
                {
                    代码 = nameof(LoginAlreadyAssociated),
                    Description = "Użytkownik o tym loginie już istnieje."
                };
            }

            公共覆盖 IdentityError InvalidUserName(string userName)
            {
                返回新的身份错误
                {
                    代码 = nameof(InvalidUserName),
                    说明 =
                        $“Nazwa użytkownika '{userName}' jest nieprawidłowa, może zawierać tylko litery lub cyfry。”
                };
            }

            公共覆盖 IdentityError InvalidEmail(字符串电子邮件)
            {
                返回新的身份错误
                {
                    代码 = nameof(InvalidEmail),
                    Description = $"地址电子邮件 '{email}' 开玩笑 nieprawidłowy。"
                };
            }

            公共覆盖 IdentityError DuplicateUserName(string userName)
            {
                返回新的身份错误
                {
                    代码 = nameof(DuplicateUserName),
                    描述 = $"Nazwa '{userName}' jest już zajęta."
                };
            }

            公共覆盖 IdentityError DuplicateEmail(字符串电子邮件)
            {
                返回新的身份错误
                {
                    代码 = nameof(DuplicateEmail),
                    描述 = $"地址电子邮件 '{email}' jest już zajęty."
                };
            }

            公共覆盖 IdentityError InvalidRoleName(字符串角色)
            {
                返回新的身份错误
                {
                    代码 = nameof(InvalidRoleName),
                    描述 = $"Nazwa roli '{role}' już niepoprawna."
                };
            }

            公共覆盖 IdentityError DuplicateRoleName(字符串角色)
            {
                返回新的身份错误
                {
                    代码 = nameof(DuplicateRoleName),
                    描述 = $"Rola '{role}' już istnieje."
                };
            }

            公共覆盖 IdentityError UserAlreadyHasPassword()
            {
                返回新的身份错误
                {
                    代码 = nameof(UserAlreadyHasPassword),
                    Description = "Użytkownik ma już ustawione hasło。"
                };
            }

            公共覆盖 IdentityError UserLockoutNotEnabled()
            {
                返回新的身份错误
                {
                    代码 = nameof(UserLockoutNotEnabled),
                    Description = "Blokada konta nie jest włączona dla tego użytkownika."
                };
            }

            公共覆盖 IdentityError UserAlreadyInRole(字符串角色)
            {
                返回新的身份错误
                {
                    代码 = nameof(UserAlreadyInRole),
                    描述 = $"Użytkownik korzysta już z roli '{role}'。"
                };
            }

            公共覆盖 IdentityError UserNotInRole(字符串角色)
            {
                返回新的身份错误
                {
                    代码 = nameof(UserNotInRole),
                    描述 = $"Użytkownika nie ma w roli '{role}'。"
                };
            }

            公共覆盖 IdentityError PasswordTooShort(int length)
            {
                返回新的身份错误
                {
                    代码 = nameof(PasswordTooShort),
                    描述 = $"Hasło musi składać się z co najmniej {length} znaków."
                };
            }

            公共覆盖 IdentityError PasswordRequiresUniqueChars(int uniqueChars)
            {
                返回新的身份错误
                {
                    代码 = nameof(PasswordRequiresUniqueChars),
                    描述 = $"Hasło musi składać się z co najmniej {uniqueChars} unikalnych znaków。"
                };
            }

            公共覆盖 IdentityError PasswordRequiresNonAlphanumeric()
            {
                返回新的身份错误
                {
                    代码 = nameof(PasswordRequiresNonAlphanumeric),
                    描述 = “Hasło musi zawierać co najmniej jeden znak niebędący literą lub cyfrą。”
                };
            }

            公共覆盖 IdentityError PasswordRequiresDigit()
            {
                返回新的身份错误
                {
                    代码 = nameof(PasswordRequiresDigit),
                    描述 = “Hasło musi zawierać co najmniej jedną cyfrę (0-9)。”
                };
            }

            公共覆盖 IdentityError PasswordRequiresLower()
            {
                返回新的身份错误
                {
                    代码 = nameof(PasswordRequiresLower),
                    描述 = “Hasło musi zawierać co najmniej jedną małą literę (az)。”
                };
            }

            公共覆盖 IdentityError PasswordRequiresUpper()
            {
                返回新的身份错误
                {
                    代码 = nameof(PasswordRequiresUpper),
                    描述 = “Hasło musi zawierać co najmniej jedną wielką literę (AZ)。”
                };
            }
        }
于 2018-02-09T21:40:41.550 回答
1

对于那些想知道,是否可以针对当前选择的文化本地化消息,是的,这是可能的。在asp.net core 2.2中,您可以创建一个类LocalizedIdentityErrorDescriber,其中IdentityResources是您的虚拟类的名称(在此处进行了描述:全球化和本地化):

public class LocalizedIdentityErrorDescriber : IdentityErrorDescriber
{
    /// <summary> 
    /// The <see cref="IStringLocalizer{LocalizedIdentityErrorDescriber}"/>
    /// used to localize the strings
    /// </summary>
    private readonly IStringLocalizer<IdentityResources> localizer;

    /// <summary>
    /// Initializes a new instance of the <see cref="LocalizedIdentityErrorDescriber"/> class.
    /// </summary>
    /// <param name="localizer">
    /// The <see cref="IStringLocalizer{LocalizedIdentityErrorDescriber}"/>
    /// that we will use to localize the strings
    /// </param>
    public LocalizedIdentityErrorDescriber(IStringLocalizer<IdentityResources> localizer)
    {
        this.localizer = localizer;
    }

    /// <summary>
    /// Returns the default <see cref="IdentityError" />.
    /// </summary>
    /// <returns>The default <see cref="IdentityError" /></returns>
    public override IdentityError DefaultError()
    {
        return this.GetErrorByCode(nameof(DefaultError));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a concurrency failure.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a concurrency failure.</returns>
    public override IdentityError ConcurrencyFailure()
    {
        return this.GetErrorByCode(nameof(ConcurrencyFailure));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password mismatch.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password mismatch.</returns>
    public override IdentityError PasswordMismatch()
    {
        return this.GetErrorByCode(nameof(PasswordMismatch));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating an invalid token.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating an invalid token.</returns>
    public override IdentityError InvalidToken()
    {
        return this.GetErrorByCode(nameof(InvalidToken));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating an external login is already associated with an account.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating an external login is already associated with an account.</returns>
    public override IdentityError LoginAlreadyAssociated()
    {
        return this.GetErrorByCode(nameof(LoginAlreadyAssociated));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified user <paramref name="userName" /> is invalid.
    /// </summary>
    /// <param name="userName">The user name that is invalid.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specified user <paramref name="userName" /> is invalid.</returns>
    public override IdentityError InvalidUserName(string userName)
    {
        return this.FormatErrorByCode(nameof(InvalidUserName), (object)userName);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="email" /> is invalid.
    /// </summary>
    /// <param name="email">The email that is invalid.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specified <paramref name="email" /> is invalid.</returns>
    public override IdentityError InvalidEmail(string email)
    {
        return this.FormatErrorByCode(nameof(InvalidEmail), (object)email);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="userName" /> already exists.
    /// </summary>
    /// <param name="userName">The user name that already exists.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specified <paramref name="userName" /> already exists.</returns>
    public override IdentityError DuplicateUserName(string userName)
    {
        return this.FormatErrorByCode(nameof(DuplicateUserName), (object)userName);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="email" /> is already associated with an account.
    /// </summary>
    /// <param name="email">The email that is already associated with an account.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specified <paramref name="email" /> is already associated with an account.</returns>
    public override IdentityError DuplicateEmail(string email)
    {
        return this.FormatErrorByCode(nameof(DuplicateEmail), (object)email);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="role" /> name is invalid.
    /// </summary>
    /// <param name="role">The invalid role.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specific role <paramref name="role" /> name is invalid.</returns>
    public override IdentityError InvalidRoleName(string role)
    {
        return this.FormatErrorByCode(nameof(InvalidRoleName), (object)role);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating the specified <paramref name="role" /> name already exists.
    /// </summary>
    /// <param name="role">The duplicate role.</param>
    /// <returns>An <see cref="IdentityError" /> indicating the specific role <paramref name="role" /> name already exists.</returns>
    public override IdentityError DuplicateRoleName(string role)
    {
        return this.FormatErrorByCode(nameof(DuplicateRoleName), (object)role);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a user already has a password.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a user already has a password.</returns>
    public override IdentityError UserAlreadyHasPassword()
    {
        return this.GetErrorByCode(nameof(UserAlreadyHasPassword));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating user lockout is not enabled.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating user lockout is not enabled..</returns>
    public override IdentityError UserLockoutNotEnabled()
    {
        return this.GetErrorByCode(nameof(UserLockoutNotEnabled));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a user is already in the specified <paramref name="role" />.
    /// </summary>
    /// <param name="role">The duplicate role.</param>
    /// <returns>An <see cref="IdentityError" /> indicating a user is already in the specified <paramref name="role" />.</returns>
    public override IdentityError UserAlreadyInRole(string role)
    {
        return this.FormatErrorByCode(nameof(UserAlreadyInRole), (object)role);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a user is not in the specified <paramref name="role" />.
    /// </summary>
    /// <param name="role">The duplicate role.</param>
    /// <returns>An <see cref="IdentityError" /> indicating a user is not in the specified <paramref name="role" />.</returns>
    public override IdentityError UserNotInRole(string role)
    {
        return this.FormatErrorByCode(nameof(UserNotInRole), (object)role);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password of the specified <paramref name="length" /> does not meet the minimum length requirements.
    /// </summary>
    /// <param name="length">The length that is not long enough.</param>
    /// <returns>An <see cref="IdentityError" /> indicating a password of the specified <paramref name="length" /> does not meet the minimum length requirements.</returns>
    public override IdentityError PasswordTooShort(int length)
    {
        return this.FormatErrorByCode(nameof(PasswordTooShort), (object)length);
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password entered does not contain a non-alphanumeric character, which is required by the password policy.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password entered does not contain a non-alphanumeric character.</returns>
    public override IdentityError PasswordRequiresNonAlphanumeric()
    {
        return this.GetErrorByCode(nameof(PasswordRequiresNonAlphanumeric));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password entered does not contain a numeric character, which is required by the password policy.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password entered does not contain a numeric character.</returns>
    public override IdentityError PasswordRequiresDigit()
    {
        return this.GetErrorByCode(nameof(PasswordRequiresDigit));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password entered does not contain a lower case letter, which is required by the password policy.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password entered does not contain a lower case letter.</returns>
    public override IdentityError PasswordRequiresLower()
    {
        return this.GetErrorByCode(nameof(PasswordRequiresLower));
    }

    /// <summary>
    /// Returns an <see cref="IdentityError" /> indicating a password entered does not contain an upper case letter, which is required by the password policy.
    /// </summary>
    /// <returns>An <see cref="IdentityError" /> indicating a password entered does not contain an upper case letter.</returns>
    public override IdentityError PasswordRequiresUpper()
    {
        return this.GetErrorByCode(nameof(PasswordRequiresUpper));
    }

    public override IdentityError PasswordRequiresUniqueChars(int uniqueChars)
    {
        return this.FormatErrorByCode(nameof(PasswordRequiresUniqueChars), (object)uniqueChars);
    }

    public override IdentityError RecoveryCodeRedemptionFailed()
    {
        return this.GetErrorByCode(nameof(RecoveryCodeRedemptionFailed));
    }

    /// <summary>Returns a localized <see cref="IdentityError"/> for the provided code.</summary>
    /// <param name="code">The error's code.</param>
    /// <returns>A localized <see cref="IdentityError"/>.</returns>
    private IdentityError GetErrorByCode(string code)
    {
        return new IdentityError()
        {
            Code = code,
            Description = this.localizer.GetString(code)
        };
    }

    /// <summary>Formats a localized <see cref="IdentityError"/> for the provided code.</summary>
    /// <param name="code">The error's code.</param>
    /// <param name="parameters">The parameters to format the string with.</param>
    /// <returns>A localized <see cref="IdentityError"/>.</returns>
    private IdentityError FormatErrorByCode(string code, params object[] parameters)
    {
        return new IdentityError
        {
            Code = code,
            Description = string.Format(this.localizer.GetString(code, parameters))
        };
    }
}

然后为您的语言创建资源文件,如下所示:Resources\(上述虚拟类的名称)(.culture).resx。对于您的默认语言文化,应留空。并且不要忘记“。” 如果不是默认值,则在文化名称之前。您的 IdentityResources 文件应如下所示: 在此处输入图像描述

在 Startup.cs 添加以下行:

 public void ConfigureServices(IServiceCollection services)
 {
      services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });
      services.AddIdentity<IdentityUser, IdentityRole>()
           .AddEntityFrameworkStores<nameofyourdbcontext>()
           .AddDefaultTokenProviders()
           .AddErrorDescriber<LocalizedIdentityErrorDescriber>(); // this line is important
       services.Configure<RequestLocalizationOptions>(options =>
       {
            var supportedCultures = new[]
            {
                new CultureInfo("en"), // english
                new CultureInfo("tr"), // turkish
                new CultureInfo("ru")  // russian
            };

            options.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
            options.RequestCultureProviders.Insert(0, new CookieRequestCultureProvider()); // type of CultureProvider you want.
        });
 }
 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
 {
        var localizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
        // IT IS IMPORTANT TO CALL UseRequestLocalization BEFORE UseMvc
        app.UseRequestLocalization(localizationOptions.Value);
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}"
            );
        });
 }

现在你几乎完成了,但你需要设置 Culture cookie,这里有一个代码示例:全球化和本地化。希望它可以帮助某人。

于 2019-01-05T12:36:28.747 回答
0

瑞典 IdentityErrorDescriber,以防有人需要。

public class SwedishIdentityErrorDescriber : IdentityErrorDescriber
{
    public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = "Ett okänt fel har inträffat." }; }
    public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "Objektet har ändrats sedan uppläsning." }; }
    public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "Felaktigt lösenord." }; }
    public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "Ogiltigt token." }; }
    public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "En användare med den här inloggningen finns redan." }; }
    public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"Användarnamnet '{userName}' är ogiltigt, kan endast innehålla bokstäver eller siffror." }; }
    public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"E-postadressen {email} är ogiltig." }; }
    public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"Användarnamnet '{userName}' finns redan." }; }
    public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"E-postadressen {email} finns redan." }; }
    public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"Rollen '{role}' är ogiltig." }; }
    public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"Rollen '{role}' finns redan." }; }
    public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "Användaren har redan angett ett lösenord." }; }
    public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "Lockout är inte aktiverat för den här användaren." }; }
    public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"Användaren har redan rollen '{role}'." }; }
    public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"Användaren har inte rollen '{role}'." }; }
    public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"Lösenordet måste ha minst {length} tecken." }; }
    public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "Lösenordet måste ha minst ett icke alfanumeriskt tecken." }; }
    public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "Lösenordet måste innehålla minst en siffra ('0'-'9')." }; }
    public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "Lösenordet måste innehålla minst en gemen ('a'-'z')." }; }
    public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "Lösenordet måste innehålla minst en versal ('A'-'Z')." }; }
}
于 2020-04-17T09:59:48.120 回答