Implement changes for RemoteLocalizationContributor.

pull/13845/head
Halil İbrahim Kalkan 3 years ago
parent f6a3530eaf
commit a63b2dfc45

@ -9,30 +9,38 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly;
public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency
{
protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; }
protected AbpApplicationConfigurationClientProxy ApplicationConfigurationClientProxy { get; }
protected AbpApplicationLocalizationClientProxy ApplicationLocalizationClientProxy { get; }
protected ApplicationConfigurationCache Cache { get; }
protected ICurrentTenantAccessor CurrentTenantAccessor { get; }
public WebAssemblyCachedApplicationConfigurationClient(
AbpApplicationConfigurationClientProxy applicationConfigurationAppService,
AbpApplicationConfigurationClientProxy applicationConfigurationClientProxy,
ApplicationConfigurationCache cache,
ICurrentTenantAccessor currentTenantAccessor)
ICurrentTenantAccessor currentTenantAccessor,
AbpApplicationLocalizationClientProxy applicationLocalizationClientProxy)
{
ApplicationConfigurationAppService = applicationConfigurationAppService;
ApplicationConfigurationClientProxy = applicationConfigurationClientProxy;
Cache = cache;
CurrentTenantAccessor = currentTenantAccessor;
ApplicationLocalizationClientProxy = applicationLocalizationClientProxy;
}
public virtual async Task InitializeAsync()
{
var configurationDto = await ApplicationConfigurationAppService.GetAsync(
var configurationDto = await ApplicationConfigurationClientProxy.GetAsync(
new ApplicationConfigurationRequestOptions {
IncludeLocalizationResources = false
}
);
var localizationDto = await ApplicationLocalizationClientProxy.GetAsync(configurationDto.Localization.CurrentCulture.Name);
configurationDto.Localization.Resources = localizationDto.Resources;
Cache.Set(configurationDto);
CurrentTenantAccessor.Current = new BasicTenantInfo(

@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.Client;
@ -25,87 +26,137 @@ public class RemoteLocalizationContributor : ILocalizationResourceContributor
?? NullLogger<RemoteLocalizationContributor>.Instance;
}
public LocalizedString GetOrNull(string cultureName, string name)
public virtual LocalizedString GetOrNull(string cultureName, string name)
{
var resource = GetResourceOrNull();
/* cultureName is not used because remote localization can only
* be done in the current culture. */
return GetOrNullInternal(_resource.ResourceName, name);
}
protected virtual LocalizedString GetOrNullInternal(string resourceName, string name)
{
var resource = GetResourceOrNull(resourceName);
if (resource == null)
{
return null;
}
var value = resource.GetOrDefault(name);
if (value == null)
var value = resource.Texts.GetOrDefault(name);
if (value != null)
{
return null;
return new LocalizedString(name, value);
}
return new LocalizedString(name, value);
foreach (var baseResource in resource.BaseResources)
{
value = GetOrNullInternal(baseResource, name);
if (value != null)
{
return new LocalizedString(name, value);
}
}
return null;
}
public void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
public virtual void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
/* cultureName is not used because remote localization can only
* be done in the current culture. */
FillInternal(_resource.ResourceName, dictionary);
}
protected virtual void FillInternal(string resourceName, Dictionary<string, LocalizedString> dictionary)
{
var resource = GetResourceOrNull();
var resource = GetResourceOrNull(resourceName);
if (resource == null)
{
return;
}
foreach (var keyValue in resource)
foreach (var baseResource in resource.BaseResources)
{
FillInternal(baseResource, dictionary);
}
foreach (var keyValue in resource.Texts)
{
dictionary[keyValue.Key] = new LocalizedString(keyValue.Key, keyValue.Value);
}
}
public async Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary)
public virtual async Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
/* cultureName is not used because remote localization can only
* be done in the current culture. */
await FillInternalAsync(_resource.ResourceName, dictionary);
}
protected virtual async Task FillInternalAsync(string resourceName, Dictionary<string, LocalizedString> dictionary)
{
var resource = await GetResourceOrNullAsync();
var resource = await GetResourceOrNullAsync(resourceName);
if (resource == null)
{
return;
}
foreach (var baseResource in resource.BaseResources)
{
await FillInternalAsync(baseResource, dictionary);
}
foreach (var keyValue in resource)
foreach (var keyValue in resource.Texts)
{
dictionary[keyValue.Key] = new LocalizedString(keyValue.Key, keyValue.Value);
}
}
public Task<IEnumerable<string>> GetSupportedCulturesAsync()
public virtual Task<IEnumerable<string>> GetSupportedCulturesAsync()
{
/* This contributor does not know all the supported cultures by the
remote localization resource, and it is not needed on the client side */
return Task.FromResult((IEnumerable<string>)Array.Empty<string>());
}
private Dictionary<string, string> GetResourceOrNull()
protected virtual ApplicationLocalizationResourceDto GetResourceOrNull(string resourceName)
{
var applicationConfigurationDto = _applicationConfigurationClient.Get();
var resource = applicationConfigurationDto
.Localization.Values
.GetOrDefault(_resource.ResourceName);
if (resource == null)
{
_logger.LogWarning($"Could not find the localization resource {_resource.ResourceName} on the remote server!");
}
return resource;
return GetResourceOrNull(applicationConfigurationDto, resourceName);
}
private async Task<Dictionary<string, string>> GetResourceOrNullAsync()
protected virtual async Task<ApplicationLocalizationResourceDto> GetResourceOrNullAsync(string resourceName)
{
var applicationConfigurationDto = await _applicationConfigurationClient.GetAsync();
return GetResourceOrNull(applicationConfigurationDto, resourceName);
}
var resource = applicationConfigurationDto
protected virtual ApplicationLocalizationResourceDto GetResourceOrNull(
ApplicationConfigurationDto applicationConfigurationDto,
string resourceName)
{
var resource = applicationConfigurationDto.Localization.Resources.GetOrDefault(resourceName);
if (resource != null)
{
return resource;
}
var legacyResource = applicationConfigurationDto
.Localization.Values
.GetOrDefault(_resource.ResourceName);
.GetOrDefault(resourceName);
if (resource == null)
if (legacyResource != null)
{
_logger.LogWarning($"Could not find the localization resource {_resource.ResourceName} on the remote server!");
return new ApplicationLocalizationResourceDto
{
Texts = legacyResource,
BaseResources = Array.Empty<string>()
};
}
return resource;
_logger.LogWarning($"Could not find the localization resource {resourceName} on the remote server!");
return null;
}
}

