committed by
GitHub
30 changed files with 781 additions and 24 deletions
@ -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<LocalizationManagementResource>(name); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace LINGYUN.Abp.LocalizationManagement.Features; |
|||
|
|||
public static class LocalizationManagementFeatures |
|||
{ |
|||
public const string GroupName = "LocalizationManagement"; |
|||
|
|||
public const string Enable = GroupName + ".Enable"; |
|||
} |
|||
@ -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<string, LocalizedString> 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<string, LocalizedString> 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<IEnumerable<string>> GetSupportedCulturesAsync() |
|||
{ |
|||
var cacheItem = await StoreCache.GetResourceOrNullAsync(Resource.ResourceName); |
|||
|
|||
if (cacheItem == null || !cacheItem.IsEnabled) |
|||
{ |
|||
return Array.Empty<string>(); |
|||
} |
|||
|
|||
return cacheItem.SupportedCultures; |
|||
} |
|||
|
|||
public void Initialize(LocalizationResourceInitializationContext context) |
|||
{ |
|||
Resource = context.Resource; |
|||
StoreCache = context.ServiceProvider.GetRequiredService<IExternalLocalizationStoreCache>(); |
|||
TextStoreCache = context.ServiceProvider.GetRequiredService<IExternalLocalizationTextStoreCache>(); |
|||
} |
|||
} |
|||
@ -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<AbpLocalizationOptions> 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<LocalizationResourceBase> 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<string[]> GetResourceNamesAsync() |
|||
{ |
|||
var cacheNames = await StoreCache.GetResourceNamesAsync(); |
|||
|
|||
return cacheNames |
|||
.Where(name => !LocalizationOptions.Resources.ContainsKey(name)) |
|||
.ToArray(); |
|||
} |
|||
|
|||
public async virtual Task<LocalizationResourceBase[]> GetResourcesAsync() |
|||
{ |
|||
var cacheItem = await StoreCache.GetResourcesAsync(); |
|||
|
|||
|
|||
if (cacheItem == null) |
|||
{ |
|||
return Array.Empty<LocalizationResourceBase>(); |
|||
} |
|||
|
|||
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; |
|||
} |
|||
} |
|||
@ -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<LocalizationResourceCacheItem> ResourceCache { get; } |
|||
protected IDistributedCache<LocalizationResourcesCacheItem> ResourcesCache { get; } |
|||
protected AbpLocalizationOptions LocalizationOptions { get; } |
|||
protected IResourceRepository ResourceRepository { get; } |
|||
|
|||
public ExternalLocalizationStoreCache( |
|||
IDistributedCache<LocalizationResourcesCacheItem> resourcesCache, |
|||
IDistributedCache<LocalizationResourceCacheItem> resourceCache, |
|||
IOptions<AbpLocalizationOptions> 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<string[]> 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<LocalizationResourceCacheItem> GetResourceOrNullAsync(string resourceName) |
|||
{ |
|||
var cacheItem = await GetResourceCacheItemAsync(resourceName); |
|||
|
|||
return cacheItem.IsEnabled ? cacheItem : null; |
|||
} |
|||
|
|||
public async virtual Task<LocalizationResourceCacheItem[]> 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<LocalizationResourceCacheItem> 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<LocalizationResourcesCacheItem> 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; |
|||
} |
|||
} |
|||
@ -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<string, string> Texts { get; set; } |
|||
public ExternalLocalizationTextCacheItem() |
|||
{ |
|||
Texts = new Dictionary<string, string>(); |
|||
} |
|||
public ExternalLocalizationTextCacheItem(Dictionary<string, string> texts) |
|||
{ |
|||
Texts = texts; |
|||
} |
|||
|
|||
public static string CalculateCacheKey(string resourceName, string cultureName) |
|||
{ |
|||
return string.Format(CacheKeyFormat, resourceName, cultureName); |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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<string> AsyncKeyedLocker; |
|||
protected ConcurrentDictionary<string, LocalizationTextMemoryCacheItem> MemoryCache { get; } |
|||
|
|||
protected IAbpDistributedLock DistributedLock { get; } |
|||
protected IServiceScopeFactory ServiceScopeFactory { get; } |
|||
protected IDistributedCache<ExternalLocalizationTextCacheItem> DistributedCache { get; } |
|||
protected IDistributedCache<ExternalLocalizationTextStampCacheItem> StampCache { get; } |
|||
|
|||
public ExternalLocalizationTextStoreCache( |
|||
IAbpDistributedLock distributedLock, |
|||
IServiceScopeFactory serviceScopeFactory, |
|||
IDistributedCache<ExternalLocalizationTextCacheItem> distributedCache, |
|||
IDistributedCache<ExternalLocalizationTextStampCacheItem> stampCache) |
|||
{ |
|||
DistributedLock = distributedLock; |
|||
ServiceScopeFactory = serviceScopeFactory; |
|||
DistributedCache = distributedCache; |
|||
StampCache = stampCache; |
|||
|
|||
AsyncKeyedLocker = new AsyncKeyedLocker<string>(o => |
|||
{ |
|||
o.PoolSize = 20; |
|||
o.PoolInitialFill = 1; |
|||
}); |
|||
MemoryCache = new ConcurrentDictionary<string, LocalizationTextMemoryCacheItem>(); |
|||
} |
|||
|
|||
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<string, string> 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<string, string>(); |
|||
} |
|||
|
|||
public async virtual Task<Dictionary<string, string>> 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<string, string>(); |
|||
} |
|||
|
|||
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<ExternalLocalizationTextCacheItem> CreateCacheItemAsync(LocalizationResourceBase resource, string cultureName) |
|||
{ |
|||
using var scope = ServiceScopeFactory.CreateScope(); |
|||
var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); |
|||
using var unitOfWork = unitOfWorkManager.Begin(requiresNew: true); |
|||
var repo = scope.ServiceProvider.GetRequiredService<ITextRepository>(); |
|||
|
|||
var texts = await repo.GetListAsync(resource.ResourceName, cultureName); |
|||
|
|||
var fillTexts = new Dictionary<string, string>(); |
|||
|
|||
foreach (var text in texts) |
|||
{ |
|||
fillTexts[text.Key] = text.Value; |
|||
} |
|||
|
|||
return new ExternalLocalizationTextCacheItem(fillTexts); |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.LocalizationManagement.External; |
|||
|
|||
public interface IExternalLocalizationStoreCache |
|||
{ |
|||
LocalizationResourceCacheItem GetResourceOrNull(string resourceName); |
|||
|
|||
Task<LocalizationResourceCacheItem> GetResourceOrNullAsync(string resourceName); |
|||
|
|||
Task<string[]> GetResourceNamesAsync(); |
|||
|
|||
Task<LocalizationResourceCacheItem[]> GetResourcesAsync(); |
|||
|
|||
Task RemoveAsync(string resourceName); |
|||
} |
|||
@ -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<string, string> GetTexts(LocalizationResourceBase resource, string cultureName); |
|||
|
|||
Task<Dictionary<string, string>> GetTextsAsync(LocalizationResourceBase resource, string cultureName); |
|||
|
|||
Task RemoveAsync(string resourceName, string cultureName); |
|||
} |
|||
@ -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<EntityChangedEventData<Resource>>, |
|||
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<Resource> 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); |
|||
} |
|||
} |
|||
} |
|||
@ -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<string>(); |
|||
SupportedCultures = supportedCultures ?? Array.Empty<string>(); |
|||
} |
|||
} |
|||
@ -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<LocalizationResourceCacheItem> Resources { get; set; } |
|||
|
|||
public LocalizationResourcesCacheItem() |
|||
{ |
|||
Resources = new List<LocalizationResourceCacheItem>(); |
|||
} |
|||
|
|||
public LocalizationResourcesCacheItem(List<LocalizationResourceCacheItem> resources) |
|||
{ |
|||
Resources = resources; |
|||
} |
|||
|
|||
public LocalizationResourceCacheItem GetResourceOrNull(string name) |
|||
{ |
|||
return Resources?.FirstOrDefault(x => x.Name == name); |
|||
} |
|||
} |
|||
@ -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<string, string> Texts { get; set; } |
|||
|
|||
public LocalizationTextMemoryCacheItem() |
|||
{ |
|||
Texts = new Dictionary<string, string>(); |
|||
} |
|||
public LocalizationTextMemoryCacheItem(Dictionary<string, string> texts, string cacheStamp) |
|||
{ |
|||
Texts = texts; |
|||
CacheStamp = cacheStamp; |
|||
LastCheckTime = DateTime.Now; |
|||
} |
|||
|
|||
public static string CalculateCacheKey(string resourceName, string cultureName) |
|||
{ |
|||
return string.Format(CacheKeyFormat, resourceName, cultureName); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue