Keerthi
Keerthi

Reputation: 63

Globalization and Localization in Pre-rendering Blazor Wasm App using cookies

I am not able to find any reference/ solution to set the culture in the Blazor app through cookies in a pre-rendered application.

Please help me to find one.

Upvotes: 0

Views: 569

Answers (2)

Add to _Host.cshtml

    @{
        var rqf = HttpContext.Request.Headers.AcceptLanguage;
        var language = Request.GetTypedHeaders()
                           .AcceptLanguage
                           ?.OrderByDescending(x => x.Quality ?? 1)
                           .Select(x => x.Value.ToString())
                           .First() ?? null;
                           if (language!=null)
                           {
            var culture = new CultureInfo(languages);
            CultureInfo.DefaultThreadCurrentCulture = culture;
            CultureInfo.DefaultThreadCurrentUICulture = culture;
        }
      
    }
    <component  type="typeof(ProImprover.Client.App)" render-mode="WebAssemblyPrerendered" />
                           

Upvotes: 0

Jacco M.
Jacco M.

Reputation: 31

I had the same problem and figured out a solution. It's not the nicest one but it works:

First, I configured localization in Progam.cs in the server project (assuming .NET 6):

builder.Services.AddLocalization();
...
...
string[] cultures = {"de","en","nl" };
app.UseRequestLocalization(new RequestLocalizationOptions()
    .SetDefaultCulture(cultures.First())
    .AddSupportedCultures(cultures)
    .AddSupportedUICultures(cultures));



In _Host.cshtml (also on the server) you can intercept the initial request to customize the current culture. For instance, check for query string value or preferred language cookie.

@page "/"
@namespace blazor.Client
@using System.Globalization
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
   Layout = "_Layout";
 

   //use the default culture from server initials request
   var requestCulture = CultureInfo.CurrentCulture.Name;
   //get culture from query string
   if (Request.Query.ContainsKey("culture"))
   {
       var lang = Request.Query["culture"].ToString();
       requestCulture = lang;
       //todo: place language cookie
   }
   //get culture from cookie
   if (Request.Cookies.TryGetValue(CookieRequestCultureProvider.DefaultCookieName, out var value))
   {
       var fromCookie = CookieRequestCultureProvider.ParseCookieValue(value).Cultures.First().Value;
       requestCulture = fromCookie;
   }

   

and then you pass the current culture to the App component (also in _Host.cshtml)

<component 
           type="typeof(App)"
           param-SelectedCulture="requestCulture"
           render-mode="WebAssemblyPrerendered" />

The custom culture is passed to the App component via 'param-SelectedCulture' as a string value.

In App.razor you can assign this value to CurrentInfo.DefaultThread like so:

@using System.Globalization

<AppState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</AppState>

@code {
    [Parameter] public string SelectedCulture { get; set; } = default!;
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            var selectedCulture = new CultureInfo(SelectedCulture);
            CultureInfo.DefaultThreadCurrentCulture = selectedCulture;
            CultureInfo.DefaultThreadCurrentUICulture = selectedCulture;
        }
    }
}

In your client app you can set a language cookie after the user selects a different language. After setting the cookie, reload the page:

NavigationManager.NavigateTo("/",true)

Upvotes: 2

Related Questions