Browse Source

add xml localzation support

pull/230/head
cKey 5 years ago
parent
commit
c8567ddbab
  1. 33
      aspnet-core/LINGYUN.MicroService.All.sln
  2. 31
      aspnet-core/LINGYUN.MicroService.Common.sln
  3. 15
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/LINGYUN.Abp.Localization.Json.csproj
  4. 10
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/LINGYUN/Abp/Localization/Json/AbpLocalizationJsonModule.cs
  5. 116
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/LINGYUN/Abp/Localization/Json/JsonPhysicalFileLocalizationResourceContributor.cs
  6. 27
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/LINGYUN/Abp/Localization/Json/LocalizationResourceExtensions.cs
  7. 55
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/README.md
  8. 15
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN.Abp.Localization.Xml.csproj
  9. 10
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/AbpLocalizationXmlModule.cs
  10. 47
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/LocalizationResourceExtensions.cs
  11. 119
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlFileLocalizationResourceContributorBase.cs
  12. 74
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlLocalizationDictionaryBuilder.cs
  13. 98
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlLocalizationFile.cs
  14. 46
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlPhysicalFileLocalizationResourceContributor.cs
  15. 20
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlVirtualFileLocalizationResourceContributor.cs
  16. 64
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/README.md
  17. 28
      aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
  18. 27
      aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN.Abp.Localization.Json.Tests.csproj
  19. 8
      aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN/Abp/Localization/Json/AbpLocalizationJsonTestBase.cs
  20. 23
      aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN/Abp/Localization/Json/AbpLocalizationJsonTestModule.cs
  21. 32
      aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN/Abp/Localization/Json/JsonLocalizationTest.cs
  22. 6
      aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN/Abp/Localization/Json/LocalizationTestResource.cs
  23. 6
      aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/TestResources/en.json
  24. 6
      aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/TestResources/zh-Hans.json
  25. 37
      aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN.Abp.Localization.Xml.Tests.csproj
  26. 8
      aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/AbpLocalizationXmlTestBase.cs
  27. 30
      aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/AbpLocalizationXmlTestModule.cs
  28. 6
      aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/LocalizationTestResource.cs
  29. 7
      aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/Resources/en.xml
  30. 7
      aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/Resources/zh-Hans.xml
  31. 94
      aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/XmlLocalizationTest.cs
  32. 8
      aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/TestResources/zh-Hans.xml

33
aspnet-core/LINGYUN.MicroService.All.sln

@ -290,7 +290,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Location.Tencen
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Location.Baidu.Tests", "tests\LINGYUN.Abp.Location.Baidu.Tests\LINGYUN.Abp.Location.Baidu.Tests.csproj", "{C892CD81-50AE-49E5-BF44-A0C28A1614CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.AspNetCore.Mvc.Client", "modules\common\LINGYUN.Abp.AspNetCore.Mvc.Client\LINGYUN.Abp.AspNetCore.Mvc.Client.csproj", "{EEF03CC6-1013-4AAF-BEED-BB4BA5021039}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Client", "modules\common\LINGYUN.Abp.AspNetCore.Mvc.Client\LINGYUN.Abp.AspNetCore.Mvc.Client.csproj", "{EEF03CC6-1013-4AAF-BEED-BB4BA5021039}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "localization", "localization", "{90E88EAC-4291-4406-8D88-EFDF61B11292}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Xml", "modules\localization\LINGYUN.Abp.Localization.Xml\LINGYUN.Abp.Localization.Xml.csproj", "{84868710-ECBB-4025-900A-EEB99EC49534}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Xml.Tests", "tests\LINGYUN.Abp.Localization.Xml.Tests\LINGYUN.Abp.Localization.Xml.Tests.csproj", "{A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Json", "modules\localization\LINGYUN.Abp.Localization.Json\LINGYUN.Abp.Localization.Json.csproj", "{EA563F48-A6EF-4886-B607-2A83F7795F1B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Localization.Json.Tests", "tests\LINGYUN.Abp.Localization.Json.Tests\LINGYUN.Abp.Localization.Json.Tests.csproj", "{EBCF7D88-49E2-413D-A7A6-1A76BC2E8161}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -770,6 +780,22 @@ Global
{EEF03CC6-1013-4AAF-BEED-BB4BA5021039}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EEF03CC6-1013-4AAF-BEED-BB4BA5021039}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EEF03CC6-1013-4AAF-BEED-BB4BA5021039}.Release|Any CPU.Build.0 = Release|Any CPU
{84868710-ECBB-4025-900A-EEB99EC49534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84868710-ECBB-4025-900A-EEB99EC49534}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84868710-ECBB-4025-900A-EEB99EC49534}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84868710-ECBB-4025-900A-EEB99EC49534}.Release|Any CPU.Build.0 = Release|Any CPU
{A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED}.Release|Any CPU.Build.0 = Release|Any CPU
{EA563F48-A6EF-4886-B607-2A83F7795F1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA563F48-A6EF-4886-B607-2A83F7795F1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA563F48-A6EF-4886-B607-2A83F7795F1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA563F48-A6EF-4886-B607-2A83F7795F1B}.Release|Any CPU.Build.0 = Release|Any CPU
{EBCF7D88-49E2-413D-A7A6-1A76BC2E8161}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBCF7D88-49E2-413D-A7A6-1A76BC2E8161}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBCF7D88-49E2-413D-A7A6-1A76BC2E8161}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBCF7D88-49E2-413D-A7A6-1A76BC2E8161}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -915,6 +941,11 @@ Global
{94B47385-E47F-4FD7-A3A9-A7AA122EFC93} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}
{C892CD81-50AE-49E5-BF44-A0C28A1614CC} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}
{EEF03CC6-1013-4AAF-BEED-BB4BA5021039} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E}
{90E88EAC-4291-4406-8D88-EFDF61B11292} = {C5CAD011-DF84-4914-939C-0C029DCEF26F}
{84868710-ECBB-4025-900A-EEB99EC49534} = {90E88EAC-4291-4406-8D88-EFDF61B11292}
{A061D2B4-B650-4F7F-A6CB-5C8FFFD512ED} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}
{EA563F48-A6EF-4886-B607-2A83F7795F1B} = {90E88EAC-4291-4406-8D88-EFDF61B11292}
{EBCF7D88-49E2-413D-A7A6-1A76BC2E8161} = {370D7CD5-1E17-4F3D-BBFA-03429F6D4F2F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}

