diff --git a/aspnet-core/LINGYUN.MicroService.SingleProject.sln b/aspnet-core/LINGYUN.MicroService.SingleProject.sln
index 05a94bccc..6f95fc248 100644
--- a/aspnet-core/LINGYUN.MicroService.SingleProject.sln
+++ b/aspnet-core/LINGYUN.MicroService.SingleProject.sln
@@ -664,6 +664,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.AspNet
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.AspNetCore", "framework\wechat\LINGYUN.Abp.WeChat.Work.AspNetCore\LINGYUN.Abp.WeChat.Work.AspNetCore.csproj", "{40DC9A79-2E8A-4C6F-A637-5C09D6F26B0E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.WeChat.Work", "framework\wechat\LINGYUN.Abp.Identity.WeChat.Work\LINGYUN.Abp.Identity.WeChat.Work.csproj", "{CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1762,6 +1764,10 @@ Global
{40DC9A79-2E8A-4C6F-A637-5C09D6F26B0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40DC9A79-2E8A-4C6F-A637-5C09D6F26B0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40DC9A79-2E8A-4C6F-A637-5C09D6F26B0E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2085,6 +2091,7 @@ Global
{4C7594CE-FB2F-4309-B95C-D4460892CF6E} = {7C714185-D3D9-4D94-B5CB-D857A0091F04}
{C9266D5D-3860-09C3-F566-489BBB57A534} = {D94D6AFE-20BD-4F21-8708-03F5E34F49FC}
{40DC9A79-2E8A-4C6F-A637-5C09D6F26B0E} = {91867618-0D86-4410-91C6-B1166A9ACDF9}
+ {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5} = {91867618-0D86-4410-91C6-B1166A9ACDF9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {711A43C0-A2F8-4E5C-9B9F-F2551E4B3FF1}
diff --git a/aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.IP.Location/LINGYUN.Abp.AuditLogging.IP.Location.csproj b/aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.IP.Location/LINGYUN.Abp.AuditLogging.IP.Location.csproj
index 753f85c89..0b01d2d85 100644
--- a/aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.IP.Location/LINGYUN.Abp.AuditLogging.IP.Location.csproj
+++ b/aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.IP.Location/LINGYUN.Abp.AuditLogging.IP.Location.csproj
@@ -14,9 +14,6 @@
false
-
- netstandard2.0
-
diff --git a/aspnet-core/framework/localization/LINGYUN.Abp.AspNetCore.Mvc.Localization/LINGYUN/Abp/AspNetCore/Mvc/Localization/TextAppService.cs b/aspnet-core/framework/localization/LINGYUN.Abp.AspNetCore.Mvc.Localization/LINGYUN/Abp/AspNetCore/Mvc/Localization/TextAppService.cs
index a5cf04a00..754915b66 100644
--- a/aspnet-core/framework/localization/LINGYUN.Abp.AspNetCore.Mvc.Localization/LINGYUN/Abp/AspNetCore/Mvc/Localization/TextAppService.cs
+++ b/aspnet-core/framework/localization/LINGYUN.Abp.AspNetCore.Mvc.Localization/LINGYUN/Abp/AspNetCore/Mvc/Localization/TextAppService.cs
@@ -99,7 +99,7 @@ public class TextAppService : ApplicationService, ITextAppService
using (CultureHelper.Use(cultureName, cultureName))
{
- localizedStrings = (await localizer.GetAllStringsAsync(true))
+ localizedStrings = (await localizer.GetAllStringsAsync(true, false, true))
.WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter))
.OrderBy(l => l.Name);
}
@@ -112,7 +112,7 @@ public class TextAppService : ApplicationService, ITextAppService
{
using (CultureHelper.Use(targetCultureName, targetCultureName))
{
- targetLocalizedStrings = (await localizer.GetAllStringsAsync(true))
+ targetLocalizedStrings = (await localizer.GetAllStringsAsync(false, false, true))
.WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter))
.OrderBy(l => l.Name);
}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application.Contracts/LINGYUN/Abp/LocalizationManagement/Permissions/LocalizationManagementPermissionDefinitionProvider.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application.Contracts/LINGYUN/Abp/LocalizationManagement/Permissions/LocalizationManagementPermissionDefinitionProvider.cs
index e719a51e6..6bb3ae3e9 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application.Contracts/LINGYUN/Abp/LocalizationManagement/Permissions/LocalizationManagementPermissionDefinitionProvider.cs
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application.Contracts/LINGYUN/Abp/LocalizationManagement/Permissions/LocalizationManagementPermissionDefinitionProvider.cs
@@ -1,5 +1,7 @@
-using LINGYUN.Abp.LocalizationManagement.Localization;
+using LINGYUN.Abp.LocalizationManagement.Features;
+using LINGYUN.Abp.LocalizationManagement.Localization;
using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Features;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.LocalizationManagement.Permissions;
@@ -15,53 +17,65 @@ public class LocalizationManagementPermissionDefinitionProvider : PermissionDefi
var resourcePermission = permissionGroup.AddPermission(
LocalizationManagementPermissions.Resource.Default,
L("Permissions:Resource"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
resourcePermission.AddChild(
LocalizationManagementPermissions.Resource.Create,
L("Permissions:Create"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
resourcePermission.AddChild(
LocalizationManagementPermissions.Resource.Update,
L("Permissions:Update"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
resourcePermission.AddChild(
LocalizationManagementPermissions.Resource.Delete,
L("Permissions:Delete"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
var languagePermission = permissionGroup.AddPermission(
LocalizationManagementPermissions.Language.Default,
L("Permissions:Language"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
languagePermission.AddChild(
LocalizationManagementPermissions.Language.Create,
L("Permissions:Create"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
languagePermission.AddChild(
LocalizationManagementPermissions.Language.Update,
L("Permissions:Update"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
languagePermission.AddChild(
LocalizationManagementPermissions.Language.Delete,
L("Permissions:Delete"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
var textPermission = permissionGroup.AddPermission(
LocalizationManagementPermissions.Text.Default,
L("Permissions:Text"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
textPermission.AddChild(
LocalizationManagementPermissions.Text.Create,
L("Permissions:Create"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
textPermission.AddChild(
LocalizationManagementPermissions.Text.Update,
L("Permissions:Update"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
textPermission.AddChild(
LocalizationManagementPermissions.Text.Delete,
L("Permissions:Delete"),
- Volo.Abp.MultiTenancy.MultiTenancySides.Host);
+ Volo.Abp.MultiTenancy.MultiTenancySides.Host)
+ .RequireFeatures(LocalizationManagementFeatures.Enable);
}
private static LocalizableString L(string name)
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/LanguageAppService.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/LanguageAppService.cs
index 90fae14c8..ac5220099 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/LanguageAppService.cs
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/LanguageAppService.cs
@@ -1,6 +1,8 @@
-using LINGYUN.Abp.LocalizationManagement.Permissions;
+using LINGYUN.Abp.LocalizationManagement.Features;
+using LINGYUN.Abp.LocalizationManagement.Permissions;
using Microsoft.AspNetCore.Authorization;
using System.Globalization;
+using System.Runtime.Versioning;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Localization;
@@ -8,6 +10,7 @@ using Volo.Abp.Localization;
namespace LINGYUN.Abp.LocalizationManagement;
[Authorize(LocalizationManagementPermissions.Language.Default)]
+[RequiresPreviewFeatures(LocalizationManagementFeatures.Enable)]
public class LanguageAppService : LocalizationAppServiceBase, ILanguageAppService
{
private readonly ILanguageRepository _repository;
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/ResourceAppService.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/ResourceAppService.cs
index fde5b7baa..83d4b58aa 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/ResourceAppService.cs
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/ResourceAppService.cs
@@ -1,11 +1,14 @@
-using LINGYUN.Abp.LocalizationManagement.Permissions;
+using LINGYUN.Abp.LocalizationManagement.Features;
+using LINGYUN.Abp.LocalizationManagement.Permissions;
using Microsoft.AspNetCore.Authorization;
+using System.Runtime.Versioning;
using System.Threading.Tasks;
using Volo.Abp;
namespace LINGYUN.Abp.LocalizationManagement;
[Authorize(LocalizationManagementPermissions.Resource.Default)]
+[RequiresPreviewFeatures(LocalizationManagementFeatures.Enable)]
public class ResourceAppService : LocalizationAppServiceBase, IResourceAppService
{
private readonly IResourceRepository _repository;
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/TextAppService.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/TextAppService.cs
index 54e32edba..90973a94b 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/TextAppService.cs
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Application/LINGYUN/Abp/LocalizationManagement/TextAppService.cs
@@ -1,10 +1,13 @@
-using LINGYUN.Abp.LocalizationManagement.Permissions;
+using LINGYUN.Abp.LocalizationManagement.Features;
+using LINGYUN.Abp.LocalizationManagement.Permissions;
using Microsoft.AspNetCore.Authorization;
+using System.Runtime.Versioning;
using System.Threading.Tasks;
namespace LINGYUN.Abp.LocalizationManagement;
[Authorize(LocalizationManagementPermissions.Text.Default)]
+[RequiresPreviewFeatures(LocalizationManagementFeatures.Enable)]
public class TextAppService : LocalizationAppServiceBase, ITextAppService
{
private readonly ITextRepository _textRepository;
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN.Abp.LocalizationManagement.Domain.Shared.csproj b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN.Abp.LocalizationManagement.Domain.Shared.csproj
index f89f38827..88d1ce1b4 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN.Abp.LocalizationManagement.Domain.Shared.csproj
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN.Abp.LocalizationManagement.Domain.Shared.csproj
@@ -24,6 +24,7 @@
+
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/AbpLocalizationManagementDomainSharedModule.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/AbpLocalizationManagementDomainSharedModule.cs
index ec03a92d7..0b0c57782 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/AbpLocalizationManagementDomainSharedModule.cs
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/AbpLocalizationManagementDomainSharedModule.cs
@@ -1,4 +1,5 @@
using LINGYUN.Abp.LocalizationManagement.Localization;
+using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Modularity;
@@ -8,6 +9,7 @@ using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.LocalizationManagement;
[DependsOn(
+ typeof(AbpFeaturesModule),
typeof(AbpValidationModule),
typeof(AbpLocalizationModule))]
public class AbpLocalizationManagementDomainSharedModule : AbpModule
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Features/LocalizationManagementFeatureDefinitionProvider.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Features/LocalizationManagementFeatureDefinitionProvider.cs
new file mode 100644
index 000000000..516c38d48
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Features/LocalizationManagementFeatureDefinitionProvider.cs
@@ -0,0 +1,25 @@
+using LINGYUN.Abp.LocalizationManagement.Localization;
+using Volo.Abp.Features;
+using Volo.Abp.Localization;
+using Volo.Abp.Validation.StringValues;
+
+namespace LINGYUN.Abp.LocalizationManagement.Features;
+
+public class LocalizationManagementFeatureDefinitionProvider : FeatureDefinitionProvider
+{
+ public override void Define(IFeatureDefinitionContext context)
+ {
+ var group = context.AddGroup(LocalizationManagementFeatures.GroupName,
+ L("Feature:LocalizationManagement"));
+ group.AddFeature(LocalizationManagementFeatures.Enable,
+ "true",
+ L("Feature:LocalizationManagementEnable"),
+ L("Feature:LocalizationManagementEnableDesc"),
+ new ToggleStringValueType());
+ }
+
+ private static LocalizableString L(string name)
+ {
+ return LocalizableString.Create(name);
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Features/LocalizationManagementFeatures.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Features/LocalizationManagementFeatures.cs
new file mode 100644
index 000000000..95e4f6493
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Features/LocalizationManagementFeatures.cs
@@ -0,0 +1,8 @@
+namespace LINGYUN.Abp.LocalizationManagement.Features;
+
+public static class LocalizationManagementFeatures
+{
+ public const string GroupName = "LocalizationManagement";
+
+ public const string Enable = GroupName + ".Enable";
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Localization/Resources/en.json b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Localization/Resources/en.json
index 70e9d1801..469b831aa 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Localization/Resources/en.json
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Localization/Resources/en.json
@@ -6,6 +6,9 @@
"DisplayName:CreationTime": "Creation Time",
"DisplayName:LastModificationTime": "Modification Time",
"DisplayName:SaveAndNext": "Save & Next",
+ "Feature:LocalizationManagement": "Localization Management",
+ "Feature:LocalizationManagementEnable": "Enable Localization Management",
+ "Feature:LocalizationManagementEnableDesc": "Enable localization management in the application",
"Permissions:LocalizationManagement": "Localization",
"Permissions:Language": "Language",
"Permissions:Resource": "Resource",
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Localization/Resources/zh-Hans.json b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Localization/Resources/zh-Hans.json
index 7bc476760..a78673b5c 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Localization/Resources/zh-Hans.json
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/Localization/Resources/zh-Hans.json
@@ -6,6 +6,9 @@
"DisplayName:CreationTime": "创建时间",
"DisplayName:LastModificationTime": "变更时间",
"DisplayName:SaveAndNext": "保存并下一步",
+ "Feature:LocalizationManagement": "本地化管理",
+ "Feature:LocalizationManagementEnable": "启用本地化管理",
+ "Feature:LocalizationManagementEnableDesc": "在应用程序中启用本地化管理",
"Permissions:LocalizationManagement": "本地化管理",
"Permissions:Language": "语言管理",
"Permissions:Resource": "资源管理",
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationResourceContributor.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationResourceContributor.cs
new file mode 100644
index 000000000..02791a5e8
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationResourceContributor.cs
@@ -0,0 +1,69 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Localization;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Localization;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+public class ExternalLocalizationResourceContributor : ILocalizationResourceContributor
+{
+ public bool IsDynamic => false;
+
+ protected LocalizationResourceBase Resource { get; private set; }
+ protected IExternalLocalizationStoreCache StoreCache { get; private set; }
+ protected IExternalLocalizationTextStoreCache TextStoreCache { get; private set; }
+
+ public virtual void Fill(string cultureName, Dictionary dictionary)
+ {
+ var texts = TextStoreCache.GetTexts(Resource, cultureName);
+
+ foreach (var text in texts)
+ {
+ dictionary[text.Key] = new LocalizedString(text.Key, text.Value);
+ }
+ }
+
+ public async virtual Task FillAsync(string cultureName, Dictionary dictionary)
+ {
+ var texts = await TextStoreCache.GetTextsAsync(Resource, cultureName);
+
+ foreach (var text in texts)
+ {
+ dictionary[text.Key] = new LocalizedString(text.Key, text.Value);
+ }
+ }
+
+ public virtual LocalizedString GetOrNull(string cultureName, string name)
+ {
+ var texts = TextStoreCache.GetTexts(Resource, cultureName);
+
+ var text = texts.GetOrDefault(name);
+ if (text == null)
+ {
+ return null;
+ }
+
+ return new LocalizedString(name, text);
+ }
+
+ public async virtual Task> GetSupportedCulturesAsync()
+ {
+ var cacheItem = await StoreCache.GetResourceOrNullAsync(Resource.ResourceName);
+
+ if (cacheItem == null || !cacheItem.IsEnabled)
+ {
+ return Array.Empty();
+ }
+
+ return cacheItem.SupportedCultures;
+ }
+
+ public void Initialize(LocalizationResourceInitializationContext context)
+ {
+ Resource = context.Resource;
+ StoreCache = context.ServiceProvider.GetRequiredService();
+ TextStoreCache = context.ServiceProvider.GetRequiredService();
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationStore.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationStore.cs
new file mode 100644
index 000000000..cff5a80a9
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationStore.cs
@@ -0,0 +1,90 @@
+using Microsoft.Extensions.Options;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Localization;
+using Volo.Abp.Localization.External;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+[Dependency(ReplaceServices = true)]
+public class ExternalLocalizationStore : IExternalLocalizationStore, ITransientDependency
+{
+ protected AbpLocalizationOptions LocalizationOptions { get; }
+ protected IExternalLocalizationStoreCache StoreCache { get; }
+
+ public ExternalLocalizationStore(
+ IOptions localizationOptions,
+ IExternalLocalizationStoreCache storeCache)
+ {
+ LocalizationOptions = localizationOptions.Value;
+ StoreCache = storeCache;
+ }
+
+ public virtual LocalizationResourceBase GetResourceOrNull(string resourceName)
+ {
+ var cacheItem = StoreCache.GetResourceOrNull(resourceName);
+
+ if (cacheItem == null || LocalizationOptions.Resources.ContainsKey(cacheItem.Name))
+ {
+ return null;
+ }
+
+ return CreateNonTypedLocalizationResource(cacheItem);
+ }
+
+ public async virtual Task GetResourceOrNullAsync(string resourceName)
+ {
+ var cacheItem = await StoreCache.GetResourceOrNullAsync(resourceName);
+
+ if (cacheItem == null || LocalizationOptions.Resources.ContainsKey(cacheItem.Name))
+ {
+ return null;
+ }
+
+ return CreateNonTypedLocalizationResource(cacheItem);
+ }
+
+ public async virtual Task GetResourceNamesAsync()
+ {
+ var cacheNames = await StoreCache.GetResourceNamesAsync();
+
+ return cacheNames
+ .Where(name => !LocalizationOptions.Resources.ContainsKey(name))
+ .ToArray();
+ }
+
+ public async virtual Task GetResourcesAsync()
+ {
+ var cacheItem = await StoreCache.GetResourcesAsync();
+
+
+ if (cacheItem == null)
+ {
+ return Array.Empty();
+ }
+
+ return cacheItem
+ .Where(x => x.IsEnabled)
+ .Where(x => !LocalizationOptions.Resources.ContainsKey(x.Name))
+ .Select(CreateNonTypedLocalizationResource)
+ .ToArray();
+ }
+
+ protected virtual NonTypedLocalizationResource CreateNonTypedLocalizationResource(LocalizationResourceCacheItem cacheItem)
+ {
+ var localizationResource = new NonTypedLocalizationResource(
+ cacheItem.Name,
+ cacheItem.DefaultCulture);
+
+ if (cacheItem.BaseResources.Length > 0)
+ {
+ localizationResource.AddBaseResources(cacheItem.BaseResources);
+ }
+
+ localizationResource.Contributors.Add(new ExternalLocalizationResourceContributor());
+
+ return localizationResource;
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationStoreCache.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationStoreCache.cs
new file mode 100644
index 000000000..1e726cb59
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationStoreCache.cs
@@ -0,0 +1,146 @@
+using Microsoft.Extensions.Options;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.Caching;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Localization;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+public class ExternalLocalizationStoreCache : IExternalLocalizationStoreCache, ITransientDependency
+{
+ protected IDistributedCache ResourceCache { get; }
+ protected IDistributedCache ResourcesCache { get; }
+ protected AbpLocalizationOptions LocalizationOptions { get; }
+ protected IResourceRepository ResourceRepository { get; }
+
+ public ExternalLocalizationStoreCache(
+ IDistributedCache resourcesCache,
+ IDistributedCache resourceCache,
+ IOptions localizationOptions,
+ IResourceRepository resourceRepository)
+ {
+ ResourceCache = resourceCache;
+ ResourcesCache = resourcesCache;
+ ResourceRepository = resourceRepository;
+ LocalizationOptions = localizationOptions.Value;
+ }
+
+ public async virtual Task RemoveAsync(string resourceName)
+ {
+ await ResourceCache.RemoveAsync(resourceName);
+ await ResourcesCache.RemoveAsync(LocalizationResourcesCacheItem.CacheKey);
+ }
+
+ public async virtual Task GetResourceNamesAsync()
+ {
+ var cacheItem = await GetResourcesCacheItemAsync();
+
+ return cacheItem.Resources
+ .Where(x => x.IsEnabled)
+ .Where(x => !LocalizationOptions.Resources.ContainsKey(x.Name))
+ .Select(x => x.Name)
+ .ToArray();
+ }
+
+ public virtual LocalizationResourceCacheItem GetResourceOrNull(string resourceName)
+ {
+ var cacheItem = GetResourceCacheItem(resourceName);
+
+ return cacheItem.IsEnabled ? cacheItem : null;
+ }
+
+ public async virtual Task GetResourceOrNullAsync(string resourceName)
+ {
+ var cacheItem = await GetResourceCacheItemAsync(resourceName);
+
+ return cacheItem.IsEnabled ? cacheItem : null;
+ }
+
+ public async virtual Task GetResourcesAsync()
+ {
+ var cacheItem = await GetResourcesCacheItemAsync();
+
+ return cacheItem.Resources
+ .Where(x => x.IsEnabled)
+ .Where(x => !LocalizationOptions.Resources.ContainsKey(x.Name))
+ .ToArray();
+ }
+
+ protected virtual LocalizationResourceCacheItem GetResourceCacheItem(string resourceName)
+ {
+ var cacheItem = ResourceCache.Get(resourceName);
+ if (cacheItem == null)
+ {
+ var resource = ResourceRepository.FindByName(resourceName);
+
+ if (resource == null)
+ {
+ cacheItem = new LocalizationResourceCacheItem(resourceName)
+ {
+ IsEnabled = false
+ };
+ }
+ else
+ {
+ cacheItem = new LocalizationResourceCacheItem(resource.Name, resource.DefaultCultureName)
+ {
+ IsEnabled = resource.Enable
+ };
+ }
+
+ ResourceCache.Set(resourceName, cacheItem);
+ }
+
+ return cacheItem;
+ }
+
+ protected async virtual Task GetResourceCacheItemAsync(string resourceName)
+ {
+ var cacheItem = await ResourceCache.GetAsync(resourceName);
+ if (cacheItem == null)
+ {
+ var resource = await ResourceRepository.FindByNameAsync(resourceName);
+ if (resource == null)
+ {
+ cacheItem = new LocalizationResourceCacheItem(resourceName)
+ {
+ IsEnabled = false
+ };
+ }
+ else
+ {
+ cacheItem = new LocalizationResourceCacheItem(resource.Name, resource.DefaultCultureName)
+ {
+ IsEnabled = resource.Enable
+ };
+ }
+
+ await ResourceCache.SetAsync(resourceName, cacheItem);
+ }
+
+ return cacheItem;
+ }
+
+ protected async virtual Task GetResourcesCacheItemAsync()
+ {
+ var cacheItem = await ResourcesCache.GetAsync(LocalizationResourcesCacheItem.CacheKey);
+ if (cacheItem == null)
+ {
+ var resources = await ResourceRepository.GetListAsync();
+ var resourceItems = resources
+ .Where(x => !LocalizationOptions.Resources.ContainsKey(x.Name))
+ .Select(x => new LocalizationResourceCacheItem(x.Name, x.DefaultCultureName)
+ {
+ IsEnabled = x.Enable,
+ })
+ .ToList();
+
+ cacheItem = new LocalizationResourcesCacheItem(resourceItems);
+
+ await ResourcesCache.SetAsync(LocalizationResourcesCacheItem.CacheKey, cacheItem);
+ }
+
+ return cacheItem;
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextCacheItem.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextCacheItem.cs
new file mode 100644
index 000000000..c4e219ba9
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextCacheItem.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using Volo.Abp.Caching;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+[Serializable]
+[IgnoreMultiTenancy]
+[CacheName("AbpExternalLocalizationTexts")]
+public class ExternalLocalizationTextCacheItem
+{
+ private const string CacheKeyFormat = "r:{0},c:{1}";
+
+ public Dictionary Texts { get; set; }
+ public ExternalLocalizationTextCacheItem()
+ {
+ Texts = new Dictionary();
+ }
+ public ExternalLocalizationTextCacheItem(Dictionary texts)
+ {
+ Texts = texts;
+ }
+
+ public static string CalculateCacheKey(string resourceName, string cultureName)
+ {
+ return string.Format(CacheKeyFormat, resourceName, cultureName);
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextStampCacheItem.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextStampCacheItem.cs
new file mode 100644
index 000000000..434063dad
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextStampCacheItem.cs
@@ -0,0 +1,29 @@
+using System;
+using Volo.Abp.Caching;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+[Serializable]
+[IgnoreMultiTenancy]
+[CacheName("AbpExternalLocalizationTextsStamp")]
+public class ExternalLocalizationTextStampCacheItem
+{
+ private const string CacheKeyFormat = "r:{0},c:{1}";
+ public string Stamp { get; set; }
+
+ public ExternalLocalizationTextStampCacheItem()
+ {
+
+ }
+
+ public ExternalLocalizationTextStampCacheItem(string stamp)
+ {
+ Stamp = stamp;
+ }
+
+ public static string CalculateCacheKey(string resourceName, string cultureName)
+ {
+ return string.Format(CacheKeyFormat, resourceName, cultureName);
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextStoreCache.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextStoreCache.cs
new file mode 100644
index 000000000..1a216363f
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/ExternalLocalizationTextStoreCache.cs
@@ -0,0 +1,143 @@
+using AsyncKeyedLock;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Caching;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.DistributedLocking;
+using Volo.Abp.Localization;
+using Volo.Abp.Uow;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+public class ExternalLocalizationTextStoreCache : IExternalLocalizationTextStoreCache, ISingletonDependency
+{
+ protected AsyncKeyedLocker AsyncKeyedLocker;
+ protected ConcurrentDictionary MemoryCache { get; }
+
+ protected IAbpDistributedLock DistributedLock { get; }
+ protected IServiceScopeFactory ServiceScopeFactory { get; }
+ protected IDistributedCache DistributedCache { get; }
+ protected IDistributedCache StampCache { get; }
+
+ public ExternalLocalizationTextStoreCache(
+ IAbpDistributedLock distributedLock,
+ IServiceScopeFactory serviceScopeFactory,
+ IDistributedCache distributedCache,
+ IDistributedCache stampCache)
+ {
+ DistributedLock = distributedLock;
+ ServiceScopeFactory = serviceScopeFactory;
+ DistributedCache = distributedCache;
+ StampCache = stampCache;
+
+ AsyncKeyedLocker = new AsyncKeyedLocker(o =>
+ {
+ o.PoolSize = 20;
+ o.PoolInitialFill = 1;
+ });
+ MemoryCache = new ConcurrentDictionary();
+ }
+
+ public async virtual Task RemoveAsync(string resourceName, string cultureName)
+ {
+ var cacheKey = ExternalLocalizationTextCacheItem.CalculateCacheKey(resourceName, cultureName);
+ var stampCacheKey = ExternalLocalizationTextStampCacheItem.CalculateCacheKey(resourceName, cultureName);
+
+ await using var lockHandle = await DistributedLock.TryAcquireAsync(cacheKey, TimeSpan.FromMinutes(1d));
+
+ await DistributedCache.RemoveAsync(cacheKey);
+
+ await StampCache.SetAsync(stampCacheKey, new ExternalLocalizationTextStampCacheItem(Guid.NewGuid().ToString()));
+ }
+
+ public Dictionary GetTexts(LocalizationResourceBase resource, string cultureName)
+ {
+ var cacheKey = ExternalLocalizationTextCacheItem.CalculateCacheKey(resource.ResourceName, cultureName);
+ var memoryCacheItem = MemoryCache.GetOrDefault(cacheKey);
+ if (memoryCacheItem != null && !IsShouldCheck(memoryCacheItem))
+ {
+ return memoryCacheItem.Texts;
+ }
+
+ return new Dictionary();
+ }
+
+ public async virtual Task> GetTextsAsync(LocalizationResourceBase resource, string cultureName)
+ {
+ var cacheKey = ExternalLocalizationTextCacheItem.CalculateCacheKey(resource.ResourceName, cultureName);
+ var memoryCacheItem = MemoryCache.GetOrDefault(cacheKey);
+ if (memoryCacheItem != null && !IsShouldCheck(memoryCacheItem))
+ {
+ return memoryCacheItem.Texts;
+ }
+
+ using (await AsyncKeyedLocker.LockAsync(cacheKey))
+ {
+ memoryCacheItem = MemoryCache.GetOrDefault(cacheKey);
+ if (memoryCacheItem != null && !IsShouldCheck(memoryCacheItem))
+ {
+ return memoryCacheItem.Texts;
+ }
+
+ var stampCacheKey = ExternalLocalizationTextStampCacheItem.CalculateCacheKey(resource.ResourceName, cultureName);
+ var stampCacheItem = await StampCache.GetAsync(stampCacheKey);
+ if (memoryCacheItem != null && memoryCacheItem.CacheStamp == stampCacheItem.Stamp)
+ {
+ memoryCacheItem.LastCheckTime = DateTime.Now;
+ return memoryCacheItem.Texts;
+ }
+
+ var distributeCacheItem = await DistributedCache.GetAsync(cacheKey);
+ if (distributeCacheItem != null)
+ {
+ MemoryCache[cacheKey] = new LocalizationTextMemoryCacheItem(distributeCacheItem.Texts, stampCacheItem.Stamp);
+
+ return distributeCacheItem.Texts;
+ }
+
+ await using var lockHandle = await DistributedLock.TryAcquireAsync(cacheKey, TimeSpan.FromMinutes(1d));
+
+ if (lockHandle == null)
+ {
+ return new Dictionary();
+ }
+
+ distributeCacheItem = await CreateCacheItemAsync(resource, cultureName);
+
+ await DistributedCache.SetAsync(cacheKey, distributeCacheItem);
+
+ stampCacheItem = new ExternalLocalizationTextStampCacheItem(Guid.NewGuid().ToString());
+ await StampCache.SetAsync(stampCacheKey, stampCacheItem);
+
+ MemoryCache[cacheKey] = new LocalizationTextMemoryCacheItem(distributeCacheItem.Texts, stampCacheItem.Stamp);
+
+ return distributeCacheItem.Texts;
+ }
+ }
+ private static bool IsShouldCheck(LocalizationTextMemoryCacheItem memoryCacheItem)
+ {
+ return DateTime.Now.Subtract(memoryCacheItem.LastCheckTime).TotalSeconds >= 30.0;
+ }
+
+ protected async virtual Task CreateCacheItemAsync(LocalizationResourceBase resource, string cultureName)
+ {
+ using var scope = ServiceScopeFactory.CreateScope();
+ var unitOfWorkManager = scope.ServiceProvider.GetRequiredService();
+ using var unitOfWork = unitOfWorkManager.Begin(requiresNew: true);
+ var repo = scope.ServiceProvider.GetRequiredService();
+
+ var texts = await repo.GetListAsync(resource.ResourceName, cultureName);
+
+ var fillTexts = new Dictionary();
+
+ foreach (var text in texts)
+ {
+ fillTexts[text.Key] = text.Value;
+ }
+
+ return new ExternalLocalizationTextCacheItem(fillTexts);
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/IExternalLocalizationStoreCache.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/IExternalLocalizationStoreCache.cs
new file mode 100644
index 000000000..cc3825d69
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/IExternalLocalizationStoreCache.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+public interface IExternalLocalizationStoreCache
+{
+ LocalizationResourceCacheItem GetResourceOrNull(string resourceName);
+
+ Task GetResourceOrNullAsync(string resourceName);
+
+ Task GetResourceNamesAsync();
+
+ Task GetResourcesAsync();
+
+ Task RemoveAsync(string resourceName);
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/IExternalLocalizationTextStoreCache.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/IExternalLocalizationTextStoreCache.cs
new file mode 100644
index 000000000..3ad00d885
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/IExternalLocalizationTextStoreCache.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Localization;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+public interface IExternalLocalizationTextStoreCache
+{
+ Dictionary GetTexts(LocalizationResourceBase resource, string cultureName);
+
+ Task> GetTextsAsync(LocalizationResourceBase resource, string cultureName);
+
+ Task RemoveAsync(string resourceName, string cultureName);
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourceCacheInvalidator.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourceCacheInvalidator.cs
new file mode 100644
index 000000000..cb8cbe422
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourceCacheInvalidator.cs
@@ -0,0 +1,36 @@
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Domain.Entities.Events;
+using Volo.Abp.EventBus;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+public class LocalizationResourceCacheInvalidator :
+ ILocalEventHandler>,
+ ITransientDependency
+{
+ private readonly IExternalLocalizationTextStoreCache _externalLocalizationTextStoreCache;
+ private readonly ILocalizationLanguageStoreCache _localizationLanguageStoreCache;
+ private readonly IExternalLocalizationStoreCache _externalLocalizationStoreCache;
+ public LocalizationResourceCacheInvalidator(
+ IExternalLocalizationTextStoreCache externalLocalizationTextStoreCache,
+ ILocalizationLanguageStoreCache localizationLanguageStoreCache,
+ IExternalLocalizationStoreCache externalLocalizationStoreCache)
+ {
+ _externalLocalizationTextStoreCache = externalLocalizationTextStoreCache;
+ _localizationLanguageStoreCache = localizationLanguageStoreCache;
+ _externalLocalizationStoreCache = externalLocalizationStoreCache;
+ }
+
+ public async virtual Task HandleEventAsync(EntityChangedEventData eventData)
+ {
+ await _externalLocalizationStoreCache.RemoveAsync(eventData.Entity.Name);
+;
+ var languages = await _localizationLanguageStoreCache.GetLanguagesAsync();
+
+ foreach (var language in languages)
+ {
+ await _externalLocalizationTextStoreCache.RemoveAsync(eventData.Entity.Name, language.CultureName);
+ }
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourceCacheItem.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourceCacheItem.cs
new file mode 100644
index 000000000..1bd160c3a
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourceCacheItem.cs
@@ -0,0 +1,32 @@
+using System;
+using Volo.Abp.Caching;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+[IgnoreMultiTenancy]
+[CacheName("AbpExternalLocalizationResource")]
+public class LocalizationResourceCacheItem
+{
+ public virtual string Name { get; set; }
+
+ public virtual string DefaultCulture { get; set; }
+
+ public virtual string[] BaseResources { get; set; }
+
+ public virtual string[] SupportedCultures { get; set; }
+
+ public bool IsEnabled { get; set; }
+
+ public LocalizationResourceCacheItem(
+ string name,
+ string defaultCulture = null,
+ string[] baseResources = null,
+ string[] supportedCultures = null)
+ {
+ Name = name;
+ DefaultCulture = defaultCulture;
+ BaseResources = baseResources ?? Array.Empty();
+ SupportedCultures = supportedCultures ?? Array.Empty();
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourcesCacheItem.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourcesCacheItem.cs
new file mode 100644
index 000000000..91bbf3c5f
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationResourcesCacheItem.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Linq;
+using Volo.Abp.Caching;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+[IgnoreMultiTenancy]
+[CacheName("AbpExternalLocalizationResources")]
+public class LocalizationResourcesCacheItem
+{
+ public const string CacheKey = "All";
+
+ public List Resources { get; set; }
+
+ public LocalizationResourcesCacheItem()
+ {
+ Resources = new List();
+ }
+
+ public LocalizationResourcesCacheItem(List resources)
+ {
+ Resources = resources;
+ }
+
+ public LocalizationResourceCacheItem GetResourceOrNull(string name)
+ {
+ return Resources?.FirstOrDefault(x => x.Name == name);
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationTextMemoryCacheItem.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationTextMemoryCacheItem.cs
new file mode 100644
index 000000000..58fd8fb85
--- /dev/null
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/External/LocalizationTextMemoryCacheItem.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+
+namespace LINGYUN.Abp.LocalizationManagement.External;
+
+public class LocalizationTextMemoryCacheItem
+{
+ private const string CacheKeyFormat = "r:{0},c:{1}";
+
+ public string CacheStamp { get; }
+
+ public DateTime LastCheckTime { get; set; }
+
+ public Dictionary Texts { get; set; }
+
+ public LocalizationTextMemoryCacheItem()
+ {
+ Texts = new Dictionary();
+ }
+ public LocalizationTextMemoryCacheItem(Dictionary texts, string cacheStamp)
+ {
+ Texts = texts;
+ CacheStamp = cacheStamp;
+ LastCheckTime = DateTime.Now;
+ }
+
+ public static string CalculateCacheKey(string resourceName, string cultureName)
+ {
+ return string.Format(CacheKeyFormat, resourceName, cultureName);
+ }
+}
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/IResourceRepository.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/IResourceRepository.cs
index 7bd96a387..29a82b9dc 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/IResourceRepository.cs
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/IResourceRepository.cs
@@ -11,6 +11,8 @@ public interface IResourceRepository : IRepository
string name,
CancellationToken cancellationToken = default);
+ Resource FindByName(string name);
+
Task FindByNameAsync(
string name,
CancellationToken cancellationToken = default);
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationLanguageCacheItem.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationLanguageCacheItem.cs
index f2b25862c..3c19db655 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationLanguageCacheItem.cs
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationLanguageCacheItem.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using Volo.Abp.Caching;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
@@ -7,9 +8,10 @@ namespace LINGYUN.Abp.LocalizationManagement;
[Serializable]
[IgnoreMultiTenancy]
+[CacheName("AbpLocalizationLanguages")]
public class LocalizationLanguageCacheItem
{
- internal const string CacheKey = "Abp.Localization.Languages";
+ public const string CacheKey = "All";
public List Languages { get; set; }
public LocalizationLanguageCacheItem()
diff --git a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationTextCacheInvalidator.cs b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationTextCacheInvalidator.cs
index 4ca3bb4ea..5d845e4f8 100644
--- a/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationTextCacheInvalidator.cs
+++ b/aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationTextCacheInvalidator.cs
@@ -1,4 +1,5 @@
-using System.Threading.Tasks;
+using LINGYUN.Abp.LocalizationManagement.External;
+using System.Threading.Tasks;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
@@ -9,8 +10,12 @@ namespace LINGYUN.Abp.LocalizationManagement;
public class LocalizationTextCacheInvalidator : ILocalEventHandler>, ITransientDependency
{
private readonly IDistributedCache _localizationTextCache;
- public LocalizationTextCacheInvalidator(IDistributedCache localizationTextCache)
+ private readonly IExternalLocalizationTextStoreCache _externalLocalizationTextStoreCache;
+ public LocalizationTextCacheInvalidator(
+ IDistributedCache localizationTextCache,
+ IExternalLocalizationTextStoreCache externalLocalizationTextStoreCache)
{
+ _externalLocalizationTextStoreCache = externalLocalizationTextStoreCache;
_localizationTextCache = localizationTextCache;
}
@@ -21,5 +26,7 @@ public class LocalizationTextCacheInvalidator : ILocalEventHandler x.Name.Equals(name));
}
+ [Obsolete("Use FindAsync() method.")]
+ public virtual Resource FindByName(string name)
+ {
+ using (Volo.Abp.Uow.UnitOfWorkManager.DisableObsoleteDbContextCreationWarning.SetScoped(true))
+ {
+ return DbSet.FirstOrDefault(localizationResourceRecord => localizationResourceRecord.Name == name);
+ }
+ }
+
public async virtual Task FindByNameAsync(
string name,
CancellationToken cancellationToken = default)