Browse Source

Merge pull request #5265 from abpframework/liangshiwei/multi-lingual-entities

Add multi-lingual entities
pull/8081/head
maliming 6 years ago
committed by GitHub
parent
commit
2348b0e1c9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      framework/Volo.Abp.sln
  2. 54
      framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs
  3. 1
      framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj
  4. 2
      framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs
  5. 1
      framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
  6. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs
  7. 3
      framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xml
  8. 30
      framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xsd
  9. 21
      framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj
  10. 11
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectModule.cs
  11. 10
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IHasMultiLingual.cs
  12. 21
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs
  13. 7
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs
  14. 95
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs
  15. 114
      framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs
  16. 3
      framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj
  17. 8
      framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs
  18. 18
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo.Abp.MultiLingualObject.Tests.csproj
  19. 21
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs
  20. 76
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObjectManager_Tests.cs
  21. 132
      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. 11
      framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookTranslation.cs
  25. 1
      nupkg/common.ps1

10
framework/Volo.Abp.sln

@ -331,6 +331,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.GlobalFeatures", "
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.GlobalFeatures.Tests", "test\Volo.Abp.GlobalFeatures.Tests\Volo.Abp.GlobalFeatures.Tests.csproj", "{231F1581-AA21-44C3-BF27-51EB3AD5355C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.GlobalFeatures.Tests", "test\Volo.Abp.GlobalFeatures.Tests\Volo.Abp.GlobalFeatures.Tests.csproj", "{231F1581-AA21-44C3-BF27-51EB3AD5355C}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiLingualObject", "src\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj", "{C9142DED-1F6C-4385-A37D-81E46B233306}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiLingualObject.Tests", "test\Volo.Abp.MultiLingualObject.Tests\Volo.Abp.MultiLingualObject.Tests.csproj", "{A30D63B0-E952-4052-BAEE-38B8BF924093}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Http.Client.IdentityModel.WebAssembly", "src\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj", "{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Http.Client.IdentityModel.WebAssembly", "src\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj", "{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.Client.Common", "src\Volo.Abp.AspNetCore.Mvc.Client.Common\Volo.Abp.AspNetCore.Mvc.Client.Common.csproj", "{8A22D962-016E-474A-8BB7-F831F0ABF3AC}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.Client.Common", "src\Volo.Abp.AspNetCore.Mvc.Client.Common\Volo.Abp.AspNetCore.Mvc.Client.Common.csproj", "{8A22D962-016E-474A-8BB7-F831F0ABF3AC}"
@ -1087,6 +1091,10 @@ Global
{A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.Debug|Any CPU.Build.0 = Debug|Any CPU {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.ActiveCfg = Release|Any CPU
{A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.Release|Any CPU.Build.0 = 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
{F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Release|Any CPU.ActiveCfg = Release|Any CPU {F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -1304,6 +1312,8 @@ Global
{DD9519E0-5A68-48DC-A051-7BF2AC922F3E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {DD9519E0-5A68-48DC-A051-7BF2AC922F3E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA} {00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1} = {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}
{F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{5AD34048-5DAA-4067-9C7D-09295617A057} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {5AD34048-5DAA-4067-9C7D-09295617A057} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{B9133C38-AC24-4E2F-B581-D124CF410CDF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {B9133C38-AC24-4E2F-B581-D124CF410CDF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}

54
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<TSource, TTranslation, TDestination> CreateMultiLingualMap<TSource, TTranslation, TDestination>(this Profile profile)
where TTranslation : class, IMultiLingualTranslation
where TSource : IHasMultiLingual<TTranslation>
{
return new(
profile.CreateMap<TSource, TDestination>().BeforeMap<AbpMultiLingualMapperAction<TSource, TTranslation, TDestination>>(),
profile.CreateMap<TTranslation, TDestination>());
}
}
public class AbpMultiLingualMapperAction<TSource, TTranslation, TDestination> : IMappingAction<TSource, TDestination>
where TTranslation : class, IMultiLingualTranslation
where TSource : IHasMultiLingual<TTranslation>
{
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<TSource, TTranslation>(source));
if (translation != null)
{
context.Mapper.Map(translation, destination);
}
}
}
public class CreateMultiLingualMapResult<TSource, TTranslation, TDestination>
{
public IMappingExpression<TSource, TDestination> EntityMap { get; }
public IMappingExpression<TTranslation, TDestination> TranslateMap { get; }
public CreateMultiLingualMapResult(
IMappingExpression<TSource, TDestination> entityMap,
IMappingExpression<TTranslation, TDestination> translateMap)
{
EntityMap = entityMap;
TranslateMap = translateMap;
}
}
}

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

@ -16,6 +16,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" /> <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.ObjectExtending\Volo.Abp.ObjectExtending.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" /> <ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
</ItemGroup> </ItemGroup>

2
framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs

@ -27,6 +27,8 @@ namespace Volo.Abp.AutoMapper
context.Services.AddSingleton<MapperAccessor>(CreateMappings); context.Services.AddSingleton<MapperAccessor>(CreateMappings);
context.Services.AddSingleton<IMapperAccessor>(provider => provider.GetRequiredService<MapperAccessor>()); context.Services.AddSingleton<IMapperAccessor>(provider => provider.GetRequiredService<MapperAccessor>());
context.Services.AddTransient(typeof(AbpMultiLingualMapperAction<,,>));
} }
private MapperAccessor CreateMappings(IServiceProvider serviceProvider) private MapperAccessor CreateMappings(IServiceProvider serviceProvider)

1
framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj

@ -20,6 +20,7 @@
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" /> <ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.ExceptionHandling\Volo.Abp.ExceptionHandling.csproj" /> <ProjectReference Include="..\Volo.Abp.ExceptionHandling\Volo.Abp.ExceptionHandling.csproj" />
<ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.csproj" /> <ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" /> <ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" /> <ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Specifications\Volo.Abp.Specifications.csproj" /> <ProjectReference Include="..\Volo.Abp.Specifications\Volo.Abp.Specifications.csproj" />

2
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.ExceptionHandling;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MultiLingualObject;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
using Volo.Abp.Specifications; using Volo.Abp.Specifications;
@ -25,6 +26,7 @@ namespace Volo.Abp.Domain
typeof(AbpTimingModule), typeof(AbpTimingModule),
typeof(AbpUnitOfWorkModule), typeof(AbpUnitOfWorkModule),
typeof(AbpObjectMappingModule), typeof(AbpObjectMappingModule),
typeof(AbpMultiLingualObjectModule),
typeof(AbpExceptionHandlingModule), typeof(AbpExceptionHandlingModule),
typeof(AbpSpecificationsModule) typeof(AbpSpecificationsModule)
)] )]

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>

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

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.MultiLingualObject</AssemblyName>
<PackageId>Volo.Abp.MultiLingualObject</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<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; }
}
}

