Reputation: 5976
I have an ASP.Net Core 3.1 app with the following startup.cs (I have tried various combinations of the below configuration based on web searches):
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<RequestLocalizationOptions>(options =>
{
options.RequestCultureProviders = new[] { new CookieRequestCultureProvider() };
});
and
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
And in my app's logon method, I'm setting the Culture Cookie as follows:
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture([logged-in-user].CultureCode)));
In subsequent requests I can see the cookie in my browser dev tools Network tab:
Yet, on the server, any given request still maintains the default server culture (which is en-ZA
) for my dev environment. (I'm seeing this by checking System.Threading.Thread.CurrentThread.CurrentCulture.Name
in any breakpoint in my server action methods)
And I'm running into date conversion issues between my client and my server (e,g client with en-US
culture as per screenshot above) sends a date of 3/5/2009 (March 5th) to the server, and the server is interpreting it as May 3rd.
Why is my server not honoring the CultureCookie? What am I missing?
Upvotes: 8
Views: 7773
Reputation: 141
I'm on asp.net core 6.0.
Thanks Anduin
for the response, that helped me a lot! The official doc was missleading.
I found the key points for me were:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("zh-CN")
};
options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
var SupportedCultures = new[]
{
new CultureInfo("en"),
new CultureInfo("zh")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en"),
SupportedCultures = SupportedCultures,
SupportedUICultures = SupportedCultures
});
.\Resources\Controllers\HomeController.zh.resx
.\Resources\Views\Home\Index.zh.resx
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options
@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var cultureItems = new List<SelectListItem>();
cultureItems.Add(new SelectListItem { Value = "", Text = Localizer["Select Lang"].Value });
cultureItems.AddRange(LocOptions.Value.SupportedUICultures
.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
.ToList());
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}
<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
<form id="selectLanguage" asp-controller="Home"
asp-action="SetLanguage" asp-route-returnUrl="@returnUrl"
method="post" class="form-horizontal" role="form">
<label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label>
<select name="culture" onchange="this.form.submit();" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
</select>
</form>
</div>
[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
);
return LocalRedirect(returnUrl);
}
private readonly ILogger<HomeController> _logger;
private readonly IStringLocalizer<HomeController> _localizer;
public HomeController(ILogger<HomeController> logger, IStringLocalizer<HomeController> localizer)
{
_localizer = localizer;
_logger = logger;
}
public IActionResult Index()
{
ViewData["Message"] = _localizer["Test Text"];
return View();
}
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["Title Text"];
}
And define the keys Test Text
and Title Text
in resource files.
Upvotes: 3
Reputation: 3727
As you mentioned, you have registered your localization service in your ConfigureServices
method.
My suggested way is to use it like:
services.AddLocalization(options => options.ResourcesPath = "Resources");
services
.AddControllersWithViews()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
But don't forget to register the middleware:
// In StartUp.cs Configure method
var SupportedCultures = new CultureInfo[]
{
new CultureInfo("en"),
new CultureInfo("zh")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(defaultLanguage),
SupportedCultures = SupportedCultures,
SupportedUICultures = SupportedCultures
});
As for your cookie end-time issue, please try to specify the end date of your cookie. Like this:
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions
{
Expires = DateTimeOffset.UtcNow.AddYears(1),
SameSite = SameSiteMode.None
});
Upvotes: 8