受欢迎的博客标签

How to Globalization and localization Asp.Net Core application

Published

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

  1. QueryStringRequestCultureProvider
  2. CookieRequestCultureProvider
  3. AcceptLanguageHeaderRequestCultureProvider
  4. 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%, where c is Culture and uic is UICulture, 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));
}));