21
framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs

@ -0,0 +1,21 @@
using System.Threading.Tasks;
namespace Volo.Abp.MultiLingualObject
{
public interface IMultiLingualObjectManager
{
TTranslation GetTranslation<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
bool fallbackToParentCultures = true,
string culture = null)
where TMultiLingual : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation;
Task<TTranslation> GetTranslationAsync<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
bool fallbackToParentCultures = true,
string culture = null)
where TMultiLingual : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation;
}
}

7
framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.MultiLingualObject
{
public interface IMultiLingualTranslation
{
string Language { get; set; }
}
}

95
framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs

@ -0,0 +1,95 @@
using System;
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 class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientDependency
{
protected ISettingProvider SettingProvider { get; }
protected const int MaxCultureFallbackDepth = 5;
public MultiLingualObjectManager(ISettingProvider settingProvider)
{
SettingProvider = settingProvider;
}
public TTranslation GetTranslation<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
bool fallbackToParentCultures = true,
string culture = null)
where TMultiLingual : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation
{
return AsyncHelper.RunSync(() =>
GetTranslationAsync<TMultiLingual, TTranslation>(multiLingual, fallbackToParentCultures, culture));
}
public virtual async Task<TTranslation> GetTranslationAsync<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
bool fallbackToParentCultures = true,
string culture = null)
where TMultiLingual : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation
{
culture ??= CultureInfo.CurrentUICulture.Name;
if (multiLingual.Translations == null || !multiLingual.Translations.Any())
{
return null;
}
var translation = multiLingual.Translations.FirstOrDefault(pt => pt.Language == culture);
if (translation != null)
{
return translation;
}
if (fallbackToParentCultures)
{
translation =
GeTranslationBasedOnCulturalRecursive(
CultureInfo.CurrentUICulture.Parent, multiLingual.Translations, 0);
if (translation != null)
{
return translation;
}
}
var defaultLanguage = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage);
translation = multiLingual.Translations.FirstOrDefault(pt => pt.Language == defaultLanguage);
if (translation != null)
{
return translation;
}
translation = multiLingual.Translations.FirstOrDefault();
return translation;
}
protected virtual 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);
}
}
}