31
aspnet-core/LINGYUN.MicroService.Common.sln

@ -117,6 +117,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Location.Tencen
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Client", "modules\common\LINGYUN.Abp.AspNetCore.Mvc.Client\LINGYUN.Abp.AspNetCore.Mvc.Client.csproj", "{7F767ACF-754A-4EBC-8936-3C1402B6EF82}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "localization", "localization", "{E73A0F8B-2B4B-4CED-82A4-1EE5E0B89744}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Json", "modules\localization\LINGYUN.Abp.Localization.Json\LINGYUN.Abp.Localization.Json.csproj", "{DADD5D6E-F09A-4563-A659-7922E26C40AB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Xml", "modules\localization\LINGYUN.Abp.Localization.Xml\LINGYUN.Abp.Localization.Xml.csproj", "{8CC72F4E-F134-4A43-9037-5D4D1F29B68A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Xml.Tests", "tests\LINGYUN.Abp.Localization.Xml.Tests\LINGYUN.Abp.Localization.Xml.Tests.csproj", "{94FEA59E-3B6D-41A0-9E44-BA5D6477244F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Json.Tests", "tests\LINGYUN.Abp.Localization.Json.Tests\LINGYUN.Abp.Localization.Json.Tests.csproj", "{BA2F4EC9-BC2C-482A-9123-BDACB8B15295}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -307,6 +317,22 @@ Global
{7F767ACF-754A-4EBC-8936-3C1402B6EF82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F767ACF-754A-4EBC-8936-3C1402B6EF82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F767ACF-754A-4EBC-8936-3C1402B6EF82}.Release|Any CPU.Build.0 = Release|Any CPU
{DADD5D6E-F09A-4563-A659-7922E26C40AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DADD5D6E-F09A-4563-A659-7922E26C40AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DADD5D6E-F09A-4563-A659-7922E26C40AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DADD5D6E-F09A-4563-A659-7922E26C40AB}.Release|Any CPU.Build.0 = Release|Any CPU
{8CC72F4E-F134-4A43-9037-5D4D1F29B68A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CC72F4E-F134-4A43-9037-5D4D1F29B68A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CC72F4E-F134-4A43-9037-5D4D1F29B68A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CC72F4E-F134-4A43-9037-5D4D1F29B68A}.Release|Any CPU.Build.0 = Release|Any CPU
{94FEA59E-3B6D-41A0-9E44-BA5D6477244F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94FEA59E-3B6D-41A0-9E44-BA5D6477244F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94FEA59E-3B6D-41A0-9E44-BA5D6477244F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{94FEA59E-3B6D-41A0-9E44-BA5D6477244F}.Release|Any CPU.Build.0 = Release|Any CPU
{BA2F4EC9-BC2C-482A-9123-BDACB8B15295}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA2F4EC9-BC2C-482A-9123-BDACB8B15295}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA2F4EC9-BC2C-482A-9123-BDACB8B15295}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA2F4EC9-BC2C-482A-9123-BDACB8B15295}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -367,6 +393,11 @@ Global
{221725FF-6C01-4F41-9F29-AC04C7D52611} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
{1B494EA1-28CF-4A61-B0BE-70BBA425C316} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
{7F767ACF-754A-4EBC-8936-3C1402B6EF82} = {086BE5BE-8594-4DA7-8819-935FEF76DABD}
{E73A0F8B-2B4B-4CED-82A4-1EE5E0B89744} = {02EA4E78-5891-43BC-944F-3E52FEE032E4}
{DADD5D6E-F09A-4563-A659-7922E26C40AB} = {E73A0F8B-2B4B-4CED-82A4-1EE5E0B89744}
{8CC72F4E-F134-4A43-9037-5D4D1F29B68A} = {E73A0F8B-2B4B-4CED-82A4-1EE5E0B89744}
{94FEA59E-3B6D-41A0-9E44-BA5D6477244F} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
{BA2F4EC9-BC2C-482A-9123-BDACB8B15295} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8}

