如何扩展Localizer支持单语言下的细分.resx资源文件?
扩展Localizer支持单语言下的细分资源文件方案
当然可以扩展Localizer来支持这种单语言下的细分资源文件需求!而且这是最贴合.NET本地化框架规范的做法,下面我给你详细拆解实现步骤:
一、核心思路:扩展资源解析逻辑
默认的ResourceManagerStringLocalizer是按{ResourceName}.{CultureName}.resx格式查找资源的,我们需要修改这个规则,让它能识别LangaugeResource.en-GB.north.resx这类带细分后缀的文件——本质是把"north/south"作为自定义文化细分标识融入本地化流程。
二、具体实现步骤
1. 自定义StringLocalizerProvider
我们需要实现自己的IStringLocalizerProvider,重写资源查找逻辑,支持解析带细分后缀的文件名:
public class RegionalStringLocalizerProvider : IStringLocalizerProvider { private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache(); private readonly IHttpContextAccessor _httpContextAccessor; public RegionalStringLocalizerProvider(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public IStringLocalizer Create(Type resourceSource) { var assemblyName = new AssemblyName(resourceSource.Assembly.FullName!); var baseName = resourceSource.FullName!; return new ResourceManagerStringLocalizer( new ResourceManager(baseName, resourceSource.Assembly), resourceSource, _resourceNamesCache, GetRegionalCultureInfo()); } public IStringLocalizer Create(string baseName, string location) { var assembly = Assembly.Load(new AssemblyName(location)); return new ResourceManagerStringLocalizer( new ResourceManager(baseName, assembly), assembly, baseName, _resourceNamesCache, GetRegionalCultureInfo()); } // 根据业务逻辑获取当前细分区域(示例从请求头取,也可从会话/用户配置读取) private CultureInfo GetRegionalCultureInfo() { var httpContext = _httpContextAccessor.HttpContext; var region = httpContext?.Request.Headers["X-Region"].FirstOrDefault() ?? "north"; var currentCulture = CultureInfo.CurrentCulture; var regionalCultureName = $"{currentCulture.Name}.{region}"; // 创建自定义细分文化,若系统未注册则自动生成 return CultureInfo.CreateSpecificCulture(regionalCultureName); } }
2. 替换默认本地化服务配置
在Program.cs中注册自定义Provider,替换默认实现:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); // 注册HttpContextAccessor用于获取请求上下文 builder.Services.AddHttpContextAccessor(); // 替换默认的StringLocalizerProvider为自定义区域化Provider builder.Services.AddSingleton<IStringLocalizerProvider, RegionalStringLocalizerProvider>(); builder.Services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { new CultureInfo("en-GB"), new CultureInfo("cy"), // 添加带细分的自定义文化 new CultureInfo("en-GB.north"), new CultureInfo("en-GB.south") }; options.DefaultRequestCulture = new RequestCulture("en-GB"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; });
3. 创建细分资源文件
按规则创建对应资源文件:
LangaugeResource.en-GB.north.resx(英式英语北部版本)LangaugeResource.en-GB.south.resx(英式英语南部版本)- 保留原
LangaugeResource.en-GB.resx作为回退(细分资源找不到键时,自动用父级文化的资源)
4. 业务代码中使用
和原有Localizer用法完全一致,框架会自动加载对应细分区域的资源:
private readonly IStringLocalizer<LangaugeResource> _localizer; public HomeController(IStringLocalizer<LangaugeResource> localizer) { _localizer = localizer; } public IActionResult Index() { var buttonText = _localizer["SubmitButton"]; return View(buttonText); }
三、备选方案:不扩展Localizer的实现
如果不想修改框架核心逻辑,也可以用自定义资源加载器:
- 手动读取指定细分目录的resx文件
- 编写
RegionalResourceLoader服务,根据当前区域标识加载对应键值对 - 这种方式更灵活,但需要自己处理缓存、回退逻辑,不如扩展Localizer贴合框架生态
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

