culture updates for requests

This commit is contained in:
2023-05-11 11:35:16 +02:00
parent 2aad6c06bd
commit 881990264c
5 changed files with 105 additions and 35 deletions
+8
View File
@@ -9,6 +9,9 @@ public class ZeroOptions : IZeroOptions
/// <inheritdoc />
public string Version { get; set; }
/// <inheritdoc />
public string Language { get; set; } = "en_US";
/// <inheritdoc />
public TimeSpan TokenExpiration { get; set; }
@@ -43,6 +46,11 @@ public interface IZeroOptions
/// </summary>
string Version { get; set; }
/// <summary>
/// ISO Code for language
/// </summary>
public string Language { get; set; }
/// <summary>
/// Expiration of a generated change token for an entity
/// </summary>
+1 -4
View File
@@ -8,12 +8,9 @@ public class ConfigurationLocalizer : Localizer
private IConfiguration _configuration;
public ConfigurationLocalizer(IConfiguration configuration, IOptionsMonitor<LocalizationOptions> options) : base()
public ConfigurationLocalizer(IConfiguration configuration, ICultureResolver cultureResolver, IOptionsMonitor<LocalizationOptions> options) : base(cultureResolver)
{
_configuration = configuration;
// set default language
Language(_configuration.GetValue<string>("Zero:Localization:Default", "de"));
}
@@ -0,0 +1,8 @@
using System.Globalization;
namespace zero.Localization;
public class CultureChangeMessage : IMessage
{
public CultureInfo Culture { get; set; }
}
+72 -12
View File
@@ -1,57 +1,117 @@
using FluentValidation;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.Extensions.Logging;
using System.Globalization;
using System.Linq.Expressions;
using System.Security.Claims;
namespace zero.Localization;
public class CultureResolver : ICultureResolver
{
/// <inheritdoc />
public CultureInfo Current { get; protected set; }
protected ILogger<CultureResolver> Logger { get; private set; }
protected IMessageAggregator MessageAggregator { get; private set; }
public CultureResolver(ILogger<CultureResolver> logger)
public CultureResolver(ILogger<CultureResolver> logger, IMessageAggregator messageAggregator)
{
Logger = logger;
MessageAggregator = messageAggregator;
}
/// <inheritdoc />
public Task<CultureInfo> Resolve(IZeroContext context)
{
//var session = context.Store.Session();
//Language language = await session.Query<Language>().FirstOrDefaultAsync();
string isoCode = "de-AT";
if (!TryConvert(context.Options.Language, out CultureInfo culture))
{
culture = CultureInfo.CurrentCulture;
}
Set(culture);
return Task.FromResult(culture);
}
/// <inheritdoc />
public bool TryConvert(string isoCode, out CultureInfo culture)
{
try
{
CultureInfo culture = CultureInfo.CreateSpecificCulture(isoCode);
culture = CultureInfo.CreateSpecificCulture(isoCode.Replace('_', '-'));
if (culture.ThreeLetterISOLanguageName.IsNullOrEmpty())
{
throw new Exception("ThreeLetterISOLanguageName is empty");
}
if (culture.ThreeLetterISOLanguageName == "ivl")
{
throw new Exception("Invariant language is not allowed");
}
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
ValidatorOptions.Global.LanguageManager.Culture = culture;
return true;
}
catch (Exception ex)
{
Logger.LogError(ex, "Could not create culture from Language code {code}", isoCode);
return Task.FromResult(CultureInfo.CurrentCulture);
Logger.LogWarning(ex, "Could not create culture from Language code {code}", isoCode);
culture = null;
return false;
}
return Task.FromResult(CultureInfo.CurrentCulture);
}
/// <inheritdoc />
public void Set(CultureInfo culture)
{
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
ValidatorOptions.Global.LanguageManager.Culture = culture;
Current = culture;
MessageAggregator.Publish(new CultureChangeMessage()
{
Culture = culture
});
}
/// <inheritdoc />
public void Subscribe(Expression<Func<CultureChangeMessage, Task>> handle)
{
MessageAggregator.Subscribe(handle);
}
}
public interface ICultureResolver
{
/// <summary>
/// Current culture
/// </summary>
CultureInfo Current { get; }
/// <summary>
/// Resolves the current application from either the backoffice user (in case it is backoffice request)
/// or the domain (in case it is frontend request).
/// </summary>
Task<CultureInfo> Resolve(IZeroContext context);
/// <summary>
/// Tries to convert an ISO code to a culture
/// </summary>
bool TryConvert(string isoCode, out CultureInfo culture);
/// <summary>
/// Set a new culture for this request
/// </summary>
void Set(CultureInfo culture);
/// <summary>
/// Subscribe to culture change
/// </summary>
void Subscribe(Expression<Func<CultureChangeMessage, Task>> handle);
}
+16 -19
View File
@@ -1,23 +1,30 @@
using System.Collections.Concurrent;
using System.Globalization;
using System.Reflection;
namespace zero.Localization;
public abstract class Localizer : ILocalizer
{
/// <inheritdoc />
public string LanguageCode { get; private set; } = "de";
protected ConcurrentDictionary<string, string> Cache { get; private set; } = new();
protected ICultureResolver CultureResolver { get; private set; }
/// <inheritdoc />
public ILocalizer Language(string languageCode)
protected string LanguageCode { get; set; }
public Localizer(ICultureResolver cultureResolver)
{
Cache = new();
LanguageCode = languageCode;
return this;
CultureResolver = cultureResolver;
CultureResolver.Subscribe(msg => OnCultureChange(msg.Culture));
OnCultureChange(CultureResolver.Current);
}
Task OnCultureChange(CultureInfo culture)
{
LanguageCode = culture.Name.Split(new char[] { '_', '-' })[0];
return Task.CompletedTask;
}
@@ -97,16 +104,6 @@ public abstract class Localizer : ILocalizer
public interface ILocalizer
{
/// <summary>
/// Current language code
/// </summary>
string LanguageCode { get; }
/// <summary>
/// Set language for localizer
/// </summary>
ILocalizer Language(string languageCode);
/// <summary>
///
/// </summary>