i18n: 5 languages (FR/EN/ZH/TH/AR), auto-detect from Windows + Settings picker
Localization infrastructure
---------------------------
PSLauncher.Core/Localization/Strings.cs is a static class exposing each
UI string as a static property. T(fr,en,zh,th,ar) helper switches by the
current language code. ~50 keys cover the visible top-level strings:
top bar, body, status badges, action buttons, "..." menu items, license
badge texts, Settings section headers, Onboarding dialog, Update dialog.
Bindings via x:Static in XAML:
xmlns:loc="clr-namespace:PSLauncher.Core.Localization;assembly=PSLauncher.Core"
Content="{x:Static loc:Strings.ActionLaunch}"
Auto-detection
--------------
LocalConfig gains a Language field defaulting to "auto". Strings.Init()
called at App.xaml.cs OnStartup before any UI:
- "auto" (or unknown code) → reads CultureInfo.CurrentUICulture
.TwoLetterISOLanguageName, picks the matching supported language,
falls back to English.
- explicit code → forced.
The chosen culture is then propagated to CurrentCulture / CurrentUICulture
so date/number formats follow.
Settings picker
---------------
SettingsDialog gets a top section "LANGUE" with a ComboBox bound to
SettingsViewModel.AvailableLanguages (Auto / FR / EN / ZH / TH / AR).
On Save, if the language code changed, prompt the user to confirm
restart, spawn `cmd /c timeout 1 & start PSLauncher.exe` and Shutdown
the current process — the new instance picks up the language at
bootstrap.
RTL for Arabic
--------------
Strings.IsRightToLeft is true when lang=="ar". App.xaml.cs sets
window.FlowDirection = RightToLeft on the MainWindow — WPF mirrors the
layout (icons on right, text aligned right).
Translations
------------
Done as best-effort by the assistant. The product wordmark "PROSERVE"
stays untranslated (brand). Logs and debug-level messages remain in
French in code — only user-visible UI is localized. Operator can
refine translations by editing Strings.cs and rebuilding.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:PSLauncher.App.ViewModels"
|
||||
Title="Paramètres"
|
||||
xmlns:loc="clr-namespace:PSLauncher.Core.Localization;assembly=PSLauncher.Core"
|
||||
Title="{x:Static loc:Strings.SettingsTitle}"
|
||||
Icon="pack://application:,,,/Resources/favicon.ico"
|
||||
Width="640" Height="720"
|
||||
MinWidth="540" MinHeight="500"
|
||||
@@ -22,13 +23,36 @@
|
||||
|
||||
<!-- Header -->
|
||||
<Border Grid.Row="0" Padding="32,24,32,16">
|
||||
<TextBlock Text="Paramètres" FontSize="22" FontWeight="SemiBold"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsTitle}" FontSize="22" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource Brush.Text.Primary}" />
|
||||
</Border>
|
||||
|
||||
<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) -->
|
||||
<Border BorderThickness="2"
|
||||
CornerRadius="6" Padding="20" Margin="0,0,0,16">
|
||||
@@ -83,7 +107,7 @@
|
||||
|
||||
<!-- Header text -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="1"
|
||||
Text="LICENSE"
|
||||
Text="{x:Static loc:Strings.SettingsLicense}"
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1"
|
||||
@@ -121,7 +145,7 @@
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
|
||||
CornerRadius="6" Padding="20" Margin="0,0,0,16">
|
||||
<StackPanel>
|
||||
<TextBlock Text="SERVEUR"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsServer}"
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,0,0,8" />
|
||||
@@ -141,7 +165,7 @@
|
||||
BorderThickness="1" Padding="8" />
|
||||
<Button Grid.Column="1" Margin="8,0,0,0"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Content="Tester"
|
||||
Content="{x:Static loc:Strings.SettingsTest}"
|
||||
Command="{Binding TestConnectionCommand}"
|
||||
IsEnabled="{Binding IsTestingConnection, Converter={StaticResource InverseBoolToBool}}" />
|
||||
</Grid>
|
||||
@@ -156,7 +180,7 @@
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
|
||||
CornerRadius="6" Padding="20" Margin="0,0,0,16">
|
||||
<StackPanel>
|
||||
<TextBlock Text="INSTALLATION"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsInstallation}"
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,0,0,8" />
|
||||
@@ -177,7 +201,7 @@
|
||||
FontFamily="Consolas" />
|
||||
<Button Grid.Column="1" Margin="8,0,0,0"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Content="📁 Parcourir"
|
||||
Content="{x:Static loc:Strings.SettingsBrowse}"
|
||||
Command="{Binding BrowseInstallRootCommand}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
@@ -188,7 +212,7 @@
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
|
||||
CornerRadius="6" Padding="20" Margin="0,0,0,16">
|
||||
<StackPanel>
|
||||
<TextBlock Text="CACHE DE TÉLÉCHARGEMENTS"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsCache}"
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,0,0,8" />
|
||||
@@ -215,7 +239,7 @@
|
||||
Command="{Binding OpenCacheFolderCommand}" />
|
||||
<Button Grid.Column="2" Margin="8,0,0,0"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Content="🗑 Vider"
|
||||
Content="{x:Static loc:Strings.SettingsClearCache}"
|
||||
Command="{Binding ClearCacheCommand}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
@@ -226,7 +250,7 @@
|
||||
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
|
||||
CornerRadius="6" Padding="20" Margin="0,0,0,16">
|
||||
<StackPanel>
|
||||
<TextBlock Text="LOGS & APPLICATION"
|
||||
<TextBlock Text="{x:Static loc:Strings.SettingsLogs}"
|
||||
FontSize="11" FontWeight="Bold"
|
||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||
Margin="0,0,0,8" />
|
||||
@@ -271,12 +295,12 @@
|
||||
Padding="20,12">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Style="{StaticResource SecondaryButton}"
|
||||
Content="Annuler"
|
||||
Content="{x:Static loc:Strings.ActionCancel}"
|
||||
IsCancel="True"
|
||||
Margin="0,0,12,0"
|
||||
Click="OnCancel" />
|
||||
<Button Style="{StaticResource AccentButton}"
|
||||
Content="Enregistrer"
|
||||
Content="{x:Static loc:Strings.ActionSave}"
|
||||
Padding="32,8"
|
||||
IsDefault="True"
|
||||
Click="OnSave" />
|
||||
|
||||
Reference in New Issue
Block a user