In the first step you should install Microsoft.AspNetCore.Localization
package from Nuget package manager then add supporting localize to middleware.
/*
Add supporting localization to Mvc and set Directory of Resources files
For example all resourcess will be in ~/Resources/Controllers/AboutController.en-GB.resx
*/
services.AddMvc()
.AddViewLocalization(
LanguageViewLocationExpanderFormat.Suffix,
opts => { opts.ResourcesPath = "Resources"; })
.AddDataAnnotationsLocalization();
services.Configure<RequestLocalizationOptions>(
opts => {
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-GB"),
new CultureInfo("zh-CN")
};
opts.DefaultRequestCulture = new RequestCulture("en-GB");
// Formatting numbers, dates, etc.
opts.SupportedCultures = supportedCultures;
// UI strings that we have localized.
opts.SupportedUICultures = supportedCultures;
});
Now Dependency Injection help us to load strings using IStringLocalizer
and IStringLocalizer<T>
. those class working over ResourceManager
and ResourceReader
were architected to improve productivity when developing localized apps in ASP.NET Core
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
namespace Localization.StarterWeb.Controllers
{
public class AboutController : Controller
{
private readonly IStringLocalizer<AboutController> _localizer;
public AboutController(IStringLocalizer<AboutController> localizer)
{
_localizer = localizer;
}
[HttpGet]
public string Index()
{
ViewBag.Title = _localizer["About Title"];
return View();
}
}
}
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<p>@Localizer["Use this area to provide additional information."]</p>
In the example at above you need to add 4 files in Resources
directory~/Resources/Controllers/AboutController.en-GB.resx
~/Resources/Controllers/AboutController.zh-CN.resx
~/Resources/Views/About/Index.en-GB.resx
~/Resources/Views/About/Index.zh-CN.resx
NOTE: Don't forget when you add language code suffix to your
.resx
files, Visual Studio will not generate resource manager for you
Now we able to detect language by providers already exists. To use them just add the providers to RequestCultureProviders
QueryStringRequestCultureProvider
CookieRequestCultureProvider
AcceptLanguageHeaderRequestCultureProvider
CustomRequestCultureProvider
QueryStringRequestCultureProvider
Some apps will use a query string to set the culture and UI culture. For apps that use the cookie or Accept-Language header approach, adding a query string to the URL is useful for debugging and testing code. By default, the QueryStringRequestCultureProvider is registered as the first localization provider in the RequestCultureProvider list. You pass the query string parameters culture and ui-culture. The following example sets the specific culture (language and region) to Spanish/Mexico: http://localhost:5000/?culture=es-MX&ui-culture=es-MX
For change the query string key you need to set QueryStringKey
when you want to init QueryStringRequestCultureProvider
object
/*
At example below your URL will be looks as this:
http://localhost:5000/?lang=es-MX&ui-lang=es-MX
*/
opts.RequestCultureProviders.Add(new QueryStringRequestCultureProvider() { QueryStringKey = "lang", UIQueryStringKey = "ui-lang" });
CookieRequestCultureProvider
Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. Use the
MakeCookieValue
method to create a cookie.
The
CookieRequestCultureProvider
DefaultCookieName
returns the default cookie name used to track the user’s preferred culture information. The default cookie name is".AspNetCore.Culture"
.
The cookie format is
c=%LANGCODE%|uic=%LANGCODE%
, wherec
isCulture
anduic
isUICulture
, for example:
c='en-UK'|uic='en-US'
How to set the culture programmatically
First create a Partial View
for language selector
@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 = LocOptions.Value.SupportedUICultures
.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
.ToList();
}
<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
<form id="selectLanguage" asp-controller="Home"
asp-action="SetLanguage" asp-route-returnUrl="@Context.Request.Path"
method="post" class="form-horizontal" role="form">
@Localizer["Language:"] <select name="culture"
onchange="this.form.submit();"
asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
</select>
</form>
</div>
After that use it everywhere you like following example at below:
@await Html.PartialAsync("_SelectLanguagePartial")
Then write the Action
in your controller for change the language using Cookie
provider
[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);
}
AcceptLanguageHeaderRequestCultureProvider
The Accept-Language header is settable in most browsers and was originally intended to specify the user's language. This setting indicates what the browser has been set to send or has inherited from the underlying operating system. The Accept-Language HTTP header from a browser request is not an infallible way to detect the user's preferred language (see Accept-Language header). A production app should include a way for a user to customize their choice of culture.
For automatic select language using browser accept list you can add this provider to detect language by each request from user.
CustomRequestCultureProvider
Suppose you want to let your customers store their language and culture in your databases. You could write a provider to look up these values for the user. The following code shows how to add a custom provider
For select culture as custom way for example what we did in DotNetBlog
you can take a looks to the source code or see the example below. In this way we can select the language in Admin
page and force the user to see the web site by our selected language. It's very useful for Weblog, Forum, CMS,... and application to manage the content.
opts.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(context => {
var settingService = context.RequestServices.GetService<Core.Service.SettingService>();
// My custom request culture logic
return Task.Run(() => new ProviderCultureResult(settingService.Get().Language));
}));