当前位置: 首页 > news >正文

ABP vNext 多语言与本地化:动态切换、资源继承与热更新

🚀 ABP vNext 多语言与本地化:动态切换、资源继承与热更新 🎉


📩 用户请求
🛠️ UseRequestLocalization
🔍 QueryString / Cookie / Accept-Language
🌍 确定 CultureInfo
📦 加载 JSON 资源 (嵌入/物理)
🔤 注入 IStringLocalizer 渲染文本
🔄 资源回退链: Shared → Validation → UI → Custom
🖥️ Blazor / Razor / JS 前端渲染

📑 目录

  • 🚀 ABP vNext 多语言与本地化:动态切换、资源继承与热更新 🎉
    • 📌 前置 `using` 声明
    • 🚀 模块化资源 & 默认文化
      • 📁 目录结构 & 嵌套分组示例
      • 📝 注册资源:DefaultResourceCulture vs SupportedCultures
    • 🔧 请求本地化管道 & 中间件顺序
    • 🌐 前端多端渲染示例
      • 1. Razor / MVC
      • 2. Blazor Server / WASM 完整 CultureSwitcher
    • 🔄 运行时切换 & 安全 Cookie
    • 🔥 开发环境 JSON 热更新
    • 🔗 资源继承与回退顺序
    • 🧪 集成测试覆盖示例
    • 📈 监控 & 日志埋点
    • 📅 日期/数字格式化示例
    • 💻 Angular/React 前端示例
    • ✅ 总结一览


📌 前置 using 声明

using System.Globalization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Volo.Abp.Localization;
using Volo.Abp.VirtualFileSystem;

🚀 模块化资源 & 默认文化

📁 目录结构 & 嵌套分组示例

Localization/
└── YourModule/├── en.json└── zh-Hans.json

示例(zh-Hans.json)

{"User": {"Greeting": "你好,{0}","Profile": "个人信息"},"Validation": {"FieldIsRequired": "这是必填字段"}
}

📝 注册资源:DefaultResourceCulture vs SupportedCultures

Configure<AbpLocalizationOptions>(options =>
{options.Resources// "zh-Hans" 是 DefaultResourceCulture(资源回退基准),非 SupportedCultures.Add<YourResource>("zh-Hans")// 回退链注释:SharedResource → AbpValidationResource → AbpUiResource → YourResource.AddBaseTypes(typeof(SharedResource),typeof(AbpValidationResource),typeof(AbpUiResource)).AddVirtualJson("/Localization/YourModule");// 列出语言供管道使用(SupportedCultures 在 RequestLocalizationOptions 中配置)options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文", isDefault: true));options.Languages.Add(new LanguageInfo("en",      "en",      "English"));
});

🔧 请求本地化管道 & 中间件顺序

builder.Services.AddLocalization();var cultures = new[] { new CultureInfo("zh-Hans"), new CultureInfo("en") };builder.Services.Configure<RequestLocalizationOptions>(options =>
{options.DefaultRequestCulture     = new RequestCulture("zh-Hans");options.SupportedCultures         = cultures;options.SupportedUICultures       = cultures;options.FallBackToParentCultures   = true;  // 自动回退至父文化options.FallBackToParentUICultures = true;// 先查 QueryString → 再 Cookie → 默认 Accept-Language Headeroptions.RequestCultureProviders.Insert(0, new QueryStringRequestCultureProvider());options.RequestCultureProviders.Insert(1, new CookieRequestCultureProvider());
});

管道中顺序

app.UseRequestLocalization();    // 必须在 Routing/Auth 之前
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
// app.UseAbpRequestLocalization(); // 如使用 ABP 扩展,可替换或调整位置

🌐 前端多端渲染示例

1. Razor / MVC

@inject IStringLocalizer<YourResource> L<h1>@L["User:Greeting", "张三"]</h1>
[LocalizationResourceName("YourResource")]
public class HomeController : AbpController {}

2. Blazor Server / WASM 完整 CultureSwitcher

@inject IStringLocalizer<YourResource> L
@inject IJSRuntime JSRuntime<select @onchange="OnCultureChanged"><option value="zh-Hans">🇨🇳 简体中文</option><option value="en">🇬🇧 English</option>
</select><h3>@L["Welcome"]</h3>@code {private async Task OnCultureChanged(ChangeEventArgs e){var culture = e.Value?.ToString()!;var cookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));// 写入 Cookieawait JSRuntime.InvokeVoidAsync("blazorCulture.set", cookieValue);// 更新 .NET 线程文化var ci = new CultureInfo(culture);CultureInfo.DefaultThreadCurrentCulture    = ci;CultureInfo.DefaultThreadCurrentUICulture = ci;StateHasChanged(); // 强制刷新 UI}
}

注意:在 _Host.cshtmlindex.html 中添加:

<script>window.blazorCulture = {set: function (cookieValue) {document.cookie = ".AspNetCore.Culture=" + cookieValue + ";path=/;";}};
</script>

🔄 运行时切换 & 安全 Cookie

public IActionResult SetLanguage(string culture)
{var cookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName,cookieValue,new CookieOptions {Path       = "/",Expires    = DateTimeOffset.UtcNow.AddYears(1),HttpOnly   = true,Secure     = true,SameSite   = SameSiteMode.Lax});return Redirect(Request.Headers["Referer"].ToString());
}

🔥 开发环境 JSON 热更新

