diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index cf250eb08..a24d8b83f 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -105,46 +105,48 @@ jobs: gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" shell: bash + + # If anyone wants to look into why appimagetool randomly errors with exit code 8, that would be cool - - name: Build AppImage (Linux) - if: matrix.platform.os == 'ubuntu-latest' - run: | - BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" - PLATFORM_NAME="${{ matrix.platform.name }}" - - sudo apt install -y zsync desktop-file-utils appstream - - mkdir -p tools - export PATH="$PATH:$(readlink -f tools)" - - # Setup appimagetool - wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" - chmod +x tools/appimagetool - chmod +x distribution/linux/appimage/build-appimage.sh - - # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) - if [ "$PLATFORM_NAME" = "linux-x64" ]; then - ARCH_NAME=x64 - export ARCH=x86_64 - elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then - ARCH_NAME=arm64 - export ARCH=aarch64 - else - echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME"" - exit 1 - fi - - export UFLAG="gh-releases-zsync|${{ secrets.RC_OWNER }}${{ secrets.RC_CANARY_NAME }}|latest|*-$ARCH_NAME.AppImage.zsync" - BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh - - pushd publish_appimage - mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage - mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync - popd - - gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage" - gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" - shell: bash +# - name: Build AppImage (Linux) +# if: matrix.platform.os == 'ubuntu-latest' +# run: | +# BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" +# PLATFORM_NAME="${{ matrix.platform.name }}" +# +# sudo apt install -y zsync desktop-file-utils appstream +# +# mkdir -p tools +# export PATH="$PATH:$(readlink -f tools)" +# +# # Setup appimagetool +# wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" +# chmod +x tools/appimagetool +# chmod +x distribution/linux/appimage/build-appimage.sh +# +# # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) +# if [ "$PLATFORM_NAME" = "linux-x64" ]; then +# ARCH_NAME=x64 +# export ARCH=x86_64 +# elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then +# ARCH_NAME=arm64 +# export ARCH=aarch64 +# else +# echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME"" +# exit 1 +# fi +# +# export UFLAG="gh-releases-zsync|${{ secrets.RC_OWNER }}${{ secrets.RC_CANARY_NAME }}|latest|*-$ARCH_NAME.AppImage.zsync" +# BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh +# +# pushd publish_appimage +# mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage +# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync +# popd +# +# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage" +# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" +# shell: bash macos_release: name: Release MacOS universal diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9f2099719..e1d85f63e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,46 +96,48 @@ jobs: shell: bash env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Build AppImage (Linux) - if: matrix.platform.os == 'ubuntu-latest' - run: | - BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" - PLATFORM_NAME="${{ matrix.platform.name }}" - - sudo apt install -y zsync desktop-file-utils appstream - - mkdir -p tools - export PATH="$PATH:$(readlink -f tools)" - - # Setup appimagetool - wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" - chmod +x tools/appimagetool - chmod +x distribution/linux/appimage/build-appimage.sh - - # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) - if [ "$PLATFORM_NAME" = "linux-x64" ]; then - ARCH_NAME=x64 - export ARCH=x86_64 - elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then - ARCH_NAME=arm64 - export ARCH=aarch64 - else - echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME"" - exit 1 - fi - - export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync" - BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh - - pushd publish_appimage - mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage - mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync - popd - gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage" - gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" - shell: bash + # If anyone wants to look into why appimagetool randomly errors with exit code 8, that would be cool + +# - name: Build AppImage (Linux) +# if: matrix.platform.os == 'ubuntu-latest' +# run: | +# BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" +# PLATFORM_NAME="${{ matrix.platform.name }}" +# +# sudo apt install -y zsync desktop-file-utils appstream +# +# mkdir -p tools +# export PATH="$PATH:$(readlink -f tools)" +# +# # Setup appimagetool +# wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" +# chmod +x tools/appimagetool +# chmod +x distribution/linux/appimage/build-appimage.sh +# +# # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) +# if [ "$PLATFORM_NAME" = "linux-x64" ]; then +# ARCH_NAME=x64 +# export ARCH=x86_64 +# elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then +# ARCH_NAME=arm64 +# export ARCH=aarch64 +# else +# echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME"" +# exit 1 +# fi +# +# export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync" +# BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh +# +# pushd publish_appimage +# mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage +# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync +# popd +# +# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage" +# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" +# shell: bash macos_release: name: Release MacOS universal diff --git a/Directory.Packages.props b/Directory.Packages.props index 5eb7eda3a..3017e8569 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -55,6 +55,7 @@ + diff --git a/assets/locales.json b/assets/locales.json index dc760c4fa..18e964d68 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -1,4 +1,24 @@ { + "Info": { + "Format1": "The Locale file uses a custom Unified format.", + "Format2": "The file starts with a list of all the supported languages.", + "Format3": "Each locale is made up an ID used for lookup and a list", + "Format4": "of the languages and their matching translations.", + "Format5": "When adding a new locale you just need to add the ID and", + "Format6": "the en_US language translation, then the validation system", + "Format7": "will add the rest of the languages automatically on rebuild.", + "Format8": "By default the languages will be added with an empty string.", + "Format9": "Any empty string or null value will automatically match the", + "Format10": "English translation.", + "Format11": "If you want to signal that a translation is supposed to", + "Format12": "match the English translation, you just have to replace the", + "Format13": "empty string with null.", + "Format14": "Translators who want to check what translations are missing", + "Format15": "for their language just need to search for:", + "Format16": "{'lang_code': ''} with double quotes instead of single", + "Format17": "e.g: {'en_US': ''} (but with any other language as English", + "Format18": "will never be missing translations)." + }, "Languages": [ "ar_SA", "de_DE", @@ -1100,101 +1120,101 @@ { "ID": "MenuBarViewWindow720", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "720p", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "MenuBarViewWindow1080", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "1080p", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "MenuBarViewWindow1440", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "1440p", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "MenuBarViewWindow2160", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "2160p", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { @@ -2092,7 +2112,7 @@ "sv_SE": "Total speltid: {0}", "th_TH": "", "tr_TR": "Toplam Oyun Süresi: {0}", - "uk_UA": "", + "uk_UA": "Всього зіграно: {0}", "zh_CN": "总游戏时间: {0}", "zh_TW": "總遊戲時間: {0}" } @@ -2650,26 +2670,26 @@ { "ID": "GameListContextMenuExtractDataExeFS", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "ExeFS", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { @@ -2700,26 +2720,26 @@ { "ID": "GameListContextMenuExtractDataRomFS", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "RomFS", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { @@ -5225,76 +5245,76 @@ { "ID": "SettingsTabSystemAudioBackendOpenAL", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "OpenAL", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "SettingsTabSystemAudioBackendSoundIO", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "SoundIO", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "Lyd Inn/Ut", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "SettingsTabSystemAudioBackendSDL2", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "SDL2", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { @@ -5950,126 +5970,126 @@ { "ID": "SettingsTabGraphicsAspectRatio4x3", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "4:3", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "SettingsTabGraphicsAspectRatio16x9", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "16:9", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "SettingsTabGraphicsAspectRatio16x10", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "16:10", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "SettingsTabGraphicsAspectRatio21x9", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "21:9", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "SettingsTabGraphicsAspectRatio32x9", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "32:9", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { @@ -6689,7 +6709,7 @@ "pl_PL": "Globalny Wpis", "pt_BR": "Entrada Global", "ru_RU": "Глобальный Ввод", - "sv_SE": "Global Input", + "sv_SE": null, "th_TH": "การป้อนข้อมูลแบบโกลบอล", "tr_TR": "Küresel Girdi", "uk_UA": "Глобальний Ввід", @@ -7217,7 +7237,7 @@ "sv_SE": "Konfiguration hittad:\n\nNamn:\t{0}\nGUID:\t{1}\n\n Väntar på anslutning till kontroller...", "th_TH": "", "tr_TR": "", - "uk_UA": "", + "uk_UA": "Знайдено конфігурацій:\n\nНазва:\t{0}\nGUID:\t{1}\n\n Очікується з’єднання з контролером...", "zh_CN": "发现配置:\n\n名称:\t{0}\nGUID:\t{1}\n\n 正在等待控制器连接...", "zh_TW": "找到控制器的配置:\n\n名稱:\t{0}\nGUID:\t{1}\n\n 正在等待控制器連線..." } @@ -7650,151 +7670,151 @@ { "ID": "ControllerSettingsButtonA", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "Α", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "A", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsButtonB", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "B", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsButtonX", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "X", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsButtonY", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "Y", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsButtonPlus", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "+", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsButtonMinus", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "-", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { @@ -8325,201 +8345,201 @@ { "ID": "ControllerSettingsTriggerL", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "L", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsTriggerR", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "R", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsTriggerZL", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "ZL", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsTriggerZR", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "ZR", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsLeftSL", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "SL", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsLeftSR", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "SR", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsRightSL", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "SL", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "ControllerSettingsRightSR", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "SR", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { @@ -13142,7 +13162,7 @@ "sv_SE": "Det gick inte att konvertera Ryujinx-versionen som mottogs från uppdateringsservern.", "th_TH": "", "tr_TR": "", - "uk_UA": "", + "uk_UA": "Не вдалося конвертувати версію Ryujinx, отриману з сервера оновлень.", "zh_CN": "无法转换从更新服务器接收的 Ryujinx 版本。", "zh_TW": "無法轉換從更新伺服器接收的 Ryujinx 版本。" } @@ -16567,7 +16587,7 @@ "sv_SE": "Om det här alternativet är aktiverat i anpassade inställningar kommer den globala inmatningskonfigurationen att användas.\n\nI de globala inställningarna: du kan aktivera eller inaktivera det efter behov; den här inställningen kommer att ärvas av alla nya anpassade konfigurationer som skapas.", "th_TH": "", "tr_TR": "", - "uk_UA": "", + "uk_UA": "Якщо цей параметр увімкнено в користувацьких налаштуваннях, буде використовуватись глобальна конфігурація вводу.\n\nВ глобальних налаштуваннях: за потреби цю опцію можна вмикати або вимикати; це налаштування автоматично застосується до всіх нових конфігурацій, які ви створите.", "zh_CN": "如果在自定义设置中启用了此选项,则将使用全局输入配置。\n\n在全局设置中: 您可以根据需要启用或禁用它;之后创建的任何自定义配置都将继承此设置。", "zh_TW": "如果在自訂設定啟用了此選項,則將使用全域輸入配置。\n\n在全域設定中:你可以根據需要啟用或停用它;之後建立的任何自訂配置都將繼承此設定。" } @@ -18917,7 +18937,7 @@ "sv_SE": "Ryujinx kunde inte hitta några installerade firmwares", "th_TH": "Ryujinx ไม่พบ เฟิร์มแวร์ที่ติดตั้งไว้ในเครื่องของคุณ", "tr_TR": "Ryujinx yüklü herhangi firmware bulamadı", - "uk_UA": "Ryujinx не вдалося знайти встановлену прошивку", + "uk_UA": "Ryujinx не вдалося знайти жодної встановленої прошивки", "zh_CN": "Ryujinx 模拟器未安装 Switch 系统固件", "zh_TW": "Ryujinx 無法找到已安裝的任何韌體" } @@ -18942,7 +18962,7 @@ "sv_SE": "Ryujinx kunde inte tolka angiven firmware. Detta sker oftast med utdaterade nycklar.", "th_TH": "Ryujinx ไม่สามารถวิเคราะห์เฟิร์มแวร์ที่ให้มาได้ ซึ่งมักมีสาเหตุมาจากคีย์ที่เก่าจนเกินไป", "tr_TR": "Ryujinx temin edilen firmware'i çözümleyemedi. Bu durum genellikle güncel olmayan keys'den kaynaklanır.", - "uk_UA": "Ryujinx не вдалося проаналізувати прошивку. Зазвичай це спричинено застарілими ключами.", + "uk_UA": "Ryujinx не вдалося проаналізувати прошивку. Зазвичай це спричинено застарілими ключами.", "zh_CN": "Ryujinx 模拟器无法解密当前固件,一般是由于使用了旧版的密钥导致的。", "zh_TW": "Ryujinx 無法解析所提供的韌體。這通常是由於金鑰過時造成的。" } @@ -19017,7 +19037,7 @@ "sv_SE": "Ett odefinierat fel inträffade! Detta ska inte hända. Kontakta en utvecklare!", "th_TH": "เกิดข้อผิดพลาดที่ไม่สามารถระบุได้! สิ่งนี้ไม่ควรเกิดขึ้น โปรดติดต่อผู้พัฒนา!", "tr_TR": "Tanımlanmayan bir hata oluştu! Bu durum ile karşılaşılmamalıydı, lütfen bir geliştirici ile iletişime geçin!", - "uk_UA": "Виникла невизначена помилка! Це не повинно було статися. Будь ласка, зверніться до розробника!", + "uk_UA": "Виникла невизначена помилка! Це не повинно було статися. Будь ласка, зверніться до розробників!", "zh_CN": "出现未定义错误!此类错误不应出现,请联系开发者!", "zh_TW": "發生未定義錯誤! 這種情況不應該發生,請聯絡開發人員!" } @@ -19692,7 +19712,7 @@ "sv_SE": "Din aktuella konfiguration är ogiltig. Öppna inställningarna och konfigurera om din inmatning.", "th_TH": "การกำหนดค่าปัจจุบันของคุณไม่ถูกต้อง กรุณาเปิดการตั้งค่าและกำหนดค่าอินพุตของคุณใหม่", "tr_TR": "Halihazırdaki konfigürasyonunuz geçersiz. Ayarları açın ve girişlerinizi yeniden konfigüre edin.", - "uk_UA": "Поточна конфігурація невірна. Відкрийте налаштування та переналаштуйте Ваші дані.", + "uk_UA": "Поточна конфігурація невірна. Перейдіть до параметрів та переналаштуйте керування.", "zh_CN": "您当前的输入配置无效。打开设置并重新设置您的输入选项。", "zh_TW": "您目前的配置無效。開啟設定並重新配置輸入。" } @@ -19717,7 +19737,7 @@ "sv_SE": "Dockat läge angivet. Handhållna kontroller bör inaktiveras.", "th_TH": "ตั้งค่าด็อกโหมด ควรปิดใช้งานการควบคุมแบบแฮนด์เฮลด์", "tr_TR": "Docked mod ayarlandı. Portatif denetim devre dışı bırakılmalı.", - "uk_UA": "Встановлений режим в док-станції. Вимкніть портативні контролери.", + "uk_UA": "Встановлений режим в док-станції. Вимкніть портативний режим.", "zh_CN": "已经设置为主机模式,应禁用掌机手柄操控。", "zh_TW": "已設定底座模式。手提控制應該停用。" } @@ -23075,26 +23095,26 @@ { "ID": "GraphicsScalingFilterFsr", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "FSR", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, "zh_CN": "FSR(超级分辨率锐画技术)", - "zh_TW": "" + "zh_TW": null } }, { @@ -23442,7 +23462,7 @@ "sv_SE": "Visa ändringslogg", "th_TH": "ด", "tr_TR": "", - "uk_UA": "", + "uk_UA": "Показати список змін", "zh_CN": "查看更新日志", "zh_TW": "檢視更新日誌" } @@ -23575,51 +23595,51 @@ { "ID": "MultiplayerModeLdnMitm", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "ldn_mitm", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { "ID": "MultiplayerModeLdnRyu", "Translations": { - "ar_SA": "", - "de_DE": "", - "el_GR": "", + "ar_SA": null, + "de_DE": null, + "el_GR": null, "en_US": "RyuLDN", - "es_ES": "", - "fr_FR": "", - "he_IL": "", - "it_IT": "", - "ja_JP": "", - "ko_KR": "", - "no_NO": "", - "pl_PL": "", - "pt_BR": "", - "ru_RU": "", - "sv_SE": "", - "th_TH": "", - "tr_TR": "", - "uk_UA": "", - "zh_CN": "", - "zh_TW": "" + "es_ES": null, + "fr_FR": null, + "he_IL": null, + "it_IT": null, + "ja_JP": null, + "ko_KR": null, + "no_NO": null, + "pl_PL": null, + "pt_BR": null, + "ru_RU": null, + "sv_SE": null, + "th_TH": null, + "tr_TR": null, + "uk_UA": null, + "zh_CN": null, + "zh_TW": null } }, { @@ -24817,7 +24837,7 @@ "sv_SE": "Startar och går in i spelet men lider av ett eller flera av följande: kraschar, deadlocks, GPU-buggar, distraherande dåligt ljud eller är helt enkelt för långsamt. Spelet kan fortfarande spelas hela vägen igenom, men inte så som spelet är avsett att spelas.", "th_TH": "", "tr_TR": "", - "uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, її все ще можна пройти, але досвід буде не найкращим.", + "uk_UA": "Запускається, але в грі на вас чекатимуть одна або декілька наступних проблем: збої, зависання, графічні баги, спотворений звук або ж гра загалом працюватиме надто повільно. Можливо, гру все ще можна буде пройти, але досвід буде не найкращим.", "zh_CN": "可以成功启动并进入游戏但可能会遇到以下一种或多种问题: 崩溃、卡死、GPU bug、令人无法接受的音频,或者只是太慢。仍然可以继续进行游戏,但是可能无法达到预期。", "zh_TW": "能啟動並進入遊戲,但可能會遇到下列狀況:崩潰、卡死、GPU bug、令人無法接受的聲音、或遊戲過慢。遊戲或可繼續進行,但是可能無法達到預期效果。" } @@ -24842,7 +24862,7 @@ "sv_SE": "Startar upp och går förbi titelskärmen men tar sig inte in i huvudspelet.", "th_TH": "", "tr_TR": "", - "uk_UA": "Запускається та проходить початковий екран, але пограти не вийде.", + "uk_UA": "Запускається та проходить початковий екран, проте зіграти у вас не вийде.", "zh_CN": "可以启动并通过标题画面但是无法进入到主要的游戏流程。", "zh_TW": "能啟動並通過標題畫面,但是無法進入主要的遊戲畫面。" } @@ -25023,4 +25043,4 @@ } } ] -} +} \ No newline at end of file diff --git a/docs/compatibility.csv b/docs/compatibility.csv index e368cd4f5..567dbe343 100644 --- a/docs/compatibility.csv +++ b/docs/compatibility.csv @@ -2257,6 +2257,7 @@ 010086F0064CE000,"Poi: Explorer Edition",nvdec,playable,2021-01-21 19:32:00 0100EB6012FD2000,"Poison Control",,playable,2021-05-16 14:01:54 010072400E04A000,"Pokémon Café ReMix",,playable,2021-08-17 20:00:04 +010008c01e742000,"Pokémon Friends",crash;services,menus,2025-07-24 13:32:00 01003D200BAA2000,"Pokémon Mystery Dungeon™: Rescue Team DX",mac-bug,playable,2024-01-21 00:16:32 01008DB008C2C000,"Pokémon Shield + Pokémon Shield Expansion Pass",deadlock;crash;online-broken;ldn-works;LAN,ingame,2024-08-12 07:20:22 0100ABF008968000,"Pokémon Sword + Pokémon Sword Expansion Pass",deadlock;crash;online-broken;ldn-works;LAN,ingame,2024-08-26 15:40:37 diff --git a/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs b/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs index 17f9be5a0..a07f0c4ae 100644 --- a/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs +++ b/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs @@ -33,7 +33,7 @@ namespace Ryujinx.BuildValidationTasks LocalesJson json; if (isGitRunner && data.Contains("\r\n")) - throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, build locally to fix..."); + throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, rebuild locally to fix..."); try { @@ -86,7 +86,7 @@ namespace Ryujinx.BuildValidationTasks } if (isGitRunner && encounteredIssue) - throw new JsonException("1 or more locales are invalid!"); + throw new JsonException("1 or more locales are invalid! Rebuild locally to fix..."); string jsonString = JsonSerializer.Serialize(json, _jsonOptions); @@ -102,6 +102,7 @@ namespace Ryujinx.BuildValidationTasks struct LocalesJson { + public Dictionary Info { get; set; } public List Languages { get; set; } public List Locales { get; set; } } diff --git a/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj b/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj index c9fea9313..c89a044b2 100644 --- a/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj +++ b/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj @@ -10,8 +10,18 @@ + Condition="'$(RuntimeIdentifier)' == ''" + IgnoreExitCode="true"> + + + + + + $(OutputOfExec.Substring($(OutputOfExec.IndexOf("Unhandled exception")))) + $(ErrorOutput.Substring(0, $(ErrorOutput.IndexOf(';')))) + + + - \ No newline at end of file + diff --git a/src/Ryujinx.Common/TitleIDs.cs b/src/Ryujinx.Common/TitleIDs.cs index d753caa33..329078af9 100644 --- a/src/Ryujinx.Common/TitleIDs.cs +++ b/src/Ryujinx.Common/TitleIDs.cs @@ -93,6 +93,7 @@ namespace Ryujinx.Common //The Pokémon Franchise "0100f4300bf2c000", // New Pokémon Snap "0100000011d90000", // Pokémon Brilliant Diamond + "010008c01e742000", // Pokémon Friends "01001f5010dfa000", // Pokémon Legends: Arceus "01003d200baa2000", // Pokémon Mystery Dungeon - Rescue Team DX "0100a3d008c5c000", // Pokémon Scarlet diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index 480d14781..881414fb6 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -73,6 +73,7 @@ + diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index 1db2332b8..1a0314bcf 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -14,6 +14,7 @@ using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration.System; +using Ryujinx.Ava.Systems.Starscript; using Ryujinx.Ava.Utilities; using Ryujinx.Common; using Ryujinx.Common.Configuration; @@ -25,6 +26,7 @@ using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Loaders.Npdm; using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Utilities; +using Starscript; using System; using System.Collections.Generic; using System.IO; @@ -41,7 +43,7 @@ using TimeSpan = System.TimeSpan; namespace Ryujinx.Ava.Systems.AppLibrary { - public class ApplicationLibrary + public class ApplicationLibrary : IStarscriptObject { public Language DesiredLanguage { get; set; } public event EventHandler ApplicationCountUpdated; @@ -1611,5 +1613,14 @@ namespace Ryujinx.Ava.Systems.AppLibrary ApplicationData newApplication = newApplications.First(it => it.IdBase == appIdBase); _applications.AddOrUpdate(newApplication); } + + private ValueMap _starscriptMap; + + public ValueMap ToStarscript() + { + _starscriptMap ??= StarscriptHelper.Wrap(this); + + return _starscriptMap; + } } } diff --git a/src/Ryujinx/Systems/Starscript/RyujinxStarscript.cs b/src/Ryujinx/Systems/Starscript/RyujinxStarscript.cs new file mode 100644 index 000000000..0f9a12436 --- /dev/null +++ b/src/Ryujinx/Systems/Starscript/RyujinxStarscript.cs @@ -0,0 +1,29 @@ +using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Common; +using Starscript; + +namespace Ryujinx.Ava.Systems.Starscript +{ + public static class RyujinxStarscript + { + public static readonly StarscriptHypervisor Hypervisor = StarscriptHypervisor.Create().WithStandardLibrary(true); + + static RyujinxStarscript() + { + Hypervisor.Set("ryujinx.releaseChannel", + ReleaseInformation.IsCanaryBuild + ? "Canary" + : ReleaseInformation.IsReleaseBuild + ? "Stable" + : "Custom"); + Hypervisor.Set("ryujinx.version", Program.Version); + Hypervisor.Set("appLibrary", RyujinxApp.MainWindow.ApplicationLibrary); + Hypervisor.Set("currentApplication", () => + RyujinxApp.MainWindow.ApplicationLibrary.FindApplication( + RyujinxApp.MainWindow.ViewModel.AppHost?.ApplicationId ?? 0, + out ApplicationData appData) + ? StarscriptHelper.Wrap(appData) + : Value.Null); + } + } +} diff --git a/src/Ryujinx/Systems/Starscript/StarscriptHelper.cs b/src/Ryujinx/Systems/Starscript/StarscriptHelper.cs new file mode 100644 index 000000000..184b8486f --- /dev/null +++ b/src/Ryujinx/Systems/Starscript/StarscriptHelper.cs @@ -0,0 +1,68 @@ +using Gommon; +using Ryujinx.Ava.Systems.AppLibrary; +using Starscript; +using System; + +namespace Ryujinx.Ava.Systems.Starscript +{ + public static class StarscriptHelper + { + public static ValueMap Wrap(ApplicationLibrary appLib) + { + ValueMap lMap = new(); + lMap.Set("appCount", () => appLib.Applications.Count); + lMap.Set("dlcCount", () => appLib.DownloadableContents.Count); + lMap.Set("updateCount", () => appLib.TitleUpdates.Count); + lMap.Set("has", ctx => + { + ulong titleId; + + try + { + titleId = ctx.Constrain(Constraint.ExactlyOneArgument).NextString(1).ToULong(); + } + catch (FormatException) + { + throw ctx.Error( + $"Invalid input to {ctx.FormattedName}; input must be a hexadecimal number in a string."); + } + + return appLib.FindApplication(titleId, out _); + }); + lMap.Set("get", ctx => + { + ulong titleId; + + try + { + titleId = ctx.Constrain(Constraint.ExactlyOneArgument).NextString(1).ToULong(); + } + catch (FormatException) + { + throw ctx.Error( + $"Invalid input to {ctx.FormattedName}; input must be a hexadecimal number in a string."); + } + + return appLib.FindApplication(titleId, + out ApplicationData applicationData) + ? Wrap(applicationData) + : null; + }); + return lMap; + } + + public static ValueMap Wrap(ApplicationData appData) + { + ValueMap aMap = new(); + aMap.Set("name", appData.Name); + aMap.Set("version", appData.Version); + aMap.Set("developer", appData.Developer); + aMap.Set("fileExtension", appData.FileExtension); + aMap.Set("fileSize", appData.FileSizeString); + aMap.Set("hasLdnGames", appData.HasLdnGames); + aMap.Set("timePlayed", appData.TimePlayedString); + aMap.Set("isFavorite", appData.Favorite); + return aMap; + } + } +} diff --git a/src/Ryujinx/Systems/Starscript/StarscriptTextBox.axaml b/src/Ryujinx/Systems/Starscript/StarscriptTextBox.axaml new file mode 100644 index 000000000..b30dc3eff --- /dev/null +++ b/src/Ryujinx/Systems/Starscript/StarscriptTextBox.axaml @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/src/Ryujinx/Systems/Starscript/StarscriptTextBox.axaml.cs b/src/Ryujinx/Systems/Starscript/StarscriptTextBox.axaml.cs new file mode 100644 index 000000000..5797c3f4a --- /dev/null +++ b/src/Ryujinx/Systems/Starscript/StarscriptTextBox.axaml.cs @@ -0,0 +1,87 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Styling; +using FluentAvalonia.UI.Controls; +using Humanizer; +using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.UI.Controls; +using Ryujinx.Ava.UI.Helpers; +using Starscript; +using Starscript.Internal; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Ryujinx.Ava.Systems.Starscript +{ + public partial class StarscriptTextBox : RyujinxControl + { + public IReadOnlyList CurrentSuggestions => ViewModel.CurrentSuggestions; + + public ParserResult CurrentScriptSource => ViewModel.CurrentScriptSource; + public Exception Exception => ViewModel.Exception; + public Script CurrentScript => ViewModel.CurrentScript; + public StringSegment CurrentScriptResult => ViewModel.CurrentScriptResult; + + public StarscriptTextBox() + { + InitializeComponent(); + + InputBox.AsyncPopulator = GetSuggestionsAsync; + InputBox.MinimumPopulateDelay = 0.Seconds(); + InputBox.TextFilter = (_, _) => true; + InputBox.TextSelector = (text, suggestion) => + { + if (text is not null && suggestion is null) + return text; + if (text is null && suggestion is not null) + return suggestion; + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (text is null && suggestion is null) + return string.Empty; + + var sb = new StringBuilder(text.Length + suggestion.Length + 1); + sb.Append(text); + + for (int i = 0; i < suggestion.Length - 1; i++) + { + if (text.EndsWith(suggestion[..(suggestion.Length - i - 1)])) + { + suggestion = suggestion[(suggestion.Length - i - 1)..]; + break; + } + } + + sb.Append(suggestion); + + return sb.ToString(); + }; + + Style textStyle = new(x => x.OfType().Descendant().OfType()); + textStyle.Setters.Add(new Setter(MarginProperty, new Thickness(0, 0))); + + Styles.Add(textStyle); + } + + private Task> GetSuggestionsAsync(string input, CancellationToken token) + => Task.FromResult(ViewModel.GetSuggestions(input, token)); + + public static StarscriptTextBox Create(StarscriptHypervisor hv) + => new() { ViewModel = new StarscriptTextBoxViewModel(hv) }; + + public static async Task Show() + { + ContentDialog contentDialog = new() + { + PrimaryButtonText = string.Empty, + SecondaryButtonText = string.Empty, + CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose], + Content = new StarscriptTextBox { ViewModel = new() } + }; + + await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles()); + } + } +} diff --git a/src/Ryujinx/Systems/Starscript/StarscriptTextBoxViewModel.cs b/src/Ryujinx/Systems/Starscript/StarscriptTextBoxViewModel.cs new file mode 100644 index 000000000..38c5b3ca3 --- /dev/null +++ b/src/Ryujinx/Systems/Starscript/StarscriptTextBoxViewModel.cs @@ -0,0 +1,126 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using Ryujinx.Ava.UI.ViewModels; +using Starscript; +using Starscript.Internal; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading; + +namespace Ryujinx.Ava.Systems.Starscript +{ + public partial class StarscriptTextBoxViewModel : BaseModel + { + private readonly StarscriptHypervisor _hv; + + public StarscriptTextBoxViewModel(StarscriptHypervisor hv = null) + { + _hv = hv ?? RyujinxStarscript.Hypervisor; + } + + public ObservableCollection CurrentSuggestions { get; } = []; + + [ObservableProperty] private bool _hasError; + [ObservableProperty] private StringSegment _currentScriptResult; + [ObservableProperty] private string _errorMessage; + private Exception _exception; + private ParserResult _currentScriptSource; + private Script _currentScript; + + public Exception Exception + { + get => _exception; + set + { + ErrorMessage = (_exception = value) switch + { + ParseException pe => pe.Error.ToString(), + StarscriptException se => se.Message, + _ => string.Empty + }; + + HasError = value is not null; + + OnPropertyChanged(); + } + } + + public ParserResult CurrentScriptSource + { + get => _currentScriptSource; + set + { + _currentScriptSource = value; + + if (value is null) + { + CurrentScript = null; + CurrentScriptResult = null; + Exception = null; + return; + } + + CurrentScript = Compiler.SingleCompile(value); + Exception = null; + + OnPropertyChanged(); + } + } + + public Script CurrentScript + { + get => _currentScript; + private set + { + try + { + CurrentScriptResult = value?.Execute(_hv)!; + _currentScript = value; + Exception = null; + } + catch (StarscriptException se) + { + _currentScript = null; + CurrentScriptResult = null; + Exception = se; + } + + OnPropertyChanged(); + } + } + + public void ReExecuteScript() + { + if (_currentScript is null) return; + + try + { + CurrentScriptResult = _currentScript.Execute(_hv)!; + } + catch (StarscriptException se) + { + CurrentScriptResult = null; + Exception = se; + } + } + + public IEnumerable GetSuggestions(string input, CancellationToken token) + { + CurrentSuggestions.Clear(); + + CurrentScriptSource = _hv.ParseAndGetCompletions(input, input.Length, CompletionCallback, token); + + if (CurrentScriptSource.HasErrors) + { + Exception = new ParseException(CurrentScriptSource.Errors.First()); + } + + OnPropertyChanged(nameof(CurrentSuggestions)); + + return CurrentSuggestions; + } + + private void CompletionCallback(string result, bool isFunction) => CurrentSuggestions.Add(isFunction ? $"{result}(" : result); + } +} diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml index 1bce31f6d..162997430 100755 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml @@ -253,6 +253,10 @@ Header="{ext:Locale MenuBarHelpAbout}" Icon="{ext:Icon fa-solid fa-circle-info}" ToolTip.Tip="{ext:Locale OpenAboutTooltip}" /> + CompatibilityListWindow.Show()); UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand; + + StarscriptDebugMenuItem.Command = Commands.Create(StarscriptTextBox.Show); FaqMenuItem.Command = SetupGuideMenuItem.Command =