From b4f205cbe5425c2904e2d6ca89365307ccd37af9 Mon Sep 17 00:00:00 2001 From: "j.foucher" Date: Sat, 2 May 2026 19:14:57 +0200 Subject: [PATCH] i18n: full pass + culture-aware dates/sizes + Software Update License wording MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Strings.cs : ~80 new keys covering status messages, progress detail (DL/extraction/verify), license summary, license details dialog, onboarding statuses, settings field labels, restart/cancel/quit confirmations, toasts, resume choice, copyright. Strings.FormatSize and Strings.FormatDate / FormatLongDate switch units (o/Ko vs B/KB) and pattern (dd/MM/yyyy vs M/d/yyyy vs 2026年) by active language. - License terminology renamed across UI: "License" → "License de mise à jour" / "Software Update License" to clarify it gates UPDATES, not Proserve itself. Expired/revoked dialogs now spell out "you can still download versions released before this date and launch any installed version". - "🔒 License insuffisante" → "🔒 License de mise à jour requise pour cette version" / "Valid update license needed for this version" so users understand it's a per-version eligibility check, not a global block. - All hardcoded FR strings in views (SettingsDialog labels, LicenseDetails fields, Onboarding statuses, dialog titles, copyright, window chrome tooltips, "Sortie le", etc.) replaced with x:Static loc bindings. - All FormatSize duplicates (5 places) and date format strings (8 places) delegate to Strings helpers — single source of truth for localization. - Settings dialog: License section moved to the top before Language. It's the most important info and conditions what the user can download. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ViewModels/InstalledVersionViewModel.cs | 13 +- .../ViewModels/SettingsViewModel.cs | 18 +- .../Views/LauncherUpdateDialog.xaml | 11 +- .../Views/LauncherUpdateDialog.xaml.cs | 12 +- .../Views/LicenseDetailsDialog.xaml | 15 +- .../Views/LicenseDetailsDialog.xaml.cs | 18 +- src/PSLauncher.App/Views/MainWindow.xaml | 48 +- .../Views/OnboardingDialog.xaml.cs | 18 +- .../Views/ReleaseNotesViewerDialog.xaml | 5 +- src/PSLauncher.App/Views/SettingsDialog.xaml | 70 +-- .../Views/UpdateAvailableDialog.xaml | 7 +- .../Views/UpdateAvailableDialog.xaml.cs | 19 +- src/PSLauncher.Core/Localization/Strings.cs | 515 +++++++++++++++++- 13 files changed, 634 insertions(+), 135 deletions(-) diff --git a/src/PSLauncher.App/ViewModels/InstalledVersionViewModel.cs b/src/PSLauncher.App/ViewModels/InstalledVersionViewModel.cs index 77b2d9d..8356b61 100644 --- a/src/PSLauncher.App/ViewModels/InstalledVersionViewModel.cs +++ b/src/PSLauncher.App/ViewModels/InstalledVersionViewModel.cs @@ -1,3 +1,4 @@ +using PSLauncher.Core.Localization; using PSLauncher.Models; namespace PSLauncher.App.ViewModels; @@ -11,17 +12,7 @@ public sealed class InstalledVersionViewModel public string Display => $"v{Model.Version}"; public string Subtitle => - $"{FormatSize(Model.SizeBytes)} • Installée le {Model.InstalledAt.ToLocalTime():dd/MM/yyyy}"; - - private static string FormatSize(long bytes) - { - if (bytes <= 0) return "—"; - string[] units = { "o", "Ko", "Mo", "Go", "To" }; - double v = bytes; - int u = 0; - while (v >= 1024 && u < units.Length - 1) { v /= 1024; u++; } - return $"{v:0.#} {units[u]}"; - } + $"{Strings.FormatSize(Model.SizeBytes)} • {Strings.FormatDate(Model.InstalledAt)}"; public override string ToString() => Display; } diff --git a/src/PSLauncher.App/ViewModels/SettingsViewModel.cs b/src/PSLauncher.App/ViewModels/SettingsViewModel.cs index d64d104..080d82d 100644 --- a/src/PSLauncher.App/ViewModels/SettingsViewModel.cs +++ b/src/PSLauncher.App/ViewModels/SettingsViewModel.cs @@ -52,11 +52,12 @@ public sealed partial class SettingsViewModel : ObservableObject get { var l = _licenseService.GetCached(); - if (l is null) return "Aucune license activée — clique pour saisir une clé"; + if (l is null) return Strings.LicenseSummaryNone; if (l.Status == "valid") - return $"{l.OwnerName} • valable jusqu'au {l.DownloadEntitlementUntil:dd/MM/yyyy}"; + return Strings.LicenseSummaryValid(l.OwnerName ?? "—", + Strings.FormatDate(l.DownloadEntitlementUntil)); if (l.Status == "expired") - return $"{l.OwnerName} • expirée le {l.DownloadEntitlementUntil:dd/MM/yyyy}"; + return Strings.LicenseSummaryExpired(Strings.FormatDate(l.DownloadEntitlementUntil)); return $"{l.OwnerName} • {l.Status}"; } } @@ -159,7 +160,7 @@ public sealed partial class SettingsViewModel : ObservableObject { var dlg = new Microsoft.Win32.OpenFolderDialog { - Title = "Choisir le dossier d'installation", + Title = Strings.SettingsInstallRoot, InitialDirectory = Directory.Exists(InstallRoot) ? InstallRoot : Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), }; if (dlg.ShowDialog() == true) @@ -287,12 +288,5 @@ public sealed partial class SettingsViewModel : ObservableObject catch { CacheSizeDisplay = "—"; } } - private static string FormatSize(long bytes) - { - if (bytes <= 0) return "0 o"; - string[] units = { "o", "Ko", "Mo", "Go", "To" }; - double v = bytes; int u = 0; - while (v >= 1024 && u < units.Length - 1) { v /= 1024; u++; } - return $"{v:0.#} {units[u]}"; - } + private static string FormatSize(long bytes) => Strings.FormatSize(bytes); } diff --git a/src/PSLauncher.App/Views/LauncherUpdateDialog.xaml b/src/PSLauncher.App/Views/LauncherUpdateDialog.xaml index 81b7674..0386b38 100644 --- a/src/PSLauncher.App/Views/LauncherUpdateDialog.xaml +++ b/src/PSLauncher.App/Views/LauncherUpdateDialog.xaml @@ -1,7 +1,8 @@ @@ -33,7 +34,7 @@ - @@ -41,11 +42,11 @@