diff --git a/Directory.Packages.props b/Directory.Packages.props
index e9bda3b..407c235 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -9,9 +9,11 @@
+
+
diff --git a/Lepo.i18n.sln b/Lepo.i18n.sln
index 1a3fb04..e61ba76 100644
--- a/Lepo.i18n.sln
+++ b/Lepo.i18n.sln
@@ -30,7 +30,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lepo.i18n.DependencyInjecti
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lepo.i18n.Wpf.UnitTests", "tests\Lepo.i18n.Wpf.UnitTests\Lepo.i18n.Wpf.UnitTests.csproj", "{ED677E81-8D0F-42B2-A001-D37FEB3AAEA2}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lepo.i18n.Json.UnitTests", "tests\Lepo.i18n.Json.UnitTests\Lepo.i18n.Json.UnitTests.csproj", "{46BB2EDE-5A5C-46BC-930F-F1FB6128B4AE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lepo.i18n.Json.UnitTests", "tests\Lepo.i18n.Json.UnitTests\Lepo.i18n.Json.UnitTests.csproj", "{46BB2EDE-5A5C-46BC-930F-F1FB6128B4AE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Galery", "src\Sample\Galery\Galery.csproj", "{9C513AB3-9C79-4D4B-BCDA-37621B2DAF1C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -70,6 +72,10 @@ Global
{46BB2EDE-5A5C-46BC-930F-F1FB6128B4AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46BB2EDE-5A5C-46BC-930F-F1FB6128B4AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46BB2EDE-5A5C-46BC-930F-F1FB6128B4AE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9C513AB3-9C79-4D4B-BCDA-37621B2DAF1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9C513AB3-9C79-4D4B-BCDA-37621B2DAF1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9C513AB3-9C79-4D4B-BCDA-37621B2DAF1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9C513AB3-9C79-4D4B-BCDA-37621B2DAF1C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Sample/Galery/App.xaml b/src/Sample/Galery/App.xaml
new file mode 100644
index 0000000..3db73e4
--- /dev/null
+++ b/src/Sample/Galery/App.xaml
@@ -0,0 +1,17 @@
+
+
+
+ LeftToRight
+
+
+
+
+
+
+
diff --git a/src/Sample/Galery/App.xaml.cs b/src/Sample/Galery/App.xaml.cs
new file mode 100644
index 0000000..505ac5a
--- /dev/null
+++ b/src/Sample/Galery/App.xaml.cs
@@ -0,0 +1,112 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using Galery.Services;
+using Galery.ViewModels.Pages;
+using Galery.ViewModels.Windows;
+using Galery.Views.Pages;
+using Galery.Views.Windows;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Lepo.i18n.DependencyInjection;
+using Lepo.i18n.Json;
+using System.IO;
+using System.Reflection;
+using System.Windows.Threading;
+using Wpf.Ui;
+using System.Globalization;
+using Newtonsoft.Json;
+using Galery.Models;
+
+namespace Galery;
+///
+/// Interaction logic for App.xaml
+///
+public partial class App
+{
+ // The.NET Generic Host provides dependency injection, configuration, logging, and other services.
+ // https://docs.microsoft.com/dotnet/core/extensions/generic-host
+ // https://docs.microsoft.com/dotnet/core/extensions/dependency-injection
+ // https://docs.microsoft.com/dotnet/core/extensions/configuration
+ // https://docs.microsoft.com/dotnet/core/extensions/logging
+ private static readonly IHost _host = Host
+ .CreateDefaultBuilder()
+ .ConfigureAppConfiguration(c => { c.SetBasePath(Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)); })
+ .ConfigureServices((context, services) =>
+ {
+ _ = services.AddStringLocalizer(b =>
+ {
+ _ = b.FromJson(Assembly.GetExecutingAssembly(), "Resources.Translations-fa-IR.json", new CultureInfo("fa-IR"));
+ _ = b.FromJson(Assembly.GetExecutingAssembly(), "Resources.Translations-en-US.json", new CultureInfo("en-US"));
+ var cul = new CultureInfo((JsonConvert.DeserializeObject(File.ReadAllText(@"CultureInfos.json")).CultureInfo));
+ b.SetCulture(cul);
+ Application.Current.Resources["MainDirection"] = cul.EnglishName == "English (United States)" ? FlowDirection.LeftToRight : FlowDirection.RightToLeft;
+ });
+
+
+ _ = services.AddHostedService();
+
+ // Page resolver service
+ _ = services.AddSingleton();
+
+ // Theme manipulation
+ _ = services.AddSingleton();
+
+ // TaskBar manipulation
+ _ = services.AddSingleton();
+
+ // Service containing navigation, same as INavigationWindow... but without window
+ _ = services.AddSingleton();
+
+ // Main window with navigation
+ _ = services.AddSingleton();
+ _ = services.AddSingleton();
+
+ _ = services.AddSingleton();
+ _ = services.AddSingleton();
+ _ = services.AddTransient();
+ _ = services.AddTransient();
+ _ = services.AddSingleton();
+ _ = services.AddSingleton();
+ }).Build();
+
+ ///
+ /// Gets registered service.
+ ///
+ /// Type of the service to get.
+ /// Instance of the service or .
+ public static T GetService()
+ where T : class
+ {
+ return _host.Services.GetService(typeof(T)) as T;
+ }
+
+ ///
+ /// Occurs when the application is loading.
+ ///
+ private void OnStartup(object sender, StartupEventArgs e)
+ {
+ _host.Start();
+ }
+
+ ///
+ /// Occurs when the application is closing.
+ ///
+ private async void OnExit(object sender, ExitEventArgs e)
+ {
+ await _host.StopAsync();
+
+ _host.Dispose();
+ }
+
+ ///
+ /// Occurs when an exception is thrown by an application but not handled.
+ ///
+ private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
+ {
+ // For more info see https://docs.microsoft.com/en-us/dotnet/api/system.windows.application.dispatcherunhandledexception?view=windowsdesktop-6.0
+ }
+}
diff --git a/src/Sample/Galery/AssemblyInfo.cs b/src/Sample/Galery/AssemblyInfo.cs
new file mode 100644
index 0000000..e170172
--- /dev/null
+++ b/src/Sample/Galery/AssemblyInfo.cs
@@ -0,0 +1,15 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+//(used if a resource is not found in the page,
+// app, or any theme specific resource dictionaries)
+)]
diff --git a/src/Sample/Galery/Assets/wpfui-icon-1024.png b/src/Sample/Galery/Assets/wpfui-icon-1024.png
new file mode 100644
index 0000000..b70c4ed
Binary files /dev/null and b/src/Sample/Galery/Assets/wpfui-icon-1024.png differ
diff --git a/src/Sample/Galery/Assets/wpfui-icon-256.png b/src/Sample/Galery/Assets/wpfui-icon-256.png
new file mode 100644
index 0000000..6b5cf5d
Binary files /dev/null and b/src/Sample/Galery/Assets/wpfui-icon-256.png differ
diff --git a/src/Sample/Galery/CultureInfos.json b/src/Sample/Galery/CultureInfos.json
new file mode 100644
index 0000000..6fb058b
--- /dev/null
+++ b/src/Sample/Galery/CultureInfos.json
@@ -0,0 +1,3 @@
+{
+ "CultureInfo": "en-US"
+}
diff --git a/src/Sample/Galery/Galery.csproj b/src/Sample/Galery/Galery.csproj
new file mode 100644
index 0000000..62f00ba
--- /dev/null
+++ b/src/Sample/Galery/Galery.csproj
@@ -0,0 +1,51 @@
+
+
+
+ WinExe
+ net8.0-windows
+ app.manifest
+ wpfui-icon.ico
+ true
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
diff --git a/src/Sample/Galery/Helpers/EnumToBooleanConverter.cs b/src/Sample/Galery/Helpers/EnumToBooleanConverter.cs
new file mode 100644
index 0000000..c606087
--- /dev/null
+++ b/src/Sample/Galery/Helpers/EnumToBooleanConverter.cs
@@ -0,0 +1,39 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using System.Globalization;
+using System.Windows.Data;
+using Wpf.Ui.Appearance;
+
+namespace Galery.Helpers;
+internal class EnumToBooleanConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (parameter is not String enumString)
+ {
+ throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName");
+ }
+
+ if (!Enum.IsDefined(typeof(ApplicationTheme), value))
+ {
+ throw new ArgumentException("ExceptionEnumToBooleanConverterValueMustBeAnEnum");
+ }
+
+ var enumValue = Enum.Parse(typeof(ApplicationTheme), enumString);
+
+ return enumValue.Equals(value);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (parameter is not String enumString)
+ {
+ throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName");
+ }
+
+ return Enum.Parse(typeof(ApplicationTheme), enumString);
+ }
+}
diff --git a/src/Sample/Galery/Models/AppConfig.cs b/src/Sample/Galery/Models/AppConfig.cs
new file mode 100644
index 0000000..f916b43
--- /dev/null
+++ b/src/Sample/Galery/Models/AppConfig.cs
@@ -0,0 +1,13 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+namespace Galery.Models;
+
+public class AppConfig
+{
+ public string ConfigurationsFolder { get; set; }
+
+ public string AppPropertiesFileName { get; set; }
+}
diff --git a/src/Sample/Galery/Models/DataColor.cs b/src/Sample/Galery/Models/DataColor.cs
new file mode 100644
index 0000000..7a0f3b5
--- /dev/null
+++ b/src/Sample/Galery/Models/DataColor.cs
@@ -0,0 +1,12 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using System.Windows.Media;
+
+namespace Galery.Models;
+public struct DataColor
+{
+ public Brush Color { get; set; }
+}
diff --git a/src/Sample/Galery/Models/LanInfo.cs b/src/Sample/Galery/Models/LanInfo.cs
new file mode 100644
index 0000000..b106626
--- /dev/null
+++ b/src/Sample/Galery/Models/LanInfo.cs
@@ -0,0 +1,5 @@
+namespace Galery.Models;
+public class LanInfo
+{
+ public string CultureInfo { get; set; } = default!;
+}
diff --git a/src/Sample/Galery/Resources/Translations-en-US.json b/src/Sample/Galery/Resources/Translations-en-US.json
new file mode 100644
index 0000000..543e653
--- /dev/null
+++ b/src/Sample/Galery/Resources/Translations-en-US.json
@@ -0,0 +1,53 @@
+{
+ "version": "1.0",
+ "strings": [
+ {
+ "name": "Test",
+ "value": "Text in english"
+ },
+ {
+ "name": "Titele",
+ "value": "WPF UI - Galery"
+ },
+ {
+ "name": "Lan",
+ "value": "Language"
+ },
+ {
+ "name": "Menu.Settings",
+ "value": "Settings"
+ },
+ {
+ "name": "Menu.Dashboard",
+ "value": "Dashboard"
+ },
+ {
+ "name": "Menu.Data",
+ "value": "Data"
+ },
+ {
+ "name": "Menu.Search",
+ "value": "Search"
+ },
+ {
+ "name": "Setting.Personalization",
+ "value": "Personalization"
+ },
+ {
+ "name": "Setting.Theme",
+ "value": "Theme"
+ },
+ {
+ "name": "Setting.Theme.Light",
+ "value": "Light"
+ },
+ {
+ "name": "Setting.Theme.Dark",
+ "value": "Dark"
+ },
+ {
+ "name": "Dashboard.Click",
+ "value": "ClickMe !"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Sample/Galery/Resources/Translations-fa-IR.json b/src/Sample/Galery/Resources/Translations-fa-IR.json
new file mode 100644
index 0000000..21622ba
--- /dev/null
+++ b/src/Sample/Galery/Resources/Translations-fa-IR.json
@@ -0,0 +1,53 @@
+{
+ "version": "1.0",
+ "strings": [
+ {
+ "name": "Test",
+ "value": "متن برای فارسی"
+ },
+ {
+ "name": "Titele",
+ "value": "WPF UI - گالری "
+ },
+ {
+ "name": "Lan",
+ "value": "زبان سیستم"
+ },
+ {
+ "name": "Menu.Settings",
+ "value": "تنظیمات"
+ },
+ {
+ "name": "Menu.Dashboard",
+ "value": "داشبورد"
+ },
+ {
+ "name": "Menu.Data",
+ "value": "دیتا"
+ },
+ {
+ "name": "Menu.Search",
+ "value": "جستجو"
+ },
+ {
+ "name": "Setting.Personalization",
+ "value": "شخصی سازی"
+ },
+ {
+ "name": "Setting.Theme.Light",
+ "value": "روز"
+ },
+ {
+ "name": "Setting.Theme",
+ "value": "تم قالب"
+ },
+ {
+ "name": "Setting.Theme.Dark",
+ "value": "شب"
+ },
+ {
+ "name": "Dashboard.Click",
+ "value": "! کلیک کنید"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Sample/Galery/Resources/Translations.cs b/src/Sample/Galery/Resources/Translations.cs
new file mode 100644
index 0000000..3405ed2
--- /dev/null
+++ b/src/Sample/Galery/Resources/Translations.cs
@@ -0,0 +1,10 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+namespace Galery.Resources;
+
+public partial class Translations
+{
+}
diff --git a/src/Sample/Galery/Services/ApplicationHostService.cs b/src/Sample/Galery/Services/ApplicationHostService.cs
new file mode 100644
index 0000000..04f49bc
--- /dev/null
+++ b/src/Sample/Galery/Services/ApplicationHostService.cs
@@ -0,0 +1,62 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using Galery.Views.Pages;
+using Galery.Views.Windows;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Wpf.Ui;
+
+namespace Galery.Services;
+///
+/// Managed host of the application.
+///
+public class ApplicationHostService : IHostedService
+{
+ private readonly IServiceProvider _serviceProvider;
+
+ private INavigationWindow _navigationWindow;
+
+ public ApplicationHostService(IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ }
+
+ ///
+ /// Triggered when the application host is ready to start the service.
+ ///
+ /// Indicates that the start process has been aborted.
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ await HandleActivationAsync();
+ }
+
+ ///
+ /// Triggered when the application host is performing a graceful shutdown.
+ ///
+ /// Indicates that the shutdown process should no longer be graceful.
+ public async Task StopAsync(CancellationToken cancellationToken)
+ {
+ await Task.CompletedTask;
+ }
+
+ ///
+ /// Creates main window during activation.
+ ///
+ private async Task HandleActivationAsync()
+ {
+ if (!Application.Current.Windows.OfType().Any())
+ {
+ _navigationWindow = (
+ _serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow
+ )!;
+ _navigationWindow!.ShowWindow();
+
+ _navigationWindow.Navigate(typeof(Views.Pages.DashboardPage));
+ }
+
+ await Task.CompletedTask;
+ }
+}
diff --git a/src/Sample/Galery/Services/PageService.cs b/src/Sample/Galery/Services/PageService.cs
new file mode 100644
index 0000000..626862f
--- /dev/null
+++ b/src/Sample/Galery/Services/PageService.cs
@@ -0,0 +1,45 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using Wpf.Ui;
+
+namespace Galery.Services;
+///
+/// Service that provides pages for navigation.
+///
+public class PageService : IPageService
+{
+ ///
+ /// Service which provides the instances of pages.
+ ///
+ private readonly IServiceProvider _serviceProvider;
+
+ ///
+ /// Creates new instance and attaches the .
+ ///
+ public PageService(IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ }
+
+ ///
+ public T? GetPage()
+ where T : class
+ {
+ if (!typeof(FrameworkElement).IsAssignableFrom(typeof(T)))
+ throw new InvalidOperationException("The page should be a WPF control.");
+
+ return (T?)_serviceProvider.GetService(typeof(T));
+ }
+
+ ///
+ public FrameworkElement? GetPage(Type pageType)
+ {
+ if (!typeof(FrameworkElement).IsAssignableFrom(pageType))
+ throw new InvalidOperationException("The page should be a WPF control.");
+
+ return _serviceProvider.GetService(pageType) as FrameworkElement;
+ }
+}
diff --git a/src/Sample/Galery/Usings.cs b/src/Sample/Galery/Usings.cs
new file mode 100644
index 0000000..c9c0526
--- /dev/null
+++ b/src/Sample/Galery/Usings.cs
@@ -0,0 +1,9 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+global using CommunityToolkit.Mvvm.ComponentModel;
+global using CommunityToolkit.Mvvm.Input;
+global using System;
+global using System.Windows;
diff --git a/src/Sample/Galery/ViewModels/Pages/DashboardViewModel.cs b/src/Sample/Galery/ViewModels/Pages/DashboardViewModel.cs
new file mode 100644
index 0000000..f09b617
--- /dev/null
+++ b/src/Sample/Galery/ViewModels/Pages/DashboardViewModel.cs
@@ -0,0 +1,18 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+namespace Galery.ViewModels.Pages;
+
+public partial class DashboardViewModel : ObservableObject
+{
+ [ObservableProperty]
+ private int _counter = 0;
+
+ [RelayCommand]
+ private void OnCounterIncrement()
+ {
+ Counter++;
+ }
+}
diff --git a/src/Sample/Galery/ViewModels/Pages/DataViewModel.cs b/src/Sample/Galery/ViewModels/Pages/DataViewModel.cs
new file mode 100644
index 0000000..7f8102d
--- /dev/null
+++ b/src/Sample/Galery/ViewModels/Pages/DataViewModel.cs
@@ -0,0 +1,50 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using Galery.Models;
+using System.Windows.Media;
+using Wpf.Ui.Controls;
+
+namespace Galery.ViewModels.Pages;
+public partial class DataViewModel : ObservableObject, INavigationAware
+{
+ private bool _isInitialized = false;
+
+ [ObservableProperty]
+ private IEnumerable _colors;
+
+ public void OnNavigatedTo()
+ {
+ if (!_isInitialized)
+ InitializeViewModel();
+ }
+
+ public void OnNavigatedFrom() { }
+
+ private void InitializeViewModel()
+ {
+ var random = new Random();
+ var colorCollection = new List();
+
+ for (int i = 0; i < 8192; i++)
+ colorCollection.Add(
+ new DataColor
+ {
+ Color = new SolidColorBrush(
+ Color.FromArgb(
+ (byte)200,
+ (byte)random.Next(0, 250),
+ (byte)random.Next(0, 250),
+ (byte)random.Next(0, 250)
+ )
+ )
+ }
+ );
+
+ Colors = colorCollection;
+
+ _isInitialized = true;
+ }
+}
diff --git a/src/Sample/Galery/ViewModels/Pages/SettingsViewModel.cs b/src/Sample/Galery/ViewModels/Pages/SettingsViewModel.cs
new file mode 100644
index 0000000..f048db3
--- /dev/null
+++ b/src/Sample/Galery/ViewModels/Pages/SettingsViewModel.cs
@@ -0,0 +1,104 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using Microsoft.Extensions.Localization;
+using Wpf.Ui.Appearance;
+using Lepo.i18n;
+using Wpf.Ui.Controls;
+using Galery.Models;
+using Newtonsoft.Json;
+using System.IO;
+
+namespace Galery.ViewModels.Pages;
+public partial class SettingsViewModel : ObservableObject, INavigationAware
+{
+ private bool _isInitialized = false;
+
+ private readonly IStringLocalizer _stringLocalizer;
+ private readonly ILocalizationCultureManager _cultureManager;
+
+ public SettingsViewModel(IStringLocalizer stringLocalizer, ILocalizationCultureManager cultureManager)
+ {
+ _stringLocalizer = stringLocalizer;
+ _cultureManager = cultureManager;
+ }
+
+ [ObservableProperty]
+ private string _appVersion = String.Empty;
+
+ [ObservableProperty]
+ private bool _isEnglish = true;
+
+ [ObservableProperty]
+ private ApplicationTheme _currentTheme = ApplicationTheme.Unknown;
+
+ public void OnNavigatedTo()
+ {
+ if (!_isInitialized)
+ InitializeViewModel();
+ }
+
+ public void OnNavigatedFrom() { }
+
+ private void InitializeViewModel()
+ {
+ AppVersion = _stringLocalizer["Lan"].Value;
+ IsEnglish = _cultureManager.GetCulture().EnglishName == "English (United States)";
+ CurrentTheme = ApplicationThemeManager.GetAppTheme();
+ //AppVersion = $"UiDesktopApp1 - {GetAssemblyVersion()}";
+ _isInitialized = true;
+ }
+
+ private string GetAssemblyVersion()
+ {
+ return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString()
+ ?? String.Empty;
+ }
+
+ [RelayCommand]
+ private void OnChangeTheme(string parameter)
+ {
+ switch (parameter)
+ {
+ case "theme_light":
+ if (CurrentTheme == ApplicationTheme.Light)
+ break;
+
+ ApplicationThemeManager.Apply(ApplicationTheme.Light);
+ CurrentTheme = ApplicationTheme.Light;
+
+ break;
+
+ default:
+ if (CurrentTheme == ApplicationTheme.Dark)
+ break;
+
+ ApplicationThemeManager.Apply(ApplicationTheme.Dark);
+ CurrentTheme = ApplicationTheme.Dark;
+
+ break;
+ }
+ }
+
+ [RelayCommand]
+ private void OnChangeLan(bool isChecked)
+ {
+ if (isChecked)
+ {
+ _cultureManager.SetCulture("en-US");
+ File.WriteAllText(@"CultureInfos.json", JsonConvert.SerializeObject(new LanInfo() { CultureInfo = "en-US" }));
+ }
+ else
+ {
+ _cultureManager.SetCulture("fa-IR");
+ File.WriteAllText(@"CultureInfos.json", JsonConvert.SerializeObject(new LanInfo() { CultureInfo = "fa-IR" }));
+ }
+
+ AppVersion = _stringLocalizer["Lan"].Value;
+
+ System.Diagnostics.Process.Start(System.Diagnostics.Process.GetCurrentProcess().ProcessName);
+ App.Current.Shutdown();
+ }
+}
diff --git a/src/Sample/Galery/ViewModels/Windows/MainWindowViewModel.cs b/src/Sample/Galery/ViewModels/Windows/MainWindowViewModel.cs
new file mode 100644
index 0000000..71917d0
--- /dev/null
+++ b/src/Sample/Galery/ViewModels/Windows/MainWindowViewModel.cs
@@ -0,0 +1,62 @@
+// This Source Code Form is subject to the terms of the MIT License.
+// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
+// Copyright (C) Leszek Pomianowski and Lepo.i18n Contributors.
+// All Rights Reserved.
+
+using Microsoft.Extensions.Localization;
+using System.Collections.ObjectModel;
+using Wpf.Ui.Controls;
+
+namespace Galery.ViewModels.Windows;
+public partial class MainWindowViewModel : ObservableObject
+{
+
+ private readonly IStringLocalizer _stringLocalizer;
+
+ [ObservableProperty]
+ private string _applicationTitle = string.Empty;
+
+ [ObservableProperty]
+ private ObservableCollection