Abp源码分析之Abp本地化
aspnetcore mvc 实现本地化
新建mvc项目

修改Program.cs
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
using System.Globalization;
var builder = WebApplication.CreateBuilder(args);
var supportedCultures = new[]
{
new CultureInfo("zh-CN"),
new CultureInfo("en-US"),
};
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
options.DefaultRequestCulture = new RequestCulture("zh-CN");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.AddControllersWithViews()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
var app = builder.Build();
app.UseRequestLocalization();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
跟本地化有关的代码
var supportedCultures = new[]
{
new CultureInfo("zh-CN"),
new CultureInfo("en-US"),
};
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
options.DefaultRequestCulture = new RequestCulture("zh-CN");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.AddControllersWithViews()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
app.UseRequestLocalization();
新建Resources目录,内容如下



修改Index.cshtml
@using Microsoft.Extensions.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using WebApplication1.Controllers
@inject IHtmlLocalizer<HomeController> HtmlLocalizer
@inject IStringLocalizer<HomeController> StringLocalizer
@inject IViewLocalizer ViewLocalizer
@{
ViewData["Title"] = "Home Page";
}
<div>string: @StringLocalizer["HelloWorld"]</div>
<div>html: @HtmlLocalizer["HelloWorld"]</div>
<div>view: @ViewLocalizer["HelloWorld"]</div>
访问首页


使用Json资源文件
新建mvc项目

安装WeihanLi.Extensions.Localization.Json包

我为了研究方便,下载了源码,所以引用了源码项目,我们正式使用时只要安装nuget包就可以了
修改Program.cs
using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
using WeihanLi.Extensions.Localization.Json;
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
// Add services to the container.
builder.Services.AddControllersWithViews();
var supportedCultures = new[]
{
new CultureInfo("zh-CN"),
new CultureInfo("en-US"),
};
services.Configure<RequestLocalizationOptions>(options =>
{
options.DefaultRequestCulture = new RequestCulture("zh-CN");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
var resourcesPath = builder.Configuration.GetAppSetting("ResourcesPath") ?? "Resources";
services.AddJsonLocalization(options =>
{
options.ResourcesPath = resourcesPath;
// options.ResourcesPathType = ResourcesPathType.TypeBased;
options.ResourcesPathType = ResourcesPathType.CultureBased;
});
services.AddControllersWithViews()
.AddMvcLocalization(options =>
{
options.ResourcesPath = resourcesPath;
}, LanguageViewLocationExpanderFormat.Suffix);
var app = builder.Build();
app.UseRequestLocalization();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
与aspnetcore原始的代码仅一下不同
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
改为:
services.AddJsonLocalization(options =>
{
options.ResourcesPath = resourcesPath;
// options.ResourcesPathType = ResourcesPathType.TypeBased;
options.ResourcesPathType = ResourcesPathType.CultureBased;
});
资源文件文件目录

内容:


源码分析

就是写了一个类JsonStringLocalizerFactory实现了IStringLocalizerFactory
写了JsonStringLocalizer实现了IStringLocalizer
在JsonStringLocalizer类的GetResources中加载json文件
private Dictionary<string, string> GetResources(string culture)
{
return _resourcesCache.GetOrAdd(culture, _ =>
{
var resourceFile = "json";
if (_resourcesPathType == ResourcesPathType.TypeBased)
{
resourceFile = $"{culture}.json";
if (_resourceName != null)
{
resourceFile = string.Join(".", _resourceName.Replace('.', Path.DirectorySeparatorChar), resourceFile);
}
}
else
{
resourceFile = string.Join(".",
Path.Combine(culture, _resourceName.Replace('.', Path.DirectorySeparatorChar)), resourceFile);
}
_searchedLocation = Path.Combine(_resourcesPath, resourceFile);
Dictionary<string, string> value = null;
if (File.Exists(_searchedLocation))
{
try
{
using var stream = File.OpenRead(_searchedLocation);
value = JsonSerializer.Deserialize<Dictionary<string, string>>(stream);
}
catch (Exception e)
{
_logger.LogError(e, "Failed to get json content, path: {path}", _searchedLocation);
}
}
else
{
_logger.LogWarning("Resource file {path} not exists", _searchedLocation);
}
return value;
});
}
ABP本地化
新建mvc项目 导入下面四个包

## 新建BookAppWebModule.cs
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
using Volo.Abp.Autofac;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.Hosting.Internal;
using BookApp.Localization;
namespace BookApp
{
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpLocalizationModule),
typeof(AbpVirtualFileSystemModule),
typeof(AbpAspNetCoreMvcModule)
)]
public class BookAppWebModule: AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(
typeof(BookStoreResource)
);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
ConfigureVirtualFileSystem(hostingEnvironment);
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("ar", "ar", "العربية"));
options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish"));
options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch"));
options.Languages.Add(new LanguageInfo("es", "es", "Español"));
options.Resources
.Add<BookStoreResource>("en")
.AddVirtualJson("/Localization/BookStore");
options.DefaultResourceType = typeof(BookStoreResource);
});
//context.Services.AddControllersWithViews()
// .AddMvcLocalization(options =>
// {
// options.ResourcesPath = "/Localization/BookStore";
// }, LanguageViewLocationExpanderFormat.Suffix);
//Configure<AbpExceptionLocalizationOptions>(options =>
//{
// options.MapCodeNamespace("BookStore", typeof(BookStoreResource));
//});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
app.UseAbpRequestLocalization();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
}
private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BookAppWebModule>();
if (hostingEnvironment.IsDevelopment())
{
options.FileSets.ReplaceEmbeddedByPhysical<BookAppWebModule>(hostingEnvironment.ContentRootPath);
}
});
}
}
}
修改Program.cs
using BookApp;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
builder.Host
.AddAppSettingsSecretsJson()
.UseAutofac();
await builder.AddApplicationAsync<BookAppWebModule>();
var app = builder.Build();
await app.InitializeApplicationAsync();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
await app.RunAsync();
新建资源文件与目录