15
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/LINGYUN.Abp.Localization.Json.csproj

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Localization" Version="4.2.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="5.0.*" />
</ItemGroup>
</Project>

10
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/LINGYUN/Abp/Localization/Json/AbpLocalizationJsonModule.cs

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Localization.Json
{
[DependsOn(typeof(AbpLocalizationModule))]
public class AbpLocalizationJsonModule : AbpModule
{
}
}

116
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/LINGYUN/Abp/Localization/Json/JsonPhysicalFileLocalizationResourceContributor.cs

@ -0,0 +1,116 @@
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Internal;
using Volo.Abp.Localization;
using Volo.Abp.Localization.Json;
namespace LINGYUN.Abp.Localization.Json
{
public class JsonPhysicalFileLocalizationResourceContributor : ILocalizationResourceContributor
{
private readonly string _filePath;
private IFileProvider _fileProvider;
private Dictionary<string, ILocalizationDictionary> _dictionaries;
private bool _subscribedForChanges;
private readonly object _syncObj = new object();
public JsonPhysicalFileLocalizationResourceContributor(string filePath)
{
_filePath = filePath;
}
public void Initialize(LocalizationResourceInitializationContext context)
{
_fileProvider = new PhysicalFileProvider(_filePath);
}
public LocalizedString GetOrNull(string cultureName, string name)
{
return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name);
}
public void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
GetDictionaries().GetOrDefault(cultureName)?.Fill(dictionary);
}
protected virtual Dictionary<string, ILocalizationDictionary> GetDictionaries()
{
var dictionaries = _dictionaries;
if (dictionaries != null)
{
return dictionaries;
}
lock (_syncObj)
{
dictionaries = _dictionaries;
if (dictionaries != null)
{
return dictionaries;
}
if (!_subscribedForChanges)
{
ChangeToken.OnChange(() => _fileProvider.Watch(_filePath.EnsureEndsWith('/') + "*.*"),
() =>
{
_dictionaries = null;
});
_subscribedForChanges = true;
}
dictionaries = _dictionaries = CreateDictionaries();
}
return dictionaries;
}
protected virtual Dictionary<string, ILocalizationDictionary> CreateDictionaries()
{
var dictionaries = new Dictionary<string, ILocalizationDictionary>();
foreach (var file in _fileProvider.GetDirectoryContents(string.Empty))
{
if (file.IsDirectory || !CanParseFile(file))
{
continue;
}
var dictionary = CreateDictionaryFromFile(file);
if (dictionaries.ContainsKey(dictionary.CultureName))
{
throw new AbpException($"{file.GetVirtualOrPhysicalPathOrNull()} dictionary has a culture name '{dictionary.CultureName}' which is already defined!");
}
dictionaries[dictionary.CultureName] = dictionary;
}
return dictionaries;
}
protected virtual bool CanParseFile(IFileInfo file)
{
return file.Name.EndsWith(".json", StringComparison.OrdinalIgnoreCase);
}
protected virtual ILocalizationDictionary CreateDictionaryFromFile(IFileInfo file)
{
using (var stream = file.CreateReadStream())
{
return CreateDictionaryFromFileContent(Utf8Helper.ReadStringFromStream(stream));
}
}
protected virtual ILocalizationDictionary CreateDictionaryFromFileContent(string fileContent)
{
return JsonLocalizationDictionaryBuilder.BuildFromJsonString(fileContent);
}
}
}

