Centralized ASP.Net

Key features ASP.Net new localization support .

In my project I need only one language. For most of the text and annotations, I can specify things in my language, but for text coming from ASP.Net Core itself, the language is English.

Examples:

  • Passwords must have at least one uppercase ("A" - "Z").
  • Passwords must have at least one digit ('0' - '9').
  • The username ' x@x.com ' has already been completed.
  • The E-post field is not a valid email address.
  • The value '' is invalid.

I tried to adjust the culture manually, but the language is still English.

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") } }); 

How can I change the language of ASP.Net Core or override its default text?

+12
source share
7 answers

The error messages listed are defined in ASP.NET Core Identity and provided by IdentityErrorDescriber . I did not find the translated resource files and I think that they are not localized. On my system (German) they are also not translated, although CultureInfo configured correctly.

You can configure your own IdentityErrorDescriber to return your own messages, as well as their translations. This is described, for example, in How to change the standard MVC Core ValidationSummary error messages?

In the Configure Startup.cs method, you can connect your Error Describer class, inherited from IdentityErrorDescriber , as

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

For other default model error messages (for example, an invalid number), you can provide your own access functions in ModelBindingMessageProvider . This provider is used by ASP.NET Core MVC and can also be configured in Startup.cs .

 services.AddMvc( options => options.ModelBindingMessageProvider.ValueIsInvalidAccessor = s => $"My not valid text for {s}"); 
+14
source

Based on the excellent answers of rboe and Tedd Hansen, I wrote an IStringLocalizer based on IdentityErrorDescriber for my own use, but I would like to share it here if someone needs multi-language support :)

The basic idea is to create a resource file for your default language and any other languages ​​in the usual way. ( https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization )

Located in (if you save my class name):

/Resources/yournamespace.LocalizedIdentityErrorDescriber.resx
/Resources/yournamespace.LocalizedIdentityErrorDescriber.fr.resx
etc...

In these keys, you will use error codes (for example: DefaultError, ConcurrencyError) as the key.

Then add a class below

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 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 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)) }; } } 

And initialize everything:

Startup.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 } [...] 
+4
source

Let me give an exhaustive answer to this question and describe how I found a solution after reading the .net kernel source code.

Before further description, first install this package using NuGet Microsoft.Extensions.Localization

as you guys remember in the full asp.net framework, switching between cultures was pretty easy

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

but in the .net core, culture is no longer tied to the current thread. The asp.net core kernel has a pipeline, and we can add various MiddleWares to it, so RequestLocalizationMiddleware is a middleware class for localization processing, we can have several providers, so it will iterate over all the culture providers, for example, QueryStringRequestCultureProvider , CookieRequestCultureProvider , AcceptLanguageHeaderReestquest recourider , AcceptLanguageHeaderReestquest recourider , RequerequestReestquest , ...

as soon as the middleware for localizing requests can receive the current locale from the first provider, it ignores the others and passes the request to the next middleware in the pipeline, so the order of the providers in the list really matters.

I personally prefer to store the culture in browser cookies, so since CookieRequestCultureProvider is not the first culture provider in the list, I move it to the top of the list, configure this part in Startup.cs> ConfigureServices as shown below

 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 }); }); 

let me describe the above code, the default culture of our application is en-US , and we only support English, Farsi, Germany, so if the browser uses a different language or you install a language other than these 3 languages ​​then the application should switch to culture default. in the above code, I simply remove the CookieCultureProvider from the list and add it as the first provider in the list (* I already described the reason why it should be the first *). CookieName works for me by default, you can change it if you want.

don't forget to add the code below under Configure (application IApplicationBuilder, enH IHostingEnvironment) in Startup.cs

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

so far so good. To have resource files, you must specify the resource path, I separately specify the resource for Controller, Views, ViewModels and SharedResources in the root path of the web project, the hierarchy is described below

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

keep in mind that for SharedResource create an empty class with the same name in the root path of the web project, I mean SharedResource.cs with a class with the same name inside.

Add the following code snippet to Startup.cs to specify the path to the resource and everything else.

 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(); 

with this configuration, for example, when you enter IStringLocalizer inside the controller, you must have the corresponding resource files in the Resources> Controllers folder (which are HomeController.resx, HomeController.fa-IR.resx, HomeController.de-DE.resx) we can also separate the path with . (say, period) in the file name, I mean Resources / Controllers / HomeController.resx can be a file in Resources / Controllers.HomeController.resx, you must embed IViewLocalizer in the views for the appropriate localization inside the views you must have resource files for views in the Resources / Views folder, for ViewModels, since we named the Models folder, please put all ViewModels in a previously created folder in the root path of the web project named Models. If the folder has a different name or you prefer a different name, do not forget to rename the Models folder in the Resource folder. then you do not need to do anything except annotate the models, for example, annotate the ViewModel properties using [DisplayName ("user email address")], and then create resources in the corresponding resource files inside the model (the file name must match the model class name) with the same key ("user email address").

let's end with where we started, I mean CookieRequestCultureProvider . As I said earlier, I prefer to store it in a cookie, but it's a bit complicated, because parsing a cookie is slightly different from what you might expect, just add the code below where you want to change the culture, just replace the preredCulture with your cultural preferences

 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)}); 

So, our main sp.net web application is now localized :)

+4
source

and Russian IdentityErrorDescriber, if anyone needs it.

 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>(); // ... } 
+3
source

Norwegian IdentityErrorDescriber, if anyone needs it.

 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 tall." }; } public override IdentityError PasswordRequiresLower() { return new IdentityError() { Code = "PasswordRequiresLower", Description = "Passordet må inneholde minst en liten bokstav (az)." }; } public override IdentityError PasswordRequiresUpper() { return new IdentityError() { Code = "PasswordRequiresUpper", Description = "Passordet må inneholde minst en stor bokstav (AZ)." }; } } 
