Browse Source

LocalizationDynamic And Localization Management

master
wwwk 3 years ago
parent
commit
f54c10c8a5
  1. 65
      Sanhe.Abp.Framework.sln
  2. 3
      modules/common/Sanhe.Abp.Localization.Dynamic/FodyWeavers.xml
  3. 38
      modules/common/Sanhe.Abp.Localization.Dynamic/README.md
  4. 15
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe.Abp.Localization.Dynamic.csproj
  5. 17
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/AbpLocalizationDynamicModule.cs
  6. 22
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/AbpLocalizationDynamicOptions.cs
  7. 30
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/DefaultLocalizationStore.cs
  8. 41
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/DynamicLanguageProvider.cs
  9. 47
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/DynamicLocalizationInitializeService.cs
  10. 40
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/DynamicLocalizationResourceContributor.cs
  11. 37
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/ILocalizationStore.cs
  12. 22
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LanguageInfoComparer.cs
  13. 58
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LocalizationCacheItem.cs
  14. 12
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LocalizationDictionary.cs
  15. 75
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LocalizationResetSynchronizer.cs
  16. 44
      modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LocalizedStringCacheResetEventData.cs
  17. 42
      modules/common/Sanhe.Abp.Localization.Dynamic/Volo/Abp/Localization/LocalizationResourceDictionaryExtensions.cs
  18. 20
      modules/common/Sanhe.Abp.Localization.Dynamic/Volo/Abp/Localization/LocalizationResourceExtensions.cs
  19. 39
      modules/localization-management/README.md
  20. 3
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/FodyWeavers.xml
  21. 20
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe.Abp.LocalizationManagement.Application.Contracts.csproj
  22. 12
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementApplicationContractsModule.cs
  23. 24
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/CreateOrUpdateLanguageInput.cs
  24. 19
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/CreateOrUpdateResourceInput.cs
  25. 9
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/CreateOrUpdateTextInput.cs
  26. 19
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/CreateTextInput.cs
  27. 8
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/GetLanguagesInput.cs
  28. 8
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/GetResourcesInput.cs
  29. 19
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/GetTextByKeyInput.cs
  30. 23
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/GetTextsInput.cs
  31. 17
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/ILanguageAppService.cs
  32. 17
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/IResourceAppService.cs
  33. 16
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/ITextAppService.cs
  34. 13
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/LanguageDto.cs
  35. 6
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/LocalizationRemoteServiceConsts.cs
  36. 72
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/Permissions/LocalizationManagementPermissionDefinitionProvider.cs
  37. 39
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/Permissions/LocalizationManagementPermissions.cs
  38. 12
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/ResourceDto.cs
  39. 13
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/TextDifferenceDto.cs
  40. 11
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/TextDto.cs
  41. 5
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/UpdateTextInput.cs
  42. 3
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/FodyWeavers.xml
  43. 20
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe.Abp.LocalizationManagement.Application.csproj
  44. 23
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementApplicationModule.cs
  45. 70
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/LanguageAppService.cs
  46. 14
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/LocalizationManagementApplicationMapperProfile.cs
  47. 75
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/ResourceAppService.cs
  48. 71
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/TextAppService.cs
  49. 3
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/FodyWeavers.xml
  50. 25
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe.Abp.LocalizationManagement.Domain.Shared.csproj
  51. 29
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementDomainSharedModule.cs
  52. 10
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/LanguageConsts.cs
  53. 8
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/Localization/LocalizationManagementResource.cs
  54. 45
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/Localization/Resources/en.json
  55. 45
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/Localization/Resources/zh-Hans.json
  56. 9
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/ResourceConsts.cs
  57. 8
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/TextConsts.cs
  58. 37
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/TextDifference.cs
  59. 22
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/TextEto.cs
  60. 3
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/FodyWeavers.xml
  61. 20
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe.Abp.LocalizationManagement.Domain.csproj
  62. 41
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementDomainModule.cs
  63. 14
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/ILanguageRepository.cs
  64. 17
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/IResourceRepository.cs
  65. 43
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/ITextRepository.cs
  66. 53
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/Language.cs
  67. 10
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/LocalizationDbProperties.cs
  68. 11
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/LocalizationManagementDomainMapperProfile.cs
  69. 85
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/LocalizationStore.cs
  70. 52
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/LocalizationSynchronizer.cs
  71. 29
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/Resource.cs
  72. 36
      modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/Text.cs
  73. 3
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/FodyWeavers.xml
  74. 19
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore.csproj
  75. 23
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/AbpLocalizationManagementEntityFrameworkCoreModule.cs
  76. 32
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/EfCoreLanguageRepository.cs
  77. 31
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/EfCoreResourceRepository.cs
  78. 132
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/EfCoreTextRepository.cs
  79. 13
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/ILocalizationDbContext.cs
  80. 25
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/LocalizationDbContext.cs
  81. 98
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/LocalizationDbContextModelBuilderExtensions.cs
  82. 17
      modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/LocalizationModelBuilderConfigurationOptions.cs
  83. 3
      modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/FodyWeavers.xml
  84. 19
      modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe.Abp.LocalizationManagement.HttpApi.csproj
  85. 41
      modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementHttpApiModule.cs
  86. 61
      modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe/Abp/LocalizationManagement/LanguageController.cs
  87. 61
      modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe/Abp/LocalizationManagement/ResourceController.cs
  88. 60
      modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe/Abp/LocalizationManagement/TextController.cs
  89. 6
      modules/mvc/Sanhe.Abp.AspNetCore.Mvc.Wrapper/Sanhe/Abp/AspNetCore/Mvc/Wrapper/Filters/AbpWrapResultFilter.cs
  90. 2
      services/book-store/Data/IdentityServerDataSeedContributor.cs

65
Sanhe.Abp.Framework.sln

