From e21cf5cd864c97b35c3bfde7627fa915808d9774 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 4 Sep 2020 00:04:49 +0800 Subject: [PATCH] Redesign multi-lingual --- framework/Volo.Abp.sln | 14 +++ .../AbpAutoMapperMultiLingualDtoExtensions.cs | 96 +++----------- .../Volo.Abp.AutoMapper.csproj | 1 + .../Abp/AutoMapper/AbpAutoMapperModule.cs | 4 +- .../Abp/Domain/Entities/IEntityTranslation.cs | 21 ---- .../Domain/Entities/IMultiLingualEntity.cs | 10 -- .../Volo.Abp.EntityFrameworkCore.csproj | 1 + .../AbpEntityTypeBuilderExtensions.cs | 13 +- .../FodyWeavers.xml | 3 + .../FodyWeavers.xsd | 30 +++++ .../Volo.Abp.MultiLingualObject.csproj | 15 +++ .../AbpMultiLingualObjectModule.cs | 11 ++ .../MultiLingualObject/IHasMultiLingual.cs | 10 ++ .../IMultiLingualTranslation.cs | 15 +++ .../MultiLingualObjectExtensions.cs | 74 +++++++++++ ...toMapperMultiLingualDtoExtensions_Tests.cs | 99 +++++++-------- .../Volo.Abp.AutoMapper.Tests.csproj | 3 +- .../Abp/AutoMapper/AutoMapperTestModule.cs | 5 +- .../Volo.Abp.MultiLingualObject.Tests.csproj | 18 +++ .../AbpMultiLingualObjectTestModule.cs | 25 ++++ .../MultiLingualObject_Tests.cs | 117 ++++++++++++++++++ .../TestObjects/MultiLingualBook.cs | 20 +++ .../TestObjects/MultiLingualBookDto.cs | 13 ++ .../MultiLingualBookTranslation.cs | 15 +++ nupkg/common.ps1 | 3 +- 25 files changed, 464 insertions(+), 172 deletions(-) delete mode 100644 framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs delete mode 100644 framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs create mode 100644 framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xml create mode 100644 framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xsd create mode 100644 framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj create mode 100644 framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectModule.cs create mode 100644 framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IHasMultiLingual.cs create mode 100644 framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs create mode 100644 framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs create mode 100644 framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj create mode 100644 framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs create mode 100644 framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs create mode 100644 framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBook.cs create mode 100644 framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookDto.cs create mode 100644 framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookTranslation.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index aa0a3f1222..f45ae3d9dc 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -331,6 +331,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.GlobalFeatures", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.GlobalFeatures.Tests", "test\Volo.Abp.GlobalFeatures.Tests\Volo.Abp.GlobalFeatures.Tests.csproj", "{231F1581-AA21-44C3-BF27-51EB3AD5355C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MultiLingualObject", "src\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj", "{C9142DED-1F6C-4385-A37D-81E46B233306}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MultiLingualObject.Tests", "test\Volo.Abp.MultiLingualObject.Tests\Volo.Abp.MultiLingualObject.Tests.csproj", "{A30D63B0-E952-4052-BAEE-38B8BF924093}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -985,6 +989,14 @@ Global {231F1581-AA21-44C3-BF27-51EB3AD5355C}.Debug|Any CPU.Build.0 = Debug|Any CPU {231F1581-AA21-44C3-BF27-51EB3AD5355C}.Release|Any CPU.ActiveCfg = Release|Any CPU {231F1581-AA21-44C3-BF27-51EB3AD5355C}.Release|Any CPU.Build.0 = Release|Any CPU + {C9142DED-1F6C-4385-A37D-81E46B233306}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9142DED-1F6C-4385-A37D-81E46B233306}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9142DED-1F6C-4385-A37D-81E46B233306}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9142DED-1F6C-4385-A37D-81E46B233306}.Release|Any CPU.Build.0 = Release|Any CPU + {A30D63B0-E952-4052-BAEE-38B8BF924093}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A30D63B0-E952-4052-BAEE-38B8BF924093}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A30D63B0-E952-4052-BAEE-38B8BF924093}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A30D63B0-E952-4052-BAEE-38B8BF924093}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1152,6 +1164,8 @@ Global {C1D891B0-AE83-42CB-987D-425A2787DE78} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {04F44063-C952-403A-815F-EFB778BDA125} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {231F1581-AA21-44C3-BF27-51EB3AD5355C} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {C9142DED-1F6C-4385-A37D-81E46B233306} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {A30D63B0-E952-4052-BAEE-38B8BF924093} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs index 37ed4af95d..273ad35645 100644 --- a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs +++ b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs @@ -1,99 +1,41 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Volo.Abp.Domain.Entities; -using Volo.Abp.Localization; +using Volo.Abp.MultiLingualObject; using Volo.Abp.Settings; -using Volo.Abp.Threading; namespace AutoMapper { public static class AbpAutoMapperMultiLingualDtoExtensions { - public static CreateMultiLingualMapResult CreateMultLingualMap< - TMultiLingualEntity, + public static CreateMultiLingualMapResult MapMultiLingual( - this Profile profile, - ISettingProvider serviceProvider, + this IMappingExpression mappingExpression, + Profile profile, + ISettingProvider provider, bool fallbackToParentCultures = false) - where TMultiLingualEntity : class, IMultiLingualEntity - where TTranslation : class, IEntityTranslation + where TDestination : class + where TSource : IHasMultiLingual + where TTranslation : class, IMultiLingualTranslation { - return new CreateMultiLingualMapResult + return new CreateMultiLingualMapResult { TranslationMap = profile.CreateMap(), - EntityMap = profile.CreateMap().BeforeMap( - (source, destination, context) => - { - if (source.Translations == null || !source.Translations.Any()) - { - return; - } - - var translation = - source.Translations.FirstOrDefault(pt => pt.Language == CultureInfo.CurrentUICulture.Name); - if (translation != null) - { - context.Mapper.Map(translation, destination); - return; - } - - if (fallbackToParentCultures) - { - translation = - GeTranslationBasedOnCulturalRecursive( - CultureInfo.CurrentUICulture.Parent, source.Translations, 0); - if (translation != null) - { - context.Mapper.Map(translation, destination); - return; - } - } - var defaultLanguage = AsyncHelper.RunSync(() => - serviceProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage)); + EntityMap = mappingExpression.BeforeMap((source, destination, context) => + { + var translation = source.GetMultiLingualTranslation(provider, fallbackToParentCultures); - translation = source.Translations.FirstOrDefault(pt => pt.Language == defaultLanguage); - if (translation != null) - { - context.Mapper.Map(translation, destination); - return; - } - - translation = source.Translations.FirstOrDefault(); - if (translation != null) - { - context.Mapper.Map(translation, destination); - } - }) + if (translation != null) + { + context.Mapper.Map(translation, destination); + } + }) }; } - - private const int MaxCultureFallbackDepth = 5; - - private static TTranslation GeTranslationBasedOnCulturalRecursive( - CultureInfo culture, ICollection translations, int currentDepth) - where TTranslation : class, IEntityTranslation - { - if (culture == null || culture.Name.IsNullOrWhiteSpace() || translations.IsNullOrEmpty() || - currentDepth > MaxCultureFallbackDepth) - { - return null; - } - - var translation = translations.FirstOrDefault(pt => - pt.Language.Equals(culture.Name, StringComparison.OrdinalIgnoreCase)); - return translation ?? - GeTranslationBasedOnCulturalRecursive(culture.Parent, - translations, currentDepth + 1); - } } - public class CreateMultiLingualMapResult + public class CreateMultiLingualMapResult { public IMappingExpression TranslationMap { get; set; } - public IMappingExpression EntityMap { get; set; } + public IMappingExpression EntityMap { get; set; } } } diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index 6e261e0b2a..124c47e055 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -16,6 +16,7 @@ + diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs index 214872e371..15df0d6986 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.Auditing; using Volo.Abp.Modularity; +using Volo.Abp.MultiLingualObject; using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectMapping; @@ -12,7 +13,8 @@ namespace Volo.Abp.AutoMapper [DependsOn( typeof(AbpObjectMappingModule), typeof(AbpObjectExtendingModule), - typeof(AbpAuditingModule) + typeof(AbpAuditingModule), + typeof(AbpMultiLingualObjectModule) )] public class AbpAutoMapperModule : AbpModule { diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs deleted file mode 100644 index 0684e615ad..0000000000 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Volo.Abp.Domain.Entities -{ - public interface IEntityTranslation - { - string Language { get; set; } - } - - public interface IEntityTranslation : IEntityTranslation - where TEntity : IEntity - { - TEntity Core { get; set; } - - TPrimaryKeyOfMultiLingualEntity CoreId { get; set; } - } - - public interface IEntityTranslation: IEntityTranslation - where TEntity : IEntity - { - - } -} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs deleted file mode 100644 index 2b25a7a90a..0000000000 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.Generic; - -namespace Volo.Abp.Domain.Entities -{ - public interface IMultiLingualEntity - where TTranslation : class, IEntityTranslation - { - ICollection Translations { get; set; } - } -} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj index 4c6fb7fbbc..f569b14da3 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj @@ -17,6 +17,7 @@ + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs index f70e64bb0a..c930e41a6c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs @@ -7,6 +7,7 @@ using Volo.Abp.Data; using Volo.Abp.Domain.Entities; using Volo.Abp.EntityFrameworkCore.ValueComparers; using Volo.Abp.EntityFrameworkCore.ValueConverters; +using Volo.Abp.MultiLingualObject; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectExtending; @@ -304,21 +305,21 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling } public static void ConfigureMultiLingual(this EntityTypeBuilder b) - where T : class, IMultiLingualEntity - where TTranslation : class, IEntityTranslation + where T : class, IHasMultiLingual + where TTranslation : class, IMultiLingualTranslation { b.As().TryConfigureEntityTranslation(); } public static void TryConfigureEntityTranslation(this EntityTypeBuilder b) { - if (b.Metadata.ClrType.IsAssignableTo()) + if (b.Metadata.ClrType.IsAssignableTo()) { - b.HasIndex(nameof(IEntityTranslation.Language)) + b.HasIndex(nameof(IMultiLingualTranslation.Language)) .IsUnique(); - b.Property(nameof(IEntityTranslation.Language)) + b.Property(nameof(IMultiLingualTranslation.Language)) .IsRequired() - .HasColumnName(nameof(IEntityTranslation.Language)); + .HasColumnName(nameof(IMultiLingualTranslation.Language)); } } diff --git a/framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xml b/framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xml new file mode 100644 index 0000000000..be0de3a908 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xsd b/framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj b/framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj new file mode 100644 index 0000000000..8f491565d9 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj @@ -0,0 +1,15 @@ + + + + + + + netstandard2.0 + + + + + + + + diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectModule.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectModule.cs new file mode 100644 index 0000000000..120cf7bac1 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectModule.cs @@ -0,0 +1,11 @@ +using Volo.Abp.Localization; +using Volo.Abp.Modularity; + +namespace Volo.Abp.MultiLingualObject +{ + [DependsOn( + typeof(AbpLocalizationModule))] + public class AbpMultiLingualObjectModule : AbpModule + { + } +} diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IHasMultiLingual.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IHasMultiLingual.cs new file mode 100644 index 0000000000..8ea05ecabd --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IHasMultiLingual.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Volo.Abp.MultiLingualObject +{ + public interface IHasMultiLingual + where TTranslation : class, IMultiLingualTranslation + { + ICollection Translations { get; set; } + } +} diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs new file mode 100644 index 0000000000..4490f569fe --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs @@ -0,0 +1,15 @@ +namespace Volo.Abp.MultiLingualObject +{ + public interface IMultiLingualTranslation + { + string Language { get; set; } + } + + public interface IMultiLingualTranslation : IMultiLingualTranslation + where T : class + { + T Core { get; set; } + + TPrimaryKeyOfMultiLingualObject CoreId { get; set; } + } +} diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs new file mode 100644 index 0000000000..6212927b02 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Volo.Abp.Localization; +using Volo.Abp.Settings; +using Volo.Abp.Threading; + +namespace Volo.Abp.MultiLingualObject +{ + public static class MultiLingualObjectExtensions + { + public static TTranslation GetMultiLingualTranslation( + this IHasMultiLingual hasMultiLingual, + ISettingProvider settingProvider, + bool fallbackToParentCultures = false) + where TTranslation : class, IMultiLingualTranslation + { + if (hasMultiLingual.Translations == null || !hasMultiLingual.Translations.Any()) + { + return null; + } + + var translation = + hasMultiLingual.Translations.FirstOrDefault(pt => pt.Language == CultureInfo.CurrentUICulture.Name); + if (translation != null) + { + return translation; + } + + if (fallbackToParentCultures) + { + translation = + GeTranslationBasedOnCulturalRecursive( + CultureInfo.CurrentUICulture.Parent, hasMultiLingual.Translations, 0); + if (translation != null) + { + return translation; + } + } + + var defaultLanguage = AsyncHelper.RunSync(() => + settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage)); + + translation = hasMultiLingual.Translations.FirstOrDefault(pt => pt.Language == defaultLanguage); + if (translation != null) + { + return translation; + } + + translation = hasMultiLingual.Translations.FirstOrDefault(); + return translation; + } + + private const int MaxCultureFallbackDepth = 5; + + private static TTranslation GeTranslationBasedOnCulturalRecursive( + CultureInfo culture, ICollection translations, int currentDepth) + where TTranslation : class, IMultiLingualTranslation + { + if (culture == null || culture.Name.IsNullOrWhiteSpace() || translations.IsNullOrEmpty() || + currentDepth > MaxCultureFallbackDepth) + { + return null; + } + + var translation = translations.FirstOrDefault(pt => + pt.Language.Equals(culture.Name, StringComparison.OrdinalIgnoreCase)); + return translation ?? + GeTranslationBasedOnCulturalRecursive(culture.Parent, + translations, currentDepth + 1); + } + } +} diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs index 22675b61ca..e89bf93375 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs +++ b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; -using System.Globalization; using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp; using Volo.Abp.AutoMapper; -using Volo.Abp.Domain.Entities; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization; +using Volo.Abp.MultiLingualObject.TestObjects; using Volo.Abp.Settings; using Volo.Abp.Testing; using Xunit; @@ -14,24 +16,24 @@ namespace AutoMapper public class AbpAutoMapperMultiLingualDtoExtensions_Tests : AbpIntegratedTest { private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper; - private readonly Book _book; + private readonly MultiLingualBook _book; public AbpAutoMapperMultiLingualDtoExtensions_Tests() { _objectMapper = ServiceProvider.GetRequiredService(); var id = Guid.NewGuid(); - _book = new Book(id, 100) + _book = new MultiLingualBook(id, 100) { - Translations = new List + Translations = new List { - new BookTranslation + new MultiLingualBookTranslation { CoreId = id, Language = "en", Name = "C# in Depth" }, - new BookTranslation + new MultiLingualBookTranslation { CoreId = id, Language = "zh-Hans", @@ -41,72 +43,65 @@ namespace AutoMapper }; } - [Fact] - public void Should_Map_CurrentUICulture() + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) { - CultureInfo.CurrentCulture = new CultureInfo("en"); - var bookDto = _objectMapper.Map(_book); - - bookDto.Name.ShouldBe("C# in Depth"); - bookDto.Price.ShouldBe(_book.Price); - bookDto.Id.ShouldBe(_book.Id); + options.UseAutofac(); } [Fact] - public void Should_Map_FeedbackUICulture() + public void Should_Map_Current_UI_Culture() { - CultureInfo.CurrentCulture = new CultureInfo("en-us"); - var bookDto = _objectMapper.Map(_book); + using (CultureHelper.Use("zh-Hans")) + { + var bookDto = _objectMapper.Map(_book); - bookDto.Name.ShouldBe("C# in Depth"); - bookDto.Price.ShouldBe(100); - bookDto.Id.ShouldBe(_book.Id); + bookDto.Name.ShouldBe("深入理解C#"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } } - } - public class Book : Entity, IMultiLingualEntity - { - public Book(Guid id, decimal price) + [Fact] + public void Should_Map_Fallback_UI_Culture() { - Id = id; - Price = price; - } - - public decimal Price { get; set; } - - public ICollection Translations { get; set; } - } - - public class BookTranslation : IEntityTranslation - { - public string Name { get; set; } - - public string Language { get; set; } - - public Book Core { get; set; } - - public Guid CoreId { get; set; } - } + using (CultureHelper.Use("en-us")) + { + var bookDto = _objectMapper.Map(_book); - public class BookDto - { - public string Name { get; set; } + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } - public Guid Id { get; set; } + [Fact] + public void Should_Map_Default_Language() + { + using (CultureHelper.Use("tr")) + { + var bookDto = _objectMapper.Map(_book); - public decimal Price { get; set; } + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } } - public class BookProfile : Profile + public class BookProfile : Profile, ITransientDependency { public BookProfile() { } - public BookProfile(ISettingProvider settingsProvider) + public BookProfile(ISettingProvider settingProvider) { - this.CreateMultLingualMap(settingsProvider, true).TranslationMap + CreateMap() + .MapMultiLingual(this, + settingProvider, true) + .TranslationMap .ForMember(d => d.Id, m => m.MapFrom(s => s.CoreId)); + ; } } } diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj index 1d3d553047..7ec539aadf 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj @@ -1,7 +1,7 @@ - + netcoreapp3.1 Volo.Abp.AutoMapper.Tests @@ -12,6 +12,7 @@ + diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs index 26f5398042..6327f5dc80 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs +++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs @@ -2,7 +2,6 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; using Volo.Abp.ObjectExtending; -using Volo.Abp.Settings; namespace Volo.Abp.AutoMapper { @@ -20,8 +19,8 @@ namespace Volo.Abp.AutoMapper options.Configurators.Add(configurationContext => { - configurationContext.MapperConfiguration.AddProfile( - new BookProfile(configurationContext.ServiceProvider.GetService())); + configurationContext.MapperConfiguration.AddProfile(configurationContext.ServiceProvider + .GetService()); }); }); } diff --git a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj new file mode 100644 index 0000000000..9527afdd02 --- /dev/null +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj @@ -0,0 +1,18 @@ + + + + + + netcoreapp3.1 + + + + + + + + + + + + diff --git a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs new file mode 100644 index 0000000000..c4fef4dc66 --- /dev/null +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs @@ -0,0 +1,25 @@ +using Autofac.Extensions.DependencyInjection; +using Volo.Abp.Autofac; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.ObjectMapping; +using Volo.Abp.Settings; + +namespace Volo.Abp.MultiLingualObject +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(AbpLocalizationModule), + typeof(AbpSettingsModule), + typeof(AbpObjectMappingModule), + typeof(AbpMultiLingualObjectModule), + typeof(AbpTestBaseModule) + )] + public class AbpMultiLingualObjectTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + base.ConfigureServices(context); + } + } +} diff --git a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs new file mode 100644 index 0000000000..d681520d20 --- /dev/null +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization; +using Volo.Abp.MultiLingualObject.TestObjects; +using Volo.Abp.ObjectMapping; +using Volo.Abp.Settings; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.MultiLingualObject +{ + public class MultiLingualObject_Tests : AbpIntegratedTest + { + private readonly IObjectMapper _objectMapper; + private readonly MultiLingualBook _book; + + public MultiLingualObject_Tests() + { + _objectMapper = ServiceProvider.GetRequiredService>(); + + var id = Guid.NewGuid(); + _book = new MultiLingualBook(id, 100) + { + Translations = new List + { + new MultiLingualBookTranslation + { + CoreId = id, + Language = "en", + Name = "C# in Depth" + }, + new MultiLingualBookTranslation + { + CoreId = id, + Language = "zh-Hans", + Name = "深入理解C#" + } + } + }; + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + [Fact] + public void Should_Map_Current_UI_Culture() + { + using (CultureHelper.Use("zh-Hans")) + { + var bookDto = _objectMapper.Map(_book); + + bookDto.Name.ShouldBe("深入理解C#"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public void Should_Map_Fallback_UI_Culture() + { + using (CultureHelper.Use("en-us")) + { + var bookDto = _objectMapper.Map(_book); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public void Should_Map_Default_Language() + { + using (CultureHelper.Use("tr")) + { + var bookDto = _objectMapper.Map(_book); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + } + + public class MultiLingualBookObjectMapper : IObjectMapper, + ITransientDependency + { + private readonly ISettingProvider _settingProvider; + + public MultiLingualBookObjectMapper(ISettingProvider settingProvider) + { + _settingProvider = settingProvider; + } + + public MultiLingualBookDto Map(MultiLingualBook source) + { + var translation = source.GetMultiLingualTranslation(_settingProvider, true); + + return new MultiLingualBookDto + { + Id = source.Id, + Name = translation.Name, + Price = source.Price + }; + } + + public MultiLingualBookDto Map(MultiLingualBook source, MultiLingualBookDto destination) + { + return default; + } + } +} diff --git a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBook.cs b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBook.cs new file mode 100644 index 0000000000..d12022a44b --- /dev/null +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBook.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Abp.MultiLingualObject.TestObjects +{ + public class MultiLingualBook : IHasMultiLingual + { + public MultiLingualBook(Guid id, decimal price) + { + Id = id; + Price = price; + } + + public Guid Id { get; } + + public decimal Price { get; set; } + + public ICollection Translations { get; set; } + } +} diff --git a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookDto.cs b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookDto.cs new file mode 100644 index 0000000000..8814f9a855 --- /dev/null +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookDto.cs @@ -0,0 +1,13 @@ +using System; + +namespace Volo.Abp.MultiLingualObject.TestObjects +{ + public class MultiLingualBookDto + { + public Guid Id { get; set; } + + public string Name { get; set; } + + public decimal Price { get; set; } + } +} diff --git a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookTranslation.cs b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookTranslation.cs new file mode 100644 index 0000000000..26c3c13d84 --- /dev/null +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookTranslation.cs @@ -0,0 +1,15 @@ +using System; + +namespace Volo.Abp.MultiLingualObject.TestObjects +{ + public class MultiLingualBookTranslation : IMultiLingualTranslation + { + public string Name { get; set; } + + public string Language { get; set; } + + public MultiLingualBook Core { get; set; } + + public Guid CoreId { get; set; } + } +} diff --git a/nupkg/common.ps1 b/nupkg/common.ps1 index 7d571f6709..79d673b869 100644 --- a/nupkg/common.ps1 +++ b/nupkg/common.ps1 @@ -124,7 +124,8 @@ $projects = ( "framework/src/Volo.Abp.Validation.Abstractions", "framework/src/Volo.Abp.Validation", "framework/src/Volo.Abp.VirtualFileSystem", - "framework/src/Volo.Abp.Kafka" + "framework/src/Volo.Abp.Kafka", + "framework/src/Volo.Abp.MultiLingualObject" # modules/account "modules/account/src/Volo.Abp.Account.Application.Contracts",