- add: language

This commit is contained in:
2025-06-23 16:39:30 +03:00
parent 02e1a14571
commit 0a2fe55c7f
23 changed files with 246 additions and 81 deletions

2
.vscode/launch.json vendored
View File

@@ -10,7 +10,7 @@
"request": "launch", "request": "launch",
"preLaunchTask": "build", "preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path. // If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Nebula.Launcher/bin/Debug/net9.0/Nebula.Launcher.dll", "program": "${workspaceFolder}/Nebula.Launcher/bin/Debug/Nebula.Launcher.dll",
"args": [], "args": [],
"cwd": "${workspaceFolder}/Nebula.Launcher", "cwd": "${workspaceFolder}/Nebula.Launcher",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console

View File

@@ -0,0 +1,48 @@
tab-account = Account
tab-servers = Servers
tab-content = Content
tab-settings = Settings
vcruntime-check-error = VC runtime dlls are not present on this computer. Install VC runtime dlls.
migration-label-task = Migration task, please wait...
task-cancel = Cancel
popup-edit-name = Edit server name
popup-add-favorite = Add favorite
popup-exception = Exception was thrown
popup-information = Information
popup-loading = Loading...
popup-twofa = 2fa
account-profiles = Profiles
account-profile-select = Select
account-profile-delete = Delete
account-auth-retry = Retry Authentication
account-auth-try-another = Or try another account
account-auth-login = Enter your login
account-auth-password = Enter your password
account-auth-server = Authentication Server
account-auth-button = Authenticate
account-auth-save = Save Profile
account-auth-hello = Hello,
account-auth-logout = Log out
auth-processing = Processing authentication request...
auth-error = An authentication error has occurred.
auth-error-occured = An error occurred during the authentication process.
auth-invalid-credentials = Invalid username or password. Please try again.
auth-connection-error = Unable to connect to the authentication server.
auth-name-resolution-error = Failed to resolve server address. Check your network or server configuration.
auth-config-read = Reading authentication configuration...
auth-try-auth-config = Attempting to authenticate using saved configuration.
config-export-logs = Export logs
config-open-data = Open data path
config-reset = Reset to default
config-save = Save changes
filter-roleplay = Roleplay
filter-language = Language
favorite-add = Add to favorites
servername-set = Set server name
twofa-enabled = You have two-factor authentication enabled. Please enter the code.
twofa-set = Proceed

View File

@@ -0,0 +1,48 @@
tab-account = Аккаунт
tab-servers = Серверы
tab-content = Контент
tab-settings = Настройки
vcruntime-check-error = VC runtime dll-библиотеки отсутствуют на этом компьютере. Установите VC runtime dll.
migration-label-task = Задача миграции, подождите...
task-cancel = Отмена
popup-edit-name = Изменить имя сервера
popup-add-favorite = Добавить в избранное
popup-exception = Произошло исключение
popup-information = Информация
popup-loading = Загрузка...
popup-twofa = 2FA
account-profiles = Профили
account-profile-select = Выбрать
account-profile-delete = Удалить
account-auth-retry = Повторить аутентификацию
account-auth-try-another = Или попробуйте другой аккаунт
account-auth-login = Введите логин
account-auth-password = Введите пароль
account-auth-server = Сервер аутентификации
account-auth-button = Аутентифицировать
account-auth-save = Сохранить профиль
account-auth-hello = Привет,
account-auth-logout = Выйти
auth-processing = Обработка запроса аутентификации...
auth-error = Произошла ошибка аутентификации.
auth-error-occured = Во время аутентификации произошла ошибка.
auth-invalid-credentials = Неверное имя пользователя или пароль. Попробуйте еще раз.
auth-connection-error = Не удается подключиться к серверу аутентификации.
auth-name-resolution-error = Не удалось разрешить адрес сервера. Проверьте сетевые настройки или конфигурацию сервера.
auth-config-read = Чтение конфигурации аутентификации...
auth-try-auth-config = Попытка аутентификации с использованием сохраненной конфигурации.
config-export-logs = Экспортировать логи
config-open-data = Открыть путь данных
config-reset = Сбросить к значениям по умолчанию
config-save = Сохранить изменения
filter-roleplay = Ролевая игра
filter-language = Язык
favorite-add = Добавить в избранное
servername-set = Установить имя сервера
twofa-enabled = У вас включена двухфакторная аутентификация. Введите код.
twofa-set = Продолжить

View File

@@ -19,13 +19,16 @@ public class FilterBox : UserControl
public Action<FilterBoxChangedEventArgs>? OnFilterChanged {get; set;} public Action<FilterBoxChangedEventArgs>? OnFilterChanged {get; set;}
public string? FilterBoxName { public string FilterBoxName {
set => filterName.Text = value; set => filterName.LocalId = value;
get => filterName.Text; get => filterName.LocalId;
} }
private StackPanel filterPanel; private StackPanel filterPanel;
private TextBox filterName = new TextBox(); private LocalizedLabel filterName = new LocalizedLabel()
{
VerticalAlignment = VerticalAlignment.Center
};
public FilterBox() public FilterBox()
{ {
@@ -34,6 +37,8 @@ public class FilterBox : UserControl
Orientation = Orientation.Horizontal, Orientation = Orientation.Horizontal,
Spacing = 5, Spacing = 5,
}; };
filterPanel.Children.Add(filterName);
Content = filterPanel; Content = filterPanel;
} }

