使用OWIN和异步方法的多语言网站

本文关键字:语言 网站 异步方法 OWIN 使用 | 更新日期: 2023-09-27 18:08:55

背景

我正在使用ASP创建一个简单的多语言网站。NET 4.6、C#、IIS上的OWIN管道(Microsoft.Owin.Host.SystemWeb(、大量异步方法调用和标准全局资源文件(App_GlobalResources中的*.resx(。该网站使用MVC5、WebAPI2和Autofac作为依赖解析程序。

问题

我无法正确更改生成的页面的区域设置/区域性,因为异步方法每个请求使用多个线程,并且我找不到为与给定请求关联的每个线程设置Thread.Current[UI]Culture的方法,因为这些属性没有同步。我还希望使用干净的代码,而不是"async/await区域性配置"干扰有用的代码。

代码

启动.cs

public void Configuration(IAppBuilder app)
{
    ...
    app.UseAutofacMiddleware(container);
    app.UseAutofacMvc();
    app.UseAutofacWebApi(httpConfiguration);
    app.UseWebApi(httpConfiguration);
    ...
    app.Use(async (ctx, next) =>
    {
        /* in production, detect based on current URL and/or cookie */
        var culture = new CultureInfo("pl_PL");
        CultureInfo.CurrentCulture = CultureInfo.CurrentUICulture = culture;
        await next.Invoke();
    });
}

SampleController.cs

public async Task<ActionResult> SayHello()
{
    // returns pl_PL message
    var msgA = Resources.Messages.HelloWorld; 
    await someService.doSthAsync();
    // returns system default (en_US) message
    var msgB = Resources.Messages.HelloWorld;
    return Content(msgA + " - " + msgB);
}

  1. 我应该按照这个SO答案中的建议创建一个自定义[AspNet]SynchronizationContext吗?如果是这样的话,我该怎么做
  2. 我应该放弃全球资源作为翻译的来源,而使用其他方法吗?如果是,我可以使用什么(图书馆?(

使用OWIN和异步方法的多语言网站

使用"归因全球化库"怎么样,它似乎正是为此目的而创建的。

您仍然可以使用resx来本地化您的资源,并且它具有强大的定制功能:

public void Configuration(IAppBuilder app)
{
    ...
    app.UseGlobalization(new OwinGlobalizationOptions("en-US",true)
       .DisablePaths("Content", "bundles")
       .Add("fr-FR", true).AddCustomSeeker(new CultureFromPreferences()));
}

我已经测试了async/await的使用,并且保留了文化:

    public async Task<ActionResult> About()
    {
        var msgA = Resources.Resources.About;
        await Task.Delay(1000);
        var msgB = Resources.Resources.About;
        ViewBag.Message = msgA + " - " + msgB;
        return View();
    }

注意:我不是这个图书馆的作者,我碰巧以前用过它。

Joe Enzmiger的答案在这里看起来很合适:

public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext     controllerContext, CancellationToken cancellationToken)
{
if (controllerContext.Request.Headers.AcceptLanguage != null && 
    controllerContext.Request.Headers.AcceptLanguage.Count > 0)
{
    string language = controllerContext.Request.Headers.AcceptLanguage.First().Value;
    var culture = CultureInfo.CreateSpecificCulture(language);
    HttpContext.Current.Items["Culture"] = culture;
    //Thread.CurrentThread.CurrentCulture = culture;
    //Thread.CurrentThread.CurrentUICulture = culture;
}
base.ExecuteAsync(controllerContext, cancellationToken); 
}

然后,在任何任务中,你都需要文化:

var culture = HttpContext.Current != null ? HttpContext.Current.Items["Culture"] as CultureInfo : Thread.CurrentThread.CurrentCulture;