通过数据库加载实现动态管理,用户可以自己修改界面显示的文本,满足国际化需求
如图所示,前端使用tdesign vnext
新建表TSYS_Localization与TSYS_LocalizationDetail
国旗图标下载网址flag-icons: Free Country Flags in SVG
在Shared下创建下图3个文件
[Table("TSYS_LocalizationDetail")]public class LocalizedResource{public long Id { get; set; }public long CultureId { get; set; } [FreeSql.DataAnnotations.Navigate(nameof(CultureId))]public virtual LocalizedCulture? Culture { get; set; }public string Type { get; set; }public string Key { get; set; }public string Value { get; set; }public string Enable { get; set; }public DateTime CreationTime { get; set; }[FreeSql.DataAnnotations.JsonMap]public ExtraPropertyDictionary ExtraProperties { get; set; } = new ExtraPropertyDictionary();//public string LocalizedCultureName { get; set; }public LocalizedString GetLocalizedString(string cultureName){return new LocalizedString(Key, Value);}}[Table("TSYS_Localization")]public class LocalizedCulture{private string isDefault;public long Id { get; set; } public string Culture { get; set; }public string CultureName { get; set; }public string Icon { get; set; }public bool IsDefault { get => isDefault == "Y" ? true : false; set => isDefault = value ? "Y" : "N"; }}
public static class DatabaseLocalizationExtensions
{public static LocalizationResourceBase AddDatabase([NotNull] this LocalizationResourceBase localizationResource, string resourceName){Check.NotNull(localizationResource, nameof(localizationResource));localizationResource.Contributors.Add(new DatabaseLocalizationResourceContributor(resourceName));return localizationResource;}
}
public class DatabaseLocalizationResourceContributor : ILocalizationResourceContributor{private IFreeSql _freeSql;private readonly string _resourceName = null;public bool IsDynamic => false;private Dictionary<string, Dictionary<string, LocalizedString>> _resources = new Dictionary<string, Dictionary<string, LocalizedString>>();public DatabaseLocalizationResourceContributor(string resourceName = null){_resourceName = resourceName;}public void Initialize(LocalizationResourceInitializationContext context){_freeSql = context.ServiceProvider.GetRequiredService<IFreeSql>();var cultureName= CultureInfo.CurrentCulture.Name;if (cultureName!=null){var dic = _freeSql.Select<LocalizedResource>().Include(t => t.Culture).Where(t => t.Culture.Culture == cultureName).ToDictionary(t => string.IsNullOrEmpty(t.Type) ? t.Key : $"{t.Type}.{t.Key}", t => new LocalizedString(t.Key, t.Value));if (dic.Count>0){_resources.Add(cultureName, dic);}} }public LocalizedString GetOrNull(string cultureName, string name){if (!_resources.ContainsKey(cultureName)){var dic = _freeSql.Select<LocalizedResource>().Include(t => t.Culture).Where(t => t.Culture.Culture == cultureName).ToDictionary(t => string.IsNullOrEmpty(t.Type) ? t.Key : $"{t.Type}.{t.Key}", t => new LocalizedString(t.Key, t.Value));if (dic.Count > 0 && !_resources.ContainsKey(cultureName)){_resources.Add(cultureName, dic);}}if (_resources.ContainsKey(cultureName) && _resources[cultureName].ContainsKey(name)){return _resources[cultureName][name];}else{if (!_freeSql.Select<LocalizedResource>().Any(t => t.Key == name)){var localization = _freeSql.Queryable<LocalizedCulture>().ToList();List<LocalizedResource> localizedResources = new List<LocalizedResource>();foreach (var item in localization){LocalizedResource localizedResource = new LocalizedResource();localizedResource.Id = YitIdHelper.NextId();localizedResource.Key = name;localizedResource.CultureId = item.Id;localizedResource.Value = name;localizedResource.Type = "";localizedResource.CreationTime = DateTime.Now;localizedResource.Enable = "Y";localizedResources.Add(localizedResource);}_freeSql.Insert<LocalizedResource>(localizedResources).ExecuteAffrows();} if (cultureName.StartsWith("zh")){ return new LocalizedString(name, name);}else{return new LocalizedString(name, name);}}}public void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary){if (!_resources.ContainsKey(cultureName)){_resources.Add(cultureName, dictionary);}else{foreach (var item in dictionary){if (_resources[cultureName].ContainsKey(item.Key)){_resources[cultureName][item.Key] = item.Value;}else{_resources[cultureName].Add(item.Key, item.Value);}}}}//调用登录时接口时触发https://localhost:44356/Account/Loginpublic async Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary){if (!_resources.ContainsKey(cultureName)){_resources.Add(cultureName, dictionary);}else{foreach (var item in dictionary){if (_resources[cultureName].ContainsKey(item.Key)){_resources[cultureName][item.Key] = item.Value; }else{_resources[cultureName].Add(item.Key, item.Value);}}}}public Task<IEnumerable<string>> GetSupportedCulturesAsync(){var cultures=_freeSql.Select<LocalizedCulture>().ToList(t => t.Culture).AsEnumerable<string>();return Task.FromResult(cultures);}}
前端更改语言时调用后端加载多语言json
合并json使用lodash库
import merge from 'lodash/merge';
后台接口数据示例