如何配置中间件实现ASP.NET 7.0 Razor Pages单资源文件本地化?
解决ASP.NET 7.0 Razor Pages单个共享资源文件本地化配置问题
问题根源分析
你遇到的InvalidOperationException: No service for type 'Microsoft.Extensions.Localization.IStringLocalizer' has been registered错误,核心原因是默认未注册非泛型的IStringLocalizer服务,同时你的本地化配置还有几处关键问题:
- 启动时直接设置
Thread.CurrentThread.CurrentUICulture无法作用于每个请求; UseRequestLocalization的调用方式不符合规范,需完整配置请求本地化选项;- 页面注入的是非泛型
IStringLocalizer,但未关联到你的共享资源文件。
修正后的完整配置
1. 调整Program.cs服务配置与中间件
var builder = WebApplication.CreateBuilder(args); // 配置本地化资源路径 builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); builder.Services.AddDbContext<OWsefaWebContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("OWsefaWebContext") ?? throw new InvalidOperationException("Connection string 'OWsefaWebContext' not found."))); // 配置Razor Pages本地化,绑定到共享资源 builder.Services.AddRazorPages() .AddDataAnnotationsLocalization(opts => { opts.DataAnnotationLocalizerProvider = (type, factory) => { var assemblyName = typeof(SharedResource).Assembly.GetName().Name; return factory.Create(nameof(SharedResource), assemblyName!); }; }) .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix); // 可选:注册非泛型IStringLocalizer,使其指向SharedResource(用于页面非泛型注入) builder.Services.AddSingleton<IStringLocalizer>(sp => { var factory = sp.GetRequiredService<IStringLocalizerFactory>(); var assemblyName = typeof(SharedResource).Assembly.GetName().Name; return factory.Create(nameof(SharedResource), assemblyName!); }); // 配置请求本地化选项 var supportedCultures = new[] { "en", "it" }; var localizationOptions = new RequestLocalizationOptions() .SetDefaultCulture("en") .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); var app = builder.Build(); using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; DataInitializer.Initialize(services); } if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } // 正确挂载请求本地化中间件(注意顺序:需在UseRouting之前) app.UseRequestLocalization(localizationOptions); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
2. 调整页面注入代码
如果注册了上述非泛型IStringLocalizer,可保留原注入代码;若想更简洁,推荐直接注入泛型版本(无需额外注册):
@page @using Microsoft.Extensions.Localization; @inject IStringLocalizer<SharedResource> localizer @model OWsefa.Web.Pages.Companies.IndexModel @{ ViewData["Title"] = "Index"; } <h1>Index</h1> <h1>@localizer["Text.Index"]</h1>
3. 确保资源文件结构正确
在项目根目录创建Resources文件夹,添加对应资源文件:
SharedResource.resx(默认语言资源,如英文)SharedResource.it.resx(意大利语资源)
在资源文件中添加键值对,例如Text.Index对应目标语言的文本内容。
关键修正点说明
- 移除启动线程的文化设置:请求级别的文化由
UseRequestLocalization中间件统一处理,启动线程的文化配置不影响用户请求; - 规范RequestLocalizationOptions配置:明确默认文化、支持的文化列表,确保中间件能正确解析请求中的文化标识;
- 绑定共享资源与本地化服务:无论是数据注解还是页面文本,都明确指向
SharedResource,保证所有本地化内容从单个资源文件读取; - 泛型IStringLocalizer优先:泛型
IStringLocalizer<T>是官方推荐方案,无需额外注册即可直接注入,更符合ASP.NET Core本地化设计规范。
内容的提问来源于stack exchange,提问作者steve fax
相关产品推荐
相关产品推荐

