mirror of https://github.com/abpframework/abp.git
16 changed files with 250 additions and 31 deletions
@ -0,0 +1,10 @@ |
|||
namespace Microsoft.Extensions.Localization |
|||
{ |
|||
public static class AbpStringLocalizerFactoryExtensions |
|||
{ |
|||
public static IStringLocalizer Create<TResource>(this IStringLocalizerFactory localizerFactory) |
|||
{ |
|||
return localizerFactory.Create(typeof(TResource)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.Abp.ExceptionHandling |
|||
{ |
|||
public interface ILocalizeErrorMessage |
|||
{ |
|||
string LocalizeMessage(LocalizationContext context); |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Localization |
|||
{ |
|||
public class LocalizationContext : IServiceProviderAccessor |
|||
{ |
|||
public IServiceProvider ServiceProvider { get; } |
|||
|
|||
public IStringLocalizerFactory LocalizerFactory { get; } |
|||
|
|||
public LocalizationContext(IServiceProvider serviceProvider) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
LocalizerFactory = ServiceProvider.GetRequiredService<IStringLocalizerFactory>(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,21 +1,9 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Volo.Abp.Identity |
|||
{ |
|||
public abstract class IdentityAppServiceBase : ApplicationService |
|||
{ |
|||
protected void CheckIdentityErrors(IdentityResult identityResult) |
|||
{ |
|||
if (!identityResult.Succeeded) |
|||
{ |
|||
//TODO: A better exception that can be shown on UI as localized?
|
|||
throw new AbpException("Operation failed: " + identityResult.Errors.Select(e => $"[{e.Code}] {e.Description}").JoinAsString(", ")); |
|||
} |
|||
|
|||
//identityResult.CheckErrors(LocalizationManager); //TODO: Get from old Abp
|
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,64 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.Text.Formatting; |
|||
|
|||
namespace Microsoft.AspNetCore.Identity |
|||
{ |
|||
public static class AbpIdentityResultExtensions |
|||
{ |
|||
public static void CheckErrors(this IdentityResult identityResult) |
|||
{ |
|||
if (identityResult.Succeeded) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (identityResult.Errors == null) |
|||
{ |
|||
throw new ArgumentException("identityResult.Errors should not be null."); |
|||
} |
|||
|
|||
throw new AbpIdentityResultException(identityResult); |
|||
} |
|||
|
|||
public static string LocalizeErrors(this IdentityResult identityResult, IStringLocalizer localizer) |
|||
{ |
|||
if (identityResult.Succeeded) |
|||
{ |
|||
throw new ArgumentException("identityResult.Succeeded should be false in order to localize errors."); |
|||
} |
|||
|
|||
if (identityResult.Errors == null) |
|||
{ |
|||
throw new ArgumentException("identityResult.Errors should not be null."); |
|||
} |
|||
|
|||
return identityResult.Errors.Select(err => LocalizeErrorMessage(err, localizer)).JoinAsString(", "); |
|||
} |
|||
|
|||
public static string LocalizeErrorMessage(this IdentityError error, IStringLocalizer localizer) |
|||
{ |
|||
var key = $"Identity.{error.Code}"; |
|||
|
|||
var localizedString = localizer[key]; |
|||
|
|||
if (!localizedString.ResourceNotFound) |
|||
{ |
|||
var englishLocalizedString = localizer.WithCulture(CultureInfo.GetCultureInfo("en"))[key]; |
|||
if (!englishLocalizedString.ResourceNotFound) |
|||
{ |
|||
if (FormattedStringValueExtracter.IsMatch(error.Description, englishLocalizedString.Value, out var values)) |
|||
{ |
|||
return string.Format(localizedString.Value, values.Cast<object>().ToArray()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return localizer["Identity.Default"]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Runtime.Serialization; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.ExceptionHandling; |
|||
using Volo.Abp.Identity.Localization; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.Abp.Identity |
|||
{ |
|||
[Serializable] |
|||
public class AbpIdentityResultException : BusinessException, ILocalizeErrorMessage |
|||
{ |
|||
public IdentityResult IdentityResult { get; } |
|||
|
|||
public AbpIdentityResultException([NotNull] IdentityResult identityResult) |
|||
: base( |
|||
code: $"Identity.{identityResult.Errors.First().Code}", |
|||
message: identityResult.Errors.Select(err => err.Description).JoinAsString(", ")) |
|||
{ |
|||
IdentityResult = Check.NotNull(identityResult, nameof(identityResult)); |
|||
} |
|||
|
|||
public AbpIdentityResultException(SerializationInfo serializationInfo, StreamingContext context) |
|||
: base(serializationInfo, context) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public string LocalizeMessage(LocalizationContext context) |
|||
{ |
|||
return IdentityResult.LocalizeErrors(context.LocalizerFactory.Create<IdentityResource>()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"culture": "en", |
|||
"texts": { |
|||
"Identity.PasswordTooShort": "Passwords must be at least {0} characters.", |
|||
"Identity.PasswordRequiresNonAlphanumeric": "Passwords must have at least one non alphanumeric character." |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"culture": "tr", |
|||
"texts": { |
|||
"Identity.PasswordTooShort": "Şifre en az {0} karakter uzunluğunda olmalı.", |
|||
"Identity.PasswordRequiresNonAlphanumeric": "Şifre en az bir sayı ya da harf olmayan karakter içermeli." |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Shouldly; |
|||
using Volo.Abp.Localization; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Identity |
|||
{ |
|||
public class AbpIdentityResultException_Tests : AbpIdentityDomainTestBase |
|||
{ |
|||
[Fact] |
|||
public void Should_Localize_Messages() |
|||
{ |
|||
var exception = new AbpIdentityResultException( |
|||
IdentityResult.Failed( |
|||
new IdentityError |
|||
{ |
|||
Code = "PasswordTooShort", |
|||
Description = "Passwords must be at least 6 characters." |
|||
}, |
|||
new IdentityError |
|||
{ |
|||
Code = "PasswordRequiresNonAlphanumeric", |
|||
Description = "Passwords must have at least one non alphanumeric character." |
|||
} |
|||
) |
|||
); |
|||
|
|||
using (AbpCultureHelper.Use("tr")) |
|||
{ |
|||
var localizeMessage = exception.LocalizeMessage(new LocalizationContext(ServiceProvider)); |
|||
|
|||
localizeMessage.ShouldContain("Şifre en az 6 karakter uzunluğunda olmalı."); |
|||
localizeMessage.ShouldContain("Şifre en az bir sayı ya da harf olmayan karakter içermeli."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue