如何获取SignalR客户端UI区域性以发送本地化内容
SignalR定向发消息适配接收方本地化的实现方案
核心问题
常规接口请求中,Resources.PropertyName会自动读取当前请求线程绑定的用户UI区域性,返回对应语言内容。但跨用户触发SignalR消息时,执行发送逻辑的线程绑定的是操作触发方的区域性,直接读取资源会返回触发方的语言内容,和消息接收方的语言设置不匹配。
实现步骤
1. 连接阶段持久化用户的区域性设置
用户建立SignalR连接时,提前把他的语言配置存下来,发消息时直接读取即可,不要在发送阶段临时猜测用户语言。
可以在Hub的OnConnectedAsync生命周期里完成存储:
// 注入IMemoryCache/IDistributedCache用于存储用户语言映射 private readonly IMemoryCache _cache; public YourHub(IMemoryCache cache) { _cache = cache; } public override async Task OnConnectedAsync() { var httpContext = Context.GetHttpContext(); // 优先取客户端主动传递的lang参数(连接时拼在hub地址后,如 /yourHub?lang=fr),准确度最高 var userLang = httpContext?.Request.Query["lang"].FirstOrDefault(); // 没传的话回退取Accept-Language请求头 if (string.IsNullOrEmpty(userLang)) { userLang = httpContext?.Request.Headers["Accept-Language"].FirstOrDefault()?.Split(',').First(); } if (!string.IsNullOrWhiteSpace(userLang)) { // 以用户ID为key缓存语言设置,缓存过期时间按需调整,分布式部署请替换为IDistributedCache _cache.Set($"User_Culture_{Context.UserIdentifier}", userLang, TimeSpan.FromDays(30)); } await base.OnConnectedAsync(); }
如果用户在使用过程中切换了网站语言,要么重新建立SignalR连接,要么单独调用一个Hub方法更新缓存里的语言值,避免缓存内容和用户实际设置不一致。
2. 发送消息时按接收方文化读取本地化资源
发送消息时不要直接读取默认的静态资源,先取出接收方的文化配置,调用资源读取的重载方法按指定文化取内容,全程不要修改当前线程的全局文化设置,避免影响触发方的后续逻辑:
// 提前注入IHubContext、缓存、IStringLocalizer/资源类 public async Task SendToTargetUser(string userIDString, object payload) { // 1. 读取目标用户的文化配置,不存在则回退到默认语言(比如英文) var targetLang = _cache.Get<string>($"User_Culture_{userIDString}"); var targetCulture = string.IsNullOrWhiteSpace(targetLang) ? CultureInfo.GetCultureInfo("en") : CultureInfo.GetCultureInfo(targetLang); // 2. 按目标文化读取对应语言的内容 // 如果你用IStringLocalizer做本地化: var localizedMsg = _localizer["Message_NotifyText", targetCulture].Value; // 如果你直接用.Designer.cs生成的资源类: // var localizedMsg = YourResource.ResourceManager.GetString("Message_NotifyText", targetCulture); // 3. 组装发送的data var data = new { NotifyText = localizedMsg, Payload = payload }; // 4. 发送消息 await _hubContext.Clients.User(userIDString).SendAsync("remoteMethod", data); }
注意事项
- 禁止在发送逻辑里直接修改
CultureInfo.CurrentCulture/CultureInfo.CurrentUICulture,当前请求上下文属于操作触发方,全局修改文化会导致后续逻辑读取到错误的触发方资源 - 多服务实例部署场景下,不要用本机内存缓存存储用户语言映射,替换为Redis等分布式缓存,避免跨实例发消息时读不到配置
- 如果你的系统用户语言是存在用户数据库表里的,也可以不用在连接时缓存,发消息前直接查库取用户的语言配置即可,连接时缓存的方式性能更优
内容的提问来源于stack exchange,提问作者Jeff Putz
相关产品推荐
相关产品推荐

