1

我有一个项目 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);
}

在视图中,我从资源中获取文本并且效果很好。

<div>@(ViewRes.GlobalResource.Hello)</div> 

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

4

1 回答 1

5

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

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

    return resourceManager.GetString("SomeResourceName");
}

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

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

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

    return base.OnConnected();
}

将其存储在客户端状态后,您现在可以构建一个 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); 
    }
}  

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

GlobalHost.HubPipeline.AddModule(new CallerCulturePipelineModule());

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

string connectionId = <get connectionId from request here>;

IHubContext yourHubContext GlobalHost.GetHubContext<YourHub>();

yourHubContext.Client(connectionId).UpdateCultureState(lang);

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

yourHubProxy.client.updateCultureState = function(lang)
{
   yourHubProxy.state.culture = lang;
}
于 2013-06-17T17:39:46.860 回答