From c035f78340743719bfe87bfabef5dbc4d00f942e Mon Sep 17 00:00:00 2001 From: Mikhail Shabanov Date: Wed, 7 Apr 2021 12:32:17 +0200 Subject: [PATCH] feat: localization added --- .../Messages/ChangeCurrentCultureMessage.cs | 14 ++ .../Model/UserSettings.cs | 9 ++ .../Pages/Index.razor | 15 +- WotBlitzStatisticsPro.Blazor/Program.cs | 18 ++- .../Resources/App.de.resx | 135 ++++++++++++++++++ .../Resources/App.resx | 101 +++++++++++++ .../Resources/App.ru.resx | 135 ++++++++++++++++++ .../Services/ILocalStorageService.cs | 11 ++ .../Services/LocalStorageService.cs | 47 ++++++ .../Shared/MainLayout.razor | 10 ++ .../Shared/MainLayoutBase.cs | 40 +++++- .../Shared/NavMenu.razor | 10 +- .../Shared/NavMenuBase.cs | 13 +- .../WotBlitzStatisticsPro.Blazor.csproj | 2 + WotBlitzStatisticsPro.Blazor/_Imports.razor | 1 + 15 files changed, 542 insertions(+), 19 deletions(-) create mode 100644 WotBlitzStatisticsPro.Blazor/Messages/ChangeCurrentCultureMessage.cs create mode 100644 WotBlitzStatisticsPro.Blazor/Model/UserSettings.cs create mode 100644 WotBlitzStatisticsPro.Blazor/Resources/App.de.resx create mode 100644 WotBlitzStatisticsPro.Blazor/Resources/App.resx create mode 100644 WotBlitzStatisticsPro.Blazor/Resources/App.ru.resx create mode 100644 WotBlitzStatisticsPro.Blazor/Services/ILocalStorageService.cs create mode 100644 WotBlitzStatisticsPro.Blazor/Services/LocalStorageService.cs diff --git a/WotBlitzStatisticsPro.Blazor/Messages/ChangeCurrentCultureMessage.cs b/WotBlitzStatisticsPro.Blazor/Messages/ChangeCurrentCultureMessage.cs new file mode 100644 index 0000000..a3fdfab --- /dev/null +++ b/WotBlitzStatisticsPro.Blazor/Messages/ChangeCurrentCultureMessage.cs @@ -0,0 +1,14 @@ +using MediatR; + +namespace WotBlitzStatisticsPro.Blazor.Messages +{ + public class ChangeCurrentCultureMessage: INotification + { + public string CultureName { get; } + + public ChangeCurrentCultureMessage(string cultureName) + { + CultureName = cultureName; + } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Model/UserSettings.cs b/WotBlitzStatisticsPro.Blazor/Model/UserSettings.cs new file mode 100644 index 0000000..2f768ae --- /dev/null +++ b/WotBlitzStatisticsPro.Blazor/Model/UserSettings.cs @@ -0,0 +1,9 @@ +namespace WotBlitzStatisticsPro.Blazor.Model +{ + public class UserSettings + { + public const string UserSettingsLocalStorageKey = "user-settings"; + + public string Culture { get; set; } = "en-US"; + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Pages/Index.razor b/WotBlitzStatisticsPro.Blazor/Pages/Index.razor index 8b7292f..2de3222 100644 --- a/WotBlitzStatisticsPro.Blazor/Pages/Index.razor +++ b/WotBlitzStatisticsPro.Blazor/Pages/Index.razor @@ -2,23 +2,24 @@ @using MediatR @using WotBlitzStatisticsPro.Blazor.Messages @using WotBlitzStatisticsPro.Blazor.Model +@inject IStringLocalizer Localize @inject IMediator Mediator
- + { await Mediator.Publish(new LoginToWgMessage()); }) Icon="vpn_key" - Text="Login with WG.net ID" - Style="width: 250px; margin: 30px" /> + Text=@Localize["Login with WG.net ID"] + Style="width: 300px; margin: 30px" /> { await Mediator.Publish(new OpenSearchDialogMessage(DialogType.FindPlayer)); }) Icon="person_search" - Text="Search player" - Style="width: 250px; margin: 30px" /> + Text=@Localize["Search player"] + Style="width: 300px; margin: 30px" /> { await Mediator.Publish(new OpenSearchDialogMessage(DialogType.FindClan)); }) Icon="screen_search_desktop" - Text="Search clan" - Style="width: 250px; margin: 30px" /> + Text=@Localize["Search clan"] + Style="width: 300px; margin: 30px" />
diff --git a/WotBlitzStatisticsPro.Blazor/Program.cs b/WotBlitzStatisticsPro.Blazor/Program.cs index 0635bf3..00948f2 100644 --- a/WotBlitzStatisticsPro.Blazor/Program.cs +++ b/WotBlitzStatisticsPro.Blazor/Program.cs @@ -1,10 +1,13 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.Extensions.DependencyInjection; using System; +using System.Globalization; using System.Net.Http; using System.Threading.Tasks; using MediatR; +using Microsoft.JSInterop; using Radzen; +using WotBlitzStatisticsPro.Blazor.Model; using WotBlitzStatisticsPro.Blazor.Services; namespace WotBlitzStatisticsPro.Blazor @@ -15,6 +18,7 @@ namespace WotBlitzStatisticsPro.Blazor { var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add("#app"); + builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); @@ -24,8 +28,20 @@ namespace WotBlitzStatisticsPro.Blazor builder.Services.AddMediatR(typeof(Program)); builder.Services.AddSingleton(); + builder.Services.AddScoped(); - await builder.Build().RunAsync(); + var host = builder.Build(); + // Reading Current Culture from LocalStorage + var localStorageService = host.Services.GetRequiredService(); + var settings = await localStorageService.GetItemAsync(UserSettings.UserSettingsLocalStorageKey); + if (settings != null) + { + var culture = new CultureInfo(settings.Culture); + CultureInfo.DefaultThreadCurrentCulture = culture; + CultureInfo.DefaultThreadCurrentUICulture = culture; + } + + await host.RunAsync(); } } } diff --git a/WotBlitzStatisticsPro.Blazor/Resources/App.de.resx b/WotBlitzStatisticsPro.Blazor/Resources/App.de.resx new file mode 100644 index 0000000..b9fdc4b --- /dev/null +++ b/WotBlitzStatisticsPro.Blazor/Resources/App.de.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Startseite + + + Anmelden mit WG.net-ID + + + Clan suchen + + + Spieler suchen + + + Willkommen bei der WOT Blitz statistics! + + \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Resources/App.resx b/WotBlitzStatisticsPro.Blazor/Resources/App.resx new file mode 100644 index 0000000..4fdb1b6 --- /dev/null +++ b/WotBlitzStatisticsPro.Blazor/Resources/App.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Resources/App.ru.resx b/WotBlitzStatisticsPro.Blazor/Resources/App.ru.resx new file mode 100644 index 0000000..aa60302 --- /dev/null +++ b/WotBlitzStatisticsPro.Blazor/Resources/App.ru.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + На главную + + + Войти с WG.net ID + + + Поиск клана + + + Поиск игрока + + + Добро пожаловать в WOT Blitz statistics! + + \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Services/ILocalStorageService.cs b/WotBlitzStatisticsPro.Blazor/Services/ILocalStorageService.cs new file mode 100644 index 0000000..49c53ab --- /dev/null +++ b/WotBlitzStatisticsPro.Blazor/Services/ILocalStorageService.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace WotBlitzStatisticsPro.Blazor.Services +{ + public interface ILocalStorageService + { + Task SetItemAsync(string key, T item); + + Task GetItemAsync(string key); + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Services/LocalStorageService.cs b/WotBlitzStatisticsPro.Blazor/Services/LocalStorageService.cs new file mode 100644 index 0000000..33f4a8b --- /dev/null +++ b/WotBlitzStatisticsPro.Blazor/Services/LocalStorageService.cs @@ -0,0 +1,47 @@ +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; +using WotBlitzStatisticsPro.Blazor.Messages; +using WotBlitzStatisticsPro.Blazor.Model; + +namespace WotBlitzStatisticsPro.Blazor.Services +{ + public class LocalStorageService: ILocalStorageService, INotificationHandler + { + private readonly IJSRuntime _jsRuntime; + private readonly NavigationManager _navigationManager; + + public LocalStorageService( + IJSRuntime jsRuntime, + NavigationManager navigationManager) + { + _jsRuntime = jsRuntime; + _navigationManager = navigationManager; + } + + public async Task SetItemAsync(string key, T item) + { + await _jsRuntime.InvokeVoidAsync("localStorage.setItem", + key, JsonSerializer.Serialize(item)); + } + + public async Task GetItemAsync(string key) + { + var json = await _jsRuntime.InvokeAsync("localStorage.getItem", key); + return string.IsNullOrEmpty(json) + ? default + : JsonSerializer.Deserialize(json); + } + + public async Task Handle(ChangeCurrentCultureMessage notification, CancellationToken cancellationToken) + { + var currentSettings = await GetItemAsync(UserSettings.UserSettingsLocalStorageKey) ?? new UserSettings(); + currentSettings.Culture = notification.CultureName; + await SetItemAsync(UserSettings.UserSettingsLocalStorageKey, currentSettings); + _navigationManager.NavigateTo(_navigationManager.Uri, forceLoad: true); + } + } +} \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Shared/MainLayout.razor b/WotBlitzStatisticsPro.Blazor/Shared/MainLayout.razor index 181e6ea..837dc9e 100644 --- a/WotBlitzStatisticsPro.Blazor/Shared/MainLayout.razor +++ b/WotBlitzStatisticsPro.Blazor/Shared/MainLayout.razor @@ -11,6 +11,16 @@ +
+ + + @foreach (var ci in CultureInfos) + { + + } + + +
diff --git a/WotBlitzStatisticsPro.Blazor/Shared/MainLayoutBase.cs b/WotBlitzStatisticsPro.Blazor/Shared/MainLayoutBase.cs index ae8ccc9..cd5c3bf 100644 --- a/WotBlitzStatisticsPro.Blazor/Shared/MainLayoutBase.cs +++ b/WotBlitzStatisticsPro.Blazor/Shared/MainLayoutBase.cs @@ -1,7 +1,13 @@ -using System.Threading; +using System.Collections.Generic; +using System.Globalization; +using System.Threading; +using MediatR; using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using Microsoft.JSInterop; using Radzen; using Radzen.Blazor; +using WotBlitzStatisticsPro.Blazor.Messages; namespace WotBlitzStatisticsPro.Blazor.Shared { @@ -10,11 +16,33 @@ namespace WotBlitzStatisticsPro.Blazor.Shared [Inject] private DialogService DialogService { get; set; } + [Inject] + private IMediator Mediator { get; set; } + public RadzenSidebar Sidebar0; public RadzenBody Body0; public bool SidebarExpanded { get; set; } = false; public bool BodyExpanded { get; set; } = true; + public Dictionary CultureInfos { get; set; } = new() + { + { "en-US", new CultureInfo("en-US", false)}, + { "ru-RU", new CultureInfo("ru-RU", false)}, + { "de-DE", new CultureInfo("de-DE", false)} + }; + + public CultureInfo CurrentCultureInfo + { + get => CultureInfo.CurrentCulture; + set + { + if (CultureInfo.CurrentCulture != value) + { + Mediator.Publish(new ChangeCurrentCultureMessage(value.Name)); + } + } + } + protected override void OnInitialized() { //if (httpContextAccessor != null && httpContextAccessor.HttpContext != null && @@ -31,8 +59,6 @@ namespace WotBlitzStatisticsPro.Blazor.Shared // } //} - - Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US"); } public void InvertSideBar() @@ -40,5 +66,13 @@ namespace WotBlitzStatisticsPro.Blazor.Shared SidebarExpanded = !SidebarExpanded; BodyExpanded = !BodyExpanded; } + + public void LanguageSelected(RadzenSplitButtonItem item) + { + if (item != null) + { + CurrentCultureInfo = CultureInfos[item.Value]; + } + } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Shared/NavMenu.razor b/WotBlitzStatisticsPro.Blazor/Shared/NavMenu.razor index f0dbe48..0014acd 100644 --- a/WotBlitzStatisticsPro.Blazor/Shared/NavMenu.razor +++ b/WotBlitzStatisticsPro.Blazor/Shared/NavMenu.razor @@ -1,9 +1,11 @@ @inherits NavMenuBase +@inject IStringLocalizer Localize +
- - - - + + + +
diff --git a/WotBlitzStatisticsPro.Blazor/Shared/NavMenuBase.cs b/WotBlitzStatisticsPro.Blazor/Shared/NavMenuBase.cs index 8baad6a..02ab994 100644 --- a/WotBlitzStatisticsPro.Blazor/Shared/NavMenuBase.cs +++ b/WotBlitzStatisticsPro.Blazor/Shared/NavMenuBase.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using MediatR; using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; using Radzen; using WotBlitzStatisticsPro.Blazor.Messages; using WotBlitzStatisticsPro.Blazor.Model; @@ -19,6 +20,10 @@ namespace WotBlitzStatisticsPro.Blazor.Shared [Inject] public ISearchDialogService SearchDialogService { get; set; } + [Inject] + private IStringLocalizer Localizer { get; set; } + + [Parameter] public EventCallback CloseSideBar { get; set; } @@ -27,17 +32,17 @@ namespace WotBlitzStatisticsPro.Blazor.Shared await CloseSideBar.InvokeAsync(); switch (menuItem.Text) { - case "Home": + case var _ when(Localizer.GetString("Home")) == menuItem.Text: NavManager.NavigateTo("/"); break; - case "Login with WG.net ID": + case var _ when (Localizer.GetString("Login with WG.net ID")) == menuItem.Text: await Mediator.Publish(new LoginToWgMessage()); break; - case "Search player": + case var _ when (Localizer.GetString("Search player")) == menuItem.Text: await Mediator.Publish(new OpenSearchDialogMessage(DialogType.FindPlayer)); //await SearchDialogService.OpenSearchDialog(DialogType.FindPlayer); break; - case "Search clan": + case var _ when (Localizer.GetString("Search clan")) == menuItem.Text: await Mediator.Publish(new OpenSearchDialogMessage(DialogType.FindClan)); break; } diff --git a/WotBlitzStatisticsPro.Blazor/WotBlitzStatisticsPro.Blazor.csproj b/WotBlitzStatisticsPro.Blazor/WotBlitzStatisticsPro.Blazor.csproj index f4db992..b670508 100644 --- a/WotBlitzStatisticsPro.Blazor/WotBlitzStatisticsPro.Blazor.csproj +++ b/WotBlitzStatisticsPro.Blazor/WotBlitzStatisticsPro.Blazor.csproj @@ -3,6 +3,7 @@ net5.0 service-worker-assets.js + true @@ -10,6 +11,7 @@ + diff --git a/WotBlitzStatisticsPro.Blazor/_Imports.razor b/WotBlitzStatisticsPro.Blazor/_Imports.razor index f94f664..e1a3ea1 100644 --- a/WotBlitzStatisticsPro.Blazor/_Imports.razor +++ b/WotBlitzStatisticsPro.Blazor/_Imports.razor @@ -5,6 +5,7 @@ @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.WebAssembly.Http +@using Microsoft.Extensions.Localization @using Microsoft.JSInterop @using WotBlitzStatisticsPro.Blazor @using WotBlitzStatisticsPro.Blazor.Shared