Skip to content

Commit 9593cd8

Browse files
committed
feat(MainWindow): add localization options to UI
src/ClusterRelocationService/MainWindow.xaml: +added localization options group with language selection Class MainWindow: +added properties for available languages and selected language code; +initialize language options on startup feat(LocalizationManager): enhance language handling src/Localization/LocalizationManager.cs: +added methods for translating language names and retrieving display names feat(translations): add localization support for multiple languages src/ClusterRelocationService/Translations/*.json: +added language entries and localization options for various languages
1 parent 3007fc3 commit 9593cd8

17 files changed

Lines changed: 277 additions & 17 deletions

File tree

src/ClusterRelocationService/MainWindow.xaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,26 @@
390390
IsChecked="{Binding LogToFile}"/>
391391
</StackPanel>
392392
</fluent:RibbonGroupBox>
393+
<fluent:RibbonGroupBox Header="{loc:Loc Key=ribbon.group.localizationOptions}">
394+
<Grid Margin="0">
395+
<Grid.ColumnDefinitions>
396+
<ColumnDefinition Width="Auto"/>
397+
<ColumnDefinition Width="*"/>
398+
</Grid.ColumnDefinitions>
399+
<Label Content="{loc:Loc Key=config.localization.language}"
400+
Grid.Column="0"
401+
VerticalAlignment="Center"
402+
Margin="0,0,5,0"/>
403+
<ComboBox Grid.Column="1"
404+
Width="100"
405+
Margin="5"
406+
ItemsSource="{Binding AvailableLanguages}"
407+
DisplayMemberPath="DisplayName"
408+
SelectedValuePath="Code"
409+
SelectedValue="{Binding SelectedLanguageCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
410+
ToolTip="{loc:Loc Key=config.localization.language.tooltip}"/>
411+
</Grid>
412+
</fluent:RibbonGroupBox>
393413
<fluent:RibbonGroupBox Header="{loc:Loc Key=ribbon.group.otherOptions}">
394414
<StackPanel>
395415
<CheckBox Content="{loc:Loc Key=config.other.checkUpdates}"

src/ClusterRelocationService/MainWindow.xaml.cs

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Windows.Media.Imaging;
1717
using System.Windows.Threading;
1818
using System.Xml.Linq;
19+
using Localization;
1920
using SharedWindows;
2021
using Utilities.Logging;
2122
using X4DataLoader;
@@ -104,6 +105,7 @@ protected virtual void OnPropertyChanged(string propertyName)
104105
public class OtherConfig
105106
{
106107
private bool _checkForUpdatesOnStartUp = false;
108+
private string _languageCode = "en";
107109
public bool CheckForUpdatesOnStartUp
108110
{
109111
get => _checkForUpdatesOnStartUp;
@@ -117,6 +119,20 @@ public bool CheckForUpdatesOnStartUp
117119
}
118120
}
119121

122+
public string? LanguageCode
123+
{
124+
get => _languageCode;
125+
set
126+
{
127+
string newValue = string.IsNullOrWhiteSpace(value) ? _languageCode : value.Trim();
128+
if (!string.Equals(_languageCode, newValue, StringComparison.OrdinalIgnoreCase))
129+
{
130+
_languageCode = newValue;
131+
OnPropertyChanged(nameof(LanguageCode));
132+
}
133+
}
134+
}
135+
120136
public event PropertyChangedEventHandler? PropertyChanged;
121137

122138
protected virtual void OnPropertyChanged(string propertyName)
@@ -125,12 +141,17 @@ protected virtual void OnPropertyChanged(string propertyName)
125141
}
126142
}
127143

144+
public sealed record LanguageOption(string Code, string DisplayName);
145+
128146
/// <summary>
129147
/// Interaction logic for MainWindow.xaml
130148
/// </summary>
131149
public partial class MainWindow : Window, INotifyPropertyChanged
132150
{
133151
private readonly string _configFileName;
152+
private readonly ObservableCollection<LanguageOption> _availableLanguages = new();
153+
private string _selectedLanguageCode = LocalizationManager.Shared.CurrentLanguage;
154+
private string? _preferredLanguageFromConfig;
134155

135156
private bool _directMode = true;
136157
public bool DirectMode
@@ -186,6 +207,30 @@ public string X4GameFolder
186207
}
187208
}
188209

210+
public ObservableCollection<LanguageOption> AvailableLanguages => _availableLanguages;
211+
212+
public string SelectedLanguageCode
213+
{
214+
get => _selectedLanguageCode;
215+
set
216+
{
217+
string normalized = string.IsNullOrWhiteSpace(value) ? LocalizationManager.Shared.DefaultLanguage : value.Trim();
218+
219+
if (!_availableLanguages.Any(option => option.Code.Equals(normalized, StringComparison.OrdinalIgnoreCase)))
220+
{
221+
normalized = LocalizationManager.Shared.DefaultLanguage;
222+
}
223+
224+
if (!string.Equals(_selectedLanguageCode, normalized, StringComparison.OrdinalIgnoreCase))
225+
{
226+
_selectedLanguageCode = normalized;
227+
OnPropertyChanged(nameof(SelectedLanguageCode));
228+
LocalizationManager.Shared.TrySetLanguage(_selectedLanguageCode);
229+
SaveConfiguration();
230+
}
231+
}
232+
}
233+
189234
private bool _checkForUpdatesOnStartUp = false;
190235
public bool CheckForUpdatesOnStartUp
191236
{
@@ -794,6 +839,7 @@ public MainWindow()
794839
{
795840
_configFileName = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.json";
796841
LoadConfiguration();
842+
InitializeLanguageOptions(_preferredLanguageFromConfig);
797843
InitializeComponent();
798844
DataContext = this;
799845
X4DataStructure.AddRange(
@@ -898,6 +944,7 @@ private void LoadConfiguration()
898944
LogToFile = logging.LogToFile;
899945

900946
CheckForUpdatesOnStartUp = other.CheckForUpdatesOnStartUp;
947+
_preferredLanguageFromConfig = other.LanguageCode;
901948
}
902949
}
903950
else
@@ -926,7 +973,7 @@ private void SaveConfiguration()
926973
Map = new MapConfig { MapColorsOpacity = MapColorsOpacity },
927974
Relocation = new RelocationConfig { ExportClustersIsEnabled = ExportClustersIsEnabled, FullMessIsEnabled = FullMessIsEnabled },
928975
Logging = new LoggingConfig { LogLevel = LogLevel, LogToFile = LogToFile },
929-
Other = new OtherConfig { CheckForUpdatesOnStartUp = CheckForUpdatesOnStartUp },
976+
Other = new OtherConfig { CheckForUpdatesOnStartUp = CheckForUpdatesOnStartUp, LanguageCode = SelectedLanguageCode },
930977
};
931978
if (X4UniverseId != DataLoader.DefaultUniverseId)
932979
{
@@ -951,6 +998,39 @@ private void SaveConfiguration()
951998
File.WriteAllText(_configFileName, jsonString);
952999
}
9531000

1001+
private void InitializeLanguageOptions(string? preferredLanguageCode)
1002+
{
1003+
var manager = LocalizationManager.Shared;
1004+
_availableLanguages.Clear();
1005+
1006+
var orderedLanguages = manager.AvailableLanguages.OrderBy(code => code, StringComparer.OrdinalIgnoreCase);
1007+
foreach (string code in orderedLanguages)
1008+
{
1009+
string displayName = manager.GetLanguageDisplayName(code, code);
1010+
_availableLanguages.Add(new LanguageOption(code, displayName));
1011+
}
1012+
1013+
if (_availableLanguages.Count == 0)
1014+
{
1015+
_selectedLanguageCode = manager.DefaultLanguage;
1016+
OnPropertyChanged(nameof(SelectedLanguageCode));
1017+
return;
1018+
}
1019+
1020+
string target = preferredLanguageCode;
1021+
if (
1022+
string.IsNullOrWhiteSpace(target)
1023+
|| !_availableLanguages.Any(option => option.Code.Equals(target, StringComparison.OrdinalIgnoreCase))
1024+
)
1025+
{
1026+
target = manager.CurrentLanguage;
1027+
}
1028+
1029+
_selectedLanguageCode = target;
1030+
OnPropertyChanged(nameof(SelectedLanguageCode));
1031+
manager.TrySetLanguage(target);
1032+
}
1033+
9541034
private void X4DataNotLoadedCheckAndWarning()
9551035
{
9561036
// Validate the loaded X4DataFolder

src/ClusterRelocationService/Translations/bn.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"app": {
33
"title": "Cluster Relocation Service"
44
},
5+
"language": {
6+
"name": "\u0995\u09be\u0982\u09b2\u09be"
7+
},
58
"ribbon": {
69
"tab": {
710
"mod": "Mod",
@@ -19,7 +22,8 @@
1922
"relocationOptions": "Relocation Options",
2023
"loggingOptions": "Logging Options",
2124
"otherOptions": "Other Options",
22-
"helpActions": "Help Actions"
25+
"helpActions": "Help Actions",
26+
"localizationOptions": "Localization Options"
2327
},
2428
"mod": {
2529
"new": "New",
@@ -61,6 +65,10 @@
6165
},
6266
"other": {
6367
"checkUpdates": "Check for Updates on StartUp"
68+
},
69+
"localization": {
70+
"language": "Language:",
71+
"language.tooltip": "Select the interface language"
6472
}
6573
},
6674
"logging": {

src/ClusterRelocationService/Translations/cs.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"app": {
33
"title": "Cluster Relocation Service"
44
},
5+
"language": {
6+
"name": "\u010ce\u0161tina"
7+
},
58
"ribbon": {
69
"tab": {
710
"mod": "Mod",
@@ -19,7 +22,8 @@
1922
"relocationOptions": "Relocation Options",
2023
"loggingOptions": "Logging Options",
2124
"otherOptions": "Other Options",
22-
"helpActions": "Help Actions"
25+
"helpActions": "Help Actions",
26+
"localizationOptions": "Localization Options"
2327
},
2428
"mod": {
2529
"new": "New",
@@ -61,6 +65,10 @@
6165
},
6266
"other": {
6367
"checkUpdates": "Check for Updates on StartUp"
68+
},
69+
"localization": {
70+
"language": "Language:",
71+
"language.tooltip": "Select the interface language"
6472
}
6573
},
6674
"logging": {

src/ClusterRelocationService/Translations/de.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"app": {
33
"title": "Cluster Relocation Service"
44
},
5+
"language": {
6+
"name": "Deutsch"
7+
},
58
"ribbon": {
69
"tab": {
710
"mod": "Mod",
@@ -19,7 +22,8 @@
1922
"relocationOptions": "Relocation Options",
2023
"loggingOptions": "Logging Options",
2124
"otherOptions": "Other Options",
22-
"helpActions": "Help Actions"
25+
"helpActions": "Help Actions",
26+
"localizationOptions": "Localization Options"
2327
},
2428
"mod": {
2529
"new": "New",
@@ -61,6 +65,10 @@
6165
},
6266
"other": {
6367
"checkUpdates": "Check for Updates on StartUp"
68+
},
69+
"localization": {
70+
"language": "Language:",
71+
"language.tooltip": "Select the interface language"
6472
}
6573
},
6674
"logging": {

src/ClusterRelocationService/Translations/en.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"app": {
33
"title": "Cluster Relocation Service"
44
},
5+
"language": {
6+
"name": "English"
7+
},
58
"ribbon": {
69
"tab": {
710
"mod": "Mod",
@@ -19,7 +22,8 @@
1922
"relocationOptions": "Relocation Options",
2023
"loggingOptions": "Logging Options",
2124
"otherOptions": "Other Options",
22-
"helpActions": "Help Actions"
25+
"helpActions": "Help Actions",
26+
"localizationOptions": "Localization Options"
2327
},
2428
"mod": {
2529
"new": "New",
@@ -61,6 +65,10 @@
6165
},
6266
"other": {
6367
"checkUpdates": "Check for Updates on StartUp"
68+
},
69+
"localization": {
70+
"language": "Language:",
71+
"language.tooltip": "Select the interface language"
6472
}
6573
},
6674
"logging": {

src/ClusterRelocationService/Translations/es.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"app": {
33
"title": "Cluster Relocation Service"
44
},
5+
"language": {
6+
"name": "Espa\u00f1ol"
7+
},
58
"ribbon": {
69
"tab": {
710
"mod": "Mod",
@@ -19,7 +22,8 @@
1922
"relocationOptions": "Relocation Options",
2023
"loggingOptions": "Logging Options",
2124
"otherOptions": "Other Options",
22-
"helpActions": "Help Actions"
25+
"helpActions": "Help Actions",
26+
"localizationOptions": "Localization Options"
2327
},
2428
"mod": {
2529
"new": "New",
@@ -61,6 +65,10 @@
6165
},
6266
"other": {
6367
"checkUpdates": "Check for Updates on StartUp"
68+
},
69+
"localization": {
70+
"language": "Language:",
71+
"language.tooltip": "Select the interface language"
6472
}
6573
},
6674
"logging": {

src/ClusterRelocationService/Translations/fr.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"app": {
33
"title": "Cluster Relocation Service"
44
},
5+
"language": {
6+
"name": "Fran\u00e7ais"
7+
},
58
"ribbon": {
69
"tab": {
710
"mod": "Mod",
@@ -19,7 +22,8 @@
1922
"relocationOptions": "Relocation Options",
2023
"loggingOptions": "Logging Options",
2124
"otherOptions": "Other Options",
22-
"helpActions": "Help Actions"
25+
"helpActions": "Help Actions",
26+
"localizationOptions": "Localization Options"
2327
},
2428
"mod": {
2529
"new": "New",
@@ -61,6 +65,10 @@
6165
},
6266
"other": {
6367
"checkUpdates": "Check for Updates on StartUp"
68+
},
69+
"localization": {
70+
"language": "Language:",
71+
"language.tooltip": "Select the interface language"
6472
}
6573
},
6674
"logging": {

src/ClusterRelocationService/Translations/it.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"app": {
33
"title": "Cluster Relocation Service"
44
},
5+
"language": {
6+
"name": "Italiano"
7+
},
58
"ribbon": {
69
"tab": {
710
"mod": "Mod",
@@ -19,7 +22,8 @@
1922
"relocationOptions": "Relocation Options",
2023
"loggingOptions": "Logging Options",
2124
"otherOptions": "Other Options",
22-
"helpActions": "Help Actions"
25+
"helpActions": "Help Actions",
26+
"localizationOptions": "Localization Options"
2327
},
2428
"mod": {
2529
"new": "New",
@@ -61,6 +65,10 @@
6165
},
6266
"other": {
6367
"checkUpdates": "Check for Updates on StartUp"
68+
},
69+
"localization": {
70+
"language": "Language:",
71+
"language.tooltip": "Select the interface language"
6472
}
6573
},
6674
"logging": {

0 commit comments

Comments
 (0)