前言 .NET 官方有一個用來管理國際化資源的擴展包Microsoft.Extensions.Localization,ASP.NET Core也用這個來實現國際化功能。但是這個包的翻譯數據是使用resx資源文件來管理的,這就意味著無法動態管理。雖然官方有在文檔中提供了一些第三方管理方案,但是都不太 ...
前言
.NET 官方有一個用來管理國際化資源的擴展包Microsoft.Extensions.Localization
,ASP.NET Core也用這個來實現國際化功能。但是這個包的翻譯數據是使用resx資源文件來管理的,這就意味著無法動態管理。雖然官方有在文檔中提供了一些第三方管理方案,但是都不太方便。其中一個是基於Json文件的,雖然可以動態管理,但是正確的Key值有時很難猜對,特別是對於嵌套類和泛型類之類名字比較特殊的。另外兩個基於EF Core的一個只是個demo;另一個已多年未更新,且上下文生命周期和併發管理有缺陷(這個庫還是我提交pr才支持的 .NET 5)。最近項目有用到國際化功能,只好重新寫一個。
新書宣傳
有關新書的更多介紹歡迎查看《C#與.NET6 開發從入門到實踐》上市,作者親自來打廣告了!
相關舊文
正文
這個擴展包代碼不多也不算複雜,主要結構參考官方內置實現。對於 .NET 5以上支持上下文工廠的版本使用上下文工廠,而對於舊版本則創建內部作用域獲取私有上下文,以此徹底避免併發問題。作用域和上下文都是需要查詢時臨時獲取和使用,查詢完數據立即銷毀避免記憶體泄漏。如果使用池化上下文工廠性能會更好。
對代碼感興趣的朋友可以移步Github。這裡直接介紹一下基本用法。
這個庫分為三個包:抽象包定義了所需介面,實體模型包定義基本實體類型,功能包定義了服務介面的實現類和用於註冊服務的擴展方法。方便為分離項目的解決方案按需引用,減少無關類型的污染。
以在ASP.NET Core中使用為例:
實體模型和上下文
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");
});
}
}
服務註冊
// 對於 .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