Deferred translation

Deferred translation is an approach where Blazor Server forces the user to refresh the website to see the translated content. Simple and effective, but it does not provide much customization. In this tutorial, we are going to learn more about deferred translation with the following topics:

  • What is deferred translation?
  • Comparing deferred translation with instant translation.
  • Suitable language selection strategies.
  • Select the language by cookies.
  • Using the URL to select language.
  • Determine language by browser setting.
You can download the example code used in this topic on GitHub.

What is deferred translation?

There are 2 approaches when making a multilingual website, deferred translation is one of the approaches. When a user selects a language, the translation process will be deferred until the next load of the web page, which means the user need to refresh the web page to see the new language. This downside is easily workaround by forcing Blazor Server to refresh the website.


Comparing deferred translation with instant translation

Deferred Translation Instant Translation
User experience Bad Good
Language selection strategy Not customizable: only supports cookies, browser settings, and URL. Cannot change the priority of the strategies. Customizable: support cookies, browser settings, URL, and custom strategies. Can change the priority of the strategies.
Resource type .resx files only. Support any file extensions and database.
Implement effort Low High

Suitable language selection strategies

For deferred translation, there are 3 language selection strategies available: cookies, browser settings, and URL with the following priority:

  1. URL.
  2. Cookies.
  3. Browser settings.

The URL strategy takes the highest priority, then cookies, then browser settings.

What does this priority mean?

Let's assume your website are using all those 3 strategies, and the user has the following environment:

  1. The requested URL indicates the language is Taiwanese (zh-TW).
  2. The cookies indicates the language is English (en-US).
  3. The browser settings indicates the language is Chinese (zh-CN).

Blazor Server will display the Taiwanese language (zh-TW) despite the cookies and the browser settings differences.


Select the language by cookies

The user preferred language is stored in cookies, as the following image illustrates:

cookie-strategy-language-stored-location.png

This is a continuation of the previous tutorial, begins at step 7.

  1. Configure in the Program.cs.
builder.Services.AddControllers();
builder.Services.AddLocalization(...);
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    // You can set the default language using the following method:
    // options.SetDefaultCulture("fr");
    options.AddSupportedCultures(new[] { "en", "fr" });
    options.AddSupportedUICultures(new[] { "en", "fr" });
    options.RequestCultureProviders = new List<IRequestCultureProvider>()
    {
        new CookieRequestCultureProvider()
    };
});

Why do we have to introduce controllers?

Blazor is an SPA framework, and there will be only 1 request, the cookies are attached to the request. When changing the cookies, it requires a new request. Introducing controllers allows you to interpret the request, allows the Blazor Server able to access the cookies.

  1. Create a folder with the name Controllers and add a controller inside that folder.

add-controller-to-blazor-server.png

[Route("[controller]/[action]")]
public class CultureController : Controller
{
    public IActionResult Set(string culture, string redirectUri)
    {
        if (culture is not null)
        {
            HttpContext.Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new(culture, culture)));
        }

        return LocalRedirect(redirectUri);
    }
}
  1. Build the language selector component. For example:
@inject NavigationManager NavigationManager

<select @onchange="OnChangeLanguage">
    <option value="">Select</option>
    <option value="en">English</option>
    <option value="fr">France</option>
</select>

@code {
    private void OnChangeLanguage(ChangeEventArgs e)
    {
        var uri = new Uri(NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
        var culture = CultureInfo.GetCultureInfo(e.Value as string);
        var cultureEscaped = Uri.EscapeDataString(culture.Name);
        var uriEscaped = Uri.EscapeDataString(uri);
        NavigationManager.NavigateTo($"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}", forceLoad: true);
    }
}

When changing the language, you need to navigate to the controller created at step 8, pass the parameters and force refresh the website.


Using the URL to select language

The user preferred language is embedded in the URL, as the following image illustrates:

url-strategy-language-stored-location.png

This is a continuation of the previous tutorial, begins at step 7.

  1. Configure in Program.cs.
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    // You can set the default language using the following method: 
    // options.SetDefaultCulture("fr");
    options.AddSupportedCultures(new[] { "fr", "en" });
    options.AddSupportedUICultures(new[] { "fr", "en" });
    options.RequestCultureProviders = new List<IRequestCultureProvider>()
    {
        new QueryStringRequestCultureProvider()
    };
});;
  1. Interpret the URL parameters at App.razor and set the respective language. For example:
@inject NavigationManager NavigationManager
@inject IOptions<RequestLocalizationOptions> RequestLocalizationOptions

...

@code {
    protected override void OnInitialized()
    {
        var uri = new Uri(NavigationManager.Uri);
        var urlParameters = HttpUtility.ParseQueryString(uri.Query);
        var defaultCulture = RequestLocalizationOptions.Value.DefaultRequestCulture.Culture;
        var cultureProvider = RequestLocalizationOptions.Value.RequestCultureProviders.First(p => p is QueryStringRequestCultureProvider) as QueryStringRequestCultureProvider;
        CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(urlParameters[cultureProvider.QueryStringKey] ?? defaultCulture.Name);
        CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo(urlParameters[cultureProvider.UIQueryStringKey] ?? CultureInfo.CurrentCulture.Name);
    }
}
  1. Build the language selector component. For example:
@inject NavigationManager NavigationManager

<select @onchange="OnChangeLanguage">
    <option value="">Select</option>
    <option value="en">English</option>
    <option value="fr">France</option>
</select>

@code {
    private void OnChangeLanguage(ChangeEventArgs e)
    {
        var uri = new Uri(NavigationManager.Uri);
        var culture = CultureInfo.GetCultureInfo(e.Value as string);
        var cultureEscaped = Uri.EscapeDataString(culture.Name);
        var urlParameters = HttpUtility.ParseQueryString(uri.Query);
        urlParameters["culture"] = cultureEscaped;
        string urlWithoutQuery = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped);
        NavigationManager.NavigateTo($"{urlWithoutQuery}?{urlParameters.ToString()}", forceLoad: true);
    }
}

When changing the language, you need to add or replace the culture parameter in the URL and force refresh the website.


Determine language by browser setting

The user preferred language is embedded in the request, as the following image illustrates:

browser-settings-strategy-language-stored-location.png

This is a continuation of the previous tutorial, begins at step 7.

  1. Configure in the Program.cs.
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    options.AddSupportedCultures(new[] { "en", "fr" });
    options.AddSupportedUICultures(new[] { "en", "fr" });
    options.RequestCultureProviders = new List<IRequestCultureProvider>()
        {
            new AcceptLanguageHeaderRequestCultureProvider()
        };
});
BLAZOR SCHOOL
Designed and built with care by our dedicated team, with contributions from a supportive community. We strive to provide the best learning experience for our users.
Docs licensed CC-BY-SA-4.0
Copyright © 2021-2025 Blazor School
An unhandled error has occurred. Reload 🗙