27
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/LINGYUN/Abp/Localization/Json/LocalizationResourceExtensions.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Localization.Json
{
public static class LocalizationResourceExtensions
{
/// <summary>
/// 添加Json本地磁盘文件支持
/// </summary>
/// <param name="localizationResource"></param>
/// <param name="jsonFilePath"></param>
/// <returns></returns>
public static LocalizationResource AddPhysicalJson(
[NotNull] this LocalizationResource localizationResource,
[NotNull] string jsonFilePath)
{
Check.NotNull(localizationResource, nameof(localizationResource));
Check.NotNull(jsonFilePath, nameof(jsonFilePath));
localizationResource.Contributors.Add(new JsonPhysicalFileLocalizationResourceContributor(jsonFilePath));
return localizationResource;
}
}
}

55
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Json/README.md

@ -0,0 +1,55 @@
# LINGYUN.Abp.Localization.Json
## 模块说明
本地化组件的Json本地文件系统集成,Abp内置组件仅集成了基于IVirtualFileProvider的实现
此组件基于PhysicalFileProvider
### 基础模块
### 高阶模块
### 权限定义
### 功能定义
### 配置定义
### 如何使用
```csharp
[DependsOn(
typeof(AbpLocalizationJsonModule))]
public class YouProjectModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<YouResource>("en")
// 一般配置在宿主项目中, 写入宿主项目中存储json文件的绝对路径(受PhysicalFileProvider的限制)
// json文件格式与Abp默认json格式保持一致
// 详情见: https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.fileproviders.physicalfileprovider?view=dotnet-plat-ext-5.0
.AddPhysicalJson(Path.Combine(Directory.GetCurrentDirectory(), "Resources"));
});
}
}
```
```json
{
"culture": "en",
"texts": {
"Hello China": "Hello China!"
}
}
```
### 更新日志

15
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN.Abp.Localization.Xml.csproj

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Localization" Version="4.2.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="5.0.*"/>
</ItemGroup>
</Project>

10
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/AbpLocalizationXmlModule.cs

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Localization.Xml
{
[DependsOn(typeof(AbpLocalizationModule))]
public class AbpLocalizationXmlModule : AbpModule
{
}
}

47
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/LocalizationResourceExtensions.cs

@ -0,0 +1,47 @@
using JetBrains.Annotations;
using System;
using Volo.Abp;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Localization.Xml
{
public static class LocalizationResourceExtensions
{
/// <summary>
/// 添加Xml虚拟文件系统支持
/// </summary>
/// <param name="localizationResource"></param>
/// <param name="virtualPath"></param>
/// <returns></returns>
public static LocalizationResource AddVirtualXml(
[NotNull] this LocalizationResource localizationResource,
[NotNull] string virtualPath)
{
Check.NotNull(localizationResource, nameof(localizationResource));
Check.NotNull(virtualPath, nameof(virtualPath));
localizationResource.Contributors.Add(new XmlVirtualFileLocalizationResourceContributor(
virtualPath.EnsureStartsWith('/')
));
return localizationResource;
}
/// <summary>
/// 添加Xml本地磁盘文件支持
/// </summary>
/// <param name="localizationResource"></param>
/// <param name="xmlFilePath"></param>
/// <returns></returns>
public static LocalizationResource AddPhysicalXml(
[NotNull] this LocalizationResource localizationResource,
[NotNull] string xmlFilePath)
{
Check.NotNull(localizationResource, nameof(localizationResource));
Check.NotNull(xmlFilePath, nameof(xmlFilePath));
localizationResource.Contributors.Add(new XmlPhysicalFileLocalizationResourceContributor(xmlFilePath));
return localizationResource;
}
}
}

119
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlFileLocalizationResourceContributorBase.cs

