带有 SignalrR 的资源文件

Had*_*asi 1 localization signalr

我有一个项目 mvc 4 c# 我正在使用资源文件进行本地化。我有改变文化的行动

public ActionResult ChangeCulture(string lang, string returnUrl)
{
    if (lang.Equals("he-IL"))
    {
        CultureInfo ci = new CultureInfo(lang);
        ci.DateTimeFormat.ShortDatePattern = "dd/MM/yy";
        ci.DateTimeFormat.LongDatePattern = "dd/MM/yy";
        ci.DateTimeFormat.LongTimePattern = "HH:mm";
        ci.DateTimeFormat.ShortTimePattern = "HH:mm";
        ci = new CultureInfo(lang);
        Thread.CurrentThread.CurrentUICulture = ci;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
    }
    else if (lang.Equals("en-US"))
    {
        CultureInfo ci = new CultureInfo(lang);
        ci = new CultureInfo(lang);
        Thread.CurrentThread.CurrentUICulture = ci;
         Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
    }
    else
    {
        return new HttpStatusCodeResult(404);
    }
    return Redirect(returnUrl);
}
Run Code Online (Sandbox Code Playgroud)

在视图中,我从资源中获取文本并且运行良好。

<div>@(ViewRes.GlobalResource.Hello)</div> 
Run Code Online (Sandbox Code Playgroud)

但是当我从 SignalR 集线器返回文本时,它总是相同的语言。为什么?

Dre*_*rsh 5

SignalR 不会在其堆栈中本地化您的文本,您必须选择正确本地化的文本并自己返回该字符串。这应该就像从 a 请求您的资源ResourceManager并让它为您选择正确本地化的文本一样简单。一个非常简单的例子看起来像这样:

public string YourHubMethod()
{ 
    ResourceManager resourceManager = new ResourceManager("YourNamespace.YourResourcesName", 
                                                          typeof(YourHubType).Assembly);

    return resourceManager.GetString("SomeResourceName");
}
Run Code Online (Sandbox Code Playgroud)

更新: 既然您已经在评论中提供了有关如何记住 Web 应用程序请求之间的当前文化的更多信息(您使用 cookie),我可以为您提供有关如何将此转移到 SignalR 的更多信息。

您首先要覆盖集线器的 OnConnected 属性,然后您可以提取 cookie 值并将其存储在 SignalR 连接状态中,如下所示:

public override Task OnConnected()
{
    Client.Culture = Context.Request.Cookies["YourCultureCookieName"];

    return base.OnConnected();
}
Run Code Online (Sandbox Code Playgroud)

一旦它存储在客户端状态中,您现在可以构建一个 HubPipelineModule 来查找该状态并为每个逻辑 SignalR 请求设置区域性:

public class CallerCulturePipelineModule : HubPipelineModule 
{ 
    protected override bool OnBeforeIncoming(IHubIncomingInvokerContext context) 
    { 
        // Use the value we stored in the Culture property of the caller's state when they connected
        CultureInfo callerCultureInfo = new CultureInfo(context.Hub.Context.Caller.Culture);

        Thread.CurrentThread.CurrentUICulture = callerCultureInfo;
        Thread.CurrentThread.CurrentCulture = callerCultureInfo;

        return base.OnBeforeIncoming(context); 
    }
}  
Run Code Online (Sandbox Code Playgroud)

然后,您需要确保将管道模块注册为 Application_Start 的一部分:

GlobalHost.HubPipeline.AddModule(new CallerCulturePipelineModule());
Run Code Online (Sandbox Code Playgroud)

最后,如果用户在已经连接的情况下更改了他们的文化,您将需要使用新选择的值更新他们的连接状态(因为他们不会重新连接)。实际上无法在集线器本身之外修改连接状态,因此您需要实际获取IHubContext集线器的 ,并通过对现有 MVC 控制器ChangeCulture方法内的客户端的显式回调来更新客户端。为此,我建议您将连接 IDChangeCulture作为可选的查询字符串变量传递给(因为用户可能不会一直连接到您的集线器?),然后使用它来回调客户端:

string connectionId = <get connectionId from request here>;

IHubContext yourHubContext GlobalHost.GetHubContext<YourHub>();

yourHubContext.Client(connectionId).UpdateCultureState(lang);
Run Code Online (Sandbox Code Playgroud)

然后在客户端,您只需更新 JavaScript 中的状态:

yourHubProxy.client.updateCultureState = function(lang)
{
   yourHubProxy.state.culture = lang;
}
Run Code Online (Sandbox Code Playgroud)