Configure<AbpVirtualFileSystemOptions>(options =>
{if (env.IsDevelopment()){// 泛型为模块的 ApplicationModule 类型options.FileSets.ReplaceEmbeddedByPhysical<YourModuleApplicationModule>(Path.Combine(env.ContentRootPath, "Localization/YourModule"));}
});

生产环境:移除此替换,使用嵌入资源提高 I/O 性能。


🔗 资源继承与回退顺序

  1. SharedResource(业务/共用文案)
  2. AbpValidationResource(验证提示)
  3. AbpUiResource(通用 UI 文案)
  4. YourResource(模块专属文案)
options.Resources.Add<YourResource>("zh-Hans").AddBaseTypes(typeof(SharedResource),typeof(AbpValidationResource),typeof(AbpUiResource));

🧪 集成测试覆盖示例

[Fact]
public async Task Localizer_Should_Return_Correct_Text_By_Cookie()
{var host = await new WebHostBuilder().UseStartup<Startup>().StartAsync();var client = host.GetTestClient();client.DefaultRequestHeaders.Add("Cookie", ".AspNetCore.Culture=c=zh-Hans|uic=zh-Hans");var response = await client.GetAsync("/Home/Index");var html = await response.Content.ReadAsStringAsync();Assert.Contains("欢迎使用 ABP", html);
}

补充:可再增加 QueryString 和 Accept-Language 的测试场景 🧪


📈 监控 & 日志埋点

builder.Services.Configure<RequestLocalizationOptions>(opts =>
{opts.Events = new RequestLocalizationEvents{OnRequestCultureResolved = ctx =>{logger.LogInformation("🌐 Culture resolved: {Culture} via {Provider}",ctx.RequestCulture.Culture,ctx.Provider.GetType().Name);return Task.CompletedTask;}};
});

📅 日期/数字格式化示例

@inject IStringLocalizer<YourResource> L<p>📆 @DateTime.Now.ToString("D", CultureInfo.CurrentCulture)</p>
<p>💰 @(1234567.89.ToString("N", CultureInfo.CurrentCulture))</p>

💻 Angular/React 前端示例

import { localization } from '@abp/ng.core'; // Angular
const l = await localization.getResource('YourResource');
console.log(l.User.Greeting('王五')); // 你好,王五import { localization as localeR } from '@abp/react'; // React
const l2 = await localeR.getResource('YourResource');
console.log(l2.User.Profile); // 个人信息

或手动:

async function setCulture(culture) {document.cookie = ".AspNetCore.Culture=c=" + culture + "|uic=" + culture + ";path=/;";window.location.reload();
}

✅ 总结一览

能力实现状态备注
模块化资源DefaultResourceCulture + AddVirtualJson
请求本地化管道QueryString/Cookie/Accept-Language + UseRequestLocalization
UI 渲染Razor/MVC + Blazor/CultureSwitcher + JS 前端支持
运行时切换安全 Cookie 配置
JSON 热更新✅(开发)ReplaceEmbeddedByPhysical
资源继承 & 回退Shared → Validation → UI → YourResource
集成测试覆盖TestServer + Cookie/QueryString/Accept-Language 测试
日志 & 监控RequestLocalizationEvents.OnRequestCultureResolved
自动回退父文化FallBackToParentCultures/UICultures
多前端框架支持Angular/React + ABP JS API 示例
http://www.xdnf.cn/news/1030573.html

相关文章:

  • webuploader分片上传示例,服务端上传文件到腾讯云CDN Teo 应用示例
  • React 第三方状态管理库的比较与选择
  • 后端通过nignx代理转发,提供接口供前端在防火墙外访问
  • 计算机网络-自顶向下—第一章概述重点复习笔记
  • AI应用:计算机视觉相关技术总结
  • Elasticsearch从安装到实战、kibana安装以及自定义IK分词器/集成整合SpringBoot详细的教程ES(四)查询、排序、分页、高亮
  • 打卡Day53
  • 2025虚幻5蓝图编辑器的细节面板调不出来
  • MySQL-DQL数据查询语句深度解析与实战指南
  • 使用docker中的ollama
  • Python实战应用-Python操作MySQL数据库
  • 雪豹速清APP:高效清理,畅享流畅手机体验
  • python打卡day53@浙大疏锦行
  • DAY 53 对抗生成网络
  • 操作系统知识(1)
  • 造轮子系列:从0到1打造生产级HTTP客户端,优雅封装OkHttp/HttpClient,支持异步、重试与文件操作
  • 自定义表单右侧属性使用v-bind绑定渲染
  • 知识点|MVC模式(Model–view–controller)
  • 中英双配毕业祝福(毕业季快乐!)
  • MRI中的“髓鞘探测器”:T1w/T2w比值揭秘
  • 【面板数据】A股上市公司注册地所在地数据集(1991-2023年)
  • securecrt里如何把会话管理器固定在会话的左侧?
  • 北航自由指令驱动的多模态导航最新研究:OctoNav:开启通用智能体具身导航
  • SageAttention2原理和计算过程
  • 开机不用输入密码,修改注册表
  • 【设计模式】UML类图与工厂模式
  • C++中 using 命名别名和命名别名模板的用法
  • 寻找区域中的面积和中心点
  • ChatNT-用于DNA、RNA和蛋白质任务的多模态对话代理-文献精读143
  • P3740 [HAOI2014] 贴海报 题解