diff --git a/zero/Configuration/ZeroOptions.cs b/zero/Configuration/ZeroOptions.cs
index 483bf31a..d469e274 100644
--- a/zero/Configuration/ZeroOptions.cs
+++ b/zero/Configuration/ZeroOptions.cs
@@ -9,6 +9,9 @@ public class ZeroOptions : IZeroOptions
///
public string Version { get; set; }
+ ///
+ public string Language { get; set; } = "en_US";
+
///
public TimeSpan TokenExpiration { get; set; }
@@ -43,6 +46,11 @@ public interface IZeroOptions
///
string Version { get; set; }
+ ///
+ /// ISO Code for language
+ ///
+ public string Language { get; set; }
+
///
/// Expiration of a generated change token for an entity
///
diff --git a/zero/Localization/ConfigurationLocalizer.cs b/zero/Localization/ConfigurationLocalizer.cs
index 6e3a9431..4fa20668 100644
--- a/zero/Localization/ConfigurationLocalizer.cs
+++ b/zero/Localization/ConfigurationLocalizer.cs
@@ -8,12 +8,9 @@ public class ConfigurationLocalizer : Localizer
private IConfiguration _configuration;
- public ConfigurationLocalizer(IConfiguration configuration, IOptionsMonitor options) : base()
+ public ConfigurationLocalizer(IConfiguration configuration, ICultureResolver cultureResolver, IOptionsMonitor options) : base(cultureResolver)
{
_configuration = configuration;
-
- // set default language
- Language(_configuration.GetValue("Zero:Localization:Default", "de"));
}
diff --git a/zero/Localization/CultureChangeMessage.cs b/zero/Localization/CultureChangeMessage.cs
new file mode 100644
index 00000000..5f73d7f6
--- /dev/null
+++ b/zero/Localization/CultureChangeMessage.cs
@@ -0,0 +1,8 @@
+using System.Globalization;
+
+namespace zero.Localization;
+
+public class CultureChangeMessage : IMessage
+{
+ public CultureInfo Culture { get; set; }
+}
\ No newline at end of file
diff --git a/zero/Localization/CultureResolver.cs b/zero/Localization/CultureResolver.cs
index c612145a..bbf98a8a 100644
--- a/zero/Localization/CultureResolver.cs
+++ b/zero/Localization/CultureResolver.cs
@@ -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
{
+ ///
+ public CultureInfo Current { get; protected set; }
+
protected ILogger Logger { get; private set; }
+ protected IMessageAggregator MessageAggregator { get; private set; }
- public CultureResolver(ILogger logger)
+
+ public CultureResolver(ILogger logger, IMessageAggregator messageAggregator)
{
Logger = logger;
+ MessageAggregator = messageAggregator;
}
///
public Task Resolve(IZeroContext context)
{
- //var session = context.Store.Session();
- //Language language = await session.Query().FirstOrDefaultAsync();
- string isoCode = "de-AT";
+ if (!TryConvert(context.Options.Language, out CultureInfo culture))
+ {
+ culture = CultureInfo.CurrentCulture;
+ }
+ Set(culture);
+
+ return Task.FromResult(culture);
+ }
+
+
+ ///
+ 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);
+ }
+
+
+ ///
+ public void Set(CultureInfo culture)
+ {
+ CultureInfo.CurrentCulture = culture;
+ CultureInfo.CurrentUICulture = culture;
+ ValidatorOptions.Global.LanguageManager.Culture = culture;
+ Current = culture;
+ MessageAggregator.Publish(new CultureChangeMessage()
+ {
+ Culture = culture
+ });
+ }
+
+
+ ///
+ public void Subscribe(Expression> handle)
+ {
+ MessageAggregator.Subscribe(handle);
}
}
public interface ICultureResolver
{
+ ///
+ /// Current culture
+ ///
+ CultureInfo Current { get; }
+
///
/// Resolves the current application from either the backoffice user (in case it is backoffice request)
/// or the domain (in case it is frontend request).
///
Task Resolve(IZeroContext context);
+
+ ///
+ /// Tries to convert an ISO code to a culture
+ ///
+ bool TryConvert(string isoCode, out CultureInfo culture);
+
+ ///
+ /// Set a new culture for this request
+ ///
+ void Set(CultureInfo culture);
+
+ ///
+ /// Subscribe to culture change
+ ///
+ void Subscribe(Expression> handle);
}
diff --git a/zero/Localization/Localizer.cs b/zero/Localization/Localizer.cs
index e2956c30..d6f51af2 100644
--- a/zero/Localization/Localizer.cs
+++ b/zero/Localization/Localizer.cs
@@ -1,23 +1,30 @@
using System.Collections.Concurrent;
+using System.Globalization;
using System.Reflection;
namespace zero.Localization;
public abstract class Localizer : ILocalizer
{
- ///
- public string LanguageCode { get; private set; } = "de";
-
-
protected ConcurrentDictionary Cache { get; private set; } = new();
+ protected ICultureResolver CultureResolver { get; private set; }
- ///
- 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
{
- ///
- /// Current language code
- ///
- string LanguageCode { get; }
-
- ///
- /// Set language for localizer
- ///
- ILocalizer Language(string languageCode);
-
///
///
///