@ -0,0 +1,119 @@
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Internal;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Localization.Xml
{
public abstract class XmlFileLocalizationResourceContributorBase : ILocalizationResourceContributor
{
private readonly string _filePath;
private IFileProvider _fileProvider;
private Dictionary<string, ILocalizationDictionary> _dictionaries;
private bool _subscribedForChanges;
private readonly object _syncObj = new object();
protected XmlFileLocalizationResourceContributorBase(string filePath)
{
_filePath = filePath;
}
public virtual void Initialize(LocalizationResourceInitializationContext context)
{
_fileProvider = BuildFileProvider(context);
Check.NotNull(_fileProvider, nameof(_fileProvider));
}
public virtual LocalizedString GetOrNull(string cultureName, string name)
{
return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name);
}
public virtual void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
GetDictionaries().GetOrDefault(cultureName)?.Fill(dictionary);
}
protected virtual Dictionary<string, ILocalizationDictionary> GetDictionaries()
{
var dictionaries = _dictionaries;
if (dictionaries != null)
{
return dictionaries;
}
lock (_syncObj)
{
dictionaries = _dictionaries;
if (dictionaries != null)
{
return dictionaries;
}
if (!_subscribedForChanges)
{
ChangeToken.OnChange(() => _fileProvider.Watch(_filePath.EnsureEndsWith('/') + "*.*"),
() =>
{
_dictionaries = null;
});
_subscribedForChanges = true;
}
dictionaries = _dictionaries = CreateDictionaries(_fileProvider, _filePath);
}
return dictionaries;
}
protected virtual Dictionary<string, ILocalizationDictionary> CreateDictionaries(IFileProvider fileProvider, string filePath)
{
var dictionaries = new Dictionary<string, ILocalizationDictionary>();
foreach (var file in fileProvider.GetDirectoryContents(filePath))
{
if (file.IsDirectory || !CanParseFile(file))
{
continue;
}
var dictionary = CreateDictionaryFromFile(file);
if (dictionaries.ContainsKey(dictionary.CultureName))
{
throw new AbpException($"{file.GetVirtualOrPhysicalPathOrNull()} dictionary has a culture name '{dictionary.CultureName}' which is already defined!");
}
dictionaries[dictionary.CultureName] = dictionary;
}
return dictionaries;
}
protected virtual bool CanParseFile(IFileInfo file)
{
return file.Name.EndsWith(".xml", StringComparison.OrdinalIgnoreCase);
}
protected virtual ILocalizationDictionary CreateDictionaryFromFile(IFileInfo file)
{
using (var stream = file.CreateReadStream())
{
return CreateDictionaryFromFileContent(Utf8Helper.ReadStringFromStream(stream));
}
}
protected virtual ILocalizationDictionary CreateDictionaryFromFileContent(string fileContent)
{
return XmlLocalizationDictionaryBuilder.BuildFromXmlString(fileContent);
}
protected abstract IFileProvider BuildFileProvider(LocalizationResourceInitializationContext context);
}
}

74
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlLocalizationDictionaryBuilder.cs

@ -0,0 +1,74 @@
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using Volo.Abp;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Localization.Xml
{
public static class XmlLocalizationDictionaryBuilder
{
public static ILocalizationDictionary BuildFromFile(string filePath)
{
try
{
return BuildFromXmlString(File.ReadAllText(filePath));
}
catch (Exception ex)
{
throw new AbpException("Invalid localization file format: " + filePath, ex);
}
}
public static ILocalizationDictionary BuildFromXmlString(string xmlString)
{
XmlLocalizationFile xmlFile;
try
{
XmlSerializer serializer = new XmlSerializer(typeof(XmlLocalizationFile));
using (StringReader reader = new StringReader(xmlString))
{
xmlFile = (XmlLocalizationFile)serializer.Deserialize(reader);
}
}
catch (Exception ex)
{
throw new AbpException("Can not parse xml string. " + ex.Message);
}
var cultureCode = xmlFile.Culture.Name;
if (string.IsNullOrEmpty(cultureCode))
{
throw new AbpException("Culture is empty in language json file.");
}
var dictionary = new Dictionary<string, LocalizedString>();
var dublicateNames = new List<string>();
foreach (var item in xmlFile.Texts)
{
if (string.IsNullOrEmpty(item.Key))
{
throw new AbpException("The key is empty in given json string.");
}
if (dictionary.GetOrDefault(item.Key) != null)
{
dublicateNames.Add(item.Key);
}
dictionary[item.Key] = new LocalizedString(item.Key, item.Value.NormalizeLineEndings());
}
if (dublicateNames.Count > 0)
{
throw new AbpException(
"A dictionary can not contain same key twice. There are some duplicated names: " +
dublicateNames.JoinAsString(", "));
}
return new StaticLocalizationDictionary(cultureCode, dictionary);
}
}
}

98
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlLocalizationFile.cs

