Niki Gagliardi
Niki Gagliardi

Reputation: 71

CultureInfo change for all user in Blazor server side

I'm developing an app with blazor server side net 6. the purpose is to have the possibility to select the preferred language for each user.

The problem is that when a user changes the language, it changes for all users

I added this line in the program.cs Program.cs

builder.Services.AddLocalization();

I created a dropdown menu where the user selects the desired language

  <MudSelect 
Class="mud-select text-field label-background-transparent pb-6 mr-3"
@bind-Value="_currentCultureOramsWeb" 
T="string" 
AnchorOrigin="Origin.BottomCenter" 
SelectedValuesChanged="ChangeSelectedCurrentCulture" 
Style="max-width:50px;" 
Edge="Edge.End">
                    
@foreach (var culture in oramsCultureInfosWeb)
    {
     <MudSelectItem Value="@culture" />
    }

</MudSelect>

once the user changes the language, i intercept the event and I change the cultureinfo

  _currentCultureOramsWeb = ci.OramsCultureInfoKey
  // ci.OramsCultureInfoValue is a string like en-US, de-DE
  CultureInfo cultureInfo = new CultureInfo(ci.OramsCultureInfoValue);
  CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
  CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;

Other than that, there are also all the .resx files once the language has been changed, I save the information in the database, linked to the user, so that this is called every time he accesses to the app

Update

In the MainLayout.razor.cs I inctercept the chenge

this is the function

        async void ChangeSelectedCurrentCulture(IEnumerable<string> values)
        {
            string newSelected = values.First();
            var ci = (from cii in oramsCultureInfoList
                      where cii.OramsCultureInfoKey == newSelected
                      select cii).First();

            _currentCultureOramsWeb = ci.OramsCultureInfoKey;

            //ci.OramsCultureInfoValue is a string 
            CultureInfo cultureInfo = new CultureInfo(ci.OramsCultureInfoValue);
            //CurrentCulture = cultureInfo;

            CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
            CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;

            if (Username != null)
            {
                using (UintOfWork uow = new UintOfWork())
                {
                    bool ris = await uow.OramsUserRepository.UpdateCultureInfoForUser(Username, ci.OramsCultureInfoKey);
                    if (ris)
                    {
                        await uow.CompleteAsync();
                    }
                }
            }

            StateHasChanged();
            if (MainJS != null)
            {
                // Refresh all with JS
                await MainJS.InvokeVoidAsync("ReloadPageAfterLangChange");
            }
        }

And this is the file Program.cs, for the localization I added only one line (builder.Services.AddLocalization();)

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using ORAMS_III_Blazor_server.Data;
using MudBlazor.Services;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
using ORAMS_III_Blazor_server.Authentication;
using Serilog;
using Microsoft.Extensions.DependencyInjection;
using ORAMS_III_Blazor_server.Logger;
using ORAMS_III_Blazor_server.PageSupport;
using ORAMS_III_Blazor_server.Data.Dashboard;
using ORAMS_III_Blazor_server.Data.Logger;

/**
* @author Niki Gagliardi
*
* @date - 12/1/2022 3:42:05 PM
*
* @version - 1.0
*/




var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();




// Per info seguire i seguenti link
//https://learn.microsoft.com/it-it/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-3.1#reflect-the-connection-state-in-the-ui
//https://learn.microsoft.com/it-it/aspnet/core/signalr/configuration?view=aspnetcore-6.0&tabs=dotnet#configure-server-options
builder.Services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(60*4);
        options.EnableDetailedErrors = false;
        options.HandshakeTimeout = TimeSpan.FromSeconds(1);
        options.KeepAliveInterval = TimeSpan.FromSeconds(1);
        options.MaximumParallelInvocationsPerClient = 1;
        options.MaximumReceiveMessageSize = 32 * 1024;
        options.StreamBufferCapacity = 10;
    });
//ex code
////builder.Services.AddServerSideBlazor();

//Multi-lang
builder.Services.AddLocalization();

// Add protected session
builder.Services.AddScoped<ProtectedSessionStorage>();

//Add CustomAuth
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();

builder.Services.AddSingleton<WeatherForecastService>();

// Service Dashboard
builder.Services.AddSingleton<DashboardModelView>();

builder.Services.AddSingleton<PageSupportModel>();

//service Logger configuration page 

builder.Services.AddSingleton<LoggerConfigurationModelView>();

//httpcontext to get ip client in login page
builder.Services.AddHttpContextAccessor();


//var logger = new LoggerConfiguration()
//  .ReadFrom.Configuration(builder.Configuration)
//  .Enrich.FromLogContext();


#region OramsLogger
//read section SerilogUser from appsettings.json
var serilogUserInfo = builder.Configuration.GetSection("SerilogUser").Get<SerilogUser>();

// pass var to constructor of OramsLogger to create a dependency injection
builder.Services.AddSingleton<IOramsLoggerService>(s => new OramsLoggerService(serilogUserInfo));
#endregion


builder.Services.AddMudServices();

//Log.Logger = new LoggerConfiguration().CreateBootstrapLogger();
builder.Host.UseSerilog(((ctx, lc) => lc.ReadFrom.Configuration(ctx.Configuration)));


var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.UseSerilogRequestLogging();

app.Run();


UPDATE 2

I tried to change the code in this way.

MainLayout.razor.cs

        public CultureInfo CurrentCulture
        {
            get => _currentCulture;
            set
            {
                
                CultureInfo.CurrentCulture.ClearCachedData();
                _currentCulture = value;
                CultureInfo.CurrentCulture = value;
                CultureInfo.CurrentUICulture = value;
                //CultureInfo.DefaultThreadCurrentCulture = value;
                //CultureInfo.DefaultThreadCurrentUICulture = value;
            }
        }

        private CultureInfo _currentCulture;

When I intercet the change of language, I set the CurrentCulture variable.

In this way, I noticed that in the mainlayout component, the value is updated, but in the other components it remains the same.

Upvotes: 1

Views: 773

Answers (0)

Related Questions