ABP vNext 多语言与本地化:动态切换、资源继承与热更新
🚀 ABP vNext 多语言与本地化:动态切换、资源继承与热更新 🎉
📑 目录
- 🚀 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.cshtml
或index.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 性能。
🔗 资源继承与回退顺序
- SharedResource(业务/共用文案)
- AbpValidationResource(验证提示)
- AbpUiResource(通用 UI 文案)
- 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 示例 |