culture updates for requests
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user