en.json内容


我们只用到AppName
新建BookStoreResource.cs
using Volo.Abp.Localization;
namespace BookApp.Localization;
[LocalizationResourceName("BookStore")]
public class BookStoreResource
{
}
修改Index.cshtml
@using Microsoft.Extensions.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using BookApp.Controllers
@using BookApp.Localization
@inject IHtmlLocalizer<BookStoreResource> HtmlLocalizer
@inject IStringLocalizer<BookStoreResource> StringLocalizer
@inject IViewLocalizer ViewLocalizer
@{
ViewData["Title"] = "Home Page";
}
<div>string: @StringLocalizer["AppName"]</div>
<div>html: @HtmlLocalizer["AppName"]</div>
<div>view: @ViewLocalizer["AppName"]</div>
显示效果


源码分析
AbpLocalizationModule.cs中
using Volo.Abp.Localization.Resources.AbpLocalization;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
using Volo.Abp.Threading;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Localization;
[DependsOn(
typeof(AbpVirtualFileSystemModule),
typeof(AbpSettingsModule),
typeof(AbpLocalizationAbstractionsModule),
typeof(AbpThreadingModule)
)]
public class AbpLocalizationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
AbpStringLocalizerFactory.Replace(context.Services);
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpLocalizationModule>("Volo.Abp", "Volo/Abp");
});
Configure<AbpLocalizationOptions>(options =>
{
options
.Resources
.Add<DefaultResource>("en");
options
.Resources
.Add<AbpLocalizationResource>("en")
.AddVirtualJson("/Localization/Resources/AbpLocalization");
});
}
}
我们查看AbpStringLocalizerFactory.Replace(context.Services);的内容
internal static void Replace(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Singleton<IStringLocalizerFactory, AbpStringLocalizerFactory>());
services.AddSingleton<ResourceManagerStringLocalizerFactory>();
}
我们发现自定义的AbpStringLocalizerFactory实现了IStringLocalizerFactory
AbpDictionaryBasedStringLocalizer实现了IStringLocalizer

跟踪GetLocalizedString()

