ava: Generate Locale menu automatically (#4243)
Currently in `MenuMainBarView.axaml` we list all available languages and hardcode the language name with the language key. It's a bit bad beause if we want to add a new language, we have to edit the `csproj` and the `axaml` with the translated language name and the language code. I've put all translations in their respective locale files, add code into `MainMenuBarView` constructor to generate the menu automatically. Now we just have to edit the `csproj` if we want to add a new language.
This commit is contained in:
parent
5e0f8e8738
commit
2355c2af62
20 changed files with 87 additions and 77 deletions
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Deutsch",
|
||||||
"MenuBarFileOpenApplet": "Applet öffnen",
|
"MenuBarFileOpenApplet": "Applet öffnen",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Öffnet das Mii Editor Applet im Standalone Modus",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Öffnet das Mii Editor Applet im Standalone Modus",
|
||||||
"SettingsTabInputDirectMouseAccess": "Direkter Mauszugriff",
|
"SettingsTabInputDirectMouseAccess": "Direkter Mauszugriff",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Ελληνικά",
|
||||||
"MenuBarFileOpenApplet": "Άνοιγμα Applet",
|
"MenuBarFileOpenApplet": "Άνοιγμα Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
|
||||||
"SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού",
|
"SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "English (US)",
|
||||||
"MenuBarFileOpenApplet": "Open Applet",
|
"MenuBarFileOpenApplet": "Open Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Open Mii Editor Applet in Standalone mode",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Open Mii Editor Applet in Standalone mode",
|
||||||
"SettingsTabInputDirectMouseAccess": "Direct Mouse Access",
|
"SettingsTabInputDirectMouseAccess": "Direct Mouse Access",
|
||||||
|
@ -611,3 +612,4 @@
|
||||||
"Recover": "Recover",
|
"Recover": "Recover",
|
||||||
"UserProfilesRecoverHeading" : "Saves were found for the following accounts"
|
"UserProfilesRecoverHeading" : "Saves were found for the following accounts"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Español (ES)",
|
||||||
"MenuBarFileOpenApplet": "Abrir applet",
|
"MenuBarFileOpenApplet": "Abrir applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abre el editor de Mii en modo autónomo",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abre el editor de Mii en modo autónomo",
|
||||||
"SettingsTabInputDirectMouseAccess": "Acceso directo al ratón",
|
"SettingsTabInputDirectMouseAccess": "Acceso directo al ratón",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Français",
|
||||||
"MenuBarFileOpenApplet": "Ouvrir Applet",
|
"MenuBarFileOpenApplet": "Ouvrir Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Ouvrir l'Applet Mii Editor en mode Standalone",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Ouvrir l'Applet Mii Editor en mode Standalone",
|
||||||
"SettingsTabInputDirectMouseAccess": "Accès direct à la souris",
|
"SettingsTabInputDirectMouseAccess": "Accès direct à la souris",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Italiano",
|
||||||
"MenuBarFileOpenApplet": "Apri Applet",
|
"MenuBarFileOpenApplet": "Apri Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Apri l'applet Mii Editor in modalità Standalone",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Apri l'applet Mii Editor in modalità Standalone",
|
||||||
"SettingsTabInputDirectMouseAccess": "Accesso diretto al mouse",
|
"SettingsTabInputDirectMouseAccess": "Accesso diretto al mouse",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "日本語",
|
||||||
"MenuBarFileOpenApplet": "アプレットを開く",
|
"MenuBarFileOpenApplet": "アプレットを開く",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
|
||||||
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
|
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "한국어",
|
||||||
"MenuBarFileOpenApplet": "애플릿 열기",
|
"MenuBarFileOpenApplet": "애플릿 열기",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드에서 Mii 편집기 애플릿 열기",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드에서 Mii 편집기 애플릿 열기",
|
||||||
"SettingsTabInputDirectMouseAccess": "직접 마우스 접속",
|
"SettingsTabInputDirectMouseAccess": "직접 마우스 접속",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Polski",
|
||||||
"MenuBarFileOpenApplet": "Otwórz Aplet",
|
"MenuBarFileOpenApplet": "Otwórz Aplet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Otwórz aplet Mii Editor w trybie Indywidualnym",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Otwórz aplet Mii Editor w trybie Indywidualnym",
|
||||||
"SettingsTabInputDirectMouseAccess": "Bezpośredni Dostęp do Myszy",
|
"SettingsTabInputDirectMouseAccess": "Bezpośredni Dostęp do Myszy",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Português (BR)",
|
||||||
"MenuBarFileOpenApplet": "Abrir Applet",
|
"MenuBarFileOpenApplet": "Abrir Applet",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abrir editor Mii em modo avulso",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abrir editor Mii em modo avulso",
|
||||||
"SettingsTabInputDirectMouseAccess": "Acesso direto ao mouse",
|
"SettingsTabInputDirectMouseAccess": "Acesso direto ao mouse",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Русский",
|
||||||
"MenuBarFileOpenApplet": "Открыть апплет",
|
"MenuBarFileOpenApplet": "Открыть апплет",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открыть апплет Mii Editor в автономном режиме.",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открыть апплет Mii Editor в автономном режиме.",
|
||||||
"SettingsTabInputDirectMouseAccess": "Прямой доступ с помощью мыши",
|
"SettingsTabInputDirectMouseAccess": "Прямой доступ с помощью мыши",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Türkçe",
|
||||||
"MenuBarFileOpenApplet": "Applet'i Aç",
|
"MenuBarFileOpenApplet": "Applet'i Aç",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Mii Editör Applet'ini Bağımsız Mod'da Aç",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Mii Editör Applet'ini Bağımsız Mod'da Aç",
|
||||||
"SettingsTabInputDirectMouseAccess": "Doğrudan Mouse Erişimi",
|
"SettingsTabInputDirectMouseAccess": "Doğrudan Mouse Erişimi",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "Yкраїнська",
|
||||||
"MenuBarFileOpenApplet": "Відкрити аплет",
|
"MenuBarFileOpenApplet": "Відкрити аплет",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрийте аплет Mii Editor в автономному режимі",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрийте аплет Mii Editor в автономному режимі",
|
||||||
"SettingsTabInputDirectMouseAccess": "Прямий доступ мишею",
|
"SettingsTabInputDirectMouseAccess": "Прямий доступ мишею",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "简体中文",
|
||||||
"MenuBarFileOpenApplet": "打开小程序",
|
"MenuBarFileOpenApplet": "打开小程序",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打开独立的 Mii 小程序",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打开独立的 Mii 小程序",
|
||||||
"SettingsTabInputDirectMouseAccess": "直通鼠标操作",
|
"SettingsTabInputDirectMouseAccess": "直通鼠标操作",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"Language": "繁體中文",
|
||||||
"MenuBarFileOpenApplet": "打開小程式",
|
"MenuBarFileOpenApplet": "打開小程式",
|
||||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打開獨立的 Mii 小程式",
|
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打開獨立的 Mii 小程式",
|
||||||
"SettingsTabInputDirectMouseAccess": "直通滑鼠操作",
|
"SettingsTabInputDirectMouseAccess": "直通滑鼠操作",
|
||||||
|
|
|
@ -6,7 +6,6 @@ using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Common.Locale
|
namespace Ryujinx.Ava.Common.Locale
|
||||||
{
|
{
|
||||||
|
|
|
@ -145,6 +145,7 @@
|
||||||
<None Remove="Assets\Locales\pt_BR.json" />
|
<None Remove="Assets\Locales\pt_BR.json" />
|
||||||
<None Remove="Assets\Locales\ru_RU.json" />
|
<None Remove="Assets\Locales\ru_RU.json" />
|
||||||
<None Remove="Assets\Locales\tr_TR.json" />
|
<None Remove="Assets\Locales\tr_TR.json" />
|
||||||
|
<None Remove="Assets\Locales\uk_UA.json" />
|
||||||
<None Remove="Assets\Locales\zh_CN.json" />
|
<None Remove="Assets\Locales\zh_CN.json" />
|
||||||
<None Remove="Assets\Locales\zh_TW.json" />
|
<None Remove="Assets\Locales\zh_TW.json" />
|
||||||
<None Remove="Assets\Styles\Styles.xaml" />
|
<None Remove="Assets\Styles\Styles.xaml" />
|
||||||
|
@ -165,6 +166,7 @@
|
||||||
<EmbeddedResource Include="Assets\Locales\pt_BR.json" />
|
<EmbeddedResource Include="Assets\Locales\pt_BR.json" />
|
||||||
<EmbeddedResource Include="Assets\Locales\ru_RU.json" />
|
<EmbeddedResource Include="Assets\Locales\ru_RU.json" />
|
||||||
<EmbeddedResource Include="Assets\Locales\tr_TR.json" />
|
<EmbeddedResource Include="Assets\Locales\tr_TR.json" />
|
||||||
|
<EmbeddedResource Include="Assets\Locales\uk_UA.json" />
|
||||||
<EmbeddedResource Include="Assets\Locales\zh_CN.json" />
|
<EmbeddedResource Include="Assets\Locales\zh_CN.json" />
|
||||||
<EmbeddedResource Include="Assets\Locales\zh_TW.json" />
|
<EmbeddedResource Include="Assets\Locales\zh_TW.json" />
|
||||||
<EmbeddedResource Include="Assets\Styles\Styles.xaml" />
|
<EmbeddedResource Include="Assets\Styles\Styles.xaml" />
|
||||||
|
|
|
@ -77,63 +77,7 @@
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem Header="{locale:Locale MenuBarOptionsChangeLanguage}">
|
<MenuItem Name="ChangeLanguageMenuItem" Header="{locale:Locale MenuBarOptionsChangeLanguage}">
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="de_DE"
|
|
||||||
Header="Deutsch" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="en_US"
|
|
||||||
Header="English (US)" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="es_ES"
|
|
||||||
Header="Español (ES)" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="fr_FR"
|
|
||||||
Header="Français" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="it_IT"
|
|
||||||
Header="Italiano" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="pt_BR"
|
|
||||||
Header="Português (BR)" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="tr_TR"
|
|
||||||
Header="Türkçe" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="el_GR"
|
|
||||||
Header="Ελληνικά" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="pl_PL"
|
|
||||||
Header="Polski" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="ru_RU"
|
|
||||||
Header="Русский" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="zh_CN"
|
|
||||||
Header="简体中文" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="zh_TW"
|
|
||||||
Header="繁體中文" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="ja_JP"
|
|
||||||
Header="日本語" />
|
|
||||||
<MenuItem
|
|
||||||
Command="{ReflectionBinding ChangeLanguage}"
|
|
||||||
CommandParameter="ko_KR"
|
|
||||||
Header="한국어" />
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
|
||||||
using Ryujinx.Ava.UI.Windows;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using LibHac.FsSystem;
|
using LibHac.FsSystem;
|
||||||
using LibHac.Ncm;
|
using LibHac.Ncm;
|
||||||
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using Ryujinx.Ava.UI.Windows;
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Views.Main
|
namespace Ryujinx.Ava.UI.Views.Main
|
||||||
{
|
{
|
||||||
|
@ -19,13 +26,47 @@ namespace Ryujinx.Ava.UI.Views.Main
|
||||||
public MainMenuBarView()
|
public MainMenuBarView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
List<MenuItem> menuItems = new();
|
||||||
|
|
||||||
|
string localePath = "Ryujinx.Ava/Assets/Locales";
|
||||||
|
string localeExt = ".json";
|
||||||
|
|
||||||
|
string[] localesPath = EmbeddedResources.GetAllAvailableResources(localePath, localeExt);
|
||||||
|
|
||||||
|
Array.Sort(localesPath);
|
||||||
|
|
||||||
|
foreach (string locale in localesPath)
|
||||||
|
{
|
||||||
|
string languageCode = Path.GetFileNameWithoutExtension(locale).Split('.').Last();
|
||||||
|
string languageJson = EmbeddedResources.ReadAllText($"{localePath}/{languageCode}{localeExt}");
|
||||||
|
var strings = JsonHelper.Deserialize<Dictionary<string, string>>(languageJson);
|
||||||
|
|
||||||
|
if (!strings.TryGetValue("Language", out string languageName))
|
||||||
|
{
|
||||||
|
languageName = languageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem menuItem = new()
|
||||||
|
{
|
||||||
|
Header = languageName,
|
||||||
|
Command = MiniCommand.Create(() =>
|
||||||
|
{
|
||||||
|
ViewModel.ChangeLanguage(languageCode);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
menuItems.Add(menuItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangeLanguageMenuItem.Items = menuItems.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnAttachedToVisualTree(e);
|
base.OnAttachedToVisualTree(e);
|
||||||
|
|
||||||
if (this.VisualRoot is MainWindow window)
|
if (VisualRoot is MainWindow window)
|
||||||
{
|
{
|
||||||
Window = window;
|
Window = window;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -127,6 +128,13 @@ namespace Ryujinx.Common
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string[] GetAllAvailableResources(string path, string ext = "")
|
||||||
|
{
|
||||||
|
return ResolveManifestPath(path).Item1.GetManifestResourceNames()
|
||||||
|
.Where(r => r.EndsWith(ext))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
private static (Assembly, string) ResolveManifestPath(string filename)
|
private static (Assembly, string) ResolveManifestPath(string filename)
|
||||||
{
|
{
|
||||||
var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
|
var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
Loading…
Reference in a new issue