114
framework/test/Volo.Abp.AutoMapper.Tests/AutoMapper/AbpAutoMapperMultiLingualDto_Tests.cs

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp;
using Volo.Abp.AutoMapper;
using Volo.Abp.Localization;
using Volo.Abp.MultiLingualObject.TestObjects;
using Volo.Abp.Testing;
using Xunit;
namespace AutoMapper
{
public class AbpAutoMapperMultiLingualDto_Tests : AbpIntegratedTest<AutoMapperTestModule>
{
private readonly Volo.Abp.ObjectMapping.IObjectMapper _objectMapper;
private readonly MultiLingualBook _book;
public AbpAutoMapperMultiLingualDto_Tests()
{
_objectMapper = ServiceProvider.GetRequiredService<Volo.Abp.ObjectMapping.IObjectMapper>();
var id = Guid.NewGuid();
_book = new MultiLingualBook(id, 100)
{
Translations = new List<MultiLingualBookTranslation>()
};
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);
}
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<MultiLingualBook, MultiLingualBookDto>(_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<MultiLingualBook, MultiLingualBookDto>(_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<MultiLingualBook, MultiLingualBookDto>(_book);
bookDto.Name.ShouldBe("C# in Depth");
bookDto.Price.ShouldBe(_book.Price);
bookDto.Id.ShouldBe(_book.Id);
}
}
[Fact]
public void NoTranslations_ShouldStillMapObject()
{
_book.Translations.Clear();
using (CultureHelper.Use("tr"))
{
var bookDto = _objectMapper.Map<MultiLingualBook, MultiLingualBookDto>(_book);
bookDto.Name.ShouldBeNull();
bookDto.Price.ShouldBe(_book.Price);
bookDto.Id.ShouldBe(_book.Id);
}
}
}
public class BookProfile : Profile
{
public BookProfile()
{
var mapResult = this.CreateMultiLingualMap<MultiLingualBook, MultiLingualBookTranslation, MultiLingualBookDto>();
mapResult.EntityMap.ValidateMemberList(MemberList.None);
mapResult.TranslateMap.ValidateMemberList(MemberList.None);
}
}
}

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

@ -11,8 +11,9 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> <ProjectReference Include="..\..\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectExtending.Tests\Volo.Abp.ObjectExtending.Tests.csproj" /> <ProjectReference Include="..\..\test\Volo.Abp.ObjectExtending.Tests\Volo.Abp.ObjectExtending.Tests.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
<ProjectReference Include="..\Volo.Abp.MultiLingualObject.Tests\Volo.Abp.MultiLingualObject.Tests.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

8
framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AutoMapperTestModule.cs

@ -1,12 +1,14 @@
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MultiLingualObject;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
namespace Volo.Abp.AutoMapper namespace Volo.Abp.AutoMapper
{ {
[DependsOn( [DependsOn(
typeof(AbpAutoMapperModule), typeof(AbpAutoMapperModule),
typeof(AbpObjectExtendingTestModule) typeof(AbpObjectExtendingTestModule),
)] typeof(AbpMultiLingualObjectModule)
)]
public class AutoMapperTestModule : AbpModule public class AutoMapperTestModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
@ -17,4 +19,4 @@ namespace Volo.Abp.AutoMapper
}); });
} }
} }
} }

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>net5.0</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="$(MicrosoftNETTestSdkPackageVersion)" />
</ItemGroup>
</Project>

21
framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectTestModule.cs

@ -0,0 +1,21 @@
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
{
}
}