View File

@@ -0,0 +1,20 @@
using Avalonia;
using Avalonia.Controls;
using Nebula.Launcher.Services;
namespace Nebula.Launcher.Controls;
public class LocalizedLabel : Label
{
public static readonly StyledProperty<string> LocalIdProperty = AvaloniaProperty.Register<LocalizedLabel, string>(nameof(LocalId));
public string LocalId
{
get => GetValue(LocalIdProperty);
set
{
SetValue(LocalIdProperty, value);
Content = LocalisationService.GetString(value);
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using Nebula.Launcher.Models; using Nebula.Launcher.Models;
using Nebula.Launcher.ViewModels.Pages; using Nebula.Launcher.ViewModels.Pages;
using Nebula.Shared.Services; using Nebula.Shared.Services;
@@ -36,7 +37,7 @@ public static class LauncherConVar
new ServerHubRecord("AltHub","https://web.networkgamez.com/api/servers") new ServerHubRecord("AltHub","https://web.networkgamez.com/api/servers")
]); ]);
public static readonly ConVar<string> CurrentLang = ConVarBuilder.Build<string>("launcher.language", "en-US"); public static readonly ConVar<string> CurrentLang = ConVarBuilder.Build<string>("launcher.language", CultureInfo.CurrentCulture.Name);
public static readonly ConVar<string> ILSpyUrl = ConVarBuilder.Build<string>("decompiler.url", public static readonly ConVar<string> ILSpyUrl = ConVarBuilder.Build<string>("decompiler.url",
"https://github.com/icsharpcode/ILSpy/releases/download/v9.0/ILSpy_binaries_9.0.0.7889-x64.zip"); "https://github.com/icsharpcode/ILSpy/releases/download/v9.0/ILSpy_binaries_9.0.0.7889-x64.zip");

View File

@@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using Avalonia.Markup.Xaml;
using Avalonia.Platform; using Avalonia.Platform;
using Fluent.Net; using Fluent.Net;
using Nebula.Shared; using Nebula.Shared;
@@ -14,33 +16,63 @@ public partial class LocalisationService
[GenerateProperty] private ConfigurationService ConfigurationService { get; } [GenerateProperty] private ConfigurationService ConfigurationService { get; }
private CultureInfo _currentCultureInfo = CultureInfo.CurrentCulture; private CultureInfo _currentCultureInfo = CultureInfo.CurrentCulture;
private MessageContext _currentMessageContext; private static MessageContext? _currentMessageContext;
private void Initialise() private void Initialise()
{ {
// LoadLanguage(CultureInfo.GetCultureInfo(ConfigurationService.GetConfigValue(LauncherConVar.CurrentLang)!)); LoadLanguage(CultureInfo.GetCultureInfo(ConfigurationService.GetConfigValue(LauncherConVar.CurrentLang)!));
} }
public void LoadLanguage(CultureInfo cultureInfo) public void LoadLanguage(CultureInfo cultureInfo)
{ {
_currentCultureInfo = cultureInfo; try
using var fs = AssetLoader.Open(new Uri($@"Assets/lang/{_currentCultureInfo.EnglishName}.ftl"));
using var sr = new StreamReader(fs);
var options = new MessageContextOptions { UseIsolating = false };
var mc = new MessageContext(cultureInfo.EnglishName, options);
var errors = mc.AddMessages(sr);
foreach (var error in errors)
{ {
Console.WriteLine(error); _currentCultureInfo = cultureInfo;
} using var fs = AssetLoader.Open(new Uri($@"avares://Nebula.Launcher/Assets/lang/{_currentCultureInfo.Name}.ftl"));
using var sr = new StreamReader(fs);
_currentMessageContext = mc; var options = new MessageContextOptions { UseIsolating = false };
var mc = new MessageContext(cultureInfo.Name, options);
var errors = mc.AddMessages(sr);
foreach (var error in errors)
{
Console.WriteLine(error);
}
_currentMessageContext = mc;
} catch (Exception e) {
LoadLanguage(CultureInfo.GetCultureInfo("en-US"));
}
} }
private void InitialiseInDesignMode() private void InitialiseInDesignMode()
{ {
Initialise(); Initialise();
} }
public static string GetString(string locale)
{
if (_currentMessageContext is null)
{
Console.WriteLine("ERROR SHIT BITHC!");
return locale;
}
var message = _currentMessageContext.GetMessage(locale);
if (message == null) return locale;
return _currentMessageContext.Format(message, new Dictionary<string, object>());
}
} }
public class LocaledText : MarkupExtension
{
public string Key { get; set; }
public LocaledText(string key) => Key = key;
public override object ProvideValue(IServiceProvider serviceProvider)
{
// Fetch the localized string using the key
return LocalisationService.GetString(Key);
}
}