在这里读取json文件
相关文章
[理解ASP.NET Core - 全球化&本地化&多语言(Globalization and Localization) ](理解ASP.NET Core - 全球化&本地化&多语言(Globalization and Localization) - xiaoxiaotank - 博客园)
作者
吴晓阳(手机:13736969112微信同号)
Abp源码分析之Abp本地化的更多相关文章
- ABP源码分析十二:本地化
本文逐个分析ABP中涉及到locaization的接口和类,以及相互之间的关系.本地化主要涉及两个方面:一个是语言(Language)的管理,这部分相对简单.另一个是语言对应得本地化资源(Locali ...
- ABP源码分析四十三:ZERO的本地化
ABP Zero模块扩展了ABP基础框架中的本地化功能,实现了通过数据库管理本地化的功能.其通过数据库保存本地化语言及其资源. ApplicationLanguage:代表本地化语言的实体类.一种语言 ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- ABP源码分析四:Configuration
核心模块的配置 Configuration是ABP中设计比较巧妙的地方.其通过AbpStartupConfiguration,Castle的依赖注入,Dictionary对象和扩展方法很巧妙的实现了配 ...
- ABP源码分析九:后台工作任务
文主要说明ABP中后台工作者模块(BackgroundWorker)的实现方式,和后台工作模块(BackgroundJob).ABP通过BackgroundWorkerManager来管理Backgr ...
- ABP源码分析二十二:Navigation
MenuDefinition:封装了导航栏上的主菜单的属性. MenuItemDefinition:封装了主菜单的子菜单的属性.子菜单可以引用其他子菜单构成一个菜单树 UserMenu/UserMen ...
- ABP源码分析三十三:ABP.Web
ABP.Web模块并不复杂,主要完成ABP系统的初始化和一些基础功能的实现. AbpWebApplication : 继承自ASP.Net的HttpApplication类,主要完成下面三件事一,在A ...
- ABP源码分析三十四:ABP.Web.Mvc
ABP.Web.Mvc模块主要完成两个任务: 第一,通过自定义的AbpController抽象基类封装ABP核心模块中的功能,以便利的方式提供给我们创建controller使用. 第二,一些常见的基础 ...
- ABP源码分析四十二:ZERO的身份认证
ABP Zero模块通过自定义实现Asp.Net Identity完成身份认证功能, 对Asp.Net Identity做了较大幅度的扩展.同时重写了ABP核心模块中的permission功能,以实现 ...
- ABP源码分析四十四:ZERO的配置
ABP Zero模块中需要配置的地方主要集中在三块:配置静态的role,配置外部认证源,以及配置本地化语言和资源. UserManagementConfig/IUserManagementConfig ...
随机推荐
- 颗粒流 + Janssen 定律 + Bagnold 数
对于 \(n\) 个球,易得有 \[\begin{array}{c} \displaystyle\frac\pi2>\theta_i>-\frac\pi2,\theta_1>\cdo ...
- AvaloniaChat-v0.0.2:兼容智谱AI 快速使用指南
智谱AI介绍 北京智谱华章科技有限公司(简称"智谱AI")致力于打造新一代认知智能大模型,专注于做大模型的中国创新.公司合作研发了中英双语千亿级超大规模预训练模型GLM-130B, ...
- WPF 设备输入事件封装
本文主要介绍WPF应用对鼠标输入.触摸屏触笔以及触摸事件的封装 之前有简单说明设备输入类型 WPF 屏幕点击的设备类型 - 唐宋元明清2188 - 博客园 (cnblogs.com) 1.鼠标 - 通 ...
- CDH添加es服务
地址:https://blog.csdn.net/guoliduo/article/details/105072857 注意:目前只支持cdh5.x的版本安装es,cdh6.x暂不支持.
- 3d格式介绍之OBJ格式
OBJ格式是一种用于3D模型的文件格式,全称为Wavefront OBJ.它由Wavefront Technologies公司开发,最初用于其高级视觉动画软件,但后来广泛应用于各种3D图形软件中. 本 ...
- LLM大模型基础知识学习总结
大家好,我是Edison. 在这个已经被AI大模型包围的时代,不了解一点大模型的基础知识和相关概念,可能出去聊天都接不上话.刚好近期我也一直在用GPT和GitHub Copilot,也刚好对这些基础知 ...
- 【YashanDB知识库】生成迁移报告失败,"报错未知类型错误异常:"
[标题]YMP迁移 [问题分类]迁移报告 [关键字]迁移报告.未知类型错误异常 [问题描述]下载迁移报告时报错"未知类型错误异常:",一长串英文 日志报错: [问题原因分析]jav ...
- mysql事务隔离级别及MVCC 原理
一.事务的隔离级别 为了保证事务与事务之间的修改操作不会互相影响,innodb希望不同的事务是隔离的执行的,互不干扰. 两个并发的事务在执行过程中有 读读.读写(一个事务在读某条数据的同时另一个事务在 ...
- LeetCode 二叉树的最近公共祖先
一.二叉搜索树的最近公共祖先 利用二叉搜索树的性质,祖先的两个孩子,左孩子的小于根节点的值,右孩子大于根节点的值. 如果根节点的值,同时大于p的值和q的值,那么在左子树找根节点: 如果根节点的值,同时 ...
- 小tips:微信小程序登录后返回登录前的页面继续操作(保留参数)
在app.js中添加如下两个方法即可: // 设置需要回调的地址 setCallbackUrl: function(mode) { return new Promise((resolve,reject ...