From 44c2adfcfb4b0f9f5ee6d2e3020ad849669691af Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:26:04 +0200 Subject: [PATCH 1/8] feat: Retrieve available cultures / languages dynamically --- .../Utils/LocalizationUtils.cs | 38 +++++++++++++++++++ .../ConfigurationDialogViewModel.cs | 18 +++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 PostCodeSerialMonitor/Utils/LocalizationUtils.cs diff --git a/PostCodeSerialMonitor/Utils/LocalizationUtils.cs b/PostCodeSerialMonitor/Utils/LocalizationUtils.cs new file mode 100644 index 0000000..054f982 --- /dev/null +++ b/PostCodeSerialMonitor/Utils/LocalizationUtils.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Resources; +using PostCodeSerialMonitor.Assets; + +namespace PostCodeSerialMonitor.Utils; + +public static class LocalizationUtils +{ + public static IEnumerable GetAvailableCultures() + { + List result = new List() + { + // Prefill with the default culture info, as this won't be gathered by GetCultures + CultureInfo.GetCultureInfo("en-US") + }; + + ResourceManager rm = new ResourceManager(typeof(Resources)); + + CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); + foreach (CultureInfo culture in cultures) + { + try + { + if (culture.Equals(CultureInfo.InvariantCulture)) continue; //do not use "==", won't work + + ResourceSet? rs = rm.GetResourceSet(culture, true, false); + if (rs != null) + result.Add(culture); + } + catch (CultureNotFoundException) + { + + } + } + return result; + } +} \ No newline at end of file diff --git a/PostCodeSerialMonitor/ViewModels/ConfigurationDialogViewModel.cs b/PostCodeSerialMonitor/ViewModels/ConfigurationDialogViewModel.cs index 4f7fbe8..c53affe 100644 --- a/PostCodeSerialMonitor/ViewModels/ConfigurationDialogViewModel.cs +++ b/PostCodeSerialMonitor/ViewModels/ConfigurationDialogViewModel.cs @@ -3,9 +3,12 @@ using CommunityToolkit.Mvvm.Input; using PostCodeSerialMonitor.Models; using PostCodeSerialMonitor.Services; +using PostCodeSerialMonitor.Utils; using System.Threading.Tasks; using Avalonia.Controls; using System; +using System.Collections.Generic; +using System.Globalization; namespace PostCodeSerialMonitor.ViewModels; @@ -32,11 +35,21 @@ public partial class ConfigurationDialogViewModel : ViewModelBase [ObservableProperty] private string fwUpdateUrl; - public ObservableCollection Languages { get; } = new(); + [ObservableProperty] + private ObservableCollection languages; [ObservableProperty] private string selectedLanguage; + public static ObservableCollection GetAvailableLanguages() + { + var languages = new ObservableCollection(); + var cultures = LocalizationUtils.GetAvailableCultures(); + foreach (CultureInfo culture in cultures) + languages.Add(culture.Name); + return languages; + } + public ConfigurationDialogViewModel(ConfigurationService configurationService) { _configurationService = configurationService; @@ -52,8 +65,7 @@ public ConfigurationDialogViewModel(ConfigurationService configurationService) SelectedLanguage = _originalConfiguration.Language; //Add available languages - Languages.Add("en-US"); - Languages.Add("pt-BR"); + Languages = GetAvailableLanguages(); } [RelayCommand] From 9a93fc36986a7716edcd8e2621e71215b992bb37 Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Sun, 8 Jun 2025 12:50:53 +0200 Subject: [PATCH 2/8] fix: Store AppConfiguration properly (as a dict) --- PostCodeSerialMonitor/Services/ConfigurationService.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PostCodeSerialMonitor/Services/ConfigurationService.cs b/PostCodeSerialMonitor/Services/ConfigurationService.cs index e027dd1..c337ea0 100644 --- a/PostCodeSerialMonitor/Services/ConfigurationService.cs +++ b/PostCodeSerialMonitor/Services/ConfigurationService.cs @@ -5,6 +5,7 @@ using PostCodeSerialMonitor.Models; using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; +using System.Collections.Generic; namespace PostCodeSerialMonitor.Services; public class ConfigurationService @@ -30,7 +31,10 @@ public async Task SaveConfigurationAsync() { try { - var json = JsonSerializer.Serialize(_configurationMonitor.CurrentValue, new JsonSerializerOptions + var newConfig = new Dictionary(){ + { nameof(AppConfiguration), _configurationMonitor.CurrentValue } + }; + var json = JsonSerializer.Serialize(newConfig, new JsonSerializerOptions { WriteIndented = true }); From 2c7ba94726d9fa272ba37a9f35a7910d530eeae3 Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Sun, 8 Jun 2025 17:47:53 +0200 Subject: [PATCH 3/8] fix: Load config.json as required, so validation can kick in --- PostCodeSerialMonitor/PostCodeSerialMonitor.csproj | 6 ++++++ PostCodeSerialMonitor/ServiceCollectionExtensions.cs | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/PostCodeSerialMonitor/PostCodeSerialMonitor.csproj b/PostCodeSerialMonitor/PostCodeSerialMonitor.csproj index a372915..47b46fe 100644 --- a/PostCodeSerialMonitor/PostCodeSerialMonitor.csproj +++ b/PostCodeSerialMonitor/PostCodeSerialMonitor.csproj @@ -37,6 +37,12 @@ + + + PreserveNewest + + + diff --git a/PostCodeSerialMonitor/ServiceCollectionExtensions.cs b/PostCodeSerialMonitor/ServiceCollectionExtensions.cs index 20a9a26..dceb8e2 100644 --- a/PostCodeSerialMonitor/ServiceCollectionExtensions.cs +++ b/PostCodeSerialMonitor/ServiceCollectionExtensions.cs @@ -28,13 +28,12 @@ public static void AddCommonServices(this IServiceCollection collection) // Build configuration var configuration = new ConfigurationBuilder() - .AddJsonFile("config.json", optional: true, reloadOnChange: true) + .AddJsonFile("config.json", optional: false, reloadOnChange: true) .Build(); // Configure options with validation - collection.Configure(configuration.GetSection(nameof(AppConfiguration))); collection.AddOptions() - .Bind(configuration.GetSection(nameof(AppConfiguration))) + .Bind(configuration.GetRequiredSection(nameof(AppConfiguration))) .Validate(x => { return x.FormatVersion == SUPPORTED_CONFIG_FORMAT_VERSION; }) From 229b5879422904529b90269a6f44e6a35852e487 Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Mon, 9 Jun 2025 04:11:54 +0200 Subject: [PATCH 4/8] fix: Assemble correct path for saving config --- PostCodeSerialMonitor/Services/ConfigurationService.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PostCodeSerialMonitor/Services/ConfigurationService.cs b/PostCodeSerialMonitor/Services/ConfigurationService.cs index c337ea0..d49a31d 100644 --- a/PostCodeSerialMonitor/Services/ConfigurationService.cs +++ b/PostCodeSerialMonitor/Services/ConfigurationService.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using System.Collections.Generic; +using System.Linq; namespace PostCodeSerialMonitor.Services; public class ConfigurationService @@ -31,6 +32,9 @@ public async Task SaveConfigurationAsync() { try { + var startupPath = AppContext.BaseDirectory?.TrimEnd(Path.DirectorySeparatorChar) + ?? throw new InvalidOperationException(); + var newConfig = new Dictionary(){ { nameof(AppConfiguration), _configurationMonitor.CurrentValue } }; @@ -39,7 +43,7 @@ public async Task SaveConfigurationAsync() WriteIndented = true }); - await File.WriteAllTextAsync(_configFilePath, json); + await File.WriteAllTextAsync(Path.Join(startupPath, _configFilePath), json); _logger.LogInformation(Assets.Resources.ConfigurationSaved); } catch (Exception ex) From a570951f62f7054844a9d361a933a77a395faaa4 Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Mon, 9 Jun 2025 04:13:53 +0200 Subject: [PATCH 5/8] feat: Load Language from config.json on startup --- PostCodeSerialMonitor/App.axaml.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/PostCodeSerialMonitor/App.axaml.cs b/PostCodeSerialMonitor/App.axaml.cs index ff6d07c..56e9958 100644 --- a/PostCodeSerialMonitor/App.axaml.cs +++ b/PostCodeSerialMonitor/App.axaml.cs @@ -6,6 +6,8 @@ using PostCodeSerialMonitor.ViewModels; using PostCodeSerialMonitor.Views; using Microsoft.Extensions.DependencyInjection; +using PostCodeSerialMonitor.Services; +using System.Globalization; namespace PostCodeSerialMonitor; @@ -29,11 +31,11 @@ public override void OnFrameworkInitializationCompleted() // Creates a ServiceProvider containing services from the provided IServiceCollection var services = collection.BuildServiceProvider(); + var configService = services.GetRequiredService(); var mainWindowViewModel = services.GetRequiredService(); - //@todo Load language setting in cofig.json. - // - //Assets.Resources.Culture = new CultureInfo("en-US"); + // Load language setting in config.json. + Assets.Resources.Culture = new CultureInfo(configService.Config.Language); if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { From a5a43966e93fba49709625b3bba3293aefd12609 Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Mon, 9 Jun 2025 04:31:00 +0200 Subject: [PATCH 6/8] feat: Show messagedialog for 'Restart required' when language is changed --- .../Assets/Resources.Designer.cs | 26 +++++++++++++++++-- .../Assets/Resources.pt-BR.resx | 8 ++++++ PostCodeSerialMonitor/Assets/Resources.resx | 8 ++++++ .../ConfigurationDialogViewModel.cs | 11 ++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/PostCodeSerialMonitor/Assets/Resources.Designer.cs b/PostCodeSerialMonitor/Assets/Resources.Designer.cs index 2861f1b..755ef01 100644 --- a/PostCodeSerialMonitor/Assets/Resources.Designer.cs +++ b/PostCodeSerialMonitor/Assets/Resources.Designer.cs @@ -627,6 +627,28 @@ public static string FailedOpenUrl { get { return ResourceManager.GetString("FailedOpenUrl", resourceCulture); } - } + } + + /// + /// In ViewModels/ConfigurationDialogViewModel.cs + /// + public static string RestartRequired + { + get + { + return ResourceManager.GetString("RestartRequired", resourceCulture); + } + } + + /// + /// In ViewModels/ConfigurationDialogViewModel.cs + /// + public static string LanguageChangedPleaseRestart + { + get + { + return ResourceManager.GetString("LanguageChangedPleaseRestart", resourceCulture); + } + } } -} \ No newline at end of file +} diff --git a/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx b/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx index 36d3f13..67ec836 100644 --- a/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx +++ b/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx @@ -369,4 +369,12 @@ Falha ao abrir URL: {0} In Views/MainWindow.axaml.cs + + Reiniciar necessário + In ViewModels/ConfigurationDialogViewModel.cs + + + O idioma foi alterado. Reinicie o aplicativo para que a alteração entre em vigor. + In ViewModels/ConfigurationDialogViewModel.cs + diff --git a/PostCodeSerialMonitor/Assets/Resources.resx b/PostCodeSerialMonitor/Assets/Resources.resx index ac64898..0336470 100644 --- a/PostCodeSerialMonitor/Assets/Resources.resx +++ b/PostCodeSerialMonitor/Assets/Resources.resx @@ -369,4 +369,12 @@ Failed to open URL: {0} In Views/MainWindow.axaml.cs + + Restart required + In ViewModels/ConfigurationDialogViewModel.cs + + + Language was changed. Please restart the application for it to take effect. + In ViewModels/ConfigurationDialogViewModel.cs + diff --git a/PostCodeSerialMonitor/ViewModels/ConfigurationDialogViewModel.cs b/PostCodeSerialMonitor/ViewModels/ConfigurationDialogViewModel.cs index c53affe..a29dd6b 100644 --- a/PostCodeSerialMonitor/ViewModels/ConfigurationDialogViewModel.cs +++ b/PostCodeSerialMonitor/ViewModels/ConfigurationDialogViewModel.cs @@ -9,6 +9,8 @@ using System; using System.Collections.Generic; using System.Globalization; +using MsBox.Avalonia; +using MsBox.Avalonia.Enums; namespace PostCodeSerialMonitor.ViewModels; @@ -71,6 +73,8 @@ public ConfigurationDialogViewModel(ConfigurationService configurationService) [RelayCommand] private async Task SaveAsync(Window window) { + bool languageChanged = _originalConfiguration.Language != SelectedLanguage; + await _configurationService.UpdateConfigurationAsync(config => { config.CheckForAppUpdates = CheckForAppUpdates; @@ -83,6 +87,13 @@ await _configurationService.UpdateConfigurationAsync(config => }); window.Close(); + + if (languageChanged) { + await MessageBoxManager + .GetMessageBoxStandard(Assets.Resources.RestartRequired, string.Format(Assets.Resources.LanguageChangedPleaseRestart), + ButtonEnum.Ok) + .ShowAsync(); + } } [RelayCommand] From 6d45fad02d0179ead10f555e9bedc936e95e095d Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Mon, 9 Jun 2025 04:39:26 +0200 Subject: [PATCH 7/8] ci: Copy config.json into artifact / release zip --- .github/workflows/build.yml | 1 + PostCodeSerialMonitor/config.json | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 02245fe..490362d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,6 +98,7 @@ jobs: shell: bash run: | cp -r PostCodeSerialMonitor/bin/${{ matrix.configuration }}/net9.0/${{ matrix.runtime }}/publish/* artifacts/${{ matrix.runtime }}/${{ matrix.configuration }}/ + cp PostCodeSerialMonitor/config.json artifacts/${{ matrix.runtime }}/${{ matrix.configuration }}/ - name: Upload artifacts uses: actions/upload-artifact@v4 diff --git a/PostCodeSerialMonitor/config.json b/PostCodeSerialMonitor/config.json index 777aa08..6d73cf6 100644 --- a/PostCodeSerialMonitor/config.json +++ b/PostCodeSerialMonitor/config.json @@ -8,6 +8,7 @@ "CodesMetaBaseUrl": "https://errors.xboxresearch.com/", "FwUpdateUrl": "https://example.com/todo", "MetaStoragePath": "meta", + "Language": "en-US", "MetaJsonUrl": "https://errors.xboxresearch.com/meta.json" } } \ No newline at end of file From a391b912cb27a6ddc23be0e28312938c0f2f49e0 Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Wed, 11 Jun 2025 19:23:29 +0200 Subject: [PATCH 8/8] localization: fix a translation for pt-BR --- PostCodeSerialMonitor/Assets/Resources.pt-BR.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx b/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx index 67ec836..8195cca 100644 --- a/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx +++ b/PostCodeSerialMonitor/Assets/Resources.pt-BR.resx @@ -370,7 +370,7 @@ In Views/MainWindow.axaml.cs - Reiniciar necessário + Necessário reiniciar In ViewModels/ConfigurationDialogViewModel.cs