@ -21,21 +21,40 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "book-store", "book-store",
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BookStore", "services\book-store\BookStore.csproj", "{64178F61-A488-4182-A409-C32AE51E33A1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BookStore", "services\book-store\BookStore.csproj", "{64178F61-A488-4182-A409-C32AE51E33A1}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.ExceptionHandling", "modules\common\Sanhe.Abp.ExceptionHandling\Sanhe.Abp.ExceptionHandling.csproj", "{FBEB7703-CF8A-4E5B-B1C7-ED9DC1ABC7BD}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sanhe.Abp.ExceptionHandling", "modules\common\Sanhe.Abp.ExceptionHandling\Sanhe.Abp.ExceptionHandling.csproj", "{FBEB7703-CF8A-4E5B-B1C7-ED9DC1ABC7BD}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.ExceptionHandling.Emailing", "modules\common\Sanhe.Abp.ExceptionHandling.Emailing\Sanhe.Abp.ExceptionHandling.Emailing.csproj", "{0692C2EA-7119-4065-8504-D7FDA70135A9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sanhe.Abp.ExceptionHandling.Emailing", "modules\common\Sanhe.Abp.ExceptionHandling.Emailing\Sanhe.Abp.ExceptionHandling.Emailing.csproj", "{0692C2EA-7119-4065-8504-D7FDA70135A9}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.Features.LimitValidation", "modules\common\Sanhe.Abp.Features.LimitValidation\Sanhe.Abp.Features.LimitValidation.csproj", "{BE246DD7-2DDB-4064-9017-7E1DD2E67195}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sanhe.Abp.Features.LimitValidation", "modules\common\Sanhe.Abp.Features.LimitValidation\Sanhe.Abp.Features.LimitValidation.csproj", "{BE246DD7-2DDB-4064-9017-7E1DD2E67195}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.Features.LimitValidation.Redis", "modules\common\Sanhe.Abp.Features.LimitValidation.Redis\Sanhe.Abp.Features.LimitValidation.Redis.csproj", "{A2BD1C66-505E-48BB-A356-38D74AA3AE0F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sanhe.Abp.Features.LimitValidation.Redis", "modules\common\Sanhe.Abp.Features.LimitValidation.Redis\Sanhe.Abp.Features.LimitValidation.Redis.csproj", "{A2BD1C66-505E-48BB-A356-38D74AA3AE0F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.Features.LimitValidation.Redis.Client", "modules\common\Sanhe.Abp.Features.LimitValidation.Redis.Client\Sanhe.Abp.Features.LimitValidation.Redis.Client.csproj", "{97DDB479-946C-489D-9089-6EAEBFEE97C6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sanhe.Abp.Features.LimitValidation.Redis.Client", "modules\common\Sanhe.Abp.Features.LimitValidation.Redis.Client\Sanhe.Abp.Features.LimitValidation.Redis.Client.csproj", "{97DDB479-946C-489D-9089-6EAEBFEE97C6}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution items", "solution items", "{8DAEBF3C-8948-44EF-AB7C-8662CCACD2C6}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution items", "solution items", "{8DAEBF3C-8948-44EF-AB7C-8662CCACD2C6}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.Localization.Dynamic", "modules\common\Sanhe.Abp.Localization.Dynamic\Sanhe.Abp.Localization.Dynamic.csproj", "{4006EECE-A268-4B46-AA4B-743AFB82A1EC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "localization-management", "localization-management", "{13AA8858-C832-4AAD-8B7D-C8AF879F39A7}"
ProjectSection(SolutionItems) = preProject
modules\localization-management\README.md = modules\localization-management\README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.LocalizationManagement.Application", "modules\localization-management\Sanhe.Abp.LocalizationManagement.Application\Sanhe.Abp.LocalizationManagement.Application.csproj", "{B76B1A6D-D756-40ED-BD87-AD8B319D708C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.LocalizationManagement.Domain.Shared", "modules\localization-management\Sanhe.Abp.LocalizationManagement.Domain.Shared\Sanhe.Abp.LocalizationManagement.Domain.Shared.csproj", "{B6293F8F-5B03-49A0-94A5-0D6778201AAD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.LocalizationManagement.Domain", "modules\localization-management\Sanhe.Abp.LocalizationManagement.Domain\Sanhe.Abp.LocalizationManagement.Domain.csproj", "{F7514BD9-2BC7-4FF1-A79A-EC5C161C2AC1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.LocalizationManagement.Application.Contracts", "modules\localization-management\Sanhe.Abp.LocalizationManagement.Application.Contracts\Sanhe.Abp.LocalizationManagement.Application.Contracts.csproj", "{53D8962F-E349-405D-831A-5E35B099F03B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.LocalizationManagement.EntityFrameworkCore", "modules\localization-management\Sanhe.Abp.LocalizationManagement.EntityFrameworkCore\Sanhe.Abp.LocalizationManagement.EntityFrameworkCore.csproj", "{E727B749-D1CA-44CA-BD86-D553A05C444F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sanhe.Abp.LocalizationManagement.HttpApi", "modules\localization-management\Sanhe.Abp.LocalizationManagement.HttpApi\Sanhe.Abp.LocalizationManagement.HttpApi.csproj", "{50B3735E-750E-483F-9A9B-F4CAE1657390}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -74,6 +93,34 @@ Global
{97DDB479-946C-489D-9089-6EAEBFEE97C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {97DDB479-946C-489D-9089-6EAEBFEE97C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{97DDB479-946C-489D-9089-6EAEBFEE97C6}.Release|Any CPU.ActiveCfg = Release|Any CPU {97DDB479-946C-489D-9089-6EAEBFEE97C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{97DDB479-946C-489D-9089-6EAEBFEE97C6}.Release|Any CPU.Build.0 = Release|Any CPU {97DDB479-946C-489D-9089-6EAEBFEE97C6}.Release|Any CPU.Build.0 = Release|Any CPU
{4006EECE-A268-4B46-AA4B-743AFB82A1EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4006EECE-A268-4B46-AA4B-743AFB82A1EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4006EECE-A268-4B46-AA4B-743AFB82A1EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4006EECE-A268-4B46-AA4B-743AFB82A1EC}.Release|Any CPU.Build.0 = Release|Any CPU
{B76B1A6D-D756-40ED-BD87-AD8B319D708C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B76B1A6D-D756-40ED-BD87-AD8B319D708C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B76B1A6D-D756-40ED-BD87-AD8B319D708C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B76B1A6D-D756-40ED-BD87-AD8B319D708C}.Release|Any CPU.Build.0 = Release|Any CPU
{B6293F8F-5B03-49A0-94A5-0D6778201AAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6293F8F-5B03-49A0-94A5-0D6778201AAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6293F8F-5B03-49A0-94A5-0D6778201AAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6293F8F-5B03-49A0-94A5-0D6778201AAD}.Release|Any CPU.Build.0 = Release|Any CPU
{F7514BD9-2BC7-4FF1-A79A-EC5C161C2AC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7514BD9-2BC7-4FF1-A79A-EC5C161C2AC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7514BD9-2BC7-4FF1-A79A-EC5C161C2AC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7514BD9-2BC7-4FF1-A79A-EC5C161C2AC1}.Release|Any CPU.Build.0 = Release|Any CPU
{53D8962F-E349-405D-831A-5E35B099F03B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53D8962F-E349-405D-831A-5E35B099F03B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53D8962F-E349-405D-831A-5E35B099F03B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53D8962F-E349-405D-831A-5E35B099F03B}.Release|Any CPU.Build.0 = Release|Any CPU
{E727B749-D1CA-44CA-BD86-D553A05C444F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E727B749-D1CA-44CA-BD86-D553A05C444F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E727B749-D1CA-44CA-BD86-D553A05C444F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E727B749-D1CA-44CA-BD86-D553A05C444F}.Release|Any CPU.Build.0 = Release|Any CPU
{50B3735E-750E-483F-9A9B-F4CAE1657390}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{50B3735E-750E-483F-9A9B-F4CAE1657390}.Debug|Any CPU.Build.0 = Debug|Any CPU
{50B3735E-750E-483F-9A9B-F4CAE1657390}.Release|Any CPU.ActiveCfg = Release|Any CPU
{50B3735E-750E-483F-9A9B-F4CAE1657390}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -91,6 +138,14 @@ Global
{BE246DD7-2DDB-4064-9017-7E1DD2E67195} = {2A768109-31B7-4C52-928C-3023DAB9F254} {BE246DD7-2DDB-4064-9017-7E1DD2E67195} = {2A768109-31B7-4C52-928C-3023DAB9F254}
{A2BD1C66-505E-48BB-A356-38D74AA3AE0F} = {2A768109-31B7-4C52-928C-3023DAB9F254} {A2BD1C66-505E-48BB-A356-38D74AA3AE0F} = {2A768109-31B7-4C52-928C-3023DAB9F254}
{97DDB479-946C-489D-9089-6EAEBFEE97C6} = {2A768109-31B7-4C52-928C-3023DAB9F254} {97DDB479-946C-489D-9089-6EAEBFEE97C6} = {2A768109-31B7-4C52-928C-3023DAB9F254}
{4006EECE-A268-4B46-AA4B-743AFB82A1EC} = {2A768109-31B7-4C52-928C-3023DAB9F254}
{13AA8858-C832-4AAD-8B7D-C8AF879F39A7} = {F5F5D604-531B-4B57-A88E-C9C5CEEC55D7}
{B76B1A6D-D756-40ED-BD87-AD8B319D708C} = {13AA8858-C832-4AAD-8B7D-C8AF879F39A7}
{B6293F8F-5B03-49A0-94A5-0D6778201AAD} = {13AA8858-C832-4AAD-8B7D-C8AF879F39A7}
{F7514BD9-2BC7-4FF1-A79A-EC5C161C2AC1} = {13AA8858-C832-4AAD-8B7D-C8AF879F39A7}
{53D8962F-E349-405D-831A-5E35B099F03B} = {13AA8858-C832-4AAD-8B7D-C8AF879F39A7}
{E727B749-D1CA-44CA-BD86-D553A05C444F} = {13AA8858-C832-4AAD-8B7D-C8AF879F39A7}
{50B3735E-750E-483F-9A9B-F4CAE1657390} = {13AA8858-C832-4AAD-8B7D-C8AF879F39A7}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AB69BFDE-9DDB-4D16-8CB8-72472C0319CD} SolutionGuid = {AB69BFDE-9DDB-4D16-8CB8-72472C0319CD}

3
modules/common/Sanhe.Abp.Localization.Dynamic/FodyWeavers.xml

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

38
modules/common/Sanhe.Abp.Localization.Dynamic/README.md

@ -0,0 +1,38 @@
# Sanhe.Abp.Localization.Dynamic
动态本地化提供者组件,添加动态提供者可实现运行时替换本地化文本
需要实现 ILocalizationStore 接口
LocalizationManagement项目提供支持
## 配置使用
```csharp
[DependsOn(typeof(AbpLocalizationDynamicModule))]
public class YouProjectModule : AbpModule
{
// other
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<YouProjectResource>()
.AddDynamic(); // 添加动态本地化文档支持
// 添加所有资源的动态文档支持,将监听所有的资源包文档变更事件
// options.Resources.AddDynamic();
// 添加所有资源的动态文档支持,忽略 IdentityResource 资源
// options.Resources.AddDynamic(typeof(IdentityResource));
});
}
}
```
## 注意事项
动态资源在启动时加载,如果通过LocalizationManagement模块查询,可能受后端存储资源体量影响整体启动时间
详情见: [DynamicLocalizationInitializeService](./Sanhe/Abp/Localization/Dynamic/DynamicLocalizationInitializeService.cs#L25-L38)

15
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe.Abp.Localization.Dynamic.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>
<PackageReference Include="Volo.Abp.EventBus" Version="$(VoloAbpVersion)" />
<PackageReference Include="Volo.Abp.Localization" Version="$(VoloAbpVersion)" />
</ItemGroup>
</Project>

17
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/AbpLocalizationDynamicModule.cs

@ -0,0 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EventBus;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Sanhe.Abp.Localization.Dynamic;
[DependsOn(
typeof(AbpEventBusModule),
typeof(AbpLocalizationModule))]
public class AbpLocalizationDynamicModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHostedService<DynamicLocalizationInitializeService>();
}
}

22
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/AbpLocalizationDynamicOptions.cs

@ -0,0 +1,22 @@
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic;
public class AbpLocalizationDynamicOptions
{
internal LocalizationDictionary LocalizationDictionary { get; }
public AbpLocalizationDynamicOptions()
{
LocalizationDictionary = new LocalizationDictionary();
}
internal void AddOrUpdate(string resourceName, Dictionary<string, ILocalizationDictionary> dictionaries)
{
var currentDictionaries = LocalizationDictionary
.GetOrAdd(resourceName, () => new Dictionary<string, ILocalizationDictionary>());
currentDictionaries.AddIfNotContains(dictionaries);
}
}

30
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/DefaultLocalizationStore.cs

@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic;
public class DefaultLocalizationStore : ILocalizationStore, ITransientDependency
{
public DefaultLocalizationStore()
{
}
public Task<List<LanguageInfo>> GetLanguageListAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(new List<LanguageInfo>());
}
public Task<Dictionary<string, ILocalizationDictionary>> GetLocalizationDictionaryAsync(string resourceName, CancellationToken cancellationToken = default)
{
return Task.FromResult(new Dictionary<string, ILocalizationDictionary>());
}
public Task<bool> ResourceExistsAsync(string resourceName, CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
}

41
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/DynamicLanguageProvider.cs

@ -0,0 +1,41 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic;
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
[ExposeServices(
typeof(ILanguageProvider),
typeof(DynamicLanguageProvider))]
public class DynamicLanguageProvider : ILanguageProvider
{
protected ILocalizationStore Store { get; }
protected AbpLocalizationOptions Options { get; }
public DynamicLanguageProvider(
ILocalizationStore store,
IOptions<AbpLocalizationOptions> options)
{
Store = store;
Options = options.Value;
}
public async virtual Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync()
{
var languages = await Store.GetLanguageListAsync();
if (!languages.Any())
{
return Options.Languages;
}
return languages
.Distinct(new LanguageInfoComparer())
.ToList();
}
}

47
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/DynamicLocalizationInitializeService.cs

@ -0,0 +1,47 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic;
public class DynamicLocalizationInitializeService : BackgroundService
{
protected ILocalizationStore Store { get; }
protected AbpLocalizationOptions LocalizationOptions { get; }
protected AbpLocalizationDynamicOptions DynamicOptions { get; }
public DynamicLocalizationInitializeService(
ILocalizationStore store,
IOptions<AbpLocalizationOptions> localizationOptions,
IOptions<AbpLocalizationDynamicOptions> dynamicOptions)
{
Store = store;
DynamicOptions = dynamicOptions.Value;
LocalizationOptions = localizationOptions.Value;
}
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
foreach (var resource in LocalizationOptions.Resources)
{
foreach (var contributor in resource.Value.Contributors)
{
if (contributor.GetType().IsAssignableFrom(typeof(DynamicLocalizationResourceContributor)))
{
var resourceLocalizationDict = await Store
.GetLocalizationDictionaryAsync(
resource.Value.ResourceName,
stoppingToken);
DynamicOptions.AddOrUpdate(resource.Value.ResourceName, resourceLocalizationDict);
}
}
}
}
catch (OperationCanceledException) { } // 忽略此异常
}
}

40
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/DynamicLocalizationResourceContributor.cs

@ -0,0 +1,40 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic;
public class DynamicLocalizationResourceContributor : ILocalizationResourceContributor
{
private readonly string _resourceName;
private AbpLocalizationDynamicOptions _options;
public DynamicLocalizationResourceContributor(string resourceName)
{
_resourceName = resourceName;
}
public virtual void Initialize(LocalizationResourceInitializationContext context)
{
_options = context.ServiceProvider.GetService<IOptions<AbpLocalizationDynamicOptions>>().Value;
}
public virtual void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
GetDictionaries().GetOrDefault(cultureName)?.Fill(dictionary);
}
public virtual LocalizedString GetOrNull(string cultureName, string name)
{
return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name);
}
protected virtual Dictionary<string, ILocalizationDictionary> GetDictionaries()
{
return _options.LocalizationDictionary
.GetOrAdd(_resourceName, () => new Dictionary<string, ILocalizationDictionary>());
}
}

37
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/ILocalizationStore.cs

@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic;
public interface ILocalizationStore
{
/// <summary>
/// 获取语言列表
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<LanguageInfo>> GetLanguageListAsync(
CancellationToken cancellationToken = default);
/// <summary>
/// 资源是否存在
/// </summary>
/// <param name="resourceName">资源名称</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> ResourceExistsAsync(
string resourceName,
CancellationToken cancellationToken = default);
/// <summary>
/// 获取当前资源下的本地化字典
/// </summary>
/// <param name="resourceName">资源名称</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Dictionary<string, ILocalizationDictionary>> GetLocalizationDictionaryAsync(
string resourceName,
CancellationToken cancellationToken = default);
}

22
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LanguageInfoComparer.cs

@ -0,0 +1,22 @@
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic;
public class LanguageInfoComparer : IEqualityComparer<LanguageInfo>
{
public bool Equals(LanguageInfo x, LanguageInfo y)
{
if (x == null || y == null)
{
return false;
}
return x.CultureName.Equals(y.CultureName);
}
public int GetHashCode(LanguageInfo obj)
{
return obj?.CultureName.GetHashCode() ?? GetHashCode();
}
}

58
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LocalizationCacheItem.cs

@ -0,0 +1,58 @@
using System.Collections.Generic;
namespace Sanhe.Abp.Localization.Dynamic;
/// <summary>
/// 本地化缓存项
/// </summary>
public class LocalizationCacheItem
{
public string Resource { get; set; }
public string Culture { get; set; }
public List<LocalizationText> Texts { get; set; }
public LocalizationCacheItem()
{
Texts = new List<LocalizationText>();
}
public LocalizationCacheItem(
string resource,
string culture,
List<LocalizationText> texts)
{
Resource = resource;
Culture = culture;
Texts = texts;
}
public static string NormalizeKey(
string resource,
string culture)
{
return $"p:Localization,r:{resource},c:{culture}";
}
}
public class LocalizationText
{
public string Key { get; set; }
public string Value { get; set; }
public LocalizationText()
{
}
public LocalizationText(
string key,
string value)
{
Key = key;
Value = value;
}
}

12
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LocalizationDictionary.cs

@ -0,0 +1,12 @@
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic;
/// <summary>
/// 用于查找本地化字符串的字典。
/// </summary>
public class LocalizationDictionary : Dictionary<string, Dictionary<string, ILocalizationDictionary>>
{
}

75
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LocalizationResetSynchronizer.cs

@ -0,0 +1,75 @@
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Localization;
namespace Sanhe.Abp.Localization.Dynamic
{
internal class LocalizationResetSynchronizer :
IDistributedEventHandler<LocalizedStringCacheResetEventData>,
ITransientDependency
{
private readonly AbpLocalizationDynamicOptions _options;
public LocalizationResetSynchronizer(
IOptions<AbpLocalizationDynamicOptions> options)
{
_options = options.Value;
}
public virtual Task HandleEventAsync(LocalizedStringCacheResetEventData eventData)
{
var dictionaries = GetDictionaries(eventData.ResourceName);
if (!dictionaries.ContainsKey(eventData.CultureName))
{
// TODO: 需要处理 data.Key data.Value 空引用
var dictionary = new Dictionary<string, LocalizedString>();
dictionary.Add(eventData.Key, new LocalizedString(eventData.Key, eventData.Value.NormalizeLineEndings()));
var newLocalizationDictionary = new StaticLocalizationDictionary(eventData.CultureName, dictionary);
dictionaries.Add(eventData.CultureName, newLocalizationDictionary);
}
else
{
// 取出当前的缓存写入到新字典进行处理
var nowLocalizationDictionary = dictionaries[eventData.CultureName];
var dictionary = new Dictionary<string, LocalizedString>();
nowLocalizationDictionary.Fill(dictionary);
var existsKey = dictionary.ContainsKey(eventData.Key);
if (!existsKey)
{
// 如果不存在,则新增
dictionary.Add(eventData.Key, new LocalizedString(eventData.Key, eventData.Value.NormalizeLineEndings()));
}
else if (existsKey && eventData.IsDeleted)
{
// 如果删掉了本地化的节点,删掉当前的缓存
dictionary.Remove(eventData.Key);
}
var newLocalizationDictionary = new StaticLocalizationDictionary(eventData.CultureName, dictionary);
if (newLocalizationDictionary != null)
{
// 重新赋值变更过的缓存
dictionaries[eventData.CultureName] = newLocalizationDictionary;
}
}
return Task.CompletedTask;
}
protected virtual Dictionary<string, ILocalizationDictionary> GetDictionaries(string resourceName)
{
return _options.LocalizationDictionary
.GetOrAdd(resourceName, () => new Dictionary<string, ILocalizationDictionary>());
}
}
}

44
modules/common/Sanhe.Abp.Localization.Dynamic/Sanhe/Abp/Localization/Dynamic/LocalizedStringCacheResetEventData.cs

@ -0,0 +1,44 @@
namespace Sanhe.Abp.Localization.Dynamic;
public class LocalizedStringCacheResetEventData
{
/// <summary>
/// 是否删除
/// </summary>
public bool IsDeleted { get; set; }
/// <summary>
/// 资源名
/// </summary>
public string ResourceName { get; set; }
/// <summary>
/// 文化名称
/// </summary>
public string CultureName { get; set; }
/// <summary>
/// 键
/// </summary>
public string Key { get; set; }
/// <summary>
/// 值
/// </summary>
public string Value { get; set; }
public LocalizedStringCacheResetEventData()
{
}
public LocalizedStringCacheResetEventData(
string resourceName,
string cultureName,
string key,
string value)
{
ResourceName = resourceName;
CultureName = cultureName;
Key = key;
Value = value;
IsDeleted = false;
}
}

42
modules/common/Sanhe.Abp.Localization.Dynamic/Volo/Abp/Localization/LocalizationResourceDictionaryExtensions.cs

@ -0,0 +1,42 @@
using Sanhe.Abp.Localization.Dynamic;
using System;
using System.Linq;
namespace Volo.Abp.Localization
{
public static class LocalizationResourceDictionaryExtensions
{
public static LocalizationResourceDictionary AddDynamic(
this LocalizationResourceDictionary resources,
params Type[] ignoreResourceTypes)
{
foreach (var resource in resources)
{
if (ShouldIgnoreType(resource.Key, ignoreResourceTypes))
{
continue;
}
if (ShouldIgnoreType(resource.Value))
{
continue;
}
resource.Value.AddDynamic();
}
return resources;
}
private static bool ShouldIgnoreType(Type resourceType, params Type[] ignoreResourceTypes)
{
if (ignoreResourceTypes == null)
{
return false;
}
return ignoreResourceTypes.Any(x => x == resourceType);
}
private static bool ShouldIgnoreType(LocalizationResource resource)
{
return resource.Contributors.Exists(x => x is DynamicLocalizationResourceContributor);
}
}
}

20
modules/common/Sanhe.Abp.Localization.Dynamic/Volo/Abp/Localization/LocalizationResourceExtensions.cs

@ -0,0 +1,20 @@
using JetBrains.Annotations;
using Sanhe.Abp.Localization.Dynamic;
namespace Volo.Abp.Localization
{
public static class DynamicLocalizationResourceExtensions
{
public static LocalizationResource AddDynamic(
[NotNull] this LocalizationResource localizationResource)
{
Check.NotNull(localizationResource, nameof(localizationResource));
localizationResource.Contributors.Add(
new DynamicLocalizationResourceContributor(
localizationResource.ResourceName));
return localizationResource;
}
}
}

39
modules/localization-management/README.md

@ -0,0 +1,39 @@
# Localization Management
本地化文档管理模块,因项目路径太长Windows系统不支持,项目目录取简称 lt
## 模块说明
### 基础模块
* [Sanhe.Abp.Localization.Dynamic](../common/Sanhe.Abp.Localization.Dynamic/Sanhe.Abp.Localization.Dynamic) 本地化扩展模块,增加 DynamicLocalizationResourceContributor 通过 ILocalizationStore 接口获取动态的本地化资源信息
* [Sanhe.Abp.LocalizationManagement.Domain.Shared](./Sanhe.Abp.LocalizationManagement.Domain.Shared) 领域层公共模块,定义了错误代码、本地化、模块设置
* [Sanhe.Abp.LocalizationManagement.Domain](./Sanhe.Abp.LocalizationManagement.Domain) 领域层模块,实现 ILocalizationStore 接口
* [Sanhe.Abp.LocalizationManagement.EntityFrameworkCore](./Sanhe.Abp.LocalizationManagement.EntityFrameworkCore) 数据访问层模块,集成EfCore
* [Sanhe.Abp.LocalizationManagement.Application.Contracts](./Sanhe.Abp.LocalizationManagement.Application.Contracts) 应用服务层公共模块,定义了管理本地化对象的外部接口、权限、功能限制策略
* [Sanhe.Abp.LocalizationManagement.Application](./Sanhe.Abp.LocalizationManagement.Application) 应用服务层实现,实现了本地化对象管理接口
* [Sanhe.Abp.LocalizationManagement.HttpApi](./Sanhe.Abp.LocalizationManagement.HttpApi) RestApi实现,实现了独立的对外RestApi接口
### 高阶模块
### 权限定义
* LocalizationManagement.Resource 授权对象是否允许访问资源
* LocalizationManagement.Resource.Create 授权对象是否允许创建资源
* LocalizationManagement.Resource.Update 授权对象是否允许修改资源
* LocalizationManagement.Resource.Delete 授权对象是否允许删除资源
* LocalizationManagement.Language 授权对象是否允许访问语言
* LocalizationManagement.Language.Create 授权对象是否允许创建语言
* LocalizationManagement.Language.Update 授权对象是否允许修改语言
* LocalizationManagement.Language.Delete 授权对象是否允许删除语言
* LocalizationManagement.Text 授权对象是否允许访问文档
* LocalizationManagement.Text.Create 授权对象是否允许创建文档
* LocalizationManagement.Text.Update 授权对象是否允许删除Oss对象
* LocalizationManagement.Text.Delete 授权对象是否允许下载Oss对象
### 功能定义
### 配置定义
## 更新日志

3
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/FodyWeavers.xml

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

20
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe.Abp.LocalizationManagement.Application.Contracts.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Authorization" Version="$(VoloAbpVersion)" />
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="$(VoloAbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sanhe.Abp.LocalizationManagement.Domain.Shared\Sanhe.Abp.LocalizationManagement.Domain.Shared.csproj" />
</ItemGroup>
</Project>

12
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementApplicationContractsModule.cs

@ -0,0 +1,12 @@
using Volo.Abp.Authorization;
using Volo.Abp.Modularity;
namespace Sanhe.Abp.LocalizationManagement;
[DependsOn(
typeof(AbpAuthorizationModule),
typeof(AbpLocalizationManagementDomainSharedModule))]
public class AbpLocalizationManagementApplicationContractsModule : AbpModule
{
}

24
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/CreateOrUpdateLanguageInput.cs

@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace Sanhe.Abp.LocalizationManagement;
public class CreateOrUpdateLanguageInput
{
public virtual bool Enable { get; set; }
[Required]
[DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxCultureNameLength))]
public string CultureName { get; set; }
[Required]
[DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxUiCultureNameLength))]
public string UiCultureName { get; set; }
[Required]
[DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxDisplayNameLength))]
public string DisplayName { get; set; }
[DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxFlagIconLength))]
public string FlagIcon { get; set; }
}

