From 223f20868aa089db8c431742d1d8170cd8c8178e Mon Sep 17 00:00:00 2001 From: _Neo_ Date: Sun, 14 Jun 2026 19:47:20 +0000 Subject: [PATCH] =?UTF-8?q?UI:=20File=20Menu=20=E2=86=92=20General=20Impro?= =?UTF-8?q?vements=20(#127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ayyyy, welcome to the UI: File Menu → General Improvements PR! Wooo, we progressing smoothly! This PR introduces small visual and "feature" improvements to the `File` menu. ### LOCALISATION: * **Fractured:** More locales: * `Dialog_ContentLoading.json` - content loading dialogs (Updates/DLC) * `Dialog_FileTypeAssociations` - file association dialogs * `Dialog_FileMenu` - File menu dialog strings (complements `MenuBar_File.json`) * **Added:** Additional entires to `Error.json` * **Populated:** `MenuBar_File.json` ### FILE MENU: * **Added:** Keyboard shortcuts to `Load Application` and `Load Unpacked Game` * Cmd + O/Ctrl + O and Cmd + Shift + O/Ctrl + Shift + O for macOS and other OS, respectively. * While many users rely on autoloaded game directories, manually opening content remains a common workflow (for those that don't rely on autoload directories). * **Merged:** `Load Title Updates` and `Load DLC` → `Load Updates/DLC` * Both actions follow the same workflow: selecting one or more directories and allowing Ryujinx to load the content. * To reduce redundancy, they have been consolidated into a single menu item that loads both Updates and DLC simultaneously, mirroring the behavior of the existing autoload functionality. * As part of this change, Title Updates has been simplified to Updates for consistency with the rest of the UI. The remaining reference in the Game List context menu has also been updated from `Manage Title Updates` to `Manage Updates`. * **Added/Updated:** File picker titles for content loading actions * `Load Application`: Select a Switch application file to load * `Load Unpacked Game`: Select a folder containing an unpacked Switch application to load * `Load Updates/DLC`: Select one or more folders to bulk load updates and DLC from * **Improved:** `Associate File Types` and `Remove File Type Associations` (initially moved to the `File` menu in #42) * These options were previously nested under `Manage File Types` and exposed as `Install File Types` and `Uninstall File Types`. The submenu added unnecessary navigation, while the action names did not clearly communicate their purpose. * The two actions have been replaced with a single dynamic menu item, whose displayed and performed action updates based on the current association state. The respective icons have been added as well (imported namespace Projektanker.Icons to allow for dynamic switching): * Link → `Associate File Types` * Link-Slash →`Remove File Type Associations` * A tooltip has also been added to clarify the action being performed. * This option is only usable when a game is not running (why associate file types when running a game? Play the game!) * **Note:** These options are only available on Windows and Linux. macOS already provides robust per‑file “Open With” handling, so a custom association system isn’t necessary. Support can be added later if needed, but current macOS limitations in Ryujinx prevent certain behaviors; these will be addressed in future PRs. * **Updated:** Menu Icons * Several icons have been updated to better reflect their associated actions and improve consistency throughout the menu: * `Load Updates/DLC...` now uses a single Inbox Tray icon instead of separate Update and DLC icons. * `Open Ryujinx Folder`, `Open Logs Folder`, and `Open Screenshots Folder` now share the same folder icon, as all three actions ultimately open a folder/directory. * `Exit` is now an Exit icon (arrow-right-from-bracket) instead of a Power button. ### OTHER: * **Improved:** `Load Updates/DLC` dialog messages * Existing dialog messages were longer than necessary and included terms such as "missing" updates and "new" DLC. * These messages have been simplified and standardized: * Updates Added: {0} or Updates Removed: {0} * DLC Added: {0} or DLC Removed: {0} _If there are any features or changes that you wish to be implemented, please comment down below and I'll be happy to accommodate!_ A GIGANTIC, ENORMOUSE HUUUUUUGEE thank you to @Babib3l for testing this and ensuring the commands work! WOOOOO!!! Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/127 --- assets/Locales/Dialog_ContentLoading.json | 104 +++ assets/Locales/Dialog_FileMenu.json | 79 ++ .../Locales/Dialog_FileTypeAssociations.json | 104 +++ assets/Locales/Error.json | 50 ++ assets/Locales/MenuBar_File.json | 326 ++++++-- assets/Locales/Root.json | 730 ++++-------------- .../Helpers/FileAssociationHelper.cs | 9 +- src/Ryujinx/Systems/AppHost.cs | 6 +- .../DownloadableContentManagerViewModel.cs | 2 +- .../UI/ViewModels/MainWindowViewModel.cs | 139 +++- .../UI/ViewModels/TitleUpdateViewModel.cs | 2 +- .../UI/Views/Main/MainMenuBarView.axaml | 56 +- .../UI/Views/Main/MainMenuBarView.axaml.cs | 21 - src/Ryujinx/UI/Windows/MainWindow.axaml | 4 + src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 8 +- 15 files changed, 893 insertions(+), 747 deletions(-) create mode 100644 assets/Locales/Dialog_ContentLoading.json create mode 100644 assets/Locales/Dialog_FileMenu.json create mode 100644 assets/Locales/Dialog_FileTypeAssociations.json diff --git a/assets/Locales/Dialog_ContentLoading.json b/assets/Locales/Dialog_ContentLoading.json new file mode 100644 index 000000000..0448b79df --- /dev/null +++ b/assets/Locales/Dialog_ContentLoading.json @@ -0,0 +1,104 @@ +{ + "Locales": [ + { + "ID": "UpdatesAddedMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Updates Added: {0}", + "es_ES": "Actualizaciones Añadidas: {0}", + "fr_FR": "Mises à Jour Ajoutées : {0}", + "he_IL": "", + "it_IT": "Aggiornamenti aggiunti: {0}", + "ja_JP": "", + "ko_KR": "추가된 업데이트: {0}", + "no_NO": "Oppdateringer lagt til: {0}", + "pl_PL": "", + "pt_BR": "Atualizações adicionadas: {0}", + "ru_RU": "Добавлено обновлений: {0}", + "sv_SE": "Tillagda uppdateringar: {0}", + "th_TH": "การอัปเดตที่เพิ่มเข้ามา: {0}", + "tr_TR": "", + "uk_UA": "Додані оновлення: {0}", + "zh_CN": "已添加更新:{0}", + "zh_TW": "已新增更新:{0}" + } + }, + { + "ID": "UpdatesRemovedMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Updates Removed: {0}", + "es_ES": "Actualizaciones Eliminadas: {0}", + "fr_FR": "Mises à Jour Supprimées : {0}", + "he_IL": "", + "it_IT": "Aggiornamenti rimossi: {0}", + "ja_JP": "", + "ko_KR": "제거된 업데이트: {0}", + "no_NO": "Fjernede oppdateringer: {0}", + "pl_PL": "", + "pt_BR": "Atualizações removidas: {0}", + "ru_RU": "Удалено обновлений: {0}", + "sv_SE": "Borttagna uppdateringar: {0}", + "th_TH": "การอัปเดตที่ถูกลบ: {0}", + "tr_TR": "", + "uk_UA": "Видалені оновлення: {0}", + "zh_CN": "已移除更新:{0}", + "zh_TW": "已移除更新:{0}" + } + }, + { + "ID": "DLCAddedMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "DLC Added: {0}", + "es_ES": "DLC Añadidos: {0}", + "fr_FR": "DLC Ajoutés : {0}", + "he_IL": "", + "it_IT": "DLC aggiunti: {0}", + "ja_JP": "", + "ko_KR": "추가된 DLC: {0}", + "no_NO": "DLC lagt til: {0}", + "pl_PL": "", + "pt_BR": "DLC adicionados: {0}", + "ru_RU": "Добавлено DLC: {0}", + "sv_SE": "Tillagda DLC: {0}", + "th_TH": "DLC ที่เพิ่มเข้ามา: {0}", + "tr_TR": "", + "uk_UA": "Додані DLC: {0}", + "zh_CN": "已添加 DLC:{0}", + "zh_TW": "已新增 DLC:{0}" + } + }, + { + "ID": "DLCRemovedMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "DLC Removed: {0}", + "es_ES": "DLC Eliminados: {0}", + "fr_FR": "DLC Supprimés : {0}", + "he_IL": "", + "it_IT": "DLC rimossi: {0}", + "ja_JP": "", + "ko_KR": "제거된 DLC: {0}", + "no_NO": "DLC fjernet: {0}", + "pl_PL": "", + "pt_BR": "DLC removidos: {0}", + "ru_RU": "Удалено DLC: {0}", + "sv_SE": "DLC borttaget: {0}", + "th_TH": "ลบ DLC: {0}", + "tr_TR": "", + "uk_UA": "Видалено DLC: {0}", + "zh_CN": "已移除 DLC:{0}", + "zh_TW": "已移除 DLC:{0}" + } + } + ] +} diff --git a/assets/Locales/Dialog_FileMenu.json b/assets/Locales/Dialog_FileMenu.json new file mode 100644 index 000000000..3c0b345a3 --- /dev/null +++ b/assets/Locales/Dialog_FileMenu.json @@ -0,0 +1,79 @@ +{ + "Locales": [ + { + "ID": "LoadApplicationFromFileFilePickerTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Select a Switch application file to load", + "es_ES": "Selecciona un archivo de aplicación de Switch para cargar", + "fr_FR": "Sélectionnez un fichier d’application Switch à charger", + "he_IL": "", + "it_IT": "Seleziona un file applicazione Switch da caricare", + "ja_JP": "", + "ko_KR": "로드할 Switch 애플리케이션 파일을 선택하세요", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Selecione um arquivo de aplicativo Switch para carregar", + "ru_RU": "Выберите файл приложения Switch для загрузки", + "sv_SE": "Välj en Switch-applikationsfil att läsa in", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть файл застосунку Switch для завантаження", + "zh_CN": "请选择要加载的 Switch 应用程序文件", + "zh_TW": "請選擇要載入的 Switch 應用程式檔案" + } + }, + { + "ID": "LoadUnpackedApplicationFromFolderFilePickerTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Select a folder containing an unpacked Switch application to load", + "es_ES": "Selecciona una carpeta que contenga una aplicación de Switch descomprimida para cargar", + "fr_FR": "Sélectionnez un dossier contenant une application Switch décompressée à charger", + "he_IL": "", + "it_IT": "Seleziona una cartella contenente un’applicazione Switch non compressa da caricare", + "ja_JP": "", + "ko_KR": "압축 해제된 Switch 애플리케이션이 포함된 폴더를 선택하여 로드하세요", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Selecione uma pasta que contenha um aplicativo Switch descompactado para carregar", + "ru_RU": "Выберите папку, содержащую распакованное приложение Switch, для загрузки", + "sv_SE": "Välj en mapp som innehåller en uppackad Switch-applikation att läsa in", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть папку, що містить розпакований застосунок Switch, для завантаження", + "zh_CN": "请选择包含未打包 Switch 应用程序的文件夹以加载", + "zh_TW": "請選擇包含未解壓縮 Switch 應用程式的資料夾以載入" + } + }, + { + "ID": "LoadUpdatesAndDLCFromFolderFilePickerTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Select one or more folders to bulk load updates and DLC from", + "es_ES": "Selecciona una o más carpetas para cargar de forma masiva actualizaciones y DLC", + "fr_FR": "Sélectionnez un ou plusieurs dossiers pour charger en masse des mises à jour et des DLC", + "he_IL": "", + "it_IT": "Seleziona una o più cartelle da cui caricare in blocco aggiornamenti e DLC", + "ja_JP": "", + "ko_KR": "업데이트 및 DLC를 대량으로 로드할 폴더를 하나 이상 선택하세요", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Selecione uma ou mais pastas para carregar em massa atualizações e DLC", + "ru_RU": "Выберите одну или несколько папок для массовой загрузки обновлений и DLC", + "sv_SE": "Välj en eller flera mappar för att massinläsa uppdateringar och DLC", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть одну або кілька папок для масового завантаження оновлень і DLC", + "zh_CN": "请选择一个或多个文件夹以批量加载更新和 DLC", + "zh_TW": "請選擇一個或多個資料夾以批次載入更新與 DLC" + } + } + ] +} diff --git a/assets/Locales/Dialog_FileTypeAssociations.json b/assets/Locales/Dialog_FileTypeAssociations.json new file mode 100644 index 000000000..327ea58de --- /dev/null +++ b/assets/Locales/Dialog_FileTypeAssociations.json @@ -0,0 +1,104 @@ +{ + "Locales": [ + { + "ID": "AssociationSuccessMessage", + "Translations": { + "ar_SA": "تم ربط أنواع الملفات بنجاح.", + "de_DE": "Dateitypen erfolgreich zugeordnet.", + "el_GR": "Οι τύποι αρχείων συσχετίστηκαν με επιτυχία.", + "en_US": "Successfully associated file types.", + "es_ES": "¡Tipos de archivo asociados con éxito.", + "fr_FR": "Types de fichiers associés avec succès.", + "he_IL": "שיוך סוגי הקבצים בוצע בהצלחה.", + "it_IT": "Tipi di file associati con successo.", + "ja_JP": "ファイルの種類の関連付けに成功しました。", + "ko_KR": "파일 형식 연결에 성공했습니다.", + "no_NO": "Filtyper ble tilknyttet.", + "pl_PL": "Pomyślnie powiązano typy plików.", + "pt_BR": "Tipos de arquivo associados com sucesso.", + "ru_RU": "Типы файлов успешно связаны.", + "sv_SE": "Filtyper har kopplats.", + "th_TH": "เชื่อมโยงประเภทไฟล์สำเร็จแล้ว", + "tr_TR": "Dosya türleri başarıyla ilişkilendirildi.", + "uk_UA": "Типи файлів успішно пов’язані.", + "zh_CN": "文件类型关联成功。", + "zh_TW": "檔案類型關聯成功。" + } + }, + { + "ID": "RemoveAssociationSuccessMessage", + "Translations": { + "ar_SA": "تمت إزالة ارتباطات أنواع الملفات بنجاح.", + "de_DE": "Dateitypzuordnungen erfolgreich entfernt.", + "el_GR": "Οι συσχετίσεις τύπων αρχείων αφαιρέθηκαν με επιτυχία.", + "en_US": "Successfully removed file type associations.", + "es_ES": "Asociaciones de tipos de archivo eliminadas con éxito.", + "fr_FR": "Associations de types de fichiers supprimées avec succès.", + "he_IL": "שיוכי סוגי הקבצים הוסרו בהצלחה.", + "it_IT": "Associazioni dei tipi di file rimosse con successo.", + "ja_JP": "ファイルの種類の関連付けの削除に成功しました。", + "ko_KR": "파일 형식 연결이 성공적으로 제거되었습니다.", + "no_NO": "Filtype-tilknytninger ble fjernet.", + "pl_PL": "Pomyślnie usunięto skojarzenia typów plików.", + "pt_BR": "Associações de tipos de arquivo removidas com sucesso.", + "ru_RU": "Связи типов файлов успешно удалены.", + "sv_SE": "Filtypsassociationer har tagits bort.", + "th_TH": "ลบการเชื่อมโยงประเภทไฟล์สำเร็จแล้ว", + "tr_TR": "Dosya türü ilişkilendirmeleri başarıyla kaldırıldı.", + "uk_UA": "Прив’язки типів файлів успішно видалено.", + "zh_CN": "文件类型关联已成功移除。", + "zh_TW": "檔案類型關聯已成功移除。" + } + }, + { + "ID": "AssociationFailedMessage", + "Translations": { + "ar_SA": "فشل ربط أنواع الملفات.", + "de_DE": "Fehler beim Zuordnen der Dateitypen.", + "el_GR": "Απέτυχε η συσχέτιση των τύπων αρχείων.", + "en_US": "Failed to associate file types.", + "es_ES": "No se pudieron asociar los tipos de archivo.", + "fr_FR": "Échec de l’association des types de fichiers.", + "he_IL": "שיוך סוגי הקבצים נכשל.", + "it_IT": "Associazione dei tipi di file non riuscita.", + "ja_JP": "ファイルの種類の関連付けに失敗しました。", + "ko_KR": "파일 형식 연결에 실패했습니다.", + "no_NO": "Klarte ikke å tilknytte filtyper.", + "pl_PL": "Nie udało się powiązać typów plików.", + "pt_BR": "Falha ao associar tipos de arquivo.", + "ru_RU": "Не удалось связать типы файлов.", + "sv_SE": "Det gick inte att koppla filtyper.", + "th_TH": "เชื่อมโยงประเภทไฟล์ไม่สำเร็จ", + "tr_TR": "Dosya türleri ilişkilendirilemedi.", + "uk_UA": "Не вдалося пов’язати типи файлів.", + "zh_CN": "文件类型关联失败。", + "zh_TW": "檔案類型關聯失敗。" + } + }, + { + "ID": "RemoveAssociationFailedMessage", + "Translations": { + "ar_SA": "فشلت إزالة ارتباطات أنواع الملفات.", + "de_DE": "Das Entfernen der Dateitypzuordnungen ist fehlgeschlagen.", + "el_GR": "Η αφαίρεση των συσχετίσεων τύπων αρχείων απέτυχε.", + "en_US": "Failed to remove file type associations.", + "es_ES": "No se pudieron eliminar las asociaciones de tipos de archivo.", + "fr_FR": "Échec de la suppression des associations de types de fichiers.", + "he_IL": "הסרת שיוכי סוגי הקבצים נכשלה.", + "it_IT": "Rimozione delle associazioni dei tipi di file non riuscita.", + "ja_JP": "ファイルの種類の関連付けの削除に失敗しました。", + "ko_KR": "파일 형식 연결 제거에 실패했습니다.", + "no_NO": "Fjerning av filtype-tilknytninger mislyktes.", + "pl_PL": "Nie udało się usunąć skojarzeń typów plików.", + "pt_BR": "Falha ao remover associações de tipos de arquivo.", + "ru_RU": "Не удалось удалить связи типов файлов.", + "sv_SE": "Det gick inte att ta bort filtypsassociationer.", + "th_TH": "ไม่สามารถลบการเชื่อมโยงประเภทไฟล์ได้", + "tr_TR": "Dosya türü ilişkilendirmeleri kaldırılamadı.", + "uk_UA": "Не вдалося видалити прив’язки типів файлів.", + "zh_CN": "文件类型关联移除失败。", + "zh_TW": "無法移除檔案類型關聯。" + } + } + ] +} diff --git a/assets/Locales/Error.json b/assets/Locales/Error.json index 4482d496b..637bc0584 100644 --- a/assets/Locales/Error.json +++ b/assets/Locales/Error.json @@ -1,5 +1,55 @@ { "Locales": [ + { + "ID": "NoApplicationFoundInFile", + "Translations": { + "ar_SA": "", + "de_DE": "Keine Anwendungen in ausgewählter Datei gefunden.", + "el_GR": "", + "en_US": "No applications found in selected file.", + "es_ES": "No se encontraron aplicaciones en el archivo seleccionado.", + "fr_FR": "Aucune application trouvée dans le fichier sélectionné.", + "he_IL": "", + "it_IT": "Nessuna applicazione trovata nel file selezionato.", + "ja_JP": "", + "ko_KR": "선택한 파일에서 앱을 찾을 수 없습니다.", + "no_NO": "Ingen apper ble funnet i valgt fil.", + "pl_PL": "", + "pt_BR": "Nenhum aplicativo encontrado no arquivo selecionado.", + "ru_RU": "Приложений в выбранном файле не найдены", + "sv_SE": "Inga applikationer hittades i vald fil.", + "th_TH": "ไม่พบแอปพลิเคชั่นจากไฟล์ที่เลือก", + "tr_TR": "", + "uk_UA": "У вибраному файлі не знайдено жодних додатків.", + "zh_CN": "未发现应用", + "zh_TW": "未能從已選擇的檔案中找到應用程式。" + } + }, + { + "ID": "NoUnpackedApplicationFoundInFolder", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Please select an unpacked application folder with a valid ExeFS or NSO/NRO.", + "es_ES": "", + "fr_FR": "Veuillez sélectionner un répertoire d’application décompressée contenant un ExeFS valide ou NSO/NRO.", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "Пожалуйста, выберите папку распакованного приложения с корректным ExeFS или NSO/NRO", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "NoKeysFound", "Translations": { diff --git a/assets/Locales/MenuBar_File.json b/assets/Locales/MenuBar_File.json index ec121856e..c1f538905 100644 --- a/assets/Locales/MenuBar_File.json +++ b/assets/Locales/MenuBar_File.json @@ -1,78 +1,278 @@ { "Locales": [ { - "ID": "ManageFileTypes", + "ID": "FileLabel", "Translations": { - "ar_SA": "إدارة أنواع الملفات", - "de_DE": "Dateitypen verwalten", - "el_GR": "Διαχείριση τύπων αρχείων", - "en_US": "Manage File Types", - "es_ES": "Administrar Tipos de Archivo", - "fr_FR": "Gérer les Types de Fichiers", - "he_IL": "ניהול סוגי קבצים", - "it_IT": "Gestisci i tipi di file", - "ja_JP": "ファイル形式を管理", - "ko_KR": "파일 형식 관리", - "no_NO": "Behandle filtyper", - "pl_PL": "Zarządzaj rodzajami plików", - "pt_BR": "Gerenciar Tipos de Arquivos", - "ru_RU": "Управление типами файлов", - "sv_SE": "Hantera filtyper", - "th_TH": "จัดการประเภทไฟล์", - "tr_TR": "Dosya uzantılarını yönet", - "uk_UA": "Керувати типами файлів", - "zh_CN": "管理文件扩展名", - "zh_TW": "管理檔案類型" + "ar_SA": "_ملف", + "de_DE": "_Datei", + "el_GR": "_Αρχείο", + "en_US": "_File", + "es_ES": "_Archivo", + "fr_FR": "_Fichier", + "he_IL": "_קובץ", + "it_IT": "_Archivio", + "ja_JP": "ファイル(_F)", + "ko_KR": "파일(_F)", + "no_NO": "_Fil", + "pl_PL": "_Plik", + "pt_BR": "_Arquivo", + "ru_RU": "_Файл", + "sv_SE": "_Arkiv", + "th_TH": "ไฟล์", + "tr_TR": "_Dosya", + "uk_UA": "_Файл", + "zh_CN": "文件(_F)", + "zh_TW": "檔案(_F)" } }, { - "ID": "InstallFileTypes", + "ID": "LoadApplicationFromFileButton", "Translations": { - "ar_SA": "تثبيت أنواع الملفات", - "de_DE": "Dateitypen installieren", - "el_GR": "Εγκαταστήσετε τύπους αρχείων.", - "en_US": "Install File Types", - "es_ES": "Instalar Tipos de Archivo", - "fr_FR": "Installer des Types de Fichiers", - "he_IL": "סוגי קבצי התקנה", - "it_IT": "Installa i tipi di file", - "ja_JP": "ファイル形式をインストール", - "ko_KR": "파일 형식 설치", - "no_NO": "Installer filtyper", - "pl_PL": "Typy plików instalacyjnych", - "pt_BR": "Instalar tipos de arquivos", - "ru_RU": "Установить типы файлов", - "sv_SE": "Installera filtyper", - "th_TH": "ติดตั้งประเภทไฟล์", - "tr_TR": "Dosya uzantılarını yükle", - "uk_UA": "Встановити типи файлів", - "zh_CN": "关联文件扩展名", - "zh_TW": "安裝檔案類型" + "ar_SA": "_تحميل التطبيق...", + "de_DE": "_Anwendung laden...", + "el_GR": "_Φόρτωση εφαρμογής...", + "en_US": "_Load Application...", + "es_ES": "_Cargar Aplicación...", + "fr_FR": "_Charger l’Application...", + "he_IL": "_טען יישום...", + "it_IT": "_Carica applicazione...", + "ja_JP": "アプリケーションをロード(_L)...", + "ko_KR": "앱 불러오기(_L)...", + "no_NO": "_Last inn program...", + "pl_PL": "_Załaduj aplikację...", + "pt_BR": "_Carregar aplicativo...", + "ru_RU": "_Загрузить приложение...", + "sv_SE": "_Läs in applikation...", + "th_TH": "_โหลดแอปพลิเคชัน...", + "tr_TR": "_Uygulamayı yükle...", + "uk_UA": "_Завантажити застосунок...", + "zh_CN": "加载应用程序(_L)...", + "zh_TW": "載入應用程式(_L)..." } }, { - "ID": "UninstallFileTypes", + "ID": "LoadUnpackedGameFromFolderButton", "Translations": { - "ar_SA": "إزالة أنواع الملفات", - "de_DE": "Dateitypen deinstallieren", - "el_GR": "Απεγκαταστήσετε τύπους αρχείων", - "en_US": "Uninstall File Types", - "es_ES": "Desinstalar Tipos de Archivo", - "fr_FR": "Désinstaller des Types de Fichiers", - "he_IL": "סוגי קבצי הסרה", - "it_IT": "Disinstalla i tipi di file", - "ja_JP": "ファイル形式をアンインストール", - "ko_KR": "파일 형식 제거", - "no_NO": "Avinstaller filtyper", - "pl_PL": "Typy plików dezinstalacyjnych", - "pt_BR": "Desinstalar tipos de arquivos", - "ru_RU": "Удалить типы файлов", - "sv_SE": "Avinstallera filtyper", - "th_TH": "ถอนการติดตั้งประเภทไฟล์", - "tr_TR": "Dosya uzantılarını kaldır", - "uk_UA": "Видалити типи файлів", - "zh_CN": "取消关联扩展名", - "zh_TW": "移除檔案類型" + "ar_SA": "تحميل لُعْبَة غير محزومة...", + "de_DE": "_Entpacktes Spiel laden...", + "el_GR": "_Φόρτωση Απακετάριστου Παιχνιδιού...", + "en_US": "Load _Unpacked Game...", + "es_ES": "Cargar Juego _Desempaquetado...", + "fr_FR": "Charger un Jeu Décompressé...", + "he_IL": "טען משחק _שאינו ארוז...", + "it_IT": "Carica gioco _estratto...", + "ja_JP": "_展開されたゲームをロード...", + "ko_KR": "압축 푼 게임 불러오기(_U)...", + "no_NO": "Last inn _upakket spill...", + "pl_PL": "Załaduj _rozpakowaną grę...", + "pt_BR": "Abrir Jogo _Extraído...", + "ru_RU": "Загрузить _распакованную игру...", + "sv_SE": "Läs in _uppackat spel...", + "th_TH": "โหลดเกมที่แตกไฟล์แล้ว...", + "tr_TR": "_Sıkıştırılmamış Oyun Yükle...", + "uk_UA": "Завантажити _розпаковану гру...", + "zh_CN": "加载解包后的游戏(_U)...", + "zh_TW": "載入未封裝的遊戲(_U)..." + } + }, + { + "ID": "LoadTitleUpdatesAndDLCFromFolderButton", + "Translations": { + "ar_SA": "", + "de_DE": "Updates/DLC laden...", + "el_GR": "", + "en_US": "Load Updates/DLC...", + "es_ES": "Cargar Actualizaciones/DLC...", + "fr_FR": "Charger les Mises à Jour/DLC...", + "he_IL": "", + "it_IT": "Carica aggiornamenti/DLC...", + "ja_JP": "", + "ko_KR": "업데이트/DLC 불러오기...", + "no_NO": "Last inn oppdateringer/DLC...", + "pl_PL": "", + "pt_BR": "Carregar atualizações/DLC...", + "ru_RU": "Загрузить обновления/DLC...", + "sv_SE": "Läs in uppdateringar/DLC...", + "th_TH": "โหลดอัปเดต/DLC...", + "tr_TR": "", + "uk_UA": "Завантажити оновлення/DLC...", + "zh_CN": "加载更新/DLC...", + "zh_TW": "載入更新/DLC..." + } + }, + { + "ID": "OpenRyuijnxFolderButton", + "Translations": { + "ar_SA": "‫فتح مجلد Ryujinx", + "de_DE": "Ryujinx-Ordner öffnen", + "el_GR": "Άνοιγμα Φακέλου Ryujinx", + "en_US": "Open Ryujinx Folder", + "es_ES": "Abrir Carpeta de Ryujinx", + "fr_FR": "Ouvrir le Dossier Ryujinx", + "he_IL": "פתח את תיקיית ריוג'ינקס", + "it_IT": "Apri la cartella di Ryujinx", + "ja_JP": "Ryujinx フォルダを開く", + "ko_KR": "Ryujinx 폴더 열기", + "no_NO": "Åpne Ryujinx mappe", + "pl_PL": "Otwórz folder Ryujinx", + "pt_BR": "Abrir Pasta do Ryujinx", + "ru_RU": "Открыть папку Ryujinx", + "sv_SE": "Öppna Ryujinx-mapp", + "th_TH": "เปิดโฟลเดอร์ Ryujinx", + "tr_TR": "Ryujinx Klasörünü aç", + "uk_UA": "Відкрити теку Ryujinx", + "zh_CN": "打开 Ryujinx 系统目录", + "zh_TW": "開啟 Ryujinx 資料夾" + } + }, + { + "ID": "OpenLogsFolderButton", + "Translations": { + "ar_SA": "فتح مجلد السجلات", + "de_DE": "Logs-Ordner öffnen", + "el_GR": "Άνοιγμα Φακέλου Καταγραφής", + "en_US": "Open Logs Folder", + "es_ES": "Abrir Carpeta de Registros", + "fr_FR": "Ouvrir le Dossier des Journaux", + "he_IL": "פתח את תיקיית קבצי הלוג", + "it_IT": "Apri la cartella dei log", + "ja_JP": "ログフォルダを開く", + "ko_KR": "로그 폴더 열기", + "no_NO": "Åpne Logg mappen", + "pl_PL": "Otwórz folder plików dziennika zdarzeń", + "pt_BR": "Abrir Pasta de _Logs", + "ru_RU": "Открыть папку журналов", + "sv_SE": "Öppna loggmapp", + "th_TH": "เปิดโฟลเดอร์ Logs", + "tr_TR": "Logs Klasörünü aç", + "uk_UA": "Відкрити теку журналів змін", + "zh_CN": "打开日志目录", + "zh_TW": "開啟日誌資料夾" + } + }, + { + "ID": "OpenScreenshotsFolderButton", + "Translations": { + "ar_SA": "", + "de_DE": "Screenshots-Ordner öffnen", + "el_GR": "", + "en_US": "Open Screenshots Folder", + "es_ES": "Abrir Carpeta de Capturas de Pantalla", + "fr_FR": "Ouvrir le Dossier des Captures d’Écran", + "he_IL": "", + "it_IT": "Apri la cartella degli screenshots", + "ja_JP": "", + "ko_KR": "스크린샷 폴더 열기", + "no_NO": "Åpne Skjermbilde Mappen", + "pl_PL": "", + "pt_BR": "Abrir Pasta de Capturas de Tela", + "ru_RU": "Открыть папку снимков экрана", + "sv_SE": "Öppna skärmbildsmappen", + "th_TH": "เปิดโฟลเดอร์ที่เก็บภาพหน้าจอ", + "tr_TR": "", + "uk_UA": "Відкрити теку скріншотів", + "zh_CN": "打开截图文件夹", + "zh_TW": "開啟螢幕擷取畫面資料夾" + } + }, + { + "ID": "AssociateFileTypesButton", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Associate File Types", + "es_ES": "", + "fr_FR": "Associer Les Types de Fichiers", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "Связать файлы с приложением", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "RemoveFileTypeAssociationsButton", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Remove File Type Associations", + "es_ES": "", + "fr_FR": "Dissocier Les Types de Fichiers", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "Удалить ассоциации файлов", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "FileTypeAssociationsToolTip", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Associates supported file types (NSP, XCI, NCA, NRO, NSO) with Ryujinx so they open automatically when double-clicked in your file manager. Removing file type associations stops this behavior.", + "es_ES": "", + "fr_FR": "Associe les types de fichiers pris en charge (NSP, XCI, NCA, NRO, NSO) à Ryujinx afin qu’ils s’ouvrent automatiquement par double-clic dans votre gestionnaire de fichiers. Les dissocier désactive ce comportement", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "Связывает поддерживаемые типы файлов (NSP, XCI, NCA, NRO, NSO) с Ryujinx, чтобы они автоматически открывались при двойном щелчке в файловом менеджере. Удаление ассоциаций файлов отключает это поведение.", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "ExitButton", + "Translations": { + "ar_SA": "_خروج", + "de_DE": "_Beenden", + "el_GR": "_Έξοδος", + "en_US": "_Exit", + "es_ES": "_Salir", + "fr_FR": "_Quitter", + "he_IL": "_יציאה", + "it_IT": "_Esci", + "ja_JP": "終了(_E)", + "ko_KR": "종료(_E)", + "no_NO": "_Avslutt", + "pl_PL": "_Wyjdź", + "pt_BR": "_Sair", + "ru_RU": "_Выйти", + "sv_SE": "_Avsluta", + "th_TH": "_ออก", + "tr_TR": "_Çıkış", + "uk_UA": "_Вихід", + "zh_CN": "退出(_E)", + "zh_TW": "結束(_E)" } } ] diff --git a/assets/Locales/Root.json b/assets/Locales/Root.json index a98d8035d..d93a2b5b7 100644 --- a/assets/Locales/Root.json +++ b/assets/Locales/Root.json @@ -176,253 +176,153 @@ } }, { - "ID": "MenuBarFile", + "ID": "MenuBarOptions", "Translations": { - "ar_SA": "_ملف", - "de_DE": "_Datei", - "el_GR": "_Αρχείο", - "en_US": "_File", - "es_ES": "_Archivo", - "fr_FR": "_Fichier", - "he_IL": "_קובץ", - "it_IT": "_Archivio", - "ja_JP": "ファイル(_F)", - "ko_KR": "파일(_F)", - "no_NO": "_Fil", - "pl_PL": "_Plik", - "pt_BR": "_Arquivo", - "ru_RU": "_Файл", - "sv_SE": "_Arkiv", - "th_TH": "ไฟล์", - "tr_TR": "_Dosya", - "uk_UA": "_Файл", - "zh_CN": "文件(_F)", - "zh_TW": "檔案(_F)" + "ar_SA": "_خيارات", + "de_DE": "_Optionen", + "el_GR": "_Επιλογές", + "en_US": "_Options", + "es_ES": "_Opciones", + "fr_FR": null, + "he_IL": "_אפשרויות", + "it_IT": "_Opzioni", + "ja_JP": "オプション(_O)", + "ko_KR": "옵션(_O)", + "no_NO": "_Alternativer", + "pl_PL": "_Opcje", + "pt_BR": "_Opções", + "ru_RU": "_Настройки", + "sv_SE": "_Inställningar", + "th_TH": "_ตัวเลือก", + "tr_TR": "_Seçenekler", + "uk_UA": "_Параметри", + "zh_CN": "选项(_O)", + "zh_TW": "選項(_O)" } }, { - "ID": "MenuBarFileOpenFromFile", + "ID": "MenuBarOptionsToggleFullscreen", "Translations": { - "ar_SA": "_تحميل التطبيق...", - "de_DE": "_Anwendung laden...", - "el_GR": "_Φόρτωση εφαρμογής...", - "en_US": "_Load Application...", - "es_ES": "_Cargar Aplicación...", - "fr_FR": "_Charger l’Application...", - "he_IL": "_טען יישום...", - "it_IT": "_Carica applicazione...", - "ja_JP": "アプリケーションをロード(_L)...", - "ko_KR": "앱 불러오기(_L)...", - "no_NO": "_Last inn program...", - "pl_PL": "_Załaduj aplikację...", - "pt_BR": "_Carregar aplicativo...", - "ru_RU": "_Загрузить приложение...", - "sv_SE": "_Läs in applikation...", - "th_TH": "_โหลดแอปพลิเคชัน...", - "tr_TR": "_Uygulamayı yükle...", - "uk_UA": "_Завантажити застосунок...", - "zh_CN": "加载应用程序(_L)...", - "zh_TW": "載入應用程式(_L)..." + "ar_SA": "التبديل إلى وضع ملء الشاشة", + "de_DE": "Vollbild", + "el_GR": "Λειτουργία Πλήρους Οθόνης", + "en_US": "Toggle Fullscreen", + "es_ES": "Cambiar a Pantalla Completa.", + "fr_FR": "Basculer en Plein Écran", + "he_IL": "שנה מצב- מסך מלא", + "it_IT": "Schermo intero", + "ja_JP": "全画面切り替え", + "ko_KR": "전체 화면 전환", + "no_NO": "Fullskjermsvisning av/på", + "pl_PL": "Przełącz na tryb pełnoekranowy", + "pt_BR": "Mudar para Tela Cheia", + "ru_RU": "Переключить полноэкранный режим", + "sv_SE": "Växla helskärm", + "th_TH": "สลับเป็นโหมดเต็มหน้าจอ", + "tr_TR": "Tam Ekran Modunu Aç", + "uk_UA": "На весь екран", + "zh_CN": "切换全屏", + "zh_TW": "切換全螢幕模式" } }, { - "ID": "MenuBarFileOpenFromFileError", + "ID": "MenuBarOptionsStartGamesInFullscreen", + "Translations": { + "ar_SA": "ابدأ الألعاب في وضع ملء الشاشة", + "de_DE": "Spiele im Vollbildmodus starten", + "el_GR": "Εκκίνηση Παιχνιδιών σε Πλήρη Οθόνη", + "en_US": "Start Games in Fullscreen Mode", + "es_ES": "Iniciar Juegos en Pantalla Completa", + "fr_FR": "Démarrer les Jeux en Plein Écran", + "he_IL": "התחל משחקים במסך מלא", + "it_IT": "Avvia i giochi a schermo intero", + "ja_JP": "全画面モードでゲームを開始", + "ko_KR": "전체 화면 모드로 게임 시작", + "no_NO": "Start spill i Fullskjermmodus", + "pl_PL": "Uruchamiaj gry w trybie pełnoekranowym", + "pt_BR": "Iniciar Jogos em Tela Cheia", + "ru_RU": "Запускать игры в полноэкранном режиме", + "sv_SE": "Starta spel i helskärmsläge", + "th_TH": "เริ่มเกมในโหมดเต็มหน้าจอ", + "tr_TR": "Oyunları Tam Ekran Modunda Başlat", + "uk_UA": "Запускати ігри на весь екран", + "zh_CN": "全屏模式启动游戏", + "zh_TW": "使用全螢幕模式啟動遊戲" + } + }, + { + "ID": "MenuBarOptionsStartGamesWithoutUI", "Translations": { "ar_SA": "", - "de_DE": "Keine Anwendungen in ausgewählter Datei gefunden.", + "de_DE": "Spiele ohne Benutzeroberfläche starten", "el_GR": "", - "en_US": "No applications found in selected file.", - "es_ES": "No se encontraron aplicaciones en el archivo seleccionado.", - "fr_FR": "Aucune application trouvée dans le fichier sélectionné.", + "en_US": "Start Games with UI Hidden", + "es_ES": "Iniziar Juegos con la Interfaz Oculta", + "fr_FR": "Démarrer les Jeux avec l’Interface Cachée", "he_IL": "", - "it_IT": "Nessuna applicazione trovata nel file selezionato.", + "it_IT": "Avvia i giochi con l'interfaccia nascosta", "ja_JP": "", - "ko_KR": "선택한 파일에서 앱을 찾을 수 없습니다.", - "no_NO": "Ingen apper ble funnet i valgt fil.", + "ko_KR": "UI를 숨긴 상태에서 게임 시작", + "no_NO": "Start Spillet med UI Gjemt", "pl_PL": "", - "pt_BR": "Nenhum aplicativo encontrado no arquivo selecionado.", - "ru_RU": "Приложений в выбранном файле не найдены", - "sv_SE": "Inga applikationer hittades i vald fil.", - "th_TH": "ไม่พบแอปพลิเคชั่นจากไฟล์ที่เลือก", + "pt_BR": "Iniciar Jogos Ocultando a Interface", + "ru_RU": "Запускать игры скрывая интерфейс", + "sv_SE": "Starta spel med dolt användargränssnitt", + "th_TH": "เริ่มเกมโดยซ่อน UI", "tr_TR": "", - "uk_UA": "У вибраному файлі не знайдено жодних додатків.", - "zh_CN": "未发现应用", - "zh_TW": "未能從已選擇的檔案中找到應用程式。" + "uk_UA": "Запускати ігри з прихованим інтерфейсом", + "zh_CN": "启动游戏时隐藏 UI", + "zh_TW": "開啟遊戲時隱藏 UI" } }, { - "ID": "MenuBarFileOpenUnpacked", + "ID": "MenuBarOptionsSettings", "Translations": { - "ar_SA": "تحميل لُعْبَة غير محزومة...", - "de_DE": "_Entpacktes Spiel laden...", - "el_GR": "_Φόρτωση Απακετάριστου Παιχνιδιού...", - "en_US": "Load _Unpacked Game...", - "es_ES": "Cargar Juego _Desempaquetado...", - "fr_FR": "Charger un Jeu Décompressé...", - "he_IL": "טען משחק _שאינו ארוז...", - "it_IT": "Carica gioco _estratto...", - "ja_JP": "_展開されたゲームをロード...", - "ko_KR": "압축 푼 게임 불러오기(_U)...", - "no_NO": "Last inn _upakket spill...", - "pl_PL": "Załaduj _rozpakowaną grę...", - "pt_BR": "Abrir Jogo _Extraído...", - "ru_RU": "Загрузить _распакованную игру...", - "sv_SE": "Läs in _uppackat spel...", - "th_TH": "โหลดเกมที่แตกไฟล์แล้ว...", - "tr_TR": "_Sıkıştırılmamış Oyun Yükle...", - "uk_UA": "Завантажити _розпаковану гру...", - "zh_CN": "加载解包后的游戏(_U)...", - "zh_TW": "載入未封裝的遊戲(_U)..." + "ar_SA": "_الإعدادات", + "de_DE": "_Einstellungen", + "el_GR": "_Ρυθμίσεις", + "en_US": "_Settings", + "es_ES": "_Configuración", + "fr_FR": "_Paramètres", + "he_IL": "_הגדרות", + "it_IT": "_Impostazioni", + "ja_JP": "設定(_S)", + "ko_KR": "설정(_S)", + "no_NO": "_Innstillinger", + "pl_PL": "_Ustawienia", + "pt_BR": "_Configurações", + "ru_RU": "_Параметры", + "sv_SE": "_Inställningar", + "th_TH": "_ตั้งค่า", + "tr_TR": "_Seçenekler", + "uk_UA": "_Налаштування", + "zh_CN": "设置(_S)", + "zh_TW": "設定(_S)" } }, { - "ID": "MenuBarFileLoadDlcFromFolder", + "ID": "MenuBarOptionsManageUserProfiles", "Translations": { - "ar_SA": "", - "de_DE": "DLC aus Ordner laden...", - "el_GR": "", - "en_US": "Load DLC...", - "es_ES": "Cargar DLC...", - "fr_FR": "Charger des DLC...", - "he_IL": "", - "it_IT": "Carica DLC...", - "ja_JP": "", - "ko_KR": "DLC 폴더에서 불러오기...", - "no_NO": "Last inn DLC...", - "pl_PL": "", - "pt_BR": "Carregar DLC...", - "ru_RU": "Загрузить DLC...", - "sv_SE": "Läs in DLC...", - "th_TH": "โหลด DLC...", - "tr_TR": "", - "uk_UA": "Завантажити DLC...", - "zh_CN": "加载 DLC...", - "zh_TW": "載入 DLC..." - } - }, - { - "ID": "MenuBarFileLoadTitleUpdatesFromFolder", - "Translations": { - "ar_SA": "", - "de_DE": "Titel-Updates aus Ordner laden...", - "el_GR": "", - "en_US": "Load Title Updates...", - "es_ES": "Cargar Actualizaciones de Títulos...", - "fr_FR": "Charger des Mises à Jour de Titres...", - "he_IL": "", - "it_IT": "Carica aggiornamenti...", - "ja_JP": "", - "ko_KR": "타이틀 업데이트 불러오기...", - "no_NO": "Last inn titteloppdateringer...", - "pl_PL": "", - "pt_BR": "Carregar Atualizações de Jogo...", - "ru_RU": "Загрузить обновления...", - "sv_SE": "Läs in titeluppdateringar...", - "th_TH": "โหลดไฟล์อัพเดต...", - "tr_TR": "", - "uk_UA": "Завантажити оновлення...", - "zh_CN": "加载游戏更新...", - "zh_TW": "載入遊戲更新..." - } - }, - { - "ID": "MenuBarFileOpenEmuFolder", - "Translations": { - "ar_SA": "‫فتح مجلد Ryujinx", - "de_DE": "Ryujinx-Ordner öffnen", - "el_GR": "Άνοιγμα Φακέλου Ryujinx", - "en_US": "Open Ryujinx Folder", - "es_ES": "Abrir Carpeta de Ryujinx", - "fr_FR": "Ouvrir le Dossier Ryujinx", - "he_IL": "פתח את תיקיית ריוג'ינקס", - "it_IT": "Apri la cartella di Ryujinx", - "ja_JP": "Ryujinx フォルダを開く", - "ko_KR": "Ryujinx 폴더 열기", - "no_NO": "Åpne Ryujinx mappe", - "pl_PL": "Otwórz folder Ryujinx", - "pt_BR": "Abrir Pasta do Ryujinx", - "ru_RU": "Открыть папку Ryujinx", - "sv_SE": "Öppna Ryujinx-mapp", - "th_TH": "เปิดโฟลเดอร์ Ryujinx", - "tr_TR": "Ryujinx Klasörünü aç", - "uk_UA": "Відкрити теку Ryujinx", - "zh_CN": "打开 Ryujinx 系统目录", - "zh_TW": "開啟 Ryujinx 資料夾" - } - }, - { - "ID": "MenuBarFileOpenScreenshotsFolder", - "Translations": { - "ar_SA": "", - "de_DE": "Screenshots-Ordner öffnen", - "el_GR": "", - "en_US": "Open Screenshots Folder", - "es_ES": "Abrir Carpeta de Capturas de Pantalla", - "fr_FR": "Ouvrir le Dossier des Captures d’Écran", - "he_IL": "", - "it_IT": "Apri la cartella degli screenshots", - "ja_JP": "", - "ko_KR": "스크린샷 폴더 열기", - "no_NO": "Åpne Skjermbilde Mappen", - "pl_PL": "", - "pt_BR": "Abrir Pasta de Capturas de Tela", - "ru_RU": "Открыть папку снимков экрана", - "sv_SE": "Öppna skärmbildsmappen", - "th_TH": "เปิดโฟลเดอร์ที่เก็บภาพหน้าจอ", - "tr_TR": "", - "uk_UA": "Відкрити теку скріншотів", - "zh_CN": "打开截图文件夹", - "zh_TW": "開啟螢幕擷取畫面資料夾" - } - }, - { - "ID": "MenuBarFileOpenLogsFolder", - "Translations": { - "ar_SA": "فتح مجلد السجلات", - "de_DE": "Logs-Ordner öffnen", - "el_GR": "Άνοιγμα Φακέλου Καταγραφής", - "en_US": "Open Logs Folder", - "es_ES": "Abrir Carpeta de Registros", - "fr_FR": "Ouvrir le Dossier des Journaux", - "he_IL": "פתח את תיקיית קבצי הלוג", - "it_IT": "Apri la cartella dei log", - "ja_JP": "ログフォルダを開く", - "ko_KR": "로그 폴더 열기", - "no_NO": "Åpne Logg mappen", - "pl_PL": "Otwórz folder plików dziennika zdarzeń", - "pt_BR": "Abrir Pasta de _Logs", - "ru_RU": "Открыть папку журналов", - "sv_SE": "Öppna loggmapp", - "th_TH": "เปิดโฟลเดอร์ Logs", - "tr_TR": "Logs Klasörünü aç", - "uk_UA": "Відкрити теку журналів змін", - "zh_CN": "打开日志目录", - "zh_TW": "開啟日誌資料夾" - } - }, - { - "ID": "MenuBarFileExit", - "Translations": { - "ar_SA": "_خروج", - "de_DE": "_Beenden", - "el_GR": "_Έξοδος", - "en_US": "_Exit", - "es_ES": "_Salir", - "fr_FR": "_Quitter", - "he_IL": "_יציאה", - "it_IT": "_Esci", - "ja_JP": "終了(_E)", - "ko_KR": "종료(_E)", - "no_NO": "_Avslutt", - "pl_PL": "_Wyjdź", - "pt_BR": "_Sair", - "ru_RU": "_Выйти", - "sv_SE": "_Avsluta", - "th_TH": "_ออก", - "tr_TR": "_Çıkış", - "uk_UA": "_Вихід", - "zh_CN": "退出(_E)", - "zh_TW": "結束(_E)" + "ar_SA": "_ملفات المستخدمين", + "de_DE": "_Benutzerprofile", + "el_GR": "_Προφίλ Χρηστών", + "en_US": "_User Profiles", + "es_ES": "_Perfiles de Usuario", + "fr_FR": "_Profils d'Utilisateurs", + "he_IL": "_פרופילי משתמש", + "it_IT": "_Profili utent", + "ja_JP": "ユーザプロファイル(_M)", + "ko_KR": "사용자 프로필(_M)", + "no_NO": "_Brukerprofiler", + "pl_PL": "_Profile użytkowników", + "pt_BR": "_Perfis de usuário", + "ru_RU": "_Учётные записи", + "sv_SE": "_Användarprofiler", + "th_TH": "_โปรไฟล์ผู้ใช้งาน", + "tr_TR": "_Kullanıcı Profilleri", + "uk_UA": "_Профілі користувачів", + "zh_CN": "用户配置文件(_M)", + "zh_TW": "使用者設定檔(_M)" } }, { @@ -1503,26 +1403,26 @@ { "ID": "GameListContextMenuManageTitleUpdates", "Translations": { - "ar_SA": "إدارة تحديثات اللُعبة", - "de_DE": "Verwalte Spiel-Updates", - "el_GR": "Διαχείριση Ενημερώσεων Παιχνιδιού", - "en_US": "Manage Title Updates", - "es_ES": "Gestionar Actualizaciones del Juego", - "fr_FR": "Gérer les Mises à Jour du Titre", - "he_IL": "מנהל עדכוני משחקים", - "it_IT": "Gestisci aggiornamenti del gioco", + "ar_SA": "إدارة التحديثات", + "de_DE": "Updates verwalten", + "el_GR": "Διαχείριση ενημερώσεων", + "en_US": "Manage Updates", + "es_ES": "Gestionar Actualizaciones", + "fr_FR": "Gérer les Mises à Jour", + "he_IL": "ניהול עדכונים", + "it_IT": "Gestisci aggiornamenti", "ja_JP": "アップデートを管理", - "ko_KR": "타이틀 업데이트 관리", - "no_NO": "Administrer titteloppdateringer", + "ko_KR": "업데이트 관리", + "no_NO": "Administrer oppdateringer", "pl_PL": "Zarządzaj aktualizacjami", - "pt_BR": "Gerenciar Atualizações do Jogo", + "pt_BR": "Gerenciar atualizações", "ru_RU": "Управление обновлениями", - "sv_SE": "Hantera speluppdateringar", - "th_TH": "จัดการเวอร์ชั่นอัปเดต", - "tr_TR": "Oyun Güncellemelerini Yönet", + "sv_SE": "Hantera uppdateringar", + "th_TH": "จัดการการอัปเดต", + "tr_TR": "Güncellemeleri Yönet", "uk_UA": "Керування оновленнями", - "zh_CN": "管理游戏更新", - "zh_TW": "管理遊戲更新" + "zh_CN": "管理更新", + "zh_TW": "管理更新" } }, { @@ -10650,106 +10550,6 @@ "zh_TW": "您要重新啟動嗎" } }, - { - "ID": "DialogInstallFileTypesSuccessMessage", - "Translations": { - "ar_SA": "تم تثبيت أنواع الملفات بنجاح!", - "de_DE": "Dateitypen erfolgreich installiert!", - "el_GR": "Επιτυχής εγκατάσταση τύπων αρχείων!", - "en_US": "Successfully installed file types!", - "es_ES": "¡Tipos de archivos instalados con éxito!", - "fr_FR": "Types de fichiers installés avec succès !", - "he_IL": "סוגי קבצים הותקנו בהצלחה!", - "it_IT": "Tipi di file installati con successo!", - "ja_JP": "ファイル形式のインストールに成功しました!", - "ko_KR": "파일 형식을 성공적으로 설치했습니다!", - "no_NO": "Filtyper ble installert!", - "pl_PL": "Pomyślnie zainstalowano typy plików!", - "pt_BR": "Tipos de arquivo instalados com sucesso!", - "ru_RU": "Типы файлов успешно установлены!", - "sv_SE": "Filtyper har installerats!", - "th_TH": "ติดตั้งตามประเภทของไฟล์สำเร็จแล้ว!", - "tr_TR": "Dosya uzantıları başarıyla yüklendi!", - "uk_UA": "Успішно встановлено типи файлів!", - "zh_CN": "关联文件类型成功!", - "zh_TW": "成功安裝檔案類型!" - } - }, - { - "ID": "DialogInstallFileTypesErrorMessage", - "Translations": { - "ar_SA": "فشل تثبيت أنواع الملفات.", - "de_DE": "Dateitypen konnten nicht installiert werden.", - "el_GR": "Απέτυχε η εγκατάσταση τύπων αρχείων.", - "en_US": "Failed to install file types.", - "es_ES": "No se pudo desinstalar los tipos de archivo.", - "fr_FR": "Échec de l'installation des types de fichiers.", - "he_IL": "נכשל בהתקנת סוגי קבצים.", - "it_IT": "Impossibile installare i tipi di file.", - "ja_JP": "ファイル形式のインストールに失敗しました.", - "ko_KR": "파일 형식을 설치하지 못했습니다.", - "no_NO": "Kunne ikke installere filtyper.", - "pl_PL": "Nie udało się zainstalować typów plików.", - "pt_BR": "Falha ao instalar tipos de arquivo.", - "ru_RU": "Не удалось установить типы файлов.", - "sv_SE": "Misslyckades med att installera filtyper.", - "th_TH": "ติดตั้งตามประเภทของไฟล์ไม่สำเร็จ", - "tr_TR": "Dosya uzantıları yükleme işlemi başarısız oldu.", - "uk_UA": "Не вдалося встановити типи файлів.", - "zh_CN": "关联文件类型失败!", - "zh_TW": "無法安裝檔案類型。" - } - }, - { - "ID": "DialogUninstallFileTypesSuccessMessage", - "Translations": { - "ar_SA": "تم إلغاء تثبيت أنواع الملفات بنجاح!", - "de_DE": "Dateitypen erfolgreich deinstalliert!", - "el_GR": "Επιτυχής απεγκατάσταση τύπων αρχείων!", - "en_US": "Successfully uninstalled file types!", - "es_ES": "¡Tipos de archivos desinstalados con éxito!", - "fr_FR": "Types de fichiers désinstallés avec succès !", - "he_IL": "סוגי קבצים הוסרו בהצלחה!", - "it_IT": "Tipi di file disinstallati con successo!", - "ja_JP": "ファイル形式のアンインストールに成功しました!", - "ko_KR": "파일 형식이 성공적으로 제거되었습니다!", - "no_NO": "Filtyper ble avinstallert!", - "pl_PL": "Pomyślnie odinstalowano typy plików!", - "pt_BR": "Tipos de arquivo desinstalados com sucesso!", - "ru_RU": "Типы файлов успешно удалены!", - "sv_SE": "Filtyper avinstallerades!", - "th_TH": "ถอนการติดตั้งตามประเภทของไฟล์สำเร็จแล้ว!", - "tr_TR": "Dosya uzantıları başarıyla kaldırıldı!", - "uk_UA": "Успішно видалено типи файлів!", - "zh_CN": "成功解除文件类型关联!", - "zh_TW": "成功移除檔案類型!" - } - }, - { - "ID": "DialogUninstallFileTypesErrorMessage", - "Translations": { - "ar_SA": "فشل إلغاء تثبيت أنواع الملفات.", - "de_DE": "Deinstallation der Dateitypen fehlgeschlagen.", - "el_GR": "Αποτυχία απεγκατάστασης τύπων αρχείων.", - "en_US": "Failed to uninstall file types.", - "es_ES": "No se pudo desinstalar los tipos de archivo.", - "fr_FR": "Échec de la désinstallation des types de fichiers.", - "he_IL": "נכשל בהסרת סוגי קבצים.", - "it_IT": "Disinstallazione dei tipi di file non riuscita.", - "ja_JP": "ファイル形式のアンインストールに失敗しました.", - "ko_KR": "파일 형식을 제거하지 못했습니다.", - "no_NO": "Kunne ikke avinstallere filtyper.", - "pl_PL": "Nie udało się odinstalować typów plików.", - "pt_BR": "Falha ao desinstalar tipos de arquivo.", - "ru_RU": "Не удалось удалить типы файлов.", - "sv_SE": "Misslyckades med att avinstallera filtyper.", - "th_TH": "ไม่สามารถถอนการติดตั้งตามประเภทของไฟล์ได้", - "tr_TR": "Dosya uzantıları kaldırma işlemi başarısız oldu.", - "uk_UA": "Не вдалося видалити типи файлів.", - "zh_CN": "解除文件类型关联失败!", - "zh_TW": "無法移除檔案類型。" - } - }, { "ID": "DialogOpenSettingsWindowLabel", "Translations": { @@ -16025,106 +15825,6 @@ "zh_TW": "選取支援的檔案格式" } }, - { - "ID": "LoadApplicationFromFileDialogTitle", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Choose a Switch compatible FILE to load", - "es_ES": "Elige un ARCHIVO compatible con Switch para cargar", - "fr_FR": "Choisissez un FICHIER compatible Switch à charger", - "he_IL": "", - "it_IT": "Scegli un FILE compatibile con Switch da caricare", - "ja_JP": "", - "ko_KR": "불러올 Switch 호환 파일을 선택", - "no_NO": "", - "pl_PL": "", - "pt_BR": "Escolha um ARQUIVO compatível com Switch para carregar", - "ru_RU": "Выберите ФАЙЛ, совместимый с Switch, для загрузки", - "sv_SE": "Välj en Switch-kompatibel FIL att läsa in", - "th_TH": "", - "tr_TR": "", - "uk_UA": "Виберіть ФАЙЛ, сумісний із Switch, для завантаження", - "zh_CN": "请选择要加载的 Switch 兼容文件", - "zh_TW": "請選擇要載入的 Switch 相容檔案" - } - }, - { - "ID": "LoadUnpackedGameFromFolderDialogTitle", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Choose an UNPACKED Switch compatible application to load", - "es_ES": "Elige una aplicación DESEMPAQUETADA compatible con Switch para cargar", - "fr_FR": "Choisissez une application DÉCOMPRESSEÉE compatible avec Switch à charger", - "he_IL": "", - "it_IT": "Scegli un’applicazione DECOMPRESSA compatibile con Switch da caricare", - "ja_JP": "", - "ko_KR": "불러올 언팩된 Switch 호환 앱을 선택", - "no_NO": "", - "pl_PL": "", - "pt_BR": "Escolha um aplicativo DESCOMPACTADO compatível com Switch para carregar", - "ru_RU": "Выберите РАСПАКОВАННОЕ, совместимое с Switch, приложение для загрузки", - "sv_SE": "Välj en UPPACKAD Switch-kompatibel applikation att läsa in", - "th_TH": "", - "tr_TR": "", - "uk_UA": "Виберіть РОЗПАКОВАНИЙ сумісний із Switch додаток для завантаження", - "zh_CN": "请选择要加载的已解包的 Switch 兼容应用程序", - "zh_TW": "請選擇要載入的已解壓縮 Switch 相容應用程式" - } - }, - { - "ID": "LoadTitleUpdatesFromFolderDialogTitle", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Choose one or more FOLDERS to bulk load title updates from", - "es_ES": "Elige una o más CARPETAS para cargar actualizaciones de título de forma masiva", - "fr_FR": "Choisissez un ou plusieurs DOSSIERS pour charger en masse des mises à jour de titres", - "he_IL": "", - "it_IT": "Scegli una o più CARTELLE da cui caricare in blocco gli aggiornamenti del titolo", - "ja_JP": "", - "ko_KR": "타이틀 업데이트를 대량으로 불러올 폴더를 하나 이상 선택", - "no_NO": "", - "pl_PL": "", - "pt_BR": "Escolha uma ou mais PASTAS para carregar atualizações de título em massa", - "ru_RU": "Выберите одну или несколько ПАПОК для массовой загрузки обновлений заголовков", - "sv_SE": "Välj en eller flera MAPPAR för att läsa in alla titeluppdateringar från", - "th_TH": "", - "tr_TR": "", - "uk_UA": "Виберіть одну або кілька ПАПОК для масового завантаження оновлень титулів", - "zh_CN": "请选择一个或多个文件夹来批量加载游戏更新", - "zh_TW": "請選擇一個或多個資料夾以批次載入遊戲更新" - } - }, - { - "ID": "LoadDLCFromFolderDialogTitle", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Choose one or more FOLDERS to bulk load DLC from", - "es_ES": "Elige una o más CARPETAS para cargar DLC de forma masiva", - "fr_FR": "Choisissez un ou plusieurs DOSSIERS pour charger en masse des DLC", - "he_IL": "", - "it_IT": "Scegli una o più CARTELLE da cui caricare DLC in blocco", - "ja_JP": "", - "ko_KR": "DLC를 대량으로 불러올 폴더를 하나 이상 선택", - "no_NO": "", - "pl_PL": "", - "pt_BR": "Escolha uma ou mais PASTAS para carregar DLC em massa", - "ru_RU": "Выберите одну или несколько ПАПОК для массовой загрузки DLC", - "sv_SE": "Välj en eller flera MAPPAR för att läsa in alla DLC från", - "th_TH": "", - "tr_TR": "", - "uk_UA": "Виберіть одну або кілька ПАПОК для масового завантаження DLC", - "zh_CN": "请选择一个或多个文件夹来批量加载 DLC", - "zh_TW": "請選擇一個或多個資料夾以批次載入 DLC" - } - }, { "ID": "AllSupportedFormats", "Translations": { @@ -17475,31 +17175,6 @@ "zh_TW": "反修剪" } }, - { - "ID": "UpdateWindowUpdateAddedMessage", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0} new update(s) added", - "es_ES": "{0} nueva(s) actualización(es) agregada(s)", - "fr_FR": "{0} nouvelle(s) mise(s) à jour ajoutée(s)", - "he_IL": "", - "it_IT": "{0} nuovo/i aggiornamento/i aggiunto/i", - "ja_JP": "", - "ko_KR": "{0}개의 신규 업데이트가 추가됨", - "no_NO": "{0} ny(e) oppdatering(er) lagt til", - "pl_PL": "", - "pt_BR": "{0} nova(s) atualização(ões) adicionada(s)", - "ru_RU": "Добавлено {0} новых обновлений", - "sv_SE": "{0} nya uppdatering(ar) lades till", - "th_TH": "มีอัปเดตใหม่เข้ามา {0} รายการ", - "tr_TR": "", - "uk_UA": "{0} нових оновлень додано", - "zh_CN": "{0} 个更新被添加", - "zh_TW": "已加入 {0} 個遊戲更新" - } - }, { "ID": "UpdateWindowBundledContentNotice", "Translations": { @@ -17625,131 +17300,6 @@ "zh_TW": "{0} 個可下載內容" } }, - { - "ID": "DlcWindowDlcAddedMessage", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0} New Downloadable Content(s) Added", - "es_ES": "Se agregó/aron {0} nuevo(s) contenido(s) descargable(s)", - "fr_FR": "{0} nouveau(x) contenu(s) téléchargeable(s) ajouté(s)", - "he_IL": "", - "it_IT": "{0} nuovo/i DLC aggiunto/i", - "ja_JP": "", - "ko_KR": "{0}개의 새로운 내려받기 가능한 콘텐츠가 추가됨", - "no_NO": "{0} nytt nedlastbart innhold lagt til", - "pl_PL": "", - "pt_BR": "{0} novo(s) conteúdo(s) para download adicionado(s)", - "ru_RU": "Добавлено {0} новое/ых DLC", - "sv_SE": "{0} nya hämtningsbara innehåll lades till", - "th_TH": "มีเนื้อหาเสริมใหม่ {0} รายการ", - "tr_TR": "", - "uk_UA": "{0} нового завантажувального вмісту додано", - "zh_CN": "{0} 个 DLC 被添加", - "zh_TW": "已加入 {0} 個 DLC" - } - }, - { - "ID": "AutoloadDlcAddedMessage", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0} New Downloadable Content(s) Added", - "es_ES": "Se agregó/aron {0} nuevo(s) contenido(s) descargable(s)", - "fr_FR": "{0} nouveau(x) contenu(s) téléchargeable(s) ajouté(s)", - "he_IL": "", - "it_IT": "{0} nuovo/i DLC aggiunto/i", - "ja_JP": "", - "ko_KR": "{0}개의 새로운 DLC가 추가됨", - "no_NO": "{0} nytt nedlastbart innhold lagt til", - "pl_PL": "", - "pt_BR": "{0} novo(s) conteúdo(s) para download adicionado(s)", - "ru_RU": "Добавлено {0} новое/ых DLC", - "sv_SE": "{0} nya hämtningsbara innehåll lades till", - "th_TH": "เพิ่มเนื้อหาเสริมดาวน์โหลดใหม่ {0} รายการ", - "tr_TR": "", - "uk_UA": "{0} нового завантажувального вмісту додано", - "zh_CN": "{0} 个 DLC 被添加", - "zh_TW": "已加入 {0} 個 DLC" - } - }, - { - "ID": "AutoloadDlcRemovedMessage", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0} Missing Downloadable Content(s) Removed", - "es_ES": "Se eliminó/aron {0} contenido(s) descargable(s) faltante(s)", - "fr_FR": "{0} contenu(s) téléchargeable(s) manquant(s) supprimé(s)", - "he_IL": "", - "it_IT": "{0} DLC mancante/i rimosso/i", - "ja_JP": "", - "ko_KR": "{0}개의 내려받기 가능한 콘텐츠가 제거됨", - "no_NO": "{0} manglende nedlastbart innhold fjernet", - "pl_PL": "", - "pt_BR": "{0} conteúdo(s) para download ausente(s) removido(s)", - "ru_RU": "Убрано {0} отсутствующие/х DLC", - "sv_SE": "{0} saknade hämtningsbara innehåll togs bort", - "th_TH": "ลบเนื้อหาเสริมที่หายไปจำนวน {0} รายการ", - "tr_TR": "", - "uk_UA": "{0} відсутнього завантажувального вмісту видалено", - "zh_CN": "{0} 个失效的 DLC 已移除", - "zh_TW": "已刪除 {0} 個遺失的 DLC" - } - }, - { - "ID": "AutoloadUpdateAddedMessage", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0} New Update(s) Added", - "es_ES": "Se agregó/aron {0} nueva(s) actualización(es)", - "fr_FR": "{0} nouvelle(s) mise(s) à jour ajoutée(s)", - "he_IL": "", - "it_IT": "{0} nuovo/i aggiornamento/i aggiunto/i", - "ja_JP": "", - "ko_KR": "{0}개의 신규 업데이트가 추가됨", - "no_NO": "{0} ny(e) oppdatering(er) lagt til", - "pl_PL": "", - "pt_BR": "{0} nova(s) atualização(ões) adicionada(s)", - "ru_RU": "Добавлено {0} новое/ых обновление/й", - "sv_SE": "{0} nya uppdatering(ar) lades till", - "th_TH": "เพิ่มการอัปเดตใหม่ {0} รายการ", - "tr_TR": "", - "uk_UA": "{0} нових оновлень додано", - "zh_CN": "{0} 个游戏更新被添加", - "zh_TW": "已加入 {0} 個遊戲更新" - } - }, - { - "ID": "AutoloadUpdateRemovedMessage", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0} Missing Update(s) Removed", - "es_ES": "Se eliminó/aron {0} actualización(es) faltante(s)", - "fr_FR": "{0} mise(s) à jour manquante(s) supprimée(s)", - "he_IL": "", - "it_IT": "{0} aggiornamento/i mancante/i rimosso/i", - "ja_JP": "", - "ko_KR": "누락된 업데이트 {0}개 삭제", - "no_NO": "{0} manglende oppdatering(er) fjernet", - "pl_PL": "", - "pt_BR": "{0} atualização(ões) ausente(s) removida(s)", - "ru_RU": "Убрано {0} отсутствующие/х обновление/й", - "sv_SE": "{0} saknade uppdatering(ar) togs bort", - "th_TH": "ลบการอัปเดตที่หายไปจำนวน {0} รายการ", - "tr_TR": "", - "uk_UA": "{0} відсутніх оновлень видалено", - "zh_CN": "{0} 个失效的游戏更新已移除", - "zh_TW": "已刪除 {0} 個遺失的遊戲更新" - } - }, { "ID": "ModWindowHeading", "Translations": { diff --git a/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs b/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs index b61dd8ee2..d57a209c2 100644 --- a/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs +++ b/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs @@ -24,6 +24,9 @@ namespace Ryujinx.Common.Helper public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()); + // NOTE: On macOS, users have a more robust file association system (via Right-Click > Get Info > "Open with:" > Ryujinx > "Change All...) + // Custom file association isn't strictly necessary and will not provide any additional benefit to macOS users. + public static bool AreMimeTypesRegistered { get @@ -38,8 +41,6 @@ namespace Ryujinx.Common.Helper return AreMimeTypesRegisteredWindows(); } - // TODO: Add macOS support. - return false; } } @@ -173,8 +174,6 @@ namespace Ryujinx.Common.Helper return InstallWindowsMimeTypes(); } - // TODO: Add macOS support. - return false; } @@ -190,8 +189,6 @@ namespace Ryujinx.Common.Helper return InstallWindowsMimeTypes(true); } - // TODO: Add macOS support. - return false; } } diff --git a/src/Ryujinx/Systems/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs index e377f9e4b..23f6d6b47 100644 --- a/src/Ryujinx/Systems/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -818,8 +818,7 @@ namespace Ryujinx.Ava.Systems if (!Device.LoadCart(ApplicationPath, romFsFiles[0])) { - await ContentDialogHelper.CreateErrorDialog( - "Please specify an unpacked game directory with a valid exefs or NSO/NRO."); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.Error_NoUnpackedApplicationFoundInFolder)); Device.Dispose(); cts.Cancel(); @@ -831,8 +830,7 @@ namespace Ryujinx.Ava.Systems Logger.Info?.Print(LogClass.Application, "Loading as cart WITHOUT RomFS."); if (!Device.LoadCart(ApplicationPath)) { - await ContentDialogHelper.CreateErrorDialog( - "Please specify an unpacked game directory with a valid exefs or NSO/NRO."); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.Error_NoUnpackedApplicationFoundInFolder)); Device.Dispose(); cts.Cancel(); throw new OperationCanceledException(cts.Token); diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs index 39e53184f..c74580dfd 100644 --- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -250,7 +250,7 @@ namespace Ryujinx.Ava.UI.ViewModels private Task ShowNewDlcAddedDialog(int numAdded) { - string msg = string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowDlcAddedMessage], numAdded); + string msg = string.Format(LocaleManager.Instance[LocaleKeys.Dialog_ContentLoading_DLCAddedMessage], numAdded); return Dispatcher.UIThread.InvokeAsync(async () => { await ContentDialogHelper.ShowTextDialog( diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index a30d273b9..51c05a692 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -136,9 +136,6 @@ namespace Ryujinx.Ava.UI.ViewModels [ObservableProperty] public partial float VolumeBeforeMute { get; set; } - [ObservableProperty] - public partial bool AreMimeTypesRegistered { get; set; } = FileAssociationHelper.AreMimeTypesRegistered; - [ObservableProperty] public partial Cursor Cursor { get; set; } [ObservableProperty] public partial string Title { get; set; } @@ -219,6 +216,11 @@ namespace Ryujinx.Ava.UI.ViewModels _rendererWaitEvent = new AutoResetEvent(false); + LocaleManager.Instance.PropertyChanged += (sender, args) => + { + RefreshFileTypeAssociationToggle(); + }; + if (Program.PreviewerDetached) { LoadConfigurableHotKeys(); @@ -679,11 +681,6 @@ namespace Ryujinx.Ava.UI.ViewModels get => ConsoleHelper.SetConsoleWindowStateSupported; } - public bool ManageFileTypesVisible - { - get => FileAssociationHelper.IsTypeAssociationSupported; - } - public Glyph Glyph { get => (Glyph)ConfigurationState.Instance.UI.GameListViewMode.Value; @@ -941,6 +938,71 @@ namespace Ryujinx.Ava.UI.ViewModels return false; } + public bool FileTypeAssociationsVisible + { + get => FileAssociationHelper.IsTypeAssociationSupported; + } + + private void RefreshFileTypeAssociationToggle() + { + OnPropertyChanged(nameof(FileTypeAssociationsMenuHeader)); + OnPropertyChanged(nameof(FileTypeAssociationsIcon)); + } + + private bool _areMimeTypesRegistered = FileAssociationHelper.AreMimeTypesRegistered; + + public bool AreMimeTypesRegistered + { + get => _areMimeTypesRegistered; + set + { + if (_areMimeTypesRegistered != value) + { + _areMimeTypesRegistered = value; + RefreshFileTypeAssociationToggle(); + } + } + } + + public string FileTypeAssociationsMenuHeader => + AreMimeTypesRegistered + ? LocaleManager.Instance[LocaleKeys.MenuBar_File_RemoveFileTypeAssociationsButton] + : LocaleManager.Instance[LocaleKeys.MenuBar_File_AssociateFileTypesButton]; + + public string FileTypeAssociationsIcon => + AreMimeTypesRegistered + ? "fa-solid fa-link-slash" + : "fa-solid fa-link"; + + [RelayCommand] + private async Task ToggleFileTypeAssociations() + { + if (AreMimeTypesRegistered) + await RemoveFileTypeAssociations(); + else + await AssociateFileTypes(); + } + + [RelayCommand] + private async Task AssociateFileTypes() + { + AreMimeTypesRegistered = FileAssociationHelper.Install(); + if (AreMimeTypesRegistered) + await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.Dialog_FileTypeAssociations_AssociationSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty); + else + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.Dialog_FileTypeAssociations_AssociationFailedMessage]); + } + + [RelayCommand] + private async Task RemoveFileTypeAssociations() + { + AreMimeTypesRegistered = !FileAssociationHelper.Uninstall(); + if (!AreMimeTypesRegistered) + await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.Dialog_FileTypeAssociations_RemoveAssociationSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty); + else + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.Dialog_FileTypeAssociations_RemoveAssociationFailedMessage]); + } + public async Task HandleFirmwareInstallation(string filename) { try @@ -1597,11 +1659,14 @@ namespace Ryujinx.Ava.UI.ViewModels AppHost.Device.System.SimulateWakeUpMessage(); } - public async Task OpenFile() + public KeyGesture LoadApplicationFromFileGesture => KeyGesture.Parse(OperatingSystem.IsMacOS() ? "Cmd+O" : "Ctrl+O"); + public KeyGesture LoadUnpackedGameFromFolderFileGesture => KeyGesture.Parse(OperatingSystem.IsMacOS() ? "Cmd+Shift+O" : "Ctrl+Shift+O"); + + public async Task LoadApplicationFromFile() { Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions { - Title = LocaleManager.Instance[LocaleKeys.LoadApplicationFromFileDialogTitle], + Title = LocaleManager.Instance[LocaleKeys.Dialog_FileMenu_LoadApplicationFromFileFilePickerTitle], FileTypeFilter = new List { new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) @@ -1667,35 +1732,17 @@ namespace Ryujinx.Ava.UI.ViewModels else { await ContentDialogHelper.CreateErrorDialog( - LocaleManager.Instance[LocaleKeys.MenuBarFileOpenFromFileError]); + LocaleManager.Instance[LocaleKeys.Error_NoApplicationFoundInFile]); } } } - public async Task LoadDlcFromFolder() - { - await LoadContentFromFolder( - LocaleKeys.AutoloadDlcAddedMessage, - LocaleKeys.AutoloadDlcRemovedMessage, - ApplicationLibrary.AutoLoadDownloadableContents, - LocaleKeys.LoadDLCFromFolderDialogTitle); - } - - public async Task LoadTitleUpdatesFromFolder() - { - await LoadContentFromFolder( - LocaleKeys.AutoloadUpdateAddedMessage, - LocaleKeys.AutoloadUpdateRemovedMessage, - ApplicationLibrary.AutoLoadTitleUpdates, - LocaleKeys.LoadTitleUpdatesFromFolderDialogTitle); - } - - public async Task OpenFolder() + public async Task LoadUnpackedGameFromFolder() { Optional result = await StorageProvider.OpenSingleFolderPickerAsync( new FolderPickerOpenOptions { - Title = LocaleManager.Instance[LocaleKeys.LoadUnpackedGameFromFolderDialogTitle] + Title = LocaleManager.Instance[LocaleKeys.Dialog_FileMenu_LoadUnpackedApplicationFromFolderFilePickerTitle] }); if (result.TryGet(out IStorageFolder value)) @@ -1709,6 +1756,36 @@ namespace Ryujinx.Ava.UI.ViewModels } } + private async Task?> PickFolders(LocaleKeys titleKey) + { + return (await StorageProvider.OpenMultiFolderPickerAsync(new FolderPickerOpenOptions + { + Title = LocaleManager.Instance[titleKey] + })).TryGet(out IReadOnlyList folders) + ? folders.Select(f => f.Path.LocalPath).ToList() + : null; + } + + public async Task LoadTitleUpdatesAndDLCFromFolder() + { + if (await PickFolders(LocaleKeys.Dialog_FileMenu_LoadUpdatesAndDLCFromFolderFilePickerTitle) is not { } dirs) + return; + + int updAdded = ApplicationLibrary.AutoLoadTitleUpdates(dirs.ToList(), out _); + int dlcAdded = ApplicationLibrary.AutoLoadDownloadableContents(dirs.ToList(), out _); + + await Dispatcher.UIThread.InvokeAsync(async () => + { + await ContentDialogHelper.ShowTextDialog( + LocaleManager.Instance[LocaleKeys.RyujinxConfirm], + string.Format(LocaleManager.Instance[LocaleKeys.Dialog_ContentLoading_UpdatesAddedMessage], updAdded) + "\n\n" + + string.Format(LocaleManager.Instance[LocaleKeys.Dialog_ContentLoading_DLCAddedMessage], dlcAdded), + string.Empty, string.Empty, string.Empty, + LocaleManager.Instance[LocaleKeys.InputDialogOk], + (int)Symbol.Checkmark); + }); + } + public static bool InitializeUserConfig(ApplicationData application) { // Code where conditions will be met before loading the user configuration (Global Config) diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index 3d34643ab..8393bc93c 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -187,7 +187,7 @@ namespace Ryujinx.Ava.UI.ViewModels private Task ShowNewUpdatesAddedDialog(int numAdded) { - string msg = string.Format(LocaleManager.Instance[LocaleKeys.UpdateWindowUpdateAddedMessage], numAdded); + string msg = string.Format(LocaleManager.Instance[LocaleKeys.Dialog_ContentLoading_UpdatesAddedMessage], numAdded); return Dispatcher.UIThread.InvokeAsync(async () => await ContentDialogHelper.ShowTextDialog( LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle], diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index bd06c04c6..0237f140d 100755 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -7,6 +7,7 @@ mc:Ignorable="d" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls" + xmlns:i="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia" xmlns:common="clr-namespace:Ryujinx.Common;assembly=Ryujinx.Common" xmlns:renderDocApi="clr-namespace:Ryujinx.Graphics.RenderDocApi;assembly=Ryujinx.Graphics.RenderDocApi" x:DataType="viewModels:MainWindowViewModel" @@ -29,50 +30,53 @@ - + + IsEnabled="{Binding EnableNonGameRunningControls}" + InputGesture="{Binding LoadApplicationFromFileGesture}" /> + IsEnabled="{Binding EnableNonGameRunningControls}" + InputGesture="{Binding LoadUnpackedGameFromFolderFileGesture}" /> - + Header="{ext:Locale MenuBar_File_OpenLogsFolderButton}" + Icon="{ext:Icon fa-solid fa-folder-closed}" /> - - - - + Header="{ext:Locale MenuBar_File_OpenScreenshotsFolderButton}" + Icon="{ext:Icon fa-solid fa-folder-closed}" /> + + + + + + Header="{ext:Locale MenuBar_File_ExitButton}" + Icon="{ext:Icon fa-solid fa-arrow-right-from-bracket}" /> Window?.Close()); OpenSettingsMenuItem.Command = Commands.Create(OpenSettings); @@ -44,8 +43,6 @@ namespace Ryujinx.Ava.UI.Views.Main ResumeEmulationMenuItem.Command = Commands.Create(() => ViewModel.AppHost?.Resume()); StopEmulationMenuItem.Command = Commands.Create(() => ViewModel.AppHost?.ShowExitPrompt().OrCompleted()); RestartEmulationMenuItem.Command = Commands.Create(() => ViewModel.RestartEmulation()); - InstallFileTypesMenuItem.Command = Commands.Create(InstallFileTypes); - UninstallFileTypesMenuItem.Command = Commands.Create(UninstallFileTypes); XciTrimmerMenuItem.Command = Commands.Create(XciTrimmerView.Show); AboutWindowMenuItem.Command = Commands.Create(AboutView.Show); CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityListWindow.Show()); @@ -189,24 +186,6 @@ namespace Ryujinx.Ava.UI.Views.Main ViewModel.ShowSkylanderActions = string.Equals(ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper(), "0100CCC0002E6000"); } - private async Task InstallFileTypes() - { - ViewModel.AreMimeTypesRegistered = FileAssociationHelper.Install(); - if (ViewModel.AreMimeTypesRegistered) - await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty); - else - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesErrorMessage]); - } - - private async Task UninstallFileTypes() - { - ViewModel.AreMimeTypesRegistered = !FileAssociationHelper.Uninstall(); - if (!ViewModel.AreMimeTypesRegistered) - await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty); - else - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesErrorMessage]); - } - private void ChangeWindowSize(string resolution) { (int resolutionWidth, int resolutionHeight) = resolution.Split(' ', 2) diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml b/src/Ryujinx/UI/Windows/MainWindow.axaml index a38e2bbbc..2ed915a37 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml @@ -45,6 +45,10 @@ + + + + diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index 365b00b77..a7e928224 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -741,10 +741,10 @@ namespace Ryujinx.Ava.UI.Windows { string[] messages = [ - numDlcRemoved > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.AutoloadDlcRemovedMessage], numDlcRemoved): null, - numDlcAdded > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.AutoloadDlcAddedMessage], numDlcAdded): null, - numUpdatesRemoved > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.AutoloadUpdateRemovedMessage], numUpdatesRemoved): null, - numUpdatesAdded > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.AutoloadUpdateAddedMessage], numUpdatesAdded) : null + numDlcRemoved > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.Dialog_ContentLoading_DLCRemovedMessage], numDlcRemoved): null, + numDlcAdded > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.Dialog_ContentLoading_DLCAddedMessage], numDlcAdded): null, + numUpdatesRemoved > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.Dialog_ContentLoading_UpdatesRemovedMessage], numUpdatesRemoved): null, + numUpdatesAdded > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.Dialog_ContentLoading_UpdatesAddedMessage], numUpdatesAdded) : null ]; string msg = String.Join("\r\n", messages);