Browse Source

Redesign multi-lingual

pull/5774/head
liangshiwei 6 years ago
parent
commit
e21cf5cd86
  1. 14
      framework/Volo.Abp.sln
  2. 96
      framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs
  3. 1
      framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj
  4. 4
      framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs
  5. 21
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs
  6. 10
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs
  7. 1
      framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj
  8. 13
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs
  9. 3
      framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xml
  10. 30
      framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xsd
  11. 15
      framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj
  12. 11
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectModule.cs
  13. 10
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IHasMultiLingual.cs
  14. 15
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs
  15. 74
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectExtensions.cs
  16. 99
      framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions_Tests.cs
  17. 3
      framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj
  18. 5
      framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs
  19. 18
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj
  20. 25
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs
  21. 117
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs
  22. 20
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBook.cs
  23. 13
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookDto.cs
  24. 15
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookTranslation.cs
  25. 3
      nupkg/common.ps1

14
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}

96
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<TMultiLingualEntity, TTranslation, TDestination> CreateMultLingualMap<
TMultiLingualEntity,
public static CreateMultiLingualMapResult<TSource, TTranslation, TDestination> MapMultiLingual<TSource,
TTranslation, TDestination>(
this Profile profile,
ISettingProvider serviceProvider,
this IMappingExpression<TSource, TDestination> mappingExpression,
Profile profile,
ISettingProvider provider,
bool fallbackToParentCultures = false)
where TMultiLingualEntity : class, IMultiLingualEntity<TTranslation>
where TTranslation : class, IEntityTranslation
where TDestination : class
where TSource : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation
{
return new CreateMultiLingualMapResult<TMultiLingualEntity, TTranslation, TDestination>
return new CreateMultiLingualMapResult<TSource, TTranslation, TDestination>
{
TranslationMap = profile.CreateMap<TTranslation, TDestination>(),
EntityMap = profile.CreateMap<TMultiLingualEntity, TDestination>().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<TMultiLingualEntity, TTranslation>(
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<TMultiLingualEntity, TTranslation>(
CultureInfo culture, ICollection<TTranslation> 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<TMultiLingualEntity, TTranslation>(culture.Parent,
translations, currentDepth + 1);
}
}
public class CreateMultiLingualMapResult<TMultiLingualEntity, TTranslation, TDestination>
public class CreateMultiLingualMapResult<TMultiLingual, TTranslation, TDestination>
{
public IMappingExpression<TTranslation, TDestination> TranslationMap { get; set; }
public IMappingExpression<TMultiLingualEntity, TDestination> EntityMap { get; set; }
public IMappingExpression<TMultiLingual, TDestination> EntityMap { get; set; }
}
}

1
framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj

@ -16,6 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectExtending\Volo.Abp.ObjectExtending.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />

4
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
{

21
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntityTranslation.cs

@ -1,21 +0,0 @@
namespace Volo.Abp.Domain.Entities
{
public interface IEntityTranslation
{
string Language { get; set; }
}
public interface IEntityTranslation<TEntity, TPrimaryKeyOfMultiLingualEntity> : IEntityTranslation
where TEntity : IEntity<TPrimaryKeyOfMultiLingualEntity>
{
TEntity Core { get; set; }
TPrimaryKeyOfMultiLingualEntity CoreId { get; set; }
}
public interface IEntityTranslation<TEntity>: IEntityTranslation<TEntity, int>
where TEntity : IEntity<int>
{
}
}

10
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IMultiLingualEntity.cs

@ -1,10 +0,0 @@
using System.Collections.Generic;
namespace Volo.Abp.Domain.Entities
{
public interface IMultiLingualEntity<TTranslation>
where TTranslation : class, IEntityTranslation
{
ICollection<TTranslation> Translations { get; set; }
}
}

1
framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj

@ -17,6 +17,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj" />
</ItemGroup>
<ItemGroup>

13
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<T, TTranslation>(this EntityTypeBuilder<T> b)
where T : class, IMultiLingualEntity<TTranslation>
where TTranslation : class, IEntityTranslation
where T : class, IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation
{
b.As<EntityTypeBuilder>().TryConfigureEntityTranslation();
}
public static void TryConfigureEntityTranslation(this EntityTypeBuilder b)
{
if (b.Metadata.ClrType.IsAssignableTo<IEntityTranslation>())
if (b.Metadata.ClrType.IsAssignableTo<IMultiLingualTranslation>())
{
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));
}
}

