i18n: full pass + culture-aware dates/sizes + Software Update License wording
- 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) <noreply@anthropic.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<Window x:Class="PSLauncher.App.Views.LauncherUpdateDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Mise à jour du launcher"
|
||||
xmlns:loc="clr-namespace:PSLauncher.Core.Localization;assembly=PSLauncher.Core"
|
||||
Title="{x:Static loc:Strings.LauncherUpdateTitle}"
|
||||
Icon="pack://application:,,,/Resources/favicon.ico"
|
||||
Width="500" Height="320"
|
||||
ResizeMode="NoResize"
|
||||
@@ -16,7 +17,7 @@
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="Mise à jour du launcher disponible"
|
||||
Text="{x:Static loc:Strings.LauncherUpdateAvailable}"
|
||||
FontSize="20" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource Brush.Text.Primary}" />
|
||||
|
||||
@@ -33,7 +34,7 @@
|
||||
<Border Grid.Row="2" Background="{StaticResource Brush.Bg.Card}"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
|
||||
CornerRadius="6" Padding="16" Margin="0,16,0,0">
|
||||
<TextBlock Text="Le launcher va se mettre à jour : il téléchargera le nouveau binaire, se fermera, sera remplacé, puis se relancera automatiquement. Cela prend quelques secondes."
|
||||
<TextBlock Text="{x:Static loc:Strings.LauncherUpdateBody}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
@@ -41,11 +42,11 @@
|
||||
<StackPanel Grid.Row="3" Orientation="Horizontal"
|
||||
HorizontalAlignment="Right" Margin="0,18,0,0">
|
||||
<Button Style="{StaticResource SecondaryButton}"
|
||||
Content="Plus tard" IsCancel="True"
|
||||
Content="{x:Static loc:Strings.ActionLater}" IsCancel="True"
|
||||
Margin="0,0,12,0"
|
||||
Click="OnLater" />
|
||||
<Button Style="{StaticResource AccentButton}"
|
||||
Content="⬇ Mettre à jour"
|
||||
Content="{x:Static loc:Strings.LauncherUpdateNow}"
|
||||
Padding="32,8"
|
||||
IsDefault="True"
|
||||
Click="OnUpdate" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Windows;
|
||||
using PSLauncher.Core.Localization;
|
||||
using PSLauncher.Models;
|
||||
|
||||
namespace PSLauncher.App.Views;
|
||||
@@ -12,7 +13,7 @@ public partial class LauncherUpdateDialog : Window
|
||||
InitializeComponent();
|
||||
VersionText.Text = $"v{currentVersion} → v{info.Version}";
|
||||
SizeText.Text = info.Download.SizeBytes > 0
|
||||
? $"Taille : {FormatSize(info.Download.SizeBytes)}"
|
||||
? Strings.SizeLabel(Strings.FormatSize(info.Download.SizeBytes))
|
||||
: "";
|
||||
}
|
||||
|
||||
@@ -29,13 +30,4 @@ public partial class LauncherUpdateDialog : Window
|
||||
DialogResult = false;
|
||||
Close();
|
||||
}
|
||||
|
||||
private static string FormatSize(long bytes)
|
||||
{
|
||||
if (bytes <= 0) return "—";
|
||||
string[] units = { "o", "Ko", "Mo", "Go" };
|
||||
double v = bytes; int u = 0;
|
||||
while (v >= 1024 && u < units.Length - 1) { v /= 1024; u++; }
|
||||
return $"{v:0.#} {units[u]}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<Window x:Class="PSLauncher.App.Views.LicenseDetailsDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:loc="clr-namespace:PSLauncher.Core.Localization;assembly=PSLauncher.Core"
|
||||
Title="License"
|
||||
Icon="pack://application:,,,/Resources/favicon.ico"
|
||||
Width="500" Height="480"
|
||||
@@ -45,7 +46,7 @@
|
||||
<ColumnDefinition Width="160" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="Client"
|
||||
<TextBlock Grid.Column="0" Text="{x:Static loc:Strings.LicenseDetailsClient}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}" FontSize="12" />
|
||||
<TextBlock Grid.Column="1" x:Name="OwnerText"
|
||||
FontWeight="SemiBold"
|
||||
@@ -56,7 +57,7 @@
|
||||
<ColumnDefinition Width="160" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="Validité téléchargements"
|
||||
<TextBlock Grid.Column="0" Text="{x:Static loc:Strings.LicenseDetailsValidity}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}" FontSize="12" />
|
||||
<TextBlock Grid.Column="1" x:Name="UntilText"
|
||||
FontWeight="SemiBold"
|
||||
@@ -67,7 +68,7 @@
|
||||
<ColumnDefinition Width="160" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="Activée le"
|
||||
<TextBlock Grid.Column="0" Text="{x:Static loc:Strings.LicenseDetailsActivatedOn}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}" FontSize="12" />
|
||||
<TextBlock Grid.Column="1" x:Name="IssuedText"
|
||||
Foreground="{StaticResource Brush.Text.Primary}" />
|
||||
@@ -77,7 +78,7 @@
|
||||
<ColumnDefinition Width="160" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="ID machine"
|
||||
<TextBlock Grid.Column="0" Text="{x:Static loc:Strings.LicenseDetailsMachineId}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}" FontSize="12"
|
||||
VerticalAlignment="Center" />
|
||||
<Grid Grid.Column="1">
|
||||
@@ -91,7 +92,7 @@
|
||||
TextTrimming="CharacterEllipsis" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1" Style="{StaticResource SecondaryButton}"
|
||||
Content="📋"
|
||||
ToolTip="Copier"
|
||||
ToolTip="{x:Static loc:Strings.CopyTooltip}"
|
||||
Click="OnCopyMachineId" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -101,11 +102,11 @@
|
||||
<!-- Footer actions -->
|
||||
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,18,0,0">
|
||||
<Button Style="{StaticResource SecondaryButton}"
|
||||
Content="🗑 Désactiver la license"
|
||||
Content="{x:Static loc:Strings.LicenseDetailsDeactivate}"
|
||||
Click="OnDeactivate"
|
||||
Margin="0,0,12,0" />
|
||||
<Button Style="{StaticResource AccentButton}"
|
||||
Content="Fermer"
|
||||
Content="{x:Static loc:Strings.ActionClose}"
|
||||
IsCancel="True" IsDefault="True"
|
||||
Padding="32,8"
|
||||
Click="OnClose" />
|
||||
|
||||
@@ -29,11 +29,11 @@ public partial class LicenseDetailsDialog : Window
|
||||
|
||||
OwnerText.Text = license.OwnerName ?? "—";
|
||||
UntilText.Text = license.DownloadEntitlementUntil is { } until
|
||||
? $"jusqu'au {until.ToLocalTime():dddd dd MMMM yyyy}"
|
||||
? Strings.FormatLongDate(until)
|
||||
: "—";
|
||||
IssuedText.Text = license.IssuedAt is { } issued
|
||||
? issued.ToLocalTime().ToString("dd/MM/yyyy")
|
||||
: (license.ServerTime?.ToLocalTime().ToString("dd/MM/yyyy") ?? "—");
|
||||
? Strings.FormatDate(issued)
|
||||
: Strings.FormatDate(license.ServerTime);
|
||||
MachineIdText.Text = licenseService.GetMachineId();
|
||||
}
|
||||
|
||||
@@ -43,19 +43,19 @@ public partial class LicenseDetailsDialog : Window
|
||||
if (l.Status == "valid")
|
||||
{
|
||||
if (until is { } u && (u - DateTime.UtcNow).TotalDays < 30)
|
||||
return ("⏰", "License valide", $"Expire bientôt — le {u.ToLocalTime():dd/MM/yyyy}",
|
||||
return ("⏰", Strings.LicenseDetailsValidTitle, Strings.LicenseDetailsExpiringSoon(Strings.FormatDate(u)),
|
||||
Color.FromRgb(0xF5, 0x9E, 0x0B), Color.FromRgb(0x3A, 0x2A, 0x0E));
|
||||
return ("✓", "License valide", "Téléchargements de nouvelles versions autorisés",
|
||||
return ("✓", Strings.LicenseDetailsValidTitle, Strings.LicenseDetailsValidSubtitle,
|
||||
Color.FromRgb(0x16, 0xA3, 0x4A), Color.FromRgb(0x0E, 0x2A, 0x1B));
|
||||
}
|
||||
if (l.Status == "expired")
|
||||
return ("⚠", "License expirée",
|
||||
until is { } u ? $"Expirée le {u.ToLocalTime():dd/MM/yyyy}" : "Plus de téléchargements possibles",
|
||||
return ("⚠", Strings.LicenseDetailsExpiredTitle,
|
||||
until is { } u ? Strings.LicenseDetailsExpiredSubtitle(Strings.FormatDate(u)) : Strings.LicenseDetailsExpiredFallback,
|
||||
Color.FromRgb(0xEF, 0x44, 0x44), Color.FromRgb(0x2A, 0x14, 0x14));
|
||||
if (l.Status == "revoked")
|
||||
return ("🚫", "License révoquée", "Contacte ASTERION pour plus d'informations",
|
||||
return ("🚫", Strings.LicenseDetailsRevokedTitle, Strings.LicenseDetailsRevokedSubtitle,
|
||||
Color.FromRgb(0xEF, 0x44, 0x44), Color.FromRgb(0x2A, 0x14, 0x14));
|
||||
return ("❓", "License inconnue", l.Message ?? l.Status,
|
||||
return ("❓", Strings.LicenseDetailsUnknownTitle, l.Message ?? l.Status,
|
||||
Color.FromRgb(0xEF, 0x44, 0x44), Color.FromRgb(0x2A, 0x14, 0x14));
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,14 @@
|
||||
Content="{Binding InstallButtonLabel}" Padding="22,8" FontSize="13"
|
||||
Command="{Binding InstallCommand}"
|
||||
Visibility="{Binding IsRemoteOnly, Converter={StaticResource BoolToVisibility}}" />
|
||||
<!-- Bouton rouge « Annuler » : visible uniquement quand on a un partial.
|
||||
Permet d'abandonner le partial et repartir de zéro (avec confirmation). -->
|
||||
<Button Style="{StaticResource DangerButton}"
|
||||
Content="{x:Static loc:Strings.ActionCancel}"
|
||||
Padding="14,8" FontSize="13" Margin="6,0,0,0"
|
||||
Command="{Binding RestartFromZeroCommand}"
|
||||
ToolTip="{x:Static loc:Strings.MenuRestartFromZero}"
|
||||
Visibility="{Binding ShowRestartFromZero, Converter={StaticResource BoolToVisibility}}" />
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Visibility="{Binding IsBusy, Converter={StaticResource BoolToVisibility}}">
|
||||
<ProgressBar Width="140" Height="6"
|
||||
@@ -149,6 +157,9 @@
|
||||
<MenuItem Header="{x:Static loc:Strings.MenuOpenFolder}"
|
||||
Command="{Binding PlacementTarget.Tag.OpenFolderCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
|
||||
Visibility="{Binding PlacementTarget.Tag.IsInstalled, RelativeSource={RelativeSource AncestorType=ContextMenu}, Converter={StaticResource BoolToVisibility}}" />
|
||||
<MenuItem Header="{x:Static loc:Strings.MenuRestartFromZero}"
|
||||
Command="{Binding PlacementTarget.Tag.RestartFromZeroCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
|
||||
Visibility="{Binding PlacementTarget.Tag.HasResumableDownload, RelativeSource={RelativeSource AncestorType=ContextMenu}, Converter={StaticResource BoolToVisibility}}" />
|
||||
<Separator Visibility="{Binding PlacementTarget.Tag.IsInstalled, RelativeSource={RelativeSource AncestorType=ContextMenu}, Converter={StaticResource BoolToVisibility}}" />
|
||||
<MenuItem Header="{x:Static loc:Strings.MenuUninstall}"
|
||||
Command="{Binding PlacementTarget.Tag.UninstallCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
|
||||
@@ -289,15 +300,15 @@
|
||||
Command="{Binding OpenSettingsCommand}"
|
||||
Margin="0,0,16,0" />
|
||||
<Button Style="{StaticResource WindowControlButton}"
|
||||
Content="—" ToolTip="Réduire"
|
||||
Content="—" ToolTip="{x:Static loc:Strings.Minimize}"
|
||||
shell:WindowChrome.IsHitTestVisibleInChrome="True"
|
||||
Click="OnMinimizeClick" />
|
||||
<Button Style="{StaticResource WindowControlButton}"
|
||||
Content="☐" ToolTip="Agrandir / Restaurer"
|
||||
Content="☐" ToolTip="{x:Static loc:Strings.Maximize}"
|
||||
shell:WindowChrome.IsHitTestVisibleInChrome="True"
|
||||
Click="OnMaxRestoreClick" />
|
||||
<Button Style="{StaticResource WindowCloseButton}"
|
||||
Content="✕" ToolTip="Fermer"
|
||||
Content="✕" ToolTip="{x:Static loc:Strings.CloseTooltip}"
|
||||
shell:WindowChrome.IsHitTestVisibleInChrome="True"
|
||||
Click="OnCloseClick" />
|
||||
</StackPanel>
|
||||
@@ -404,7 +415,7 @@
|
||||
FontSize="13"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,8,0,0">
|
||||
<Run Text="Sortie le " />
|
||||
<Run Text="{x:Static loc:Strings.ReleasedOn}" />
|
||||
<Run Text="{Binding FeaturedVersion.PrimaryDate, Mode=OneWay}" />
|
||||
<Run Text=" • " />
|
||||
<Run Text="{Binding FeaturedVersion.SizeDisplay, Mode=OneWay}" />
|
||||
@@ -419,13 +430,23 @@
|
||||
Command="{Binding FeaturedVersion.LaunchCommand}"
|
||||
Visibility="{Binding FeaturedVersion.IsInstalled, Converter={StaticResource BoolToVisibility}}" />
|
||||
|
||||
<Button Grid.Row="0" Grid.RowSpan="3" Grid.Column="1"
|
||||
Style="{StaticResource AccentButton}"
|
||||
Content="{Binding FeaturedVersion.InstallButtonLabel}"
|
||||
FontSize="20" Padding="48,16"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding FeaturedVersion.InstallCommand}"
|
||||
Visibility="{Binding FeaturedVersion.IsRemoteOnly, Converter={StaticResource BoolToVisibility}}" />
|
||||
<StackPanel Grid.Row="0" Grid.RowSpan="3" Grid.Column="1"
|
||||
Orientation="Vertical" VerticalAlignment="Center"
|
||||
Visibility="{Binding FeaturedVersion.IsRemoteOnly, Converter={StaticResource BoolToVisibility}}">
|
||||
<Button Style="{StaticResource AccentButton}"
|
||||
Content="{Binding FeaturedVersion.InstallButtonLabel}"
|
||||
FontSize="20" Padding="48,16"
|
||||
Command="{Binding FeaturedVersion.InstallCommand}" />
|
||||
<!-- Bouton rouge « Annuler » : visible uniquement quand un partial existe.
|
||||
Permet d'abandonner et repartir de zéro (confirmation requise). -->
|
||||
<Button Style="{StaticResource DangerButton}"
|
||||
Content="{x:Static loc:Strings.ActionCancel}"
|
||||
FontSize="13" Padding="20,8" Margin="0,8,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
Command="{Binding FeaturedVersion.RestartFromZeroCommand}"
|
||||
ToolTip="{x:Static loc:Strings.MenuRestartFromZero}"
|
||||
Visibility="{Binding FeaturedVersion.ShowRestartFromZero, Converter={StaticResource BoolToVisibility}}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="0" Grid.RowSpan="3" Grid.Column="1"
|
||||
Orientation="Vertical" VerticalAlignment="Center" Width="220"
|
||||
@@ -460,6 +481,9 @@
|
||||
<MenuItem Header="{x:Static loc:Strings.MenuOpenFolder}"
|
||||
Command="{Binding PlacementTarget.Tag.OpenFolderCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
|
||||
Visibility="{Binding PlacementTarget.Tag.IsInstalled, RelativeSource={RelativeSource AncestorType=ContextMenu}, Converter={StaticResource BoolToVisibility}}" />
|
||||
<MenuItem Header="{x:Static loc:Strings.MenuRestartFromZero}"
|
||||
Command="{Binding PlacementTarget.Tag.RestartFromZeroCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
|
||||
Visibility="{Binding PlacementTarget.Tag.HasResumableDownload, RelativeSource={RelativeSource AncestorType=ContextMenu}, Converter={StaticResource BoolToVisibility}}" />
|
||||
<Separator Visibility="{Binding PlacementTarget.Tag.IsInstalled, RelativeSource={RelativeSource AncestorType=ContextMenu}, Converter={StaticResource BoolToVisibility}}" />
|
||||
<MenuItem Header="{x:Static loc:Strings.MenuUninstall}"
|
||||
Command="{Binding PlacementTarget.Tag.UninstallCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
|
||||
@@ -519,7 +543,7 @@
|
||||
Background="#A0000000"
|
||||
CornerRadius="10"
|
||||
Padding="10,4">
|
||||
<TextBlock Text="© 2026 ASTERION VR — Tous droits réservés"
|
||||
<TextBlock Text="{x:Static loc:Strings.Copyright}"
|
||||
FontSize="11"
|
||||
Foreground="White" />
|
||||
</Border>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using PSLauncher.Core.Licensing;
|
||||
using PSLauncher.Core.Localization;
|
||||
|
||||
namespace PSLauncher.App.Views;
|
||||
|
||||
@@ -24,12 +25,12 @@ public partial class OnboardingDialog : Window
|
||||
var key = KeyBox.Text?.Trim().ToUpperInvariant() ?? string.Empty;
|
||||
if (string.IsNullOrEmpty(key) || key.Contains("XXXX"))
|
||||
{
|
||||
ShowStatus("Saisis une clé valide au format PRSRV-XXXX-XXXX-XXXX-XXXX.", isError: true);
|
||||
ShowStatus(Strings.OnboardingInvalidKey, isError: true);
|
||||
return;
|
||||
}
|
||||
|
||||
ActivateButton.IsEnabled = false;
|
||||
ShowStatus("Validation en cours…", isError: false);
|
||||
ShowStatus(Strings.OnboardingValidating, isError: false);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -38,7 +39,8 @@ public partial class OnboardingDialog : Window
|
||||
{
|
||||
case "valid":
|
||||
_licenseService.SaveCached(key, resp);
|
||||
ShowStatus($"License activée ({resp.OwnerName}). Téléchargements autorisés jusqu'au {resp.DownloadEntitlementUntil:dd/MM/yyyy}.", isError: false);
|
||||
ShowStatus(Strings.OnboardingActivated(resp.OwnerName ?? "—",
|
||||
Strings.FormatDate(resp.DownloadEntitlementUntil)), isError: false);
|
||||
LicenseActivated = true;
|
||||
DialogResult = true;
|
||||
Close();
|
||||
@@ -46,27 +48,27 @@ public partial class OnboardingDialog : Window
|
||||
|
||||
case "expired":
|
||||
_licenseService.SaveCached(key, resp); // on cache quand même pour permettre de lancer les versions installées
|
||||
ShowStatus($"License expirée le {resp.DownloadEntitlementUntil:dd/MM/yyyy}. Tu peux toujours utiliser les versions déjà installées, mais plus en télécharger de nouvelles.", isError: true);
|
||||
ShowStatus(Strings.OnboardingExpired(Strings.FormatDate(resp.DownloadEntitlementUntil)), isError: true);
|
||||
LicenseActivated = true;
|
||||
DialogResult = true;
|
||||
Close();
|
||||
return;
|
||||
|
||||
case "revoked":
|
||||
ShowStatus("Cette license a été révoquée. Contacte ASTERION.", isError: true);
|
||||
ShowStatus(Strings.OnboardingRevoked, isError: true);
|
||||
break;
|
||||
case "machine_limit_exceeded":
|
||||
ShowStatus(resp.Message ?? "Cette license a atteint son nombre maximum de machines.", isError: true);
|
||||
ShowStatus(resp.Message ?? Strings.OnboardingMachineLimit, isError: true);
|
||||
break;
|
||||
case "invalid":
|
||||
default:
|
||||
ShowStatus(resp.Message ?? "Clé de license inconnue.", isError: true);
|
||||
ShowStatus(resp.Message ?? Strings.OnboardingInvalid, isError: true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowStatus($"Erreur de communication avec le serveur :\n{ex.Message}", isError: true);
|
||||
ShowStatus(Strings.OnboardingServerError(ex.Message), isError: true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<Window x:Class="PSLauncher.App.Views.ReleaseNotesViewerDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Notes de version"
|
||||
xmlns:loc="clr-namespace:PSLauncher.Core.Localization;assembly=PSLauncher.Core"
|
||||
Title="{x:Static loc:Strings.MsgBoxReleaseNotes}"
|
||||
Icon="pack://application:,,,/Resources/favicon.ico"
|
||||
Width="640" Height="540"
|
||||
MinWidth="480" MinHeight="400"
|
||||
@@ -33,7 +34,7 @@
|
||||
|
||||
<Button Grid.Row="2"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Content="Fermer"
|
||||
Content="{x:Static loc:Strings.ActionClose}"
|
||||
IsCancel="True"
|
||||
IsDefault="True"
|
||||
HorizontalAlignment="Right"
|
||||
|
||||
@@ -30,30 +30,9 @@
|
||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" Padding="32,0,32,16">
|
||||
<StackPanel>
|
||||
|
||||
<!-- Langue de l'interface -->
|
||||
<Border Background="{StaticResource Brush.Bg.Card}"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
|
||||
CornerRadius="6" Padding="20" Margin="0,0,0,16">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsLanguage}"
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,0,0,8" />
|
||||
<ComboBox ItemsSource="{Binding AvailableLanguages}"
|
||||
DisplayMemberPath="Name"
|
||||
SelectedValuePath="Code"
|
||||
SelectedValue="{Binding Language, Mode=TwoWay}"
|
||||
Background="#1A1A20"
|
||||
Foreground="{StaticResource Brush.Text.Primary}"
|
||||
BorderBrush="{StaticResource Brush.Border}"
|
||||
BorderThickness="1" Padding="8" />
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsLanguageHint}"
|
||||
FontSize="11" Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
FontStyle="Italic" Margin="0,6,0,0" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- License (en tête, bordure colorée selon état) -->
|
||||
<!-- License de mise à jour (en tête : c'est l'info la plus importante,
|
||||
elle conditionne ce que l'utilisateur peut télécharger.
|
||||
Bordure colorée selon l'état : vert/jaune/rouge). -->
|
||||
<Border BorderThickness="2"
|
||||
CornerRadius="6" Padding="20" Margin="0,0,0,16">
|
||||
<Border.Style>
|
||||
@@ -124,7 +103,7 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="Identifiant machine (anonyme)"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsMachineId}"
|
||||
FontSize="11"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}" />
|
||||
<TextBlock Text="{Binding MachineId}"
|
||||
@@ -134,12 +113,35 @@
|
||||
</StackPanel>
|
||||
<Button Grid.Column="1"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Content="📋 Copier"
|
||||
Content="{x:Static loc:Strings.SettingsCopyMachineId}"
|
||||
Command="{Binding CopyMachineIdCommand}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Langue de l'interface -->
|
||||
<Border Background="{StaticResource Brush.Bg.Card}"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
|
||||
CornerRadius="6" Padding="20" Margin="0,0,0,16">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsLanguage}"
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,0,0,8" />
|
||||
<ComboBox ItemsSource="{Binding AvailableLanguages}"
|
||||
DisplayMemberPath="Name"
|
||||
SelectedValuePath="Code"
|
||||
SelectedValue="{Binding Language, Mode=TwoWay}"
|
||||
Background="#1A1A20"
|
||||
Foreground="{StaticResource Brush.Text.Primary}"
|
||||
BorderBrush="{StaticResource Brush.Border}"
|
||||
BorderThickness="1" Padding="8" />
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsLanguageHint}"
|
||||
FontSize="11" Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
FontStyle="Italic" Margin="0,6,0,0" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Serveur -->
|
||||
<Border Background="{StaticResource Brush.Bg.Card}"
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
|
||||
@@ -149,7 +151,7 @@
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,0,0,8" />
|
||||
<TextBlock Text="URL de l'API"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsApiUrl}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
FontSize="12" Margin="0,0,0,4" />
|
||||
<Grid>
|
||||
@@ -184,7 +186,7 @@
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,0,0,8" />
|
||||
<TextBlock Text="Dossier où sont installées les versions"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsInstallRoot}"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
FontSize="12" Margin="0,0,0,4" />
|
||||
<Grid>
|
||||
@@ -229,7 +231,8 @@
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock FontSize="12"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}">
|
||||
<Run Text="Taille actuelle : " />
|
||||
<Run Text="{x:Static loc:Strings.SettingsCacheSize}" />
|
||||
<Run Text=" " />
|
||||
<Run Text="{Binding CacheSizeDisplay}" FontWeight="SemiBold" />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
@@ -256,10 +259,11 @@
|
||||
Margin="0,0,0,8" />
|
||||
<TextBlock FontSize="13"
|
||||
Foreground="{StaticResource Brush.Text.Primary}">
|
||||
<Run Text="Version : " />
|
||||
<Run Text="{x:Static loc:Strings.SettingsLauncherVersion}" />
|
||||
<Run Text=" " />
|
||||
<Run Text="{Binding LauncherVersion, Mode=OneWay}" FontWeight="SemiBold" />
|
||||
</TextBlock>
|
||||
<TextBlock Text="© 2026 ASTERION VR — Tous droits réservés"
|
||||
<TextBlock Text="{x:Static loc:Strings.Copyright}"
|
||||
FontSize="12"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,4,0,0" />
|
||||
@@ -273,14 +277,14 @@
|
||||
FontFamily="Consolas" FontSize="11"
|
||||
Foreground="{StaticResource Brush.Text.Primary}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Text="Logs rotation quotidienne, 10 jours conservés"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsCacheRotation}"
|
||||
FontSize="12"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,2,0,0" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="1" Margin="8,0,0,0"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Content="📁 Ouvrir"
|
||||
Content="{x:Static loc:Strings.OpenButton}"
|
||||
Command="{Binding OpenLogsFolderCommand}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<Window x:Class="PSLauncher.App.Views.UpdateAvailableDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Mise à jour disponible"
|
||||
xmlns:loc="clr-namespace:PSLauncher.Core.Localization;assembly=PSLauncher.Core"
|
||||
Title="{x:Static loc:Strings.UpdateAvailableTitle}"
|
||||
Icon="pack://application:,,,/Resources/favicon.ico"
|
||||
Width="640" Height="540"
|
||||
MinWidth="480" MinHeight="400"
|
||||
@@ -38,12 +39,12 @@
|
||||
|
||||
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,18,0,0">
|
||||
<Button Style="{StaticResource SecondaryButton}"
|
||||
Content="Plus tard"
|
||||
Content="{x:Static loc:Strings.ActionLater}"
|
||||
IsCancel="True"
|
||||
Margin="0,0,12,0"
|
||||
Click="OnLater" />
|
||||
<Button Style="{StaticResource PrimaryButton}"
|
||||
Content="⬇ Télécharger"
|
||||
Content="{x:Static loc:Strings.UpdateDownload}"
|
||||
Padding="32,10"
|
||||
Click="OnDownload" />
|
||||
</StackPanel>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Windows;
|
||||
using PSLauncher.Core.Localization;
|
||||
using PSLauncher.Models;
|
||||
|
||||
namespace PSLauncher.App.Views;
|
||||
@@ -9,10 +10,14 @@ public partial class UpdateAvailableDialog : Window
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
var sizeText = version.Download.SizeBytes > 0
|
||||
? Strings.FormatSize(version.Download.SizeBytes)
|
||||
: Strings.SizeUnknown;
|
||||
|
||||
DataContext = new
|
||||
{
|
||||
Title = $"PROSERVE v{version.Version} disponible",
|
||||
Subtitle = $"Date de release : {version.ReleasedAt.ToLocalTime():dd MMMM yyyy} • {FormatSize(version.Download.SizeBytes)}",
|
||||
Title = Strings.UpdateAvailableHeading(version.Version),
|
||||
Subtitle = Strings.UpdateAvailableSubtitle(Strings.FormatLongDate(version.ReleasedAt), sizeText),
|
||||
ReleaseNotesDocument = MarkdownTheming.BuildThemedDocument(releaseNotesMarkdown)
|
||||
};
|
||||
}
|
||||
@@ -32,14 +37,4 @@ public partial class UpdateAvailableDialog : Window
|
||||
DialogResult = false;
|
||||
Close();
|
||||
}
|
||||
|
||||
private static string FormatSize(long bytes)
|
||||
{
|
||||
if (bytes <= 0) return "taille inconnue";
|
||||
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]}";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user