IViewLocalizer 有时在 .net core 3.1 中不起作用
IViewLocalizer does not work sometimes in .net core 3.1
我在我的应用程序中配置了一个全球化,问题是当我调用一个进行服务调用的控制器方法时,它不起作用(实际上返回密钥)。当我删除服务调用并且方法仍然为空时,它工作正常。
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
});
所以我从 ASP.NET 核心团队那里得到了答案。在这里分享它,以便遇到此问题的其他人 post 可以找到它。
观察到的行为的原因是 .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
查询字符串参数指定区域性。
希望对您有所帮助!
我在我的应用程序中配置了一个全球化,问题是当我调用一个进行服务调用的控制器方法时,它不起作用(实际上返回密钥)。当我删除服务调用并且方法仍然为空时,它工作正常。
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
});
所以我从 ASP.NET 核心团队那里得到了答案。在这里分享它,以便遇到此问题的其他人 post 可以找到它。
观察到的行为的原因是 .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
查询字符串参数指定区域性。
希望对您有所帮助!