预渲染Blazor Wasm应用中使用Cookie实现全球化与本地化的相关问题
核心实现步骤
1. 配置服务端请求本地化中间件
该中间件会在预渲染流程启动前读取Cookie中的区域性配置,确保服务端预渲染阶段就能使用正确的区域性生成页面内容,代码需要添加到项目的Program.cs文件中,且中间件注册顺序必须在Blazor相关中间件之前:
var builder = WebApplication.CreateBuilder(args); // 注册本地化服务,ResourcesPath为资源文件存放目录,可按需修改 builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); builder.Services.Configure<RequestLocalizationOptions>(options => { // 配置支持的区域性列表,可按需扩展 var supportedCultures = new[] { "zh-CN", "en-US", "ja-JP" }; options.SetDefaultCulture("zh-CN") .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); // 将Cookie作为最高优先级的区域性检测源 options.RequestCultureProviders.Insert(0, new CookieRequestCultureProvider()); }); // 其他服务注册逻辑,例如Blazor Server/Blazor WebAssembly预渲染相关服务 var app = builder.Build(); // 启用请求本地化中间件,必须放在Blazor预渲染中间件之前 app.UseRequestLocalization(); // 其他中间件配置,例如静态文件、路由、授权等 // ... app.MapBlazorHub(); app.MapFallbackToPage("/_Host");
2. 预渲染阶段传递区域性到Blazor应用
避免服务端预渲染和客户端启动后的区域性不一致问题,修改预渲染入口页_Host.cshtml:
@page "/" @using Microsoft.AspNetCore.Localization @inject IOptions<RequestLocalizationOptions> LocOptions @{ // 从当前请求中获取已读取的区域性配置 var requestCulture = HttpContext.Features.Get<IRequestCultureFeature>(); } <!-- 将区域性作为参数传递给App组件,render-mode根据你的项目配置为ServerPrerendered或者WebAssemblyPrerendered --> <component type="typeof(App)" render-mode="ServerPrerendered" param-Culture="@requestCulture.RequestCulture.Culture.Name" param-UICulture="@requestCulture.RequestCulture.UICulture.Name" />
修改根组件App.razor,接收传递的区域性参数并配置应用全局区域性:
@inject NavigationManager NavManager @using System.Globalization <CascadingAuthenticationState> <Router AppAssembly="@typeof(App).Assembly"> <!-- 原有路由配置保持不变 --> </Router> </CascadingAuthenticationState> @code { [Parameter] public string Culture { get; set; } = default!; [Parameter] public string UICulture { get; set; } = default!; protected override void OnInitialized() { // 配置当前线程的全局区域性,和预渲染阶段保持一致 var culture = new CultureInfo(Culture); CultureInfo.DefaultThreadCurrentCulture = culture; CultureInfo.DefaultThreadCurrentUICulture = culture; } }
3. 实现区域性切换逻辑
切换区域性时写入对应Cookie,强制刷新页面触发预渲染流程重新读取Cookie:
// 该方法可放在共用服务或者页面组件中,需要注入IHttpContextAccessor和NavigationManager public void SwitchCulture(string targetCulture) { // 生成符合CookieRequestCultureProvider格式的Cookie值 var cookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(targetCulture)); // 写入Cookie,过期时间可按需设置 HttpContext.Response.Cookies.Append( CookieRequestCultureProvider.DefaultCookieName, cookieValue, new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) } ); // 强制刷新页面,触发预渲染流程读取新的区域性 NavManager.NavigateTo(NavManager.Uri, forceLoad: true); }
4. Blazor WebAssembly预渲染额外适配
如果你使用的是Blazor WebAssembly预渲染模式,需要额外在WebAssembly项目中添加客户端读取Cookie配置区域性的逻辑,确保客户端启动后的区域性和服务端预渲染结果一致:
- 在
wwwroot/index.html中添加读取Cookie的JS方法:
function getCookie(cookieName) { const value = `; ${document.cookie}`; const parts = value.split(`; ${cookieName}=`); if (parts.length === 2) return parts.pop().split(';').shift(); }
- 在WebAssembly项目的
Program.cs中添加读取Cookie配置区域性的逻辑:
var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); // 读取Cookie中的区域性配置 var host = builder.Build(); var jsRuntime = host.Services.GetRequiredService<IJSRuntime>(); var cultureCookie = await jsRuntime.InvokeAsync<string>("getCookie", CookieRequestCultureProvider.DefaultCookieName); if (!string.IsNullOrEmpty(cultureCookie)) { var cultureResult = CookieRequestCultureProvider.ParseCookieValue(cultureCookie); if (cultureResult != null) { var culture = new CultureInfo(cultureResult.Culture); CultureInfo.DefaultThreadCurrentCulture = culture; CultureInfo.DefaultThreadCurrentUICulture = culture; } } await host.RunAsync();
注意事项:
- 预渲染阶段无法调用Blazor JS运行时,因此不能通过前端JS读取Cookie设置区域性,必须依赖服务端请求本地化中间件的读取逻辑
- 切换区域性后必须强制刷新页面,才能触发预渲染流程更新区域性,避免前后端渲染内容不一致导致的 hydration 报错
- 如果你不需要保留区域性长期生效,也可以将Cookie的生命周期设置为会话级,关闭浏览器后自动失效
内容的提问来源于stack exchange,提问作者Keerthi
相关产品推荐
相关产品推荐

