Files
MeWeb/src/MeWeb.App/Services/Localizer.cs
T

89 lines
2.7 KiB
C#
Raw Normal View History

using System.ComponentModel;
using System.Globalization;
using System.Text.Json;
using Avalonia.Data;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.MarkupExtensions;
namespace MeWeb.App.Services;
public sealed class Localizer : INotifyPropertyChanged
{
readonly Dictionary<string, string> english = Load(Languages.Fallback.Code);
Dictionary<string, string> current;
public Localizer() => current = english;
public static Localizer Instance { get; } = new();
public event PropertyChangedEventHandler PropertyChanged;
public Language Language { get; private set; } = Languages.Fallback;
public CultureInfo Culture { get; private set; } = CultureInfo.GetCultureInfo(Languages.Fallback.Code);
public bool IsRightToLeft => Language.Rtl;
public string this[string key] => current.GetValueOrDefault(key) ?? english.GetValueOrDefault(key) ?? key;
public string Format(string key, params object[] args)
{
try
{
return string.Format(Culture, this[key], args);
}
catch (FormatException)
{
return this[key];
}
}
public void SetLanguage(Language language)
{
Language = language ?? Languages.Fallback;
current = Language.Code == Languages.Fallback.Code ? english : Load(Language.Code);
Culture = CultureFor(Language.Code);
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.DefaultThreadCurrentUICulture = Culture;
CultureInfo.CurrentCulture = CultureInfo.CurrentUICulture = Culture;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty));
}
public static bool Has(string code) => typeof(Localizer).Assembly.GetManifestResourceInfo(ResourceName(code)) is not null;
static string ResourceName(string code) => $"strings.{code}.json";
static Dictionary<string, string> Load(string code)
{
using var stream = typeof(Localizer).Assembly.GetManifestResourceStream(ResourceName(code));
if (stream is null) return [];
return JsonSerializer.Deserialize(stream, AppJsonContext.Default.DictionaryStringString) ?? [];
}
static CultureInfo CultureFor(string code)
{
try
{
return CultureInfo.GetCultureInfo(code);
}
catch (CultureNotFoundException)
{
return CultureInfo.InvariantCulture;
}
}
}
public sealed class TrExtension : MarkupExtension
{
public TrExtension()
{
}
public TrExtension(string key) => Key = key;
public string Key { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) =>
new ReflectionBindingExtension($"[{Key}]") { Mode = BindingMode.OneWay, Source = Localizer.Instance }.ProvideValue(serviceProvider);
}