From 905a41a643f9e111192cb6877ac7e792555fa23f Mon Sep 17 00:00:00 2001 From: _Neo_ Date: Sat, 27 Jun 2026 02:11:31 +0000 Subject: [PATCH] =?UTF-8?q?UI:=20Actions=20Menu=20(Part=202=20of=204)=20?= =?UTF-8?q?=E2=86=92=20XCI=20Trimmer=20(#146)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ayyyy, welcome to the UI: Actions Menu → XCI Trimmer PR! Let's keep it up! This is the second PR in a series aimed at delivering the largest overhaul and improvements to the `Actions` menu yet. This second PR introduces visual improvements to the `XCI Trimmer` and also fixes some bugs. ### GENERAL: * **Renamed:** `XCI Trimmer` files to use the capitalised XCI instead of Xci * Files were inconsistently named with either Xci or XCI. As such, they were all renamed to use XCI. ### LOCALISATION: * **Fractured:** More locales * `Common_Search.json` - search-related locales * `Common_Sort.json` - sorting fields, ascending/descending locales * `Dialog_XCITrimmer.json` - XCI trimmer dialogs * `GameListContextMenu.json` - all UI dialogs related to the game list menu (right-click game) * `XCITrimmer.json` - all UI-related locales for the XCI Trimmer window * **Added:** Additional entry to `StatusBar.json` * **Added:** `Simulate Wake-Up Message` to `MenuBar_Actions.json` (previously did not exist there, for some reason). **NOTE:** `Common_Search.json` and `Common_Sort.json` were not fully populated, but many more locales will be added and cleaned up in future PRs. ### XCI TRIMMER: * **Renamed:** `Trim XCI Files` menu → `XCI Trimmer` * **XCI Trimmer (Window):** * **Renamed:** Window title from `XCI File Trimmer` → `XCI Trimmer` * **Renamed:** `X of Y Title(s) Selected` → `XCI Selected: X/Y` * `Z Displayed` was renamed to `Displayed: Z` and, as usual, appears only when searching for particular XCIs in the search bar. * **Fixed:** Counting bug * Pressing `Select Shown` continuously would increment the amount of XCIs selected to infinity (e.g. if 5 XCIs are in the list, then you could get 1201312 of 5 Title(s) Selected). Furthermore, when you were trimming a specific number of XCIs (not the all XCIs) at once, it would show that its trimming all titles from the list (e.g. "Trimming 5 Titles" when only 1 was being trimmed). * **Changed:** Button structure * Previous structure included 2 buttons: `Select Shown` and `Deselect Shown`. Initially, they were renamed to `Select All` and `Deselect All`, as that sounded more natural. However, after further consideration, they were both removed and replaced by a single button, whose action and label would change depending on the state it was in: * If no XCIs were selected → `Select All` * If at least one XCI is selected →`Clear Selection` * `Clear Selection` was used instead of Deselect All, because some translations were quite awkward. * Furthermore, this reflects the way the button works: you are not "deselecting all" when only 2 out of 5 XCIs are selected - you are clearing that particular selection of XCIs. * **Improved:** Button and Control Layout (above list) * Sorting dropdown was expanded a bit further (150 default to 170 width), as some locales would get cutoff. This will be further adjusted in a future PR, which will tackle all of Ryujinx's sorting features. * Added a new sorting: Trim Status * See images for visual comparison. * **Improved:** XCI List Layout * The entire list was revamped to be more modern and cleaner to look at. * Instead of displaying the file status (Trimmed, Untrimmed, Partial, Failed, Unknown), it now shows icons: Checkmark (Trimmed), Cross (Untrimmed), Wrench (Partial), Exclamation Mark (Failed), Question mark (everything else/Unknown), No Icon (when it's not XCI). * Furthermore, it shows a Sync icon when performing the trimming/untrimming operation. * Additionally, it shows the said status when you hover above the icons. * Save X MB and Saved Y MB were both removed and replaced with just the amount and a percentage value (how much you save per file). * See images for visual comparison. * NOTE: Icons are still under consideration and may be changed in the future. * **Improved:** Bottom Savings Display * Instead of showing `Potential Savings`" and `Actual Savings`, the bottom row now shows the amount `Saved` AND the amount `Remaining`. ### GAME LIST CONTEXT MENU (Right-Click Game): * **Renamed:** `Check & Trim XCI File` → `Trim XCI` * The option already performs a check regardless. * **Remove:** `Trim XCI` Tooltip * The user can press the option and will be confronted with a dialog, which explains what the feature does. Furthermore, the action itself is reversible at any moment (i.e. before trimming and after trimming in the XCI Trimmer). * It is planned to either add a message that tells the user they can untrim the XCI in the XCI Trimmer, or to make the option work both ways (Trim & Untrim). This is still under consideration, but, if chosen to be implemented, it will be a part of the Game List Context Menu PR. * **Added:** IsVisible parameter to `Trim XCI` * Instead of displaying `Trim XCI` for every single game (NSP, NSO, etc.), it will only be displayed for XCIs (as they are the only ones that can be trimmed). It is still _enabled_ only if an XCI is untrimmed. * **Improved:** `Trim XCI` Dialog * Some minor visual adjustment and organisation improvements. * **Changed:** Value formatting for "File Size", "Game Size", and "Space Savings" * Previously they were very long numbers, expressed in MB, with all the decimals. Instead of displaying them as such, they were shortened to display the same amount as they do in the XCI Trimmer window already. * All further dialogs will be improved in a separate PR, because they desperately need consistency. ### STATUS BAR: * **Adjusted:** Formatting of XCI Trimming Status on status bar * **Forced:** Filename without extension (as we are already trimming an XCI already). * **Fixed:** Trimming Position when Playtime is not available * **Fixed:** Progress bar position (will be further adjusted in a Status Bar PR…boy there will be a lot of PRs, which is good) _If there are any features or changes that you wish to be implemented, please comment down below and I'll be happy to accommodate!_ Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/146 --- assets/Locales/Common_Search.json | 29 + assets/Locales/Common_Sort.json | 129 +++ assets/Locales/Dialog_XCITrimmer.json | 304 +++++ assets/Locales/GameListContextMenu.json | 29 + assets/Locales/MenuBar_Actions.json | 55 +- assets/Locales/Root.json | 1007 +---------------- assets/Locales/StatusBar.json | 27 +- assets/Locales/XCITrimmer.json | 429 +++++++ .../Common/Models/XCITrimmerFileModel.cs | 50 +- src/Ryujinx/Common/XCITrimmerLog.cs | 4 +- .../UI/Controls/ApplicationContextMenu.axaml | 6 +- .../XCITrimmerFileSpaceSavingsConverter.cs | 47 +- .../XCITrimmerFileStatusConverter.cs | 38 +- .../XCITrimmerOperationOutcomeHelper.cs | 20 +- .../UI/ViewModels/MainWindowViewModel.cs | 26 +- ...merViewModel.cs => XCITrimmerViewModel.cs} | 138 ++- .../DownloadableContentManagerView.axaml | 2 +- .../UI/Views/Dialog/ModManagerView.axaml | 2 +- .../UI/Views/Dialog/XCITrimmerView.axaml | 185 +++ ...rView.axaml.cs => XCITrimmerView.axaml.cs} | 18 +- .../UI/Views/Dialog/XciTrimmerView.axaml | 311 ----- .../UI/Views/Main/MainMenuBarView.axaml | 4 +- .../UI/Views/Main/MainMenuBarView.axaml.cs | 2 +- .../UI/Views/Main/MainStatusBarView.axaml | 48 +- .../UI/Views/Main/MainViewControls.axaml | 6 +- .../UI/Views/User/UserSaveManagerView.axaml | 8 +- 26 files changed, 1466 insertions(+), 1458 deletions(-) create mode 100644 assets/Locales/Common_Search.json create mode 100644 assets/Locales/Common_Sort.json create mode 100644 assets/Locales/Dialog_XCITrimmer.json create mode 100644 assets/Locales/GameListContextMenu.json create mode 100644 assets/Locales/XCITrimmer.json rename src/Ryujinx/UI/ViewModels/{XciTrimmerViewModel.cs => XCITrimmerViewModel.cs} (78%) create mode 100644 src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml rename src/Ryujinx/UI/Views/Dialog/{XciTrimmerView.axaml.cs => XCITrimmerView.axaml.cs} (82%) delete mode 100644 src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml diff --git a/assets/Locales/Common_Search.json b/assets/Locales/Common_Search.json new file mode 100644 index 000000000..9fbe786be --- /dev/null +++ b/assets/Locales/Common_Search.json @@ -0,0 +1,29 @@ +{ + "Locales": [ + { + "ID": "SearchWatermark", + "Translations": { + "ar_SA": "بحث", + "de_DE": "Suche", + "el_GR": "Αναζήτηση", + "en_US": "Search", + "es_ES": "Buscar", + "fr_FR": "Rechercher", + "he_IL": "חפש", + "it_IT": "Cerca", + "ja_JP": "検索", + "ko_KR": "찾기", + "no_NO": "Søk", + "pl_PL": "Wyszukaj", + "pt_BR": "Buscar", + "ru_RU": "Поиск", + "sv_SE": "Sök", + "th_TH": "ค้นหา", + "tr_TR": "Ara", + "uk_UA": "Пошук", + "zh_CN": "搜索", + "zh_TW": "搜尋" + } + } + ] +} diff --git a/assets/Locales/Common_Sort.json b/assets/Locales/Common_Sort.json new file mode 100644 index 000000000..8c614bfda --- /dev/null +++ b/assets/Locales/Common_Sort.json @@ -0,0 +1,129 @@ +{ + "Locales": [ + { + "ID": "NameLabel", + "Translations": { + "ar_SA": "الاسم", + "de_DE": "", + "el_GR": "Όνομα", + "en_US": "Name", + "es_ES": "Nombre", + "fr_FR": "Nom", + "he_IL": "שם", + "it_IT": "Nome", + "ja_JP": "名称", + "ko_KR": "이름", + "no_NO": "Navn", + "pl_PL": "Nazwa", + "pt_BR": "Nome", + "ru_RU": "Название", + "sv_SE": "Namn", + "th_TH": "ชื่อ", + "tr_TR": "İsim", + "uk_UA": "Назва", + "zh_CN": "名称", + "zh_TW": "名稱" + } + }, + { + "ID": "SavingsLabel", + "Translations": { + "ar_SA": "التوفير", + "de_DE": "Einsparung", + "el_GR": "Εξοικονόμηση", + "en_US": "Savings", + "es_ES": "Ahorro", + "fr_FR": "Économies", + "he_IL": "חיסכון", + "it_IT": "Risparmio", + "ja_JP": "節約", + "ko_KR": "절약", + "no_NO": "Besparelse", + "pl_PL": "Oszczędność", + "pt_BR": "Economia", + "ru_RU": "Экономия", + "sv_SE": "Besparing", + "th_TH": "การประหยัด", + "tr_TR": "Tasarruf", + "uk_UA": "Економія", + "zh_CN": "节省", + "zh_TW": "節省" + } + }, + { + "ID": "TrimStatusLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Trim Status", + "es_ES": "Estado del recorte", + "fr_FR": "État de réduction", + "he_IL": "", + "it_IT": "Stato della riduzione", + "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": "OrderAscending", + "Translations": { + "ar_SA": "تصاعدي", + "de_DE": "Aufsteigend", + "el_GR": "Αύξουσα", + "en_US": "Ascending", + "es_ES": "Ascendente", + "fr_FR": "Croissant", + "he_IL": "סדר עולה", + "it_IT": "Crescente", + "ja_JP": "昇順", + "ko_KR": "오름차순", + "no_NO": "Stigende", + "pl_PL": "Rosnąco", + "pt_BR": "Ascendente", + "ru_RU": "По Возрастанию", + "sv_SE": "Stigande", + "th_TH": "จากน้อยไปมาก", + "tr_TR": "Artan", + "uk_UA": "За зростанням", + "zh_CN": "升序", + "zh_TW": "從小到大" + } + }, + { + "ID": "OrderDescending", + "Translations": { + "ar_SA": "تنازلي", + "de_DE": "Absteigend", + "el_GR": "Φθίνουσα", + "en_US": "Descending", + "es_ES": "Descendente", + "fr_FR": "Décroissant", + "he_IL": "סדר יורד", + "it_IT": "Decrescente", + "ja_JP": "降順", + "ko_KR": "내림차순", + "no_NO": "Synkende", + "pl_PL": "Malejąco", + "pt_BR": "Descendente", + "ru_RU": "По Убыванию", + "sv_SE": "Fallande", + "th_TH": "จากมากไปน้อย", + "tr_TR": "Azalan", + "uk_UA": "За спаданням", + "zh_CN": "降序", + "zh_TW": "從大到小" + } + } + ] +} diff --git a/assets/Locales/Dialog_XCITrimmer.json b/assets/Locales/Dialog_XCITrimmer.json new file mode 100644 index 000000000..754c14947 --- /dev/null +++ b/assets/Locales/Dialog_XCITrimmer.json @@ -0,0 +1,304 @@ +{ + "Locales": [ + { + "ID": "PrimaryMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Removes unused space from the XCI to reduce its file size.", + "es_ES": "Elimina el espacio no utilizado del XCI para reducir su tamaño.", + "fr_FR": "Supprime l’espace inutilisé du XCI afin de réduire sa taille.", + "he_IL": "", + "it_IT": "Rimuove lo spazio inutilizzato dall'XCI per ridurne le dimensioni.", + "ja_JP": "", + "ko_KR": "XCI에서 사용되지 않는 공간을 제거하여 파일 크기를 줄입니다.", + "no_NO": "Fjerner ubrukt plass fra XCI-filen for å redusere filstørrelsen.", + "pl_PL": "Usuwa nieużywane miejsce z pliku XCI, aby zmniejszyć jego rozmiar.", + "pt_BR": "Remove o espaço não utilizado do XCI para reduzir seu tamanho.", + "ru_RU": "Удаляет неиспользуемое пространство из XCI, уменьшая размер файла.", + "sv_SE": "Tar bort oanvänt utrymme från XCI-filen för att minska filstorleken.", + "th_TH": "ลบพื้นที่ที่ไม่ได้ใช้งานออกจาก XCI เพื่อลดขนาดไฟล์", + "tr_TR": "", + "uk_UA": "Видаляє невикористаний простір із XCI, зменшуючи розмір файлу.", + "zh_CN": "移除 XCI 中未使用的空间以减小文件大小。", + "zh_TW": "移除 XCI 中未使用的空間以減少檔案大小。" + } + }, + { + "ID": "SecondaryMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "File: {0:n} MB • Game: {1:n} MB\n\nSavings: {2:n} MB", + "es_ES": "Archivo: {0:n} MB • Juego: {1:n} MB\n\nAhorro: {2:n} MB", + "fr_FR": "Fichier: {0:n} Mo • Jeu: {1:n} Mo\n\nÉconomies: {2:n} Mo", + "he_IL": "", + "it_IT": "File: {0:n} MB • Gioco: {1:n} MB\n\nRisparmio: {2:n} MB", + "ja_JP": "", + "ko_KR": "파일: {0:n} MB • 게임: {1:n} MB\n\n절약: {2:n} MB", + "no_NO": "Fil: {0:n} MB • Spill: {1:n} MB\n\nBesparelse: {2:n} MB", + "pl_PL": "Plik: {0:n} MB • Gra: {1:n} MB\n\nOszczędności: {2:n} MB", + "pt_BR": "Arquivo: {0:n} MB • Jogo: {1:n} MB\n\nEconomia: {2:n} MB", + "ru_RU": "Файл: {0:n} МБ • Игра: {1:n} МБ\n\nЭкономия: {2:n} МБ", + "sv_SE": "Fil: {0:n} MB • Spel: {1:n} MB\n\nBesparing: {2:n} MB", + "th_TH": "ไฟล์: {0:n} MB • เกม: {1:n} MB\n\nการประหยัด: {2:n} MB", + "tr_TR": "", + "uk_UA": "Файл: {0:n} МБ • Гра: {1:n} МБ\n\nЕкономія: {2:n} МБ", + "zh_CN": "文件: {0:n} MB • 游戏: {1:n} MB\n\n节省: {2:n} MB", + "zh_TW": "檔案: {0:n} MB • 遊戲: {1:n} MB\n\n節省: {2:n} MB" + } + }, + { + "ID": "NoTrimNecessaryMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI does not require trimming. Check logs for details.", + "es_ES": "El XCI no necesita ser recortado. Verifica los logs para detalles.", + "fr_FR": "Le XCI n’a pas besoin d’être réduit. Référez-vous aux journaux pour détails.", + "he_IL": "", + "it_IT": "Non è necessario ridurre la dimensione del XCI. Controlla i log per dettagli.", + "ja_JP": "", + "ko_KR": "XCI는 트리밍할 필요가 없습니다. 자세한 내용은 로그를 확인.", + "no_NO": "XCI trenger ikke å trimmes. Sjekk loggene for detaljer.", + "pl_PL": "XCI nie wymaga przycinania. Sprawdź dzienniki, aby uzyskać szczegóły.", + "pt_BR": "O XCI não precisa ser reduzido. Verifique os logs para detalhes.", + "ru_RU": "XCI не требует обрезки. Проверьте логи для подробностей.", + "sv_SE": "XCI behöver inte optimeras. Kontrollera loggen för detaljer.", + "th_TH": "XCI ไม่จำเป็นต้องถูกตัดแต่ง โปรดตรวจสอบบันทึกสำหรับรายละเอียด", + "tr_TR": "", + "uk_UA": "XCI не потребує обрізання. Перевірте журнали для отримання деталей.", + "zh_CN": "XCI 不需要被瘦身。查看日志以获得更多细节。", + "zh_TW": "XCI 不需要修剪。檢查日誌以取得更多資訊。" + } + }, + { + "ID": "NoUntrimPossibleMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI cannot be untrimmed. Check logs for details.", + "es_ES": "El recorte del XCI no puede ser deshecho. Verifica los registros para detalles.", + "fr_FR": "Le XCI ne peut être restauré. Référez-vous aux journaux pour détails.", + "he_IL": "", + "it_IT": "XCI non può essere ripristinato. Controlla i log per dettagli.", + "ja_JP": "", + "ko_KR": "XCI는 복원할 수 없습니다. 자세한 내용은 로그를 확인.", + "no_NO": "XCI kan ikke gjenopprettes. Sjekk loggene for detaljer.", + "pl_PL": "XCI nie może zostać przywrócone. Sprawdź dzienniki, aby uzyskać szczegóły.", + "pt_BR": "XCI não pode ser desfeito. Verifique os logs para detalhes.", + "ru_RU": "XCI не может быть восстановлен. Проверьте журналы для подробностей.", + "sv_SE": "XCI kan inte återställas. Kontrollera loggen för detaljer.", + "th_TH": "ไม่สามารถคืนค่า XCI ได้ โปรดตรวจสอบบันทึกสำหรับรายละเอียด", + "tr_TR": "", + "uk_UA": "XCI не можна відновити. Перевірте журнали для деталей.", + "zh_CN": "XCI 不能恢复。查看日志以获取详情。", + "zh_TW": "XCI 無法恢復。檢查日誌以取得詳情。" + } + }, + { + "ID": "ReadOnlyFileCannotFixMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI is read-only and could not be made writable. Check logs for details.", + "es_ES": "XCI es solo lectura y no se puede escribir. Verifica los registros para detalles.", + "fr_FR": "XCI en lecture seule et n'a pas pu être rendu écrivable. Référez-vous aux journaux pour détails.", + "he_IL": "", + "it_IT": "XCI è solo lettura e non può essere scritto. Controlla i log per dettagli.", + "ja_JP": "", + "ko_KR": "XCI 파일은 읽기 전용이며 쓰기 불가. 로그를 확인하십시오.", + "no_NO": "XCI er skrivebeskyttet og kunne ikke gjøres skrivbar. Sjekk loggene for detaljer.", + "pl_PL": "XCI jest tylko do odczytu i nie można zapisać. Sprawdź logi dla szczegółów.", + "pt_BR": "XCI é somente leitura e não pode ser gravado. Verifique os logs para detalhes.", + "ru_RU": "XCI только для чтения и не стал доступен для записи. Проверьте журналы для подробностей.", + "sv_SE": "XCI-filen är skrivskyddad och kunde inte göras skrivbar. Kontrollera loggen för mer information", + "th_TH": "XCI เป็นอ่านอย่างเดียวและไม่สามารถเขียนได้ ตรวจสอบบันทึกสำหรับรายละเอียด", + "tr_TR": "", + "uk_UA": "XCI тільки для читання і не можна записати. Перевірте логи для деталей.", + "zh_CN": "XCI 只读,无法写入。查看日志以获取详情。", + "zh_TW": "XCI 檔案唯讀,無法寫入。檢查日誌以取得詳情。" + } + }, + { + "ID": "SizeChangedMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI size changed since last scan. Ensure the file is not being written to and try again.", + "es_ES": "El tamaño de XCI ha cambiado desde que fue escaneado. Verifica que no se esté escribiendo al archivo y vuelve a intentarlo.", + "fr_FR": "La taille de XCI a changé depuis son analyse. Vérifiez que le fichier n’est pas en cours d’écriture, puis réessayez.", + "he_IL": "", + "it_IT": "La dimensione di XCI è cambiata da quando è stato scansionato. Controlla che il file non sia scritto e riprova.", + "ja_JP": "", + "ko_KR": "XCI 크기가 스캔 후 변경되었습니다. 파일이 쓰여지고 있지 않은지 확인하고 다시 시도하세요.", + "no_NO": "XCI har endret størrelse siden den ble skannet. Kontroller at det ikke skrives til filen, og prøv på nytt.", + "pl_PL": "Rozmiar XCI zmienił się od momentu zeskanowania. Sprawdź, czy plik nie jest zapisywany, a następnie spróbuj ponownie.", + "pt_BR": "O tamanho de XCI mudou desde que foi escaneado. Verifique se o arquivo não está sendo gravado e tente novamente.", + "ru_RU": "Размер XCI изменился после сканирования. Проверьте, не записывается ли файл, и попробуйте снова.", + "sv_SE": "XCI har ändrats i storlek sedan den lästes av. Kontrollera att filen inte skrivs till och försök igen.", + "th_TH": "ขนาด XCI เปลี่ยนไปตั้งแต่การสแกนครั้งล่าสุด ตรวจสอบว่าไฟล์ไม่ได้ถูกเขียน และลองใหม่", + "tr_TR": "", + "uk_UA": "Розмір XCI змінився з моменту сканування. Перевірте, чи не записується файл, та спробуйте знову.", + "zh_CN": "XCI 在扫描后大小发生了变化。请检查文件是否未被写入,然后重试。", + "zh_TW": "XCI 檔案大小自上次掃描以來已經改變。請檢查檔案是否未被寫入,然後再嘗試。" + } + }, + { + "ID": "FreeSpaceCheckFailedMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI has data in the free space area. It is not safe to trim.", + "es_ES": "XCI tiene datos en el área de espacio libre. No es seguro recortarlo.", + "fr_FR": "XCI contient des données dans la zone d'espace libre. Il n'est pas sûr de le réduire.", + "he_IL": "", + "it_IT": "XCI contiene dati nell'area di spazio libero. Non è sicuro ridurre la sua dimensione.", + "ja_JP": "", + "ko_KR": "XCI 파일에 여유 공간 영역에 데이터가 있으므로 트리밍하는 것이 안전하지 않습니다.", + "no_NO": "XCI har data i den ledige plassen. Det er ikke trygt å trimme den.", + "pl_PL": "XCI zawiera dane w obszarze wolnego miejsca. Nie jest bezpieczne go przycinać.", + "pt_BR": "XCI tem dados na área de espaço livre. Não é seguro reduzi-lo.", + "ru_RU": "XCI содержит данные в свободной области. Его обрезка небезопасна.", + "sv_SE": "XCI har data i det lediga utrymmet. Det är inte säkert att optimera.", + "th_TH": "XCI มีข้อมูลในพื้นที่ว่าง จึงไม่ปลอดภัยที่จะทำการตัดแต่ง", + "tr_TR": "", + "uk_UA": "XCI містить дані в зоні вільного простору. Тому обрізка небезпечна.", + "zh_CN": "XCI 文件的空闲区域内有数据。不能安全瘦身。", + "zh_TW": "XCI 檔案有數據儲存於空閒區域。修剪不安全。" + } + }, + { + "ID": "InvalidDataMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI contains invalid data. Check logs for details.", + "es_ES": "XCI contiene datos inválidos. Lee el registro para detalles.", + "fr_FR": "XCI contient des données invalides. Référez-vous aux journaux pour détails.", + "he_IL": "", + "it_IT": "XCI contiene dati non validi. Controlla i log per dettagli.", + "ja_JP": "", + "ko_KR": "XCI 파일에 유효하지 않은 데이터가 포함되어 있습니다. 로그를 확인하세요.", + "no_NO": "XCI-filen inneholder ugyldige data. Sjekk loggene for detaljer.", + "pl_PL": "XCI zawiera nieprawidłowe dane. Sprawdź dzienniki, aby uzyskać szczegóły.", + "pt_BR": "XCI contém dados inválidos. Verifique os logs para detalhes.", + "ru_RU": "XCI содержит недопустимые данные. Проверьте журналы для подробностей.", + "sv_SE": "XCI-filen innehåller ogiltig data. Kontrollera loggen för detaljer.", + "th_TH": "XCI มีข้อมูลที่ไม่ถูกต้อง โปรดตรวจสอบบันทึกสำหรับรายละเอียด", + "tr_TR": "", + "uk_UA": "XCI містить недійсні дані. Перевірте журнали для деталей.", + "zh_CN": "XCI 文件含有无效数据。查看日志以获得更多细节。", + "zh_TW": "XCI 檔案帶有無效的數據。檢查日誌以取得更多資訊" + } + }, + { + "ID": "WriteErrorMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI could not be opened for writing. Check logs for details.", + "es_ES": "XCI no se puede abrir para escribir. Lee el registro para detalles.", + "fr_FR": "XCI n'a pas pu être ouvert pour écriture. Consultez les journaux pour détails.", + "he_IL": "", + "it_IT": "XCI non può essere aperto in scrittura. Controlla i log per dettagli.", + "ja_JP": "", + "ko_KR": "XCI를 쓰기 위해 열 수 없습니다. 로그를 확인하세요.", + "no_NO": "XCI kunne ikke åpnes for skriving. Sjekk loggene for detaljer.", + "pl_PL": "Nie można otworzyć XCI do zapisu. Sprawdź dzienniki, aby uzyskać szczegóły.", + "pt_BR": "XCI não pôde ser aberto para gravação. Verifique os logs para detalhes.", + "ru_RU": "Не удалось открыть XCI для записи. Проверьте журналы для подробностей.", + "sv_SE": "XCI kunde inte öppnas för skrivning. Kontrollera loggen för detaljer.", + "th_TH": "ไม่สามารถเปิด XCI เพื่อเขียนข้อมูลได้ โปรดตรวจสอบบันทึกสำหรับรายละเอียด", + "tr_TR": "", + "uk_UA": "Не вдалося відкрити XCI для запису. Перевірте журнали для деталей.", + "zh_CN": "XCI 不能写入。查看日志以获得更多细节。", + "zh_TW": "XCI 無法開啟以進行寫入。請檢查日誌以取得更多資訊。" + } + }, + { + "ID": "TrimFailedMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Failed to trim XCI.", + "es_ES": "El recorte del XCI falló.", + "fr_FR": "La réduction du XCI a échoué.", + "he_IL": "", + "it_IT": "Riduzione del XCI fallita.", + "ja_JP": "", + "ko_KR": "XCI 트리밍에 실패했습니다.", + "no_NO": "Trimming av XCI mislyktes.", + "pl_PL": "Nie udało się przyciąć XCI.", + "pt_BR": "A redução do XCI falhou.", + "ru_RU": "Обрезка XCI не удалась.", + "sv_SE": "Optimering av XCI misslyckades.", + "th_TH": "การตัดแต่ง XCI ล้มเหลว", + "tr_TR": "", + "uk_UA": "Не вдалося обрізати XCI.", + "zh_CN": "XCI 瘦身失败。", + "zh_TW": "修剪 XCI 失敗。" + } + }, + { + "ID": "TrimCancelledMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "The operation was cancelled.", + "es_ES": "La operación fue cancelada.", + "fr_FR": "L'opération a été annulée.", + "he_IL": "", + "it_IT": "L'operazione è stata annullata.", + "ja_JP": "", + "ko_KR": "작업이 취소되었습니다.", + "no_NO": "Operasjonen ble avbrutt.", + "pl_PL": "", + "pt_BR": "A operação foi cancelada.", + "ru_RU": "Операция была отменена.", + "sv_SE": "Åtgärden avbröts.", + "th_TH": "การดำเนินการถูกยกเลิกแล้ว.", + "tr_TR": "", + "uk_UA": "Операцію перервано.", + "zh_CN": "操作已取消。", + "zh_TW": "操作已取消。" + } + }, + { + "ID": "NoOperationPerformedMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "No operation was performed.", + "es_ES": "No se realizó ninguna operación.", + "fr_FR": "Aucune opération n'a été effectuée.", + "he_IL": "", + "it_IT": "Non è stata effettuata alcuna operazione.", + "ja_JP": "", + "ko_KR": "작업이 수행되지 않았습니다.", + "no_NO": "Ingen operasjon ble utført.", + "pl_PL": "", + "pt_BR": "Nenhuma operação foi realizada.", + "ru_RU": "Операция не была выполнена.", + "sv_SE": "Ingen åtgärd genomfördes.", + "th_TH": "ไม่มีการดำเนินการใด ๆ", + "tr_TR": "", + "uk_UA": "Операцію не було виконано.", + "zh_CN": "未执行任何操作。", + "zh_TW": "沒有執行任何操作。" + } + } + ] +} \ No newline at end of file diff --git a/assets/Locales/GameListContextMenu.json b/assets/Locales/GameListContextMenu.json new file mode 100644 index 000000000..2ed75db6b --- /dev/null +++ b/assets/Locales/GameListContextMenu.json @@ -0,0 +1,29 @@ +{ + "Locales": [ + { + "ID": "TrimXCIButton", + "Translations": { + "ar_SA": "تقليم XCI", + "de_DE": "Zuschneiden der XCI", + "el_GR": "Κοπή XCI", + "en_US": "Trim XCI", + "es_ES": "Recortar XCI", + "fr_FR": "Réduire le XCI", + "he_IL": "חתוך XCI", + "it_IT": "Riduci il XCI", + "ja_JP": "XCIをトリム", + "ko_KR": "XCI 트림", + "no_NO": "Trim XCI-filen", + "pl_PL": "Przytnij XCI", + "pt_BR": "Reduzir o XCI", + "ru_RU": "Обрезать XCI", + "sv_SE": "Optimera XCI", + "th_TH": "ลดขนาด XCI", + "tr_TR": "XCI'yi Kırp", + "uk_UA": "Нарізка XCI", + "zh_CN": "精简 XCI", + "zh_TW": "修剪 XCI" + } + } + ] +} \ No newline at end of file diff --git a/assets/Locales/MenuBar_Actions.json b/assets/Locales/MenuBar_Actions.json index e7f094959..95334b571 100644 --- a/assets/Locales/MenuBar_Actions.json +++ b/assets/Locales/MenuBar_Actions.json @@ -228,26 +228,26 @@ { "ID": "XCITrimmerButton", "Translations": { - "ar_SA": "", - "de_DE": "XCI-Dateien trimmen", + "ar_SA": "", + "de_DE": "XCI-Trimmer", "el_GR": "", - "en_US": "Trim XCI Files", - "es_ES": "Recortar Archivos XCI", - "fr_FR": "Réduire les Fichiers XCI", + "en_US": "XCI Trimmer", + "es_ES": "Recortador de XCI", + "fr_FR": "Réducteur de XCI", "he_IL": "", - "it_IT": "Riduci dimensioni dei file XCI", + "it_IT": "Trimmer XCI", "ja_JP": "", "ko_KR": "XCI 파일 트리머", "no_NO": "Trim XCI-filer", - "pl_PL": "", - "pt_BR": "Reduzir Arquivos XCI", - "ru_RU": "Обрезать XCI файлы", - "sv_SE": "Optimera XCI-filer", - "th_TH": "ตัดแต่งไฟล์ XCI", - "tr_TR": "", - "uk_UA": "Обрізати XCI файли", - "zh_CN": "瘦身 XCI 文件", - "zh_TW": "修剪 XCI 檔案" + "pl_PL": "Przycinacz XCI", + "pt_BR": "Cortador de XCI", + "ru_RU": "Триммер XCI", + "sv_SE": "XCI-trimmer", + "th_TH": "", + "tr_TR": "XCI Kesici", + "uk_UA": "Тример XCI", + "zh_CN": "", + "zh_TW": "" } }, { @@ -450,6 +450,31 @@ "zh_TW": "移除 Skylander" } }, + { + "ID": "SimulateWakeUpMessageButton", + "Translations": { + "ar_SA": "محاكاة رسالة الاستيقاظ", + "de_DE": "Aufwachnachricht simulieren", + "el_GR": "Προσομοίωση Μηνύματος Αφύπνισης", + "en_US": "Simulate Wake-Up Message", + "es_ES": "Simular Mensaje de Reactivación", + "fr_FR": "Simuler un Message de Réveil", + "he_IL": "דמה הודעת השכמה", + "it_IT": "Simula messaggio di risveglio", + "ja_JP": "スリープ復帰メッセージをシミュレート", + "ko_KR": "절전 모드 해제 메시지 시뮬레이션", + "no_NO": "Simuler oppvåknings-melding", + "pl_PL": "Symuluj wiadomość wybudzania", + "pt_BR": "Simular Mensagem de Acordar o Console", + "ru_RU": "Имитировать сообщение пробуждения", + "sv_SE": "Simulera uppvakningsmeddelande", + "th_TH": "จำลองการปลุกอุปกรณ์ให้ทำงาน", + "tr_TR": "Uyandırma Mesajı Simüle Et", + "uk_UA": "Симулювати повідомлення про пробудження", + "zh_CN": "模拟唤醒消息", + "zh_TW": "模擬喚醒訊息" + } + }, { "ID": "TakeScreenshotButton", "Translations": { diff --git a/assets/Locales/Root.json b/assets/Locales/Root.json index 75ffe3bbe..e85a1c6a6 100644 --- a/assets/Locales/Root.json +++ b/assets/Locales/Root.json @@ -1,4 +1,4 @@ -{ +{ "Locales": [ { "ID": "SettingsTabInputDirectMouseAccess", @@ -325,31 +325,6 @@ "zh_TW": "使用者設定檔(_M)" } }, - { - "ID": "MenuBarOptionsSimulateWakeUpMessage", - "Translations": { - "ar_SA": "محاكاة رسالة الاستيقاظ", - "de_DE": "Aufwachnachricht simulieren", - "el_GR": "Προσομοίωση Μηνύματος Αφύπνισης", - "en_US": "Simulate Wake-Up Message", - "es_ES": "Simular Mensaje de Reactivación", - "fr_FR": "Simuler un Message de Réveil", - "he_IL": "דמה הודעת השכמה", - "it_IT": "Simula messaggio di risveglio", - "ja_JP": "スリープ復帰メッセージをシミュレート", - "ko_KR": "절전 모드 해제 메시지 시뮬레이션", - "no_NO": "Simuler oppvåknings-melding", - "pl_PL": "Symuluj wiadomość wybudzania", - "pt_BR": "Simular Mensagem de Acordar o Console", - "ru_RU": "Имитировать сообщение пробуждения", - "sv_SE": "Simulera uppvakningsmeddelande", - "th_TH": "จำลองการปลุกอุปกรณ์ให้ทำงาน", - "tr_TR": "Uyandırma Mesajı Simüle Et", - "uk_UA": "Симулювати повідомлення про пробудження", - "zh_CN": "模拟唤醒消息", - "zh_TW": "模擬喚醒訊息" - } - }, { "ID": "MenuBarView", "Translations": { @@ -750,31 +725,6 @@ "zh_TW": "圖示" } }, - { - "ID": "GameListHeaderApplication", - "Translations": { - "ar_SA": "الاسم", - "de_DE": "", - "el_GR": "Όνομα", - "en_US": "Name", - "es_ES": "Nombre", - "fr_FR": "Nom", - "he_IL": "שם", - "it_IT": "Nome", - "ja_JP": "名称", - "ko_KR": "이름", - "no_NO": "Navn", - "pl_PL": "Nazwa", - "pt_BR": "Nome", - "ru_RU": "Название", - "sv_SE": "Namn", - "th_TH": "ชื่อ", - "tr_TR": "Oyun Adı", - "uk_UA": "Назва", - "zh_CN": "名称", - "zh_TW": "名稱" - } - }, { "ID": "GameListHeaderDeveloper", "Translations": { @@ -8466,7 +8416,7 @@ "no_NO": "Veiledning", "pl_PL": "", "pt_BR": "Guia", - "ru_RU": "Кнопка меню", + "ru_RU": "Меню", "sv_SE": null, "th_TH": "คู่มือ", "tr_TR": "Rehber", @@ -10775,31 +10725,6 @@ "zh_TW": "開啟設定視窗" } }, - { - "ID": "DialogOpenXCITrimmerWindowLabel", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "XCI Trimmer Window", - "es_ES": "Ventana Recortador XCI", - "fr_FR": "Fenêtre de Réduction de Fichiers XCI", - "he_IL": "", - "it_IT": "Riduci dimensioni dei file XCI", - "ja_JP": "", - "ko_KR": "XCI 트리머 창", - "no_NO": "XCI Trimmervindu", - "pl_PL": "", - "pt_BR": "Janela de Redução XCI", - "ru_RU": "Окно XCI триммера", - "sv_SE": "XCI-optimerare", - "th_TH": "หน้าต่างตัดแต่งไฟล์ XCI", - "tr_TR": "", - "uk_UA": "Вікно XCI Тримера", - "zh_CN": "XCI 文件瘦身窗口", - "zh_TW": "XCI 修剪器視窗" - } - }, { "ID": "DialogControllerAppletTitle", "Translations": { @@ -13000,56 +12925,6 @@ "zh_TW": "我的最愛" } }, - { - "ID": "OrderAscending", - "Translations": { - "ar_SA": "تصاعدي", - "de_DE": "Aufsteigend", - "el_GR": "Αύξουσα", - "en_US": "Ascending", - "es_ES": "Ascendente", - "fr_FR": "Croissant", - "he_IL": "סדר עולה", - "it_IT": "Crescente", - "ja_JP": "昇順", - "ko_KR": "오름차순", - "no_NO": "Stigende", - "pl_PL": "Rosnąco", - "pt_BR": "Ascendente", - "ru_RU": "По Возрастанию", - "sv_SE": "Stigande", - "th_TH": "จากน้อยไปมาก", - "tr_TR": "Artan", - "uk_UA": "За зростанням", - "zh_CN": "升序", - "zh_TW": "從小到大" - } - }, - { - "ID": "OrderDescending", - "Translations": { - "ar_SA": "تنازلي", - "de_DE": "Absteigend", - "el_GR": "Φθίνουσα", - "en_US": "Descending", - "es_ES": "Descendente", - "fr_FR": "Décroissant", - "he_IL": "סדר יורד", - "it_IT": "Decrescente", - "ja_JP": "降順", - "ko_KR": "내림차순", - "no_NO": "Synkende", - "pl_PL": "Malejąco", - "pt_BR": "Descendente", - "ru_RU": "По Убыванию", - "sv_SE": "Fallande", - "th_TH": "จากมากไปน้อย", - "tr_TR": "Azalan", - "uk_UA": "За спаданням", - "zh_CN": "降序", - "zh_TW": "從大到小" - } - }, { "ID": "SettingsTabGraphicsFeatures", "Translations": { @@ -15100,156 +14975,6 @@ "zh_TW": "附帶:" } }, - { - "ID": "TitleXCIStatusPartialLabel", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Partial", - "es_ES": "Parcial", - "fr_FR": "Partiel", - "he_IL": "", - "it_IT": "Parziale", - "ja_JP": "", - "ko_KR": "일부", - "no_NO": "Delvis", - "pl_PL": "", - "pt_BR": "Parcial", - "ru_RU": "Частично", - "sv_SE": "Delvis", - "th_TH": "ยังไม่สมบูรณ์", - "tr_TR": "", - "uk_UA": "Часткові", - "zh_CN": "分区", - "zh_TW": "部分" - } - }, - { - "ID": "TitleXCIStatusTrimmableLabel", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Untrimmed", - "es_ES": "Sin Recortar", - "fr_FR": "Non Réduit", - "he_IL": "", - "it_IT": "Dim. originale", - "ja_JP": "", - "ko_KR": "트리밍되지 않음", - "no_NO": "Ikke trimmet", - "pl_PL": "", - "pt_BR": "Não Reduzido", - "ru_RU": "Не обрезан", - "sv_SE": "Orörd", - "th_TH": "ยังไม่ได้ตัดแต่ง", - "tr_TR": "", - "uk_UA": "Необрізані", - "zh_CN": "没有瘦身的", - "zh_TW": "未修剪" - } - }, - { - "ID": "TitleXCIStatusUntrimmableLabel", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Trimmed", - "es_ES": "Recortado", - "fr_FR": "Réduit", - "he_IL": "", - "it_IT": "Dim. ridotta", - "ja_JP": "", - "ko_KR": "트리밍됨", - "no_NO": "Trimmet", - "pl_PL": "", - "pt_BR": "Reduzido", - "ru_RU": "Обрезан", - "sv_SE": "Optimerad", - "th_TH": "ตัดแต่งแล้ว", - "tr_TR": "", - "uk_UA": "Обрізані", - "zh_CN": "经过瘦身的", - "zh_TW": "已修剪" - } - }, - { - "ID": "TitleXCIStatusFailedLabel", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "(Failed)", - "es_ES": "(Fallido)", - "fr_FR": "(Échoué)", - "he_IL": "", - "it_IT": "(Fallito)", - "ja_JP": "", - "ko_KR": "(실패)", - "no_NO": "(Mislyktes)", - "pl_PL": "", - "pt_BR": "Falhou", - "ru_RU": "(Ошибка)", - "sv_SE": "(misslyckades)", - "th_TH": "(ล้มเหลว)", - "tr_TR": "", - "uk_UA": "(Невдача)", - "zh_CN": "(失败)", - "zh_TW": "(失敗)" - } - }, - { - "ID": "TitleXCICanSaveLabel", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Save {0:n0} Mb", - "es_ES": "Ahorra {0:n0} Mb", - "fr_FR": "Sauvegarde de {0:n0} Mo", - "he_IL": "", - "it_IT": "Risparmia {0:n0} MB", - "ja_JP": "", - "ko_KR": "{0:n0}MB 저장", - "no_NO": "Spare {0:n0} Mb", - "pl_PL": "", - "pt_BR": "Salvar {0:n0} Mb", - "ru_RU": "Освободить {0:n0} Мб", - "sv_SE": "Spara {0:n0} Mb", - "th_TH": "บันทึก {0:n0} เมกะไบต์", - "tr_TR": "", - "uk_UA": "Зберегти {0:n0} Мб", - "zh_CN": "能节约 {0:n0} Mb", - "zh_TW": "可節省 {0:n0} Mb" - } - }, - { - "ID": "TitleXCISavingLabel", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Saved {0:n0} Mb", - "es_ES": "{0:n0} Mb ahorrado(s)", - "fr_FR": "Sauvegardé {0:n0} Mo", - "he_IL": "", - "it_IT": "Risparmiati {0:n0} MB", - "ja_JP": "", - "ko_KR": "{0:n0}MB 저장됨", - "no_NO": "Spart {0:n0} Mb", - "pl_PL": "", - "pt_BR": "Salvo {0:n0} Mb", - "ru_RU": "Освобождено {0:n0} Мб", - "sv_SE": "Sparade {0:n0} Mb", - "th_TH": "บันทึกแล้ว {0:n0} เมกะไบต์", - "tr_TR": "", - "uk_UA": "Збережено {0:n0} Мб", - "zh_CN": "节约了 {0:n0} Mb", - "zh_TW": "已節省 {0:n0} Mb" - } - }, { "ID": "RyujinxInfo", "Translations": { @@ -16575,306 +16300,6 @@ "zh_TW": "選取模組資料夾" } }, - { - "ID": "TrimXCIFileDialogPrimaryText", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "This function will first check the empty space and then trim the XCI File to save disk space.", - "es_ES": "Esta función verificará el espacio vacío y después recortará el archivo XCI para ahorrar espacio en disco", - "fr_FR": "Cette fonction vérifie d’abord l’espace libre, puis réduit le fichier XCI pour économiser de l’espace disque.", - "he_IL": "", - "it_IT": "Questa funzionalità controllerà prima lo spazio libero e poi ridurrà la dimensione del file XCI per risparmiare spazio su disco.", - "ja_JP": "", - "ko_KR": "이 기능은 먼저 충분한 공간을 확보한 다음 XCI 파일을 트리밍하여 디스크 공간을 절약합니다.", - "no_NO": "Denne funksjonen kontrollerer først hvor mye plass som er ledig, og trimmer deretter XCI-filen for å spare diskplass.", - "pl_PL": "", - "pt_BR": "Esta função primeiro verificará o espaço vazio e depois reduzirá o arquivo XCI para economizar espaço em disco.", - "ru_RU": "Эта функция сначала проверит наличие пустого пространства, а затем обрежет XCI файл для экономии места на диске.", - "sv_SE": "Denna funktion kommer först att kontrollera ledigt utrymme och sedan optimera XCI-filen för att spara diskutrymme.", - "th_TH": "ฟังก์ชันนี้จะตรวจสอบพื้นที่ว่างก่อน จากนั้นจึงตัดแต่งไฟล์ XCI เพื่อประหยัดพื้นที่ดิสก์", - "tr_TR": "", - "uk_UA": "Ця функція спочатку перевірить наявність порожнього місця, після чого обріже файл XCI для економії місця на диску.", - "zh_CN": "这个功能将会先检查 XCI 文件,再对其执行瘦身操作以节约磁盘空间。", - "zh_TW": "此功能首先檢查 XCI 檔案是否有可修剪的字元,然後修剪檔案以節省儲存空間。" - } - }, - { - "ID": "TrimXCIFileDialogSecondaryText", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Current File Size: {0:n} MB\nGame Data Size: {1:n} MB\nDisk Space Savings: {2:n} MB", - "es_ES": "Tamaño de archivo actual: {0:n} MB\nTamaño de datos de juego: {1:n} MB\nAhorro de espacio en disco: {2:n} MB", - "fr_FR": "Taille actuelle du fichier: {0:n} MB\nTaille des données du jeu: {1:n} MB\nEspace disque économisé: {2:n} MB", - "he_IL": "", - "it_IT": "Dimensione attuale del file: {0:n} MB\nDimensione dei dati del gioco: {1:n} MB\nRisparmio spazio su disco: {2:n} MB", - "ja_JP": "", - "ko_KR": "현재 파일 크기 : {0:n}MB\n게임 데이터 크기 : {1:n}MB\n디스크 공간 절약 : {2:n}MB", - "no_NO": "Nåværende filstørrelse: 0:n MB\nSpilldatastørrelse: {1:n} MB\nDiskplassbesparelse: {2:n} MB", - "pl_PL": "", - "pt_BR": "Tamanho atual do arquivo: {0:n} MB\nTamanho dos dados do jogo: {1:n} MB\nEconomia de espaço em disco: {2:n} MB", - "ru_RU": "Размер текущего файла: {0:n} Мб\nРазмер игровых данных: {1:n} MB\nЭкономия дискового пространства: {2:n} Мб", - "sv_SE": "Aktuell filstorlek: {0:n} MB\nStorlek för speldata: {1:n} MB\nSparat diskutrymme: {2:n} MB", - "th_TH": "ขนาดไฟล์ปัจจุบัน: {0:n} เมกะไบต์\nขนาดข้อมูลเกม: {1:n} เมกะไบต์\nพื้นที่ดิสก์ที่ประหยัดได้: {2:n} เมกะไบต์", - "tr_TR": "", - "uk_UA": "Поточний розмір файла: {0:n} MB\nРозмір файлів гри: {1:n} MB\nЕкономія місця: {2:n} MB", - "zh_CN": "当前文件大小: {0:n} MB\n游戏数据大小: {1:n} MB\n节约的磁盘空间: {2:n} MB", - "zh_TW": "現在的檔案大小: {0:n} MB\n遊戲資料大小: {1:n} MB\n節省的儲存空間: {2:n} MB" - } - }, - { - "ID": "TrimXCIFileNoTrimNecessary", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "XCI File does not need to be trimmed. Check logs for further details", - "es_ES": "El archivo XCI no necesita ser recortado. Verifica los logs para más detalles.", - "fr_FR": "Le Fichier XCI n’a pas besoin d’être réduit. Référez-vous aux journaux pour plus de détails.", - "he_IL": "", - "it_IT": "Non è necessario ridurre la dimensione del file XCI. Controlla i log per ulteriori dettagli", - "ja_JP": "", - "ko_KR": "XCI 파일은 트리밍할 필요가 없습니다. 자세한 내용은 로그를 확인", - "no_NO": "XCI-filen trenger ikke å trimmes. Sjekk loggene for mer informasjon", - "pl_PL": "", - "pt_BR": "O arquivo XCI não precisa ser reduzido. Verifique os logs para mais detalhes", - "ru_RU": "XCI файл содержит недопустимые данные. Проверьте логи для получения дополнительной информации.", - "sv_SE": "XCI-filen behöver inte optimeras. Kontrollera loggen för mer information", - "th_TH": "ไฟล์ XCI ไม่จำเป็นต้องถูกตัดแต่ง โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม", - "tr_TR": "", - "uk_UA": "XCI файл не потребує обрізання. Перевірте журнали (logs) для отримання додаткової інформації", - "zh_CN": "XCI 文件不需要被瘦身。查看日志以获得更多细节。", - "zh_TW": "XCI 檔案不需要修剪。檢查日誌以取得更多資訊" - } - }, - { - "ID": "TrimXCIFileNoUntrimPossible", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "XCI File cannot be untrimmed. Check logs for further details", - "es_ES": "El recorte del archivo XCI no puede ser deshecho. Verifica los registros para más detalles.", - "fr_FR": "Fichier XCI ne peut pas être dé-réduit. Référez-vous aux journaux pour plus de détails", - "he_IL": "", - "it_IT": "Il file XCI non può essere riportato alla sua dimensione originale. Controlla i log per ulteriori dettagli", - "ja_JP": "", - "ko_KR": "XCI 파일은 트리밍을 해제할 수 없습니다. 자세한 내용은 로그를 확인", - "no_NO": "XCI-filen kan ikke trimmes. Sjekk loggene for mer informasjon", - "pl_PL": "", - "pt_BR": "O arquivo XCI reduzido não pode ser desfeito. Verifique os logs para mais detalhes", - "ru_RU": "XCI файл не может быть обрезан. Проверьте логи для получения более подробной информации", - "sv_SE": "XCI-filen kan inte avoptimeras. Kontrollera loggen för mer information", - "th_TH": "ไฟล์ XCI ไม่สามารถคืนสภาพเดิม (untrimmed) ได้ โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม", - "tr_TR": "", - "uk_UA": "XCI файл не може бути обрізаний. Перевірте журнали (logs) для отримання додаткової інформації", - "zh_CN": "XCI 文件不能被瘦身。查看日志以获得更多细节。", - "zh_TW": "XCI 檔案不能被修剪。檢查日誌以取得更多資訊" - } - }, - { - "ID": "TrimXCIFileReadOnlyFileCannotFix", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "XCI File is Read Only and could not be made writable. Check logs for further details", - "es_ES": "El archivo XCI es de solo Lectura y no se le puede escribir. Lee el registro para más información.", - "fr_FR": "Fichier XCI est en Lecture Seule et n'a pas pu être rendu accessible en écriture. Référez-vous aux journaux pour plus de détails", - "he_IL": "", - "it_IT": "Il file XCI è in sola lettura e non può essere reso accessibile in scrittura. Controlla i log per ulteriori dettagli", - "ja_JP": "", - "ko_KR": "XCI 파일은 읽기 전용이므로 쓰기 가능하게 만들 수 없습니다. 자세한 내용은 로그를 확인", - "no_NO": "XCI-filen er skrivebeskyttet og kunne ikke gjøres skrivbar. Sjekk loggene for mer informasjon", - "pl_PL": "", - "pt_BR": "O arquivo XCI é somente leitura e não pôde ser tornado gravável. Verifique os logs para mais detalhes", - "ru_RU": "XCI файл доступен только для чтения и его невозможно сделать доступным для записи. Проверьте логи для получения более подробной информации", - "sv_SE": "XCI-filen är skrivskyddad och kunde inte göras skrivbar. Kontrollera loggen för mer information", - "th_TH": "ไฟล์ XCI เป็นแบบอ่านอย่างเดียว และไม่สามารถเปลี่ยนเป็นแบบเขียนได้ โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม", - "tr_TR": "", - "uk_UA": "XCI файл \"Тільки для Читання\" і не може бути прочитаним. Перевірте журнали (logs) для отримання додаткової інформації", - "zh_CN": "XCI 文件是只读的,且不可以被标记为可读取的。查看日志以获得更多细节。", - "zh_TW": "XCI 檔案是唯讀,並且無法改成可寫入。檢查日誌以取得更多資訊" - } - }, - { - "ID": "TrimXCIFileFileSizeChanged", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "XCI File has changed in size since it was scanned. Please check the file is not being written to and try again.", - "es_ES": "El archivo XCI ha cambiado de tamaño desde que fue escaneado. Verifica que no se esté escribiendo al archivo y vuelve a intentarlo.", - "fr_FR": "La taille du Fichier XCI a changé depuis son analyse. Veuillez vérifier que le fichier n’est pas en cours d’écriture, puis réessayez.", - "he_IL": "", - "it_IT": "La dimensione del file XCI è cambiata da quando è stato scansionato. Controlla che il file non stia venendo scritto da qualche altro programma e poi riprova.", - "ja_JP": "", - "ko_KR": "XCI 파일이 스캔된 후 크기가 변경되었습니다. 파일이 쓰여지고 있지 않은지 확인하고 다시 시도하세요.", - "no_NO": "XCI File har endret størrelse siden den ble skannet. Kontroller at det ikke skrives til filen, og prøv på nytt.", - "pl_PL": "", - "pt_BR": "O arquivo XCI mudou de tamanho desde que foi escaneado. Verifique se o arquivo não está sendo gravado e tente novamente.", - "ru_RU": "XCI файл изменился в размере после сканирования. Проверьте, не производится ли запись в этот файл, и повторите попытку.", - "sv_SE": "XCI-filen har ändrats i storlek sedan den lästes av. Kontrollera att filen inte skrivs till och försök igen.", - "th_TH": "ขนาดไฟล์ XCI มีการเปลี่ยนแปลงตั้งแต่ที่สแกนครั้งล่าสุด กรุณาตรวจสอบว่าไฟล์ไม่ได้ถูกเขียนข้อมูล และลองใหม่อีกครั้ง", - "tr_TR": "", - "uk_UA": "Розмір файлу XCI змінився з моменту сканування. Перевірте, чи не записується файл, та спробуйте знову", - "zh_CN": "XCI 文件在扫描后大小发生了变化。请检查文件是否未被写入,然后重试。", - "zh_TW": "XCI 檔案大小比較上次的掃瞄已經改變。請檢查檔案是否未被寫入,然後再嘗試。" - } - }, - { - "ID": "TrimXCIFileFreeSpaceCheckFailed", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "XCI File has data in the free space area, it is not safe to trim", - "es_ES": "El archivo XCI tiene datos en el área de espacio libre, no es seguro recortar.", - "fr_FR": "Fichier XCI a des données dans la zone d'espace libre, ce n'est pas sûr de réduire", - "he_IL": "", - "it_IT": "Il file XCI contiene dei dati nello spazio libero, non è sicuro ridurne la dimensione", - "ja_JP": "", - "ko_KR": "XCI 파일에 여유 공간 영역에 데이터가 있으므로 트리밍하는 것이 안전하지 않음", - "no_NO": "XCI-filen har data i ledig plass, og det er ikke trygt å trimme den", - "pl_PL": "", - "pt_BR": "O arquivo XCI tem dados na área de espaço livre, não é seguro reduzi-lo", - "ru_RU": "XCI файл содержит данные в пустой зоне, обрезать его небезопасно", - "sv_SE": "XCI-filen har data i det lediga utrymmet. Den är inte säker att optimera", - "th_TH": "ไฟล์ XCI มีข้อมูลในพื้นที่ว่าง จึงไม่ปลอดภัยที่จะทำการตัดแต่ง", - "tr_TR": "", - "uk_UA": "Файл XCI містить дані в зоні вільного простору, тому обрізка небезпечна", - "zh_CN": "XCI 文件的空闲区域内有数据,不能安全瘦身。", - "zh_TW": "XCI 檔案有數據儲存於可節省儲存空間的區域,所以試圖修剪並不安全" - } - }, - { - "ID": "TrimXCIFileInvalidXCIFile", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "XCI File contains invalid data. Check logs for further details", - "es_ES": "El archivo XCI contiene datos inválidos. Lee el registro para más información.", - "fr_FR": "Fichier XCI contient des données invalides. Regarder les journaux pour plus de détails", - "he_IL": "", - "it_IT": "Il file XCI contiene dei dati non validi. Controlla i log per ulteriori dettagli", - "ja_JP": "", - "ko_KR": "XCI 파일에 유효하지 않은 데이터가 포함되어 있습니다. 자세한 내용은 로그를 확인", - "no_NO": "XCI-filen inneholder ugyldige data. Sjekk loggene for ytterligere detaljer", - "pl_PL": "", - "pt_BR": "O arquivo XCI contém dados inválidos. Verifique os logs para obter mais detalhes", - "ru_RU": "XCI файл содержит недопустимые данные. Проверьте логи для получения дополнительной информации", - "sv_SE": "XCI-filen innehåller ogiltig data. Kontrollera loggen för mer information", - "th_TH": "ไฟล์ XCI มีข้อมูลที่ไม่ถูกต้อง โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม", - "tr_TR": "", - "uk_UA": "XCI Файл містить недійсні дані. Перевірте журнали (logs) для отримання додаткової інформації", - "zh_CN": "XCI 文件含有无效数据。查看日志以获得更多细节。", - "zh_TW": "XCI 檔案帶有無效的數據。檢查日誌以取得更多資訊" - } - }, - { - "ID": "TrimXCIFileFileIOWriteError", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "XCI File could not be opened for writing. Check logs for further details", - "es_ES": "El archivo XCI no se puede abrir para escribirlo. Lee el registro para más información.", - "fr_FR": "Fichier XCI n'a pas pu être ouvert pour écriture. Regarder les journaux pour plus de détails", - "he_IL": "", - "it_IT": "Il file XCI non può essere aperto in scrittura. Controlla i log per ulteriori dettagli", - "ja_JP": "", - "ko_KR": "XCI 파일을 쓰기 위해 열 수 없습니다. 자세한 내용은 로그를 확인", - "no_NO": "XCI-filen kunne ikke åpnes for skriving. Sjekk loggene for ytterligere detaljer", - "pl_PL": "", - "pt_BR": "O arquivo XCI não pôde ser aberto para gravação. Verifique os logs para mais detalhes", - "ru_RU": "Не удалось открыть XCI файл для записи. Проверьте журналы для получения дополнительной информации", - "sv_SE": "XCI-filen kunde inte öppnas för skrivning. Kontrollera loggen för mer information", - "th_TH": "ไม่สามารถเปิดไฟล์ XCI เพื่อเขียนข้อมูลได้ โปรดตรวจสอบบันทึก (logs) สำหรับรายละเอียดเพิ่มเติม", - "tr_TR": "", - "uk_UA": "XCI Файл файл не вдалося відкрити для запису. Перевірте журнали для додаткової інформації", - "zh_CN": "XCI 文件不能被读写。查看日志以获得更多细节。", - "zh_TW": "XCI 檔案不能被寫入。檢查日誌以取得更多資訊" - } - }, - { - "ID": "TrimXCIFileFailedPrimaryText", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Trimming of the XCI file failed", - "es_ES": "El recorte del archivo XCI falló", - "fr_FR": "Réduction du fichier XCI a échoué", - "he_IL": "", - "it_IT": "Riduzione della dimensione del file XCI fallita", - "ja_JP": "", - "ko_KR": "XCI 파일 트리밍에 실패", - "no_NO": "Trimming av XCI-filen mislyktes", - "pl_PL": "", - "pt_BR": "A redução do arquivo XCI falhou", - "ru_RU": "Обрезка XCI файла не удалась", - "sv_SE": "Optimering av XCI-filen misslyckades", - "th_TH": "การตัดแต่งไฟล์ XCI ล้มเหลว", - "tr_TR": "", - "uk_UA": "Не вдалося обрізати файл XCI", - "zh_CN": "XCI 文件瘦身失败", - "zh_TW": "修剪 XCI 檔案失敗" - } - }, - { - "ID": "TrimXCIFileCancelled", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "The operation was cancelled", - "es_ES": "La operación fue cancelada", - "fr_FR": "L'opération a été annulée", - "he_IL": "", - "it_IT": "L'operazione è stata annullata", - "ja_JP": "", - "ko_KR": "작업이 취소됨", - "no_NO": "Operasjonen ble avlyst", - "pl_PL": "", - "pt_BR": "A operação foi cancelada", - "ru_RU": "Операция была отменена", - "sv_SE": "Åtgärden avbröts", - "th_TH": "การดำเนินการถูกยกเลิกแล้ว", - "tr_TR": "", - "uk_UA": "Операція перервана", - "zh_CN": "操作已取消", - "zh_TW": "修剪已取消" - } - }, - { - "ID": "TrimXCIFileFileUndertermined", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "No operation was performed", - "es_ES": "No se realizó ninguna operación", - "fr_FR": "Aucune opération a été faite", - "he_IL": "", - "it_IT": "Non è stata effettuata alcuna operazione", - "ja_JP": "", - "ko_KR": "작업이 수행되지 않음", - "no_NO": "Ingen operasjon ble utført", - "pl_PL": "", - "pt_BR": "Nenhuma operação foi realizada", - "ru_RU": "Операция не была проведена", - "sv_SE": "Ingen åtgärd genomfördes", - "th_TH": "ไม่มีการดำเนินการใด ๆ ถูกทำขึ้น", - "tr_TR": "", - "uk_UA": "Операція не проводилася", - "zh_CN": "未执行操作", - "zh_TW": "沒有修剪" - } - }, { "ID": "UserProfileWindowTitle", "Translations": { @@ -17001,378 +16426,28 @@ } }, { - "ID": "XCITrimmerWindowTitle", + "ID": "UpdateWindowUpdateAddedMessage", "Translations": { "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "XCI File Trimmer", - "es_ES": "Recortador de Archivos XCI", - "fr_FR": "Réducteur de Fichiers XCI", + "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": "Riduci dimensioni dei file XCI", + "it_IT": "{0} nuovo/i aggiornamento/i aggiunto/i", "ja_JP": "", - "ko_KR": "XCI 파일 트리머", - "no_NO": "", + "ko_KR": "{0}개의 신규 업데이트가 추가됨", + "no_NO": "{0} ny(e) oppdatering(er) lagt til", "pl_PL": "", - "pt_BR": "Redutor de Arquivo XCI", - "ru_RU": "Триммер XCI файлов", - "sv_SE": "Optimera XCI-filer", - "th_TH": "เครื่องมือตัดแต่งไฟล์ XCI", + "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": "Обрізка XCI Файлів", - "zh_CN": "XCI 文件瘦身器", - "zh_TW": "XCI 檔案修剪器" - } - }, - { - "ID": "XCITrimmerTitleStatusCount", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0} of {1} Title(s) Selected", - "es_ES": "{0} de {1} Título(s) Seleccionado(s)", - "fr_FR": "{0} sur {1} Fichier(s) Sélectionnés", - "he_IL": "", - "it_IT": "{0} di {1} titoli selezionati", - "ja_JP": "", - "ko_KR": "{1}개 타이틀 중 {0}개 선택됨", - "no_NO": "{0} av {1} Valgte tittel(er)", - "pl_PL": "", - "pt_BR": "{0} de {1} Título(s) Selecionado(s)", - "ru_RU": "{0} из {1} файл(а/ов) выбран(о)", - "sv_SE": "{0} av {1} spel markerade", - "th_TH": "เลือก {0} จาก {1} รายการ", - "tr_TR": "", - "uk_UA": "{0} з {1} тайтл(ів) обрано", - "zh_CN": "在 {1} 中选中了 {0} 个游戏 ", - "zh_TW": "已選擇 {1} 之 {0} 的遊戲" - } - }, - { - "ID": "XCITrimmerTitleStatusCountWithFilter", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0} of {1} Title(s) Selected ({2} displayed)", - "es_ES": "{0} de {1} Título(s) Seleccionado(s) ({2} Mostrado(s))", - "fr_FR": "{0} sur {1} Fichier(s) Sélectionnés ({2} affiché(s)", - "he_IL": "", - "it_IT": "{0} di {1} titoli selezionati ({2} visualizzati)", - "ja_JP": "", - "ko_KR": "{1}개 타이틀 중 {0}개 선택됨({2}개 표시됨)", - "no_NO": "{0} av {1} Tittel(er) valgt ({2} vises)", - "pl_PL": "", - "pt_BR": "{0} de {1} Título(s) Selecionado(s) ({2} exibidos)", - "ru_RU": "{0} из {1} файл(а/ов) выбран(о) ({2} показан(о))", - "sv_SE": "{0} av {1} spel markerade ({2} visade)", - "th_TH": "เลือก {0} จาก {1} รายการ (แสดงผล {2} รายการ)", - "tr_TR": "", - "uk_UA": "{0} з {1} тайтл(ів) обрано ({2} відображається)", - "zh_CN": "在 {1} 中选中了 {0} 个游戏 (显示了 {2} 个)", - "zh_TW": "已選擇 {1} 之 {0} 的遊戲 (已顯示 {2} 個)" - } - }, - { - "ID": "XCITrimmerTitleStatusTrimming", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Trimming {0} Title(s)...", - "es_ES": "Recortando {0} Título(s)...", - "fr_FR": "Réduction de {0} Fichier(s)...", - "he_IL": "", - "it_IT": "Riduzione delle dimensioni di {0} titolo/i...", - "ja_JP": "", - "ko_KR": "{0}개의 타이틀을 트리밍 중...", - "no_NO": "Trimming av {0} tittel(er)...", - "pl_PL": "", - "pt_BR": "Reduzindo {0} Título(s)...", - "ru_RU": "Обрезка {0} файла(ов)...", - "sv_SE": "Optimerar {0} spel...", - "th_TH": "กำลังตัดแต่ง {0} รายการ...", - "tr_TR": "", - "uk_UA": "Обрізка {0} тайтл(ів)...", - "zh_CN": "{0} 个游戏瘦身中。。。", - "zh_TW": "正在修剪 {0} 個遊戲..." - } - }, - { - "ID": "XCITrimmerTitleStatusUntrimming", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Untrimming {0} Title(s)...", - "es_ES": "Deshaciendo Recorte de {0} Título(s)...", - "fr_FR": "Dé-Réduction de {0} Fichier(s)...", - "he_IL": "", - "it_IT": "Ripristino alle dimensioni originali di {0} titolo/i...", - "ja_JP": "", - "ko_KR": "{0}개의 타이틀을 트리밍 해제 중...", - "no_NO": "Untrimming {0} Tittel(er)...", - "pl_PL": "", - "pt_BR": "Desfazendo redução {0} Título(s)...", - "ru_RU": "Отмена обрезки {0} файла(ов)...", - "sv_SE": "Avoptimerar {0} spel...", - "th_TH": "กำลังยกเลิกการตัดแต่ง {0} รายการ...", - "tr_TR": "", - "uk_UA": "Необрізаних {0} тайтл(ів)...", - "zh_CN": "正在精简 {0} 个游戏", - "zh_TW": "正在反修剪 {0} 個遊戲..." - } - }, - { - "ID": "XCITrimmerTitleStatusFailed", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Failed", - "es_ES": "Fallido", - "fr_FR": "Échoué", - "he_IL": "", - "it_IT": "Fallito", - "ja_JP": "", - "ko_KR": "실패", - "no_NO": "Mislyktes", - "pl_PL": "", - "pt_BR": "Falhou", - "ru_RU": "Ошибка", - "sv_SE": "Misslyckades", - "th_TH": "ล้มเหลว", - "tr_TR": "", - "uk_UA": "Невдача", - "zh_CN": "失败", - "zh_TW": "失敗" - } - }, - { - "ID": "XCITrimmerPotentialSavings", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Potential Savings", - "es_ES": "Ahorro Potencial", - "fr_FR": "Économies Potentielles", - "he_IL": "", - "it_IT": "Risparmio potenziale", - "ja_JP": "", - "ko_KR": "잠재적 비용 절감", - "no_NO": "Potensielle besparelser", - "pl_PL": "", - "pt_BR": "Economia Potencial", - "ru_RU": "Потенциальная экономия места", - "sv_SE": "Möjlig besparning", - "th_TH": "พื้นที่ประหยัดได้", - "tr_TR": "", - "uk_UA": "Потенційна економія", - "zh_CN": "潜在的储存空间节省", - "zh_TW": "潛在節省的儲存空間" - } - }, - { - "ID": "XCITrimmerActualSavings", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Actual Savings", - "es_ES": "Ahorro Real", - "fr_FR": "Économies Réelles", - "he_IL": "", - "it_IT": "Risparmio effettivo", - "ja_JP": "", - "ko_KR": "실제 비용 절감", - "no_NO": "Faktiske besparelser", - "pl_PL": "", - "pt_BR": "Economia Real", - "ru_RU": "Фактическая экономия места", - "sv_SE": "Faktisk besparning", - "th_TH": "พื้นที่ที่ประหยัดจริง", - "tr_TR": "", - "uk_UA": "Зекономлено", - "zh_CN": "实际的储存空间节省", - "zh_TW": "實際節省的儲存空間" - } - }, - { - "ID": "XCITrimmerSavingsMb", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "{0:n0} Mb", - "es_ES": null, - "fr_FR": "{0:n0} Mo", - "he_IL": "", - "it_IT": "{0:n0} MB", - "ja_JP": "", - "ko_KR": "{0:n0}MB", - "no_NO": "", - "pl_PL": "", - "pt_BR": null, - "ru_RU": "{0:n0} Мб", - "sv_SE": null, - "th_TH": "{0:n0} เมกะไบต์", - "tr_TR": "", - "uk_UA": "{0:n0} Мб", - "zh_CN": null, - "zh_TW": null - } - }, - { - "ID": "XCITrimmerSelectDisplayed", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Select Shown", - "es_ES": "Seleccionar Mostrado(s)", - "fr_FR": "Sélectionner Affiché", - "he_IL": "", - "it_IT": "Seleziona visualizzati", - "ja_JP": "", - "ko_KR": "표시됨 선택", - "no_NO": "Velg vist", - "pl_PL": "", - "pt_BR": "Marcar Todos", - "ru_RU": "Выбрать видимое", - "sv_SE": "Markera visade", - "th_TH": "เลือกรายการที่แสดง", - "tr_TR": "", - "uk_UA": "Вибрати показані", - "zh_CN": "选定显示的", - "zh_TW": "選擇已顯示" - } - }, - { - "ID": "XCITrimmerDeselectDisplayed", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Deselect Shown", - "es_ES": "Deseleccionar Mostrado(s)", - "fr_FR": "Désélectionner Affiché", - "he_IL": "", - "it_IT": "Deseleziona visualizzati", - "ja_JP": "", - "ko_KR": "표시됨 선택 취소", - "no_NO": "Opphev valg av Vist", - "pl_PL": "", - "pt_BR": "Desmarcar Todos", - "ru_RU": "Отменить выбор видимого", - "sv_SE": "Avmarkera visade", - "th_TH": "ยกเลิกการเลือกรายการที่แสดง", - "tr_TR": "", - "uk_UA": "Скасувати вибір показаного", - "zh_CN": "反选显示的", - "zh_TW": "取消選擇已顯示" - } - }, - { - "ID": "XCITrimmerSortName", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Title", - "es_ES": "Título", - "fr_FR": "Titre", - "he_IL": "", - "it_IT": "Titolo", - "ja_JP": "", - "ko_KR": "타이틀", - "no_NO": "Tittel", - "pl_PL": "", - "pt_BR": "Título", - "ru_RU": "Название", - "sv_SE": "Titel", - "th_TH": "ชื่อไฟล์", - "tr_TR": "", - "uk_UA": "Назва", - "zh_CN": "标题", - "zh_TW": "名稱" - } - }, - { - "ID": "XCITrimmerSortSaved", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Space Savings", - "es_ES": "Ahorro de Espacio", - "fr_FR": "Économies de disque dur", - "he_IL": "", - "it_IT": "Spazio risparmiato", - "ja_JP": "", - "ko_KR": "공간 절약", - "no_NO": "Plassbesparelser", - "pl_PL": "", - "pt_BR": "Economia de Espaço", - "ru_RU": "Экономия места на диске", - "sv_SE": "Utrymmesbesparning", - "th_TH": "ลดการใช้พื้นที่", - "tr_TR": "", - "uk_UA": "Економія місця", - "zh_CN": "节省空间", - "zh_TW": "節省的儲存空間" - } - }, - { - "ID": "XCITrimmerTrim", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Trim", - "es_ES": "Recortar", - "fr_FR": "Réduire", - "he_IL": "", - "it_IT": "Riduci dimensioni", - "ja_JP": "", - "ko_KR": "트림", - "no_NO": "", - "pl_PL": "", - "pt_BR": "Reduzir XCI", - "ru_RU": "Обрезать", - "sv_SE": "Optimera", - "th_TH": "ตัดแต่ง", - "tr_TR": "", - "uk_UA": "Обрізка", - "zh_CN": "瘦身", - "zh_TW": "修剪" - } - }, - { - "ID": "XCITrimmerUntrim", - "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", - "en_US": "Untrim", - "es_ES": "Deshacer Recorte", - "fr_FR": "Dé-Réduire", - "he_IL": "", - "it_IT": "Riporta alle dimensioni originali", - "ja_JP": "", - "ko_KR": "언트림", - "no_NO": "Utrim", - "pl_PL": "", - "pt_BR": "Desfazer Redução", - "ru_RU": "Отменить обрезку", - "sv_SE": "Avoptimera", - "th_TH": "ยกเลิกการตัดแต่ง", - "tr_TR": "", - "uk_UA": "Зшивання", - "zh_CN": "取消精简", - "zh_TW": "反修剪" + "uk_UA": "{0} нових оновлень додано", + "zh_CN": "{0} 个更新被添加", + "zh_TW": "已加入 {0} 個遊戲更新" } }, { @@ -18450,31 +17525,6 @@ "zh_TW": "存檔管理員" } }, - { - "ID": "Name", - "Translations": { - "ar_SA": "الاسم", - "de_DE": "", - "el_GR": "Όνομα", - "en_US": "Name", - "es_ES": "Nombre", - "fr_FR": "Nom", - "he_IL": "שם", - "it_IT": "Nome", - "ja_JP": "名称", - "ko_KR": "이름", - "no_NO": "Navn", - "pl_PL": "Nazwa", - "pt_BR": "Nome", - "ru_RU": "Название", - "sv_SE": "Namn", - "th_TH": "ชื่อ", - "tr_TR": "İsim", - "uk_UA": "Назва", - "zh_CN": "名称", - "zh_TW": "名稱" - } - }, { "ID": "Size", "Translations": { @@ -18500,31 +17550,6 @@ "zh_TW": "大小" } }, - { - "ID": "Search", - "Translations": { - "ar_SA": "بحث", - "de_DE": "Suche", - "el_GR": "Αναζήτηση", - "en_US": "Search", - "es_ES": "Buscar", - "fr_FR": "Rechercher", - "he_IL": "חפש", - "it_IT": "Cerca", - "ja_JP": "検索", - "ko_KR": "찾기", - "no_NO": "Søk", - "pl_PL": "Wyszukaj", - "pt_BR": "Buscar", - "ru_RU": "Поиск", - "sv_SE": "Sök", - "th_TH": "ค้นหา", - "tr_TR": "Ara", - "uk_UA": "Пошук", - "zh_CN": "搜索", - "zh_TW": "搜尋" - } - }, { "ID": "UserProfilesRecoverLostAccounts", "Translations": { diff --git a/assets/Locales/StatusBar.json b/assets/Locales/StatusBar.json index 174efe010..d308cc848 100644 --- a/assets/Locales/StatusBar.json +++ b/assets/Locales/StatusBar.json @@ -1,7 +1,32 @@ { "Locales": [ + { + "ID": "TrimmingXCILabel", + "Translations": { + "ar_SA": "جاري تقليم: {0}", + "de_DE": "Schneide: {0}", + "el_GR": "Κόβει το: {0}", + "en_US": "Trimming: {0}", + "es_ES": "Recortando: {0}", + "fr_FR": "Réduction de: {0}", + "he_IL": "חיתוך: {0}", + "it_IT": "Riduzione di: {0}", + "ja_JP": "{0} をトリミング中:", + "ko_KR": "{0} 트리밍:", + "no_NO": "Trimming av: {0}", + "pl_PL": "Przycinanie: {0}", + "pt_BR": "Reduzindo: {0}", + "ru_RU": "Обрезка: {0}", + "sv_SE": "Trimmar: {0}", + "th_TH": "กำลังตัด: {0}", + "tr_TR": "{0} Kısaltılıyor:", + "uk_UA": "Обрізка: {0}", + "zh_CN": "正在修剪: {0}", + "zh_TW": "正在修剪: {0}" + } + }, { - "ID": "FirmwareVersion", + "ID": "FirmwareVersionLabel", "Translations": { "ar_SA": "", "de_DE": "", diff --git a/assets/Locales/XCITrimmer.json b/assets/Locales/XCITrimmer.json new file mode 100644 index 000000000..6ebaf288e --- /dev/null +++ b/assets/Locales/XCITrimmer.json @@ -0,0 +1,429 @@ +{ + "Locales": [ + { + "ID": "StatusCountLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI Selected: {0}/{1}", + "es_ES": "XCI Seleccionados: {0}/{1}", + "fr_FR": "XCI Sélectionnés : {0}/{1}", + "he_IL": "", + "it_IT": "XCI Selezionati: {0}/{1}", + "ja_JP": "", + "ko_KR": "XCI 선택됨: {0}/{1}", + "no_NO": "XCI Valgt: {0}/{1}", + "pl_PL": "XCI Wybrane: {0}/{1}", + "pt_BR": "XCI Selecionados: {0}/{1}", + "ru_RU": "Выбрано XCI: {0}/{1}", + "sv_SE": "XCI Valda: {0}/{1}", + "th_TH": "XCI เลือกแล้ว: {0}/{1}", + "tr_TR": "", + "uk_UA": "Вибрано XCI: {0}/{1}", + "zh_CN": "XCI 已选: {0}/{1}", + "zh_TW": "XCI 已選擇: {0}/{1}" + } + }, + { + "ID": "StatusCountWithFilterLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "XCI Selected: {0}/{1} (Displayed: {2})", + "es_ES": "XCI Seleccionados: {0}/{1} (Mostrados: {2})", + "fr_FR": "XCI Sélectionnés : {0}/{1} (Affichés : {2})", + "he_IL": "", + "it_IT": "XCI Selezionati: {0}/{1} (Visualizzati: {2})", + "ja_JP": "", + "ko_KR": "XCI 선택됨: {0}/{1} (표시됨: {2})", + "no_NO": "XCI Valgt: {0}/{1} (Vises: {2})", + "pl_PL": "XCI Wybrane: {0}/{1} (Wyświetlone: {2})", + "pt_BR": "XCI Selecionados: {0}/{1} (Exibidos: {2})", + "ru_RU": "Выбрано XCI: {0}/{1} (Отображается: {2})", + "sv_SE": "XCI Valda: {0}/{1} (Visas: {2})", + "th_TH": "XCI เลือกแล้ว: {0}/{1} (แสดง: {2})", + "tr_TR": "", + "uk_UA": "Вибрано XCI: {0}/{1} (Відображається: {2})", + "zh_CN": "XCI 已选: {0}/{1}(显示: {2})", + "zh_TW": "XCI 已選擇: {0}/{1}(顯示: {2})" + } + }, + { + "ID": "StatusTrimmingLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Trimming: {0}/{1}...", + "es_ES": "Recortando: {0}/{1}...", + "fr_FR": "Réduction : {0}/{1}...", + "he_IL": "", + "it_IT": "Riduzione: {0}/{1}...", + "ja_JP": "", + "ko_KR": "트리밍: {0}/{1}...", + "no_NO": "Trimmer: {0}/{1}...", + "pl_PL": "", + "pt_BR": "Recortando: {0}/{1}...", + "ru_RU": "Обрезка: {0}/{1}...", + "sv_SE": "Trimmar: {0}/{1}...", + "th_TH": "กำลังตัดแต่ง: {0}/{1}...", + "tr_TR": "", + "uk_UA": "Обрізання: {0}/{1}...", + "zh_CN": "正在修剪:{0}/{1}...", + "zh_TW": "正在修剪:{0}/{1}..." + } + }, + { + "ID": "StatusUntrimmingLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Untrimming {0}...", + "es_ES": "Deshaciendo el recorte {0}...", + "fr_FR": "Restauration de {0}...", + "he_IL": "", + "it_IT": "Ripristino di {0}...", + "ja_JP": "", + "ko_KR": "{0} 복원 중...", + "no_NO": "Gjenoppretter {0}...", + "pl_PL": "", + "pt_BR": "Restaurando {0}...", + "ru_RU": "Восстановление {0}...", + "sv_SE": "Återställer {0}...", + "th_TH": "กำลังกู้คืน {0}...", + "tr_TR": "", + "uk_UA": "Відновлення {0}...", + "zh_CN": "正在恢复 {0}...", + "zh_TW": "正在還原 {0}..." + } + }, + { + "ID": "SelectAllButton", + "Translations": { + "ar_SA": "اختر الكل", + "de_DE": "Alles auswählen", + "el_GR": "Επιλογή όλων", + "en_US": "Select All", + "es_ES": "Seleccionar Todo", + "fr_FR": "Sélectionner Tout", + "he_IL": "בחר הכל", + "it_IT": "Seleziona tutto", + "ja_JP": "すべて選択", + "ko_KR": "모두 선택", + "no_NO": "Velg alle", + "pl_PL": "Zaznacz wszystko", + "pt_BR": "Selecionar tudo", + "ru_RU": "Выбрать все", + "sv_SE": "Markera alla", + "th_TH": "เลือกทั้งหมด", + "tr_TR": "Hepsini seç", + "uk_UA": "Вибрати все", + "zh_CN": "选择全部", + "zh_TW": "選擇全部" + } + }, + { + "ID": "ClearSelectionButton", + "Translations": { + "ar_SA": "مسح التحديد", + "de_DE": "Auswahl aufheben", + "el_GR": "Εκκαθάριση επιλογής", + "en_US": "Clear Selection", + "es_ES": "Borrar selección", + "fr_FR": "Effacer la sélection", + "he_IL": "נקה בחירה", + "it_IT": "Cancella selezione", + "ja_JP": "選択をクリア", + "ko_KR": "선택 해제", + "no_NO": "Fjern utvalg", + "pl_PL": "Wyczyść zaznaczenie", + "pt_BR": "Limpar seleção", + "ru_RU": "Очистить выделение", + "sv_SE": "Rensa markering", + "th_TH": "ล้างการเลือก", + "tr_TR": "Seçimi temizle", + "uk_UA": "Очистити вибір", + "zh_CN": "清除选择", + "zh_TW": "清除選擇" + } + }, + { + "ID": "TrimmedLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Trimmed", + "es_ES": "Recortado", + "fr_FR": "Réduit", + "he_IL": "", + "it_IT": "Dim. ridotta", + "ja_JP": "", + "ko_KR": "트리밍됨", + "no_NO": "Trimmet", + "pl_PL": "", + "pt_BR": "Reduzido", + "ru_RU": "Обрезан", + "sv_SE": "Optimerad", + "th_TH": "ตัดแต่งแล้ว", + "tr_TR": "", + "uk_UA": "Обрізані", + "zh_CN": "经过瘦身的", + "zh_TW": "已修剪" + } + }, + { + "ID": "UntrimmedLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Untrimmed", + "es_ES": "Sin Recortar", + "fr_FR": "Non Réduit", + "he_IL": "", + "it_IT": "Dim. originale", + "ja_JP": "", + "ko_KR": "트리밍되지 않음", + "no_NO": "Ikke trimmet", + "pl_PL": "", + "pt_BR": "Não Reduzido", + "ru_RU": "Не обрезан", + "sv_SE": "Orörd", + "th_TH": "ยังไม่ได้ตัดแต่ง", + "tr_TR": "", + "uk_UA": "Необрізані", + "zh_CN": "没有瘦身的", + "zh_TW": "未修剪" + } + }, + { + "ID": "PartialLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Partial", + "es_ES": "Parcial", + "fr_FR": "Partiel", + "he_IL": "", + "it_IT": "Parziale", + "ja_JP": "", + "ko_KR": "일부", + "no_NO": "Delvis", + "pl_PL": "", + "pt_BR": "Parcial", + "ru_RU": "Частично", + "sv_SE": "Delvis", + "th_TH": "ยังไม่สมบูรณ์", + "tr_TR": "", + "uk_UA": "Часткові", + "zh_CN": "分区", + "zh_TW": "部分" + } + }, + { + "ID": "FailedLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Failed", + "es_ES": "Fallido", + "fr_FR": "Échoué", + "he_IL": "", + "it_IT": "Fallito", + "ja_JP": "", + "ko_KR": "실패", + "no_NO": "Mislyktes", + "pl_PL": "", + "pt_BR": "Falhou", + "ru_RU": "Ошибка", + "sv_SE": "Misslyckades", + "th_TH": "ล้มเหลว", + "tr_TR": "", + "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": "Nieznany", + "pt_BR": "Desconhecido", + "ru_RU": "Неизвестно", + "sv_SE": "Okänd", + "th_TH": "ไม่รู้จัก", + "tr_TR": "Bilinmeyen", + "uk_UA": "Невідомо", + "zh_CN": "未知", + "zh_TW": "未知" + } + }, + { + "ID": "CalculatedSavingsLabel", + "Translations": { + "ar_SA": null, + "de_DE": null, + "el_GR": null, + "en_US": "{0} MB ({1}%)", + "es_ES": null, + "fr_FR": "{0} Mo ({1} %)", + "he_IL": null, + "it_IT": null, + "ja_JP": "{0}MB({1}%)", + "ko_KR": "{0}MB ({1}%)", + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": "{0} МБ ({1}%)", + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": "{0} МБ ({1}%)", + "zh_CN": "{0} MB({1}%)", + "zh_TW": "{0} MB({1}%)" + } + }, + { + "ID": "SavedLabel", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Saved:", + "es_ES": "Ahorrado:", + "fr_FR": "Économies :", + "he_IL": "", + "it_IT": "Risparmiato:", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "Zaoszczędzone:", + "pt_BR": "Economizado:", + "ru_RU": "Сохранено:", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "Збережено:", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "RemainingLabel", + "Translations": { + "ar_SA": "المتبقية:", + "de_DE": "Verbleibend:", + "el_GR": "Απομένουν:", + "en_US": "Remaining:", + "es_ES": "Restante:", + "fr_FR": "Restant :", + "he_IL": "נותרו:", + "it_IT": "Rimanenti:", + "ja_JP": "残り:", + "ko_KR": "남은:", + "no_NO": "Gjenstående:", + "pl_PL": "Pozostało:", + "pt_BR": "Restante:", + "ru_RU": "Осталось:", + "sv_SE": "Kvar:", + "th_TH": "เหลือ:", + "tr_TR": "Kalan:", + "uk_UA": "Залишилося:", + "zh_CN": "剩余:", + "zh_TW": "剩餘:" + } + }, + { + "ID": "MBLabel", + "Translations": { + "ar_SA": null, + "de_DE": null, + "el_GR": null, + "en_US": "{0} MB", + "es_ES": null, + "fr_FR": "{0} Mo", + "he_IL": null, + "it_IT": null, + "ja_JP": "{0}MB", + "ko_KR": "{0}MB", + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": "{0} МБ", + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": "{0} МБ", + "zh_CN": null, + "zh_TW": null + } + }, + { + "ID": "TrimButton", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Trim", + "es_ES": "Recortar", + "fr_FR": "Réduire", + "he_IL": "", + "it_IT": "Riduci", + "ja_JP": "", + "ko_KR": "트림", + "no_NO": "", + "pl_PL": "Przytnij", + "pt_BR": "Reduzir", + "ru_RU": "Обрезать", + "sv_SE": "Trimma", + "th_TH": "ตัด", + "tr_TR": "Kırp", + "uk_UA": "Обрізати", + "zh_CN": "瘦身", + "zh_TW": "修剪" + } + }, + { + "ID": "UntrimButton", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Untrim", + "es_ES": "Desrecortar", + "fr_FR": "Dé-Réduire", + "he_IL": "", + "it_IT": "Ripristina", + "ja_JP": "", + "ko_KR": "언트림", + "no_NO": "Utrim", + "pl_PL": "", + "pt_BR": "Restaurar", + "ru_RU": "Восстановить", + "sv_SE": "Avoptimera", + "th_TH": "กู้คืน", + "tr_TR": "", + "uk_UA": "Відновити", + "zh_CN": "取消精简", + "zh_TW": "反修剪" + } + } + ] +} diff --git a/src/Ryujinx/Common/Models/XCITrimmerFileModel.cs b/src/Ryujinx/Common/Models/XCITrimmerFileModel.cs index 233ac2b6d..3362d063c 100644 --- a/src/Ryujinx/Common/Models/XCITrimmerFileModel.cs +++ b/src/Ryujinx/Common/Models/XCITrimmerFileModel.cs @@ -1,3 +1,4 @@ +using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; @@ -11,6 +12,7 @@ namespace Ryujinx.Ava.Common.Models bool Untrimmable, long PotentialSavingsB, long CurrentSavingsB, + long OriginalSizeB, int? PercentageProgress, XCIFileTrimmer.OperationOutcome ProcessingOutcome) { @@ -25,31 +27,57 @@ namespace Ryujinx.Ava.Common.Models trimmer.CanBeUntrimmed, trimmer.DiskSpaceSavingsB, trimmer.DiskSpaceSavedB, + applicationData.FileSize, null, XCIFileTrimmer.OperationOutcome.Undetermined ); } - public bool IsFailed + public bool IsFailed => + ProcessingOutcome is not XCIFileTrimmer.OperationOutcome.Undetermined + and not XCIFileTrimmer.OperationOutcome.Successful; + + public string StatusText { get { - return ProcessingOutcome is not XCIFileTrimmer.OperationOutcome.Undetermined and - not XCIFileTrimmer.OperationOutcome.Successful; + if (IsFailed) + return LocaleManager.Instance[LocaleKeys.XCITrimmer_FailedLabel]; + + return ProcessingOutcome switch + { + XCIFileTrimmer.OperationOutcome.Successful => + CurrentSavingsB > 0 + ? LocaleManager.Instance[LocaleKeys.XCITrimmer_UntrimmedLabel] + : LocaleManager.Instance[LocaleKeys.XCITrimmer_TrimmedLabel], + + XCIFileTrimmer.OperationOutcome.Undetermined => + Trimmable && Untrimmable + ? LocaleManager.Instance[LocaleKeys.XCITrimmer_PartialLabel] + + : Trimmable + ? LocaleManager.Instance[LocaleKeys.XCITrimmer_UntrimmedLabel] + + : Untrimmable + ? LocaleManager.Instance[LocaleKeys.XCITrimmer_TrimmedLabel] + + : LocaleManager.Instance[LocaleKeys.XCITrimmer_UnknownLabel], + + _ => LocaleManager.Instance[LocaleKeys.XCITrimmer_UnknownLabel] + }; } } + public bool HasStatusDetail => + ProcessingOutcome != XCIFileTrimmer.OperationOutcome.Undetermined; + public virtual bool Equals(XCITrimmerFileModel obj) { - if (obj == null) + if (obj is null) return false; - return this.Path == obj.Path; - } - - public override int GetHashCode() - { - return this.Path.GetHashCode(); + return Path == obj.Path; } + public override int GetHashCode() => Path.GetHashCode(); } -} +} \ No newline at end of file diff --git a/src/Ryujinx/Common/XCITrimmerLog.cs b/src/Ryujinx/Common/XCITrimmerLog.cs index 3f840abba..6039ef9f9 100644 --- a/src/Ryujinx/Common/XCITrimmerLog.cs +++ b/src/Ryujinx/Common/XCITrimmerLog.cs @@ -26,9 +26,9 @@ namespace Ryujinx.Ava.Common internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog { - private readonly XciTrimmerViewModel _viewModel; + private readonly XCITrimmerViewModel _viewModel; - public TrimmerWindow(XciTrimmerViewModel viewModel) + public TrimmerWindow(XCITrimmerViewModel viewModel) { _viewModel = viewModel; } diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml index 9f2999a4c..e8d028f5d 100755 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml @@ -103,10 +103,10 @@ + IsVisible="{Binding IsXCIFile}" + Icon="{ext:Icon fa-solid fa-scissors}" /> 0) + { + mbValue = (currentSavings / _bytesPerMB).CoerceAtLeast(0); + percentage = (currentSavings / (double)originalSize) * 100; + } + else if (potentialSavings > 0) + { + mbValue = (potentialSavings / _bytesPerMB).CoerceAtLeast(0); + percentage = (potentialSavings / (double)originalSize) * 100; + } + + return GetFormattedString(app, mbValue, percentage); + } + + private string GetFormattedString(XCITrimmerFileModel app, long mb, double percentage) + { + // Round percentage to 1 decimal place + double roundedPercentage = Math.Round(percentage, 1); + if (app.CurrentSavingsB < app.PotentialSavingsB) { - return LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleXCICanSaveLabel, ((app.PotentialSavingsB - app.CurrentSavingsB) / _bytesPerMB).CoerceAtLeast(0)); + return LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.XCITrimmer_CalculatedSavingsLabel, mb, roundedPercentage); } else { - return LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleXCISavingLabel, (app.CurrentSavingsB / _bytesPerMB).CoerceAtLeast(0)); + return LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.XCITrimmer_CalculatedSavingsLabel, mb, roundedPercentage); } } diff --git a/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusConverter.cs b/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusConverter.cs index 9a0e9fcbf..f9aec086a 100644 --- a/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusConverter.cs +++ b/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusConverter.cs @@ -1,7 +1,7 @@ using Avalonia; using Avalonia.Data; using Avalonia.Data.Converters; -using Ryujinx.Ava.Common.Locale; +using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Models; using System; using System.Globalization; @@ -16,26 +16,30 @@ namespace Ryujinx.Ava.UI.Helpers public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is UnsetValueType) - { return BindingOperations.DoNothing; - } - - if (!targetType.IsAssignableFrom(typeof(string))) - { - return null; - } if (value is not XCITrimmerFileModel app) - { - return null; - } + return default(Symbol); + + bool isProcessing = app.PercentageProgress != null; + + if (isProcessing) + return Symbol.Sync; - return app.PercentageProgress != null ? String.Empty : - app.ProcessingOutcome is not OperationOutcome.Successful and not OperationOutcome.Undetermined ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusFailedLabel] : - app.Trimmable & app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusPartialLabel] : - app.Trimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusTrimmableLabel] : - app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusUntrimmableLabel] : - String.Empty; + if (app.ProcessingOutcome is not OperationOutcome.Successful + and not OperationOutcome.Undetermined) + return Symbol.ImportantFilled; + + if (app.Trimmable && app.Untrimmable) + return Symbol.Repair; + + if (app.Trimmable) + return Symbol.Clear; + + if (app.Untrimmable) + return Symbol.Checkmark; + + return Symbol.Help; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/src/Ryujinx/UI/Helpers/XCITrimmerOperationOutcomeHelper.cs b/src/Ryujinx/UI/Helpers/XCITrimmerOperationOutcomeHelper.cs index d58056469..7a95b4ce8 100644 --- a/src/Ryujinx/UI/Helpers/XCITrimmerOperationOutcomeHelper.cs +++ b/src/Ryujinx/UI/Helpers/XCITrimmerOperationOutcomeHelper.cs @@ -9,17 +9,15 @@ namespace Ryujinx.Ava.UI.Helpers { public string LocalizedText => opOutcome switch { - OperationOutcome.NoTrimNecessary => LocaleManager.Instance[LocaleKeys.TrimXCIFileNoTrimNecessary], - OperationOutcome.NoUntrimPossible => LocaleManager.Instance[LocaleKeys.TrimXCIFileNoUntrimPossible], - OperationOutcome.ReadOnlyFileCannotFix => LocaleManager.Instance[ - LocaleKeys.TrimXCIFileReadOnlyFileCannotFix], - OperationOutcome.FreeSpaceCheckFailed => LocaleManager.Instance[ - LocaleKeys.TrimXCIFileFreeSpaceCheckFailed], - OperationOutcome.InvalidXCIFile => LocaleManager.Instance[LocaleKeys.TrimXCIFileInvalidXCIFile], - OperationOutcome.FileIOWriteError => LocaleManager.Instance[LocaleKeys.TrimXCIFileFileIOWriteError], - OperationOutcome.FileSizeChanged => LocaleManager.Instance[LocaleKeys.TrimXCIFileFileSizeChanged], - OperationOutcome.Cancelled => LocaleManager.Instance[LocaleKeys.TrimXCIFileCancelled], - OperationOutcome.Undetermined => LocaleManager.Instance[LocaleKeys.TrimXCIFileFileUndertermined], + OperationOutcome.NoTrimNecessary => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_NoTrimNecessaryMessage], + OperationOutcome.NoUntrimPossible => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_NoUntrimPossibleMessage], + OperationOutcome.ReadOnlyFileCannotFix => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_ReadOnlyFileCannotFixMessage], + OperationOutcome.FreeSpaceCheckFailed => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_FreeSpaceCheckFailedMessage], + OperationOutcome.InvalidXCIFile => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_InvalidDataMessage], + OperationOutcome.FileIOWriteError => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_WriteErrorMessage], + OperationOutcome.FileSizeChanged => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_SizeChangedMessage], + OperationOutcome.Cancelled => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_TrimCancelledMessage], + OperationOutcome.Undetermined => LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_NoOperationPerformedMessage], _ => null }; } diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 8d3824e86..66cb28fab 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -496,6 +496,8 @@ namespace Ryujinx.Ava.UI.ViewModels public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo; + public bool IsXCIFile => Path.GetExtension(SelectedApplication.Path)?.ToLower() == ".xci"; + public bool HasDlc => ApplicationLibrary.HasDlcs(SelectedApplication.Id); public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder && @@ -790,7 +792,7 @@ namespace Ryujinx.Ava.UI.ViewModels { ApplicationSort.Favorite => LocaleManager.Instance[LocaleKeys.CommonFavorite], ApplicationSort.TitleId => LocaleManager.Instance[LocaleKeys.DlcManagerTableHeadingTitleIdLabel], - ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication], + ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.Common_Sort_NameLabel], ApplicationSort.Developer => LocaleManager.Instance[LocaleKeys.GameListSortDeveloper], ApplicationSort.LastPlayed => LocaleManager.Instance[LocaleKeys.GameListSortLastPlayed], ApplicationSort.TotalTimePlayed => LocaleManager.Instance[LocaleKeys.GameListSortTimePlayed], @@ -1935,13 +1937,13 @@ namespace Ryujinx.Ava.UI.ViewModels if (version != null) { - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBar_FirmwareVersion, version.VersionString); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBar_FirmwareVersionLabel, version.VersionString); hasApplet = version.Major > 3; } else { - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBar_FirmwareVersion, "NaN"); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBar_FirmwareVersionLabel, "NaN"); } IsAppletMenuActive = hasApplet; @@ -2317,7 +2319,7 @@ namespace Ryujinx.Ava.UI.ViewModels if (notifyUser != null) { await ContentDialogHelper.CreateWarningDialog( - LocaleManager.Instance[LocaleKeys.TrimXCIFileFailedPrimaryText], + LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_TrimFailedMessage], notifyUser ); } @@ -2343,18 +2345,18 @@ namespace Ryujinx.Ava.UI.ViewModels if (trimmer.CanBeTrimmed) { - double savings = (double)trimmer.DiskSpaceSavingsB / 1024.0 / 1024.0; - double currentFileSize = (double)trimmer.FileSizeB / 1024.0 / 1024.0; - double cartDataSize = (double)trimmer.DataSizeB / 1024.0 / 1024.0; + int savings = (int)Math.Round((double)trimmer.DiskSpaceSavingsB / 1024.0 / 1024.0); + int currentFileSize = (int)Math.Round((double)trimmer.FileSizeB / 1024.0 / 1024.0); + int cartDataSize = (int)Math.Round((double)trimmer.DataSizeB / 1024.0 / 1024.0); string secondaryText = LocaleManager.Instance.UpdateAndGetDynamicValue( - LocaleKeys.TrimXCIFileDialogSecondaryText, currentFileSize, cartDataSize, savings); + LocaleKeys.Dialog_XCITrimmer_SecondaryMessage, currentFileSize.ToString("0"), cartDataSize.ToString("0"), savings.ToString("0")); UserResult result = await ContentDialogHelper.CreateConfirmationDialog( - LocaleManager.Instance[LocaleKeys.TrimXCIFileDialogPrimaryText], + LocaleManager.Instance[LocaleKeys.Dialog_XCITrimmer_PrimaryMessage], secondaryText, LocaleManager.Instance[LocaleKeys.Continue], LocaleManager.Instance[LocaleKeys.Cancel], - LocaleManager.Instance[LocaleKeys.GameListContextMenuTrimXCI] + LocaleManager.Instance[LocaleKeys.GameListContextMenu_TrimXCIButton] ); if (result == UserResult.Yes) @@ -2364,8 +2366,8 @@ namespace Ryujinx.Ava.UI.ViewModels Dispatcher.UIThread.Post(() => { StatusBarProgressStatusText = - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarXCIFileTrimming, - Path.GetFileName(filename)); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBar_TrimmingXCILabel, + Path.GetFileNameWithoutExtension(filename)); StatusBarProgressStatusVisible = true; StatusBarProgressMaximum = 1; StatusBarProgressValue = 0; diff --git a/src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs b/src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs similarity index 78% rename from src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs rename to src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs index 1281cc834..187dff624 100644 --- a/src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs @@ -16,7 +16,7 @@ using static Ryujinx.Common.Utilities.XCIFileTrimmer; namespace Ryujinx.Ava.UI.ViewModels { - public class XciTrimmerViewModel : BaseModel + public class XCITrimmerViewModel : BaseModel { private const long BytesPerMb = 1024 * 1024; @@ -29,11 +29,11 @@ namespace Ryujinx.Ava.UI.ViewModels public enum SortField { Name, - Saved + Savings, + Status } - private const string _FileExtXCI = "XCI"; - + private const string _fileExtXCI = "XCI"; private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger; private ApplicationLibrary ApplicationLibrary => _mainWindowViewModel.ApplicationLibrary; private Optional _processingApplication = null; @@ -45,8 +45,11 @@ namespace Ryujinx.Ava.UI.ViewModels private string _search; private ProcessingMode _processingMode; private SortField _sortField = SortField.Name; + private int _processingCurrent; + private int _processingTotal; + - public XciTrimmerViewModel(MainWindowViewModel mainWindowViewModel) + public XCITrimmerViewModel(MainWindowViewModel mainWindowViewModel) { _logger = new XCITrimmerLog.TrimmerWindow(this); _mainWindowViewModel = mainWindowViewModel; @@ -56,7 +59,7 @@ namespace Ryujinx.Ava.UI.ViewModels private void LoadXCIApplications() { IEnumerable apps = ApplicationLibrary.Applications.Items - .Where(app => app.FileExtension == _FileExtXCI); + .Where(app => app.FileExtension == _fileExtXCI); foreach (ApplicationData xciApp in apps) AddOrUpdateXCITrimmerFile(CreateXCITrimmerFile(xciApp.Path)); @@ -64,11 +67,9 @@ namespace Ryujinx.Ava.UI.ViewModels ApplicationsChanged(); } - private XCITrimmerFileModel CreateXCITrimmerFile( - string path, - OperationOutcome operationOutcome = OperationOutcome.Undetermined) + private XCITrimmerFileModel CreateXCITrimmerFile(string path, OperationOutcome operationOutcome = OperationOutcome.Undetermined) { - ApplicationData xciApp = ApplicationLibrary.Applications.Items.First(app => app.FileExtension == _FileExtXCI && app.Path == path); + ApplicationData xciApp = ApplicationLibrary.Applications.Items.First(app => app.FileExtension == _fileExtXCI && app.Path == path); return XCITrimmerFileModel.FromApplicationData(xciApp, _logger) with { ProcessingOutcome = operationOutcome }; } @@ -90,11 +91,15 @@ namespace Ryujinx.Ava.UI.ViewModels SortAndFilter(); } + public bool AnySelected => + _selectedXCIFiles.Count > 0; + private void SortingChanged() { OnPropertiesChanged( nameof(IsSortedByName), - nameof(IsSortedBySaved), + nameof(IsSortedBySavings), + nameof(IsSortedByStatus), nameof(SortingAscending), nameof(SortingField), nameof(SortingFieldName)); @@ -114,6 +119,7 @@ namespace Ryujinx.Ava.UI.ViewModels nameof(Status), nameof(PotentialSavings), nameof(ActualSavings), + nameof(SavingsDifference), nameof(CanTrim), nameof(CanUntrim)); @@ -123,16 +129,30 @@ namespace Ryujinx.Ava.UI.ViewModels private void SelectionChanged(bool displayedChanged = true) { - OnPropertiesChanged( - nameof(Status), - nameof(CanTrim), - nameof(CanUntrim), - nameof(SelectedXCIFiles)); + OnPropertyChanged(nameof(Status)); + OnPropertyChanged(nameof(CanTrim)); + OnPropertyChanged(nameof(CanUntrim)); + OnPropertyChanged(nameof(SelectedXCIFiles)); + OnPropertyChanged(nameof(AnySelected)); + OnPropertyChanged(nameof(SelectToggleText)); if (displayedChanged) OnPropertyChanged(nameof(SelectedDisplayedXCIFiles)); } + public void ToggleSelect() + { + if (AnySelected) + DeselectAll(); + else + SelectAll(); + } + + public string SelectToggleText => + AnySelected + ? LocaleManager.Instance[LocaleKeys.XCITrimmer_ClearSelectionButton] + : LocaleManager.Instance[LocaleKeys.XCITrimmer_SelectAllButton]; + private void ProcessingChanged() { OnPropertiesChanged( @@ -167,6 +187,14 @@ namespace Ryujinx.Ava.UI.ViewModels (processingMode == ProcessingMode.Trimming && xci.Trimmable) )).ToList(); + _processingTotal = toProcess.Count; + _processingCurrent = 0; + + Dispatcher.UIThread.Post(() => + { + OnPropertyChanged(nameof(Status)); + }); + List viewsSaved = DisplayedXCIFiles.ToList(); Dispatcher.UIThread.Post(() => @@ -219,6 +247,12 @@ namespace Ryujinx.Ava.UI.ViewModels ProcessingApplication = null; }); } + _processingCurrent++; + + Dispatcher.UIThread.Post(() => + { + OnPropertyChanged(nameof(Status)); + }); } } finally @@ -226,9 +260,20 @@ namespace Ryujinx.Ava.UI.ViewModels Dispatcher.UIThread.Post(() => { _displayedXCIFiles.AddOrReplaceMatching(_allXCIFiles, viewsSaved); - _selectedXCIFiles.AddOrReplaceMatching(_allXCIFiles, toProcess); + Processing = false; ApplicationsChanged(); + + _selectedXCIFiles.Clear(); + + foreach (var processed in toProcess) + { + var updated = _allXCIFiles.FirstOrDefault(x => x.Path == processed.Path); + if (updated != null) + _selectedXCIFiles.Add(updated); + } + + SelectionChanged(); }); } }) @@ -254,9 +299,9 @@ namespace Ryujinx.Ava.UI.ViewModels private class CompareXCITrimmerFiles : IComparer { - private readonly XciTrimmerViewModel _viewModel; + private readonly XCITrimmerViewModel _viewModel; - public CompareXCITrimmerFiles(XciTrimmerViewModel ViewModel) + public CompareXCITrimmerFiles(XCITrimmerViewModel ViewModel) { _viewModel = ViewModel; } @@ -270,9 +315,13 @@ namespace Ryujinx.Ava.UI.ViewModels case SortField.Name: result = x.Name.CompareTo(y.Name); break; - case SortField.Saved: + case SortField.Savings: result = x.PotentialSavingsB.CompareTo(y.PotentialSavingsB); break; + case SortField.Status: + + result = x.CurrentSavingsB.CompareTo(y.CurrentSavingsB); + break; } if (!_viewModel.SortingAscending) @@ -312,15 +361,16 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public void SelectDisplayed() + public void SelectAll() { + SelectedXCIFiles.Clear(); SelectedXCIFiles.AddRange(DisplayedXCIFiles); SelectionChanged(); } - public void DeselectDisplayed() + public void DeselectAll() { - SelectedXCIFiles.RemoveMany(DisplayedXCIFiles); + SelectedXCIFiles.Clear(); SelectionChanged(); } @@ -426,16 +476,23 @@ namespace Ryujinx.Ava.UI.ViewModels { return _processingMode switch { - ProcessingMode.Trimming => string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerTitleStatusTrimming], DisplayedXCIFiles.Count), - ProcessingMode.Untrimming => string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerTitleStatusUntrimming], DisplayedXCIFiles.Count), + ProcessingMode.Trimming => string.Format( + LocaleManager.Instance[LocaleKeys.XCITrimmer_StatusTrimmingLabel], + _processingCurrent, + _processingTotal), + + ProcessingMode.Untrimming => string.Format( + LocaleManager.Instance[LocaleKeys.XCITrimmer_StatusUntrimmingLabel], + _processingCurrent, + _processingTotal), _ => string.Empty }; } else { return string.IsNullOrEmpty(Search) ? - string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerTitleStatusCount], SelectedXCIFiles.Count, AllXCIFiles.Count) : - string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerTitleStatusCountWithFilter], SelectedXCIFiles.Count, AllXCIFiles.Count, DisplayedXCIFiles.Count); + string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmer_StatusCountLabel], SelectedXCIFiles.Count, AllXCIFiles.Count) : + string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmer_StatusCountWithFilterLabel], SelectedXCIFiles.Count, AllXCIFiles.Count, DisplayedXCIFiles.Count); } } } @@ -466,8 +523,9 @@ namespace Ryujinx.Ava.UI.ViewModels { return SortingField switch { - SortField.Name => LocaleManager.Instance[LocaleKeys.XCITrimmerSortName], - SortField.Saved => LocaleManager.Instance[LocaleKeys.XCITrimmerSortSaved], + SortField.Name => LocaleManager.Instance[LocaleKeys.Common_Sort_NameLabel], + SortField.Savings => LocaleManager.Instance[LocaleKeys.Common_Sort_SavingsLabel], + SortField.Status => LocaleManager.Instance[LocaleKeys.Common_Sort_TrimStatusLabel], _ => string.Empty, }; } @@ -488,11 +546,13 @@ namespace Ryujinx.Ava.UI.ViewModels get => _sortField == SortField.Name; } - public bool IsSortedBySaved + public bool IsSortedBySavings { - get => _sortField == SortField.Saved; + get => _sortField == SortField.Savings; } + public bool IsSortedByStatus => _sortField == SortField.Status; + public AvaloniaList SelectedXCIFiles { get => _selectedXCIFiles; @@ -517,7 +577,7 @@ namespace Ryujinx.Ava.UI.ViewModels { get { - return string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerSavingsMb], AllXCIFiles.Sum(xci => xci.PotentialSavingsB / BytesPerMb)); + return string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmer_MBLabel], AllXCIFiles.Sum(xci => xci.PotentialSavingsB / BytesPerMb)); } } @@ -525,7 +585,19 @@ namespace Ryujinx.Ava.UI.ViewModels { get { - return string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmerSavingsMb], AllXCIFiles.Sum(xci => xci.CurrentSavingsB / BytesPerMb)); + return string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmer_MBLabel], AllXCIFiles.Sum(xci => xci.CurrentSavingsB / BytesPerMb)); + } + } + + public string SavingsDifference + { + get + { + long potentialSavings = AllXCIFiles.Sum(xci => xci.PotentialSavingsB); + long actualSavings = AllXCIFiles.Sum(xci => xci.CurrentSavingsB); + long differenceMb = (potentialSavings - actualSavings) / BytesPerMb; + + return string.Format(LocaleManager.Instance[LocaleKeys.XCITrimmer_MBLabel], differenceMb); } } diff --git a/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml b/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml index 8b97a4822..05d4f47d6 100644 --- a/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml +++ b/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml @@ -63,7 +63,7 @@ MinHeight="29" MaxHeight="29" HorizontalAlignment="Stretch" - Watermark="{ext:Locale Search}" + Watermark="{ext:Locale Common_Search_SearchWatermark}" Text="{Binding Search}" /> diff --git a/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml index ee913b56d..4c17721a1 100644 --- a/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml +++ b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml @@ -46,7 +46,7 @@ MinHeight="27" MaxHeight="27" HorizontalAlignment="Stretch" - Watermark="{ext:Locale Search}" + Watermark="{ext:Locale Common_Search_SearchWatermark}" Text="{Binding Search}" /> diff --git a/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml b/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml new file mode 100644 index 000000000..54a485b19 --- /dev/null +++ b/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml.cs b/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml.cs similarity index 82% rename from src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml.cs rename to src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml.cs index 8fb8c151c..1e003aeec 100644 --- a/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/XCITrimmerView.axaml.cs @@ -11,13 +11,19 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.UI.Views.Dialog { - public partial class XciTrimmerView : RyujinxControl + public partial class XCITrimmerView : RyujinxControl { - public XciTrimmerView() + public XCITrimmerView() { InitializeComponent(); } + private void ToggleSelect(object sender, RoutedEventArgs e) + { + if (DataContext is XCITrimmerViewModel vm) + vm.ToggleSelect(); + } + public static async Task Show() { ContentDialog contentDialog = new() @@ -25,11 +31,11 @@ namespace Ryujinx.Ava.UI.Views.Dialog PrimaryButtonText = string.Empty, SecondaryButtonText = string.Empty, CloseButtonText = string.Empty, - Content = new XciTrimmerView + Content = new XCITrimmerView { - ViewModel = new XciTrimmerViewModel(RyujinxApp.MainWindow.ViewModel) + ViewModel = new XCITrimmerViewModel(RyujinxApp.MainWindow.ViewModel) }, - Title = LocaleManager.Instance[LocaleKeys.XCITrimmerWindowTitle] + Title = LocaleManager.Instance[LocaleKeys.MenuBar_Actions_XCITrimmerButton] }; Style bottomBorder = new(x => x.OfType().Name("DialogSpace").Child().OfType()); @@ -63,7 +69,7 @@ namespace Ryujinx.Ava.UI.Views.Dialog public void Sort_Checked(object sender, RoutedEventArgs args) { if (sender is RadioButton { Tag: string sortField }) - ViewModel.SortingField = Enum.Parse(sortField); + ViewModel.SortingField = Enum.Parse(sortField); } public void Order_Checked(object sender, RoutedEventArgs args) diff --git a/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml b/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml deleted file mode 100644 index 4bddcd16a..000000000 --- a/src/Ryujinx/UI/Views/Dialog/XciTrimmerView.axaml +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index 0237f140d..3b69a1a7a 100755 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -163,7 +163,7 @@ IsEnabled="{Binding HasSkylander}" /> @@ -216,7 +216,7 @@ - + diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs index 013d991d6..5ad7b6bd2 100644 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs @@ -43,7 +43,7 @@ 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()); - XciTrimmerMenuItem.Command = Commands.Create(XciTrimmerView.Show); + XCITrimmerMenuItem.Command = Commands.Create(XCITrimmerView.Show); AboutWindowMenuItem.Command = Commands.Create(AboutView.Show); CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityListWindow.Show()); LdnGameListMenuItem.Command = Commands.Create(() => LdnGamesListWindow.Show()); diff --git a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml index 3138f9c1e..33c69dab3 100644 --- a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml @@ -50,33 +50,37 @@ VerticalAlignment="Center" IsVisible="{Binding EnableNonGameRunningControls}" Text="{ext:Locale StatusBarGamesLoaded}" /> - - - + + + + + + Text="{ext:Locale StatusBar_FirmwareVersionLabel}" /> diff --git a/src/Ryujinx/UI/Views/Main/MainViewControls.axaml b/src/Ryujinx/UI/Views/Main/MainViewControls.axaml index 55d23ba41..1937f8dff 100644 --- a/src/Ryujinx/UI/Views/Main/MainViewControls.axaml +++ b/src/Ryujinx/UI/Views/Main/MainViewControls.axaml @@ -95,7 +95,7 @@ Tag="Favorite" /> @@ -153,13 +153,13 @@ diff --git a/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml b/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml index 80fb442e5..72f3c72de 100644 --- a/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml +++ b/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml @@ -33,7 +33,7 @@ HorizontalContentAlignment="Left" MinWidth="100"> + Content="{ext:Locale Common_Sort_NameLabel}" /> @@ -46,9 +46,9 @@ HorizontalContentAlignment="Left" MinWidth="150"> + Content="{ext:Locale Common_Sort_OrderAscending}" /> + Content="{ext:Locale Common_Sort_OrderDescending}" />