This commit introduces comprehensive localization support for the application, enabling dynamic language switching and localized UI elements. Key changes include: - Added `.resx` files for German (de-DE), English (en-US), and French (fr-FR). - Updated Razor components to use `IStringLocalizer` for dynamic string localization. - Introduced the `L(string key, string fallback)` helper method for consistent localized string retrieval with fallback support. - Implemented dynamic culture initialization in `Program.cs` via an API call to `/api/Localization/lang`. - Localized error pages, grid columns, tabs, popups, validation messages, and tooltips. - Dynamically generated privacy policy links based on the current culture. - Improved user experience with fully localized loading states, error handling, and UI labels. These changes enhance accessibility and usability, making the application more user-friendly for a global audience.
80 lines
2.4 KiB
Plaintext
80 lines
2.4 KiB
Plaintext
@using EnvelopeGenerator.Server.Client.Services
|
|
@using EnvelopeGenerator.Application.Resources
|
|
@using Microsoft.AspNetCore.Components.Routing
|
|
@using Microsoft.Extensions.Localization
|
|
@using System.Globalization
|
|
@inherits LayoutComponentBase
|
|
@implements IDisposable
|
|
|
|
@inject ThemeService ThemeService
|
|
@inject IStringLocalizer<Resource> UiLocalizer
|
|
@inject NavigationManager Navigation
|
|
|
|
<HeadContent>
|
|
<link href="@ThemeService.ThemeCssHref" rel="stylesheet" />
|
|
</HeadContent>
|
|
|
|
<div class="page" data-bs-theme="@ThemeService.BootstrapTheme">
|
|
<main>
|
|
<article class="content">
|
|
@Body
|
|
</article>
|
|
</main>
|
|
<footer class="receiver-footer">
|
|
<div class="receiver-footer__left">
|
|
<span>© SignFlow 2023-2024 <a href="https://digitaldata.works" target="_blank" rel="noopener">Digital Data GmbH</a></span>
|
|
<span class="receiver-footer__sep">|</span>
|
|
<a href="@GetPrivacyPolicyPath()" target="_blank" rel="noopener">@L("PrivacyPolicy", "Datenschutz")</a>
|
|
</div>
|
|
|
|
<div class="receiver-footer__right">
|
|
<LanguageControls />
|
|
<ThemeControls />
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
|
|
@code {
|
|
[Inject] IHttpClientFactory HttpClientFactory { get; set; } = default!;
|
|
|
|
private Action? _themeChangeHandler;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
Navigation.LocationChanged += OnLocationChanged;
|
|
await FontLoader.LoadFonts(HttpClientFactory, ["opensans.ttf"]);
|
|
_themeChangeHandler = () => InvokeAsync(StateHasChanged);
|
|
ThemeService.OnChange += _themeChangeHandler;
|
|
await base.OnInitializedAsync();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
ThemeService.OnChange -= _themeChangeHandler;
|
|
Navigation.LocationChanged -= OnLocationChanged;
|
|
}
|
|
|
|
private void OnLocationChanged(object? sender, LocationChangedEventArgs e)
|
|
=> _ = InvokeAsync(StateHasChanged);
|
|
|
|
private string GetPrivacyPolicyPath()
|
|
{
|
|
var current = CultureInfo.CurrentUICulture.Name;
|
|
var code = current switch
|
|
{
|
|
"de-DE" => "de-DE",
|
|
"en-US" => "en-US",
|
|
"fr-FR" => "fr-FR",
|
|
_ => "de-DE"
|
|
};
|
|
|
|
return $"docs/privacy-policy.{code}.html";
|
|
}
|
|
|
|
string L(string key, string fallback)
|
|
{
|
|
var value = UiLocalizer[key];
|
|
return value.ResourceNotFound ? fallback : value.Value;
|
|
}
|
|
}
|