Blazor hosted Webassembly项目如何基于数据库资源实现本地化
实现方案
Blazor WASM 客户端无法直接访问服务端数据库,你需要通过「服务端暴露本地化接口 + 客户端自定义 IStringLocalizer 实现」的方式完成配置,具体步骤如下:
1. 服务端改造
你已经完成了数据库本地化的基础配置,只需要新增一个接口提供翻译资源即可:
- 新增
LocalizationController控制器,注入你已实现的数据库本地化服务/业务DbContext,提供查询接口:
[ApiController] [Route("api/[controller]")] public class LocalizationController : ControllerBase { // 你之前教程实现的数据库本地化读取服务 private readonly IDbLocalizationService _localizationService; public LocalizationController(IDbLocalizationService localizationService) { _localizationService = localizationService; } [HttpGet] public ActionResult<Dictionary<string, string>> GetAll([FromQuery] string culture, [FromQuery] string resourceType = null) { var resources = _localizationService.GetResources(culture, resourceType); return Ok(resources.ToDictionary(x => x.Key, x => x.Value)); } }
2. 客户端实现自定义本地化服务
替换默认的resx实现,自定义IStringLocalizer和对应工厂,调用服务端接口拉取翻译:
- 先实现自定义字符串定位器:
public class ApiStringLocalizer : IStringLocalizer { private readonly HttpClient _httpClient; private readonly string _resourceType; private Dictionary<string, string> _localizations = new(); public ApiStringLocalizer(HttpClient httpClient, string resourceType) { _httpClient = httpClient; _resourceType = resourceType; } public LocalizedString this[string name] { get { if (_localizations.TryGetValue(name, out var value)) { return new LocalizedString(name, value); } // 未命中时返回键本身,和默认行为一致 return new LocalizedString(name, name, resourceNotFound: true); } } public LocalizedString this[string name, params object[] arguments] { get { var format = this[name]; return new LocalizedString(name, string.Format(format.Value, arguments), format.ResourceNotFound); } } // 初始化时拉取对应语言的所有翻译缓存到本地 public async Task LoadResourcesAsync(CultureInfo culture) { var response = await _httpClient.GetFromJsonAsync<Dictionary<string, string>>( $"api/localization?culture={culture.Name}&resourceType={_resourceType}"); _localizations = response ?? new Dictionary<string, string>(); } // 其余IStringLocalizer接口方法按需求实现即可 public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures) { return _localizations.Select(kv => new LocalizedString(kv.Key, kv.Value)); } }
- 再实现对应的工厂类,用来生成带泛型参数的
IStringLocalizer<T>实例:
public class ApiStringLocalizerFactory : IStringLocalizerFactory { private readonly HttpClient _httpClient; public ApiStringLocalizerFactory(HttpClient httpClient) { _httpClient = httpClient; } public IStringLocalizer Create(Type resourceSource) { var localizer = new ApiStringLocalizer(_httpClient, resourceSource.FullName); // 初始化时加载当前语言资源 localizer.LoadResourcesAsync(CultureInfo.CurrentCulture).Wait(); return localizer; } public IStringLocalizer Create(string baseName, string location) { var localizer = new ApiStringLocalizer(_httpClient, baseName); localizer.LoadResourcesAsync(CultureInfo.CurrentCulture).Wait(); return localizer; } }
3. 客户端服务注册替换
在客户端项目的Program.cs中替换默认的本地化服务实现:
var builder = WebAssemblyHostBuilder.CreateDefault(args); // 配置指向服务端的HttpClient builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); // 替换默认的本地化工厂实现 builder.Services.AddSingleton<IStringLocalizerFactory, ApiStringLocalizerFactory>(); builder.Services.AddScoped(typeof(IStringLocalizer<>), typeof(StringLocalizer<>)); // 配置支持的语言 builder.Services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("zh-CN") }; options.DefaultRequestCulture = new RequestCulture("zh-CN"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; }); await builder.Build().RunAsync();
注意事项
- 可以将拉取到的本地化资源缓存到
localStorage中,切换语言时清空缓存重新拉取,减少重复请求 - 如果不需要按资源类型拆分翻译,接口可以去掉
resourceType参数,统一返回所有翻译即可 - 首次加载时可以提前拉取一次资源,避免页面显示延迟
内容的提问来源于stack exchange,提问作者T0bi
相关产品推荐
相关产品推荐