+2
source

, :

    public class PolishLocalizedIdentityErrorDescriber : IdentityErrorDescriber
         {
            public override IdentityError DefaultError()
             {
                return new IdentityError
                 {
                    Code = nameof(DefaultError),
                    Description = "Wystąpił nieznany błąd."
                 };
             }

            public override IdentityError ConcurrencyFailure()
             {
                return new IdentityError
                 {
                    Code = nameof(ConcurrencyFailure),
                    Description = "Błąd współbieżności, obiekt został już zmodyfikowany."
                 };
             }

            public override IdentityError PasswordMismatch()
             {
                return new IdentityError
                 {
                    Code = nameof(PasswordMismatch),
                    Description = "Niepoprawne hasło."
                 };
             }

            public override IdentityError InvalidToken()
             {
                return new IdentityError
                 {
                    Code = nameof(InvalidToken),
                    Description = "Nieprawidłowy token."
                 };
             }

            public override IdentityError RecoveryCodeRedemptionFailed()
             {
                return new IdentityError
                 {
                    Code = nameof(RecoveryCodeRedemptionFailed),
                    Description = "Pobranie kodu odzyskiwania nie powiodło się."
                 };
             }

            public override IdentityError LoginAlreadyAssociated()
             {
                return new IdentityError
                 {
                    Code = nameof(LoginAlreadyAssociated),
                    Description = "Użytkownik o tym loginie już istnieje."
                 };
             }

            public override IdentityError InvalidUserName(string userName)
             {
                return new IdentityError
                 {
                    Code = nameof(InvalidUserName),
                    Description =
                        $"Nazwa użytkownika '{userName}' jest nieprawidłowa, może zawierać tylko litery lub cyfry."
                 };
             }

            public override IdentityError InvalidEmail(string email)
             {
                return new IdentityError
                 {
                    Code = nameof(InvalidEmail),
                    Description = $"Adres e-mail '{email}' jest nieprawidłowy."
                 };
             }

            public override IdentityError DuplicateUserName(string userName)
             {
                return new IdentityError
                 {
                    Code = nameof(DuplicateUserName),
                    Description = $"Nazwa '{userName}' jest już zajęta."
                 };
             }

            public override IdentityError DuplicateEmail(string email)
             {
                return new IdentityError
                 {
                    Code = nameof(DuplicateEmail),
                    Description = $"Adres e-mail '{email}' jest już zajęty."
                 };
             }

            public override IdentityError InvalidRoleName(string role)
             {
                return new IdentityError
                 {
                    Code = nameof(InvalidRoleName),
                    Description = $"Nazwa roli '{role}' już niepoprawna."
                 };
             }

            public override IdentityError DuplicateRoleName(string role)
             {
                return new IdentityError
                 {
                    Code = nameof(DuplicateRoleName),
                    Description = $"Rola '{role}' już istnieje."
                 };
             }

            public override IdentityError UserAlreadyHasPassword()
             {
                return new IdentityError
                 {
                    Code = nameof(UserAlreadyHasPassword),
                    Description = "Użytkownik ma już ustawione hasło."
                 };
             }

            public override IdentityError UserLockoutNotEnabled()
             {
                return new IdentityError
                 {
                    Code = nameof(UserLockoutNotEnabled),
                    Description = "Blokada konta nie jest włączona dla tego użytkownika."
                 };
             }

            public override IdentityError UserAlreadyInRole(string role)
             {
                return new IdentityError
                 {
                    Code = nameof(UserAlreadyInRole),
                    Description = $"Użytkownik korzysta już z roli '{role}'."
                 };
             }

            public override IdentityError UserNotInRole(string role)
             {
                return new IdentityError
                 {
                    Code = nameof(UserNotInRole),
                    Description = $"Użytkownika nie ma w roli '{role}'."
                 };
             }

            public override IdentityError PasswordTooShort(int length)
             {
                return new IdentityError
                 {
                    Code = nameof(PasswordTooShort),
                    Description = $"Hasło musi składać się z co najmniej {length} znaków."
                 };
             }

            public override IdentityError PasswordRequiresUniqueChars(int uniqueChars)
             {
                return new IdentityError
                 {
                    Code = nameof(PasswordRequiresUniqueChars),
                    Description = $"Hasło musi składać się z co najmniej {uniqueChars} unikalnych znaków."
                 };
             }

            public override IdentityError PasswordRequiresNonAlphanumeric()
             {
                return new IdentityError
                 {
                    Code = nameof(PasswordRequiresNonAlphanumeric),
                    Description = "Hasło musi zawierać co najmniej jeden znak niebędący literą lub cyfrą."
                 };
             }

            public override IdentityError PasswordRequiresDigit()
             {
                return new IdentityError
                 {
                    Code = nameof(PasswordRequiresDigit),
                    Description = "Hasło musi zawierać co najmniej jedną cyfrę (0-9)."
                 };
             }

            public override IdentityError PasswordRequiresLower()
             {
                return new IdentityError
                 {
                    Code = nameof(PasswordRequiresLower),
                    Description = "Hasło musi zawierać co najmniej jedną małą literę (az)."
                 };
             }

            public override IdentityError PasswordRequiresUpper()
             {
                return new IdentityError
                 {
                    Code = nameof(PasswordRequiresUpper),
                    Description = "Hasło musi zawierać co najmniej jedną wielką literę (AZ)."
                 };
             }
         }
+1
source

, , , , . 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 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 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 : enter image description here

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?}" ); }); } 

, cookie Culture, : . , - .

+1
source

All Articles