@ -15,6 +15,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu
{
protected IHttpContextAccessor HttpContextAccessor { get; }
protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; }
protected AbpApplicationLocalizationClientProxy ApplicationLocalizationClientProxy { get; }
protected ICurrentUser CurrentUser { get; }
protected IDistributedCache<ApplicationConfigurationDto> Cache { get; }
@ -22,11 +23,13 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu
IDistributedCache<ApplicationConfigurationDto> cache,
AbpApplicationConfigurationClientProxy applicationConfigurationAppService,
ICurrentUser currentUser,
IHttpContextAccessor httpContextAccessor)
IHttpContextAccessor httpContextAccessor,
AbpApplicationLocalizationClientProxy applicationLocalizationClientProxy)
{
ApplicationConfigurationAppService = applicationConfigurationAppService;
CurrentUser = currentUser;
HttpContextAccessor = httpContextAccessor;
ApplicationLocalizationClientProxy = applicationLocalizationClientProxy;
Cache = cache;
}
@ -42,11 +45,7 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu
configuration = await Cache.GetOrAddAsync(
cacheKey,
async () => await ApplicationConfigurationAppService.GetAsync(
new ApplicationConfigurationRequestOptions
{
IncludeLocalizationResources = false
}),
async () => await GetRemoteConfigurationAsync(),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300) //TODO: Should be configurable.
@ -61,6 +60,24 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu
return configuration;
}
private async Task<ApplicationConfigurationDto> GetRemoteConfigurationAsync()
{
var config = await ApplicationConfigurationAppService.GetAsync(
new ApplicationConfigurationRequestOptions
{
IncludeLocalizationResources = false
}
);
var localizationDto = await ApplicationLocalizationClientProxy.GetAsync(
config.Localization.CurrentCulture.Name
);
config.Localization.Resources = localizationDto.Resources;
return config;
}
public ApplicationConfigurationDto Get()
{
var cacheKey = CreateCacheKey();

@ -2,5 +2,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
public class ApplicationConfigurationRequestOptions
{
/// <summary>
/// Set to true to fill the Values property in <see cref="ApplicationConfigurationDto.Localization"/>.
/// </summary>
public bool IncludeLocalizationResources { get; set; } = true;
}

@ -7,8 +7,23 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
[Serializable]
public class ApplicationLocalizationConfigurationDto
{
/// <summary>
/// This is not filled if <see cref="ApplicationConfigurationRequestOptions.IncludeLocalizationResources"/> is false.
/// </summary>
public Dictionary<string, Dictionary<string, string>> Values { get; set; }
/// <summary>
/// This property will never be filled by the application configuration endpoint
/// (by AbpApplicationConfigurationAppService). However, it is here to be filled
/// using the application localization endpoint (AbpApplicationLocalizationAppService).
/// This is an ugly design, but it is the best solution for backward-compability and
/// simple implementation.
///
/// It's client's responsibility to fill this property
/// using the application localization endpoint.
/// </summary>
public Dictionary<string, ApplicationLocalizationResourceDto> Resources { get; set; } = new();
public List<LanguageInfo> Languages { get; set; }
public CurrentCultureDto CurrentCulture { get; set; }

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
[Serializable]
public class ApplicationLocalizationDto
{
public Dictionary<string, ApplicationLocalizationResourceDto> Resources { get; set; }

@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
[Serializable]
public class ApplicationLocalizationResourceDto
{
public Dictionary<string, string> Texts { get; set; }
public List<string> BaseResources { get; set; }
public string[] BaseResources { get; set; }
}

@ -1,5 +1,8 @@
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using System;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
[Serializable]
public class CurrentCultureDto
{
public string DisplayName { get; set; }

@ -61,7 +61,7 @@ public class AbpApplicationLocalizationAppService :
localizationConfig.Resources[resource.ResourceName] =
new ApplicationLocalizationResourceDto {
Texts = dictionary,
BaseResources = resource.BaseResourceNames
BaseResources = resource.BaseResourceNames.ToArray()
};
}

Loading…
Cancel
Save