【问题标题】:IViewLocalizer does not work sometimes in .net core 3.1IViewLocalizer 有时在 .net core 3.1 中不起作用
【发布时间】:2020-06-23 12:50:40
【问题描述】:

我在我的应用程序中配置了一个全球化,问题是当我调用一个正在进行服务调用的控制器方法时,它不起作用(实际上是返回键)。当我删除服务调用并且方法仍然为空时,它工作得很好。

 public async Task<IActionResult> Index(int id)
 {
     var item = _mapper.Map<ItemViewModel>(await _itemService.GetById(id));
     item.ItemImages = await _itemImageService.GetImageByItemId(id);
     return View(null);
 }

剃刀页面

@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
    ViewData["Title"] = "Index";
}


<div class="container" style="margin:100px 0 0 0">
    <h1>@Localizer["Category"]</h1>
</div>

Startup.cs

 services.AddLocalization(opts => opts.ResourcesPath = "Resources");
 services.AddMvc()
         .AddViewLocalization(
              LanguageViewLocationExpanderFormat.Suffix,
              opts => opts.ResourcesPath = "Resources")
         .AddDataAnnotationsLocalization();
  
 services.AddControllersWithViews();
 services.AddRazorPages();

配置

var supportedCultures = new[]
{
      new CultureInfo("am-AM"),
      new CultureInfo("en-US"),
      new CultureInfo("ru-RU")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
      DefaultRequestCulture = new RequestCulture("en-US"),
      SupportedCultures = supportedCultures,
      SupportedUICultures = supportedCultures
});

【问题讨论】:

  • IViewLocalizer 的工作方式是,如果找不到该键的值,它将返回该键。所以也许你只是错过了翻译。
  • 澄清一下——我指的是上面默认的 IViewLocalizer 实现行为。
  • 不,它工作正常,所以我找到了一个解决方法,只是将我的方法从异步更改为正常,现在工作正常,但我不知道为什么会这样。
  • 这很有趣。你不应该那样做。你能分享一个托管在 GitHub 上的小型复制品吗?我可以看看。
  • @Artak 这是我的 GitHub 存储库github.com/h2002d/PetFinder.git

标签: .net asp.net-core cultureinfo asp.net-core-localization


【解决方案1】:

所以我从 ASP.NET Core 团队那里得到了答案。在这里分享它,以便其他看到这篇文章的人可以找到它。

观察到行为的原因是 .NET Core 将 CultureInfo 存储在 AsyncLocal 上,这导致区域性存储在给定异步控制流的本地 - 在本例中为异步方法。

ASP.NET 团队共享的示例有助于进一步阐明这一点:

static async Task Main(string[] args)
{
    await SetCultureActionFilter();
    Console.WriteLine(CultureInfo.CurrentCulture);
}

static async Task SetCultureActionFilter()
{
    await Task.Yield();
    CultureInfo.CurrentCulture = new CultureInfo("fr-FR");

    Console.WriteLine(CultureInfo.CurrentCulture);
}

上面的代码会有以下输出:

fr-FR
en-US

解决方案

不应在动作过滤器/动作执行上下文中设置文化。 相反,应该使用已经在您的代码中注册的 LocalizationMiddleware。正如文档所建议的,对于生产应用程序,建议使用CookieRequestCultureProvider.DefaultCookieName cookie 来指定文化。 cookie 具有以下格式:c=%LANGCODE%|uic=%LANGCODE%。因此,您可以将其设置为 c=am|uic=am,并且您应该获得与所需文化匹配的资源。

以下是可用于更改页面文化的示例操作:

public IActionResult ChangeCulture(string culture)
{
    Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, $"c={culture}|uic={culture}");
    return RedirectToAction("Index");
}

然后,当用户单击相应的文化按钮时,只需调用/[controller]/changeculture?culture=am 处的操作作为示例。

或者,您可以通过 ?culture=am-AM 查询字符串参数指定区域性。

希望这会有所帮助!

【讨论】:

  • 正如 Artak 提到的,这需要由中间件完成,在我的示例中是 BaseController 但问题是 OnActionExecuted 和其中的方法不是异步方法,所以我将它们更改为异步并且它完美运行。
猜你喜欢
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-02
  • 2021-06-27
  • 1970-01-01
  • 2020-07-25
  • 2020-04-10
相关资源
最近更新 更多