Browse Source

Implement changes for RemoteLocalizationContributor.

pull/13845/head
Halil İbrahim Kalkan 4 years ago
parent
commit
a63b2dfc45
  1. 18
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs
  2. 113
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs
  3. 29
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs
  4. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationRequestOptions.cs
  5. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs
  6. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs
  7. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationResourceDto.cs
  8. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs
  9. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs

18
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs

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

113
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs

@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.Localization; using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.Client; namespace Volo.Abp.AspNetCore.Mvc.Client;
@ -25,87 +26,137 @@ public class RemoteLocalizationContributor : ILocalizationResourceContributor
?? NullLogger<RemoteLocalizationContributor>.Instance; ?? 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) if (resource == null)
{ {
return null; return null;
} }
var value = resource.GetOrDefault(name); var value = resource.Texts.GetOrDefault(name);
if (value == null) 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) if (resource == null)
{ {
return; 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); 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) if (resource == null)
{ {
return; 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); 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 /* This contributor does not know all the supported cultures by the
remote localization resource, and it is not needed on the client side */ remote localization resource, and it is not needed on the client side */
return Task.FromResult((IEnumerable<string>)Array.Empty<string>()); return Task.FromResult((IEnumerable<string>)Array.Empty<string>());
} }
private Dictionary<string, string> GetResourceOrNull() protected virtual ApplicationLocalizationResourceDto GetResourceOrNull(string resourceName)
{ {
var applicationConfigurationDto = _applicationConfigurationClient.Get(); var applicationConfigurationDto = _applicationConfigurationClient.Get();
return GetResourceOrNull(applicationConfigurationDto, resourceName);
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;
} }
private async Task<Dictionary<string, string>> GetResourceOrNullAsync() protected virtual async Task<ApplicationLocalizationResourceDto> GetResourceOrNullAsync(string resourceName)
{ {
var applicationConfigurationDto = await _applicationConfigurationClient.GetAsync(); 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 .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;
} }
} }

29
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs

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

3
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationRequestOptions.cs

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

15
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs

@ -7,8 +7,23 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
[Serializable] [Serializable]
public class ApplicationLocalizationConfigurationDto 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; } 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 List<LanguageInfo> Languages { get; set; }
public CurrentCultureDto CurrentCulture { get; set; } public CurrentCultureDto CurrentCulture { get; set; }

2
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs

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

4
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationResourceDto.cs

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

5
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs

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

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs

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

Loading…
Cancel
Save