基于EF Core存储的国际化服务

前言

.NET 官方有一个用来管理国际化资源的扩展包Microsoft.Extensions.LocalizationASP.NET Core也用这个来实现国际化功能。但是这个包的翻译数据是使用resx资源文件来管理的,这就意味着无法动态管理。虽然官方有在文档中提供了一些第三方管理方案,但是都不太方便。其中一个是基于Json文件的,虽然可以动态管理,但是正确的Key值有时很难猜对,特别是对于嵌套类和泛型类之类名字比较特殊的。另外两个基于EF Core的一个只是个demo;另一个已多年未更新,且上下文生命周期和并发管理有缺陷(这个库还是我提交pr才支持的 .NET 5)。最近项目有用到国际化功能,只好重新写一个。

新书宣传

有关新书的更多介绍欢迎查看《C#与.NET6 开发从入门到实践》上市,作者亲自来打广告了!

相关旧文

Asp.Net Core 混合全球化与本地化支持

正文

这个扩展包代码不多也不算复杂,主要结构参考官方内置实现。对于 .NET 5以上支持上下文工厂的版本使用上下文工厂,而对于旧版本则创建内部作用域获取私有上下文,以此彻底避免并发问题。作用域和上下文都是需要查询时临时获取和使用,查询完数据立即销毁避免内存泄漏。如果使用池化上下文工厂性能会更好。

对代码感兴趣的朋友可以移步Github。这里直接介绍一下基本用法。

这个库分为三个包:抽象包定义了所需接口,实体模型包定义基本实体类型,功能包定义了服务接口的实现类和用于注册服务的扩展方法。方便为分离项目的解决方案按需引用,减少无关类型的污染。

以在ASP.NET Core中使用为例:

实体模型和上下文

csharp 复制代码
public class YourLocalizationRecord : LocalizationRecord
{
    public int YourProperty { get; set; }
}

public class YourDbContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 使用默认类型。
        modelBuilder.UseLocalizationRecord();

        // 使用自定义类型,需要继承LocalizationRecord。
        modelBuilder.UseLocalizationRecord<YourLocalizationRecord>(b =>
        {
            b.Property(r => r.ResourceCulture).HasMaxLength(32);
            b.ToTable($"{nameof(YourLocalizationRecord)}s");
        });
    }
}

服务注册

csharp 复制代码
// 对于 .NET 5 以上请使用上下文工厂。
services.AddDbContextFactoty<YourDbContext>(options => options.UseSqlite("Localization.db"));
// 或者池化工厂也是一样的,而且更好。
services.AddPooledDbContextFactoty<YourDbContext>(options => options.UseSqlite("Localization.db"));
// 注册一个自定义工厂服务模拟作用域上下文服务
services.AddScoped<YourDbContext>(sp => sp.GetRequiredService<IDbContextFactory<YourDbContext>>().CreateDbContext());

// 对于 .NETStandard 2.0 或 2.1 请使用上下文。
services.AddDbContext<YourDbContext>(options => options.UseSqlite("Localization.db"));

// 注册使用默认实体类型的服务。
services.AddEntityFrameworkCoreLocalization<YourDbContext>(options =>
{
    options.ResourcesPath = "Resources";
    // 是否自动创建缺失的资源记录
    options.CreateLocalizationResourcesIfNotExist = true;
});

//  注册使用自定义实体类型的服务。
services.AddEntityFrameworkCoreLocalization<YourDbContext, YourLocalizationRecord>(options =>
{
    options.ResourcesPath = "Resources";
    // 是否自动创建缺失的资源记录
    options.CreateLocalizationResourcesIfNotExist = true;
});

其他的和官方文档用法完全一致,如果需要清除缓存使资源能在下次读取时更新,可以使用服务IDynamicResourceStringLocalizerFactory。这个服务继承自内置服务,获取的IStringLocalizerFactory服务实际上也是IDynamicResourceStringLocalizerFactory的实现。

既然已经有上下文了,想怎么读写数据应该不必多言了吧。实体类的属性LocalizedContent就是翻译后的文本。如果使用自动创建记录,只需要查找所有这个属性为null的记录并翻译保存,最后清除缓存即可。

结语

为了实现对 .NETStantard 2.0 的兼容代码上使用了条件编译预处理实现一份代码一个项目同时编译到所有框架,最大程度共用代码简化代码管理。

附上国际化官方文档:使 ASP.NET Core 应用内容可本地化在本地化 ASP.NET Core 应用中为每个请求选择语言/区域性

许可证:MIT

代码仓库:CoreDX.Extensions.Localization.EntityFrameworkCore - Github

Nuget:CoreDX.Extensions.Localization.EntityFrameworkCore

Nuget:CoreDX.Extensions.Localization.EntityFrameworkCore.Abstractions

Nuget:CoreDX.Extensions.Localization.EntityFrameworkCore.Models

QQ群

读者交流QQ群:540719365

欢迎读者和广大朋友一起交流,如发现本书错误也欢迎通过博客园、QQ群等方式告知笔者。

本文地址:https://www.cnblogs.com/coredx/p/18294729.html

相关推荐
小羊没烦恼!14 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
神仙别闹14 小时前
基于C#+MySQL实现(WinForm)个人聊天室软件
c#
kybs199117 小时前
全球灾害数据分析可视化 毕业设计-附源码66794
vue.js·spring boot·mysql·安全·django·c#·asp.net
Polevne21 小时前
C# SFTP客户端实现文件传输
c#·ssh
samble21 小时前
从零搭建灌装监控系统(四):深色主题与样式系统,ResourceDictionary 统一管理
c#·wpf·mvvm·样式·工业控制
cjp5601 天前
024 . WPF MVVM类封装优化
c#
淡海水1 天前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
asdzx671 天前
如何使用 C# 提取 PPT 文本与图片
c#·ppt·提取文本
2501_930707782 天前
使用C#代码使用条件格式为 Excel 隔行设置颜色
c#·excel
何以解忧唯有撸码2 天前
【开源】c#造个轮子-日程安排工具
c#·自定义控件