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:
Ac_K 2023-01-11 01:29:22 +01:00 committed by GitHub
parent 5e0f8e8738
commit 2355c2af62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 87 additions and 77 deletions

View file

@ -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",

View file

@ -1,4 +1,5 @@
{ {
"Language": "Ελληνικά",
"MenuBarFileOpenApplet": "Άνοιγμα Applet", "MenuBarFileOpenApplet": "Άνοιγμα Applet",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
"SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού", "SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού",

View file

@ -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"
} }

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -1,4 +1,5 @@
{ {
"Language": "日本語",
"MenuBarFileOpenApplet": "アプレットを開く", "MenuBarFileOpenApplet": "アプレットを開く",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス", "SettingsTabInputDirectMouseAccess": "マウス直接アクセス",

View file

@ -1,4 +1,5 @@
{ {
"Language": "한국어",
"MenuBarFileOpenApplet": "애플릿 열기", "MenuBarFileOpenApplet": "애플릿 열기",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드에서 Mii 편집기 애플릿 열기", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드에서 Mii 편집기 애플릿 열기",
"SettingsTabInputDirectMouseAccess": "직접 마우스 접속", "SettingsTabInputDirectMouseAccess": "직접 마우스 접속",

View file

@ -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",

View file

@ -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",

View file

@ -1,4 +1,5 @@
{ {
"Language": "Русский",
"MenuBarFileOpenApplet": "Открыть апплет", "MenuBarFileOpenApplet": "Открыть апплет",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открыть апплет Mii Editor в автономном режиме.", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открыть апплет Mii Editor в автономном режиме.",
"SettingsTabInputDirectMouseAccess": "Прямой доступ с помощью мыши", "SettingsTabInputDirectMouseAccess": "Прямой доступ с помощью мыши",

View file

@ -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",

View file

@ -1,4 +1,5 @@
{ {
"Language": "Yкраїнська",
"MenuBarFileOpenApplet": "Відкрити аплет", "MenuBarFileOpenApplet": "Відкрити аплет",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрийте аплет Mii Editor в автономному режимі", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "Відкрийте аплет Mii Editor в автономному режимі",
"SettingsTabInputDirectMouseAccess": "Прямий доступ мишею", "SettingsTabInputDirectMouseAccess": "Прямий доступ мишею",

View file

@ -1,4 +1,5 @@
{ {
"Language": "简体中文",
"MenuBarFileOpenApplet": "打开小程序", "MenuBarFileOpenApplet": "打开小程序",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打开独立的 Mii 小程序", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "打开独立的 Mii 小程序",
"SettingsTabInputDirectMouseAccess": "直通鼠标操作", "SettingsTabInputDirectMouseAccess": "直通鼠标操作",

View file

@ -1,4 +1,5 @@
{ {
"Language": "繁體中文",
"MenuBarFileOpenApplet": "打開小程式", "MenuBarFileOpenApplet": "打開小程式",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "打開獨立的 Mii 小程式", "MenuBarFileOpenAppletOpenMiiAppletToolTip": "打開獨立的 Mii 小程式",
"SettingsTabInputDirectMouseAccess": "直通滑鼠操作", "SettingsTabInputDirectMouseAccess": "直通滑鼠操作",

View file

@ -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
{ {

View file

@ -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" />

View file

@ -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

View file

@ -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;
} }

View file

@ -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);