19
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/CreateOrUpdateResourceInput.cs

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace Sanhe.Abp.LocalizationManagement;
public class CreateOrUpdateResourceInput
{
public bool Enable { get; set; }
[Required]
[DynamicStringLength(typeof(ResourceConsts), nameof(ResourceConsts.MaxNameLength))]
public string Name { get; set; }
[DynamicStringLength(typeof(ResourceConsts), nameof(ResourceConsts.MaxDisplayNameLength))]
public string DisplayName { get; set; }
[DynamicStringLength(typeof(ResourceConsts), nameof(ResourceConsts.MaxDescriptionLength))]
public string Description { get; set; }
}

9
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/CreateOrUpdateTextInput.cs

@ -0,0 +1,9 @@
using Volo.Abp.Validation;
namespace Sanhe.Abp.LocalizationManagement;
public class CreateOrUpdateTextInput
{
[DynamicStringLength(typeof(TextConsts), nameof(TextConsts.MaxValueLength))]
public string Value { get; set; }
}

19
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/CreateTextInput.cs

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace Sanhe.Abp.LocalizationManagement;
public class CreateTextInput : CreateOrUpdateTextInput
{
[Required]
[DynamicStringLength(typeof(ResourceConsts), nameof(ResourceConsts.MaxNameLength))]
public string ResourceName { get; set; }
[Required]
[DynamicStringLength(typeof(TextConsts), nameof(TextConsts.MaxKeyLength))]
public string Key { get; set; }
[Required]
[DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxCultureNameLength))]
public string CultureName { get; set; }
}

