I have a Globalization configured in my application, the issue is that when I call a controller method which is making a service call, it does not work (actually returning key). when I delete the service call and method remains empty its working just fine.
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);
}
Razor pages
@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();
Configure
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
});
So I've got an answer from the ASP.NET Core team on this. Sharing it here so others who will come across this post can find it.
The reason for the observed behavior is that .NET Core stores CultureInfo
on an AsyncLocal which results in the culture being stored local to the given asynchronous control flow - asynchronous method in this case.
The sample shared by the ASP.NET team helps clarify this even further:
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);
}
The above code will have the below output:
fr-FR
en-US
Culture should not be set in an action filter / action execution context.
Instead, the LocalizationMiddleware which is already registered in your code, should be utilized. As the documentation suggests, for production apps it's recommended to use the CookieRequestCultureProvider.DefaultCookieName
cookie to specify the culture. The cookie has the following format: c=%LANGCODE%|uic=%LANGCODE%
. So you can set it to c=am|uic=am
and you should get the resources to be rendered matching the desired culture.
Here is a sample action you can use to change the culture of the page:
public IActionResult ChangeCulture(string culture)
{
Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, $"c={culture}|uic={culture}");
return RedirectToAction("Index");
}
Then, when the user clicks the appropriate culture buttons, simply call the action at /[controller]/changeculture?culture=am
as an example.
Alternatively, you can specify the culture through the ?culture=am-AM
querystring parameter.
Hope this helps!