ASP.NET Core 6 Razor应用按语言子目录管理资源文件可行性咨询
在ASP.NET Core 6 Razor应用中按语言子目录管理资源文件的实现方案
完全可以通过ASP.NET Core官方提供的本地化扩展实现这种按语言子目录分组的资源管理结构,不需要依赖第三方类库。核心思路是自定义资源路径的解析逻辑,让本地化系统能够识别语言子目录下的资源文件。
实现步骤
1. 基础本地化服务配置
首先在Program.cs中注册本地化服务,并指定资源文件的根目录:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); // 配置支持的文化 builder.Services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("de"), // 添加其他需要支持的语言 }; options.DefaultRequestCulture = new RequestCulture("en"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; }); // 启用请求本地化中间件 app.UseRequestLocalization();
2. 自定义本地化工厂
默认的IStringLocalizerFactory是按「文件名+文化后缀」的规则解析资源,我们需要自定义工厂类,让它根据当前文化去对应语言子目录中查找资源文件。
创建自定义工厂类:
using System.Globalization; using System.Reflection; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; public class CultureDirectoryStringLocalizerFactory : IStringLocalizerFactory { private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache(); private readonly IFileProvider _fileProvider; private readonly LocalizationOptions _options; public CultureDirectoryStringLocalizerFactory(IFileProvider fileProvider, IOptions<LocalizationOptions> options) { _fileProvider = fileProvider ?? throw new ArgumentNullException(nameof(fileProvider)); _options = options?.Value ?? throw new ArgumentNullException(nameof(options)); } public IStringLocalizer Create(Type resourceSource) { var typeInfo = resourceSource.GetTypeInfo(); return Create(typeInfo.Namespace, typeInfo.Name); } public IStringLocalizer Create(string baseName, string location) { if (string.IsNullOrEmpty(baseName)) throw new ArgumentNullException(nameof(baseName)); if (string.IsNullOrEmpty(location)) throw new ArgumentNullException(nameof(location)); return new ResourceManagerStringLocalizer( new ResourceManager(baseName, Assembly.Load(new AssemblyName(location))), Assembly.Load(new AssemblyName(location)), baseName, _resourceNamesCache, new CultureDirectoryResourcePathProvider(_fileProvider, _options.ResourcesPath)); } private class CultureDirectoryResourcePathProvider : IResourcePathProvider { private readonly IFileProvider _fileProvider; private readonly string _resourcesPath; public CultureDirectoryResourcePathProvider(IFileProvider fileProvider, string resourcesPath) { _fileProvider = fileProvider; _resourcesPath = resourcesPath; } public string GetResourcePath(string baseName, string cultureName) { // 从baseName中提取资源相对路径(比如从"MyApp.Pages.Index"得到"Pages/Index") var resourceSegments = baseName.Split('.') .SkipWhile(segment => !segment.Equals("Pages", StringComparison.OrdinalIgnoreCase)) .ToList(); // 处理布局页等非页面资源(比如_Layout.resx) if (!resourceSegments.Any() && baseName.EndsWith("_Layout")) { resourceSegments.Add("_Layout"); } var resourcePath = string.Join("/", resourceSegments); // 构建最终资源路径:Resources/{cultureName}/{resourcePath}.resx return Path.Combine(_resourcesPath, cultureName, $"{resourcePath}.resx"); } } }
3. 注册自定义工厂
在Program.cs中将自定义工厂注册到服务容器,替换默认实现:
builder.Services.AddSingleton<IStringLocalizerFactory, CultureDirectoryStringLocalizerFactory>();
4. 配置资源文件属性
确保所有资源文件(*.resx)的生成操作设置为「嵌入的资源」,否则本地化系统无法读取这些文件。
在视图中使用本地化
在Razor页面或布局页中注入IStringLocalizer或IViewLocalizer即可正常使用:
比如在Index.cshtml中:
@using Microsoft.Extensions.Localization @inject IStringLocalizer<Index> Localizer <h1>@Localizer["Welcome"]</h1>
在_Layout.cshtml中:
@using Microsoft.Extensions.Localization @inject IStringLocalizer<_Layout> Localizer <footer>@Localizer["Copyright"]</footer>
内容的提问来源于stack exchange,提问作者Ale32bit
相关产品推荐
相关产品推荐

