Let me give an exhaustive answer to this question and describe how I found a solution after reading the .net kernel source code.
Before further description, first install this package using NuGet Microsoft.Extensions.Localization
as you guys remember in the full asp.net framework, switching between cultures was pretty easy
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
but in the .net core, culture is no longer tied to the current thread. The asp.net core kernel has a pipeline, and we can add various MiddleWares to it, so RequestLocalizationMiddleware is a middleware class for localization processing, we can have several providers, so it will iterate over all the culture providers, for example, QueryStringRequestCultureProvider , CookieRequestCultureProvider , AcceptLanguageHeaderReestquest recourider , AcceptLanguageHeaderReestquest recourider , RequerequestReestquest , ...
as soon as the middleware for localizing requests can receive the current locale from the first provider, it ignores the others and passes the request to the next middleware in the pipeline, so the order of the providers in the list really matters.
I personally prefer to store the culture in browser cookies, so since CookieRequestCultureProvider is not the first culture provider in the list, I move it to the top of the list, configure this part in Startup.cs> ConfigureServices as shown below
services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("fa-IR"), new CultureInfo("de-DE") }; options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; var defaultCookieRequestProvider = options.RequestCultureProviders.FirstOrDefault(rcp => rcp.GetType() == typeof(CookieRequestCultureProvider)); if (defaultCookieRequestProvider != null) options.RequestCultureProviders.Remove(defaultCookieRequestProvider); options.RequestCultureProviders.Insert(0, new CookieRequestCultureProvider() { CookieName = ".AspNetCore.Culture", Options = options }); });
let me describe the above code, the default culture of our application is en-US , and we only support English, Farsi, Germany, so if the browser uses a different language or you install a language other than these 3 languages then the application should switch to culture default. in the above code, I simply remove the CookieCultureProvider from the list and add it as the first provider in the list (* I already described the reason why it should be the first *). CookieName works for me by default, you can change it if you want.
don't forget to add the code below under Configure (application IApplicationBuilder, enH IHostingEnvironment) in Startup.cs
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>(); app.UseRequestLocalization(options.Value);
so far so good. To have resource files, you must specify the resource path, I separately specify the resource for Controller, Views, ViewModels and SharedResources in the root path of the web project, the hierarchy is described below
|-Resoures |---Controllers |---Views |---Models |---SharedResource.resx |---SharedResource.fa-IR.resx |---SharedResource.de-DE.resx
Hide resultkeep in mind that for SharedResource create an empty class with the same name in the root path of the web project, I mean SharedResource.cs with a class with the same name inside.
Add the following code snippet to Startup.cs to specify the path to the resource and everything else.
services.AddLocalization(options => options.ResourcesPath = "Resources"); services.AddMvc() AddViewLocalization( LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources/Views"; })
with this configuration, for example, when you enter IStringLocalizer inside the controller, you must have the corresponding resource files in the Resources> Controllers folder (which are HomeController.resx, HomeController.fa-IR.resx, HomeController.de-DE.resx) we can also separate the path with . (say, period) in the file name, I mean Resources / Controllers / HomeController.resx can be a file in Resources / Controllers.HomeController.resx, you must embed IViewLocalizer in the views for the appropriate localization inside the views you must have resource files for views in the Resources / Views folder, for ViewModels, since we named the Models folder, please put all ViewModels in a previously created folder in the root path of the web project named Models. If the folder has a different name or you prefer a different name, do not forget to rename the Models folder in the Resource folder. then you do not need to do anything except annotate the models, for example, annotate the ViewModel properties using [DisplayName ("user email address")], and then create resources in the corresponding resource files inside the model (the file name must match the model class name) with the same key ("user email address").
let's end with where we started, I mean CookieRequestCultureProvider . As I said earlier, I prefer to store it in a cookie, but it's a bit complicated, because parsing a cookie is slightly different from what you might expect, just add the code below where you want to change the culture, just replace the preredCulture with your cultural preferences
var preferedCulture = "fa-IR";
So, our main sp.net web application is now localized :)