i18n: localize all MessageBox dialogs

The previous batch only covered XAML strings. The runtime MessageBox
dialogs (errors, confirmations, info popups) stayed hardcoded in
French, breaking immersion for non-FR users.

Added ~15 keys to Strings.cs for the MessageBox bodies and titles:
- error / launch error / confirm / info / patience / language change /
  release notes (titles)
- launch failed / self-update failed / install failed / uninstall
  failed / uninstall confirm with version+folder+size / no release
  notes / fetch failed / clear cache confirm / deactivate license
  (short and detailed) / language restart (bodies)

Some are parametrized (MsgLaunchFailed(detail), MsgUninstallConfirm
(version, folder, size)) so the localized strings interpolate the
runtime values cleanly across all 5 languages.

Replaced every MessageBox.Show in MainViewModel, SettingsViewModel
and LicenseDetailsDialog.xaml.cs to use these keys. The "Échec : "
prefix in the cache-clear error was dropped — the error message alone
is sufficient with Strings.MsgBoxError as the dialog title.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 13:56:52 +02:00
parent b9ce591d22
commit 0d4f126e3a
4 changed files with 133 additions and 26 deletions

View File

@@ -12,6 +12,7 @@ using PSLauncher.Core.Configuration;
using PSLauncher.Core.Downloads;
using PSLauncher.Core.Installations;
using PSLauncher.Core.Licensing;
using PSLauncher.Core.Localization;
using PSLauncher.Core.Manifests;
using PSLauncher.Core.Process;
using PSLauncher.Core.Updates;
@@ -338,8 +339,8 @@ public sealed partial class MainViewModel : ObservableObject
catch (Exception ex)
{
_logger.LogError(ex, "Self-update failed");
MessageBox.Show($"Mise à jour du launcher échouée :\n\n{ex.Message}",
"Erreur", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show(Strings.MsgSelfUpdateFailed(ex.Message),
Strings.MsgBoxError, MessageBoxButton.OK, MessageBoxImage.Error);
StatusMessage = $"Erreur self-update : {ex.Message}";
IsBusy = false;
}
@@ -463,15 +464,15 @@ public sealed partial class MainViewModel : ObservableObject
catch (Exception ex)
{
_logger.LogError(ex, "Launch failed");
MessageBox.Show($"Impossible de lancer la version :\n\n{ex.Message}",
"Erreur de lancement", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show(Strings.MsgLaunchFailed(ex.Message),
Strings.MsgBoxLaunchError, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private async Task InstallVersionAsync(VersionRowViewModel row)
{
if (row.Remote is null) return;
if (IsBusy) { MessageBox.Show("Une autre opération est déjà en cours.", "Patience", MessageBoxButton.OK, MessageBoxImage.Information); return; }
if (IsBusy) { MessageBox.Show(Strings.MsgBusy, Strings.MsgBoxPatience, MessageBoxButton.OK, MessageBoxImage.Information); return; }
IsBusy = true;
_activeRow = row;
@@ -555,8 +556,8 @@ public sealed partial class MainViewModel : ObservableObject
row.ProgressDetail = null;
row.ProgressPercent = 0;
MessageBox.Show(
$"Le téléchargement ou l'installation a échoué :\n\n{ex.Message}",
"Erreur", MessageBoxButton.OK, MessageBoxImage.Error);
Strings.MsgInstallFailed(ex.Message),
Strings.MsgBoxError, MessageBoxButton.OK, MessageBoxImage.Error);
StatusMessage = $"Erreur : {ex.Message}";
_toastService.ShowError($"Échec v{row.Version}", ex.Message);
}
@@ -575,13 +576,13 @@ public sealed partial class MainViewModel : ObservableObject
var sizeStr = FormatSize(row.SizeBytes);
var confirm = MessageBox.Show(
$"Supprimer la version v{row.Version} ?\n\nDossier : {row.FolderPath}\nLibérera {sizeStr}.\n\nCette action est irréversible.",
"Confirmer la suppression",
Strings.MsgUninstallConfirm(row.Version, row.FolderPath, sizeStr),
Strings.MsgBoxConfirm,
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (confirm != MessageBoxResult.Yes) return;
if (IsBusy) { MessageBox.Show("Une autre opération est déjà en cours.", "Patience", MessageBoxButton.OK, MessageBoxImage.Information); return; }
if (IsBusy) { MessageBox.Show(Strings.MsgBusy, Strings.MsgBoxPatience, MessageBoxButton.OK, MessageBoxImage.Information); return; }
IsBusy = true;
row.State = VersionRowState.Uninstalling;
@@ -596,7 +597,7 @@ public sealed partial class MainViewModel : ObservableObject
{
_logger.LogError(ex, "Uninstall failed for {Version}", row.Version);
row.State = VersionRowState.InstalledIdle;
MessageBox.Show($"Suppression échouée : {ex.Message}", "Erreur",
MessageBox.Show(Strings.MsgUninstallFailed(ex.Message), Strings.MsgBoxError,
MessageBoxButton.OK, MessageBoxImage.Error);
StatusMessage = $"Erreur : {ex.Message}";
}
@@ -611,8 +612,8 @@ public sealed partial class MainViewModel : ObservableObject
var url = row.Remote?.ReleaseNotesUrl;
if (string.IsNullOrEmpty(url))
{
MessageBox.Show("Aucune release note disponible pour cette version.",
"Release notes", MessageBoxButton.OK, MessageBoxImage.Information);
MessageBox.Show(Strings.MsgNoReleaseNotes,
Strings.MsgBoxReleaseNotes, MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
string notes;
@@ -620,8 +621,8 @@ public sealed partial class MainViewModel : ObservableObject
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to fetch release notes");
MessageBox.Show($"Impossible de récupérer les release notes :\n{ex.Message}",
"Erreur", MessageBoxButton.OK, MessageBoxImage.Warning);
MessageBox.Show(Strings.MsgReleaseNotesFetchFailed(ex.Message),
Strings.MsgBoxError, MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}

View File

@@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging;
using PSLauncher.Core.Configuration;
using PSLauncher.Core.Downloads;
using PSLauncher.Core.Licensing;
using PSLauncher.Core.Localization;
using PSLauncher.Models;
namespace PSLauncher.App.ViewModels;
@@ -185,8 +186,8 @@ public sealed partial class SettingsViewModel : ObservableObject
private void ClearCache()
{
var confirm = MessageBox.Show(
"Vider le cache de téléchargements ? Les téléchargements en cours/pause seront perdus.",
"Confirmer",
Strings.MsgClearCacheConfirm,
Strings.MsgBoxConfirm,
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (confirm != MessageBoxResult.Yes) return;
@@ -201,7 +202,7 @@ public sealed partial class SettingsViewModel : ObservableObject
catch (Exception ex)
{
_logger.LogError(ex, "ClearCache failed");
MessageBox.Show("Échec : " + ex.Message, "Erreur", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show(ex.Message, Strings.MsgBoxError, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
@@ -232,8 +233,8 @@ public sealed partial class SettingsViewModel : ObservableObject
// la nouvelle langue. Plutôt que de demander à l'utilisateur de fermer/rouvrir,
// on spawne un cmd qui attend la fermeture puis relance.
var ok = MessageBox.Show(
"Le launcher va redémarrer pour appliquer la nouvelle langue.",
"Changement de langue",
Strings.MsgLanguageRestart,
Strings.MsgBoxLanguageChange,
MessageBoxButton.OKCancel, MessageBoxImage.Information, MessageBoxResult.OK);
if (ok == MessageBoxResult.OK)
{
@@ -263,8 +264,8 @@ public sealed partial class SettingsViewModel : ObservableObject
private void DeactivateLicense()
{
var confirm = MessageBox.Show(
"Désactiver la license sur cette machine ?\nTu pourras la réactiver avec ta clé.",
"Confirmer",
Strings.MsgDeactivateLicenseConfirm,
Strings.MsgBoxConfirm,
MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
if (confirm != MessageBoxResult.Yes) return;
_licenseService.Clear();