net9 abp vnext 多语言通过数据库动态管理

news/2024/12/2 18:02:29/

通过数据库加载实现动态管理,用户可以自己修改界面显示的文本,满足国际化需求

如图所示,前端使用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';

后台接口数据示例


http://www.ppmy.cn/news/1551809.html

相关文章

Network Link Conditioner Mac 上模拟网络环境工具的安装和使用

前言 Xcode 的模拟器本身是不支持模拟网络环境的&#xff0c;在开发界面的时候&#xff0c;设计会出无网、弱网这种情况的设计图&#xff0c;为了方便在开发过程中实现这些情况的代码逻辑&#xff0c;Network Link Conditioner 就是模拟网络环境的好帮手。 安装 Network Lin…

C语言——指针基础

1 指针基础 怎么获得变量地址 1 如何产生一个指针变量——>类型* 标识符;int* p1;char* p2;double* p3;//不同类型的基本指针占用内存是一样的都是4个字节&#xff08;32位&#xff09;/8个字节&#xff08;64位&#xff09;&#xff0c;都是存的地址2 数组名是数组首地址…

git使用记录与总结

目录 前言 一、git是什么&#xff1f; 二、使用记录 1.git安装 2.git clone 3.-lfs初始化 4.git add 5.git commit 6.git push 相关问题与解决 总结 前言 随着Github、hugging face等平台各种开源代码、模型的广泛使用&#xff0c;个人可以使用git方便的下载代码与…

群控系统服务端开发模式-应用开发-前端邮箱短信通道开发

一、添加视图 在根目录下src文件夹下views文件夹下param文件夹下emailsms文件夹下&#xff0c;新建index.vue&#xff0c;代码如下 <template><el-tabs type"border-card"><el-tab-pane v-if"$store.getters.butts.includes(ParamEmailsmsIndex…

Linux常用操作之vim快捷操作

文章目录 前言一、vim三种工作模式二、命令行模式操作三、编辑模式操作四、末行模式操作五、vim快速注释多行操作六、vim快速取消多行注释操作 前言 在使用Linux操作系统时,经常会使用vi/vim编辑文件,会涉及到文件内容的删除、注释、增加等&#xff0c;如果改动的地方较多,那么…

工厂方法模式与抽象工厂模式

首先是一个工厂方法模式&#xff1a; #include <iostream> #include <string> using namespace std;// 抽象产品类 class Car { public:virtual void Run() 0; // 纯虚函数&#xff0c;定义产品接口virtual ~Car() {} // 虚析构函数&#xff0c;保证多态删除 };/…

java——Spring中的Bean线程安全问题

Spring中的Bean对象是否线程安全取决于多个因素&#xff0c;包括Bean的作用域&#xff08;scope&#xff09;、Bean的实现方式以及如何使用这些Bean。以下是一些关键点来帮助理解Spring中Bean的线程安全性&#xff1a; 1. Bean的作用域 Singleton (默认作用域)&#xff1a;在…

Ardupilot开源无人机之Geek SDK讨论

Ardupilot开源无人机之Geek SDK讨论 1. 源由2. 假设3. 思考3.1 结构构型3.2 有限资源3.3 软硬件构架 4.Ardupilot构架 - 2024kaga Update5. 讨论5.1 话题1&#xff1a;工作模式5.2 话题2&#xff1a;关键要点5.3 话题3&#xff1a;产品设计 6. Geek SDK - OpenFire6.1 开源技术…