qq5464642 发表于 2025-2-7 03:25:13

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{        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;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;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微信同号)
页: [1]
查看完整版本: Abp源码分析之Abp本地化