我试图通过使用以下帖子中的建议来获取针对Asp.Net Identity的瑞典语的本地化错误消息:How to localize ASP.NET Identity UserName and Password error messages?
使用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。下的新文件夹。< / p>
当我在本地运行我的网站时,我发现Microsoft.AspNet.Identity.Core.resources.dll已复制到MySite \ bin \ sv \
但是我无法让它发挥作用:(
如果我在我的Web.config中设置:
<system.web>
...
<globalization culture="sv-SE" uiCulture="sv" />
</system.web>
我仍然收到英文默认错误消息。但如果我改为德语,我已经从NuGet中收录了,我会收到德语错误消息。
使用dotPeek我将我的dll与德语进行了比较,除了我的PublicKeyToken = null和德语的#34; 31bf3856ad364e35&#34;之外,它们是相同的。这可能是我无法加载我的dll的原因吗?无论如何为dll设置PublicKeyToken?任何解决方法?
感谢您的任何指示。
答案 0 :(得分:8)
除非您拥有Microsoft用于签署dll的私钥。
更新:作为一种解决方法,直到我们添加对插入您自己的资源的支持,您现在可能只使用显式切换包装所有默认标识结果错误消息,应该只有大约10-20个面向用户的错误。
类似的东西:
public static string Localize(string error) {
switch (error) {
case "<english error>": return "<localized version";
}
}
答案 1 :(得分:5)
我需要在默认的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()
。
答案 2 :(得分:4)
目前这是一个非常糟糕的解决方案,但一个解决方案解决方案。为我们这些需要本地化并且不在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. (A-Z)";
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. (a-z)";
//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;
}
}
答案 3 :(得分:2)
另一种选择是从Microsoft.AspNet.Identity.PasswordValidator继承然后覆盖ValidateAsync。
然后,您可以使用自己的资源文件进行本地化。英语的原始资源文件可以使用DotPeek或类似文件找到,然后您可以将其用作英语作为您自己翻译的模板。
我的resx文件:
MyLocalization / IdentityResource.resx(与Microsoft.AspNet.Identity.Core.Resources相同)
MyLocalization / IdentityResource.nb-no.resx(我的挪威语翻译)
var manager = new ApplicationUserManager(new UserStore<ApplicationUser> (context.Get<ApplicationDbContext>()));
// 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;
}
/// <summary>
/// Ensures that the string is of the required length and meets the configured requirements
///
/// </summary>
/// <param name="item"/>
/// <returns/>
public override Task<IdentityResult> 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<string> list = new List<string>();
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<char>((IEnumerable<char>)item, new Func<char, bool>(this.IsLetterOrDigit)))
list.Add(Resources.PasswordRequireNonLetterOrDigit);
if (this.RequireDigit && Enumerable.All<char>((IEnumerable<char>)item, (Func<char, bool>)(c => !this.IsDigit(c))))
list.Add(Resources.PasswordRequireDigit);
if (this.RequireLowercase && Enumerable.All<char>((IEnumerable<char>)item, (Func<char, bool>)(c => !this.IsLower(c))))
list.Add(Resources.PasswordRequireLower);
if (this.RequireUppercase && Enumerable.All<char>((IEnumerable<char>)item, (Func<char, bool>)(c => !this.IsUpper(c))))
list.Add(Resources.PasswordRequireUpper);
if (list.Count == 0)
return Task.FromResult<IdentityResult>(IdentityResult.Success);
return Task.FromResult<IdentityResult>(IdentityResult.Failed(new string[1]
{
string.Join(" ", (IEnumerable<string>) list)
}));
}
}
`
答案 4 :(得分:2)
Password
字段的另一种解决方法是使用RegisterViewModel.Password
实现CustomValidationAttribute
:
public class RegisterViewModel
{
[CustomValidation(typeof(CustomValidations), "ValidatePassword")]
public string Password { get; set; }
}
使用CustomValidations.ValidatePassword
方法来模仿您为PasswordValidator
设置的密码验证规则。即:
public static class CustomValidations
{
public static ValidationResult ValidatePassword(string password)
{
// Implement validation logic here, e.g. require numbers,
// uppercase etc. and create localized ValidationResult.
return new ValidationResult(Resources.PasswordValidation.NoNumbers);
}
}
在这里,您可以使用标准的resx资源文件,显然可以根据个人喜好本地化您的错误消息。因此,总而言之,您只需禁止任何无效密码到达PasswordValidator
。
对于Email
字段,这会有点难看,因为它需要往返DB以验证唯一性等,但它应该是可行的。
使用此解决方案的额外好处是产生的错误将是“每个字段”,即您不必使用@Html.ValidationSummary
显示所有验证错误,但可以这样做:
@Html.ValidationMessageFor(m => m.Password, null, new { @class = "text-danger" })
答案 5 :(得分:0)
这是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<TRole>.
StoreNotIQueryableUserStore= Store does not implement IQueryableUserStore<TUser>.
StoreNotIUserClaimStore= Store does not implement IUserClaimStore<TUser>.
StoreNotIUserConfirmationStore= Store does not implement IUserConfirmationStore<TUser>.
StoreNotIUserEmailStore= Store does not implement IUserEmailStore<TUser>.
StoreNotIUserLockoutStore= Store does not implement IUserLockoutStore<TUser>.
StoreNotIUserLoginStore= Store does not implement IUserLoginStore<TUser>.
StoreNotIUserPasswordStore= Store does not implement IUserPasswordStore<TUser>.
StoreNotIUserPhoneNumberStore= Store does not implement IUserPhoneNumberStore<TUser>.
StoreNotIUserRoleStore= Store does not implement IUserRoleStore<TUser>.
StoreNotIUserSecurityStampStore= Store does not implement IUserSecurityStampStore<TUser>.
StoreNotIUserTwoFactorStore= Store does not implement IUserTwoFactorStore<TUser>.
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.*