@ -0,0 +1,98 @@
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace LINGYUN.Abp.Localization.Xml
{
[Serializable]
[XmlRoot(Namespace = "lingyun.abp", ElementName = "localization")]
public class XmlLocalizationFile
{
[XmlElement("culture")]
public CultureInfo Culture { get; set; } = new CultureInfo();
[XmlArray("texts")]
[XmlArrayItem("text")]
public LocalizationText[] Texts { get; set; } = new LocalizationText[0];
public XmlLocalizationFile() { }
public XmlLocalizationFile(string culture)
{
Culture = new CultureInfo(culture);
}
public XmlLocalizationFile(string culture, LocalizationText[] texts)
{
Culture = new CultureInfo(culture);
Texts = texts;
}
public void WriteToPath(string filePath)
{
var fileName = Path.Combine(filePath, Culture.Name + ".xml");
using FileStream fileStream = new(fileName, FileMode.Create, FileAccess.Write);
InternalWrite(fileStream, Encoding.UTF8);
}
private void InternalWrite(Stream stream, Encoding encoding)
{
if (encoding == null)
{
throw new ArgumentNullException("encoding");
}
XmlSerializer serializer = new(GetType());
XmlWriterSettings settings = new()
{
Indent = true,
NewLineChars = "\r\n",
Encoding = encoding,
IndentChars = " "
};
using XmlWriter writer = XmlWriter.Create(stream, settings);
serializer.Serialize(writer, this);
writer.Close();
}
}
[Serializable]
public class CultureInfo
{
[XmlAttribute("name")]
public string Name { get; set; }
public CultureInfo()
{
}
public CultureInfo(string name)
{
Name = name;
}
}
[Serializable]
public class LocalizationText
{
[XmlAttribute("key")]
public string Key { get; set; }
[XmlAttribute("value")]
public string Value { get; set; }
public LocalizationText()
{
}
public LocalizationText(string key, string value)
{
Key = key;
Value = value;
}
}
}

46
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlPhysicalFileLocalizationResourceContributor.cs

@ -0,0 +1,46 @@
using Microsoft.Extensions.FileProviders;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Localization.Xml
{
public class XmlPhysicalFileLocalizationResourceContributor : XmlFileLocalizationResourceContributorBase
{
private readonly string _filePath;
public XmlPhysicalFileLocalizationResourceContributor(string filePath)
: base(filePath)
{
_filePath = filePath;
}
protected override IFileProvider BuildFileProvider(LocalizationResourceInitializationContext context)
{
return new PhysicalFileProvider(_filePath);
}
protected override Dictionary<string, ILocalizationDictionary> CreateDictionaries(IFileProvider fileProvider, string filePath)
{
var dictionaries = new Dictionary<string, ILocalizationDictionary>();
foreach (var file in fileProvider.GetDirectoryContents(string.Empty))
{
if (file.IsDirectory || !CanParseFile(file))
{
continue;
}
var dictionary = CreateDictionaryFromFile(file);
if (dictionaries.ContainsKey(dictionary.CultureName))
{
throw new AbpException($"{file.GetVirtualOrPhysicalPathOrNull()} dictionary has a culture name '{dictionary.CultureName}' which is already defined!");
}
dictionaries[dictionary.CultureName] = dictionary;
}
return dictionaries;
}
}
}

20
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/LINGYUN/Abp/Localization/Xml/XmlVirtualFileLocalizationResourceContributor.cs

@ -0,0 +1,20 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Volo.Abp.Localization;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Localization.Xml
{
public class XmlVirtualFileLocalizationResourceContributor : XmlFileLocalizationResourceContributorBase
{
public XmlVirtualFileLocalizationResourceContributor(string filePath)
: base(filePath)
{
}
protected override IFileProvider BuildFileProvider(LocalizationResourceInitializationContext context)
{
return context.ServiceProvider.GetRequiredService<IVirtualFileProvider>();
}
}
}

64
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Xml/README.md

@ -0,0 +1,64 @@
# LINGYUN.Abp.Localization.Xml
## 模块说明
本地化组件的Xml文档集成,内置PhysicalFileProvider与VirtualFileProvider实现
### 基础模块
### 高阶模块
### 权限定义
### 功能定义
### 配置定义
### 如何使用
```csharp
[DependsOn(
typeof(AbpLocalizationXmlModule))]
public class YouProjectModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<YouProjectModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<YouResource>("en")
// 当前项目中的虚拟文件系统目录,详情见: https://docs.abp.io/en/abp/latest/Virtual-File-System
.AddVirtualXml("/LINGYUN/Abp/Localization/Xml/Resources")
// 一般配置在宿主项目中, 写入宿主项目中存储xml文件的绝对路径(受PhysicalFileProvider的限制)
// 详情见: https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.fileproviders.physicalfileprovider?view=dotnet-plat-ext-5.0
.AddPhysicalXml(Path.Combine(Directory.GetCurrentDirectory(), "Resources"));
});
}
}
```
Xml文件格式如下
序列化: [XmlLocalizationFile](./LINGYUN/Abp/Localization/Xml/XmlLocalizationFile.cs) 类型实现
```xml
<?xml version="1.0" encoding="utf-8"?>
<localization xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="lingyun.abp">
<culture name="en" />
<texts>
<text key="Hello China" value="Hello China!" />
<text key="Welcome" value="Welcome!" />
</texts>
</localization>
```
### 更新日志