View File

@@ -23,10 +23,10 @@ public partial class MainViewModel : ViewModelBase
{ {
private readonly List<ListItemTemplate> _templates = private readonly List<ListItemTemplate> _templates =
[ [
new ListItemTemplate(typeof(AccountInfoViewModel), "user", "Account"), new ListItemTemplate(typeof(AccountInfoViewModel), "user", "tab-account"),
new ListItemTemplate(typeof(ServerOverviewModel), "file", "Servers"), new ListItemTemplate(typeof(ServerOverviewModel), "file", "tab-servers"),
new ListItemTemplate(typeof(ContentBrowserViewModel), "folder", "Content"), new ListItemTemplate(typeof(ContentBrowserViewModel), "folder", "tab-content"),
new ListItemTemplate(typeof(ConfigurationViewModel), "settings", "Settings") new ListItemTemplate(typeof(ConfigurationViewModel), "settings", "tab-settings")
]; ];
private readonly List<PopupViewModelBase> _viewQueue = new(); private readonly List<PopupViewModelBase> _viewQueue = new();
@@ -41,6 +41,7 @@ public partial class MainViewModel : ViewModelBase
[ObservableProperty] private bool _popup; [ObservableProperty] private bool _popup;
[ObservableProperty] private ListItemTemplate? _selectedListItem; [ObservableProperty] private ListItemTemplate? _selectedListItem;
[GenerateProperty] private LocalisationService LocalisationService { get; }
[GenerateProperty] private DebugService DebugService { get; } = default!; [GenerateProperty] private DebugService DebugService { get; } = default!;
[GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!; [GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!;
[GenerateProperty] private ContentService ContentService { get; } = default!; [GenerateProperty] private ContentService ContentService { get; } = default!;
@@ -53,7 +54,11 @@ public partial class MainViewModel : ViewModelBase
protected override void InitialiseInDesignMode() protected override void InitialiseInDesignMode()
{ {
Items = new ObservableCollection<ListItemTemplate>(_templates); Items = new ObservableCollection<ListItemTemplate>(_templates.Select(a=>
{
return new ListItemTemplate(a.ModelType, a.IconKey, LocalisationService.GetString(a.Label));
}
));
RequirePage<AccountInfoViewModel>(); RequirePage<AccountInfoViewModel>();
} }
@@ -76,7 +81,7 @@ public partial class MainViewModel : ViewModelBase
if (!VCRuntimeDllChecker.AreVCRuntimeDllsPresent()) if (!VCRuntimeDllChecker.AreVCRuntimeDllsPresent())
{ {
OnPopupRequired("VC runtime dlls are not present on this computer. Install VC runtime dlls."); OnPopupRequired(LocalisationService.GetString("vcruntime-check-error"));
Helper.OpenBrowser("https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170"); Helper.OpenBrowser("https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170");
} }
} }
@@ -87,7 +92,7 @@ public partial class MainViewModel : ViewModelBase
return; return;
var loadingHandler = ViewHelperService.GetViewModel<LoadingContextViewModel>(); var loadingHandler = ViewHelperService.GetViewModel<LoadingContextViewModel>();
loadingHandler.LoadingName = "Migration task, please wait..."; loadingHandler.LoadingName = LocalisationService.GetString("migration-label-task");
loadingHandler.IsCancellable = false; loadingHandler.IsCancellable = false;
if (!ContentService.CheckMigration(loadingHandler)) if (!ContentService.CheckMigration(loadingHandler))

View File

@@ -38,6 +38,7 @@ public partial class AccountInfoViewModel : ViewModelBase
[ObservableProperty] private bool _doRetryAuth; [ObservableProperty] private bool _doRetryAuth;
private bool _isProfilesEmpty; private bool _isProfilesEmpty;
[GenerateProperty] private LocalisationService LocalisationService { get; }
[GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!; [GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!;
[GenerateProperty] private ConfigurationService ConfigurationService { get; } = default!; [GenerateProperty] private ConfigurationService ConfigurationService { get; } = default!;
[GenerateProperty] private DebugService DebugService { get; } [GenerateProperty] private DebugService DebugService { get; }
@@ -79,7 +80,7 @@ public partial class AccountInfoViewModel : ViewModelBase
public void DoAuth(string? code = null) public void DoAuth(string? code = null)
{ {
var message = ViewHelperService.GetViewModel<InfoPopupViewModel>(); var message = ViewHelperService.GetViewModel<InfoPopupViewModel>();
message.InfoText = "Auth think, please wait..."; message.InfoText = LocalisationService.GetString("auth-processing");
message.IsInfoClosable = false; message.IsInfoClosable = false;
PopupMessageService.Popup(message); PopupMessageService.Popup(message);
@@ -102,7 +103,7 @@ public partial class AccountInfoViewModel : ViewModelBase
} }
catch (Exception ex) catch (Exception ex)
{ {
var unexpectedError = new Exception("An unexpected error occurred during authentication.", ex); var unexpectedError = new Exception(LocalisationService.GetString("auth-error"), ex);
_logger.Error(unexpectedError); _logger.Error(unexpectedError);
PopupMessageService.Popup(unexpectedError); PopupMessageService.Popup(unexpectedError);
} }
@@ -112,7 +113,7 @@ public partial class AccountInfoViewModel : ViewModelBase
if (!IsLogged) if (!IsLogged)
{ {
PopupMessageService.Popup(new Exception("No one of auth server is available.", exception)); PopupMessageService.Popup(exception ?? new Exception(LocalisationService.GetString("auth-error")));
} }
}); });
} }
@@ -156,7 +157,7 @@ public partial class AccountInfoViewModel : ViewModelBase
_logger.Log("TFA required"); _logger.Log("TFA required");
break; break;
case AuthenticateDenyCode.InvalidCredentials: case AuthenticateDenyCode.InvalidCredentials:
PopupError("Invalid Credentials! Please, try another password or login!", e); PopupError(LocalisationService.GetString("auth-invalid-credentials"), e);
break; break;
default: default:
throw; throw;
@@ -168,17 +169,17 @@ public partial class AccountInfoViewModel : ViewModelBase
switch (e.HttpRequestError) switch (e.HttpRequestError)
{ {
case HttpRequestError.ConnectionError: case HttpRequestError.ConnectionError:
PopupError("Failed to connect to the authentication server.", e); PopupError(LocalisationService.GetString("auth-connection-error"), e);
DoRetryAuth = true; DoRetryAuth = true;
break; break;
case HttpRequestError.NameResolutionError: case HttpRequestError.NameResolutionError:
PopupError("Unable to resolve the server address.", e); PopupError(LocalisationService.GetString("auth-name-resolution-error"), e);
DoRetryAuth = true; DoRetryAuth = true;
break; break;
default: default:
var authError = new Exception("An error occurred during authentication.", e); var authError = new Exception(LocalisationService.GetString("auth-error"), e);
_logger.Error(authError); _logger.Error(authError);
PopupMessageService.Popup(authError); PopupMessageService.Popup(authError);
break; break;
@@ -223,10 +224,10 @@ public partial class AccountInfoViewModel : ViewModelBase
Accounts.Add(alpm); Accounts.Add(alpm);
} }
private async Task ReadAuthConfig() private void ReadAuthConfig()
{ {
var message = ViewHelperService.GetViewModel<InfoPopupViewModel>(); var message = ViewHelperService.GetViewModel<InfoPopupViewModel>();
message.InfoText = "Read configuration file, please wait..."; message.InfoText = LocalisationService.GetString("auth-config-read");
message.IsInfoClosable = false; message.IsInfoClosable = false;
PopupMessageService.Popup(message); PopupMessageService.Popup(message);
foreach (var profile in foreach (var profile in
@@ -247,7 +248,7 @@ public partial class AccountInfoViewModel : ViewModelBase
public async void DoCurrentAuth() public async void DoCurrentAuth()
{ {
var message = ViewHelperService.GetViewModel<InfoPopupViewModel>(); var message = ViewHelperService.GetViewModel<InfoPopupViewModel>();
message.InfoText = "Trying to auth with saved data..."; message.InfoText = LocalisationService.GetString("auth-try-auth-config");
message.IsInfoClosable = false; message.IsInfoClosable = false;
PopupMessageService.Popup(message); PopupMessageService.Popup(message);
@@ -261,7 +262,7 @@ public partial class AccountInfoViewModel : ViewModelBase
} }
catch (Exception ex) catch (Exception ex)
{ {
var unexpectedError = new Exception("An unexpected error occurred during authentication.", ex); var unexpectedError = new Exception(LocalisationService.GetString("auth-error"), ex);
_logger.Error(unexpectedError); _logger.Error(unexpectedError);
PopupMessageService.Popup(unexpectedError); PopupMessageService.Popup(unexpectedError);
return; return;
@@ -290,7 +291,7 @@ public partial class AccountInfoViewModel : ViewModelBase
private void PopupError(string message, Exception e) private void PopupError(string message, Exception e)
{ {
message = "An error occurred during authentication: " + message; message = LocalisationService.GetString("auth-error-occured") + message;
_logger.Error(new Exception(message, e)); _logger.Error(new Exception(message, e));
var messageView = ViewHelperService.GetViewModel<InfoPopupViewModel>(); var messageView = ViewHelperService.GetViewModel<InfoPopupViewModel>();

View File

@@ -200,7 +200,10 @@ public sealed class ArrayUnitConfigControl : Border, IConfigControl
{ {
private readonly List<IConfigControl> _itemControls = []; private readonly List<IConfigControl> _itemControls = [];
private readonly StackPanel _itemsPanel = new StackPanel() { Orientation = Orientation.Vertical }; private readonly StackPanel _itemsPanel = new StackPanel() { Orientation = Orientation.Vertical };
private readonly Button _addButton = new Button() { Content = "Add Item", Classes = { "ConfigBorder" }}; private readonly Button _addButton = new Button() { Content = new Label()
{
Content = "Add Item"
}, Classes = { "ConfigBorder" }};
private readonly int _oldCount; private readonly int _oldCount;
private readonly Type _elementType; private readonly Type _elementType;
private readonly StackPanel _panel = new(); private readonly StackPanel _panel = new();
@@ -232,7 +235,7 @@ public sealed class ArrayUnitConfigControl : Border, IConfigControl
{ {
var itemPanel = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 2 }; var itemPanel = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 2 };
var control = ConfigControlHelper.GetConfigControl(_itemControls.Count.ToString(), value); var control = ConfigControlHelper.GetConfigControl(_itemControls.Count.ToString(), value);
var removeButton = new Button { Content = "Remove", Classes = { "ConfigBorder" }}; var removeButton = new Button { Content = new Label(){ Content = "Remove" }, Classes = { "ConfigBorder" }};
removeButton.Click += (_, _) => removeButton.Click += (_, _) =>
{ {

View File

@@ -1,6 +1,7 @@
using System; using System;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using Nebula.Launcher.ServerListProviders; using Nebula.Launcher.ServerListProviders;
using Nebula.Launcher.Services;
using Nebula.Launcher.ViewModels.Pages; using Nebula.Launcher.ViewModels.Pages;
using Nebula.Launcher.Views.Pages; using Nebula.Launcher.Views.Pages;
using Nebula.Shared.Services; using Nebula.Shared.Services;
@@ -30,7 +31,7 @@ public partial class AddFavoriteViewModel : PopupViewModelBase
[GenerateProperty] private ServerOverviewModel ServerOverviewModel { get; } [GenerateProperty] private ServerOverviewModel ServerOverviewModel { get; }
[GenerateProperty] private DebugService DebugService { get; } [GenerateProperty] private DebugService DebugService { get; }
[GenerateProperty] private FavoriteServerListProvider FavoriteServerListProvider { get; } [GenerateProperty] private FavoriteServerListProvider FavoriteServerListProvider { get; }
public override string Title => "Add to favorite"; public override string Title => LocalisationService.GetString("popup-add-favorite");
public override bool IsClosable => true; public override bool IsClosable => true;
[ObservableProperty] private string _ipInput; [ObservableProperty] private string _ipInput;

View File

@@ -1,4 +1,5 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using Nebula.Launcher.Services;
using Nebula.Launcher.Views.Popup; using Nebula.Launcher.Views.Popup;
using Nebula.Shared.Services; using Nebula.Shared.Services;
@@ -10,7 +11,7 @@ public sealed partial class EditServerNameViewModel : PopupViewModelBase
{ {
[GenerateProperty] public override PopupMessageService PopupMessageService { get; } [GenerateProperty] public override PopupMessageService PopupMessageService { get; }
[GenerateProperty] public ConfigurationService ConfigurationService { get; } [GenerateProperty] public ConfigurationService ConfigurationService { get; }
public override string Title => "Edit server name"; public override string Title => LocalisationService.GetString("popup-edit-name");
public override bool IsClosable => true; public override bool IsClosable => true;
[ObservableProperty] private string _ipInput; [ObservableProperty] private string _ipInput;

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using Nebula.Launcher.Services;
using Nebula.Launcher.Views.Popup; using Nebula.Launcher.Views.Popup;
using Nebula.Shared.Services; using Nebula.Shared.Services;
@@ -10,7 +11,7 @@ namespace Nebula.Launcher.ViewModels.Popup;
public sealed partial class ExceptionListViewModel : PopupViewModelBase public sealed partial class ExceptionListViewModel : PopupViewModelBase
{ {
[GenerateProperty] public override PopupMessageService PopupMessageService { get; } [GenerateProperty] public override PopupMessageService PopupMessageService { get; }
public override string Title => "Exception was thrown"; public override string Title => LocalisationService.GetString("popup-exception");
public override bool IsClosable => true; public override bool IsClosable => true;
public ObservableCollection<Exception> Errors { get; } = new(); public ObservableCollection<Exception> Errors { get; } = new();

View File

@@ -1,4 +1,5 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using Nebula.Launcher.Services;
using Nebula.Launcher.Views.Popup; using Nebula.Launcher.Views.Popup;
using Nebula.Shared.Services; using Nebula.Shared.Services;
@@ -12,7 +13,7 @@ public partial class InfoPopupViewModel : PopupViewModelBase
[ObservableProperty] private string _infoText = "Test"; [ObservableProperty] private string _infoText = "Test";
public override string Title => "Info"; public override string Title => LocalisationService.GetString("popup-information");
public bool IsInfoClosable { get; set; } = true; public bool IsInfoClosable { get; set; } = true;
public override bool IsClosable => IsInfoClosable; public override bool IsClosable => IsInfoClosable;

View File

@@ -1,4 +1,5 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using Nebula.Launcher.Services;
using Nebula.Launcher.Views.Popup; using Nebula.Launcher.Views.Popup;
using Nebula.Shared.Models; using Nebula.Shared.Models;
using Nebula.Shared.Services; using Nebula.Shared.Services;
@@ -16,7 +17,7 @@ public sealed partial class LoadingContextViewModel : PopupViewModelBase, ILoadi
[ObservableProperty] private int _resolvedJobs; [ObservableProperty] private int _resolvedJobs;
public string LoadingName { get; set; } = "Loading..."; public string LoadingName { get; set; } = LocalisationService.GetString("popup-loading");
public bool IsCancellable { get; set; } = true; public bool IsCancellable { get; set; } = true;
public override bool IsClosable => false; public override bool IsClosable => false;

View File

@@ -1,4 +1,5 @@
using System; using System;
using Nebula.Launcher.Services;
using Nebula.Launcher.Views.Popup; using Nebula.Launcher.Views.Popup;
using Nebula.Shared.Services; using Nebula.Shared.Services;
@@ -24,6 +25,6 @@ public partial class TfaViewModel : PopupViewModelBase
} }
[GenerateProperty] public override PopupMessageService PopupMessageService { get; } [GenerateProperty] public override PopupMessageService PopupMessageService { get; }
public override string Title => "2fa"; public override string Title => LocalisationService.GetString("popup-twofa");
public override bool IsClosable => true; public override bool IsClosable => true;
} }

View File

@@ -5,6 +5,7 @@
x:Class="Nebula.Launcher.Views.Pages.AccountInfoView" x:Class="Nebula.Launcher.Views.Pages.AccountInfoView"
x:DataType="pages:AccountInfoViewModel" x:DataType="pages:AccountInfoViewModel"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:customControls="clr-namespace:Nebula.Launcher.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="clr-namespace:Nebula.Launcher.ViewModels.Pages" xmlns:pages="clr-namespace:Nebula.Launcher.ViewModels.Pages"
@@ -28,7 +29,7 @@
<GradientStop Color="#292222" Offset="1.0" /> <GradientStop Color="#292222" Offset="1.0" />
</LinearGradientBrush> </LinearGradientBrush>
</Border.Background> </Border.Background>
<Label HorizontalAlignment="Center">Profiles:</Label> <customControls:LocalizedLabel HorizontalAlignment="Center" LocalId="account-profiles"/>
</Border> </Border>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ItemsControl <ItemsControl
@@ -59,17 +60,13 @@
Command="{Binding OnSelect}" Command="{Binding OnSelect}"
CornerRadius="0,0,0,10" CornerRadius="0,0,0,10"
Padding="5"> Padding="5">
<Label> <customControls:LocalizedLabel LocalId="account-profile-select"/>
Select
</Label>
</Button> </Button>
<Button <Button
Command="{Binding OnDelete}" Command="{Binding OnDelete}"
CornerRadius="0,10,0,0" CornerRadius="0,10,0,0"
Padding="5"> Padding="5">
<Label> <customControls:LocalizedLabel LocalId="account-profile-delete"/>
Delete
</Label>
</Button> </Button>
</StackPanel> </StackPanel>
</Panel> </Panel>
@@ -108,27 +105,21 @@
Command="{Binding DoCurrentAuth}" Command="{Binding DoCurrentAuth}"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"> HorizontalContentAlignment="Center">
<Label>Retry previous auth</Label> <customControls:LocalizedLabel LocalId="account-auth-retry"/>
</Button> </Button>
</Border> </Border>
<Label HorizontalAlignment="Center">Or try another account</Label> <customControls:LocalizedLabel HorizontalAlignment="Center" LocalId="account-auth-try-another"/>
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center"> <customControls:LocalizedLabel VerticalAlignment="Center" LocalId="account-auth-login"/>
Login:
</Label>
<TextBox Text="{Binding CurrentLogin}" MinWidth="200" /> <TextBox Text="{Binding CurrentLogin}" MinWidth="200" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Label HorizontalAlignment="Left" VerticalAlignment="Center"> <customControls:LocalizedLabel HorizontalAlignment="Left" VerticalAlignment="Center" LocalId="account-auth-password"/>
Password:
</Label>
<TextBox PasswordChar="#" MinWidth="200" Text="{Binding CurrentPassword}" /> <TextBox PasswordChar="#" MinWidth="200" Text="{Binding CurrentPassword}" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center"> <customControls:LocalizedLabel VerticalAlignment="Center" LocalId="account-auth-server"/>
Auth server:
</Label>
<Button Command="{Binding ExpandAuthUrlCommand}" VerticalAlignment="Stretch"> <Button Command="{Binding ExpandAuthUrlCommand}" VerticalAlignment="Stretch">
<Label>+</Label> <Label>+</Label>
</Button> </Button>
@@ -161,7 +152,7 @@
Command="{Binding DoAuth}" Command="{Binding DoAuth}"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"> HorizontalContentAlignment="Center">
<Label>Auth</Label> <customControls:LocalizedLabel LocalId="account-auth-button"/>
</Button> </Button>
</Border> </Border>
<Border BoxShadow="{StaticResource DefaultShadow}"> <Border BoxShadow="{StaticResource DefaultShadow}">
@@ -169,7 +160,7 @@
Command="{Binding SaveProfileCommand}" Command="{Binding SaveProfileCommand}"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"> HorizontalContentAlignment="Center">
<Label>Save profile</Label> <customControls:LocalizedLabel LocalId="account-auth-save"/>
</Button> </Button>
</Border> </Border>
<Button Command="{Binding ExpandAuthViewCommand}" HorizontalAlignment="Right"> <Button Command="{Binding ExpandAuthViewCommand}" HorizontalAlignment="Right">
@@ -186,7 +177,7 @@
Path="/Assets/svg/user.svg" /> Path="/Assets/svg/user.svg" />
<Label> <Label>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal"> <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<TextBlock>Hello,</TextBlock> <customControls:LocalizedLabel LocalId="account-auth-hello"/>
<TextBlock Text="{Binding CurrentLogin}" /> <TextBlock Text="{Binding CurrentLogin}" />
</StackPanel> </StackPanel>
</Label> </Label>
@@ -197,12 +188,12 @@
Spacing="5"> Spacing="5">
<Border BoxShadow="{StaticResource DefaultShadow}"> <Border BoxShadow="{StaticResource DefaultShadow}">
<Button Command="{Binding Logout}"> <Button Command="{Binding Logout}">
<Label>Logout</Label> <customControls:LocalizedLabel LocalId="account-auth-logout"/>
</Button> </Button>
</Border> </Border>
<Border BoxShadow="{StaticResource DefaultShadow}"> <Border BoxShadow="{StaticResource DefaultShadow}">
<Button Command="{Binding SaveProfileCommand}"> <Button Command="{Binding SaveProfileCommand}">
<Label>Save profile</Label> <customControls:LocalizedLabel LocalId="account-auth-save"/>
</Button> </Button>
</Border> </Border>
</StackPanel> </StackPanel>

View File

@@ -3,6 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="clr-namespace:Nebula.Launcher.ViewModels.Pages" xmlns:pages="clr-namespace:Nebula.Launcher.ViewModels.Pages"
xmlns:customControls="clr-namespace:Nebula.Launcher.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Nebula.Launcher.Views.Pages.ConfigurationView" x:Class="Nebula.Launcher.Views.Pages.ConfigurationView"
x:DataType="pages:ConfigurationViewModel"> x:DataType="pages:ConfigurationViewModel">
@@ -29,7 +30,7 @@
Padding="5" Padding="5"
Margin="5" Margin="5"
Command="{Binding InvokeUpdateConfiguration}"> Command="{Binding InvokeUpdateConfiguration}">
Save <customControls:LocalizedLabel LocalId="config-save"/>
</Button> </Button>
<Button <Button
Classes="ConfigBorder" Classes="ConfigBorder"
@@ -38,7 +39,7 @@
Padding="5" Padding="5"
Margin="5" Margin="5"
Command="{Binding ResetConfig}"> Command="{Binding ResetConfig}">
Reset to default <customControls:LocalizedLabel LocalId="config-reset"/>
</Button> </Button>
<Button <Button
Classes="ConfigBorder" Classes="ConfigBorder"
@@ -47,7 +48,7 @@
Padding="5" Padding="5"
Margin="5" Margin="5"
Command="{Binding OpenDataFolder}"> Command="{Binding OpenDataFolder}">
Open Data path <customControls:LocalizedLabel LocalId="config-open-data"/>
</Button> </Button>
<Button <Button
@@ -57,7 +58,7 @@
Padding="5" Padding="5"
Margin="5" Margin="5"
Command="{Binding ExportLogs}"> Command="{Binding ExportLogs}">
Export logs <customControls:LocalizedLabel LocalId="config-export-logs"/>
</Button> </Button>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@@ -51,8 +51,8 @@
VerticalAlignment="Bottom" VerticalAlignment="Bottom"
IsVisible="{Binding IsFilterVisible}"> IsVisible="{Binding IsFilterVisible}">
<StackPanel Orientation="Vertical" Spacing="2" Margin="15"> <StackPanel Orientation="Vertical" Spacing="2" Margin="15">
<controls:FilterBox Name="EssentialFilters" FilterBoxName="Roleplay" FilterCommand="{Binding OnFilterChanged}"/> <controls:FilterBox Name="EssentialFilters" FilterBoxName="filter-roleplay" FilterCommand="{Binding OnFilterChanged}"/>
<controls:FilterBox Name="LanguageFilters" FilterBoxName="Language" FilterCommand="{Binding OnFilterChanged}"/> <controls:FilterBox Name="LanguageFilters" FilterBoxName="filter-language" FilterCommand="{Binding OnFilterChanged}"/>
</StackPanel> </StackPanel>
</Border> </Border>

View File

@@ -8,6 +8,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup" xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup"
xmlns:customControls="clr-namespace:Nebula.Launcher.Controls"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.DataContext> <Design.DataContext>
<popup:AddFavoriteViewModel /> <popup:AddFavoriteViewModel />
@@ -18,7 +19,7 @@
</Border> </Border>
<Border Background="{StaticResource DefaultSelected}" BoxShadow="{StaticResource DefaultShadow}"> <Border Background="{StaticResource DefaultSelected}" BoxShadow="{StaticResource DefaultShadow}">
<Button Command="{Binding OnEnter}" HorizontalAlignment="Stretch"> <Button Command="{Binding OnEnter}" HorizontalAlignment="Stretch">
<Label HorizontalAlignment="Center">Add</Label> <customControls:LocalizedLabel HorizontalAlignment="Center" LocalId="favorite-add"/>
</Button> </Button>
</Border> </Border>
<Label> <Label>

View File

@@ -3,6 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup" xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup"
xmlns:customControls="clr-namespace:Nebula.Launcher.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Nebula.Launcher.Views.Popup.EditServerNameView" x:Class="Nebula.Launcher.Views.Popup.EditServerNameView"
x:DataType="popup:EditServerNameViewModel"> x:DataType="popup:EditServerNameViewModel">
@@ -19,7 +20,7 @@
</Border> </Border>
<Border Background="{StaticResource DefaultSelected}" BoxShadow="{StaticResource DefaultShadow}"> <Border Background="{StaticResource DefaultSelected}" BoxShadow="{StaticResource DefaultShadow}">
<Button Command="{Binding OnEnter}" HorizontalAlignment="Stretch"> <Button Command="{Binding OnEnter}" HorizontalAlignment="Stretch">
<Label HorizontalAlignment="Center">Set name</Label> <customControls:LocalizedLabel HorizontalAlignment="Center" LocalId="servername-set"/>
</Button> </Button>
</Border> </Border>
</StackPanel> </StackPanel>

View File

@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:customControls="clr-namespace:Nebula.Launcher.Controls"
xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup" xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Nebula.Launcher.Views.Popup.LoadingContextView" x:Class="Nebula.Launcher.Views.Popup.LoadingContextView"
@@ -29,7 +30,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
Command="{Binding Cancel}" Command="{Binding Cancel}"
IsVisible="{Binding IsCancellable}"> IsVisible="{Binding IsCancellable}">
<Label>Cancel</Label> <customControls:LocalizedLabel LocalId="task-cancel"/>
</Button> </Button>
</Panel> </Panel>
</StackPanel> </StackPanel>

View File

@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:customControls="clr-namespace:Nebula.Launcher.Controls"
xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup" xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Nebula.Launcher.Views.Popup.TfaView"> x:Class="Nebula.Launcher.Views.Popup.TfaView">
@@ -9,7 +10,7 @@
<popup:TfaViewModel /> <popup:TfaViewModel />
</Design.DataContext> </Design.DataContext>
<StackPanel HorizontalAlignment="Stretch" Spacing="25" VerticalAlignment="Center"> <StackPanel HorizontalAlignment="Stretch" Spacing="25" VerticalAlignment="Center">
<Label HorizontalAlignment="Center">You have two-factor authentication enabled. Please enter the code.</Label> <customControls:LocalizedLabel HorizontalAlignment="Center" LocalId="twofa-enabled"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10" x:Name="TContainer"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10" x:Name="TContainer">
<Border BoxShadow="{StaticResource DefaultShadow}"> <Border BoxShadow="{StaticResource DefaultShadow}">
<TextBox MaxLength="1"/> <TextBox MaxLength="1"/>
@@ -32,7 +33,7 @@
</StackPanel> </StackPanel>
<Border BoxShadow="{StaticResource DefaultShadow}" Background="{StaticResource DefaultSelected}" HorizontalAlignment="Center"> <Border BoxShadow="{StaticResource DefaultShadow}" Background="{StaticResource DefaultSelected}" HorizontalAlignment="Center">
<Button Click="Button_OnClick"> <Button Click="Button_OnClick">
<Label HorizontalAlignment="Center" Margin="15,5,15,5">OK</Label> <customControls:LocalizedLabel HorizontalAlignment="Center" Margin="15,5,15,5" LocalId="twofa-set"/>
</Button> </Button>
</Border> </Border>
</StackPanel> </StackPanel>