From 8623d8202b3c47e5788cac0e509ab430a42c73d6 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 1 Sep 2020 17:56:56 +0800 Subject: [PATCH 01/11] initialize multi-lingual-entities --- framework/Volo.Abp.sln | 7 ++ .../AbpAutoMapperMultiLingualDtoExtensions.cs | 99 +++++++++++++++++++ .../Volo.Abp.AutoMapper.csproj | 1 + .../Volo.Abp.Ddd.Domain.csproj | 1 + .../AbpEntityTypeBuilderExtensions.cs | 21 ++++ .../FodyWeavers.xml | 3 + .../FodyWeavers.xsd | 30 ++++++ .../Volo.Abp.MultiLingualEntities.csproj | 11 +++ .../IEntityTranslation.cs | 19 ++++ .../IMultiLingualEntity.cs | 10 ++ 10 files changed, 202 insertions(+) create mode 100644 framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs create mode 100644 framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xml create mode 100644 framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xsd create mode 100644 framework/src/Volo.Abp.MultiLingualEntities/Volo.Abp.MultiLingualEntities.csproj create mode 100644 framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IEntityTranslation.cs create mode 100644 framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IMultiLingualEntity.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index aa0a3f1222..ad70bec8dd 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -331,6 +331,8 @@ 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.MultiLingualEntities", "src\Volo.Abp.MultiLingualEntities\Volo.Abp.MultiLingualEntities.csproj", "{83E4016D-5941-4735-AF88-422144619588}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -985,6 +987,10 @@ 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 + {83E4016D-5941-4735-AF88-422144619588}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83E4016D-5941-4735-AF88-422144619588}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83E4016D-5941-4735-AF88-422144619588}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83E4016D-5941-4735-AF88-422144619588}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1152,6 +1158,7 @@ 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} + {83E4016D-5941-4735-AF88-422144619588} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} 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 new file mode 100644 index 0000000000..345f28d542 --- /dev/null +++ b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Volo.Abp.Localization; +using Volo.Abp.MultiLingualEntities; +using Volo.Abp.Settings; +using Volo.Abp.Threading; + +namespace AutoMapper +{ + public static class AbpAutoMapperMultiLingualDtoExtensions + { + public static CreateMultiLingualMapResult CreateMultLingualMap< + TMultiLingualEntity, + TTranslation, TDestination>( + this Profile profile, + ISettingProvider serviceProvider, + bool fallbackToParentCultures = false) + where TMultiLingualEntity : class, IMultiLingualEntity + where TTranslation : class, IEntityTranslation + { + 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)); + + 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); + } + }) + }; + } + + 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 IMappingExpression TranslationMap { 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 bd5cffe848..a026d68c48 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -18,6 +18,7 @@ + diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj index ab162e60c7..ad9df0c7f2 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj @@ -24,6 +24,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 44962eca4c..179e575358 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.MultiLingualEntities; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectExtending; @@ -28,6 +29,7 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling b.TryConfigureLastModificationTime(); b.TryConfigureModificationAudited(); b.TryConfigureMultiTenant(); + b.TryConfigureEntityTranslation(); } public static void ConfigureConcurrencyStamp(this EntityTypeBuilder b) @@ -302,6 +304,25 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling b.As().TryConfigureConcurrencyStamp(); } + public static void ConfigureMultiLingual(this EntityTypeBuilder b) + where T : class, IMultiLingualEntity + where TTranslation : class, IEntityTranslation + { + b.As().TryConfigureEntityTranslation(); + } + + public static void TryConfigureEntityTranslation(this EntityTypeBuilder b) + { + if (b.Metadata.ClrType.IsAssignableTo()) + { + b.HasIndex(nameof(IEntityTranslation.Language)) + .IsUnique(); + b.Property(nameof(IEntityTranslation.Language)) + .IsRequired() + .HasColumnName(nameof(IEntityTranslation.Language)); + } + } + //TODO: Add other interfaces (IAuditedObject...) } } diff --git a/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xml b/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xml new file mode 100644 index 0000000000..be0de3a908 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xsd b/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualEntities/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.MultiLingualEntities/Volo.Abp.MultiLingualEntities.csproj b/framework/src/Volo.Abp.MultiLingualEntities/Volo.Abp.MultiLingualEntities.csproj new file mode 100644 index 0000000000..7b81cbbe05 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualEntities/Volo.Abp.MultiLingualEntities.csproj @@ -0,0 +1,11 @@ + + + + + + + netstandard2.0 + + + + diff --git a/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IEntityTranslation.cs b/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IEntityTranslation.cs new file mode 100644 index 0000000000..1a770bff92 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IEntityTranslation.cs @@ -0,0 +1,19 @@ +namespace Volo.Abp.MultiLingualEntities +{ + public interface IEntityTranslation + { + string Language { get; set; } + } + + public interface IEntityTranslation : IEntityTranslation + { + TEntity Core { get; set; } + + TPrimaryKeyOfMultiLingualEntity CoreId { get; set; } + } + + public interface IEntityTranslation: IEntityTranslation + { + + } +} diff --git a/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IMultiLingualEntity.cs b/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IMultiLingualEntity.cs new file mode 100644 index 0000000000..9e3dae8cc2 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IMultiLingualEntity.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Volo.Abp.MultiLingualEntities +{ + public interface IMultiLingualEntity + where TTranslation : class, IEntityTranslation + { + ICollection Translations { get; set; } + } +} From 294467264f43b348a848d34da5763ba110ffa4a0 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 2 Sep 2020 16:33:10 +0800 Subject: [PATCH 02/11] Remove multLingualEntities project --- framework/Volo.Abp.sln | 7 ----- .../AbpAutoMapperMultiLingualDtoExtensions.cs | 2 +- .../Volo.Abp.AutoMapper.csproj | 2 +- .../Domain/Entities}/IEntityTranslation.cs | 4 ++- .../Domain/Entities}/IMultiLingualEntity.cs | 2 +- .../AbpEntityTypeBuilderExtensions.cs | 1 - .../FodyWeavers.xml | 3 -- .../FodyWeavers.xsd | 30 ------------------- .../Volo.Abp.MultiLingualEntities.csproj | 11 ------- 9 files changed, 6 insertions(+), 56 deletions(-) rename framework/src/{Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities => Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities}/IEntityTranslation.cs (74%) rename framework/src/{Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities => Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities}/IMultiLingualEntity.cs (84%) delete mode 100644 framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xml delete mode 100644 framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xsd delete mode 100644 framework/src/Volo.Abp.MultiLingualEntities/Volo.Abp.MultiLingualEntities.csproj diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index ad70bec8dd..aa0a3f1222 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -331,8 +331,6 @@ 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.MultiLingualEntities", "src\Volo.Abp.MultiLingualEntities\Volo.Abp.MultiLingualEntities.csproj", "{83E4016D-5941-4735-AF88-422144619588}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -987,10 +985,6 @@ 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 - {83E4016D-5941-4735-AF88-422144619588}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83E4016D-5941-4735-AF88-422144619588}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83E4016D-5941-4735-AF88-422144619588}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83E4016D-5941-4735-AF88-422144619588}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1158,7 +1152,6 @@ 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} - {83E4016D-5941-4735-AF88-422144619588} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} 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 345f28d542..37ed4af95d 100644 --- a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs +++ b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using Volo.Abp.Domain.Entities; using Volo.Abp.Localization; -using Volo.Abp.MultiLingualEntities; using Volo.Abp.Settings; using Volo.Abp.Threading; diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index a026d68c48..6e261e0b2a 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IEntityTranslation.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs similarity index 74% rename from framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IEntityTranslation.cs rename to framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs index 1a770bff92..0684e615ad 100644 --- a/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IEntityTranslation.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs @@ -1,4 +1,4 @@ -namespace Volo.Abp.MultiLingualEntities +namespace Volo.Abp.Domain.Entities { public interface IEntityTranslation { @@ -6,6 +6,7 @@ } public interface IEntityTranslation : IEntityTranslation + where TEntity : IEntity { TEntity Core { get; set; } @@ -13,6 +14,7 @@ } public interface IEntityTranslation: IEntityTranslation + where TEntity : IEntity { } diff --git a/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IMultiLingualEntity.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs similarity index 84% rename from framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IMultiLingualEntity.cs rename to framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs index 9e3dae8cc2..2b25a7a90a 100644 --- a/framework/src/Volo.Abp.MultiLingualEntities/Volo/Abp/MultiLingualEntities/IMultiLingualEntity.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Volo.Abp.MultiLingualEntities +namespace Volo.Abp.Domain.Entities { public interface IMultiLingualEntity where TTranslation : class, IEntityTranslation 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 179e575358..f70e64bb0a 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,7 +7,6 @@ using Volo.Abp.Data; using Volo.Abp.Domain.Entities; using Volo.Abp.EntityFrameworkCore.ValueComparers; using Volo.Abp.EntityFrameworkCore.ValueConverters; -using Volo.Abp.MultiLingualEntities; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectExtending; diff --git a/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xml b/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xml deleted file mode 100644 index be0de3a908..0000000000 --- a/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xsd b/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xsd deleted file mode 100644 index 3f3946e282..0000000000 --- a/framework/src/Volo.Abp.MultiLingualEntities/FodyWeavers.xsd +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - '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.MultiLingualEntities/Volo.Abp.MultiLingualEntities.csproj b/framework/src/Volo.Abp.MultiLingualEntities/Volo.Abp.MultiLingualEntities.csproj deleted file mode 100644 index 7b81cbbe05..0000000000 --- a/framework/src/Volo.Abp.MultiLingualEntities/Volo.Abp.MultiLingualEntities.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - netstandard2.0 - - - - From 6319b22753bc0930ce36d8468599fbedefef8650 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 2 Sep 2020 17:14:24 +0800 Subject: [PATCH 03/11] Add unit tests --- ...toMapperMultiLingualDtoExtensions_Tests.cs | 112 ++++++++++++++++++ .../Abp/AutoMapper/AutoMapperTestModule.cs | 15 ++- 2 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs new file mode 100644 index 0000000000..22675b61ca --- /dev/null +++ b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.AutoMapper; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Settings; +using Volo.Abp.Testing; +using Xunit; + +namespace AutoMapper +{ + public class AbpAutoMapperMultiLingualDtoExtensions_Tests : AbpIntegratedTest + { + private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper; + private readonly Book _book; + + public AbpAutoMapperMultiLingualDtoExtensions_Tests() + { + _objectMapper = ServiceProvider.GetRequiredService(); + + var id = Guid.NewGuid(); + _book = new Book(id, 100) + { + Translations = new List + { + new BookTranslation + { + CoreId = id, + Language = "en", + Name = "C# in Depth" + }, + new BookTranslation + { + CoreId = id, + Language = "zh-Hans", + Name = "深入理解C#" + } + } + }; + } + + [Fact] + public void Should_Map_CurrentUICulture() + { + 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); + } + + [Fact] + public void Should_Map_FeedbackUICulture() + { + CultureInfo.CurrentCulture = new CultureInfo("en-us"); + var bookDto = _objectMapper.Map(_book); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(100); + bookDto.Id.ShouldBe(_book.Id); + } + } + + public class Book : Entity, IMultiLingualEntity + { + public Book(Guid id, decimal price) + { + 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; } + } + + public class BookDto + { + public string Name { get; set; } + + public Guid Id { get; set; } + + public decimal Price { get; set; } + } + + public class BookProfile : Profile + { + public BookProfile() + { + } + + public BookProfile(ISettingProvider settingsProvider) + { + this.CreateMultLingualMap(settingsProvider, true).TranslationMap + .ForMember(d => d.Id, m => m.MapFrom(s => s.CoreId)); + } + } +} 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 44331522a7..26f5398042 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 @@ -1,12 +1,15 @@ -using Volo.Abp.Modularity; +using AutoMapper; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; using Volo.Abp.ObjectExtending; +using Volo.Abp.Settings; namespace Volo.Abp.AutoMapper { [DependsOn( typeof(AbpAutoMapperModule), typeof(AbpObjectExtendingTestModule) - )] + )] public class AutoMapperTestModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) @@ -14,7 +17,13 @@ namespace Volo.Abp.AutoMapper Configure(options => { options.AddMaps(); + + options.Configurators.Add(configurationContext => + { + configurationContext.MapperConfiguration.AddProfile( + new BookProfile(configurationContext.ServiceProvider.GetService())); + }); }); } } -} \ No newline at end of file +} From 41dba351f313cdff635a0a8600b8a8872ce26732 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 2 Sep 2020 17:46:16 +0800 Subject: [PATCH 04/11] Update Volo.Abp.Ddd.Domain.csproj --- framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj index ad9df0c7f2..ab162e60c7 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj @@ -24,7 +24,6 @@ - From e21cf5cd864c97b35c3bfde7627fa915808d9774 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 4 Sep 2020 00:04:49 +0800 Subject: [PATCH 05/11] 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", From 83d5b754bbb302297d55cebb68be4da78bf01ffd Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 4 Sep 2020 18:56:13 +0800 Subject: [PATCH 06/11] Create MultiLingualObjectManager --- .../AbpAutoMapperMultiLingualDtoExtensions.cs | 41 ------ .../Volo.Abp.AutoMapper.csproj | 2 - .../Abp/AutoMapper/AbpAutoMapperModule.cs | 4 +- .../IMultiLingualObjectManager.cs | 12 ++ ...nsions.cs => MultiLingualObjectManager.cs} | 41 +++--- ...toMapperMultiLingualDtoExtensions_Tests.cs | 107 -------------- .../AbpAutoMapperMultiLingualDto_Tests.cs | 132 ++++++++++++++++++ .../Abp/AutoMapper/AutoMapperTestModule.cs | 14 +- .../MultiLingualObject_Tests.cs | 91 +++++++----- 9 files changed, 227 insertions(+), 217 deletions(-) delete mode 100644 framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs create mode 100644 framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs rename framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/{MultiLingualObjectExtensions.cs => MultiLingualObjectManager.cs} (53%) delete mode 100644 framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs create mode 100644 framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs diff --git a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs deleted file mode 100644 index 273ad35645..0000000000 --- a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Volo.Abp.MultiLingualObject; -using Volo.Abp.Settings; - -namespace AutoMapper -{ - public static class AbpAutoMapperMultiLingualDtoExtensions - { - public static CreateMultiLingualMapResult MapMultiLingual( - this IMappingExpression mappingExpression, - Profile profile, - ISettingProvider provider, - bool fallbackToParentCultures = false) - where TDestination : class - where TSource : IHasMultiLingual - where TTranslation : class, IMultiLingualTranslation - { - return new CreateMultiLingualMapResult - { - TranslationMap = profile.CreateMap(), - - EntityMap = mappingExpression.BeforeMap((source, destination, context) => - { - var translation = source.GetMultiLingualTranslation(provider, fallbackToParentCultures); - - if (translation != null) - { - context.Mapper.Map(translation, destination); - } - }) - }; - } - } - - public class CreateMultiLingualMapResult - { - public IMappingExpression TranslationMap { 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 124c47e055..bd5cffe848 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -16,10 +16,8 @@ - - 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 15df0d6986..214872e371 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -4,7 +4,6 @@ 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; @@ -13,8 +12,7 @@ namespace Volo.Abp.AutoMapper [DependsOn( typeof(AbpObjectMappingModule), typeof(AbpObjectExtendingModule), - typeof(AbpAuditingModule), - typeof(AbpMultiLingualObjectModule) + typeof(AbpAuditingModule) )] public class AbpAutoMapperModule : AbpModule { diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs new file mode 100644 index 0000000000..5180588411 --- /dev/null +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.MultiLingualObject +{ + public interface IMultiLingualObjectManager + { + Task GetTranslationAsync(TMultiLingual multiLingual, + bool fallbackToParentCultures = true, string culture = null) + where TMultiLingual : IHasMultiLingual + where TTranslation : class, IMultiLingualTranslation; + } +} diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs similarity index 53% rename from framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs rename to framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs index 6212927b02..68fc083e21 100644 --- a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs @@ -2,27 +2,39 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; using Volo.Abp.Settings; -using Volo.Abp.Threading; namespace Volo.Abp.MultiLingualObject { - public static class MultiLingualObjectExtensions + public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientDependency { - public static TTranslation GetMultiLingualTranslation( - this IHasMultiLingual hasMultiLingual, - ISettingProvider settingProvider, - bool fallbackToParentCultures = false) + protected ISettingProvider SettingProvider { get; } + + protected const int MaxCultureFallbackDepth = 5; + + public MultiLingualObjectManager(ISettingProvider settingProvider) + { + SettingProvider = settingProvider; + } + + public virtual async Task GetTranslationAsync(TMultiLingual multiLingual, + bool fallbackToParentCultures = true, + string culture = null) + where TMultiLingual : IHasMultiLingual where TTranslation : class, IMultiLingualTranslation { - if (hasMultiLingual.Translations == null || !hasMultiLingual.Translations.Any()) + culture ??= CultureInfo.CurrentUICulture.Name; + + if (multiLingual.Translations == null || !multiLingual.Translations.Any()) { return null; } var translation = - hasMultiLingual.Translations.FirstOrDefault(pt => pt.Language == CultureInfo.CurrentUICulture.Name); + multiLingual.Translations.FirstOrDefault(pt => pt.Language == culture); if (translation != null) { return translation; @@ -32,29 +44,26 @@ namespace Volo.Abp.MultiLingualObject { translation = GeTranslationBasedOnCulturalRecursive( - CultureInfo.CurrentUICulture.Parent, hasMultiLingual.Translations, 0); + CultureInfo.CurrentUICulture.Parent, multiLingual.Translations, 0); if (translation != null) { return translation; } } - var defaultLanguage = AsyncHelper.RunSync(() => - settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage)); + var defaultLanguage = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); - translation = hasMultiLingual.Translations.FirstOrDefault(pt => pt.Language == defaultLanguage); + translation = multiLingual.Translations.FirstOrDefault(pt => pt.Language == defaultLanguage); if (translation != null) { return translation; } - translation = hasMultiLingual.Translations.FirstOrDefault(); + translation = multiLingual.Translations.FirstOrDefault(); return translation; } - private const int MaxCultureFallbackDepth = 5; - - private static TTranslation GeTranslationBasedOnCulturalRecursive( + protected virtual TTranslation GeTranslationBasedOnCulturalRecursive( CultureInfo culture, ICollection translations, int currentDepth) where TTranslation : class, IMultiLingualTranslation { diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs deleted file mode 100644 index e89bf93375..0000000000 --- a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; -using Shouldly; -using Volo.Abp; -using Volo.Abp.AutoMapper; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Localization; -using Volo.Abp.MultiLingualObject.TestObjects; -using Volo.Abp.Settings; -using Volo.Abp.Testing; -using Xunit; - -namespace AutoMapper -{ - public class AbpAutoMapperMultiLingualDtoExtensions_Tests : AbpIntegratedTest - { - private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper; - private readonly MultiLingualBook _book; - - public AbpAutoMapperMultiLingualDtoExtensions_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 BookProfile : Profile, ITransientDependency - { - public BookProfile() - { - } - - public BookProfile(ISettingProvider settingProvider) - { - 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/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs new file mode 100644 index 0000000000..ea59a35ce5 --- /dev/null +++ b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp; +using Volo.Abp.AutoMapper; +using Volo.Abp.Localization; +using Volo.Abp.MultiLingualObject; +using Volo.Abp.MultiLingualObject.TestObjects; +using Volo.Abp.Testing; +using Xunit; + +namespace AutoMapper +{ + public class AbpAutoMapperMultiLingualDto_Tests : AbpIntegratedTest + { + private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper; + private readonly IMultiLingualObjectManager _multiLingualObjectManager; + private readonly MultiLingualBook _book; + + public AbpAutoMapperMultiLingualDto_Tests() + { + _multiLingualObjectManager = ServiceProvider.GetRequiredService(); + _objectMapper = ServiceProvider.GetRequiredService(); + + var id = Guid.NewGuid(); + _book = new MultiLingualBook(id, 100) + { + Translations = new List() + }; + + var en = new MultiLingualBookTranslation + { + CoreId = id, + Language = "en", + Name = "C# in Depth", + Core = _book + }; + var zh = new MultiLingualBookTranslation + { + CoreId = id, + Language = "zh-Hans", + Name = "深入理解C#", + Core = _book + }; + + _book.Translations.Add(en); + _book.Translations.Add(zh); + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + [Fact] + public async Task Should_Map_Current_UI_Culture() + { + using (CultureHelper.Use("zh-Hans")) + { + var translation = + await _multiLingualObjectManager + .GetTranslationAsync(_book); + + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("深入理解C#"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public async Task Should_Map_Fallback_UI_Culture() + { + using (CultureHelper.Use("en-us")) + { + var translation = + await _multiLingualObjectManager + .GetTranslationAsync(_book); + + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public async Task Should_Map_Default_Language() + { + using (CultureHelper.Use("tr")) + { + var translation = + await _multiLingualObjectManager + .GetTranslationAsync(_book); + + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public async Task Should_Map_Specified_Language() + { + using (CultureHelper.Use("zh-Hans")) + { + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book, culture:"en"); + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + } + + public class BookProfile : Profile + { + public BookProfile() + { + CreateMap() + .ForMember(d => d.Price, m => m.MapFrom(s => s.Core.Price)) + .ForMember(d => d.Id, m => m.MapFrom(s => s.CoreId)); + } + } +} 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 6327f5dc80..6e9fb10bf2 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 @@ -1,13 +1,13 @@ -using AutoMapper; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; +using Volo.Abp.Modularity; +using Volo.Abp.MultiLingualObject; using Volo.Abp.ObjectExtending; namespace Volo.Abp.AutoMapper { [DependsOn( typeof(AbpAutoMapperModule), - typeof(AbpObjectExtendingTestModule) + typeof(AbpObjectExtendingTestModule), + typeof(AbpMultiLingualObjectModule) )] public class AutoMapperTestModule : AbpModule { @@ -16,12 +16,6 @@ namespace Volo.Abp.AutoMapper Configure(options => { options.AddMaps(); - - options.Configurators.Add(configurationContext => - { - configurationContext.MapperConfiguration.AddProfile(configurationContext.ServiceProvider - .GetService()); - }); }); } } 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 index d681520d20..f52eb17c19 100644 --- 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 @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; 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; @@ -14,32 +14,38 @@ namespace Volo.Abp.MultiLingualObject { public class MultiLingualObject_Tests : AbpIntegratedTest { - private readonly IObjectMapper _objectMapper; + private readonly IObjectMapper _objectMapper; + private readonly IMultiLingualObjectManager _multiLingualObjectManager; private readonly MultiLingualBook _book; public MultiLingualObject_Tests() { - _objectMapper = ServiceProvider.GetRequiredService>(); + _objectMapper = ServiceProvider.GetRequiredService(); + _multiLingualObjectManager = 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#" - } - } + Translations = new List() }; + + var en = new MultiLingualBookTranslation + { + CoreId = id, + Language = "en", + Name = "C# in Depth", + Core = _book + }; + var zh = new MultiLingualBookTranslation + { + CoreId = id, + Language = "zh-Hans", + Name = "深入理解C#", + Core = _book + }; + + _book.Translations.Add(en); + _book.Translations.Add(zh); } protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) @@ -48,11 +54,12 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public void Should_Map_Current_UI_Culture() + public async Task Should_Map_Current_UI_Culture() { using (CultureHelper.Use("zh-Hans")) { - var bookDto = _objectMapper.Map(_book); + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); + var bookDto = _objectMapper.Map(translation); bookDto.Name.ShouldBe("深入理解C#"); bookDto.Price.ShouldBe(_book.Price); @@ -61,11 +68,12 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public void Should_Map_Fallback_UI_Culture() + public async Task Should_Map_Fallback_UI_Culture() { using (CultureHelper.Use("en-us")) { - var bookDto = _objectMapper.Map(_book); + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); + var bookDto = _objectMapper.Map(translation); bookDto.Name.ShouldBe("C# in Depth"); bookDto.Price.ShouldBe(_book.Price); @@ -74,11 +82,26 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public void Should_Map_Default_Language() + public async Task Should_Map_Default_Language() { using (CultureHelper.Use("tr")) { - var bookDto = _objectMapper.Map(_book); + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); + var bookDto = _objectMapper.Map(translation); + + bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Price.ShouldBe(_book.Price); + bookDto.Id.ShouldBe(_book.Id); + } + } + + [Fact] + public async Task Should_Map_Specified_Language() + { + using (CultureHelper.Use("zh-Hans")) + { + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book, culture:"en"); + var bookDto = _objectMapper.Map(translation); bookDto.Name.ShouldBe("C# in Depth"); bookDto.Price.ShouldBe(_book.Price); @@ -87,29 +110,21 @@ namespace Volo.Abp.MultiLingualObject } } - public class MultiLingualBookObjectMapper : IObjectMapper, + public class MultiLingualBookObjectMapper : IObjectMapper, ITransientDependency { - private readonly ISettingProvider _settingProvider; - public MultiLingualBookObjectMapper(ISettingProvider settingProvider) + public MultiLingualBookDto Map(MultiLingualBookTranslation source) { - _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 + Price = source.Core.Price, + Id = source.CoreId, + Name = source.Name }; } - public MultiLingualBookDto Map(MultiLingualBook source, MultiLingualBookDto destination) + public MultiLingualBookDto Map(MultiLingualBookTranslation source, MultiLingualBookDto destination) { return default; } From d6bdfed4a97a966df1fd3b304a31ed228fa937d4 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 28 Oct 2020 16:47:14 +0800 Subject: [PATCH 07/11] Upgrade to NET 5 --- .../Volo.Abp.MultiLingualObject.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 9527afdd02..7ccdd79fbb 100644 --- a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj @@ -3,7 +3,7 @@ - netcoreapp3.1 + net5.0 From 37d41c9aaf9b5492d9ecb24e3ea80daeb2b98b10 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 30 Oct 2020 15:59:28 +0800 Subject: [PATCH 08/11] Remove TryConfigureEntityTranslation --- .../Volo.Abp.EntityFrameworkCore.csproj | 1 - .../AbpEntityTypeBuilderExtensions.cs | 21 ------------------- 2 files changed, 22 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj index dc6e1f0534..a123570984 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj @@ -17,7 +17,6 @@ - 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 c930e41a6c..44962eca4c 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,7 +7,6 @@ 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; @@ -29,7 +28,6 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling b.TryConfigureLastModificationTime(); b.TryConfigureModificationAudited(); b.TryConfigureMultiTenant(); - b.TryConfigureEntityTranslation(); } public static void ConfigureConcurrencyStamp(this EntityTypeBuilder b) @@ -304,25 +302,6 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling b.As().TryConfigureConcurrencyStamp(); } - public static void ConfigureMultiLingual(this EntityTypeBuilder b) - where T : class, IHasMultiLingual - where TTranslation : class, IMultiLingualTranslation - { - b.As().TryConfigureEntityTranslation(); - } - - public static void TryConfigureEntityTranslation(this EntityTypeBuilder b) - { - if (b.Metadata.ClrType.IsAssignableTo()) - { - b.HasIndex(nameof(IMultiLingualTranslation.Language)) - .IsUnique(); - b.Property(nameof(IMultiLingualTranslation.Language)) - .IsRequired() - .HasColumnName(nameof(IMultiLingualTranslation.Language)); - } - } - //TODO: Add other interfaces (IAuditedObject...) } } From 8ad4c43c9fba7e0377fea8a3b2ae68b4a663852f Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 20 Jan 2021 16:13:12 +0800 Subject: [PATCH 09/11] Resolve the conflict --- framework/Volo.Abp.sln | 6 ++++++ .../Volo.Abp.AutoMapper.Tests.csproj | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index d76d818644..6e12f98279 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -1073,6 +1073,10 @@ Global {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.Debug|Any CPU.Build.0 = Debug|Any CPU {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.Release|Any CPU.ActiveCfg = Release|Any CPU {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.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 + {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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1254,6 +1258,8 @@ Global {DD9519E0-5A68-48DC-A051-7BF2AC922F3E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA} {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1} = {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/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj index 1f11e8fc34..37ffca1657 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 @@ -11,8 +11,9 @@ - + + From 63b34abb7bab420ec8d6398004e1072eecca1f05 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 27 Jan 2021 18:01:47 +0800 Subject: [PATCH 10/11] Improved --- .../AbpAutoMapperMultiLingualDtoExtensions.cs | 54 +++++++++++++ .../Volo.Abp.AutoMapper.csproj | 1 + .../Abp/AutoMapper/AbpAutoMapperModule.cs | 4 +- .../Volo.Abp.Ddd.Domain.csproj | 1 + .../Volo/Abp/Domain/AbpDddDomainModule.cs | 2 + .../IMultiLingualObjectManager.cs | 13 +++- .../IMultiLingualTranslation.cs | 8 -- .../MultiLingualObjectManager.cs | 18 ++++- .../AbpAutoMapperMultiLingualDto_Tests.cs | 50 ++++-------- .../AbpMultiLingualObjectTestModule.cs | 4 - .../MultiLingualObjectManager_Tests.cs | 76 +++++++++++++++++++ .../MultiLingualObject_Tests.cs | 54 ++++++------- .../MultiLingualBookTranslation.cs | 6 +- 13 files changed, 207 insertions(+), 84 deletions(-) create mode 100644 framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs create mode 100644 framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObjectManager_Tests.cs diff --git a/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs new file mode 100644 index 0000000000..83cb2b35b9 --- /dev/null +++ b/framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs @@ -0,0 +1,54 @@ +using Volo.Abp.MultiLingualObject; +using Volo.Abp.Threading; + +namespace AutoMapper +{ + public static class AbpAutoMapperMultiLingualDtoExtensions + { + public static CreateMultiLingualMapResult CreateMultiLingualMap(this Profile profile) + where TTranslation : class, IMultiLingualTranslation + where TSource : IHasMultiLingual + { + + return new( + profile.CreateMap().BeforeMap>(), + profile.CreateMap()); + } + } + + public class AbpMultiLingualMapperAction : IMappingAction + where TTranslation : class, IMultiLingualTranslation + where TSource : IHasMultiLingual + { + private readonly IMultiLingualObjectManager _multiLingualObjectManager; + + public AbpMultiLingualMapperAction(IMultiLingualObjectManager multiLingualObjectManager) + { + _multiLingualObjectManager = multiLingualObjectManager; + } + + public void Process(TSource source, TDestination destination, ResolutionContext context) + { + var translation = AsyncHelper.RunSync(() => _multiLingualObjectManager.GetTranslationAsync(source)); + if (translation != null) + { + context.Mapper.Map(translation, destination); + } + } + } + + public class CreateMultiLingualMapResult + { + public IMappingExpression EntityMap { get; } + + public IMappingExpression TranslateMap { get; } + + public CreateMultiLingualMapResult( + IMappingExpression entityMap, + IMappingExpression translateMap) + { + EntityMap = entityMap; + TranslateMap = translateMap; + } + } +} diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index 9f028d31ee..4a5f44f937 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 25707e3899..48a88867a8 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -25,8 +25,10 @@ namespace Volo.Abp.AutoMapper { context.Services.AddAutoMapperObjectMapper(); - context.Services.AddSingleton(provider => CreateMappings(provider)); + context.Services.AddSingleton(CreateMappings); context.Services.AddSingleton(provider => provider.GetRequiredService()); + + context.Services.AddTransient(typeof(AbpMultiLingualMapperAction<,,>)); } private MapperAccessor CreateMappings(IServiceProvider serviceProvider) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj index 87879334af..e676f24313 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj @@ -20,6 +20,7 @@ + diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs index 523a6ee4f2..0ebbe859bd 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs @@ -6,6 +6,7 @@ using Volo.Abp.EventBus; using Volo.Abp.ExceptionHandling; using Volo.Abp.Guids; using Volo.Abp.Modularity; +using Volo.Abp.MultiLingualObject; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectMapping; using Volo.Abp.Specifications; @@ -25,6 +26,7 @@ namespace Volo.Abp.Domain typeof(AbpTimingModule), typeof(AbpUnitOfWorkModule), typeof(AbpObjectMappingModule), + typeof(AbpMultiLingualObjectModule), typeof(AbpExceptionHandlingModule), typeof(AbpSpecificationsModule) )] diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs index 5180588411..e6ddc840e5 100644 --- a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs @@ -4,8 +4,17 @@ namespace Volo.Abp.MultiLingualObject { public interface IMultiLingualObjectManager { - Task GetTranslationAsync(TMultiLingual multiLingual, - bool fallbackToParentCultures = true, string culture = null) + TTranslation GetTranslation( + TMultiLingual multiLingual, + bool fallbackToParentCultures = true, + string culture = null) + where TMultiLingual : IHasMultiLingual + where TTranslation : class, IMultiLingualTranslation; + + Task GetTranslationAsync( + TMultiLingual multiLingual, + bool fallbackToParentCultures = true, + string culture = null) where TMultiLingual : IHasMultiLingual where TTranslation : class, IMultiLingualTranslation; } diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs index 4490f569fe..3676e08b44 100644 --- a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs @@ -4,12 +4,4 @@ { 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/MultiLingualObjectManager.cs b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs index 68fc083e21..dc6a82a28d 100644 --- a/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; using Volo.Abp.Settings; +using Volo.Abp.Threading; namespace Volo.Abp.MultiLingualObject { @@ -20,7 +21,19 @@ namespace Volo.Abp.MultiLingualObject SettingProvider = settingProvider; } - public virtual async Task GetTranslationAsync(TMultiLingual multiLingual, + public TTranslation GetTranslation( + TMultiLingual multiLingual, + bool fallbackToParentCultures = true, + string culture = null) + where TMultiLingual : IHasMultiLingual + where TTranslation : class, IMultiLingualTranslation + { + return AsyncHelper.RunSync(() => + GetTranslationAsync(multiLingual, fallbackToParentCultures, culture)); + } + + public virtual async Task GetTranslationAsync( + TMultiLingual multiLingual, bool fallbackToParentCultures = true, string culture = null) where TMultiLingual : IHasMultiLingual @@ -33,8 +46,7 @@ namespace Volo.Abp.MultiLingualObject return null; } - var translation = - multiLingual.Translations.FirstOrDefault(pt => pt.Language == culture); + var translation = multiLingual.Translations.FirstOrDefault(pt => pt.Language == culture); if (translation != null) { return translation; diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs index ea59a35ce5..0efb72625b 100644 --- a/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs +++ b/framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp; using Volo.Abp.AutoMapper; using Volo.Abp.Localization; -using Volo.Abp.MultiLingualObject; using Volo.Abp.MultiLingualObject.TestObjects; using Volo.Abp.Testing; using Xunit; @@ -16,12 +14,10 @@ namespace AutoMapper public class AbpAutoMapperMultiLingualDto_Tests : AbpIntegratedTest { private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper; - private readonly IMultiLingualObjectManager _multiLingualObjectManager; private readonly MultiLingualBook _book; public AbpAutoMapperMultiLingualDto_Tests() { - _multiLingualObjectManager = ServiceProvider.GetRequiredService(); _objectMapper = ServiceProvider.GetRequiredService(); var id = Guid.NewGuid(); @@ -32,17 +28,13 @@ namespace AutoMapper var en = new MultiLingualBookTranslation { - CoreId = id, Language = "en", Name = "C# in Depth", - Core = _book }; var zh = new MultiLingualBookTranslation { - CoreId = id, Language = "zh-Hans", Name = "深入理解C#", - Core = _book }; _book.Translations.Add(en); @@ -55,15 +47,11 @@ namespace AutoMapper } [Fact] - public async Task Should_Map_Current_UI_Culture() + public void Should_Map_Current_UI_Culture() { using (CultureHelper.Use("zh-Hans")) { - var translation = - await _multiLingualObjectManager - .GetTranslationAsync(_book); - - var bookDto = _objectMapper.Map(translation); + var bookDto = _objectMapper.Map(_book); bookDto.Name.ShouldBe("深入理解C#"); bookDto.Price.ShouldBe(_book.Price); @@ -72,15 +60,11 @@ namespace AutoMapper } [Fact] - public async Task Should_Map_Fallback_UI_Culture() + public void Should_Map_Fallback_UI_Culture() { using (CultureHelper.Use("en-us")) { - var translation = - await _multiLingualObjectManager - .GetTranslationAsync(_book); - - var bookDto = _objectMapper.Map(translation); + var bookDto = _objectMapper.Map(_book); bookDto.Name.ShouldBe("C# in Depth"); bookDto.Price.ShouldBe(_book.Price); @@ -89,15 +73,11 @@ namespace AutoMapper } [Fact] - public async Task Should_Map_Default_Language() + public void Should_Map_Default_Language() { using (CultureHelper.Use("tr")) { - var translation = - await _multiLingualObjectManager - .GetTranslationAsync(_book); - - var bookDto = _objectMapper.Map(translation); + var bookDto = _objectMapper.Map(_book); bookDto.Name.ShouldBe("C# in Depth"); bookDto.Price.ShouldBe(_book.Price); @@ -106,14 +86,15 @@ namespace AutoMapper } [Fact] - public async Task Should_Map_Specified_Language() + public void NoTranslations_ShouldStillMapObject() { - using (CultureHelper.Use("zh-Hans")) + _book.Translations.Clear(); + + using (CultureHelper.Use("tr")) { - var translation = await _multiLingualObjectManager.GetTranslationAsync(_book, culture:"en"); - var bookDto = _objectMapper.Map(translation); + var bookDto = _objectMapper.Map(_book); - bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Name.ShouldBeNull(); bookDto.Price.ShouldBe(_book.Price); bookDto.Id.ShouldBe(_book.Id); } @@ -124,9 +105,10 @@ namespace AutoMapper { public BookProfile() { - CreateMap() - .ForMember(d => d.Price, m => m.MapFrom(s => s.Core.Price)) - .ForMember(d => d.Id, m => m.MapFrom(s => s.CoreId)); + var mapResult = this.CreateMultiLingualMap(); + + mapResult.EntityMap.ValidateMemberList(MemberList.None); + mapResult.TranslateMap.ValidateMemberList(MemberList.None); } } } 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 index c4fef4dc66..f8f79a3065 100644 --- a/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs @@ -17,9 +17,5 @@ namespace Volo.Abp.MultiLingualObject )] 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/MultiLingualObjectManager_Tests.cs b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObjectManager_Tests.cs new file mode 100644 index 0000000000..269bf91b54 --- /dev/null +++ b/framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObjectManager_Tests.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Localization; +using Volo.Abp.MultiLingualObject.TestObjects; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.MultiLingualObject +{ + public class MultiLingualObjectManager_Tests : AbpIntegratedTest + { + private readonly IMultiLingualObjectManager _multiLingualObjectManager; + private readonly MultiLingualBook _book; + + public MultiLingualObjectManager_Tests() + { + _multiLingualObjectManager = ServiceProvider.GetRequiredService(); + + var id = Guid.NewGuid(); + _book = new MultiLingualBook(id, 100) + { + Translations = new List() + }; + + var en = new MultiLingualBookTranslation + { + Language = "en", + Name = "C# in Depth", + }; + var zh = new MultiLingualBookTranslation + { + Language = "zh-Hans", + Name = "深入理解C#", + }; + + _book.Translations.Add(en); + _book.Translations.Add(zh); + } + + [Fact] + public void GetTranslation() + { + using (CultureHelper.Use("en-us")) + { + var translation = _multiLingualObjectManager.GetTranslation(_book); + + translation.Name.ShouldBe("C# in Depth"); + } + } + + [Fact] + public async Task GetTranslationAsync() + { + using (CultureHelper.Use("en-us")) + { + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); + + translation.Name.ShouldBe("C# in Depth"); + } + } + + [Fact] + public async Task Should_Get_Specified_Language() + { + using (CultureHelper.Use("zh-Hans")) + { + var translation = await _multiLingualObjectManager.GetTranslationAsync(_book, culture: "en"); + + translation.Name.ShouldBe("C# in Depth"); + } + } + } +} 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 index f52eb17c19..917a11a2a8 100644 --- 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 @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.DependencyInjection; @@ -15,13 +14,11 @@ namespace Volo.Abp.MultiLingualObject public class MultiLingualObject_Tests : AbpIntegratedTest { private readonly IObjectMapper _objectMapper; - private readonly IMultiLingualObjectManager _multiLingualObjectManager; private readonly MultiLingualBook _book; public MultiLingualObject_Tests() { _objectMapper = ServiceProvider.GetRequiredService(); - _multiLingualObjectManager = ServiceProvider.GetRequiredService(); var id = Guid.NewGuid(); _book = new MultiLingualBook(id, 100) @@ -31,17 +28,13 @@ namespace Volo.Abp.MultiLingualObject var en = new MultiLingualBookTranslation { - CoreId = id, Language = "en", Name = "C# in Depth", - Core = _book }; var zh = new MultiLingualBookTranslation { - CoreId = id, Language = "zh-Hans", Name = "深入理解C#", - Core = _book }; _book.Translations.Add(en); @@ -54,12 +47,11 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public async Task Should_Map_Current_UI_Culture() + public void Should_Map_Current_UI_Culture() { using (CultureHelper.Use("zh-Hans")) { - var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); - var bookDto = _objectMapper.Map(translation); + var bookDto = _objectMapper.Map(_book); bookDto.Name.ShouldBe("深入理解C#"); bookDto.Price.ShouldBe(_book.Price); @@ -68,12 +60,11 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public async Task Should_Map_Fallback_UI_Culture() + public void Should_Map_Fallback_UI_Culture() { using (CultureHelper.Use("en-us")) { - var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); - var bookDto = _objectMapper.Map(translation); + var bookDto = _objectMapper.Map(_book); bookDto.Name.ShouldBe("C# in Depth"); bookDto.Price.ShouldBe(_book.Price); @@ -82,12 +73,11 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public async Task Should_Map_Default_Language() + public void Should_Map_Default_Language() { using (CultureHelper.Use("tr")) { - var translation = await _multiLingualObjectManager.GetTranslationAsync(_book); - var bookDto = _objectMapper.Map(translation); + var bookDto = _objectMapper.Map(_book); bookDto.Name.ShouldBe("C# in Depth"); bookDto.Price.ShouldBe(_book.Price); @@ -96,35 +86,45 @@ namespace Volo.Abp.MultiLingualObject } [Fact] - public async Task Should_Map_Specified_Language() + public void NoTranslations_ShouldStillMapObject() { - using (CultureHelper.Use("zh-Hans")) + _book.Translations.Clear(); + + using (CultureHelper.Use("tr")) { - var translation = await _multiLingualObjectManager.GetTranslationAsync(_book, culture:"en"); - var bookDto = _objectMapper.Map(translation); + var bookDto = _objectMapper.Map(_book); - bookDto.Name.ShouldBe("C# in Depth"); + bookDto.Name.ShouldBeNull(); bookDto.Price.ShouldBe(_book.Price); bookDto.Id.ShouldBe(_book.Id); } } } - public class MultiLingualBookObjectMapper : IObjectMapper, + public class MultiLingualBookObjectMapper : IObjectMapper, ITransientDependency { + private readonly IMultiLingualObjectManager _multiLingualObjectManager; - public MultiLingualBookDto Map(MultiLingualBookTranslation source) + public MultiLingualBookObjectMapper(IMultiLingualObjectManager multiLingualObjectManager) { + _multiLingualObjectManager = multiLingualObjectManager; + } + + public MultiLingualBookDto Map(MultiLingualBook source) + { + var translation = + _multiLingualObjectManager.GetTranslation(source); + return new MultiLingualBookDto { - Price = source.Core.Price, - Id = source.CoreId, - Name = source.Name + Price = source.Price, + Id = source.Id, + Name = translation?.Name }; } - public MultiLingualBookDto Map(MultiLingualBookTranslation source, MultiLingualBookDto destination) + public MultiLingualBookDto Map(MultiLingualBook source, MultiLingualBookDto destination) { return default; } 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 index 26c3c13d84..5f35554078 100644 --- 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 @@ -2,14 +2,10 @@ namespace Volo.Abp.MultiLingualObject.TestObjects { - public class MultiLingualBookTranslation : IMultiLingualTranslation + public class MultiLingualBookTranslation : IMultiLingualTranslation { public string Name { get; set; } public string Language { get; set; } - - public MultiLingualBook Core { get; set; } - - public Guid CoreId { get; set; } } } From 106a2df7fc22040d0e3944319623feea1016f4f6 Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 16 Mar 2021 16:25:54 +0800 Subject: [PATCH 11/11] Update Volo.Abp.MultiLingualObject.csproj --- .../Volo.Abp.MultiLingualObject.csproj | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj b/framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj index 8f491565d9..d6df31e1ed 100644 --- a/framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj +++ b/framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj @@ -2,9 +2,15 @@ - + netstandard2.0 + Volo.Abp.MultiLingualObject + Volo.Abp.MultiLingualObject + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false