28
aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs

@ -19,7 +19,9 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StackExchange.Redis;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Unicode;
@ -41,6 +43,7 @@ using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer;
using Volo.Abp.IdentityServer.Jwt;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
@ -89,6 +92,7 @@ namespace AuthServer.Host
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
PreConfigure<CapOptions>(options =>
{
@ -100,6 +104,29 @@ namespace AuthServer.Host
})
.UseDashboard();
});
var cerConfig = configuration.GetSection("Certificates");
if (hostingEnvironment.IsProduction() &&
cerConfig.Exists())
{
// 开发环境下存在证书配置
// 且证书文件存在则使用自定义的证书文件来启动Ids服务器
var cerPath = Path.Combine(hostingEnvironment.ContentRootPath, cerConfig["CerPath"]);
if (File.Exists(cerPath))
{
PreConfigure<AbpIdentityServerBuilderOptions>(options =>
{
options.AddDeveloperSigningCredential = false;
});
var cer = new X509Certificate2(cerPath, cerConfig["Password"]);
PreConfigure<IIdentityServerBuilder>(builder =>
{
builder.AddSigningCredential(cer);
});
}
}
}
public override void ConfigureServices(ServiceConfigurationContext context)
@ -280,6 +307,7 @@ namespace AuthServer.Host
}
else
{
// 需要实现一个错误页面
app.UseErrorPage();
app.UseHsts();
}

27
aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN.Abp.Localization.Json.Tests.csproj

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\localization\LINGYUN.Abp.Localization.Json\LINGYUN.Abp.Localization.Json.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" />
</ItemGroup>
</Project>

8
aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN/Abp/Localization/Json/AbpLocalizationJsonTestBase.cs

@ -0,0 +1,8 @@
using LINGYUN.Abp.Tests;
namespace LINGYUN.Abp.Localization.Json
{
public abstract class AbpLocalizationJsonTestBase : AbpTestsBase<AbpLocalizationJsonTestModule>
{
}
}

23
aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN/Abp/Localization/Json/AbpLocalizationJsonTestModule.cs

@ -0,0 +1,23 @@
using LINGYUN.Abp.Tests;
using System.IO;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Localization.Json
{
[DependsOn(
typeof(AbpTestsBaseModule),
typeof(AbpLocalizationJsonModule))]
public class AbpLocalizationJsonTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<LocalizationTestResource>("en")
.AddPhysicalJson(Path.Combine(Directory.GetCurrentDirectory(), "TestResources"));
});
}
}
}

32
aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN/Abp/Localization/Json/JsonLocalizationTest.cs

@ -0,0 +1,32 @@
using Microsoft.Extensions.Localization;
using Shouldly;
using Volo.Abp.Localization;
using Xunit;
namespace LINGYUN.Abp.Localization.Json
{
public class JsonLocalizationTest : AbpLocalizationJsonTestBase
{
private readonly IStringLocalizer<LocalizationTestResource> _localizer;
public JsonLocalizationTest()
{
_localizer = GetRequiredService<IStringLocalizer<LocalizationTestResource>>();
}
[Fact]
public void Should_Get_Physical_Localized_Text_If_Defined_In_Current_Culture()
{
using (CultureHelper.Use("zh-Hans"))
{
_localizer["Hello China"].Value.ShouldBe("China 你好!");
}
using (CultureHelper.Use("en"))
{
_localizer["Hello China"].Value.ShouldBe("Hello China!");
}
}
}
}

6
aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/LINGYUN/Abp/Localization/Json/LocalizationTestResource.cs

@ -0,0 +1,6 @@
namespace LINGYUN.Abp.Localization.Json
{
public class LocalizationTestResource
{
}
}

6
aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/TestResources/en.json

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"Hello China": "Hello China!"
}
}

6
aspnet-core/tests/LINGYUN.Abp.Localization.Json.Tests/TestResources/zh-Hans.json

@ -0,0 +1,6 @@
{
"culture": "zh-Hans",
"texts": {
"Hello China": "China 你好!"
}
}

37
aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN.Abp.Localization.Xml.Tests.csproj

