From 8474d52778d6bc45146b59a1fc921e6702f4b96a Mon Sep 17 00:00:00 2001 From: Ac_K Date: Sat, 21 Jan 2023 02:06:19 +0100 Subject: [PATCH] Ava UI: Fix `string.Format` issues in Locale (#4305) * Ava UI: Fix `string.Format` issues in Locale * LoacLanguage everytime now * Apply suggestions from code review Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * fix UpdateAndGetDynamicValue Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> --- Ryujinx.Ava/AppHost.cs | 9 +- Ryujinx.Ava/Assets/Locales/de_DE.json | 2 +- Ryujinx.Ava/Assets/Locales/el_GR.json | 2 +- Ryujinx.Ava/Assets/Locales/en_US.json | 2 +- Ryujinx.Ava/Assets/Locales/es_ES.json | 2 +- Ryujinx.Ava/Assets/Locales/fr_FR.json | 2 +- Ryujinx.Ava/Assets/Locales/it_IT.json | 2 +- Ryujinx.Ava/Assets/Locales/ja_JP.json | 2 +- Ryujinx.Ava/Assets/Locales/ko_KR.json | 2 +- Ryujinx.Ava/Assets/Locales/pl_PL.json | 2 +- Ryujinx.Ava/Assets/Locales/pt_BR.json | 2 +- Ryujinx.Ava/Assets/Locales/ru_RU.json | 2 +- Ryujinx.Ava/Assets/Locales/tr_TR.json | 2 +- Ryujinx.Ava/Assets/Locales/uk_UA.json | 2 +- Ryujinx.Ava/Assets/Locales/zh_CN.json | 2 +- Ryujinx.Ava/Assets/Locales/zh_TW.json | 2 +- Ryujinx.Ava/Common/ApplicationHelper.cs | 7 +- Ryujinx.Ava/Common/Locale/LocaleExtension.cs | 2 +- Ryujinx.Ava/Common/Locale/LocaleManager.cs | 84 +++++++++++++------ Ryujinx.Ava/Modules/Updater/Updater.cs | 2 +- Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs | 25 +++--- .../UI/Applet/SwkbdAppletDialog.axaml.cs | 6 +- Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs | 4 +- Ryujinx.Ava/UI/Models/TitleUpdateModel.cs | 2 +- .../UI/ViewModels/AboutWindowViewModel.cs | 5 +- .../ViewModels/ControllerSettingsViewModel.cs | 4 +- .../UI/ViewModels/MainWindowViewModel.cs | 56 ++++++++----- .../UI/ViewModels/TitleUpdateViewModel.cs | 2 +- .../UI/ViewModels/UserSaveManagerViewModel.cs | 3 +- Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs | 2 +- .../DownloadableContentManagerWindow.axaml.cs | 4 +- Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs | 4 +- .../UI/Windows/TitleUpdateWindow.axaml.cs | 2 +- 33 files changed, 144 insertions(+), 109 deletions(-) diff --git a/Ryujinx.Ava/AppHost.cs b/Ryujinx.Ava/AppHost.cs index 067be5c01..fdeee2cc8 100644 --- a/Ryujinx.Ava/AppHost.cs +++ b/Ryujinx.Ava/AppHost.cs @@ -462,8 +462,7 @@ namespace Ryujinx.Ava { UserResult result = await ContentDialogHelper.CreateConfirmationDialog( LocaleManager.Instance[LocaleKeys.DialogFirmwareNoFirmwareInstalledMessage], - string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallEmbeddedMessage], - firmwareVersion.VersionString), + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallEmbeddedMessage, firmwareVersion.VersionString), LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance[LocaleKeys.InputDialogNo], ""); @@ -493,10 +492,8 @@ namespace Ryujinx.Ava _viewModel.RefreshFirmwareStatus(); await ContentDialogHelper.CreateInfoDialog( - string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstalledMessage], - firmwareVersion.VersionString), - string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallEmbeddedSuccessMessage], - firmwareVersion.VersionString), + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstalledMessage, firmwareVersion.VersionString), + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallEmbeddedSuccessMessage, firmwareVersion.VersionString), LocaleManager.Instance[LocaleKeys.InputDialogOk], "", LocaleManager.Instance[LocaleKeys.RyujinxInfo]); diff --git a/Ryujinx.Ava/Assets/Locales/de_DE.json b/Ryujinx.Ava/Assets/Locales/de_DE.json index 4d656bc99..8bf00d7ed 100644 --- a/Ryujinx.Ava/Assets/Locales/de_DE.json +++ b/Ryujinx.Ava/Assets/Locales/de_DE.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Möchtest du das ausgewählte Profil löschen?", "DialogControllerSettingsModifiedConfirmMessage": "Die aktuellen Controller-Einstellungen wurden aktualisiert.", "DialogControllerSettingsModifiedConfirmSubMessage": "Controller-Einstellungen speichern?", - "DialogDlcLoadNcaErrorMessage": "{0}. Fehlerhafte Datei: {1}", + "DialogLoadNcaErrorMessage": "{0}. Fehlerhafte Datei: {1}", "DialogDlcNoDlcErrorMessage": "Die angegebene Datei enthält keinen DLC für den ausgewählten Titel!", "DialogPerformanceCheckLoggingEnabledMessage": "Es wurde die Debug Protokollierung aktiviert", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Um eine optimale Leistung zu erzielen, wird empfohlen, die Debug Protokollierung zu deaktivieren. Debug Protokollierung jetzt deaktivieren?", diff --git a/Ryujinx.Ava/Assets/Locales/el_GR.json b/Ryujinx.Ava/Assets/Locales/el_GR.json index ca3be8b9a..de8897368 100644 --- a/Ryujinx.Ava/Assets/Locales/el_GR.json +++ b/Ryujinx.Ava/Assets/Locales/el_GR.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Θέλετε να διαγράψετε το επιλεγμένο προφίλ", "DialogControllerSettingsModifiedConfirmMessage": "Οι τρέχουσες ρυθμίσεις χειρισμού έχουν ενημερωθεί.", "DialogControllerSettingsModifiedConfirmSubMessage": "Θέλετε να αποθηκεύσετε;", - "DialogDlcLoadNcaErrorMessage": "{0}. Σφάλμα Αρχείου: {1}", + "DialogLoadNcaErrorMessage": "{0}. Σφάλμα Αρχείου: {1}", "DialogDlcNoDlcErrorMessage": "Το αρχείο δεν περιέχει DLC για τον επιλεγμένο τίτλο!", "DialogPerformanceCheckLoggingEnabledMessage": "Έχετε ενεργοποιημένη την καταγραφή εντοπισμού σφαλμάτων, η οποία έχει σχεδιαστεί για χρήση μόνο από προγραμματιστές.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Για βέλτιστη απόδοση, συνιστάται η απενεργοποίηση καταγραφής εντοπισμού σφαλμάτων. Θέλετε να απενεργοποιήσετε την καταγραφή τώρα;", diff --git a/Ryujinx.Ava/Assets/Locales/en_US.json b/Ryujinx.Ava/Assets/Locales/en_US.json index ba5af264b..3d5096759 100644 --- a/Ryujinx.Ava/Assets/Locales/en_US.json +++ b/Ryujinx.Ava/Assets/Locales/en_US.json @@ -375,7 +375,7 @@ "DialogUserProfileUnsavedChangesSubMessage": "Do you want to discard your changes?", "DialogControllerSettingsModifiedConfirmMessage": "The current controller settings has been updated.", "DialogControllerSettingsModifiedConfirmSubMessage": "Do you want to save?", - "DialogDlcLoadNcaErrorMessage": "{0}. Errored File: {1}", + "DialogLoadNcaErrorMessage": "{0}. Errored File: {1}", "DialogDlcNoDlcErrorMessage": "The specified file does not contain a DLC for the selected title!", "DialogPerformanceCheckLoggingEnabledMessage": "You have trace logging enabled, which is designed to be used by developers only.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "For optimal performance, it's recommended to disable trace logging. Would you like to disable trace logging now?", diff --git a/Ryujinx.Ava/Assets/Locales/es_ES.json b/Ryujinx.Ava/Assets/Locales/es_ES.json index 660d62a1e..13b05fc04 100644 --- a/Ryujinx.Ava/Assets/Locales/es_ES.json +++ b/Ryujinx.Ava/Assets/Locales/es_ES.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "¿Quieres eliminar el perfil seleccionado?", "DialogControllerSettingsModifiedConfirmMessage": "Se ha actualizado la configuración del mando actual.", "DialogControllerSettingsModifiedConfirmSubMessage": "¿Guardar cambios?", - "DialogDlcLoadNcaErrorMessage": "{0}. Archivo con error: {1}", + "DialogLoadNcaErrorMessage": "{0}. Archivo con error: {1}", "DialogDlcNoDlcErrorMessage": "¡Ese archivo no contiene contenido descargable para el título seleccionado!", "DialogPerformanceCheckLoggingEnabledMessage": "Has habilitado los registros debug, diseñados solo para uso de los desarrolladores.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Para un rendimiento óptimo, se recomienda deshabilitar los registros debug. ¿Quieres deshabilitarlos ahora?", diff --git a/Ryujinx.Ava/Assets/Locales/fr_FR.json b/Ryujinx.Ava/Assets/Locales/fr_FR.json index 71f32c6ee..fad46751a 100644 --- a/Ryujinx.Ava/Assets/Locales/fr_FR.json +++ b/Ryujinx.Ava/Assets/Locales/fr_FR.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Voulez-vous supprimer le profil sélectionné ?", "DialogControllerSettingsModifiedConfirmMessage": "Les paramètres actuels du contrôleur ont été mis à jour.", "DialogControllerSettingsModifiedConfirmSubMessage": "Voulez-vous sauvegarder?", - "DialogDlcLoadNcaErrorMessage": "{0}. Fichier erroné : {1}", + "DialogLoadNcaErrorMessage": "{0}. Fichier erroné : {1}", "DialogDlcNoDlcErrorMessage": "Le fichier spécifié ne contient pas de DLC pour le titre sélectionné !", "DialogPerformanceCheckLoggingEnabledMessage": "Vous avez activé la journalisation des traces, conçue pour être utilisée uniquement par les développeurs.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Pour des performances optimales, il est recommandé de désactiver la journalisation des traces. Souhaitez-vous désactiver la journalisation des traces maintenant ?", diff --git a/Ryujinx.Ava/Assets/Locales/it_IT.json b/Ryujinx.Ava/Assets/Locales/it_IT.json index fbdd4046d..0ae027496 100644 --- a/Ryujinx.Ava/Assets/Locales/it_IT.json +++ b/Ryujinx.Ava/Assets/Locales/it_IT.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Vuoi eliminare il profilo selezionato?", "DialogControllerSettingsModifiedConfirmMessage": "Le attuali impostazioni del controller sono state aggiornate.", "DialogControllerSettingsModifiedConfirmSubMessage": "Vuoi salvare?", - "DialogDlcLoadNcaErrorMessage": "{0}. File errato: {1}", + "DialogLoadNcaErrorMessage": "{0}. File errato: {1}", "DialogDlcNoDlcErrorMessage": "Il file specificato non contiene un DLC per il titolo selezionato!", "DialogPerformanceCheckLoggingEnabledMessage": "Hai abilitato il trace logging, che è progettato per essere usato solo dagli sviluppatori.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Per prestazioni ottimali, si raccomanda di disabilitare il trace logging. Vuoi disabilitare il debug logging adesso?", diff --git a/Ryujinx.Ava/Assets/Locales/ja_JP.json b/Ryujinx.Ava/Assets/Locales/ja_JP.json index b1e0a43bf..581443f55 100644 --- a/Ryujinx.Ava/Assets/Locales/ja_JP.json +++ b/Ryujinx.Ava/Assets/Locales/ja_JP.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "選択されたプロファイルを削除しますか", "DialogControllerSettingsModifiedConfirmMessage": "現在のコントローラ設定が更新されました.", "DialogControllerSettingsModifiedConfirmSubMessage": "セーブしますか?", - "DialogDlcLoadNcaErrorMessage": "{0}. エラー発生ファイル: {1}", + "DialogLoadNcaErrorMessage": "{0}. エラー発生ファイル: {1}", "DialogDlcNoDlcErrorMessage": "選択されたファイルはこのタイトル用の DLC ではありません!", "DialogPerformanceCheckLoggingEnabledMessage": "トレースロギングを有効にします. これは開発者のみに有用な機能です.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "パフォーマンス最適化のためには,トレースロギングを無効にすることを推奨します. トレースロギングを無効にしてよろしいですか?", diff --git a/Ryujinx.Ava/Assets/Locales/ko_KR.json b/Ryujinx.Ava/Assets/Locales/ko_KR.json index 5379efa9c..adf7f61e3 100644 --- a/Ryujinx.Ava/Assets/Locales/ko_KR.json +++ b/Ryujinx.Ava/Assets/Locales/ko_KR.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "선택한 프로파일을 삭제하겠습니까?", "DialogControllerSettingsModifiedConfirmMessage": "현재 컨트롤러 설정이 업데이트되었습니다.", "DialogControllerSettingsModifiedConfirmSubMessage": "저장하겠습니까?", - "DialogDlcLoadNcaErrorMessage": "{0}입니다. 오류 발생 파일: {1}", + "DialogLoadNcaErrorMessage": "{0}입니다. 오류 발생 파일: {1}", "DialogDlcNoDlcErrorMessage": "지정된 파일에 선택한 타이틀에 대한 DLC가 포함되어 있지 않습니다!", "DialogPerformanceCheckLoggingEnabledMessage": "개발자만 사용하도록 설계된 추적 로깅이 활성화되어 있습니다.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "최적의 성능을 위해 추적 로깅을 비활성화하는 것이 좋습니다. 지금 추적 로깅을 비활성화하겠습니까?", diff --git a/Ryujinx.Ava/Assets/Locales/pl_PL.json b/Ryujinx.Ava/Assets/Locales/pl_PL.json index 0cc0b4f91..077ccc2d5 100644 --- a/Ryujinx.Ava/Assets/Locales/pl_PL.json +++ b/Ryujinx.Ava/Assets/Locales/pl_PL.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Czy chcesz usunąć wybrany profil", "DialogControllerSettingsModifiedConfirmMessage": "Aktualne ustawienia kontrolera zostały zaktualizowane.", "DialogControllerSettingsModifiedConfirmSubMessage": "Czy chcesz zapisać?", - "DialogDlcLoadNcaErrorMessage": "{0}. Błędny Plik: {1}", + "DialogLoadNcaErrorMessage": "{0}. Błędny Plik: {1}", "DialogDlcNoDlcErrorMessage": "Określony plik nie zawiera DLC dla wybranego tytułu!", "DialogPerformanceCheckLoggingEnabledMessage": "Masz włączone rejestrowanie śledzenia, które jest przeznaczone tylko dla programistów.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Aby uzyskać optymalną wydajność, zaleca się wyłączenie rejestrowania śledzenia. Czy chcesz teraz wyłączyć rejestrowanie śledzenia?", diff --git a/Ryujinx.Ava/Assets/Locales/pt_BR.json b/Ryujinx.Ava/Assets/Locales/pt_BR.json index ded6cf95f..effe8c028 100644 --- a/Ryujinx.Ava/Assets/Locales/pt_BR.json +++ b/Ryujinx.Ava/Assets/Locales/pt_BR.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Deseja deletar o perfil selecionado", "DialogControllerSettingsModifiedConfirmMessage": "As configurações de controle atuais foram atualizadas.", "DialogControllerSettingsModifiedConfirmSubMessage": "Deseja salvar?", - "DialogDlcLoadNcaErrorMessage": "{0}. Arquivo com erro: {1}", + "DialogLoadNcaErrorMessage": "{0}. Arquivo com erro: {1}", "DialogDlcNoDlcErrorMessage": "O arquivo especificado não contém DLCs para o título selecionado!", "DialogPerformanceCheckLoggingEnabledMessage": "Os logs de depuração estão ativos, esse recurso é feito para ser usado apenas por desenvolvedores.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Para melhor performance, é recomendável desabilitar os logs de depuração. Gostaria de desabilitar os logs de depuração agora?", diff --git a/Ryujinx.Ava/Assets/Locales/ru_RU.json b/Ryujinx.Ava/Assets/Locales/ru_RU.json index 7b25f4554..ea60bd918 100644 --- a/Ryujinx.Ava/Assets/Locales/ru_RU.json +++ b/Ryujinx.Ava/Assets/Locales/ru_RU.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Вы хотите удалить выбранный профиль", "DialogControllerSettingsModifiedConfirmMessage": "Текущие настройки контроллера обновлены.", "DialogControllerSettingsModifiedConfirmSubMessage": "Вы хотите сохранить?", - "DialogDlcLoadNcaErrorMessage": "{0}. Файл с ошибкой: {1}", + "DialogLoadNcaErrorMessage": "{0}. Файл с ошибкой: {1}", "DialogDlcNoDlcErrorMessage": "Указанный файл не содержит DLC для выбранной игры!", "DialogPerformanceCheckLoggingEnabledMessage": "У вас включено ведение журнала отладки, предназначенное только для разработчиков.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Для оптимальной производительности рекомендуется отключить ведение журнала отладки. Вы хотите отключить ведение журнала отладки сейчас?", diff --git a/Ryujinx.Ava/Assets/Locales/tr_TR.json b/Ryujinx.Ava/Assets/Locales/tr_TR.json index f277713ba..decc3cfd6 100644 --- a/Ryujinx.Ava/Assets/Locales/tr_TR.json +++ b/Ryujinx.Ava/Assets/Locales/tr_TR.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Seçilen profili silmek istiyor musunuz", "DialogControllerSettingsModifiedConfirmMessage": "Güncel kontrolcü seçenekleri güncellendi.", "DialogControllerSettingsModifiedConfirmSubMessage": "Kaydetmek istiyor musunuz?", - "DialogDlcLoadNcaErrorMessage": "{0}. Hatalı Dosya: {1}", + "DialogLoadNcaErrorMessage": "{0}. Hatalı Dosya: {1}", "DialogDlcNoDlcErrorMessage": "Belirtilen dosya seçilen oyun için DLC içermiyor!", "DialogPerformanceCheckLoggingEnabledMessage": "Sadece geliştiriler için dizayn edilen Trace Loglama seçeneği etkin.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "En iyi performans için trace loglama'nın devre dışı bırakılması tavsiye edilir. Trace loglama seçeneğini şimdi devre dışı bırakmak ister misiniz?", diff --git a/Ryujinx.Ava/Assets/Locales/uk_UA.json b/Ryujinx.Ava/Assets/Locales/uk_UA.json index 01d433da6..111337a42 100644 --- a/Ryujinx.Ava/Assets/Locales/uk_UA.json +++ b/Ryujinx.Ava/Assets/Locales/uk_UA.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "Ви хочете видалити вибраний профіль", "DialogControllerSettingsModifiedConfirmMessage": "Поточні налаштування контролера оновлено.", "DialogControllerSettingsModifiedConfirmSubMessage": "Ви хочете зберегти?", - "DialogDlcLoadNcaErrorMessage": "{0}. Файл з помилкою: {1}", + "DialogLoadNcaErrorMessage": "{0}. Файл з помилкою: {1}", "DialogDlcNoDlcErrorMessage": "Зазначений файл не містить DLC для вибраного заголовку!", "DialogPerformanceCheckLoggingEnabledMessage": "Ви увімкнули журнал налагодження, призначений лише для розробників.", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "Для оптимальної продуктивності рекомендується вимкнути ведення журналу налагодження. Ви хочете вимкнути ведення журналу налагодження зараз?", diff --git a/Ryujinx.Ava/Assets/Locales/zh_CN.json b/Ryujinx.Ava/Assets/Locales/zh_CN.json index cd76951a7..25dc3cbaf 100644 --- a/Ryujinx.Ava/Assets/Locales/zh_CN.json +++ b/Ryujinx.Ava/Assets/Locales/zh_CN.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "是否删除选择的账户", "DialogControllerSettingsModifiedConfirmMessage": "目前的输入预设已更新", "DialogControllerSettingsModifiedConfirmSubMessage": "要保存吗?", - "DialogDlcLoadNcaErrorMessage": "{0}. 错误的文件: {1}", + "DialogLoadNcaErrorMessage": "{0}. 错误的文件: {1}", "DialogDlcNoDlcErrorMessage": "选择的文件不包含所选游戏的 DLC!", "DialogPerformanceCheckLoggingEnabledMessage": "您启用了跟踪日志,仅供开发人员使用。", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "为了获得最佳性能,建议禁用跟踪日志记录。您是否要立即禁用?", diff --git a/Ryujinx.Ava/Assets/Locales/zh_TW.json b/Ryujinx.Ava/Assets/Locales/zh_TW.json index e68329957..940282a0f 100644 --- a/Ryujinx.Ava/Assets/Locales/zh_TW.json +++ b/Ryujinx.Ava/Assets/Locales/zh_TW.json @@ -370,7 +370,7 @@ "DialogUserProfileDeletionConfirmMessage": "是否刪除選擇的帳號", "DialogControllerSettingsModifiedConfirmMessage": "目前的輸入預設已更新", "DialogControllerSettingsModifiedConfirmSubMessage": "要儲存嗎?", - "DialogDlcLoadNcaErrorMessage": "{0}. 錯誤的檔案: {1}", + "DialogLoadNcaErrorMessage": "{0}. 錯誤的檔案: {1}", "DialogDlcNoDlcErrorMessage": "選擇的檔案不包含所選遊戲的 DLC!", "DialogPerformanceCheckLoggingEnabledMessage": "您啟用了跟蹤日誌,僅供開發人員使用。", "DialogPerformanceCheckLoggingEnabledConfirmMessage": "為了獲得最佳效能,建議停用跟蹤日誌記錄。您是否要立即停用?", diff --git a/Ryujinx.Ava/Common/ApplicationHelper.cs b/Ryujinx.Ava/Common/ApplicationHelper.cs index 8e5bdaec7..2dc3d37ff 100644 --- a/Ryujinx.Ava/Common/ApplicationHelper.cs +++ b/Ryujinx.Ava/Common/ApplicationHelper.cs @@ -80,8 +80,7 @@ namespace Ryujinx.Ava.Common { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog( - string.Format(LocaleManager.Instance[LocaleKeys.DialogMessageCreateSaveErrorMessage], result.ToStringWithName())); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogMessageCreateSaveErrorMessage, result.ToStringWithName())); }); return false; @@ -100,7 +99,7 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogMessageFindSaveErrorMessage], result.ToStringWithName())); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogMessageFindSaveErrorMessage, result.ToStringWithName())); }); return false; @@ -164,7 +163,7 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.Post(async () => { UserResult result = await ContentDialogHelper.CreateConfirmationDialog( - string.Format(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionMessage], ncaSectionType, Path.GetFileName(titleFilePath)), + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogNcaExtractionMessage, ncaSectionType, Path.GetFileName(titleFilePath)), "", "", LocaleManager.Instance[LocaleKeys.InputDialogCancel], diff --git a/Ryujinx.Ava/Common/Locale/LocaleExtension.cs b/Ryujinx.Ava/Common/Locale/LocaleExtension.cs index 6c54becdc..b82c405de 100644 --- a/Ryujinx.Ava/Common/Locale/LocaleExtension.cs +++ b/Ryujinx.Ava/Common/Locale/LocaleExtension.cs @@ -20,7 +20,7 @@ namespace Ryujinx.Ava.Common.Locale ReflectionBindingExtension binding = new($"[{keyToUse}]") { - Mode = BindingMode.OneWay, + Mode = BindingMode.OneWay, Source = LocaleManager.Instance }; diff --git a/Ryujinx.Ava/Common/Locale/LocaleManager.cs b/Ryujinx.Ava/Common/Locale/LocaleManager.cs index 5bcaa437e..1374bfee1 100644 --- a/Ryujinx.Ava/Common/Locale/LocaleManager.cs +++ b/Ryujinx.Ava/Common/Locale/LocaleManager.cs @@ -13,56 +13,87 @@ namespace Ryujinx.Ava.Common.Locale { private const string DefaultLanguageCode = "en_US"; - private Dictionary _localeStrings; - private ConcurrentDictionary _dynamicValues; + private Dictionary _localeStrings; + private Dictionary _localeDefaultStrings; + private readonly ConcurrentDictionary _dynamicValues; public static LocaleManager Instance { get; } = new LocaleManager(); - public Dictionary LocaleStrings { get => _localeStrings; set => _localeStrings = value; } - public LocaleManager() { - _localeStrings = new Dictionary(); - _dynamicValues = new ConcurrentDictionary(); + _localeStrings = new Dictionary(); + _localeDefaultStrings = new Dictionary(); + _dynamicValues = new ConcurrentDictionary(); Load(); } public void Load() { + // Load the system Language Code. string localeLanguageCode = CultureInfo.CurrentCulture.Name.Replace('-', '_'); + // If the view is loaded with the UI Previewer detached, then override it with the saved one or default. if (Program.PreviewerDetached) { if (!string.IsNullOrEmpty(ConfigurationState.Instance.Ui.LanguageCode.Value)) { localeLanguageCode = ConfigurationState.Instance.Ui.LanguageCode.Value; } + else + { + localeLanguageCode = DefaultLanguageCode; + } } - // Load english first, if the target language translation is incomplete, we default to english. + // Load en_US as default, if the target language translation is incomplete. LoadDefaultLanguage(); - if (localeLanguageCode != DefaultLanguageCode) - { - LoadLanguage(localeLanguageCode); - } + LoadLanguage(localeLanguageCode); } public string this[LocaleKeys key] { get { + // Check if the locale contains the key. if (_localeStrings.TryGetValue(key, out string value)) { + // Check if the localized string needs to be formatted. if (_dynamicValues.TryGetValue(key, out var dynamicValue)) { - return string.Format(value, dynamicValue); + try + { + return string.Format(value, dynamicValue); + } + catch (Exception) + { + // If formatting failed use the default text instead. + if (_localeDefaultStrings.TryGetValue(key, out value)) + { + try + { + return string.Format(value, dynamicValue); + } + catch (Exception) + { + // If formatting the default text failed return the key. + return key.ToString(); + } + } + } } return value; } + // If the locale doesn't contain the key return the default one. + if (_localeDefaultStrings.TryGetValue(key, out string defaultValue)) + { + return defaultValue; + } + + // If the locale text doesn't exist return the key. return key.ToString(); } set @@ -73,42 +104,43 @@ namespace Ryujinx.Ava.Common.Locale } } - public void UpdateDynamicValue(LocaleKeys key, params object[] values) + public string UpdateAndGetDynamicValue(LocaleKeys key, params object[] values) { _dynamicValues[key] = values; OnPropertyChanged("Item"); + + return this[key]; } - public void LoadDefaultLanguage() + private void LoadDefaultLanguage() { - LoadLanguage(DefaultLanguageCode); + _localeDefaultStrings = LoadJsonLanguage(); } public void LoadLanguage(string languageCode) { - string languageJson = EmbeddedResources.ReadAllText($"Ryujinx.Ava/Assets/Locales/{languageCode}.json"); - - if (languageJson == null) + foreach (var item in LoadJsonLanguage(languageCode)) { - return; + this[item.Key] = item.Value; } + } - var strings = JsonHelper.Deserialize>(languageJson); + private Dictionary LoadJsonLanguage(string languageCode = DefaultLanguageCode) + { + var localeStrings = new Dictionary(); + string languageJson = EmbeddedResources.ReadAllText($"Ryujinx.Ava/Assets/Locales/{languageCode}.json"); + var strings = JsonHelper.Deserialize>(languageJson); foreach (var item in strings) { if (Enum.TryParse(item.Key, out var key)) { - this[key] = item.Value; + localeStrings[key] = item.Value; } } - if (Program.PreviewerDetached) - { - ConfigurationState.Instance.Ui.LanguageCode.Value = languageCode; - ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); - } + return localeStrings; } } } \ No newline at end of file diff --git a/Ryujinx.Ava/Modules/Updater/Updater.cs b/Ryujinx.Ava/Modules/Updater/Updater.cs index 39683187e..62dc17729 100644 --- a/Ryujinx.Ava/Modules/Updater/Updater.cs +++ b/Ryujinx.Ava/Modules/Updater/Updater.cs @@ -588,7 +588,7 @@ namespace Ryujinx.Modules } catch { - Logger.Warning?.Print(LogClass.Application, string.Format(LocaleManager.Instance[LocaleKeys.UpdaterRenameFailed], file)); + Logger.Warning?.Print(LogClass.Application, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.UpdaterRenameFailed, file)); } } diff --git a/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs b/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs index 0809cb4f8..a49077f21 100644 --- a/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs +++ b/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs @@ -29,17 +29,12 @@ namespace Ryujinx.Ava.UI.Applet public bool DisplayMessageDialog(ControllerAppletUiArgs args) { - string playerCount = args.PlayerCountMin == args.PlayerCountMax - ? args.PlayerCountMin.ToString() - : $"{args.PlayerCountMin}-{args.PlayerCountMax}"; - - LocaleKeys key = args.PlayerCountMin == args.PlayerCountMax ? LocaleKeys.DialogControllerAppletMessage : LocaleKeys.DialogControllerAppletMessagePlayerRange; - - string message = string.Format(LocaleManager.Instance[key], - playerCount, - args.SupportedStyles, - string.Join(", ", args.SupportedPlayers), - args.IsDocked ? LocaleManager.Instance[LocaleKeys.DialogControllerAppletDockModeSet] : ""); + string message = LocaleManager.Instance.UpdateAndGetDynamicValue( + args.PlayerCountMin == args.PlayerCountMax ? LocaleKeys.DialogControllerAppletMessage : LocaleKeys.DialogControllerAppletMessagePlayerRange, + args.PlayerCountMin == args.PlayerCountMax ? args.PlayerCountMin.ToString() : $"{args.PlayerCountMin}-{args.PlayerCountMax}", + args.SupportedStyles, + string.Join(", ", args.SupportedPlayers), + args.IsDocked ? LocaleManager.Instance[LocaleKeys.DialogControllerAppletDockModeSet] : ""); return DisplayMessageDialog(LocaleManager.Instance[LocaleKeys.DialogControllerAppletTitle], message); } @@ -92,7 +87,7 @@ namespace Ryujinx.Ava.UI.Applet } catch (Exception ex) { - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogMessageDialogErrorExceptionMessage], ex)); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogMessageDialogErrorExceptionMessage, ex)); dialogCloseEvent.Set(); } @@ -126,7 +121,8 @@ namespace Ryujinx.Ava.UI.Applet catch (Exception ex) { error = true; - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogSoftwareKeyboardErrorExceptionMessage], ex)); + + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogSoftwareKeyboardErrorExceptionMessage, ex)); } finally { @@ -181,7 +177,8 @@ namespace Ryujinx.Ava.UI.Applet catch (Exception ex) { dialogCloseEvent.Set(); - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogErrorAppletErrorExceptionMessage], ex)); + + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogErrorAppletErrorExceptionMessage, ex)); } }); diff --git a/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs b/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs index 78e6f237e..78c62a9a7 100644 --- a/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs +++ b/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs @@ -139,14 +139,16 @@ namespace Ryujinx.Ava.UI.Controls else if (_inputMin > 0 && _inputMax == int.MaxValue) { Error.IsVisible = true; - Error.Text = string.Format(LocaleManager.Instance[LocaleKeys.SwkbdMinCharacters], _inputMin); + + Error.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinCharacters, _inputMin); _checkLength = length => _inputMin <= length; } else { Error.IsVisible = true; - Error.Text = string.Format(LocaleManager.Instance[LocaleKeys.SwkbdMinRangeCharacters], _inputMin, _inputMax); + + Error.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinRangeCharacters, _inputMin, _inputMax); _checkLength = length => _inputMin <= length && length <= _inputMax; } diff --git a/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs b/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs index 06ec8e302..4ed629ff1 100644 --- a/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs +++ b/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs @@ -76,11 +76,11 @@ namespace Ryujinx.Ava.UI.Helpers string setupButtonLabel = isInSetupGuide ? LocaleManager.Instance[LocaleKeys.OpenSetupGuideMessage] : ""; var result = await ContentDialogHelper.CreateInfoDialog( - string.Format(LocaleManager.Instance[LocaleKeys.DialogUserErrorDialogMessage], errorCode, GetErrorTitle(error)), + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogUserErrorDialogMessage, errorCode, GetErrorTitle(error)), GetErrorDescription(error) + (isInSetupGuide ? LocaleManager.Instance[LocaleKeys.DialogUserErrorDialogInfoMessage] : ""), setupButtonLabel, LocaleManager.Instance[LocaleKeys.InputDialogOk], - string.Format(LocaleManager.Instance[LocaleKeys.DialogUserErrorDialogTitle], errorCode)); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogUserErrorDialogTitle, errorCode)); if (result == UserResult.Ok) { diff --git a/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs b/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs index c57b3a26a..80476a433 100644 --- a/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs +++ b/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Ava.UI.Models public ApplicationControlProperty Control { get; } public string Path { get; } - public string Label => string.Format(LocaleManager.Instance[LocaleKeys.TitleUpdateVersionLabel], Control.DisplayVersionString.ToString()); + public string Label => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleUpdateVersionLabel, Control.DisplayVersionString.ToString()); public TitleUpdateModel(ApplicationControlProperty control, string path) { diff --git a/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs b/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs index 5faad33fb..872c1a37f 100644 --- a/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs +++ b/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs @@ -81,10 +81,7 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public string Developers - { - get => string.Format(LocaleManager.Instance[LocaleKeys.AboutPageDeveloperListMore], "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz"); - } + public string Developers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz"); public AboutWindowViewModel() { diff --git a/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs b/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs index 5d5ca5f83..f63fc3491 100644 --- a/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs +++ b/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs @@ -3,6 +3,8 @@ using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Svg.Skia; using Avalonia.Threading; +using LibHac.Bcat; +using LibHac.Tools.Fs; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Input; using Ryujinx.Ava.UI.Controls; @@ -717,7 +719,7 @@ namespace Ryujinx.Ava.UI.ViewModels { Logger.Error?.Print(LogClass.Configuration, $"Profile {ProfileName} is incompatible with the current input configuration system."); - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileErrorMessage], ProfileName)); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogProfileInvalidProfileErrorMessage, ProfileName)); return; } diff --git a/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs index 443e0d180..8bd146ed8 100644 --- a/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs +++ b/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs @@ -5,8 +5,10 @@ using Avalonia.Media; using Avalonia.Threading; using DynamicData; using DynamicData.Binding; +using LibHac.Bcat; using LibHac.Fs; using LibHac.FsSystem; +using LibHac.Tools.Fs; using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Input; @@ -947,20 +949,18 @@ namespace Ryujinx.Ava.UI.ViewModels if (firmwareVersion == null) { - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareNotFoundErrorMessage], filename)); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareNotFoundErrorMessage, filename)); return; } - string dialogTitle = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallTitle], firmwareVersion.VersionString); + string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallTitle, firmwareVersion.VersionString); + string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallMessage, firmwareVersion.VersionString); SystemVersion currentVersion = ContentManager.GetCurrentFirmwareVersion(); - - string dialogMessage = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallMessage], firmwareVersion.VersionString); - if (currentVersion != null) { - dialogMessage += string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallSubMessage], currentVersion.VersionString); + dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallSubMessage, currentVersion.VersionString); } dialogMessage += LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallConfirmMessage]; @@ -993,7 +993,7 @@ namespace Ryujinx.Ava.UI.ViewModels { waitingDialog.Close(); - string message = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage], firmwareVersion.VersionString); + string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage, firmwareVersion.VersionString); await ContentDialogHelper.CreateInfoDialog(dialogTitle, message, LocaleManager.Instance[LocaleKeys.InputDialogOk], "", LocaleManager.Instance[LocaleKeys.RyujinxInfo]); @@ -1063,7 +1063,7 @@ namespace Ryujinx.Ava.UI.ViewModels IsLoadingIndeterminate = false; break; case LoadState.Loaded: - LoadHeading = string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], TitleName); + LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, TitleName); IsLoadingIndeterminate = true; CacheLoadStatus = ""; break; @@ -1079,7 +1079,7 @@ namespace Ryujinx.Ava.UI.ViewModels IsLoadingIndeterminate = false; break; case ShaderCacheLoadingState.Loaded: - LoadHeading = string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], TitleName); + LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, TitleName); IsLoadingIndeterminate = true; CacheLoadStatus = ""; break; @@ -1333,10 +1333,15 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public void ChangeLanguage(object obj) + public void ChangeLanguage(object languageCode) { - LocaleManager.Instance.LoadDefaultLanguage(); - LocaleManager.Instance.LoadLanguage((string)obj); + LocaleManager.Instance.LoadLanguage((string)languageCode); + + if (Program.PreviewerDetached) + { + ConfigurationState.Instance.Ui.LanguageCode.Value = (string)languageCode; + ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); + } } public async void ManageProfiles() @@ -1374,7 +1379,7 @@ namespace Ryujinx.Ava.UI.ViewModels // FIXME: Found a way to reproduce the bold effect on the title name (fork?). UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DialogWarning], - string.Format(LocaleManager.Instance[LocaleKeys.DialogPPTCDeletionMessage], selection.TitleName), + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, selection.TitleName), LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); @@ -1401,7 +1406,7 @@ namespace Ryujinx.Ava.UI.ViewModels } catch (Exception e) { - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogPPTCDeletionErrorMessage], file.Name, e)); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, e)); } } } @@ -1438,7 +1443,7 @@ namespace Ryujinx.Ava.UI.ViewModels // FIXME: Found a way to reproduce the bold effect on the title name (fork?). UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DialogWarning], - string.Format(LocaleManager.Instance[LocaleKeys.DialogShaderDeletionMessage], selection.TitleName), + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, selection.TitleName), LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); @@ -1463,7 +1468,7 @@ namespace Ryujinx.Ava.UI.ViewModels } catch (Exception e) { - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogPPTCDeletionErrorMessage], directory.Name, e)); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, directory.Name, e)); } } } @@ -1476,7 +1481,7 @@ namespace Ryujinx.Ava.UI.ViewModels } catch (Exception e) { - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.ShaderCachePurgeError], file.Name, e)); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.ShaderCachePurgeError, file.Name, e)); } } } @@ -1641,7 +1646,7 @@ namespace Ryujinx.Ava.UI.ViewModels StatusBarProgressMaximum = 0; StatusBarProgressValue = 0; - LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0); }); ReloadGameList?.Invoke(); @@ -1755,8 +1760,14 @@ namespace Ryujinx.Ava.UI.ViewModels } CanUpdate = false; - LoadHeading = string.IsNullOrWhiteSpace(titleName) ? string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], AppHost.Device.Application.TitleName) : titleName; - TitleName = string.IsNullOrWhiteSpace(titleName) ? AppHost.Device.Application.TitleName : titleName; + + LoadHeading = TitleName = titleName; + + if (string.IsNullOrWhiteSpace(titleName)) + { + LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, AppHost.Device.Application.TitleName); + TitleName = AppHost.Device.Application.TitleName; + } SwitchToRenderer(startFullscreen); @@ -1807,14 +1818,13 @@ namespace Ryujinx.Ava.UI.ViewModels if (version != null) { - LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarSystemVersion, - version.VersionString); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarSystemVersion, version.VersionString); hasApplet = version.Major > 3; } else { - LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarSystemVersion, "0.0"); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarSystemVersion, "0.0"); } IsAppletMenuActive = hasApplet; diff --git a/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs b/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs index 131ebd25b..1bac94245 100644 --- a/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs +++ b/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs @@ -181,7 +181,7 @@ public class TitleUpdateViewModel : BaseModel { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogDlcLoadNcaErrorMessage], ex.Message, path)); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, path)); }); } } diff --git a/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs b/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs index dad74230f..097634a80 100644 --- a/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs +++ b/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs @@ -17,8 +17,7 @@ namespace Ryujinx.Ava.UI.ViewModels private ObservableCollection _views = new(); private AccountManager _accountManager; - public string SaveManagerHeading => - string.Format(LocaleManager.Instance[LocaleKeys.SaveManagerHeading], _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId); + public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId); public int SortIndex { diff --git a/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs b/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs index b27d20d37..cb939763b 100644 --- a/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs +++ b/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs @@ -31,7 +31,7 @@ namespace Ryujinx.Ava.UI.Windows { LoadedCheats = new AvaloniaList(); - Heading = string.Format(LocaleManager.Instance[LocaleKeys.CheatWindowHeading], titleName, titleId.ToUpper()); + Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper()); InitializeComponent(); diff --git a/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml.cs b/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml.cs index fa9d70e22..47216c489 100644 --- a/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml.cs +++ b/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml.cs @@ -86,7 +86,7 @@ namespace Ryujinx.Ava.UI.Windows private void PrintHeading() { - Heading.Text = string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], _downloadableContents.Count, _titleName, _titleId.ToString("X16")); + Heading.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DlcWindowHeading, _downloadableContents.Count, _titleName, _titleId.ToString("X16")); } private void LoadDownloadableContents() @@ -133,7 +133,7 @@ namespace Ryujinx.Ava.UI.Windows { Dispatcher.UIThread.InvokeAsync(async () => { - await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogDlcLoadNcaErrorMessage], ex.Message, containerPath)); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, containerPath)); }); } diff --git a/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs b/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs index dcd89ac0a..921dfbb11 100644 --- a/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs +++ b/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs @@ -146,7 +146,7 @@ namespace Ryujinx.Ava.UI.Windows private void ApplicationLibrary_ApplicationCountUpdated(object sender, ApplicationCountUpdatedEventArgs e) { - LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarGamesLoaded, e.NumAppsLoaded, e.NumAppsFound); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, e.NumAppsLoaded, e.NumAppsFound); Dispatcher.UIThread.Post(() => { @@ -416,7 +416,7 @@ namespace Ryujinx.Ava.UI.Windows ViewModel.StatusBarProgressMaximum = 0; ViewModel.StatusBarProgressValue = 0; - LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0); }); ReloadGameList(); diff --git a/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs b/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs index 9d8b9a7b9..41370e669 100644 --- a/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs +++ b/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs @@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Windows SecondaryButtonText = "", CloseButtonText = "", Content = new TitleUpdateWindow(virtualFileSystem, titleId, titleName), - Title = string.Format(LocaleManager.Instance[LocaleKeys.GameUpdateWindowHeading], titleName, titleId.ToString("X16")) + Title = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.GameUpdateWindowHeading, titleName, titleId.ToString("X16")) }; Style bottomBorder = new(x => x.OfType().Name("DialogSpace").Child().OfType());