8
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/GetLanguagesInput.cs

@ -0,0 +1,8 @@
using Volo.Abp.Application.Dtos;
namespace Sanhe.Abp.LocalizationManagement;
public class GetLanguagesInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
}

8
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/GetResourcesInput.cs

@ -0,0 +1,8 @@
using Volo.Abp.Application.Dtos;
namespace Sanhe.Abp.LocalizationManagement;
public class GetResourcesInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
}

19
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/GetTextByKeyInput.cs

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace Sanhe.Abp.LocalizationManagement;
public class GetTextByKeyInput
{
[Required]
[DynamicStringLength(typeof(TextConsts), nameof(TextConsts.MaxKeyLength))]
public string Key { get; set; }
[Required]
[DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxCultureNameLength))]
public string CultureName { get; set; }
[Required]
[DynamicStringLength(typeof(ResourceConsts), nameof(ResourceConsts.MaxNameLength))]
public string ResourceName { get; set; }
}

23
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/GetTextsInput.cs

@ -0,0 +1,23 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Validation;
namespace Sanhe.Abp.LocalizationManagement;
public class GetTextsInput : PagedAndSortedResultRequestDto
{
[Required]
[DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxCultureNameLength))]
public string CultureName { get; set; }
[Required]
[DynamicStringLength(typeof(LanguageConsts), nameof(LanguageConsts.MaxCultureNameLength))]
public string TargetCultureName { get; set; }
[DynamicStringLength(typeof(ResourceConsts), nameof(ResourceConsts.MaxNameLength))]
public string ResourceName { get; set; }
public bool? OnlyNull { get; set; }
public string Filter { get; set; }
}

17
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/ILanguageAppService.cs

@ -0,0 +1,17 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Sanhe.Abp.LocalizationManagement;
public interface ILanguageAppService :
ICrudAppService<
LanguageDto,
Guid,
GetLanguagesInput,
CreateOrUpdateLanguageInput,
CreateOrUpdateLanguageInput>
{
Task<ListResultDto<LanguageDto>> GetAllAsync();
}

17
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/IResourceAppService.cs

@ -0,0 +1,17 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Sanhe.Abp.LocalizationManagement;
public interface IResourceAppService :
ICrudAppService<
ResourceDto,
Guid,
GetResourcesInput,
CreateOrUpdateResourceInput,
CreateOrUpdateResourceInput>
{
Task<ListResultDto<ResourceDto>> GetAllAsync();
}

16
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/ITextAppService.cs

@ -0,0 +1,16 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace Sanhe.Abp.LocalizationManagement;
public interface ITextAppService :
ICrudAppService<
TextDto,
TextDifferenceDto,
int,
GetTextsInput,
CreateTextInput,
UpdateTextInput>
{
Task<TextDto> GetByCultureKeyAsync(GetTextByKeyInput input);
}

13
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/LanguageDto.cs

@ -0,0 +1,13 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Sanhe.Abp.LocalizationManagement;
public class LanguageDto : AuditedEntityDto<Guid>
{
public bool Enable { get; set; }
public string CultureName { get; set; }
public string UiCultureName { get; set; }
public string DisplayName { get; set; }
public string FlagIcon { get; set; }
}

6
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/LocalizationRemoteServiceConsts.cs

@ -0,0 +1,6 @@
namespace Sanhe.Abp.LocalizationManagement;
public static class LocalizationRemoteServiceConsts
{
public const string RemoteServiceName = "LocalizationManagement";
}

72
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/Permissions/LocalizationManagementPermissionDefinitionProvider.cs

