MailSharp / MailSharp.MailClient / Services / LocalizationService.cs
Code · 112 lines · 3005 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112using System.Collections.Concurrent;
using System.Globalization;
using System.Text.Json;

namespace MailSharp.MailClient.Services;

public class LocalizationService(IHttpContextAccessor httpContextAccessor, IWebHostEnvironment env)
{
	private readonly IHttpContextAccessor _httpContextAccessor = httpContextAccessor;
	private readonly string _localizationPath = Path.Combine(env.ContentRootPath, "Localization");

	private static readonly ConcurrentDictionary<string, Dictionary<string, string>> _cache = new();

	public string CurrentLanguage
	{
		get
		{
			var ctx = _httpContextAccessor.HttpContext;
			if (ctx?.Request.Cookies.TryGetValue("lang", out var lang) == true
				&& !string.IsNullOrEmpty(lang)
				&& File.Exists(Path.Combine(_localizationPath, lang + ".json")))
			{
				return lang;
			}
			return "nl";
		}
	}

	public CultureInfo Culture
	{
		get
		{
			try { return CultureInfo.GetCultureInfo(CurrentLanguage); }
			catch (CultureNotFoundException) { return CultureInfo.InvariantCulture; }
		}
	}

	public IEnumerable<(string Code, string Name)> AvailableLanguages()
	{
		if (!Directory.Exists(_localizationPath))
			yield break;

		var langs = Directory.GetFiles(_localizationPath, "*.json")
			.Select(file =>
			{
				var code = Path.GetFileNameWithoutExtension(file);
				var dict = GetDictionary(code);
				var name = dict.TryGetValue("__name__", out var n) ? n : code;
				var order = dict.TryGetValue("__order__", out var o) && int.TryParse(o, out var oi) ? oi : 999;
				return (code, name, order);
			})
			.OrderBy(x => x.order)
			.ThenBy(x => x.name);

		foreach (var (code, name, _) in langs)
			yield return (code, name);
	}

	public string this[string key]
	{
		get
		{
			var lang = CurrentLanguage;
			var dict = GetDictionary(lang);
			if (dict.TryGetValue(key, out var val)) return val;

			if (lang != "nl")
			{
				var fallback = GetDictionary("nl");
				if (fallback.TryGetValue(key, out var fallbackVal)) return fallbackVal;
			}

			return key;
		}
	}

	public string Format(string key, params object[] args)
	{
		try { return string.Format(this[key], args); }
		catch { return this[key]; }
	}

	public bool LanguageExists(string? lang) =>
		!string.IsNullOrEmpty(lang) && lang.Length <= 10 && lang.All(c => char.IsLetterOrDigit(c) || c == '-') &&
		File.Exists(Path.Combine(_localizationPath, lang + ".json"));

	public Dictionary<string, string> GetAllStrings(string? lang = null)
	{
		var code = LanguageExists(lang) ? lang! : CurrentLanguage;
		return GetDictionary(code)
			.Where(kv => !kv.Key.StartsWith("__"))
			.ToDictionary(kv => kv.Key, kv => kv.Value);
	}

	private Dictionary<string, string> GetDictionary(string lang)
	{
		return _cache.GetOrAdd(lang, code =>
		{
			var file = Path.Combine(_localizationPath, code + ".json");
			if (!File.Exists(file)) return [];
			try
			{
				var json = File.ReadAllText(file);
				return JsonSerializer.Deserialize<Dictionary<string, string>>(json) ?? [];
			}
			catch
			{
				return [];
			}
		});
	}
}