如何在Blazor服务器端渲染应用中设置语言并更新组件
Blazor SSR 语言切换不生效的解决方案
你的问题核心在于:当前仅在客户端设置了文化信息,但未同步更新服务器端的本地化上下文,也没有触发已渲染组件的重新渲染。以下是具体解决步骤:
1. 完善服务器端本地化配置
首先在 Program.cs 中补充本地化服务和请求文化中间件,确保服务器能正确识别和应用客户端的文化设置:
// 添加本地化支持,指定资源文件路径 builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); // 配置支持的文化列表 var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("pt-PT"), new CultureInfo("fr-FR") }; // 配置请求本地化选项 builder.Services.Configure<RequestLocalizationOptions>(options => { options.DefaultRequestCulture = new RequestCulture("en-US"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; // 使用Cookie持久化文化设置,确保SSR首次渲染能读取正确文化 options.RequestCultureProviders.Insert(0, new CookieRequestCultureProvider()); }); // 注册HttpContext访问器 builder.Services.AddHttpContextAccessor(); // 添加全局文化状态服务,用于通知组件文化变化 builder.Services.AddScoped<CultureState>(sp => { var contextAccessor = sp.GetRequiredService<IHttpContextAccessor>(); var requestCulture = contextAccessor.HttpContext?.Features.Get<IRequestCultureFeature>()?.RequestCulture.Culture ?? CultureInfo.GetCultureInfo("en-US"); return new CultureState(requestCulture); }); // 中间件顺序要注意,放在MapRazorComponents之前 app.UseRequestLocalization(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode();
2. 创建全局文化状态服务
这个服务用于广播文化变化事件,让所有需要本地化的组件感知到文化切换:
public class CultureState { public event Action? CultureChanged; private CultureInfo _currentCulture; public CultureState(CultureInfo initialCulture) { _currentCulture = initialCulture; } public void SetCulture(CultureInfo culture) { if (_currentCulture.Name != culture.Name) { _currentCulture = culture; CultureChanged?.Invoke(); } } public CultureInfo CurrentCulture => _currentCulture; }
3. 修改语言切换组件逻辑
更新组件,实现客户端+服务器端的文化同步,并触发全局状态通知:
@using System.Globalization @inject IJSRuntime JSRuntime @inject IHttpContextAccessor HttpContextAccessor @inject CultureState CultureState <select class="form-control" @onchange="ChangeLanguage"> @foreach (var language in supportedLanguages) { <option value="@language.Name" selected="@(CultureState.CurrentCulture.Name == language.Name)"> @language.DisplayName </option> } </select> @code { CultureInfo[] supportedLanguages = new[] { new CultureInfo("en-US"), new CultureInfo("pt-PT"), new CultureInfo("fr-FR"), }; private async Task ChangeLanguage(ChangeEventArgs e) { var cultureName = e.Value?.ToString(); if (string.IsNullOrEmpty(cultureName)) return; var targetCulture = new CultureInfo(cultureName); // 1. 更新服务器端Cookie和当前线程文化 var httpContext = HttpContextAccessor.HttpContext; if (httpContext != null) { httpContext.Response.Cookies.Append( CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(targetCulture)), new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) } ); CultureInfo.CurrentCulture = targetCulture; CultureInfo.CurrentUICulture = targetCulture; } // 2. 同步客户端存储(可选,确保页面刷新后保留文化设置) await JSRuntime.InvokeVoidAsync("localStorage.setItem", "blazor-culture", cultureName); // 3. 通知所有组件文化已更新 CultureState.SetCulture(targetCulture); } }
4. 让本地化组件响应文化变化
在使用 IStringLocalizer 的组件中,订阅文化变化事件并触发重新渲染:
@inject IStringLocalizer<App> _localize @inject CultureState CultureState @implements IDisposable <h1>@_localize["Welcome"]</h1> <p>@_localize["Description"]</p> @code { protected override void OnInitialized() { CultureState.CultureChanged += RefreshLocalization; } private void RefreshLocalization() { // 触发组件重新渲染,更新本地化文本 StateHasChanged(); } public void Dispose() { // 取消订阅,避免内存泄漏 CultureState.CultureChanged -= RefreshLocalization; } }
关键说明
- 原代码仅在客户端执行了JS操作,但Blazor SSR的本地化依赖服务器端的文化上下文,必须同步更新服务器端的Cookie和线程文化。
- 通过全局
CultureState服务的事件通知机制,无需刷新页面即可让所有已渲染组件重新读取本地化资源并更新UI。
内容的提问来源于stack exchange,提问作者Nmaster88
相关产品推荐
相关产品推荐