76
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<AbpMultiLingualObjectTestModule>
{
private readonly IMultiLingualObjectManager _multiLingualObjectManager;
private readonly MultiLingualBook _book;
public MultiLingualObjectManager_Tests()
{
_multiLingualObjectManager = ServiceProvider.GetRequiredService<IMultiLingualObjectManager>();
var id = Guid.NewGuid();
_book = new MultiLingualBook(id, 100)
{
Translations = new List<MultiLingualBookTranslation>()
};
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<MultiLingualBook, MultiLingualBookTranslation>(_book);
translation.Name.ShouldBe("C# in Depth");
}
}
[Fact]
public async Task GetTranslationAsync()
{
using (CultureHelper.Use("en-us"))
{
var translation = await _multiLingualObjectManager.GetTranslationAsync<MultiLingualBook, MultiLingualBookTranslation>(_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<MultiLingualBook, MultiLingualBookTranslation>(_book, culture: "en");
translation.Name.ShouldBe("C# in Depth");
}
}
}
}

132
framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/MultiLingualObject_Tests.cs

@ -0,0 +1,132 @@
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.Testing;
using Xunit;
namespace Volo.Abp.MultiLingualObject
{
public class MultiLingualObject_Tests : AbpIntegratedTest<AbpMultiLingualObjectTestModule>
{
private readonly IObjectMapper _objectMapper;
private readonly MultiLingualBook _book;
public MultiLingualObject_Tests()
{
_objectMapper = ServiceProvider.GetRequiredService<IObjectMapper>();
var id = Guid.NewGuid();
_book = new MultiLingualBook(id, 100)
{
Translations = new List<MultiLingualBookTranslation>()
};
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);
}
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<MultiLingualBook, MultiLingualBookDto>(_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<MultiLingualBook, MultiLingualBookDto>(_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<MultiLingualBook, MultiLingualBookDto>(_book);
bookDto.Name.ShouldBe("C# in Depth");
bookDto.Price.ShouldBe(_book.Price);
bookDto.Id.ShouldBe(_book.Id);
}
}
[Fact]
public void NoTranslations_ShouldStillMapObject()
{
_book.Translations.Clear();
using (CultureHelper.Use("tr"))
{
var bookDto = _objectMapper.Map<MultiLingualBook, MultiLingualBookDto>(_book);
bookDto.Name.ShouldBeNull();
bookDto.Price.ShouldBe(_book.Price);
bookDto.Id.ShouldBe(_book.Id);
}
}
}
public class MultiLingualBookObjectMapper : IObjectMapper<MultiLingualBook, MultiLingualBookDto>,
ITransientDependency
{
private readonly IMultiLingualObjectManager _multiLingualObjectManager;
public MultiLingualBookObjectMapper(IMultiLingualObjectManager multiLingualObjectManager)
{
_multiLingualObjectManager = multiLingualObjectManager;
}
public MultiLingualBookDto Map(MultiLingualBook source)
{
var translation =
_multiLingualObjectManager.GetTranslation<MultiLingualBook, MultiLingualBookTranslation>(source);
return new MultiLingualBookDto
{
Price = source.Price,
Id = source.Id,
Name = translation?.Name
};
}
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; }
}
}

11
framework/test/Volo.Abp.MultiLingualObject.Tests/Volo/Abp/MultiLingualObject/TestObjects/MultiLingualBookTranslation.cs

@ -0,0 +1,11 @@
using System;
namespace Volo.Abp.MultiLingualObject.TestObjects
{
public class MultiLingualBookTranslation : IMultiLingualTranslation
{
public string Name { get; set; }
public string Language { get; set; }
}
}

1
nupkg/common.ps1

@ -146,6 +146,7 @@ $projects = (
"framework/src/Volo.Abp.Validation", "framework/src/Volo.Abp.Validation",
"framework/src/Volo.Abp.VirtualFileSystem", "framework/src/Volo.Abp.VirtualFileSystem",
"framework/src/Volo.Abp.Kafka", "framework/src/Volo.Abp.Kafka",
"framework/src/Volo.Abp.MultiLingualObject",
"framework/src/Volo.Abp.Swashbuckle", "framework/src/Volo.Abp.Swashbuckle",
# modules/account # modules/account

Loading…
Cancel
Save