3
framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

15
framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup>
</Project>

11
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
{
}
}

10
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<TTranslation>
where TTranslation : class, IMultiLingualTranslation
{
ICollection<TTranslation> Translations { get; set; }
}
}

15
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<T, TPrimaryKeyOfMultiLingualObject> : IMultiLingualTranslation
where T : class
{
T Core { get; set; }
TPrimaryKeyOfMultiLingualObject CoreId { get; set; }
}
}

74
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<TTranslation>(
this IHasMultiLingual<TTranslation> 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<TTranslation>(
CultureInfo culture, ICollection<TTranslation> 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);
}
}
}

99
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<AutoMapperTestModule>
{
private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper;
private readonly Book _book;
private readonly MultiLingualBook _book;
public AbpAutoMapperMultiLingualDtoExtensions_Tests()
{
_objectMapper = ServiceProvider.GetRequiredService<Volo.Abp.ObjectMapping.IObjectMapper>();
var id = Guid.NewGuid();
_book = new Book(id, 100)
_book = new MultiLingualBook(id, 100)
{
Translations = new List<BookTranslation>
Translations = new List<MultiLingualBookTranslation>
{
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>(_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, BookDto>(_book);
using (CultureHelper.Use("zh-Hans"))
{
var bookDto = _objectMapper.Map<MultiLingualBook, MultiLingualBookDto>(_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<Guid>, IMultiLingualEntity<BookTranslation>
{
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<BookTranslation> Translations { get; set; }
}
public class BookTranslation : IEntityTranslation<Book, Guid>
{
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<MultiLingualBook, MultiLingualBookDto>(_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<MultiLingualBook, MultiLingualBookDto>(_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<Book, BookTranslation, BookDto>(settingsProvider, true).TranslationMap
CreateMap<MultiLingualBook, MultiLingualBookDto>()
.MapMultiLingual<MultiLingualBook, MultiLingualBookTranslation, MultiLingualBookDto>(this,
settingProvider, true)
.TranslationMap
.ForMember(d => d.Id, m => m.MapFrom(s => s.CoreId));
;
}
}
}

3
framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>Volo.Abp.AutoMapper.Tests</AssemblyName>
@ -12,6 +12,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectExtending.Tests\Volo.Abp.ObjectExtending.Tests.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiLingualObject.Tests\Volo.Abp.MultiLingualObject.Tests.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
</ItemGroup>

5
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<ISettingProvider>()));
configurationContext.MapperConfiguration.AddProfile(configurationContext.ServiceProvider
.GetService<BookProfile>());
});
});
}

18
framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
</ItemGroup>
</Project>

25
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);
}
}
}

117
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<AbpMultiLingualObjectTestModule>
{
private readonly IObjectMapper<MultiLingualBook, MultiLingualBookDto> _objectMapper;
private readonly MultiLingualBook _book;
public MultiLingualObject_Tests()
{
_objectMapper = ServiceProvider.GetRequiredService<IObjectMapper<MultiLingualBook, MultiLingualBookDto>>();
var id = Guid.NewGuid();
_book = new MultiLingualBook(id, 100)
{
Translations = new List<MultiLingualBookTranslation>
{
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<MultiLingualBook, MultiLingualBookDto>,
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;
}
}
}

20
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<MultiLingualBookTranslation>
{
public MultiLingualBook(Guid id, decimal price)
{
Id = id;
Price = price;
}
public Guid Id { get; }
public decimal Price { get; set; }
public ICollection<MultiLingualBookTranslation> Translations { get; set; }
}
}

13
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; }
}
}

15
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<MultiLingualBook, Guid>
{
public string Name { get; set; }
public string Language { get; set; }
public MultiLingualBook Core { get; set; }
public Guid CoreId { get; set; }
}
}

3
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",

Loading…
Cancel
Save