Asp.Net Identity Localization PublicKeyToken

我试图通过使用以下post的建议来获取瑞典语对Asp.Net Identity的本地化错误消息: 如何本地化ASP.NET Identity UserName和Password错误消息?

使用NuGet我下载了德语语言包,然后在dotPeek中打开\ packages \ Microsoft.AspNet.Identity.Core.2.0.0 \ lib \ net45 \ de \ Microsoft.AspNet.Identity.Core.resources.dll,然后将其导出到一个新的VS项目:

https://github.com/nielsbosma/AspNet.Identity.Resources.Swedish/

我已将生成的\ Microsoft.AspNet.Identity.Core.resources.dll复制到\​​ packages \ Microsoft.AspNet.Identity.Core.2.0.0 \ lib \ net45 \ se下的新文件夹。

当我在本地运行我的网站时,我看到Microsoft.AspNet.Identity.Core.resources.dll已被复制到MySite \ bin \ sv \

但我不能让它工作:(

如果我在我的Web.config中设置:

 ...   

我仍然得到英文默认错误消息。 但如果我改为德语,我已经从NuGet中包含了我收到德语错误消息。

使用dotPeek我将我的dll与德语进行了比较,除了我的PublicKeyToken = null和德语为“31bf3856ad364e35”之外,它们是相同的。 这可能是我无法加载我的DLL的原因吗? 无论如何为dll设置PublicKeyToken? 任何解决方法?

谢谢你的任何指示。

除非您拥有Microsoft用于签署dll的私钥。

更新:作为一种解决方法,直到我们添加对插入您自己的资源的支持,您现在可能只使用显式切换包装所有默认标识结果错误消息,应该只有大约10-20个面向用户的错误。

就像是:

 public static string Localize(string error) { switch (error) { case "": return " 

在Peter的答案的启发下,我想出了蹩脚但快速的解决方案。

我需要在默认的AccountController模板中本地化错误,所以我编写了自己的AddLocalizedErrors方法。 我正在使用Resources来本地化错误。

  //Original method private void AddErrors(IdentityResult result) { foreach (var error in result.Errors) { ModelState.AddModelError("", error); } } //My method private void AddLocalizedErrors(IdentityResult result, ApplicationUser user) { foreach (var error in result.Errors) { var localizedError = error; string userName = ""; string email = ""; if (user != null) { userName = user.UserName; email = user.Email; } //password errors localizedError = localizedError.Replace("Passwords must have at least one uppercase ('A'-'Z').", AspNetValidationMessages.password_uppercase); localizedError = localizedError.Replace("Passwords must have at least one digit ('0'-'9').", AspNetValidationMessages.password_digit); localizedError = localizedError.Replace("Passwords must have at least one lowercase ('a'-'z').", AspNetValidationMessages.password_lowercase); localizedError = localizedError.Replace("Passwords must have at least one non letter or digit character.", AspNetValidationMessages.password_nonletter_nondigit); localizedError = localizedError.Replace("Passwords must have at least one non letter or digit character.", AspNetValidationMessages.password_nonletter_nondigit); localizedError = localizedError.Replace("Passwords must have at least one non letter or digit character.", AspNetValidationMessages.password_nonletter_nondigit); //register errors localizedError = localizedError.Replace("Name "+userName+" is already taken.", AspNetValidationMessages.name_taken.Replace("{0}", userName)); localizedError = localizedError.Replace("Email '" + email + "' is already taken.", AspNetValidationMessages.email_taken.Replace("{0}", email)); ModelState.AddModelError("", localizedError); } } 

我正在使用string.Replace()因为例如密码错误只是单个密码要求的字符串。

谈到角色的收集,我应该更有创意。 可能使用string.Contains()

目前这是一个非常糟糕的解决方案,但一个解决方案解决方案。 为我们这些需要本地化并且不在Microsoft工作的人节省时间…这就是我作为荷兰语语言的解决方法所做的。

 public class Demo { private string LocalizeIdentityError(string error, IdentityUser user) { if (error == "User already in role.") return "De gebruiker zit reeds in deze rol."; else if (error == "User is not in role.") return "De gebruiker zit niet in deze rol."; //else if (error == "Role {0} does not exist.") return "De rol bestaat nog niet"; //else if (error == "Store does not implement IUserClaimStore<TUser>.") return ""; //else if (error == "No IUserTwoFactorProvider for '{0}' is registered.") return ""; //else if (error == "Store does not implement IUserEmailStore<TUser>.") return ""; else if (error == "Incorrect password.") return "Ongeldig wachtwoord"; //else if (error == "Store does not implement IUserLockoutStore<TUser>.") return ""; //else if (error == "No IUserTokenProvider is registered.") return ""; //else if (error == "Store does not implement IUserRoleStore<TUser>.") return ""; //else if (error == "Store does not implement IUserLoginStore<TUser>.") return ""; else if (error == "User name {0} is invalid, can only contain letters or digits.") return "De gebruikersnaam '"+user.UserName+"' kan alleen letters of cijfers bevatten."; //else if (error == "Store does not implement IUserPhoneNumberStore<TUser>.") return ""; //else if (error == "Store does not implement IUserConfirmationStore<TUser>.") return ""; else if (error.StartsWith("Passwords must be at least ")) return "Een wachtwoord moet minstens {0} karakters bevatten."; //else if (error == "{0} cannot be null or empty.") return ""; else if (user != null && error == "Name "+user.UserName+" is already taken.") return "De gebruikersnaam '" + user.UserName + "' is reeds in gebruik."; else if (error == "User already has a password set.") return "Deze gebruiker heeft reeds een wachtwoord ingesteld."; //else if (error == "Store does not implement IUserPasswordStore<TUser>.") return ""; else if (error == "Passwords must have at least one non letter or digit character.") return "Wachtwoorden moeten minstens een ander karakter dan een letter of cijfer bevatten."; else if (error == "UserId not found.") return "De gebruiker kon niet gevonden worden."; else if (error == "Invalid token.") return "Ongeldig token."; else if (user != null && error == "Email '" + user.Email + "' is invalid.") return "Het emailadres '" + user.Email + "' is ongeldig."; else if (user != null && error == "User " + user.UserName + " does not exist.") return "De gebruiker '" + user.UserName + "' bestaat niet."; else if (error == "Store does not implement IQueryableRoleStore<TRole>.") return ""; else if (error == "Lockout is not enabled for this user.") return "Lockout is niet geactiveerd voor deze gebruiker."; //else if (error == "Store does not implement IUserTwoFactorStore<TUser>.") return ""; else if (error == "Passwords must have at least one uppercase ('A'-'Z').") return "Wachtwoorden moeten minstens één hoofdletter bevatten. (AZ)"; else if (error == "Passwords must have at least one digit ('0'-'9').") return "Wachtwoorden moeten minstens één getal bevatten. (0-9)"; else if (error == "Passwords must have at least one lowercase ('a'-'z').") return "Wachtwoorden moeten minstens één kleine letter bevatten. (az)"; //else if (error == "Store does not implement IQueryableUserStore<TUser>.") return ""; else if (user != null && error == "Email '" + user.Email + "' is already taken.") return "Het emailadres '" + user.Email + "' is reeds in gebruik. Probeer aan te melden."; //else if (error == "Store does not implement IUserSecurityStampStore<TUser>.") return ""; else if (error == "A user with that external login already exists.") return "Een gebruiker met deze externe login bestaat reeds."; else if (error == "An unknown failure has occured.") return "Een onbekende fout is opgetreden. Probeer het later opnieuw."; return error; } } 

另一种选择是从Microsoft.AspNet.Identity.PasswordValidatorinheritance然后覆盖ValidateAsync。

然后,您可以使用自己的资源文件进行本地化。 可以使用DotPeek或类似工具找到英语的原始资源文件,然后您可以将其用作英语作为您自己的其他语言翻译的模板。

我的resx文件:

MyLocalization / IdentityResource.resx(与Microsoft.AspNet.Identity.Core.Resources中的相同)

MyLocalization / IdentityResource.nb-no.resx(我的挪威语翻译)

  var manager = new ApplicationUserManager(new UserStore (context.Get())); // Configure validation logic for passwords manager.PasswordValidator = new MyCustomPasswordValidator(System.Threading.Thread.CurrentThread.CurrentUICulture) 

在MyCustomPasswordValidator.cs中:(还请注意我在ValidateAsync中也必须做的错误修正)

 using Resources = MyLocalization.IdentityResource; public class MyCustomPasswordValidator : Microsoft.AspNet.Identity.PasswordValidator { private readonly CultureInfo _currentUIculture; public MyCustomPasswordValidator(CultureInfo currentUIculture) { _currentUIculture = currentUIculture; } ///  /// Ensures that the string is of the required length and meets the configured requirements /// ///  ///  ///  public override Task ValidateAsync(string item) { //BUG: CurrentUICulture is not set correctly https://aspnetidentity.codeplex.com/workitem/2060 System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUIculture; if (item == null) throw new ArgumentNullException("item"); List list = new List(); if (string.IsNullOrWhiteSpace(item) || item.Length < this.RequiredLength) list.Add(string.Format((IFormatProvider)CultureInfo.CurrentCulture, Resources.PasswordTooShort, new object[1] { (object) this.RequiredLength })); if (this.RequireNonLetterOrDigit && Enumerable.All((IEnumerable)item, new Func(this.IsLetterOrDigit))) list.Add(Resources.PasswordRequireNonLetterOrDigit); if (this.RequireDigit && Enumerable.All((IEnumerable)item, (Func)(c => !this.IsDigit(c)))) list.Add(Resources.PasswordRequireDigit); if (this.RequireLowercase && Enumerable.All((IEnumerable)item, (Func)(c => !this.IsLower(c)))) list.Add(Resources.PasswordRequireLower); if (this.RequireUppercase && Enumerable.All((IEnumerable)item, (Func)(c => !this.IsUpper(c)))) list.Add(Resources.PasswordRequireUpper); if (list.Count == 0) return Task.FromResult(IdentityResult.Success); return Task.FromResult(IdentityResult.Failed(new string[1] { string.Join(" ", (IEnumerable) list) })); } } 

`

Password字段的另一个解决方法可能是使用CustomValidationAttribute实现RegisterViewModel.Password

 public class RegisterViewModel { [CustomValidation(typeof(CustomValidations), "ValidatePassword")] public string Password { get; set; } } 

并拥有CustomValidations.ValidatePassword方法,该方法将模拟您为PasswordValidator设置的密码validation规则。 即:

 public static class CustomValidations { public static ValidationResult ValidatePassword(string password) { // Implement validation logic here, eg require numbers, // uppercase etc. and create localized ValidationResult. return new ValidationResult(Resources.PasswordValidation.NoNumbers); } } 

在这里,您可以使用标准resx资源文件,根据个人喜好显然可以本地化您的错误消息。 因此,总而言之,您只需禁止任何无效密码到达PasswordValidator

对于Email字段,这会有点难看,因为它需要往返DB来validation唯一性等,但它应该是可行的。

使用此解决方案的额外好处是产生的错误将是“每个字段”,即您不必使用@Html.ValidationSummary显示所有validation错误,但可以执行以下操作:

 @Html.ValidationMessageFor(m => m.Password, null, new { @class = "text-danger" }) 

这是en-US Resources.resx文件键和值列表。 这些是需要本地化的值。 源代码见http://aspnetidentity.codeplex.com

Asp.Net Identity {name} Validator.cs ErrorMessage Resources.resx本地化请参阅: http : //aspnetidentity.codeplex.com/discussions/638351

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