@ -0,0 +1,72 @@
using Sanhe.Abp.LocalizationManagement.Localization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
namespace Sanhe.Abp.LocalizationManagement.Permissions;
public class LocalizationManagementPermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var permissionGroup = context.AddGroup(
LocalizationManagementPermissions.GroupName,
L("Permissions:LocalizationManagement"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
var resourcePermission = permissionGroup.AddPermission(
LocalizationManagementPermissions.Resource.Default,
L("Permissions:Resource"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
resourcePermission.AddChild(
LocalizationManagementPermissions.Resource.Create,
L("Permissions:Create"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
resourcePermission.AddChild(
LocalizationManagementPermissions.Resource.Update,
L("Permissions:Update"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
resourcePermission.AddChild(
LocalizationManagementPermissions.Resource.Delete,
L("Permissions:Delete"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
var languagePermission = permissionGroup.AddPermission(
LocalizationManagementPermissions.Language.Default,
L("Permissions:Language"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
languagePermission.AddChild(
LocalizationManagementPermissions.Language.Create,
L("Permissions:Create"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
languagePermission.AddChild(
LocalizationManagementPermissions.Language.Update,
L("Permissions:Update"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
languagePermission.AddChild(
LocalizationManagementPermissions.Language.Delete,
L("Permissions:Delete"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
var textPermission = permissionGroup.AddPermission(
LocalizationManagementPermissions.Text.Default,
L("Permissions:Text"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
textPermission.AddChild(
LocalizationManagementPermissions.Text.Create,
L("Permissions:Create"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
textPermission.AddChild(
LocalizationManagementPermissions.Text.Update,
L("Permissions:Update"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
textPermission.AddChild(
LocalizationManagementPermissions.Text.Delete,
L("Permissions:Delete"),
Volo.Abp.MultiTenancy.MultiTenancySides.Host);
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<LocalizationManagementResource>(name);
}
}

39
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/Permissions/LocalizationManagementPermissions.cs

@ -0,0 +1,39 @@
namespace Sanhe.Abp.LocalizationManagement.Permissions;
public static class LocalizationManagementPermissions
{
public const string GroupName = "LocalizationManagement";
public class Resource
{
public const string Default = GroupName + ".Resource";
public const string Create = Default + ".Create";
public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete";
}
public class Language
{
public const string Default = GroupName + ".Language";
public const string Create = Default + ".Create";
public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete";
}
public class Text
{
public const string Default = GroupName + ".Text";
public const string Create = Default + ".Create";
public const string Update = Default + ".Update";
public const string Delete = Default + ".Delete";
}
}

12
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/ResourceDto.cs

@ -0,0 +1,12 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Sanhe.Abp.LocalizationManagement;
public class ResourceDto : AuditedEntityDto<Guid>
{
public bool Enable { get; set; }
public string Name { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
}

13
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/TextDifferenceDto.cs

@ -0,0 +1,13 @@
using Volo.Abp.Application.Dtos;
namespace Sanhe.Abp.LocalizationManagement;
public class TextDifferenceDto : EntityDto<int>
{
public string CultureName { get; set; }
public string Key { get; set; }
public string Value { get; set; }
public string ResourceName { get; set; }
public string TargetCultureName { get; set; }
public string TargetValue { get; set; }
}

11
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/TextDto.cs

@ -0,0 +1,11 @@
using Volo.Abp.Application.Dtos;
namespace Sanhe.Abp.LocalizationManagement;
public class TextDto : EntityDto<int>
{
public string Key { get; set; }
public string Value { get; set; }
public string CultureName { get; set; }
public string ResourceName { get; set; }
}

5
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application.Contracts/Sanhe/Abp/LocalizationManagement/UpdateTextInput.cs

@ -0,0 +1,5 @@
namespace Sanhe.Abp.LocalizationManagement;
public class UpdateTextInput : CreateOrUpdateTextInput
{
}

3
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/FodyWeavers.xml

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

20
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe.Abp.LocalizationManagement.Application.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(VoloAbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sanhe.Abp.LocalizationManagement.Domain\Sanhe.Abp.LocalizationManagement.Domain.csproj" />
<ProjectReference Include="..\Sanhe.Abp.LocalizationManagement.Application.Contracts\Sanhe.Abp.LocalizationManagement.Application.Contracts.csproj" />
</ItemGroup>
</Project>

23
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementApplicationModule.cs

@ -0,0 +1,23 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
namespace Sanhe.Abp.LocalizationManagement;
[DependsOn(
typeof(AbpDddApplicationModule),
typeof(AbpLocalizationManagementDomainModule),
typeof(AbpLocalizationManagementApplicationContractsModule))]
public class AbpLocalizationManagementApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<AbpLocalizationManagementApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<LocalizationManagementApplicationMapperProfile>(validate: true);
});
}
}

70
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/LanguageAppService.cs

@ -0,0 +1,70 @@
using Sanhe.Abp.LocalizationManagement.Permissions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Sanhe.Abp.LocalizationManagement;
public class LanguageAppService : CrudAppService<
Language,
LanguageDto,
Guid,
GetLanguagesInput,
CreateOrUpdateLanguageInput,
CreateOrUpdateLanguageInput>, ILanguageAppService
{
public LanguageAppService(ILanguageRepository repository) : base(repository)
{
GetPolicyName = LocalizationManagementPermissions.Language.Default;
GetListPolicyName = LocalizationManagementPermissions.Language.Default;
CreatePolicyName = LocalizationManagementPermissions.Language.Create;
UpdatePolicyName = LocalizationManagementPermissions.Language.Update;
DeletePolicyName = LocalizationManagementPermissions.Language.Delete;
}
public async virtual Task<ListResultDto<LanguageDto>> GetAllAsync()
{
await CheckGetListPolicyAsync();
var languages = await Repository.GetListAsync();
return new ListResultDto<LanguageDto>(
ObjectMapper.Map<List<Language>, List<LanguageDto>>(languages));
}
protected override Language MapToEntity(CreateOrUpdateLanguageInput createInput)
{
return new Language(
createInput.CultureName,
createInput.UiCultureName,
createInput.DisplayName,
createInput.FlagIcon)
{
Enable = createInput.Enable
};
}
protected override void MapToEntity(CreateOrUpdateLanguageInput updateInput, Language entity)
{
if (!string.Equals(entity.FlagIcon, updateInput.FlagIcon, StringComparison.InvariantCultureIgnoreCase))
{
entity.FlagIcon = updateInput.FlagIcon;
}
entity.ChangeCulture(updateInput.CultureName, updateInput.UiCultureName, updateInput.DisplayName);
entity.Enable = updateInput.Enable;
}
protected async override Task<IQueryable<Language>> CreateFilteredQueryAsync(GetLanguagesInput input)
{
var query = await base.CreateFilteredQueryAsync(input);
query = query.WhereIf(!input.Filter.IsNullOrWhiteSpace(),
x => x.CultureName.Contains(input.Filter) || x.UiCultureName.Contains(input.Filter) ||
x.DisplayName.Contains(input.Filter));
return query;
}
}

14
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/LocalizationManagementApplicationMapperProfile.cs

@ -0,0 +1,14 @@
using AutoMapper;
namespace Sanhe.Abp.LocalizationManagement;
public class LocalizationManagementApplicationMapperProfile : Profile
{
public LocalizationManagementApplicationMapperProfile()
{
CreateMap<Language, LanguageDto>();
CreateMap<Resource, ResourceDto>();
CreateMap<Text, TextDto>();
CreateMap<TextDifference, TextDifferenceDto>();
}
}

75
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/ResourceAppService.cs

@ -0,0 +1,75 @@
using Sanhe.Abp.LocalizationManagement.Permissions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Sanhe.Abp.LocalizationManagement;
public class ResourceAppService : CrudAppService<
Resource,
ResourceDto,
Guid,
GetResourcesInput,
CreateOrUpdateResourceInput,
CreateOrUpdateResourceInput>, IResourceAppService
{
public ResourceAppService(IResourceRepository repository) : base(repository)
{
GetPolicyName = LocalizationManagementPermissions.Resource.Default;
GetListPolicyName = LocalizationManagementPermissions.Resource.Default;
CreatePolicyName = LocalizationManagementPermissions.Resource.Create;
UpdatePolicyName = LocalizationManagementPermissions.Resource.Update;
DeletePolicyName = LocalizationManagementPermissions.Resource.Delete;
}
public async virtual Task<ListResultDto<ResourceDto>> GetAllAsync()
{
await CheckGetListPolicyAsync();
var resources = await Repository.GetListAsync();
return new ListResultDto<ResourceDto>(
ObjectMapper.Map<List<Resource>, List<ResourceDto>>(resources));
}
protected override Resource MapToEntity(CreateOrUpdateResourceInput createInput)
{
return new Resource(
createInput.Name,
createInput.DisplayName,
createInput.Description)
{
Enable = createInput.Enable
};
}
protected override void MapToEntity(CreateOrUpdateResourceInput updateInput, Resource entity)
{
if (!string.Equals(entity.Name, updateInput.Name, StringComparison.InvariantCultureIgnoreCase))
{
entity.Name = updateInput.Name;
}
if (!string.Equals(entity.DisplayName, updateInput.DisplayName, StringComparison.InvariantCultureIgnoreCase))
{
entity.DisplayName = updateInput.DisplayName;
}
if (!string.Equals(entity.Description, updateInput.Description, StringComparison.InvariantCultureIgnoreCase))
{
entity.Description = updateInput.Description;
}
entity.Enable = updateInput.Enable;
}
protected async override Task<IQueryable<Resource>> CreateFilteredQueryAsync(GetResourcesInput input)
{
var query = await base.CreateFilteredQueryAsync(input);
query = query.WhereIf(!input.Filter.IsNullOrWhiteSpace(),
x => x.Name.Contains(input.Filter) || x.DisplayName.Contains(input.Filter));
return query;
}
}

71
modules/localization-management/Sanhe.Abp.LocalizationManagement.Application/Sanhe/Abp/LocalizationManagement/TextAppService.cs

@ -0,0 +1,71 @@
using Sanhe.Abp.LocalizationManagement.Permissions;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Sanhe.Abp.LocalizationManagement;
public class TextAppService : CrudAppService<
Text,
TextDto,
TextDifferenceDto,
int,
GetTextsInput,
CreateTextInput,
UpdateTextInput>, ITextAppService
{
private readonly ITextRepository _textRepository;
public TextAppService(ITextRepository repository) : base(repository)
{
_textRepository = repository;
GetPolicyName = LocalizationManagementPermissions.Text.Default;
GetListPolicyName = LocalizationManagementPermissions.Text.Default;
CreatePolicyName = LocalizationManagementPermissions.Text.Create;
UpdatePolicyName = LocalizationManagementPermissions.Text.Update;
DeletePolicyName = LocalizationManagementPermissions.Text.Delete;
}
public async virtual Task<TextDto> GetByCultureKeyAsync(GetTextByKeyInput input)
{
await CheckGetPolicyAsync();
var text = await _textRepository.GetByCultureKeyAsync(
input.ResourceName, input.CultureName, input.Key);
return await MapToGetOutputDtoAsync(text);
}
public async override Task<PagedResultDto<TextDifferenceDto>> GetListAsync(GetTextsInput input)
{
await CheckGetListPolicyAsync();
var count = await _textRepository.GetDifferenceCountAsync(
input.CultureName, input.TargetCultureName,
input.ResourceName, input.OnlyNull, input.Filter);
var texts = await _textRepository.GetDifferencePagedListAsync(
input.CultureName, input.TargetCultureName,
input.ResourceName, input.OnlyNull, input.Filter,
input.Sorting, input.SkipCount, input.MaxResultCount);
return new PagedResultDto<TextDifferenceDto>(count,
ObjectMapper.Map<List<TextDifference>, List<TextDifferenceDto>>(texts));
}
protected override Text MapToEntity(CreateTextInput createInput)
{
return new Text(
createInput.ResourceName,
createInput.CultureName,
createInput.Key,
createInput.Value);
}
protected override void MapToEntity(UpdateTextInput updateInput, Text entity)
{
entity.SetValue(updateInput.Value);
}
}

3
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/FodyWeavers.xml

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

25
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe.Abp.LocalizationManagement.Domain.Shared.csproj

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="Sanhe\Abp\LocalizationManagement\Localization\Resources\en.json" />
<None Remove="Sanhe\Abp\LocalizationManagement\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Sanhe\Abp\LocalizationManagement\Localization\Resources\en.json" />
<EmbeddedResource Include="Sanhe\Abp\LocalizationManagement\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Validation" Version="$(VoloAbpVersion)" />
<PackageReference Include="Volo.Abp.Localization" Version="$(VoloAbpVersion)" />
</ItemGroup>
</Project>

29
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementDomainSharedModule.cs

@ -0,0 +1,29 @@
using Sanhe.Abp.LocalizationManagement.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Validation;
using Volo.Abp.VirtualFileSystem;
namespace Sanhe.Abp.LocalizationManagement
{
[DependsOn(
typeof(AbpValidationModule),
typeof(AbpLocalizationModule))]
public class AbpLocalizationManagementDomainSharedModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpLocalizationManagementDomainSharedModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<LocalizationManagementResource>("en")
.AddVirtualJson("/Sanhe/Abp/LocalizationManagement/Localization/Resources");
});
}
}
}

10
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/LanguageConsts.cs

@ -0,0 +1,10 @@
namespace Sanhe.Abp.LocalizationManagement
{
public static class LanguageConsts
{
public static int MaxCultureNameLength { get; set; } = 20;
public static int MaxUiCultureNameLength { get; set; } = 20;
public static int MaxDisplayNameLength { get; set; } = 64;
public static int MaxFlagIconLength { get; set; } = 30;
}
}

8
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/Localization/LocalizationManagementResource.cs

@ -0,0 +1,8 @@
using Volo.Abp.Localization;
namespace Sanhe.Abp.LocalizationManagement.Localization;
[LocalizationResourceName("LocalizationManagement")]
public class LocalizationManagementResource
{
}

45
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/Localization/Resources/en.json

@ -0,0 +1,45 @@
{
"culture": "en",
"texts": {
"Languages": "Languages",
"Resources": "Resources",
"Texts": "Texts",
"Delete": "Delete",
"DisplayName:Any": "Any",
"DisplayName:CreationTime": "Creation Time",
"DisplayName:CultureName": "Culture",
"DisplayName:Description": "Description",
"DisplayName:DisplayName": "Display Name",
"DisplayName:Enable": "Enable",
"DisplayName:FlagIcon": "Flag Icon",
"DisplayName:Key": "Key",
"DisplayName:LastModificationTime": "Modification Time",
"DisplayName:Name": "Name",
"DisplayName:OnlyNull": "Only Null",
"DisplayName:ResourceName": "Resource",
"DisplayName:SaveAndNext": "Save & Next",
"DisplayName:TargetCultureName": "Target Culture",
"DisplayName:TargetValue": "Target Value",
"DisplayName:UiCultureName": "Ui Culture",
"DisplayName:Value": "Value",
"Permissions:LocalizationManagement": "Localization",
"Permissions:Language": "Language",
"Permissions:Resource": "Resource",
"Permissions:Text": "Text",
"Permissions:Create": "Create",
"Permissions:Update": "Update",
"Permissions:Delete": "Delete",
"Edit": "Edit",
"EditByName": "Edit - {0}",
"Filter": "Filter",
"Language:AddNew": "Add New Language",
"Resource:AddNew": "Add New Resource",
"SaveAndNext": "Save & Next",
"SearchFilter": "Search",
"Text:AddNew": "Add New Text",
"WillDeleteLanguage": "Language to be deleted {0}",
"WillDeleteResource": "Resource to be deleted {0}",
"WillDeleteText": "Document to be deleted {0}"
}
}

45
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/Localization/Resources/zh-Hans.json

@ -0,0 +1,45 @@
{
"culture": "zh-Hans",
"texts": {
"Languages": "语言",
"Resources": "资源",
"Texts": "文档",
"Delete": "删除",
"DisplayName:Any": "所有",
"DisplayName:CreationTime": "创建时间",
"DisplayName:CultureName": "文化名称",
"DisplayName:Description": "描述",
"DisplayName:DisplayName": "显示名称",
"DisplayName:Enable": "启用",
"DisplayName:FlagIcon": "旗帜图标",
"DisplayName:Key": "键",
"DisplayName:LastModificationTime": "变更时间",
"DisplayName:Name": "名称",
"DisplayName:OnlyNull": "仅空值",
"DisplayName:ResourceName": "资源名称",
"DisplayName:SaveAndNext": "保存并下一步",
"DisplayName:TargetCultureName": "目标文化",
"DisplayName:TargetValue": "目标值",
"DisplayName:UiCultureName": "界面文化",
"DisplayName:Value": "值",
"Permissions:LocalizationManagement": "本地化管理",
"Permissions:Language": "语言管理",
"Permissions:Resource": "资源管理",
"Permissions:Text": "文档管理",
"Permissions:Create": "新增",
"Permissions:Update": "编辑",
"Permissions:Delete": "删除",
"Edit": "编辑",
"EditByName": "编辑 - {0}",
"Filter": "过滤字符",
"Language:AddNew": "添加新语言",
"Resource:AddNew": "添加新资源",
"SaveAndNext": "保存并下一步",
"SearchFilter": "请输入过滤字符",
"Text:AddNew": "添加新文档",
"WillDeleteLanguage": "将要删除语言 {0}",
"WillDeleteResource": "将要删除资源 {0}",
"WillDeleteText": "将要删除文档 {0}"
}
}

9
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/ResourceConsts.cs

@ -0,0 +1,9 @@
namespace Sanhe.Abp.LocalizationManagement
{
public static class ResourceConsts
{
public static int MaxNameLength { get; set; } = 50;
public static int MaxDisplayNameLength { get; set; } = 64;
public static int MaxDescriptionLength { get; set; } = 64;
}
}

8
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/TextConsts.cs

@ -0,0 +1,8 @@
namespace Sanhe.Abp.LocalizationManagement
{
public static class TextConsts
{
public static int MaxKeyLength { get; set; } = 512;
public static int MaxValueLength { get; set; } = 2 * 1024;
}
}

37
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/TextDifference.cs

@ -0,0 +1,37 @@
namespace Sanhe.Abp.LocalizationManagement
{
/// <summary>
/// 文本差异
/// </summary>
public class TextDifference
{
public int Id { get; set; }
public string CultureName { get; set; }
public string Key { get; set; }
public string Value { get; set; }
public string ResourceName { get; set; }
public string TargetCultureName { get; set; }
public string TargetValue { get; set; }
public TextDifference() { }
public TextDifference(
int id,
string cultureName,
string key,
string value,
string targetCultureName,
string targetValue = null,
string resourceName = null)
{
Id = id;
Key = key;
Value = value;
CultureName = cultureName;
TargetCultureName = targetCultureName;
TargetValue = targetValue;
ResourceName = resourceName;
}
}
}

22
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain.Shared/Sanhe/Abp/LocalizationManagement/TextEto.cs

@ -0,0 +1,22 @@
namespace Sanhe.Abp.LocalizationManagement
{
public class TextEto
{
/// <summary>
/// 文化名称
/// </summary>
public string CultureName { get; set; }
/// <summary>
/// Key
/// </summary>
public string Key { get; set; }
/// <summary>
/// Value
/// </summary>
public string Value { get; set; }
/// <summary>
/// 资源名称
/// </summary>
public string ResourceName { get; set; }
}
}

3
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/FodyWeavers.xml

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

20
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe.Abp.LocalizationManagement.Domain.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="$(VoloAbpVersion)" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(VoloAbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\common\Sanhe.Abp.Localization.Dynamic\Sanhe.Abp.Localization.Dynamic.csproj" />
<ProjectReference Include="..\Sanhe.Abp.LocalizationManagement.Domain.Shared\Sanhe.Abp.LocalizationManagement.Domain.Shared.csproj" />
</ItemGroup>
</Project>

41
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementDomainModule.cs

@ -0,0 +1,41 @@
using Microsoft.Extensions.DependencyInjection;
using Sanhe.Abp.Localization.Dynamic;
using Sanhe.Abp.LocalizationManagement.Localization;
using Volo.Abp.AutoMapper;
using Volo.Abp.Domain;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Sanhe.Abp.LocalizationManagement;
[DependsOn(
typeof(AbpAutoMapperModule),
typeof(AbpDddDomainModule),
typeof(AbpLocalizationDynamicModule),
typeof(AbpLocalizationManagementDomainSharedModule))]
public class AbpLocalizationManagementDomainModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<AbpLocalizationManagementDomainModule>();
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<LocalizationManagementResource>()
.AddDynamic();
});
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<LocalizationManagementDomainMapperProfile>(validate: true);
});
// 分布式事件
//Configure<AbpDistributedEntityEventOptions>(options =>
//{
// options.AutoEventSelectors.Add<Text>();
// options.EtoMappings.Add<Text, TextEto>();
//});
}
}

14
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/ILanguageRepository.cs

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Sanhe.Abp.LocalizationManagement;
public interface ILanguageRepository : IRepository<Language, Guid>
{
Task<Language> FindByCultureNameAsync(string cultureName, CancellationToken cancellationToken = default);
Task<List<Language>> GetActivedListAsync(CancellationToken cancellationToken = default);
}

17
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/IResourceRepository.cs

@ -0,0 +1,17 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Sanhe.Abp.LocalizationManagement;
public interface IResourceRepository : IRepository<Resource, Guid>
{
Task<bool> ExistsAsync(
string name,
CancellationToken cancellationToken = default);
Task<Resource> FindByNameAsync(
string name,
CancellationToken cancellationToken = default);
}

43
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/ITextRepository.cs

@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Sanhe.Abp.LocalizationManagement;
public interface ITextRepository : IRepository<Text, int>
{
Task<Text> GetByCultureKeyAsync(
string resourceName,
string cultureName,
string key,
CancellationToken cancellationToken = default);
Task<List<Text>> GetListAsync(
string resourceName,
CancellationToken cancellationToken = default);
Task<List<Text>> GetListAsync(
string resourceName,
string cultureName,
CancellationToken cancellationToken = default);
Task<int> GetDifferenceCountAsync(
string cultureName,
string targetCultureName,
string resourceName = null,
bool? onlyNull = null,
string filter = null,
CancellationToken cancellationToken = default);
Task<List<TextDifference>> GetDifferencePagedListAsync(
string cultureName,
string targetCultureName,
string resourceName = null,
bool? onlyNull = null,
string filter = null,
string sorting = nameof(Text.Key),
int skipCount = 1,
int maxResultCount = 10,
CancellationToken cancellationToken = default);
}

53
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/Language.cs

@ -0,0 +1,53 @@
using JetBrains.Annotations;
using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.Localization;
namespace Sanhe.Abp.LocalizationManagement;
public class Language : AuditedEntity<Guid>, ILanguageInfo
{
public virtual bool Enable { get; set; }
public virtual string CultureName { get; protected set; }
public virtual string UiCultureName { get; protected set; }
public virtual string DisplayName { get; protected set; }
public virtual string FlagIcon { get; set; }
protected Language() { }
public Language(
[NotNull] string cultureName,
[NotNull] string uiCultureName,
[NotNull] string displayName,
string flagIcon = null)
{
CultureName = Check.NotNullOrWhiteSpace(cultureName, nameof(cultureName), LanguageConsts.MaxCultureNameLength);
UiCultureName = Check.NotNullOrWhiteSpace(uiCultureName, nameof(uiCultureName), LanguageConsts.MaxUiCultureNameLength);
DisplayName = Check.NotNullOrWhiteSpace(displayName, nameof(displayName), LanguageConsts.MaxDisplayNameLength);
FlagIcon = !flagIcon.IsNullOrWhiteSpace()
? Check.Length(flagIcon, nameof(flagIcon), LanguageConsts.MaxFlagIconLength)
: null;
Enable = true;
}
public virtual void ChangeCulture(string cultureName, string uiCultureName = null, string displayName = null)
{
ChangeCultureInternal(cultureName, uiCultureName, displayName);
}
private void ChangeCultureInternal(string cultureName, string uiCultureName, string displayName)
{
CultureName = Check.NotNullOrWhiteSpace(cultureName, nameof(cultureName), LanguageConsts.MaxCultureNameLength);
UiCultureName = !uiCultureName.IsNullOrWhiteSpace()
? Check.Length(uiCultureName, nameof(uiCultureName), LanguageConsts.MaxUiCultureNameLength)
: cultureName;
DisplayName = !displayName.IsNullOrWhiteSpace()
? Check.Length(displayName, nameof(displayName), LanguageConsts.MaxDisplayNameLength)
: cultureName;
}
}

10
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/LocalizationDbProperties.cs

@ -0,0 +1,10 @@
namespace Sanhe.Abp.LocalizationManagement;
public static class LocalizationDbProperties
{
public static string DbTablePrefix { get; set; } = "AbpLocalization";
public static string DbSchema { get; set; } = null;
public const string ConnectionStringName = "AbpLocalizationManagement";
}

11
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/LocalizationManagementDomainMapperProfile.cs

@ -0,0 +1,11 @@
using AutoMapper;
namespace Sanhe.Abp.LocalizationManagement;
public class LocalizationManagementDomainMapperProfile : Profile
{
public LocalizationManagementDomainMapperProfile()
{
CreateMap<Text, TextEto>();
}
}

85
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/LocalizationStore.cs

@ -0,0 +1,85 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Sanhe.Abp.Localization.Dynamic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
namespace Sanhe.Abp.LocalizationManagement;
[Dependency(ServiceLifetime.Singleton, ReplaceServices = true)]
[ExposeServices(
typeof(ILocalizationStore),
typeof(LocalizationStore))]
public class LocalizationStore : ILocalizationStore
{
protected ILanguageRepository LanguageRepository { get; }
protected ITextRepository TextRepository { get; }
protected IResourceRepository ResourceRepository { get; }
public LocalizationStore(
ILanguageRepository languageRepository,
ITextRepository textRepository,
IResourceRepository resourceRepository)
{
TextRepository = textRepository;
LanguageRepository = languageRepository;
ResourceRepository = resourceRepository;
}
public async virtual Task<List<LanguageInfo>> GetLanguageListAsync(
CancellationToken cancellationToken = default)
{
var languages = await LanguageRepository.GetActivedListAsync(cancellationToken);
return languages
.Select(x => new LanguageInfo(x.CultureName, x.UiCultureName, x.DisplayName, x.FlagIcon))
.ToList();
}
public async virtual Task<Dictionary<string, ILocalizationDictionary>> GetLocalizationDictionaryAsync(
string resourceName,
CancellationToken cancellationToken = default)
{
// TODO: 引用缓存?
var dictionaries = new Dictionary<string, ILocalizationDictionary>();
var resource = await ResourceRepository.FindByNameAsync(resourceName, cancellationToken);
if (resource == null || !resource.Enable)
{
// 资源不存在或未启用返回空
return dictionaries;
}
var texts = await TextRepository.GetListAsync(resourceName, cancellationToken);
foreach (var textGroup in texts.GroupBy(x => x.CultureName))
{
var cultureTextDictionaires = new Dictionary<string, LocalizedString>();
foreach (var text in textGroup)
{
// 本地化名称去重
if (!cultureTextDictionaires.ContainsKey(text.Key))
{
cultureTextDictionaires[text.Key] = new LocalizedString(text.Key, text.Value.NormalizeLineEndings());
}
}
// 本地化语言去重
if (!dictionaries.ContainsKey(textGroup.Key))
{
dictionaries[textGroup.Key] = new StaticLocalizationDictionary(textGroup.Key, cultureTextDictionaires);
}
}
return dictionaries;
}
public async virtual Task<bool> ResourceExistsAsync(string resourceName, CancellationToken cancellationToken = default)
{
return await ResourceRepository.ExistsAsync(resourceName, cancellationToken);
}
}

52
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/LocalizationSynchronizer.cs

@ -0,0 +1,52 @@
using Sanhe.Abp.Localization.Dynamic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Distributed;
namespace Sanhe.Abp.LocalizationManagement;
public class LocalizationSynchronizer :
ILocalEventHandler<EntityCreatedEventData<Text>>,
ILocalEventHandler<EntityUpdatedEventData<Text>>,
ILocalEventHandler<EntityDeletedEventData<Text>>,
ITransientDependency
{
private readonly IDistributedEventBus _eventBus;
public LocalizationSynchronizer(
IDistributedEventBus eventBus)
{
_eventBus = eventBus;
}
public async virtual Task HandleEventAsync(EntityCreatedEventData<Text> eventData)
{
await HandleEventAsync(BuildResetEventData(eventData.Entity));
}
public async virtual Task HandleEventAsync(EntityUpdatedEventData<Text> eventData)
{
await HandleEventAsync(BuildResetEventData(eventData.Entity));
}
public async virtual Task HandleEventAsync(EntityDeletedEventData<Text> eventData)
{
var data = BuildResetEventData(eventData.Entity);
data.IsDeleted = true;
await HandleEventAsync(data);
}
private LocalizedStringCacheResetEventData BuildResetEventData(Text text)
{
return new LocalizedStringCacheResetEventData(
text.ResourceName, text.CultureName, text.Key, text.Value);
}
private async Task HandleEventAsync(LocalizedStringCacheResetEventData eventData)
{
await _eventBus.PublishAsync(eventData);
}
}

29
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/Resource.cs

@ -0,0 +1,29 @@
using JetBrains.Annotations;
using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
namespace Sanhe.Abp.LocalizationManagement;
public class Resource : AuditedEntity<Guid>
{
public virtual bool Enable { get; set; }
public virtual string Name { get; set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
protected Resource() { }
public Resource(
[NotNull] string name,
[CanBeNull] string displayName = null,
[CanBeNull] string description = null)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), ResourceConsts.MaxNameLength);
DisplayName = displayName ?? Name;
Description = description;
Enable = true;
}
}

36
modules/localization-management/Sanhe.Abp.LocalizationManagement.Domain/Sanhe/Abp/LocalizationManagement/Text.cs

@ -0,0 +1,36 @@
using JetBrains.Annotations;
using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
namespace Sanhe.Abp.LocalizationManagement;
public class Text : Entity<int>
{
public virtual string CultureName { get; protected set; }
public virtual string Key { get; protected set; }
public virtual string Value { get; protected set; }
public virtual string ResourceName { get; protected set; }
protected Text() { }
public Text(
[NotNull] string resourceName,
[NotNull] string cultureName,
[NotNull] string key,
[CanBeNull] string value)
{
ResourceName = Check.NotNull(resourceName, nameof(resourceName), ResourceConsts.MaxNameLength);
CultureName = Check.NotNullOrWhiteSpace(cultureName, nameof(cultureName), LanguageConsts.MaxCultureNameLength);
Key = Check.NotNullOrWhiteSpace(key, nameof(key), TextConsts.MaxKeyLength);
Value = !value.IsNullOrWhiteSpace()
? Check.NotNullOrWhiteSpace(value, nameof(value), TextConsts.MaxValueLength)
: "";
}
public void SetValue(string value)
{
Value = !value.IsNullOrWhiteSpace()
? Check.NotNullOrWhiteSpace(value, nameof(value), TextConsts.MaxValueLength)
: Value;
}
}

3
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/FodyWeavers.xml

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

19
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="$(VoloAbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sanhe.Abp.LocalizationManagement.Domain\Sanhe.Abp.LocalizationManagement.Domain.csproj" />
</ItemGroup>
</Project>

23
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/AbpLocalizationManagementEntityFrameworkCoreModule.cs

@ -0,0 +1,23 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace Sanhe.Abp.LocalizationManagement.EntityFrameworkCore;
[DependsOn(
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpLocalizationManagementDomainModule))]
public class AbpLocalizationManagementEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<LocalizationDbContext>(options =>
{
options.AddRepository<Text, EfCoreTextRepository>();
options.AddRepository<Language, EfCoreLanguageRepository>();
options.AddRepository<Resource, EfCoreResourceRepository>();
options.AddDefaultRepositories(includeAllEntities: true);
});
}
}

32
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/EfCoreLanguageRepository.cs

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Sanhe.Abp.LocalizationManagement.EntityFrameworkCore;
public class EfCoreLanguageRepository : EfCoreRepository<LocalizationDbContext, Language, Guid>, ILanguageRepository
{
public EfCoreLanguageRepository(IDbContextProvider<LocalizationDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async virtual Task<Language> FindByCultureNameAsync(
string cultureName,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).Where(x => x.CultureName.Equals(cultureName))
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public async virtual Task<List<Language>> GetActivedListAsync(CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).Where(x => x.Enable)
.ToListAsync(GetCancellationToken(cancellationToken));
}
}

31
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/EfCoreResourceRepository.cs

@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Sanhe.Abp.LocalizationManagement.EntityFrameworkCore;
public class EfCoreResourceRepository : EfCoreRepository<LocalizationDbContext, Resource, Guid>, IResourceRepository
{
public EfCoreResourceRepository(IDbContextProvider<LocalizationDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async virtual Task<bool> ExistsAsync(
string name,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).AnyAsync(x => x.Name.Equals(name), cancellationToken: cancellationToken);
}
public async virtual Task<Resource> FindByNameAsync(
string name,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).Where(x => x.Name.Equals(name))
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
}

132
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/EfCoreTextRepository.cs

@ -0,0 +1,132 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Sanhe.Abp.LocalizationManagement.EntityFrameworkCore;
public class EfCoreTextRepository : EfCoreRepository<LocalizationDbContext, Text, int>, ITextRepository
{
public EfCoreTextRepository(IDbContextProvider<LocalizationDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async virtual Task<Text> GetByCultureKeyAsync(
string resourceName,
string cultureName,
string key,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(x => x.ResourceName.Equals(resourceName) && x.CultureName.Equals(cultureName) && x.Key.Equals(key))
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public async virtual Task<int> GetDifferenceCountAsync(
string cultureName,
string targetCultureName,
string resourceName = null,
bool? onlyNull = null,
string filter = null,
CancellationToken cancellationToken = default)
{
return await (await BuildTextDifferenceQueryAsync(
cultureName,
targetCultureName,
resourceName,
onlyNull,
filter))
.CountAsync(GetCancellationToken(cancellationToken));
}
public async virtual Task<List<Text>> GetListAsync(
string resourceName,
CancellationToken cancellationToken = default)
{
var languages = (await GetDbContextAsync()).Set<Language>();
var texts = await GetDbSetAsync();
return await (from txts in texts
join lg in languages
on txts.CultureName equals lg.CultureName
where txts.ResourceName.Equals(resourceName) &&
lg.Enable
select txts)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async virtual Task<List<Text>> GetListAsync(
string resourceName,
string cultureName,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(x => x.ResourceName.Equals(resourceName) && x.CultureName.Equals(cultureName))
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async virtual Task<List<TextDifference>> GetDifferencePagedListAsync(
string cultureName,
string targetCultureName,
string resourceName = null,
bool? onlyNull = null,
string filter = null,
string sorting = nameof(TextDifference.Key),
int skipCount = 1,
int maxResultCount = 10,
CancellationToken cancellationToken = default)
{
return await (await BuildTextDifferenceQueryAsync(
cultureName,
targetCultureName,
resourceName,
onlyNull,
filter,
sorting))
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
protected async virtual Task<IQueryable<TextDifference>> BuildTextDifferenceQueryAsync(
string cultureName,
string targetCultureName,
string resourceName = null,
bool? onlyNull = null,
string filter = null,
string sorting = nameof(TextDifference.Key))
{
var textQuery = (await GetDbSetAsync())
.Where(x => x.CultureName.Equals(cultureName))
.WhereIf(!resourceName.IsNullOrWhiteSpace(), x => x.ResourceName.Equals(resourceName))
.WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Key.Contains(filter))
.OrderBy(sorting ?? nameof(TextDifference.Key));
var targetTextQuery = (await GetDbSetAsync())
.Where(x => x.CultureName.Equals(targetCultureName))
.WhereIf(!resourceName.IsNullOrWhiteSpace(), x => x.ResourceName.Equals(resourceName));
var query = from crtText in textQuery
join tgtText in targetTextQuery
on crtText.Key equals tgtText.Key
into tgt
from tt in tgt.DefaultIfEmpty()
where onlyNull.HasValue && onlyNull.Value
? tt.Value == null
: 1 == 1
select new TextDifference(
crtText.Id,
crtText.CultureName,
crtText.Key,
crtText.Value,
targetCultureName,
tt != null ? tt.Value : null,
crtText.ResourceName);
return query;
}
}

13
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/ILocalizationDbContext.cs

@ -0,0 +1,13 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
namespace Sanhe.Abp.LocalizationManagement.EntityFrameworkCore;
[ConnectionStringName(LocalizationDbProperties.ConnectionStringName)]
public interface ILocalizationDbContext : IEfCoreDbContext
{
DbSet<Resource> Resources { get; set; }
DbSet<Language> Languages { get; set; }
DbSet<Text> Texts { get; set; }
}

25
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/LocalizationDbContext.cs

@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
namespace Sanhe.Abp.LocalizationManagement.EntityFrameworkCore;
[ConnectionStringName(LocalizationDbProperties.ConnectionStringName)]
public class LocalizationDbContext : AbpDbContext<LocalizationDbContext>, ILocalizationDbContext
{
public virtual DbSet<Resource> Resources { get; set; }
public virtual DbSet<Language> Languages { get; set; }
public virtual DbSet<Text> Texts { get; set; }
public LocalizationDbContext(DbContextOptions<LocalizationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureLocalization();
}
}

98
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/LocalizationDbContextModelBuilderExtensions.cs

@ -0,0 +1,98 @@
using Microsoft.EntityFrameworkCore;
using System;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Sanhe.Abp.LocalizationManagement.EntityFrameworkCore;
public static class LocalizationDbContextModelBuilderExtensions
{
public static void ConfigureLocalization(
this ModelBuilder builder,
Action<LocalizationModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new LocalizationModelBuilderConfigurationOptions(
LocalizationDbProperties.DbTablePrefix,
LocalizationDbProperties.DbSchema
);
optionsAction?.Invoke(options);
builder.Entity<Language>(x =>
{
x.ToTable(options.TablePrefix + "Languages", options.Schema);
x.Property(p => p.CultureName)
.IsRequired()
.HasMaxLength(LanguageConsts.MaxCultureNameLength)
.HasColumnName(nameof(Language.CultureName));
x.Property(p => p.UiCultureName)
.IsRequired()
.HasMaxLength(LanguageConsts.MaxUiCultureNameLength)
.HasColumnName(nameof(Language.UiCultureName));
x.Property(p => p.DisplayName)
.IsRequired()
.HasMaxLength(LanguageConsts.MaxDisplayNameLength)
.HasColumnName(nameof(Language.DisplayName));
x.Property(p => p.FlagIcon)
.IsRequired(false)
.HasMaxLength(LanguageConsts.MaxFlagIconLength)
.HasColumnName(nameof(Language.FlagIcon));
x.Property(p => p.Enable)
.HasDefaultValue(true);
x.ConfigureByConvention();
x.HasIndex(p => p.CultureName);
});
builder.Entity<Resource>(x =>
{
x.ToTable(options.TablePrefix + "Resources", options.Schema);
x.Property(p => p.Name)
.IsRequired()
.HasMaxLength(ResourceConsts.MaxNameLength)
.HasColumnName(nameof(Resource.Name));
x.Property(p => p.DisplayName)
.HasMaxLength(ResourceConsts.MaxDisplayNameLength)
.HasColumnName(nameof(Resource.DisplayName));
x.Property(p => p.Description)
.HasMaxLength(ResourceConsts.MaxDescriptionLength)
.HasColumnName(nameof(Resource.Description));
x.Property(p => p.Enable)
.HasDefaultValue(true);
x.ConfigureByConvention();
x.HasIndex(p => p.Name);
});
builder.Entity<Text>(x =>
{
x.ToTable(options.TablePrefix + "Texts", options.Schema);
x.Property(p => p.CultureName)
.IsRequired()
.HasMaxLength(LanguageConsts.MaxCultureNameLength)
.HasColumnName(nameof(Text.CultureName));
x.Property(p => p.Key)
.IsRequired()
.HasMaxLength(TextConsts.MaxKeyLength)
.HasColumnName(nameof(Text.Key));
x.Property(p => p.Value)
.HasMaxLength(TextConsts.MaxValueLength)
.HasColumnName(nameof(Text.Value));
x.ConfigureByConvention();
x.HasIndex(p => p.Key);
});
}
}

17
modules/localization-management/Sanhe.Abp.LocalizationManagement.EntityFrameworkCore/Sanhe/Abp/LocalizationManagement/EntityFrameworkCore/LocalizationModelBuilderConfigurationOptions.cs

@ -0,0 +1,17 @@
using JetBrains.Annotations;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Sanhe.Abp.LocalizationManagement.EntityFrameworkCore;
public class LocalizationModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
{
public LocalizationModelBuilderConfigurationOptions(
[NotNull] string tablePrefix = "",
[CanBeNull] string schema = null)
: base(
tablePrefix,
schema)
{
}
}

3
modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/FodyWeavers.xml

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

19
modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe.Abp.LocalizationManagement.HttpApi.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sanhe.Abp.LocalizationManagement.Application.Contracts\Sanhe.Abp.LocalizationManagement.Application.Contracts.csproj" />
</ItemGroup>
</Project>

41
modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe/Abp/LocalizationManagement/AbpLocalizationManagementHttpApiModule.cs

@ -0,0 +1,41 @@
using Microsoft.Extensions.DependencyInjection;
using Sanhe.Abp.LocalizationManagement.Localization;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Validation.Localization;
namespace Sanhe.Abp.LocalizationManagement;
[DependsOn(
typeof(AbpAspNetCoreMvcModule),
typeof(AbpLocalizationManagementApplicationContractsModule))]
public class AbpLocalizationManagementHttpApiModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
// Dto验证本地化
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(
typeof(LocalizationManagementResource),
typeof(AbpLocalizationManagementApplicationContractsModule).Assembly);
});
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpLocalizationManagementApplicationContractsModule).Assembly);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<LocalizationManagementResource>()
.AddBaseTypes(typeof(AbpValidationResource));
});
}
}

61
modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe/Abp/LocalizationManagement/LanguageController.cs

@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
namespace Sanhe.Abp.LocalizationManagement;
[RemoteService(Name = LocalizationRemoteServiceConsts.RemoteServiceName)]
[Area("localization")]
[Route("api/localization/languages")]
public class LanguageController : AbpController, ILanguageAppService
{
private readonly ILanguageAppService _service;
public LanguageController(ILanguageAppService service)
{
_service = service;
}
[HttpPost]
public virtual Task<LanguageDto> CreateAsync(CreateOrUpdateLanguageInput input)
{
return _service.CreateAsync(input);
}
[HttpDelete]
[Route("{id}")]
public virtual Task DeleteAsync(Guid id)
{
return _service.DeleteAsync(id);
}
[HttpGet]
[Route("all")]
public virtual Task<ListResultDto<LanguageDto>> GetAllAsync()
{
return _service.GetAllAsync();
}
[HttpGet]
[Route("{id}")]
public virtual Task<LanguageDto> GetAsync(Guid id)
{
return _service.GetAsync(id);
}
[HttpGet]
public virtual Task<PagedResultDto<LanguageDto>> GetListAsync(GetLanguagesInput input)
{
return _service.GetListAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual Task<LanguageDto> UpdateAsync(Guid id, CreateOrUpdateLanguageInput input)
{
return _service.UpdateAsync(id, input);
}
}

61
modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe/Abp/LocalizationManagement/ResourceController.cs

@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
namespace Sanhe.Abp.LocalizationManagement;
[RemoteService(Name = LocalizationRemoteServiceConsts.RemoteServiceName)]
[Area("localization")]
[Route("api/localization/resources")]
public class ResourceController : AbpController, IResourceAppService
{
private readonly IResourceAppService _service;
public ResourceController(IResourceAppService service)
{
_service = service;
}
[HttpPost]
public virtual Task<ResourceDto> CreateAsync(CreateOrUpdateResourceInput input)
{
return _service.CreateAsync(input);
}
[HttpDelete]
[Route("{id}")]
public virtual Task DeleteAsync(Guid id)
{
return _service.DeleteAsync(id);
}
[HttpGet]
[Route("all")]
public virtual Task<ListResultDto<ResourceDto>> GetAllAsync()
{
return _service.GetAllAsync();
}
[HttpGet]
[Route("{id}")]
public virtual Task<ResourceDto> GetAsync(Guid id)
{
return _service.GetAsync(id);
}
[HttpGet]
public virtual Task<PagedResultDto<ResourceDto>> GetListAsync(GetResourcesInput input)
{
return _service.GetListAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual Task<ResourceDto> UpdateAsync(Guid id, CreateOrUpdateResourceInput input)
{
return _service.UpdateAsync(id, input);
}
}

60
modules/localization-management/Sanhe.Abp.LocalizationManagement.HttpApi/Sanhe/Abp/LocalizationManagement/TextController.cs

@ -0,0 +1,60 @@
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
namespace Sanhe.Abp.LocalizationManagement;
[RemoteService(Name = LocalizationRemoteServiceConsts.RemoteServiceName)]
[Area("localization")]
[Route("api/localization/texts")]
public class TextController : AbpController, ITextAppService
{
private readonly ITextAppService _service;
public TextController(ITextAppService service)
{
_service = service;
}
[HttpPost]
public virtual Task<TextDto> CreateAsync(CreateTextInput input)
{
return _service.CreateAsync(input);
}
[HttpDelete]
[Route("{id}")]
public virtual Task DeleteAsync(int id)
{
return _service.DeleteAsync(id);
}
[HttpGet]
[Route("{id}")]
public virtual Task<TextDto> GetAsync(int id)
{
return _service.GetAsync(id);
}
[HttpGet]
[Route("by-culture-key")]
public virtual Task<TextDto> GetByCultureKeyAsync(GetTextByKeyInput input)
{
return _service.GetByCultureKeyAsync(input);
}
[HttpGet]
public virtual Task<PagedResultDto<TextDifferenceDto>> GetListAsync(GetTextsInput input)
{
return _service.GetListAsync(input);
}
[HttpPut]
[Route("{id}")]
public virtual Task<TextDto> UpdateAsync(int id, UpdateTextInput input)
{
return _service.UpdateAsync(id, input);
}
}

6
modules/mvc/Sanhe.Abp.AspNetCore.Mvc.Wrapper/Sanhe/Abp/AspNetCore/Mvc/Wrapper/Filters/AbpWrapResultFilter.cs

@ -1,7 +1,7 @@
using Sanhe.Abp.AspNetCore.Mvc.Wrapper.Wraping; using Microsoft.AspNetCore.Mvc.Filters;
using Sanhe.Abp.Wrapper;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Sanhe.Abp.AspNetCore.Mvc.Wrapper.Wraping;
using Sanhe.Abp.Wrapper;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;

2
services/book-store/Data/IdentityServerDataSeedContributor.cs

@ -70,7 +70,7 @@ public class IdentityServerDataSeedContributor : IDataSeedContributor, ITransien
private async Task CreateApiResourcesAsync() private async Task CreateApiResourcesAsync()
{ {
var commonApiUserClaims = new[] {"email", "email_verified", "name", "phone_number", "phone_number_verified", "role"}; var commonApiUserClaims = new[] { "email", "email_verified", "name", "phone_number", "phone_number_verified", "role" };
await CreateApiResourceAsync("BookStore", commonApiUserClaims); await CreateApiResourceAsync("BookStore", commonApiUserClaims);
} }

Loading…
Cancel
Save