ScarletKuro / Blazor.WebAssembly.DynamicCulture

Blazor.WebAssembly.DynamicCulture.Loader is a powerful tool that simplifies the process of loading multiple localization satellite assemblies simultaneously during startup in Blazor WebAssembly applications. With this tool, there's no need to manually refresh the page in order to access the new resource assembly.
MIT License
8 stars 0 forks source link

Reload Resources from other csproj #5

Closed SerreauFrederic closed 1 month ago

SerreauFrederic commented 3 months ago

Hi,

I used this package and it works correctly.

But I have other projects in my solution, and these do not reload the resources dynamically.

Is there a solution for this case?

Thanks

ScarletKuro commented 3 months ago

Hi,

Could you please provide more context and technical details regarding your issue? It would be very helpful if you could share a reproduction of the problem. Your current description is quite vague and doesn't offer enough information for me to assist you.

Thank you.

SerreauFrederic commented 2 months ago

Hi,

Sorry for the delay in replying.

I'm trying to make a demo project in the next few days.

Thanks

Pinox commented 1 month ago

Hi @ScarletKuro

Same problem on my side. Not sure if it is similar to above.

Would like to use your nuget of Blazor.WebAssembly.DynamicCulture packages in my Blazor Hybrid app as screen refreshes on native type apps is undesirable when the culture changes.

I always get the following error when I move my pages to a Shared Razor Library. image

I tried to change the resources path to variations of "_context\DynamicCulture.Shared\Resources\Translations" but I can't get it to work.

Also, on the MAUI side how do we use "await app.SetMiddlewareCulturesAsync();" as Maui Blazor does not have a WebAssembly host ?

Would appreciate your feedback and thanks in advance.

Sample App https://1drv.ms/u/s!AkcH3KVxOeYGvspaYsYHSaKo6U5i7A?e=m8pLas

ScarletKuro commented 1 month ago

Hi @Pinox,

You need to add the following code to the DynamicCulture.Web project:

builder.Services.AddLocalization();
builder.Services.TryAddSingleton<ILocalizationService, LocalizationService>();
builder.Services.TryAddScoped<LocalizationLocalStorageManager>();
builder.Services.TryAddScoped<LocalizationNavigatorManager>();
builder.Services.TryAddScoped<LocalizationQueryManager>();
builder.Services.TryAddScoped<LocalizationContextManager>();
builder.Services.TryAddScoped<LocalizationDynamicMiddleware>();

Unfortunately, the WebApp template requires these services to be registered in both places, for DynamicCulture.Web.Client it's done through AddLocalizationDynamic.

While I see that the Localizer["About"] in the AppBar changes when switching languages, I haven't tested this solution in a WebApp. It was primarily designed for standalone WASM projects and has only been battle-tested in my startup projects using this template. Using WebApp as is at your own risk. I may look into officially supporting WebApp later.

Pinox commented 1 month ago

Thanks @ScarletKuro

You're an absolute star. Thanks so much !!

For anyone that is interested here is the source for the full working copy tested on Android , WinUI3 and WASM.

https://1drv.ms/u/s!AkcH3KVxOeYGvspdctvubjVyq7TqNg?e=SPcDCv

All working like a charm !!

SerreauFrederic commented 1 month ago

Well after some tests it turns out that the resources load well finally, it is rather a problem of refresh depending on where I place the component.

For example in my demo, if it is placed in the appBar, it does nothing. If we use the one that is in the Home page, the resources of this same page are modified, but not that of the NavBar as long as I do not interact with it.

I still put the example, but I managed to get by with StateHasChanged on the components that I want to refresh.

Thanks.

DynamicCultureMultiProjects.zip

ScarletKuro commented 1 month ago

I still put the example, but I managed to get by with StateHasChanged on the components that I want to refresh.

This is the expected behavior. You need to call StateHasChanged on page / component that require translation.

If we use the one that is in the Home page, the resources of this same page are modified, but not that of the NavBar

It works on the same page because when you change language, Blazor automatically refreshes the page / component as part of its default behavior when an EventCallback is triggered. However, other pages / components are not tracked.

This is why the Blazor.WebAssembly.DynamicCulture package includes the LanguageTrackProvider: https://github.com/ScarletKuro/Blazor.WebAssembly.DynamicCulture/blob/f524f2e69991df8127798b4571bc5452cae88fcd/src/Blazor.WebAssembly.DynamicCulture/LanguageTrackProvider.cs#L47 It tracks language changes and refreshes the needed parts that use this provider: https://github.com/ScarletKuro/Blazor.WebAssembly.DynamicCulture/blob/master/docs/Blazor-wasm-localization.md#add-components

Since you are not using Blazor.WebAssembly.DynamicCulture packages, you'll need to handle this yourself.

Pinox commented 1 month ago

@ScarletKuro

Just one update , putting your suggestions in Blazor Server + Blazr MAUI works fine when I keep the instance of the app open and refreshes the browser control.

builder.Services.AddLocalization(); builder.Services.TryAddSingleton<ILocalizationService, LocalizationService>(); builder.Services.TryAddScoped(); builder.Services.TryAddScoped(); builder.Services.TryAddScoped(); builder.Services.TryAddScoped(); builder.Services.TryAddScoped();

There seems to be a problem when I restart the app, BlazorCulture on localstorage displays the culture correctly but it's not invoked on the startup. (that is MAUI + Blazor Server) So the culture in localstorage is correct, for example set to ru - Russian but the dropdown language control displays English and the displayed language of labels will also be English

Is there any command that I can run to invoke this ? I assume this is happening because I can't use await app.SetMiddlewareCulturesAsync(); in Server + MAUI as it's tied to the WebAssemblyHost.

ScarletKuro commented 1 month ago

@Pinox the problem is that this is the only solution for WASM, as it only uses APIs that exist in the context of WASM. If you are using a server or mixing render boundaries between WASM and the Server, it will also not work. This was created for a specific purpose: to eliminate the restrictions of WASM.

  1. By default, WASM loads only one satellite (language resource .dll) assembly at a time. This means that if you change the language, it will stash the new resources, and in order for them to take effect, you need to hard refresh the page. This was not acceptable to me.

  2. To use the native IStringLocalizer.

If you need a hybrid solution that works consistently across all environments, I would recommend looking at Toolbelt.Blazor.I18nText. It does not use Microsoft .resx files, which means it does not require satellite assemblies. Instead, it uses JSON, which eliminates the restrictions present in WASM (If you look at pros is has "the display language can be changed without page reloading", which my solution tried to achieve, but sololy on WASM environment). As far as I know, this solution should work in all render modes, as stated in the description.

Pinox commented 1 month ago

Thanks @ScarletKuro

I just loaded the localstorage value on startup into culture and that solved the issue ;))

CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo( from localstorage )

When I do above my language control dropdown is also set to the correct value.

So happy with your solution ;))

ScarletKuro commented 1 month ago

I am closing this issue, as I believe all questions have been answered.