Localization in ASP.NET Core Razor Pages – Cultures

Hello habr! Right now OTUS is opening recruitment for a new course stream “C # ASP.NET Core developer”… In this regard, we traditionally share with you a useful translation and invite you to sign up for Open Day, within which it will be possible to learn in detail about the course, as well as ask the expert the questions you are interested in.

This is the first article in a series on localization in ASP.NET Core Razor Pages applications. In this article, we will look at the configuration required to prepare a site for content localization, or in other words, for site globalization. In future articles, I’ll talk about creating localized content and how to present it to the end user.

Globalization in ASP.NET Core

Globalization is preparing an application to support different languages ​​depending on the user’s preference. Localization is the process of adapting website content to different countries, regions or cultures. The starting point for globalizing a web application is the ability to define the language or culture for each request. Next, we need a mechanism to select content based on the culture of the current request. In this article, we will look at the role played by the class CultureInfo in localization, and how you can implement the presentation component so that users can choose their preferred culture for queries.

The steps below add basic localization to a Razor Pages app that is built from a standard ASP.NET Core 3.0 web app template with no authentication configured. I named my application “Localization”. You can name yours whatever you want, but in that case, do not forget about namespaces if you copy the code from this article.

1. Start by opening the file Startup.cs and adding the following using directives:

using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Options;

2. Localization is an additional feature. It is not enabled by default. Change the method ConfigureServicesby including AddLocalization, which will make various localization helper services available to the dependency injection system. Then add the following code for config RequestLocalizationOptions in the application.

services.Configure<RequestLocalizationOptions>(options =>
   var supportedCultures = new[]
        new CultureInfo("en"),
        new CultureInfo("de"),
        new CultureInfo("fr"),
        new CultureInfo("es"),
        new CultureInfo("ru"),
        new CultureInfo("ja"),
        new CultureInfo("ar"),
        new CultureInfo("zh"),
        new CultureInfo("en-GB")
    options.DefaultRequestCulture = new RequestCulture("en-GB");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

You need to specify the languages ​​or cultures that you plan to support in your application. Cultures are represented in .NET by the class CultureInfo, which contains information on formatting of numbers and dates, calendars, writing systems, sorting orders, and other issues depending on the location of the end user. Overloading a class constructor CultureInfoused here accepts a string that represents the culture name. Valid values ​​are ISO 639-1 codes that represent the language (for example, “en” for English), with an optional ISO 3166 subculture code that represents the country or dialect (for example, “en-GB” for the UK or “en- ZA for South Africa). The example above supports multiple languages, including one subculture, British English, which was set as the default culture.

3. Now that RequestLocalizationOptions configured, they can be applied to the request localization middleware that needs to be added to the method Configure after app.UseRouting():


var localizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value;

Setting the query culture

To define the culture of the current query, the query localization middleware uses components called RequestCultureProviders… Three of them are added by default:

  • QueryStringRequestCultureProviderwhich gets the culture from the query string

  • CookieRequestCultureProviderwhich gets the culture from the cookie

Providers are called one by one until the culture of the request can be determined. You can also create your own provider, which I plan to dwell on in more detail in the next article. Until then, I’ll show you how to create presentation componentwhich allows the user to set the culture for the current request.

1. The first step is to create a folder named Models and add a class file named CultureSwitcherModel.cs

using System.Collections.Generic;
using System.Globalization;
namespace Localisation.Models
    public class CultureSwitcherModel
        public CultureInfo CurrentUICulture { get; set; }
        public List<CultureInfo> SupportedCultures { get; set; }

2. Add a folder named ViewComponents and add a new C # class file named CultureSwitcherViewcomponent.cs… Then replace the content with the following code:

using Localisation.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Linq;
namespace Localisation.ViewComponents
    public class CultureSwitcherViewComponent : ViewComponent
        private readonly IOptions<RequestLocalizationOptions> localizationOptions;
        public CultureSwitcherViewComponent(IOptions<RequestLocalizationOptions> localizationOptions) =>
            this.localizationOptions = localizationOptions;
        public IViewComponentResult Invoke()
            var cultureFeature = HttpContext.Features.Get<IRequestCultureFeature>();
            var model = new CultureSwitcherModel
                SupportedCultures = localizationOptions.Value.SupportedUICultures.ToList(),
                CurrentUICulture = cultureFeature.RequestCulture.UICulture
            return View(model);

3. Add a new folder to the folder Pages and name it Components… Inside add another folder named CultureSwitcher… Then add Razor View to default.cshtml and replace the existing content with the following:

@model CultureSwitcherModel
    <form id="culture-switcher">
        <select name="culture" id="culture-options">
            @foreach (var culture in Model.SupportedCultures)
                <option value="@culture.Name" selected="@(Model.CurrentUICulture.Name == culture.Name)">@culture.DisplayName</option>
    document.getElementById("culture-options").addEventListener("change", () => {

The view component is simple select an item filled with supported crops that have been customized in Startup… The view it is in uses the default get method, which means the submitted value will appear in the query string with the name cultureQueryStringRequestCultureProvider is designed to search for an element in a query string by key culture (and / or ui-culture).

CurrentCulture for a query specifies the local formatting to be used for things like dates and numbers. CurrentUICulture is used to select the correct resource containing translated strings. In the next article in this series, I’ll look at how to use resource files to localize static content. For CurrentCulture and CurrentUICulture you can set different values, but more often it makes sense for both of these values ​​to be the same. If only one of them is set (for example, through one query string value), then the value is assigned to both properties.

4. At this point, you probably have some red wavy lines in the newly created view – open the file _ViewImports.cshtml and add the second and third directives usingbelow, along with the last line that allows you to use the tag helper to render the view component:

@using Localisation
@using Localisation.Models
@using System.Globalization
@namespace Localisation.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Localisation

5. Include the culture switcher component on the layout page using the tag-helper approach as shown here in the last line.

<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
    <ul class="navbar-nav flex-grow-1">
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>

6. Change Index.cshtmlby including the code in the code block and the HTML for the table that displays the various bits of data:

@using Microsoft.AspNetCore.Localization
@model IndexModel
    ViewData["Title"] = "Home page";
    var requestCultureFeature = HttpContext.Features.Get<IRequestCultureFeature>();
    var requestCulture = requestCultureFeature.RequestCulture;
<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <table class="table culture-table">
            <td style="width:50%;">Culture</td>
            <td>@requestCulture.Culture.DisplayName {@requestCulture.Culture.Name}</td>
            <td>UI Culture</td>
            <td>UICulture Parent</td>

When you first start the application, the culture for the request is set AcceptHeadersCultureRequestProvider… When you use the dropdown to select different crops, the culture is set QueryStringCultureRequestProvider… Try adding the ui-culture key to the query string with a different culture key value (for example https://localhost:xxxxx/?culture=es&ui-culture=de) to see what happens.


This article provides an introduction to localization in Razor Pages. It provides an example of the configuration of the cultures that you want to support in your application and how to pass that configuration to the localization middleware. It demonstrates how the culture for the current request works in terms of formatting the content for display. It also demonstrates how you can allow your visitors to change the culture according to their preferences.

You may have noticed that although the names of the days and months are automatically translated based on the calendar associated with the current culture, the rest of the static content remains in English. In the next article, I’ll show you how to use resource files (.resx) to manage multiple translations for this content type.

More about the course

Read more:

  • Compressing responses in GRPC for ASP.NET CORE 3.0

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *