ant-design-blazor/components/locale-provider/LocaleProvider.cs
agolub-s 8e60219b35
feat(module: datepicker): add mask to DatePickerBase for input value constraint (#3120)
* Add support multiple date formats for DatePickerBase

* Fix test

* Extend docs

* Fix merge

* Revert "Add support multiple date formats for DatePickerBase"

This reverts commit 9021dcdd

* Refactoring. Add mask property for DatePickerBase. For input value constraint.

* Some fixes

* Refactoring

* Add value converter for MaskInput

* Some fix

* fix Chinese

* Refactoring

* Fix tests

* Fix tests

* clean up

* Fix tests

* Pass mask to RangePicker

* Fix AvatarTests

* Fix merge

* Stage

* Stabilized tests

---------

Co-authored-by: James Yeung <shunjiey@hotmail.com>
2023-10-05 17:24:16 +08:00

166 lines
6.2 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using AntDesign.Locales;
namespace AntDesign
{
public class LocaleProvider
{
public static Locale CurrentLocale => GetCurrentLocale();
public static string DefaultLanguage = "en-US";
private static readonly ConcurrentDictionary<string, Locale> _localeCache = new ConcurrentDictionary<string, Locale>();
private static Assembly _resourcesAssembly = typeof(LocaleProvider).Assembly;
private static readonly IDictionary<string, string> _availableResources = GetAvailableResources();
private static IDictionary<string, string> GetAvailableResources()
{
var availableResources = _resourcesAssembly
.GetManifestResourceNames()
.Select(x => Regex.Match(x, @"^.*locales\.(.+)\.json"))
.Where(x => x.Success)
.ToDictionary(x => x.Groups[1].Value, x => x.Value);
foreach (var resource in availableResources.ToArray())
{
var parentCultureName = GetParentCultureName(resource.Key);
while (parentCultureName != string.Empty)
{
if (!availableResources.ContainsKey(parentCultureName))
{
availableResources.Add(parentCultureName, resource.Value);
}
parentCultureName = GetParentCultureName(parentCultureName);
}
}
return availableResources;
}
public static Locale GetCurrentLocale()
{
return GetLocale(CultureInfo.CurrentUICulture);
}
public static Locale GetLocale(string cultureName)
{
if (TryGetSpecifiedLocale(cultureName, out Locale locale)) return locale;
// fallback to parent CultureInfo
var parentCultureName = GetParentCultureName(cultureName);
if (parentCultureName != string.Empty)
{
if (TryGetSpecifiedLocale(parentCultureName, out locale))
{
AddClonedLocale(cultureName, ref locale);
return locale;
}
if (cultureName.Count(c => c == '-') == 2)
{
var lang = cultureName[..cultureName.IndexOf('-')];
var region = cultureName[cultureName.LastIndexOf('-')..];
if (TryGetSpecifiedLocale(lang + region, out locale))
{
AddClonedLocale(cultureName, ref locale);
return locale;
}
}
parentCultureName = GetParentCultureName(parentCultureName);
if (parentCultureName != string.Empty && TryGetSpecifiedLocale(parentCultureName, out locale))
{
AddClonedLocale(cultureName, ref locale);
return locale;
}
}
// fallback to default language
if (TryGetSpecifiedLocale(DefaultLanguage, out locale))
{
AddClonedLocale(cultureName, ref locale);
return locale;
}
// fallback to 'en-US'
TryGetSpecifiedLocale("en-US", out locale);
AddClonedLocale(cultureName, ref locale);
return locale;
}
public static Locale GetLocale(CultureInfo cultureInfo)
{
return GetLocale(cultureInfo.Name);
}
public static void SetLocale(string cultureName, Locale locale = null)
{
var culture = CultureInfo.GetCultureInfo(cultureName);
if (culture != null)
{
CultureInfo.DefaultThreadCurrentUICulture = culture;
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
if (locale != null)
{
locale.SetCultureInfo(cultureName);
_localeCache.AddOrUpdate(cultureName, locale, (name, original) => locale);
}
}
private static bool TryGetSpecifiedLocale(string cultureName, out Locale locale)
{
if (!_availableResources.ContainsKey(cultureName)) return _localeCache.TryGetValue(cultureName, out locale);
locale = _localeCache.GetOrAdd(cultureName, key =>
{
string fileName = _availableResources[key];
using var fileStream = _resourcesAssembly.GetManifestResourceStream(fileName);
if (fileStream == null) return null;
using var streamReader = new StreamReader(fileStream);
var content = streamReader.ReadToEnd();
var serializerOptions = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
};
serializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
var result = JsonSerializer.Deserialize<Locale>(content, serializerOptions);
result.SetCultureInfo(key);
return result;
});
return true;
}
private static void AddClonedLocale(string cultureName, ref Locale locale)
{
locale = JsonSerializer.Deserialize<Locale>(
JsonSerializer.Serialize(locale, new JsonSerializerOptions { IgnoreReadOnlyProperties = true }));
locale.SetCultureInfo(cultureName);
_localeCache.TryAdd(cultureName, locale);
}
private static string GetParentCultureName(string name)
{
if (string.IsNullOrWhiteSpace(name)) return "";
try
{
return CultureInfo.GetCultureInfo(name).Parent.Name;
}
catch (Exception)
{
if (name.Contains("-")) return name[0..name.LastIndexOf("-")];
else return "";
}
}
}
}