diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs new file mode 100644 index 0000000000..fae03d74b8 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs @@ -0,0 +1,63 @@ +using System; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using Microsoft.AspNetCore.Mvc.DataAnnotations; +using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; + +namespace Volo.Abp.AspNetCore.Mvc +{ + public class AbpDataAnnotationAutoLocalizationMetadataDetailsProvider : IDisplayMetadataProvider + { + private const string PropertyLocalizationKeyPrefix = "Property:"; + + private readonly Lazy _stringLocalizerFactory; + private readonly Lazy> _localizationOptions; + + public AbpDataAnnotationAutoLocalizationMetadataDetailsProvider(IServiceCollection services) + { + _stringLocalizerFactory = services.GetRequiredServiceLazy(); + _localizationOptions = services.GetRequiredServiceLazy>(); + } + + public void CreateDisplayMetadata(DisplayMetadataProviderContext context) + { + var displayMetadata = context.DisplayMetadata; + if (displayMetadata.DisplayName != null) + { + return; + } + + var attributes = context.Attributes; + + if (attributes.OfType().Any() || + attributes.OfType().Any()) + { + return; + } + + if (_localizationOptions.Value.Value.DataAnnotationLocalizerProvider == null) + { + return; + } + + var containerType = context.Key.ContainerType ?? context.Key.ModelType; + var localizer = _localizationOptions.Value.Value.DataAnnotationLocalizerProvider(containerType, _stringLocalizerFactory.Value); + + displayMetadata.DisplayName = () => + { + var localizedString = localizer[PropertyLocalizationKeyPrefix + context.Key.Name]; + + if (localizedString.ResourceNotFound) + { + localizedString = localizer[context.Key.Name]; + } + + return localizedString; + }; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs index dd509b1746..4de46b2f0b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs @@ -15,6 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc AddConventions(options, services); AddFilters(options); AddModelBinders(options); + AddMetadataProviders(options, services); } private static void AddConventions(MvcOptions options, IServiceCollection services) @@ -34,5 +35,12 @@ namespace Volo.Abp.AspNetCore.Mvc { //options.ModelBinderProviders.Add(new AbpDateTimeModelBinderProvider()); } + + private static void AddMetadataProviders(MvcOptions options, IServiceCollection services) + { + options.ModelMetadataDetailsProviders.Add( + new AbpDataAnnotationAutoLocalizationMetadataDetailsProvider(services) + ); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpMvcDataAnnotationsLocalizationOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpMvcDataAnnotationsLocalizationOptions.cs index bca738b101..70c15cfd55 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpMvcDataAnnotationsLocalizationOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpMvcDataAnnotationsLocalizationOptions.cs @@ -15,12 +15,12 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization } public void AddAssemblyResource( - [NotNull] Type resourceType, + [NotNull] Type resourceType, params Assembly[] assemblies) { if (assemblies.IsNullOrEmpty()) { - assemblies = new Assembly[] {resourceType.Assembly}; + assemblies = new[] { resourceType.Assembly }; } foreach (var assembly in assemblies) diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/LocalizationTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/LocalizationTestController.cs index 184bfe1c99..1a9b6e7de8 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/LocalizationTestController.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/App/LocalizationTestController.cs @@ -19,7 +19,7 @@ namespace Volo.Abp.AspNetCore.App public class PersonModel { - [Display(Name = nameof(BirthDate))] + //[Display(Name = nameof(BirthDate))] public string BirthDate { get; set; } public PersonModel()