diff --git a/assets/Locales/Amiibo.json b/assets/Locales/Amiibo.json new file mode 100644 index 000000000..57cab92f7 --- /dev/null +++ b/assets/Locales/Amiibo.json @@ -0,0 +1,229 @@ +{ + "Locales": [ + { + "ID": "WindowTitle", + "Translations": { + "ar_SA": "أميبو", + "de_DE": "", + "el_GR": "", + "en_US": "Amiibo", + "es_ES": null, + "fr_FR": null, + "he_IL": "אמיבו", + "it_IT": "", + "ja_JP": "", + "ko_KR": null, + "no_NO": "", + "pl_PL": "", + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": "อมิโบ้", + "tr_TR": "", + "uk_UA": "", + "zh_CN": null, + "zh_TW": null + } + }, + { + "ID": "SeriesLabel", + "Translations": { + "ar_SA": "سلسلة", + "de_DE": "Serie", + "el_GR": "Σειρά", + "en_US": "Series", + "es_ES": "Serie", + "fr_FR": "Séries", + "he_IL": "סדרה", + "it_IT": "Serie", + "ja_JP": "シリーズ", + "ko_KR": "시리즈", + "no_NO": "Serie", + "pl_PL": "Seria", + "pt_BR": "Série", + "ru_RU": "Серия", + "sv_SE": "Serie", + "th_TH": "ซีรีส์", + "tr_TR": "Seri", + "uk_UA": "Серія", + "zh_CN": "系列", + "zh_TW": "系列" + } + }, + { + "ID": "ShowAllAmiiboLabel", + "Translations": { + "ar_SA": "إظهار الكل Amiibo", + "de_DE": "Alle Amiibo anzeigen", + "el_GR": "Εμφάνιση Όλων των Amiibo", + "en_US": "Show All Amiibo", + "es_ES": "Mostrar Todas las Amiibo", + "fr_FR": "Afficher Tous les Amiibo", + "he_IL": "הצג הכל Amiibo", + "it_IT": "Mostra tutti gli Amiibo", + "ja_JP": "すべてのAmiiboを表示", + "ko_KR": "모든 Amiibo 표시", + "no_NO": "Vis alle Amiibo", + "pl_PL": "Pokaż Wszystkie Amiibo", + "pt_BR": "Mostrar Todos os Amiibo", + "ru_RU": "Показывать все Amiibo", + "sv_SE": "Visa alla Amiibo", + "th_TH": "แสดง Amiibo ทั้งหมด", + "tr_TR": "Tüm Amiibo'ları Göster", + "uk_UA": "Показати всі Amiibo", + "zh_CN": "显示所有 Amiibo", + "zh_TW": "顯示所有 Amiibo" + } + }, + { + "ID": "UseRandomUuidLabel", + "Translations": { + "ar_SA": "استخدام UUID عشوائي", + "de_DE": "Zufällige UUID verwenden", + "el_GR": "Χρήση τυχαίου UUID", + "en_US": "Use Random UUID", + "es_ES": "Usar UUID aleatorio", + "fr_FR": "Utiliser un UUID aléatoire", + "he_IL": "השתמש ב-UUID אקראי", + "it_IT": "Usa UUID casuale", + "ja_JP": "ランダム UUID を使用", + "ko_KR": "무작위 UUID 사용", + "no_NO": "Bruk tilfeldig UUID", + "pl_PL": "Użyj losowego UUID", + "pt_BR": "Usar UUID aleatório", + "ru_RU": "Использовать случайный UUID", + "sv_SE": "Använd slumpmässig UUID", + "th_TH": "ใช้ UUID แบบสุ่ม", + "tr_TR": "Rastgele UUID kullan", + "uk_UA": "Використовувати випадковий UUID", + "zh_CN": "使用随机 UUID", + "zh_TW": "使用隨機 UUID" + } + }, + { + "ID": "PauseEmulationWhileScanningAmiibo", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Pause Emulation While Scanning", + "es_ES": "", + "fr_FR": "", + "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": "UsageLabel", + "Translations": { + "ar_SA": "الاستخدام:", + "de_DE": "Nutzung:", + "el_GR": "Χρήση:", + "en_US": "Usage:", + "es_ES": "Uso:", + "fr_FR": "Utilisation :", + "he_IL": "שימוש:", + "it_IT": "Utilizzo:", + "ja_JP": "使用法:", + "ko_KR": "사용법:", + "no_NO": "Forbruk:", + "pl_PL": "Użycie:", + "pt_BR": "Uso:", + "ru_RU": "Применение:", + "sv_SE": "Användning:", + "th_TH": "การใช้งาน:", + "tr_TR": "Kullanım:", + "uk_UA": "Використання:", + "zh_CN": "用法:", + "zh_TW": "用途:" + } + }, + { + "ID": "WritableLabel", + "Translations": { + "ar_SA": "الاستخدام (يمكنه حفظ البيانات):", + "de_DE": "Nutzung (Kann Daten speichern):", + "el_GR": "Χρήση (Μπορεί να αποθηκεύσει δεδομένα):", + "en_US": "Usage (Can Save Data):", + "es_ES": "Uso (Puede guardar datos):", + "fr_FR": "Utilisation (Peut enregistrer des données) :", + "he_IL": "שימוש (יכול לשמור נתונים):", + "it_IT": "Utilizzo (Può salvare dati):", + "ja_JP": "使用法(データを保存できます):", + "ko_KR": "사용법 (데이터 저장 가능):", + "no_NO": "Bruk (Kan lagre data):", + "pl_PL": "Użycie (Może zapisywać dane):", + "pt_BR": "Uso (Pode salvar dados):", + "ru_RU": "Применение (Может сохранять данные):", + "sv_SE": "Användning (Kan spara data):", + "th_TH": "การใช้งาน (สามารถบันทึกข้อมูลได้):", + "tr_TR": "Kullanım (Veri kaydedebilir):", + "uk_UA": "Використання (Може зберігати дані):", + "zh_CN": "用法(可保存数据):", + "zh_TW": "用途(可儲存資料):" + } + }, + { + "ID": "UnknownLabel", + "Translations": { + "ar_SA": "غير معروف", + "de_DE": "Unbekannt", + "el_GR": "Άγνωστο", + "en_US": "Unknown", + "es_ES": "Desconocido", + "fr_FR": "Inconnu", + "he_IL": "לא ידוע", + "it_IT": "Sconosciuto", + "ja_JP": "不明", + "ko_KR": "알 수 없음", + "no_NO": "Ukjent", + "pl_PL": "Nieznane", + "pt_BR": "Desconhecido", + "ru_RU": "Неизвестно", + "sv_SE": "Okänt", + "th_TH": "ไม่รู้จัก", + "tr_TR": "Bilinmeyen", + "uk_UA": "Невідомо", + "zh_CN": "未知", + "zh_TW": "未知" + } + }, + { + "ID": "ScanButton", + "Translations": { + "ar_SA": "فحص Amiibo", + "de_DE": "Amiibo einscannen", + "el_GR": "Σαρώστε το Amiibo", + "en_US": "Scan Amiibo", + "es_ES": "Escanear Amiibo", + "fr_FR": "Scanner l'Amiibo", + "he_IL": "סרוק את ה-Amiibo", + "it_IT": "Scansiona l'Amiibo", + "ja_JP": "Amiiboをスキャン", + "ko_KR": "Amiibo 스캔하기", + "no_NO": "Skanne Amiibo", + "pl_PL": "Zeskanuj Amiibo", + "pt_BR": "Escanear Amiibo", + "ru_RU": "Сканировать Amiibo", + "sv_SE": "Skanna Amiibo", + "th_TH": "สแกน Amiibo", + "tr_TR": "Amiibo'yu tara", + "uk_UA": "Сканувати Amiibo", + "zh_CN": "扫描 Amiibo", + "zh_TW": "掃描 Amiibo" + } + } + ] +} diff --git a/assets/Locales/Common_Buttons.json b/assets/Locales/Common_Buttons.json new file mode 100644 index 000000000..1198c2cc6 --- /dev/null +++ b/assets/Locales/Common_Buttons.json @@ -0,0 +1,29 @@ +{ + "Locales": [ + { + "ID": "Cancel", + "Translations": { + "ar_SA": "إلغاء", + "de_DE": "Abbrechen", + "el_GR": "Ακύρωση", + "en_US": "Cancel", + "es_ES": "Cancelar", + "fr_FR": "Annuler", + "he_IL": "ביטול", + "it_IT": "Annulla", + "ja_JP": "キャンセル", + "ko_KR": "취소", + "no_NO": "Avbryt", + "pl_PL": "Anuluj", + "pt_BR": "Cancelar", + "ru_RU": "Отмена", + "sv_SE": "Avbryt", + "th_TH": "ยกเลิก", + "tr_TR": "İptal", + "uk_UA": "Скасувати", + "zh_CN": "取消", + "zh_TW": "取消" + } + } + ] +} diff --git a/assets/Locales/Common_FilePicker.json b/assets/Locales/Common_FilePicker.json new file mode 100644 index 000000000..751ca0847 --- /dev/null +++ b/assets/Locales/Common_FilePicker.json @@ -0,0 +1,29 @@ +{ + "Locales": [ + { + "ID": "AllSupportedFormats", + "Translations": { + "ar_SA": "كل التنسيقات المدعومة", + "de_DE": "Alle unterstützten Formate", + "el_GR": "Όλες Οι Υποστηριζόμενες Μορφές", + "en_US": "All Supported Formats", + "es_ES": "Todos los Formatos Soportados", + "fr_FR": "Tous les Formats Supportés", + "he_IL": "כל הפורמטים הנתמכים", + "it_IT": "Tutti i formati supportati", + "ja_JP": "すべての対応フォーマット", + "ko_KR": "지원되는 모든 형식", + "no_NO": "Alle støttede formater", + "pl_PL": "Wszystkie Obsługiwane Formaty", + "pt_BR": "Todos os Formatos Suportados", + "ru_RU": "Все поддерживаемые форматы", + "sv_SE": "Alla format som stöds", + "th_TH": "รูปแบบที่รองรับทั้งหมด", + "tr_TR": "Tüm Desteklenen Formatlar", + "uk_UA": "Усі підтримувані формати", + "zh_CN": "所有支持的格式", + "zh_TW": "所有支援的格式" + } + } + ] +} diff --git a/assets/Locales/Common_Search.json b/assets/Locales/Common_Search.json index 9fbe786be..32900955a 100644 --- a/assets/Locales/Common_Search.json +++ b/assets/Locales/Common_Search.json @@ -1,5 +1,30 @@ { "Locales": [ + { + "ID": "SearchAmiiboWatermark", + "Translations": { + "ar_SA": "بحث Amiibo...", + "de_DE": "Amiibo suchen...", + "el_GR": "Αναζήτηση Amiibo...", + "en_US": "Search Amiibo...", + "es_ES": "Buscar Amiibo...", + "fr_FR": "Rechercher Amiibo...", + "he_IL": "חפש Amiibo...", + "it_IT": "Cerca Amiibo...", + "ja_JP": "Amiiboを検索...", + "ko_KR": "Amiibo 검색...", + "no_NO": "Søk Amiibo...", + "pl_PL": "Wyszukaj Amiibo...", + "pt_BR": "Buscar Amiibo...", + "ru_RU": "Поиск Amiibo...", + "sv_SE": "Sök Amiibo...", + "th_TH": "ค้นหา Amiibo...", + "tr_TR": "Amiibo Ara...", + "uk_UA": "Пошук Amiibo...", + "zh_CN": "搜索 Amiibo...", + "zh_TW": "搜尋 Amiibo..." + } + }, { "ID": "SearchWatermark", "Translations": { diff --git a/assets/Locales/Dialog_Amiibo.json b/assets/Locales/Dialog_Amiibo.json new file mode 100644 index 000000000..bc3861b54 --- /dev/null +++ b/assets/Locales/Dialog_Amiibo.json @@ -0,0 +1,179 @@ +{ + "Locales": [ + { + "ID": "ScanAmiiboFromBinFilePickerTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Select a BIN file to scan an Amiibo from", + "es_ES": "Selecciona un archivo BIN para escanear un Amiibo", + "fr_FR": "Sélectionnez un fichier BIN pour scanner un Amiibo", + "he_IL": "", + "it_IT": "Seleziona un file BIN da cui scansionare un Amiibo", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Selecione um arquivo BIN para escanear um Amiibo", + "ru_RU": "Выберите BIN-файл для сканирования Amiibo", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть BIN-файл для сканування Amiibo", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "APITitle", + "Translations": { + "ar_SA": "أميبو API", + "de_DE": "Amiibo-API", + "el_GR": "API για Amiibo.", + "en_US": "Amiibo API", + "es_ES": "API Amiibo", + "fr_FR": "API Amiibo", + "he_IL": "ממשק תכנות אמיבו", + "it_IT": "API Amiibo", + "ja_JP": "", + "ko_KR": null, + "no_NO": "", + "pl_PL": "API Amiibo", + "pt_BR": "API Amiibo", + "ru_RU": "API Amiibo", + "sv_SE": "Amiibo-API", + "th_TH": "อามิโบ้ API", + "tr_TR": "", + "uk_UA": "API Amiibo", + "zh_CN": null, + "zh_TW": null + } + }, + { + "ID": "APIFailFetchMessage", + "Translations": { + "ar_SA": "حدث خطأ أثناء جلب المعلومات من API.", + "de_DE": "Beim Abrufen von Informationen aus der API ist ein Fehler aufgetreten.", + "el_GR": "Παρουσιάστηκε σφάλμα κατά την ανάκτηση πληροφοριών από το API.", + "en_US": "An error occured while fetching information from the API.", + "es_ES": "Ocurrió un error al recibir información de la API.", + "fr_FR": "Une erreur est survenue lors de la récupération des informations de l'API.", + "he_IL": "אירעה שגיאה בעת שליפת מידע מהממשק.", + "it_IT": "Si è verificato un errore durante il recupero delle informazioni dall'API.", + "ja_JP": "API からの情報取得中にエラーが発生しました.", + "ko_KR": "API에서 정보를 가져오는 중에 오류가 발생했습니다.", + "no_NO": "En feil oppstod under henting av informasjon fra API.", + "pl_PL": "Wystąpił błąd podczas pobierania informacji z API.", + "pt_BR": "Um erro ocorreu ao tentar obter informações da API.", + "ru_RU": "Произошла ошибка при получении информации из API.", + "sv_SE": "Ett fel inträffade vid hämtning av information från API.", + "th_TH": "เกิดข้อผิดพลาดขณะเรียกข้อมูลจาก API", + "tr_TR": "API'dan bilgi alırken bir hata oluştu.", + "uk_UA": "Під час отримання інформації з API сталася помилка.", + "zh_CN": "从 API 获取信息时出错。", + "zh_TW": "從 API 取得資訊時出現錯誤。" + } + }, + { + "ID": "APIConnectErrorMessage", + "Translations": { + "ar_SA": "غير قادر على الاتصال بخادم API أميبو. قد تكون الخدمة معطلة أو قد تحتاج إلى التحقق من اتصالك بالإنترنت.", + "de_DE": "Verbindung zum Amiibo API Server kann nicht hergestellt werden. Der Dienst ist möglicherweise nicht verfügbar oder es existiert keine Internetverbindung.", + "el_GR": "Δεν είναι δυνατή η σύνδεση με τον διακομιστή Amiibo API. Η υπηρεσία μπορεί να είναι εκτός λειτουργίας ή μπορεί να χρειαστεί να επαληθεύσετε ότι έχετε ενεργή σύνδεσή στο Διαδίκτυο.", + "en_US": "Unable to connect to Amiibo API server. The service may be down or you may need to verify your internet connection is online.", + "es_ES": "No se pudo conectar al servidor de la API Amiibo. El servicio puede estar caído o tu conexión a internet puede haberse desconectado.", + "fr_FR": "Impossible de se connecter au serveur API Amiibo. Le service est peut-être hors service ou vous devriez peut-être vérifier que votre connexion internet est connectée.", + "he_IL": "לא ניתן להתחבר לממשק שרת האמיבו. ייתכן שהשירות מושבת או שתצטרך לוודא שהחיבור לאינטרנט שלך מקוון.", + "it_IT": "Impossibile connettersi al server dell'API Amiibo. Il servizio potrebbe non essere disponibile o potresti non essere connesso a Internet.", + "ja_JP": "Amiibo API サーバに接続できませんでした. サーバがダウンしているか, インターネット接続に問題があるかもしれません.", + "ko_KR": "Amiibo API 서버에 연결할 수 없습니다. 서비스가 다운되었거나 인터넷 연결이 온라인 상태인지 확인이 필요합니다.", + "no_NO": "Kan ikke koble til Amiibo API server. Tjenesten kan være nede, eller du må kanskje verifisere at din internettforbindelse er tilkoblet.", + "pl_PL": "Nie można połączyć się z serwerem API Amiibo. Usługa może nie działać lub może być konieczne sprawdzenie, czy połączenie internetowe jest online.", + "pt_BR": "Não foi possível conectar ao servidor da API Amiibo. O serviço pode estar fora do ar ou você precisa verificar sua conexão com a Internet.", + "ru_RU": "Не удалось подключиться к серверу Amiibo API. Служба может быть недоступна или вам может потребоваться проверить ваше интернет-соединение.", + "sv_SE": "Kunde inte ansluta till Amiibo API-server. Tjänsten kanske är nere eller så behöver du kontrollera att din internetanslutning fungerar.", + "th_TH": "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ Amiibo API บางบริการอาจหยุดทำงาน หรือไม่คุณต้องทำการตรวจสอบว่าอินเทอร์เน็ตของคุณอยู่ในสถานะเชื่อมต่ออยู่หรือไม่", + "tr_TR": "Amiibo API sunucusuna bağlanılamadı. Sunucu çevrimdışı olabilir veya uygun bir internet bağlantınızın olduğunu kontrol etmeniz gerekebilir.", + "uk_UA": "Неможливо підключитися до сервера Amiibo API. Можливо, служба не працює або вам потрібно перевірити, чи є підключення до Інтернету.", + "zh_CN": "无法连接到 Amiibo API 服务器,服务可能已关闭,或者没有连接互联网。", + "zh_TW": "無法連接 Amiibo API 伺服器。服務可能已停機,或者您可能需要確認網際網路連線是否在線上。" + } + }, + { + "ID": "RenameAmiiboTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Rename Amiibo", + "es_ES": "Renombrar Amiibo", + "fr_FR": "Renommer l'Amiibo", + "he_IL": "", + "it_IT": "Rinomina Amiibo", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Renomear Amiibo", + "ru_RU": "Переименовать Amiibo", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Перейменувати Amiibo", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "ScanAmiiboTitle", + "Translations": { + "ar_SA": "فحص Amiibo", + "de_DE": "Amiibo einscannen", + "el_GR": "Σαρώστε το Amiibo", + "en_US": "Scan Amiibo", + "es_ES": "Escanear Amiibo", + "fr_FR": "Scanner l'Amiibo", + "he_IL": "סרוק את ה-Amiibo", + "it_IT": "Scansiona l'Amiibo", + "ja_JP": "Amiiboをスキャン", + "ko_KR": "Amiibo 스캔하기", + "no_NO": "Skanne Amiibo", + "pl_PL": "Zeskanuj Amiibo", + "pt_BR": "Escanear Amiibo", + "ru_RU": "Сканировать Amiibo", + "sv_SE": "Skanna Amiibo", + "th_TH": "สแกน Amiibo", + "tr_TR": "Amiibo'yu tara", + "uk_UA": "Сканувати Amiibo", + "zh_CN": "扫描 Amiibo", + "zh_TW": "掃描 Amiibo" + } + }, + { + "ID": "ScanAmiiboMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Please scan your Amiibo now.", + "es_ES": "Escanea tu Amiibo ahora.", + "fr_FR": "Veuillez scannez votre Amiibo.", + "he_IL": "", + "it_IT": "Scansiona ora il tuo Amiibo.", + "ja_JP": "", + "ko_KR": "지금 Amiibo를 스캔하세요.", + "no_NO": "Vennligst skann Amiiboene dine nå.", + "pl_PL": "", + "pt_BR": "Por favor, escaneie seu Amiibo agora.", + "ru_RU": "Пожалуйста, сканируйте ваш Amiibo.", + "sv_SE": "Skanna din Amiibo nu.", + "th_TH": "กรุณาสแกน Amiibo ของคุณตอนนี้", + "tr_TR": "", + "uk_UA": "Будь ласка, проскануйте Ваш Amiibo.", + "zh_CN": "请现在扫描你的 Amiibo", + "zh_TW": "請掃描你的 Amiibo。" + } + } + ] +} \ No newline at end of file diff --git a/assets/Locales/Dialog_Skylanders.json b/assets/Locales/Dialog_Skylanders.json new file mode 100644 index 000000000..fb7daea94 --- /dev/null +++ b/assets/Locales/Dialog_Skylanders.json @@ -0,0 +1,29 @@ +{ + "Locales": [ + { + "ID": "ScanSkylanderFilePickerTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Select a BIN, SKY, DMP, or DUMP file to scan a Skylander from", + "es_ES": "Selecciona un archivo BIN, SKY, DMP o DUMP para escanear un Skylander", + "fr_FR": "Sélectionnez un fichier BIN, SKY, DMP ou DUMP pour scanner un Skylander", + "he_IL": "", + "it_IT": "Seleziona un file BIN, SKY, DMP o DUMP da cui scansionare uno Skylander", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "Selecione um arquivo BIN, SKY, DMP ou DUMP para escanear um Skylander", + "ru_RU": "Выберите файл BIN, SKY, DMP или DUMP для сканирования Skylander", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Виберіть файл BIN, SKY, DMP або DUMP для сканування Skylander", + "zh_CN": "", + "zh_TW": "" + } + } + ] +} diff --git a/assets/Locales/MenuBar_Actions.json b/assets/Locales/MenuBar_Actions.json index 1d0f97d4c..2508de727 100644 --- a/assets/Locales/MenuBar_Actions.json +++ b/assets/Locales/MenuBar_Actions.json @@ -378,26 +378,26 @@ { "ID": "ScanAmiiboFromBinButton", "Translations": { - "ar_SA": "مسح Amiibo (.BIN)", - "de_DE": "Amiibo scannen (.BIN)", - "el_GR": "Σάρωση Amiibo (.BIN)", - "en_US": "Scan Amiibo (.BIN)", - "es_ES": "Escanear un Amiibo (.BIN)", - "fr_FR": "Scanner un Amiibo (.BIN)", - "he_IL": "סרוק Amiibo (.BIN)", - "it_IT": "Scansiona un Amiibo (.BIN)", - "ja_JP": "Amiibo をスキャン (.BIN)", - "ko_KR": "Amiibo 스캔 (.BIN)", - "no_NO": "Skann en Amiibo (.BIN)", - "pl_PL": "Skanuj Amiibo (.BIN)", - "pt_BR": "Escaneie um Amiibo (.BIN)", - "ru_RU": "Сканировать Amiibo (.BIN)", - "sv_SE": "Skanna en Amiibo (.BIN)", - "th_TH": "สแกนอามีโบ (.BIN)", - "tr_TR": "Amiibo Tara (.BIN)", - "uk_UA": "Сканувати Amiibo (.BIN)", - "zh_CN": "扫描 Amiibo (.BIN)", - "zh_TW": "掃瞄 Amiibo (.BIN)" + "ar_SA": "مسح Amiibo (BIN)", + "de_DE": "Amiibo scannen (BIN)", + "el_GR": "Σάρωση Amiibo (BIN)", + "en_US": "Scan Amiibo (BIN)", + "es_ES": "Escanear un Amiibo (BIN)", + "fr_FR": "Scanner un Amiibo (BIN)", + "he_IL": "סרוק Amiibo (BIN)", + "it_IT": "Scansiona un Amiibo (BIN)", + "ja_JP": "Amiibo をスキャン (BIN)", + "ko_KR": "Amiibo 스캔 (BIN)", + "no_NO": "Skann en Amiibo (BIN)", + "pl_PL": "Skanuj Amiibo (BIN)", + "pt_BR": "Escaneie um Amiibo (BIN)", + "ru_RU": "Сканировать Amiibo (BIN)", + "sv_SE": "Skanna en Amiibo (BIN)", + "th_TH": "สแกนอามีโบ (BIN)", + "tr_TR": "Amiibo Tara (BIN)", + "uk_UA": "Сканувати Amiibo (BIN)", + "zh_CN": "扫描 Amiibo (BIN)", + "zh_TW": "掃瞄 Amiibo (BIN)" } }, { diff --git a/assets/Locales/Root.json b/assets/Locales/Root.json index f2a827bb3..46117fb97 100644 --- a/assets/Locales/Root.json +++ b/assets/Locales/Root.json @@ -175,156 +175,6 @@ "zh_TW": "" } }, - { - "ID": "MenuBarOptions", - "Translations": { - "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": "MenuBarOptionsToggleFullscreen", - "Translations": { - "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": "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": "Spiele ohne Benutzeroberfläche starten", - "el_GR": "", - "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": "Avvia i giochi con l'interfaccia nascosta", - "ja_JP": "", - "ko_KR": "UI를 숨긴 상태에서 게임 시작", - "no_NO": "Start Spillet med UI Gjemt", - "pl_PL": "", - "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": "启动游戏时隐藏 UI", - "zh_TW": "開啟遊戲時隱藏 UI" - } - }, - { - "ID": "MenuBarOptionsSettings", - "Translations": { - "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": "MenuBarOptionsManageUserProfiles", - "Translations": { - "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)" - } - }, { "ID": "MenuBarView", "Translations": { @@ -2125,56 +1975,6 @@ "zh_TW": "開啟此應用程式模組的另一個 SD 卡 Atmosphère 資料夾。適用於為真實硬體封裝的模組。" } }, - { - "ID": "GameListContextMenuTrimXCI", - "Translations": { - "ar_SA": "", - "de_DE": "XCI-Datei prüfen & trimmen", - "el_GR": "", - "en_US": "Check & Trim XCI File", - "es_ES": "Verificar & Recortar Archivo XCI", - "fr_FR": "Vérifier & Réduire le Fichier XCI", - "he_IL": "", - "it_IT": "Controlla & Riduci il File XCI", - "ja_JP": "", - "ko_KR": "XCI 파일 확인 & 트림", - "no_NO": "Kontroller & trim XCI-filen", - "pl_PL": "", - "pt_BR": "Verificar & Reduzir o Arquivo XCI", - "ru_RU": "Проверить & обрезать XCI файл", - "sv_SE": "Kontrollera & optimera XCI-fil", - "th_TH": "ตรวจสอบ & ลดขนาดไฟล์ XCI", - "tr_TR": "", - "uk_UA": "Перевірка & нарізка XCI Файлу", - "zh_CN": "检查并精简 XCI 文件", - "zh_TW": "檢查 & 修剪 XCI 檔案" - } - }, - { - "ID": "GameListContextMenuTrimXCIToolTip", - "Translations": { - "ar_SA": "", - "de_DE": "Trimmt und prüft die XCI-Datei um Speicherplatz zu sparen.", - "el_GR": "", - "en_US": "Check and Trim XCI File to Save Disk Space", - "es_ES": "Verificar y Recortar Archivo XCI para Ahorrar Espacio en Disco", - "fr_FR": "Vérifier et Réduire le Fichier XCI pour Économiser de l’Espace Disque", - "he_IL": "", - "it_IT": "Controlla e riduci la dimensione del file XCI per risparmiare spazio su disco", - "ja_JP": "", - "ko_KR": "디스크 공간을 절약하기 위해 XCI 파일 확인 및 트림", - "no_NO": "Kontroller og trimm XCI-filen for å spare diskplass", - "pl_PL": "", - "pt_BR": "Verifique e reduza o arquivo XCI para economizar espaço em disco", - "ru_RU": "Проверить и обрезать XCI файл для экономии места на диске", - "sv_SE": "Kontrollera och optimera XCI-fil för att spara diskutrymme", - "th_TH": "ตรวจสอบและลดขนาดไฟล์ XCI เพื่อประหยัดเนื้อที่เก็บข้อมูล", - "tr_TR": "", - "uk_UA": "Перевірити та обрізати XCI Файл задля збереження місця на диску", - "zh_CN": "检查并瘦身 XCI 文件以节约磁盘空间", - "zh_TW": "檢查及修剪 XCI 檔案以節省儲存空間" - } - }, { "ID": "StatusBarGamesLoaded", "Translations": { @@ -2200,31 +2000,6 @@ "zh_TW": "{0}/{1} 遊戲已載入" } }, - { - "ID": "StatusBarXCIFileTrimming", - "Translations": { - "ar_SA": "", - "de_DE": "XCI-Datei trimmen: '{0}'", - "el_GR": "", - "en_US": "Trimming XCI File '{0}'", - "es_ES": "Recortando el Siguiente Archivo XCI: '{0}'", - "fr_FR": "Réduction du Fichier XCI '{0}'", - "he_IL": "", - "it_IT": "Riduzione della dimensione del file XCI '{0}'", - "ja_JP": "", - "ko_KR": "XCI 파일 '{0}' 트리밍", - "no_NO": "Trimming av XCI-filen '{0}'", - "pl_PL": "", - "pt_BR": "Reduzindo o Arquivo XCI '{0}'", - "ru_RU": "Обрезается XCI файл '{0}'", - "sv_SE": "Optimerar XCI-filen '{0}'", - "th_TH": "กำลังลดขนาดไฟล์ XCI '{0}'", - "tr_TR": "", - "uk_UA": "Обрізається XCI Файлів '{0}'", - "zh_CN": "正在瘦身 XCI 文件 '{0}'", - "zh_TW": "正在修剪 XCI 檔案 '{0}'" - } - }, { "ID": "LinuxVmMaxMapCountDialogTitle", "Translations": { @@ -5750,31 +5525,6 @@ "zh_TW": "確定" } }, - { - "ID": "SettingsButtonCancel", - "Translations": { - "ar_SA": "إلغاء", - "de_DE": "Abbrechen", - "el_GR": "Ακύρωση", - "en_US": "Cancel", - "es_ES": "Cancelar", - "fr_FR": "Annuler", - "he_IL": "ביטול", - "it_IT": "Annulla", - "ja_JP": "キャンセル", - "ko_KR": "취소", - "no_NO": "Avbryt", - "pl_PL": "Anuluj", - "pt_BR": "Cancelar", - "ru_RU": "Отмена", - "sv_SE": "Avbryt", - "th_TH": "ยกเลิก", - "tr_TR": "İptal", - "uk_UA": "Скасувати", - "zh_CN": "取消", - "zh_TW": "取消" - } - }, { "ID": "SettingsButtonApply", "Translations": { @@ -9125,31 +8875,6 @@ "zh_TW": "確定" } }, - { - "ID": "InputDialogCancel", - "Translations": { - "ar_SA": "إلغاء", - "de_DE": "Abbrechen", - "el_GR": "Ακύρωση", - "en_US": "Cancel", - "es_ES": "Cancelar", - "fr_FR": "Annuler", - "he_IL": "ביטול", - "it_IT": "Annulla", - "ja_JP": "キャンセル", - "ko_KR": "취소", - "no_NO": "Avbryt", - "pl_PL": "Anuluj", - "pt_BR": "Cancelar", - "ru_RU": "Отмена", - "sv_SE": "Avbryt", - "th_TH": "ยกเลิก", - "tr_TR": "İptal", - "uk_UA": "Скасувати", - "zh_CN": "取消", - "zh_TW": "取消" - } - }, { "ID": "InputDialogCancelling", "Translations": { @@ -10900,81 +10625,6 @@ "zh_TW": "Ryujinx 錯誤 ({0})" } }, - { - "ID": "DialogAmiiboApiTitle", - "Translations": { - "ar_SA": "أميبو API", - "de_DE": "Amiibo-API", - "el_GR": "API για Amiibo.", - "en_US": "Amiibo API", - "es_ES": "API Amiibo", - "fr_FR": "API Amiibo", - "he_IL": "ממשק תכנות אמיבו", - "it_IT": "API Amiibo", - "ja_JP": "", - "ko_KR": null, - "no_NO": "", - "pl_PL": "API Amiibo", - "pt_BR": "API Amiibo", - "ru_RU": "API Amiibo", - "sv_SE": "Amiibo-API", - "th_TH": "อามิโบ้ API", - "tr_TR": "", - "uk_UA": "API Amiibo", - "zh_CN": null, - "zh_TW": null - } - }, - { - "ID": "DialogAmiiboApiFailFetchMessage", - "Translations": { - "ar_SA": "حدث خطأ أثناء جلب المعلومات من API.", - "de_DE": "Beim Abrufen von Informationen aus der API ist ein Fehler aufgetreten.", - "el_GR": "Παρουσιάστηκε σφάλμα κατά την ανάκτηση πληροφοριών από το API.", - "en_US": "An error occured while fetching information from the API.", - "es_ES": "Ocurrió un error al recibir información de la API.", - "fr_FR": "Une erreur est survenue lors de la récupération des informations de l'API.", - "he_IL": "אירעה שגיאה בעת שליפת מידע מהממשק.", - "it_IT": "Si è verificato un errore durante il recupero delle informazioni dall'API.", - "ja_JP": "API からの情報取得中にエラーが発生しました.", - "ko_KR": "API에서 정보를 가져오는 중에 오류가 발생했습니다.", - "no_NO": "En feil oppstod under henting av informasjon fra API.", - "pl_PL": "Wystąpił błąd podczas pobierania informacji z API.", - "pt_BR": "Um erro ocorreu ao tentar obter informações da API.", - "ru_RU": "Произошла ошибка при получении информации из API.", - "sv_SE": "Ett fel inträffade vid hämtning av information från API.", - "th_TH": "เกิดข้อผิดพลาดขณะเรียกข้อมูลจาก API", - "tr_TR": "API'dan bilgi alırken bir hata oluştu.", - "uk_UA": "Під час отримання інформації з API сталася помилка.", - "zh_CN": "从 API 获取信息时出错。", - "zh_TW": "從 API 取得資訊時出現錯誤。" - } - }, - { - "ID": "DialogAmiiboApiConnectErrorMessage", - "Translations": { - "ar_SA": "غير قادر على الاتصال بخادم API أميبو. قد تكون الخدمة معطلة أو قد تحتاج إلى التحقق من اتصالك بالإنترنت.", - "de_DE": "Verbindung zum Amiibo API Server kann nicht hergestellt werden. Der Dienst ist möglicherweise nicht verfügbar oder es existiert keine Internetverbindung.", - "el_GR": "Δεν είναι δυνατή η σύνδεση με τον διακομιστή Amiibo API. Η υπηρεσία μπορεί να είναι εκτός λειτουργίας ή μπορεί να χρειαστεί να επαληθεύσετε ότι έχετε ενεργή σύνδεσή στο Διαδίκτυο.", - "en_US": "Unable to connect to Amiibo API server. The service may be down or you may need to verify your internet connection is online.", - "es_ES": "No se pudo conectar al servidor de la API Amiibo. El servicio puede estar caído o tu conexión a internet puede haberse desconectado.", - "fr_FR": "Impossible de se connecter au serveur API Amiibo. Le service est peut-être hors service ou vous devriez peut-être vérifier que votre connexion internet est connectée.", - "he_IL": "לא ניתן להתחבר לממשק שרת האמיבו. ייתכן שהשירות מושבת או שתצטרך לוודא שהחיבור לאינטרנט שלך מקוון.", - "it_IT": "Impossibile connettersi al server dell'API Amiibo. Il servizio potrebbe non essere disponibile o potresti non essere connesso a Internet.", - "ja_JP": "Amiibo API サーバに接続できませんでした. サーバがダウンしているか, インターネット接続に問題があるかもしれません.", - "ko_KR": "Amiibo API 서버에 연결할 수 없습니다. 서비스가 다운되었거나 인터넷 연결이 온라인 상태인지 확인이 필요합니다.", - "no_NO": "Kan ikke koble til Amiibo API server. Tjenesten kan være nede, eller du må kanskje verifisere at din internettforbindelse er tilkoblet.", - "pl_PL": "Nie można połączyć się z serwerem API Amiibo. Usługa może nie działać lub może być konieczne sprawdzenie, czy połączenie internetowe jest online.", - "pt_BR": "Não foi possível conectar ao servidor da API Amiibo. O serviço pode estar fora do ar ou você precisa verificar sua conexão com a Internet.", - "ru_RU": "Не удалось подключиться к серверу Amiibo API. Служба может быть недоступна или вам может потребоваться проверить ваше интернет-соединение.", - "sv_SE": "Kunde inte ansluta till Amiibo API-server. Tjänsten kanske är nere eller så behöver du kontrollera att din internetanslutning fungerar.", - "th_TH": "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ Amiibo API บางบริการอาจหยุดทำงาน หรือไม่คุณต้องทำการตรวจสอบว่าอินเทอร์เน็ตของคุณอยู่ในสถานะเชื่อมต่ออยู่หรือไม่", - "tr_TR": "Amiibo API sunucusuna bağlanılamadı. Sunucu çevrimdışı olabilir veya uygun bir internet bağlantınızın olduğunu kontrol etmeniz gerekebilir.", - "uk_UA": "Неможливо підключитися до сервера Amiibo API. Можливо, служба не працює або вам потрібно перевірити, чи є підключення до Інтернету.", - "zh_CN": "无法连接到 Amiibo API 服务器,服务可能已关闭,或者没有连接互联网。", - "zh_TW": "無法連接 Amiibo API 伺服器。服務可能已停機,或者您可能需要確認網際網路連線是否在線上。" - } - }, { "ID": "DialogProfileInvalidProfileErrorMessage", "Translations": { @@ -12500,131 +12150,6 @@ "zh_TW": "在預設瀏覽器中開啟貢獻者的網頁" } }, - { - "ID": "AmiiboSeriesLabel", - "Translations": { - "ar_SA": "مجموعة أميبو", - "de_DE": "Amiibo-Serie", - "el_GR": "Σειρά Amiibo", - "en_US": "Amiibo Series", - "es_ES": "Serie de Amiibo", - "fr_FR": "Séries Amiibo", - "he_IL": "סדרת אמיבו", - "it_IT": "Serie Amiibo", - "ja_JP": "Amiibo シリーズ", - "ko_KR": "Amiibo 시리즈", - "no_NO": "Amibo Serie", - "pl_PL": "Seria Amiibo", - "pt_BR": "Franquia Amiibo", - "ru_RU": "Серия Amiibo", - "sv_SE": "Amiibo-serie", - "th_TH": "ชุดซีรีส์ Amiibo", - "tr_TR": "Amiibo Serisi", - "uk_UA": "Серія Amiibo", - "zh_CN": "Amiibo 系列", - "zh_TW": "Amiibo 系列" - } - }, - { - "ID": "AmiiboCharacterLabel", - "Translations": { - "ar_SA": "شخصية", - "de_DE": "Charakter", - "el_GR": "Χαρακτήρας", - "en_US": "Character", - "es_ES": "Personaje", - "fr_FR": "Personnage", - "he_IL": "דמות", - "it_IT": "Personaggio", - "ja_JP": "キャラクタ", - "ko_KR": "캐릭터", - "no_NO": "Karakter", - "pl_PL": "Postać", - "pt_BR": "Personagem", - "ru_RU": "Персонаж", - "sv_SE": "Karaktär", - "th_TH": "ตัวละคร", - "tr_TR": "Karakter", - "uk_UA": "Персонаж", - "zh_CN": "角色", - "zh_TW": "角色" - } - }, - { - "ID": "AmiiboScanButtonLabel", - "Translations": { - "ar_SA": "فحصه", - "de_DE": "Einscannen", - "el_GR": "Σαρώστε το", - "en_US": "Scan It", - "es_ES": "Escanear", - "fr_FR": "Scanner", - "he_IL": "סרוק את זה", - "it_IT": "Scansiona", - "ja_JP": "スキャン", - "ko_KR": "스캔하기", - "no_NO": "Skanne det", - "pl_PL": "Zeskanuj", - "pt_BR": "Escanear", - "ru_RU": "Сканировать", - "sv_SE": "Skanna den", - "th_TH": "สแกนเลย", - "tr_TR": "Tarat", - "uk_UA": "Сканувати", - "zh_CN": "扫描", - "zh_TW": "掃描" - } - }, - { - "ID": "AmiiboOptionsShowAllLabel", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Show incompatible Amiibo for this game", - "es_ES": "Mostrar Amiibo incompatibles con este juego", - "fr_FR": "Montrer les Amiibo incompatibles avec ce jeu", - "he_IL": "", - "it_IT": "Mostra Amiibo compatibili per questo gioco", - "ja_JP": "", - "ko_KR": "이 게임에 호환되지 않는 Amiibo 표시", - "no_NO": "", - "pl_PL": "", - "pt_BR": "Mostar Amiibos incompatíveis para este jogo.", - "ru_RU": "", - "sv_SE": "Visa Amiibo som inte är kompatibla med detta spel", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "显示与此游戏不兼容的 Amiibo", - "zh_TW": "顯示與此遊戲不相容的 Amiibo" - } - }, - { - "ID": "AmiiboOptionsUsRandomTagLabel", - "Translations": { - "ar_SA": "هاك: استخدم علامة Uuid عشوائية ", - "de_DE": "Hack: Benutze zufällige Tag-UUID", - "el_GR": "Hack: Χρησιμοποιήστε τυχαίο αναγνωριστικό UUID", - "en_US": "Hack: Use Random tag Uuid", - "es_ES": "Hack: Usar Etiqueta Aleatoria Uuid", - "fr_FR": "Hack : Utiliser un tag Uuid Aléatoire", - "he_IL": "האצה: השתמש בתג Uuid אקראי", - "it_IT": "Espediente: Usa un UUID del tag casuale", - "ja_JP": "ハック: ランダムな Uuid を使用", - "ko_KR": "핵 : 무작위 태그 Uuid 사용", - "no_NO": "Hack: Bruk tilfeldig tag-Uuid", - "pl_PL": "Hack: Użyj losowego UUID tagu", - "pt_BR": "Hack: Usar Uuid de tag Aleatório", - "ru_RU": "Хак: Использовать случайный тег Uuid", - "sv_SE": "Hack: Använd slumpmässig tagg för Uuid", - "th_TH": "แฮ็ค: สุ่มแท็ก Uuid", - "tr_TR": "Hack: Rastgele bir Uuid kullan", - "uk_UA": "Хитрість: Використовувати випадковий тег Uuid", - "zh_CN": "修改:使用随机生成的 Amiibo ID", - "zh_TW": "補釘修正:使用隨機標記的 Uuid" - } - }, { "ID": "DlcManagerTableHeadingEnabledLabel", "Translations": { @@ -15125,81 +14650,6 @@ "zh_TW": "長度必須為 {0} 到 {1} 個字元" } }, - { - "ID": "CabinetTitle", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Cabinet Dialog", - "es_ES": "Diálogo Gabinete", - "fr_FR": "Dialogue de Cabinet", - "he_IL": "", - "it_IT": "Modale del Cabinet", - "ja_JP": "", - "ko_KR": "캐비닛 대화 상자", - "no_NO": "Dialogboks for kabinett", - "pl_PL": "", - "pt_BR": "Diálogo do Gabinete", - "ru_RU": "Сообщение кабинета", - "sv_SE": "Cabinet-dialog", - "th_TH": "กล่องโต้ตอบไฟล์ Cabinet", - "tr_TR": "", - "uk_UA": "Сповіщення Cabinet", - "zh_CN": "档案对话框", - "zh_TW": "Cabinet 對話方塊" - } - }, - { - "ID": "CabinetDialog", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Enter your Amiibo's new name", - "es_ES": "Ingresa el nuevo nombre de tu Amiibo", - "fr_FR": "Entrer le nouveau nom de votre Amiibo", - "he_IL": "", - "it_IT": "Inserisci il nuovo nome del tuo Amiibo", - "ja_JP": "", - "ko_KR": "Amiibo의 새 이름 입력하기", - "no_NO": "Skriv inn Amiiboens nye navn", - "pl_PL": "", - "pt_BR": "Digite o novo nome do seu Amiibo", - "ru_RU": "Введите новое имя вашего Amiibo", - "sv_SE": "Ange nya namnet för din Amiibo", - "th_TH": "กรุณาใส่ชื่อใหม่ของ Amiibo ของคุณ", - "tr_TR": "", - "uk_UA": "Вкажіть Ваше нове ім'я Amiibo", - "zh_CN": "输入你的 Amiibo 的新名字", - "zh_TW": "輸入 Amiibo 的新名稱" - } - }, - { - "ID": "CabinetScanDialog", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Please scan your Amiibo now.", - "es_ES": "Escanea tu Amiibo ahora.", - "fr_FR": "Veuillez scannez votre Amiibo.", - "he_IL": "", - "it_IT": "Scansiona ora il tuo Amiibo.", - "ja_JP": "", - "ko_KR": "지금 Amiibo를 스캔하세요.", - "no_NO": "Vennligst skann Amiiboene dine nå.", - "pl_PL": "", - "pt_BR": "Por favor, escaneie seu Amiibo agora.", - "ru_RU": "Пожалуйста, сканируйте ваш Amiibo.", - "sv_SE": "Skanna din Amiibo nu.", - "th_TH": "กรุณาสแกน Amiibo ของคุณตอนนี้", - "tr_TR": "", - "uk_UA": "Будь ласка, проскануйте Ваш Amiibo.", - "zh_CN": "请现在扫描你的 Amiibo", - "zh_TW": "請掃描你的 Amiibo。" - } - }, { "ID": "SoftwareKeyboard", "Translations": { @@ -15725,56 +15175,6 @@ "zh_TW": "正在編譯著色器" } }, - { - "ID": "OpenFileDialogTitle", - "Translations": { - "ar_SA": "حدد ملف مدعوم لفتحه", - "de_DE": "Wähle eine unterstützte Datei", - "el_GR": "Επιλέξτε ένα υποστηριζόμενο αρχείο για άνοιγμα", - "en_US": "Select a supported file to open", - "es_ES": "Selecciona un archivo soportado para cargar", - "fr_FR": "Sélectionnez un fichier compatible à ouvrir", - "he_IL": "בחר קובץ נתמך לפתיחה", - "it_IT": "Seleziona un file supportato da aprire", - "ja_JP": "開くファイルを選択", - "ko_KR": "지원되는 파일을 선택하여 열기", - "no_NO": "Velg en støttet fil for å åpne", - "pl_PL": "Wybierz obsługiwany plik do otwarcia", - "pt_BR": "Selecione um arquivo suportado para abrir", - "ru_RU": "Выберите совместимый файл для открытия", - "sv_SE": "Välj en fil som stöds att öppna", - "th_TH": "เลือกไฟล์ที่สนับสนุนเพื่อเปิด", - "tr_TR": "Açmak için desteklenen bir dosya seçin", - "uk_UA": "Виберіть підтримуваний файл для відкриття", - "zh_CN": "选择支持的游戏文件并加载", - "zh_TW": "選取支援的檔案格式" - } - }, - { - "ID": "AllSupportedFormats", - "Translations": { - "ar_SA": "كل التنسيقات المدعومة", - "de_DE": "Alle unterstützten Formate", - "el_GR": "Όλες Οι Υποστηριζόμενες Μορφές", - "en_US": "All Supported Formats", - "es_ES": "Todos los Formatos Soportados", - "fr_FR": "Tous les Formats Supportés", - "he_IL": "כל הפורמטים הנתמכים", - "it_IT": "Tutti i formati supportati", - "ja_JP": "すべての対応フォーマット", - "ko_KR": "지원되는 모든 형식", - "no_NO": "Alle støttede formater", - "pl_PL": "Wszystkie Obsługiwane Formaty", - "pt_BR": "Todos os Formatos Suportados", - "ru_RU": "Все поддерживаемые форматы", - "sv_SE": "Alla format som stöds", - "th_TH": "รูปแบบที่รองรับทั้งหมด", - "tr_TR": "Tüm Desteklenen Formatlar", - "uk_UA": "Усі підтримувані формати", - "zh_CN": "所有支持的格式", - "zh_TW": "所有支援的格式" - } - }, { "ID": "RyujinxUpdater", "Translations": { @@ -16125,106 +15525,6 @@ "zh_TW": "管理帳戶 - 大頭貼" } }, - { - "ID": "Amiibo", - "Translations": { - "ar_SA": "أميبو", - "de_DE": "", - "el_GR": "", - "en_US": "Amiibo", - "es_ES": null, - "fr_FR": null, - "he_IL": "אמיבו", - "it_IT": "", - "ja_JP": "", - "ko_KR": null, - "no_NO": "", - "pl_PL": "", - "pt_BR": null, - "ru_RU": null, - "sv_SE": null, - "th_TH": "อมิโบ้", - "tr_TR": "", - "uk_UA": "", - "zh_CN": null, - "zh_TW": null - } - }, - { - "ID": "Unknown", - "Translations": { - "ar_SA": "غير معروف", - "de_DE": "Unbekannt", - "el_GR": "Άγνωστο", - "en_US": "Unknown", - "es_ES": "Desconocido", - "fr_FR": "Inconnu", - "he_IL": "לא ידוע", - "it_IT": "Sconosciuto", - "ja_JP": "不明", - "ko_KR": "알 수 없음", - "no_NO": "Ukjent", - "pl_PL": "Nieznane", - "pt_BR": "Desconhecido", - "ru_RU": "Неизвестно", - "sv_SE": "Okänt", - "th_TH": "ไม่รู้จัก", - "tr_TR": "Bilinmeyen", - "uk_UA": "Невідомо", - "zh_CN": "未知", - "zh_TW": "未知" - } - }, - { - "ID": "Usage", - "Translations": { - "ar_SA": "الاستخدام", - "de_DE": "Nutzung", - "el_GR": "Χρήση", - "en_US": "Usage", - "es_ES": "Uso", - "fr_FR": "Utilisation", - "he_IL": "שימוש", - "it_IT": "Utilizzo", - "ja_JP": "使用法", - "ko_KR": "사용법", - "no_NO": "Forbruk", - "pl_PL": "Użycie", - "pt_BR": "Uso", - "ru_RU": "Применение", - "sv_SE": "Användning", - "th_TH": "การใช้งาน", - "tr_TR": "Kullanım", - "uk_UA": "Використання", - "zh_CN": "用法", - "zh_TW": "用途" - } - }, - { - "ID": "Writable", - "Translations": { - "ar_SA": "قابل للكتابة", - "de_DE": "Beschreibbar", - "el_GR": "Εγγράψιμο", - "en_US": "Writable", - "es_ES": "Escribible", - "fr_FR": "Ecriture possible", - "he_IL": "ניתן לכתיבה", - "it_IT": "Scrivibile", - "ja_JP": "書き込み可能", - "ko_KR": "쓰기 가능", - "no_NO": "Skrivbart", - "pl_PL": "Zapisywalne", - "pt_BR": "Gravável", - "ru_RU": "Доступно для записи", - "sv_SE": "Skrivbar", - "th_TH": "สามารถเขียนทับได้", - "tr_TR": "Yazılabilir", - "uk_UA": "Можливість запису", - "zh_CN": "可写入", - "zh_TW": "可寫入" - } - }, { "ID": "SelectDlcDialogTitle", "Translations": { diff --git a/docs/compatibility.csv b/docs/compatibility.csv index a0a7e730a..b24ffd31b 100644 --- a/docs/compatibility.csv +++ b/docs/compatibility.csv @@ -2667,7 +2667,8 @@ 0100C52011460000,"Sky: Children of the Light",cpu;online-broken,nothing,2023-02-23 10:57:10 010041C01014E000,"Skybolt Zack",,playable,2021-04-12 18:28:00 0100A0A00D1AA000,"SKYHILL",,playable,2021-03-05 15:19:11 -0100CCC0002E6000,"Skylanders Imaginators",crash;services,boots,2020-05-30 18:49:18 +010048D000BFC000,"Skylanders Imaginators",,playable,2026-07-02 22:43:30 +0100CCC0002E6000,"Skylanders Imaginators",,playable,2026-07-02 22:43:30 010021A00ABEE000,"SKYPEACE",,playable,2020-05-29 14:14:30 0100EA400BF44000,"SkyScrappers",,playable,2020-05-28 22:11:25 0100F3C00C400000,"SkyTime",slow,ingame,2020-05-30 09:24:51 diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs index 1b70f96f9..7928a6194 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs @@ -502,15 +502,20 @@ namespace Ryujinx.Ava.Systems.Configuration public bool DebuggerSuspendOnStart { get; set; } /// - /// Show toggles for dirty hacks in the UI. + /// Show toggles for dirty hacks in the UI. /// public bool ShowDirtyHacks { get; set; } /// - /// The packed values of the enabled dirty hacks. + /// The packed values of the enabled dirty hacks. /// public ulong[] DirtyHacks { get; set; } + /// + /// Pause emulation while scanning Amiibo + /// + public bool PauseEmulationWhileScanningAmiibo { get; set; } + /// /// Loads a configuration file from disk /// diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs index bc3f3bcd5..59b1f5804 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs @@ -115,7 +115,7 @@ namespace Ryujinx.Ava.Systems.Configuration System.SkipUserProfilesManager.Value = cff.SkipUserProfiles; System.UseHypervisor.Value = cff.UseHypervisor; System.GCLowLatency.Value = cff.GCLowLatency; - + UI.GuiColumns.FavColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FavColumn : UI.GuiColumns.FavColumn.Value; UI.GuiColumns.IconColumn.Value = shouldLoadFromFile ? cff.GuiColumns.IconColumn : UI.GuiColumns.IconColumn.Value; UI.GuiColumns.AppColumn.Value = shouldLoadFromFile ? cff.GuiColumns.AppColumn : UI.GuiColumns.AppColumn.Value; @@ -151,6 +151,7 @@ namespace Ryujinx.Ava.Systems.Configuration UI.WindowStartup.WindowPositionX.Value = shouldLoadFromFile ? cff.WindowStartup.WindowPositionX : UI.WindowStartup.WindowPositionX.Value; UI.WindowStartup.WindowPositionY.Value = shouldLoadFromFile ? cff.WindowStartup.WindowPositionY : UI.WindowStartup.WindowPositionY.Value; UI.WindowStartup.WindowMaximized.Value = shouldLoadFromFile ? cff.WindowStartup.WindowMaximized : UI.WindowStartup.WindowMaximized.Value; + UI.PauseEmulationWhileScanningAmiibo.Value = cff.PauseEmulationWhileScanningAmiibo; Hid.EnableKeyboard.Value = cff.EnableKeyboard; Hid.EnableMouse.Value = cff.EnableMouse; diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs index a2f011bbb..6af7a2383 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs @@ -196,6 +196,11 @@ namespace Ryujinx.Ava.Systems.Configuration /// public ReactiveObject ShowDynamicInputSwapWarning { get; private set; } + /// + /// Pause emulation while scanning Amiibo + /// + public ReactiveObject PauseEmulationWhileScanningAmiibo { get; private set; } + public UISection() { GuiColumns = new Columns(); @@ -217,6 +222,8 @@ namespace Ryujinx.Ava.Systems.Configuration ShowConsole.Event += static (_, e) => ConsoleHelper.SetConsoleWindowState(e.NewValue); ShowDynamicInputSwapWarning = new ReactiveObject(); ShowDynamicInputSwapWarning.Value = true; + PauseEmulationWhileScanningAmiibo = new ReactiveObject(); + PauseEmulationWhileScanningAmiibo.Value = true; } } diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.cs index afff7957f..bcd8e50ca 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.cs @@ -158,6 +158,7 @@ namespace Ryujinx.Ava.Systems.Configuration DebuggerSuspendOnStart = Debug.DebuggerSuspendOnStart, ShowDirtyHacks = Hacks.ShowDirtyHacks, DirtyHacks = Hacks.EnabledHacks.Select(it => it.Pack()).ToArray(), + PauseEmulationWhileScanningAmiibo = UI.PauseEmulationWhileScanningAmiibo, }; return configurationFile; @@ -262,6 +263,7 @@ namespace Ryujinx.Ava.Systems.Configuration UI.WindowStartup.WindowPositionX.Value = 0; UI.WindowStartup.WindowPositionY.Value = 0; UI.WindowStartup.WindowMaximized.Value = false; + UI.PauseEmulationWhileScanningAmiibo.Value = true; Hid.EnableKeyboard.Value = false; Hid.EnableMouse.Value = false; Hid.DisableInputWhenOutOfFocus.Value = false; diff --git a/src/Ryujinx/UI/Applet/AvaHostUIHandler.cs b/src/Ryujinx/UI/Applet/AvaHostUIHandler.cs index 45235ee3f..9c28be6e8 100644 --- a/src/Ryujinx/UI/Applet/AvaHostUIHandler.cs +++ b/src/Ryujinx/UI/Applet/AvaHostUIHandler.cs @@ -187,7 +187,7 @@ namespace Ryujinx.Ava.UI.Applet StringLengthMax = 25 }; (UserResult result, string userInput) = - await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.CabinetDialog], args); + await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.Dialog_Amiibo_RenameAmiiboTitle], args); if (result == UserResult.Ok) { inputText = userInput; @@ -212,11 +212,11 @@ namespace Ryujinx.Ava.UI.Applet { dialogCloseEvent.Set(); await ContentDialogHelper.CreateInfoDialog( - LocaleManager.Instance[LocaleKeys.CabinetScanDialog], + LocaleManager.Instance[LocaleKeys.Dialog_Amiibo_ScanAmiiboMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, - LocaleManager.Instance[LocaleKeys.CabinetTitle] + LocaleManager.Instance[LocaleKeys.Dialog_Amiibo_ScanAmiiboTitle] ); }); dialogCloseEvent.WaitOne(); diff --git a/src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs b/src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs index bef6fc47d..9e7572e1a 100644 --- a/src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs +++ b/src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs @@ -74,10 +74,14 @@ namespace Ryujinx.Ava.UI.Controls content._host = contentDialog; contentDialog.Title = title; - contentDialog.PrimaryButtonText = args.SubmitText; + + contentDialog.PrimaryButtonText = string.IsNullOrWhiteSpace(args.SubmitText) + ? LocaleManager.Instance[LocaleKeys.InputDialogOk] + : args.SubmitText; + contentDialog.IsPrimaryButtonEnabled = content._checkLength(content.Message.Length); contentDialog.SecondaryButtonText = string.Empty; - contentDialog.CloseButtonText = LocaleManager.Instance[LocaleKeys.InputDialogCancel]; + contentDialog.CloseButtonText = LocaleManager.Instance[LocaleKeys.Common_Buttons_Cancel]; contentDialog.Content = content; void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs) diff --git a/src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs index 053972c2c..34959c0b1 100644 --- a/src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs @@ -3,8 +3,10 @@ using Avalonia.Collections; using Avalonia.Media.Imaging; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; +using Path = System.IO.Path; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models.Amiibo; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; @@ -20,31 +22,39 @@ using System.Linq; using System.Net.Http; using System.Text; using System.Text.Json; +using System.Threading; using System.Threading.Tasks; namespace Ryujinx.Ava.UI.ViewModels { public partial class AmiiboWindowViewModel : BaseModel, IDisposable { - // ReSharper disable once InconsistentNaming - private static bool _cachedUseRandomUuid; - - private const string DefaultJson = "{ \"amiibo\": [] }"; - private const float AmiiboImageSize = 350f; - - private readonly string _amiiboJsonPath; - private readonly byte[] _amiiboLogoBytes; - private readonly HttpClient _httpClient; - private readonly AmiiboWindow _owner; - - private List _amiiboList; - private AvaloniaList _amiibos; - private ObservableCollection _amiiboSeries; + public enum AmiiboSortField + { + Name, + + } private int _amiiboSelectedIndex; private int _seriesSelectedIndex; private bool _showAllAmiibo; + // ReSharper disable once InconsistentNaming + private static bool _cachedUseRandomUuid; + public bool IsSortedByName => _sortField == AmiiboSortField.Name; + private const string DefaultJson = "{ \"amiibo\": [] }"; + private const float AmiiboImageSize = 350f; + public string TitleId { get; set; } + public string LastScannedAmiiboId { get; set; } + public string SortingFieldName => LocaleManager.Instance[LocaleKeys.Common_Sort_NameLabel]; + private readonly string _amiiboJsonPath; + private readonly byte[] _amiiboLogoBytes; + private readonly HttpClient _httpClient; + private readonly AmiiboWindow _owner; + private List _amiiboList; + private AvaloniaList _amiibos; + private ObservableCollection _amiiboSeries; + private CancellationTokenSource _imageCts = new(); private static readonly AmiiboJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); public AmiiboWindowViewModel(AmiiboWindow owner, string lastScannedAmiiboId, string titleId) @@ -73,9 +83,6 @@ namespace Ryujinx.Ava.UI.ViewModels public AmiiboWindowViewModel() { } - public string TitleId { get; set; } - public string LastScannedAmiiboId { get; set; } - public UserResult Response { get; private set; } public bool UseRandomUuid @@ -151,6 +158,42 @@ namespace Ryujinx.Ava.UI.ViewModels } } + public bool PauseEmulationWhileScanningAmiibo + { + get => ConfigurationState.Instance.UI.PauseEmulationWhileScanningAmiibo.Value; + set + { + ConfigurationState.Instance.UI.PauseEmulationWhileScanningAmiibo.Value = value; + ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); + OnPropertyChanged(); + } + } + + private string _searchText = string.Empty; + private bool _sortingAscending = true; + + public string SearchText + { + get => _searchText; + set + { + _searchText = value; + FilterAmiibo(); + OnPropertyChanged(); + } + } + + public bool SortingAscending + { + get => _sortingAscending; + set + { + _sortingAscending = value; + FilterAmiibo(); + OnPropertyChanged(); + } + } + [ObservableProperty] public partial Bitmap AmiiboImage { get; set; } @@ -166,14 +209,14 @@ namespace Ryujinx.Ava.UI.ViewModels { _owner.ScannedAmiibo = AmiiboList[AmiiboSelectedIndex]; _owner.IsScanned = true; - _owner.Close(); + } } public void Cancel() { _owner.IsScanned = false; - _owner.Close(); + } public void Dispose() @@ -315,42 +358,46 @@ namespace Ryujinx.Ava.UI.ViewModels private void ParseAmiiboData() { _amiiboSeries.Clear(); - _amiibos.Clear(); - for (int i = 0; i < _amiiboList.Count; i++) + foreach (AmiiboApi amiibo in _amiiboList) { - if (!_amiiboSeries.Contains(_amiiboList[i].AmiiboSeries)) + if (!_amiiboSeries.Contains(amiibo.AmiiboSeries)) { - if (!ShowAllAmiibo) + if (_showAllAmiibo) { - foreach (AmiiboApiGamesSwitch game in _amiiboList[i].GamesSwitch) - { - if (game != null) - { - if (game.GameId.Contains(TitleId)) - { - AmiiboSeries.Add(_amiiboList[i].AmiiboSeries); - - break; - } - } - } + _amiiboSeries.Add(amiibo.AmiiboSeries); } else { - AmiiboSeries.Add(_amiiboList[i].AmiiboSeries); + bool hasCompatible = amiibo.GamesSwitch.Any(game => + game != null && game.GameId.Contains(TitleId)); + + if (hasCompatible) + { + _amiiboSeries.Add(amiibo.AmiiboSeries); + } } } } - if (LastScannedAmiiboId != string.Empty) + if (_showAllAmiibo) + { + SeriesSelectedIndex = -1; + } + else if (LastScannedAmiiboId != string.Empty) { SelectLastScannedAmiibo(); } - else + else if (_amiiboSeries.Count > 0) { SeriesSelectedIndex = 0; } + else + { + SeriesSelectedIndex = -1; + } + + FilterAmiibo(); } private void SelectLastScannedAmiibo() @@ -360,104 +407,109 @@ namespace Ryujinx.Ava.UI.ViewModels SeriesSelectedIndex = AmiiboSeries.IndexOf(scanned.AmiiboSeries); AmiiboSelectedIndex = AmiiboList.IndexOf(scanned); } - + private void FilterAmiibo() { _amiibos.Clear(); - List amiiboSortedList; + IEnumerable query = _amiiboList.AsEnumerable(); - // If no series selected, just display all available amiibos - if (_seriesSelectedIndex < 0) + if (_seriesSelectedIndex >= 0 && _seriesSelectedIndex < _amiiboSeries.Count) { - amiiboSortedList = _amiiboList - .OrderBy(amiibo => amiibo.AmiiboSeries) - .ThenBy(x => x.Name) - .ToList(); - } - else - { - amiiboSortedList = _amiiboList - .Where(amiibo => amiibo.AmiiboSeries == _amiiboSeries[SeriesSelectedIndex]) - .OrderBy(amiibo => amiibo.Name).ToList(); + string selectedSeries = _amiiboSeries[_seriesSelectedIndex]; + query = query.Where(amiibo => amiibo.AmiiboSeries == selectedSeries); } - - - for (int i = 0; i < amiiboSortedList.Count; i++) + if (!string.IsNullOrWhiteSpace(_searchText)) { - if (!_amiibos.Contains(amiiboSortedList[i])) + query = query.Where(amiibo => + amiibo.Name.Contains(_searchText, StringComparison.OrdinalIgnoreCase)); + } + + if (!_showAllAmiibo) + { + query = query.Where(amiibo => + amiibo.GamesSwitch.Any(game => game != null && game.GameId.Contains(TitleId))); + } + + query = _sortingAscending + ? query.OrderBy(amiibo => amiibo.Name) + : query.OrderByDescending(amiibo => amiibo.Name); + + _amiibos.AddRange(query); + + int restoredIndex = -1; + for (int i = 0; i < _amiibos.Count; i++) + { + if (_amiibos[i].GetId() == LastScannedAmiiboId) { - if (!_showAllAmiibo) - { - foreach (AmiiboApiGamesSwitch game in amiiboSortedList[i].GamesSwitch) - { - if (game != null) - { - if (game.GameId.Contains(TitleId)) - { - _amiibos.Add(amiiboSortedList[i]); - - break; - } - } - } - } - else - { - _amiibos.Add(amiiboSortedList[i]); - } + restoredIndex = i; + break; } } - AmiiboSelectedIndex = 0; + AmiiboSelectedIndex = restoredIndex != -1 + ? restoredIndex + : (_amiibos.Count > 0 ? 0 : -1); + + SetAmiiboDetails(); + } + + private AmiiboSortField _sortField = AmiiboSortField.Name; + + public AmiiboSortField SortingField + { + get => _sortField; + set + { + _sortField = value; + FilterAmiibo(); + OnPropertyChanged(nameof(SortingFieldName)); + OnPropertyChanged(nameof(IsSortedByName)); + } } private void SetAmiiboDetails() { ResetAmiiboPreview(); - Usage = string.Empty; if (_amiiboSelectedIndex < 0 || _amiibos.Count < 1) - { return; - } AmiiboApi selected = _amiibos[_amiiboSelectedIndex]; - - string imageUrl = _amiiboList.FirstOrDefault(amiibo => amiibo.Equals(selected)).Image; + string imageUrl = selected.Image; StringBuilder usageStringBuilder = new(); + bool writable = false; - for (int i = 0; i < _amiiboList.Count; i++) + foreach (AmiiboApiGamesSwitch game in selected.GamesSwitch) { - if (_amiiboList[i].Equals(selected)) + if (game != null && game.GameId.Contains(TitleId)) { - bool writable = false; - - foreach (AmiiboApiGamesSwitch item in _amiiboList[i].GamesSwitch) + foreach (AmiiboApiUsage usageItem in game.AmiiboUsage) { - if (item.GameId.Contains(TitleId)) - { - foreach (AmiiboApiUsage usageItem in item.AmiiboUsage) - { - usageStringBuilder.Append($"{Environment.NewLine}- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}"); - - writable = usageItem.Write; - } - } + usageStringBuilder.Append($"{Environment.NewLine}- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}"); + if (usageItem.Write) + writable = true; } - - if (usageStringBuilder.Length == 0) - { - usageStringBuilder.Append($"{LocaleManager.Instance[LocaleKeys.Unknown]}."); - } - - Usage = $"{LocaleManager.Instance[LocaleKeys.Usage]} {(writable ? $" ({LocaleManager.Instance[LocaleKeys.Writable]})" : string.Empty)} : {usageStringBuilder}"; } } + string usageLabel = writable + ? LocaleManager.Instance[LocaleKeys.Amiibo_WritableLabel] + : LocaleManager.Instance[LocaleKeys.Amiibo_UsageLabel]; + + if (usageStringBuilder.Length == 0) + { + usageStringBuilder.Append(Environment.NewLine + Environment.NewLine + LocaleManager.Instance[LocaleKeys.Amiibo_UnknownLabel]); + } + else + { + usageStringBuilder.Replace(Environment.NewLine + "-", Environment.NewLine + Environment.NewLine + "-"); + } + + Usage = usageLabel + usageStringBuilder.ToString(); _ = UpdateAmiiboPreview(imageUrl); } @@ -510,8 +562,8 @@ namespace Ryujinx.Ava.UI.ViewModels Logger.Error?.Print(LogClass.Application, $"Failed to request amiibo data: {exception}"); } - await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle], - LocaleManager.Instance[LocaleKeys.DialogAmiiboApiFailFetchMessage], + await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.Dialog_Amiibo_APITitle], + LocaleManager.Instance[LocaleKeys.Dialog_Amiibo_APIFailFetchMessage], LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, LocaleManager.Instance[LocaleKeys.RyujinxInfo]); @@ -526,26 +578,33 @@ namespace Ryujinx.Ava.UI.ViewModels private async Task UpdateAmiiboPreview(string imageUrl) { - HttpResponseMessage response = await _httpClient.GetAsync(imageUrl); + _imageCts.Cancel(); + _imageCts = new CancellationTokenSource(); - if (response.IsSuccessStatusCode) + try { - byte[] amiiboPreviewBytes = await response.Content.ReadAsByteArrayAsync(); - using MemoryStream memoryStream = new(amiiboPreviewBytes); + using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_imageCts.Token); - Bitmap bitmap = new(memoryStream); + HttpResponseMessage response = await _httpClient.GetAsync(imageUrl, linkedCts.Token); - double ratio = Math.Min(AmiiboImageSize / bitmap.Size.Width, - AmiiboImageSize / bitmap.Size.Height); + if (response.IsSuccessStatusCode) + { + byte[] bytes = await response.Content.ReadAsByteArrayAsync(linkedCts.Token); + using MemoryStream ms = new(bytes); - int resizeHeight = (int)(bitmap.Size.Height * ratio); - int resizeWidth = (int)(bitmap.Size.Width * ratio); + Bitmap bitmap = new(ms); - AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(resizeWidth, resizeHeight)); + double ratio = Math.Min(AmiiboImageSize / bitmap.Size.Width, AmiiboImageSize / bitmap.Size.Height); + int newWidth = (int)(bitmap.Size.Width * ratio); + int newHeight = (int)(bitmap.Size.Height * ratio); + + AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(newWidth, newHeight)); + } } - else + catch (OperationCanceledException) { } + catch (Exception ex) { - Logger.Error?.Print(LogClass.Application, $"Failed to get amiibo preview. Response status code: {response.StatusCode}"); + Logger.Error?.Print(LogClass.Application, $"Failed to load amiibo preview: {ex}"); } } @@ -560,8 +619,8 @@ namespace Ryujinx.Ava.UI.ViewModels private static async Task ShowInfoDialog() { - await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle], - LocaleManager.Instance[LocaleKeys.DialogAmiiboApiConnectErrorMessage], + await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.Dialog_Amiibo_APITitle], + LocaleManager.Instance[LocaleKeys.Dialog_Amiibo_APIConnectErrorMessage], LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, LocaleManager.Instance[LocaleKeys.RyujinxInfo]); diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index a848d70ed..69b804f34 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -160,6 +160,10 @@ namespace Ryujinx.Ava.UI.ViewModels [ObservableProperty] public partial bool UpdateAvailable { get; set; } + [ObservableProperty] public partial string SkylanderButtonHeader { get; set; } = string.Empty; + + [ObservableProperty] public partial bool SkylanderButtonEnabled { get; set; } + public static AsyncRelayCommand UpdateCommand { get; } = Commands.Create(async () => { if (Updater.CanUpdate(true)) @@ -204,6 +208,8 @@ namespace Ryujinx.Ava.UI.ViewModels internal AppHost AppHost { get; set; } + public RelayCommand ToggleSkylanderCommand { get; } + public MainWindowViewModel() { Applications = []; @@ -233,6 +239,8 @@ namespace Ryujinx.Ava.UI.ViewModels Volume = ConfigurationState.Instance.System.AudioVolume; CustomVSyncInterval = ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value; } + + ToggleSkylanderCommand = new RelayCommand(ExecuteToggleSkylander); } ~MainWindowViewModel() @@ -376,6 +384,50 @@ namespace Ryujinx.Ava.UI.ViewModels public bool CanScanAmiiboBinaries => AmiiboBinReader.HasAmiiboKeyFile; + [RelayCommand] + private void UpdateSkylanderButton() + { + SkylanderButtonHeader = HasSkylander + ? LocaleManager.Instance[LocaleKeys.MenuBar_Actions_RemoveSkylanderButton] + : LocaleManager.Instance[LocaleKeys.MenuBar_Actions_ScanSkylanderButton]; + + SkylanderButtonEnabled = HasSkylander || IsSkylanderRequested; + + OnPropertyChanged(nameof(SkylanderButtonHeader)); + OnPropertyChanged(nameof(SkylanderButtonEnabled)); + + Dispatcher.UIThread.Post(() => + { + OnPropertyChanged(nameof(SkylanderButtonHeader)); + }, DispatcherPriority.Render); + } + + private void UpdateSkylanderState() + { + if (AppHost?.Device?.System == null) return; + + IsSkylanderRequested = AppHost.Device.System.SearchingForSkylander(out _); + HasSkylander = AppHost.Device.System.HasSkylander(out _); + + UpdateSkylanderButton(); + } + + private async void ExecuteToggleSkylander() + { + if (!IsGameRunning) return; + + if (HasSkylander) + { + await RemoveSkylander(); + } + else + { + await ScanSkylander(); + } + + UpdateSkylanderState(); + } + public bool IsSkylanderRequested { get => field && _isGameRunning; @@ -384,6 +436,7 @@ namespace Ryujinx.Ava.UI.ViewModels field = value; OnPropertyChanged(); + UpdateSkylanderButton(); } } @@ -395,17 +448,7 @@ namespace Ryujinx.Ava.UI.ViewModels field = value; OnPropertyChanged(); - } - } - - public bool ShowSkylanderActions - { - get => field && _isGameRunning; - set - { - field = value; - - OnPropertyChanged(); + UpdateSkylanderButton(); } } @@ -1496,7 +1539,7 @@ namespace Ryujinx.Ava.UI.ViewModels Title = LocaleManager.Instance[LocaleKeys.Dialog_Firmware_InstallFromFileFilePickerTitle], FileTypeFilter = new List { - new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) + new(LocaleManager.Instance[LocaleKeys.Common_FilePicker_AllSupportedFormats]) { Patterns = ["*.xci", "*.zip"], AppleUniformTypeIdentifiers = ["com.ryujinx.xci", "public.zip-archive"], @@ -1680,7 +1723,7 @@ namespace Ryujinx.Ava.UI.ViewModels Title = LocaleManager.Instance[LocaleKeys.Dialog_FileMenu_LoadApplicationFromFileFilePickerTitle], FileTypeFilter = new List { - new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) + new(LocaleManager.Instance[LocaleKeys.Common_FilePicker_AllSupportedFormats]) { Patterns = ["*.nsp", "*.xci", "*.nca", "*.nro", "*.nso"], AppleUniformTypeIdentifiers = @@ -2010,40 +2053,58 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public async Task OpenBinFile() + public async Task ScanAmiiboFromBin() { - if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning) - { - Optional result = await StorageProvider.OpenSingleFilePickerAsync( - new FilePickerOpenOptions - { - Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], - FileTypeFilter = new List - { - new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) - { - Patterns = ["*.bin"], - } - } - }); + bool shouldPause = ConfigurationState.Instance.UI.PauseEmulationWhileScanningAmiibo.Value && IsGameRunning; - if (result.HasValue) + if (shouldPause && AppHost?.Device?.System != null) + { + AppHost?.Pause(); + } + try + { + if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning) { - AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath); + Optional result = await StorageProvider.OpenSingleFilePickerAsync( + new FilePickerOpenOptions + { + Title = LocaleManager.Instance[LocaleKeys.Dialog_Amiibo_ScanAmiiboFromBinFilePickerTitle], + FileTypeFilter = new List + { + new(LocaleManager.Instance[LocaleKeys.Common_FilePicker_AllSupportedFormats]) + { + Patterns = ["*.bin"], + } + } + }); + + if (result.HasValue) + { + AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath); + } + } + } + finally + { + if (shouldPause && AppHost?.Device?.System != null) + { + AppHost?.Resume(); } } } - public async Task OpenSkylanderWindow() + + [RelayCommand] + public async Task ScanSkylander() { if (AppHost.Device.System.SearchingForSkylander(out int deviceId)) { Optional result = await StorageProvider.OpenSingleFilePickerAsync( new FilePickerOpenOptions { - Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], + Title = LocaleManager.Instance[LocaleKeys.Dialog_Skylanders_ScanSkylanderFilePickerTitle], FileTypeFilter = new List { - new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) + new(LocaleManager.Instance[LocaleKeys.Common_FilePicker_AllSupportedFormats]) { Patterns = ["*.sky", "*.bin", "*.dmp", "*.dump"], }, @@ -2066,12 +2127,15 @@ namespace Ryujinx.Ava.UI.ViewModels AppHost.Device.System.ScanSkylander(deviceId, data); } } + UpdateSkylanderButton(); } } + [RelayCommand] public async Task RemoveSkylander() { AppHost.Device.System.RemoveSkylander(); + UpdateSkylanderButton(); } public void ReloadRenderDocApi() diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index c73553f80..45429b88c 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -154,7 +154,7 @@ namespace Ryujinx.Ava.UI.ViewModels AllowMultiple = true, FileTypeFilter = new List { - new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) + new(LocaleManager.Instance[LocaleKeys.Common_FilePicker_AllSupportedFormats]) { Patterns = ["*.nsp"], AppleUniformTypeIdentifiers = ["com.ryujinx.nsp"], diff --git a/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml b/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml index 05d4f47d6..68727e4ee 100644 --- a/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml +++ b/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml @@ -190,7 +190,7 @@ MinWidth="90" Margin="5" Click="Close"> - + diff --git a/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml index 4c17721a1..9835b431c 100644 --- a/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml +++ b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml @@ -158,7 +158,7 @@ MinWidth="90" Margin="5" Click="Close"> - + diff --git a/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml b/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml index ba3e85e8b..e29687642 100644 --- a/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml +++ b/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml @@ -145,7 +145,7 @@ Name="CancelButton" MinWidth="90" Click="Close"> - + diff --git a/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml b/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml index 601a7f3dd..fff8c0ce3 100644 --- a/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml +++ b/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml @@ -173,7 +173,7 @@ - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - + - - - - + + + + - - - - + + diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml b/src/Ryujinx/UI/Windows/MainWindow.axaml index d5c717dee..1d0124ae6 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml @@ -40,10 +40,11 @@ - + + diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml b/src/Ryujinx/UI/Windows/SettingsWindow.axaml index 7be53d2cd..677e2d0df 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml @@ -155,7 +155,7 @@ Command="{Binding OkButton}" />