@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Localization\Xml\Resources\en.xml" />
<None Remove="LINGYUN\Abp\Localization\Xml\Resources\zh-Hans.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Localization\Xml\Resources\en.xml" />
<EmbeddedResource Include="LINGYUN\Abp\Localization\Xml\Resources\zh-Hans.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\localization\LINGYUN.Abp.Localization.Xml\LINGYUN.Abp.Localization.Xml.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" />
</ItemGroup>
</Project>

8
aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/AbpLocalizationXmlTestBase.cs

@ -0,0 +1,8 @@
using LINGYUN.Abp.Tests;
namespace LINGYUN.Abp.Localization.Xml
{
public abstract class AbpLocalizationXmlTestBase : AbpTestsBase<AbpLocalizationXmlTestModule>
{
}
}

30
aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/AbpLocalizationXmlTestModule.cs

@ -0,0 +1,30 @@
using LINGYUN.Abp.Tests;
using System.IO;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Localization.Xml
{
[DependsOn(
typeof(AbpTestsBaseModule),
typeof(AbpLocalizationXmlModule))]
public class AbpLocalizationXmlTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpLocalizationXmlTestModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<LocalizationTestResource>("en")
.AddVirtualXml("/LINGYUN/Abp/Localization/Xml/Resources")
.AddPhysicalXml(Path.Combine(Directory.GetCurrentDirectory(), "TestResources"));
});
}
}
}

6
aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/LocalizationTestResource.cs

@ -0,0 +1,6 @@
namespace LINGYUN.Abp.Localization.Xml
{
public class LocalizationTestResource
{
}
}

7
aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/Resources/en.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<localization xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="lingyun.abp">
<culture name="en" />
<texts>
<text key="Hello China" value="Hello China!" />
</texts>
</localization>

7
aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/Resources/zh-Hans.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<localization xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="lingyun.abp">
<culture name="zh-Hans" />
<texts>
<text key="Hello China" value="China 你好!" />
</texts>
</localization>

94
aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN/Abp/Localization/Xml/XmlLocalizationTest.cs

@ -0,0 +1,94 @@
using Microsoft.Extensions.Localization;
using Shouldly;
using System.IO;
using Volo.Abp.Localization;
using Xunit;
namespace LINGYUN.Abp.Localization.Xml
{
public class XmlLocalizationTest : AbpLocalizationXmlTestBase
{
private readonly static string[] _localizerFiles = new string[]
{
Path.Combine("./TestResources", "zh-Hans.xml"),
Path.Combine("./TestResources", "en.xml")
};
private readonly IStringLocalizer<LocalizationTestResource> _localizer;
public XmlLocalizationTest()
{
_localizer = GetRequiredService<IStringLocalizer<LocalizationTestResource>>();
}
[Fact]
public void Should_Get_Physical_Localized_Text_If_Defined_In_Current_Culture()
{
Init();
using (CultureHelper.Use("zh-Hans"))
{
_localizer["Hello World"].Value.ShouldBe("世界你好!");
_localizer["C# Test"].Value.ShouldBe("C#测试");
}
using (CultureHelper.Use("en"))
{
_localizer["Hello World"].Value.ShouldBe("Hello World!");
_localizer["C# Test"].Value.ShouldBe("C# Test!");
}
}
[Fact]
public void Should_Get_Virtual_Localized_Text_If_Defined_In_Current_Culture()
{
using (CultureHelper.Use("zh-Hans"))
{
_localizer["Hello China"].Value.ShouldBe("China 你好!");
}
using (CultureHelper.Use("en"))
{
_localizer["Hello China"].Value.ShouldBe("Hello China!");
}
}
private static void Init()
{
var zhHansfile = new XmlLocalizationFile("zh-Hans")
{
Texts = new LocalizationText[]
{
new LocalizationText("Hello World", "世界你好!"),
new LocalizationText("C# Test", "C#测试")
}
};
zhHansfile.WriteToPath("./TestResources");
var enFile = new XmlLocalizationFile("en")
{
Texts = new LocalizationText[]
{
new LocalizationText("Hello World", "Hello World!"),
new LocalizationText("C# Test", "C# Test!")
}
};
enFile.WriteToPath("./TestResources");
}
public override void Dispose()
{
base.Dispose();
foreach (var file in _localizerFiles)
{
if (File.Exists(file))
{
File.Delete(file);
}
}
}
}
}

8
aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/TestResources/zh-Hans.xml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<localization xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="lingyun.abp">
<culture name="zh-Hans" />
<texts>
<text key="Hello World" value="世界你好!" />
<text key="C# Test" value="C#测试" />
</texts>
</localization>
Loading…
Cancel
Save