mirror of
https://github.com/modrinth/code.git
synced 2026-07-31 21:26:40 +00:00
Compare commits
77
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb91d5599c | ||
|
|
815d4db8c2 | ||
|
|
a7014a6467 | ||
|
|
5dbba00eb2 | ||
|
|
5ed322d281 | ||
|
|
8591bc8ebc | ||
|
|
01fd18d550 | ||
|
|
3aaa2ef071 | ||
|
|
a3aeeac2c3 | ||
|
|
dfba212be4 | ||
|
|
3877999e53 | ||
|
|
46a7cf490d | ||
|
|
b5f7406998 | ||
|
|
3679d2c786 | ||
|
|
f48a2f64db | ||
|
|
fe80ac10fc | ||
|
|
cf0d260802 | ||
|
|
503d34ee0f | ||
|
|
bfbe66f73b | ||
|
|
64e17c7c1b | ||
|
|
c082594825 | ||
|
|
e5831d38eb | ||
|
|
1cabfe3e85 | ||
|
|
36423eb5b5 | ||
|
|
7d15fd3ac0 | ||
|
|
c1780eef7d | ||
|
|
d2a66bb2b0 | ||
|
|
98b1730e19 | ||
|
|
180cef6eaa | ||
|
|
b828fa17de | ||
|
|
72a4e86c26 | ||
|
|
93f8da1666 | ||
|
|
f474940321 | ||
|
|
83b0586fd2 | ||
|
|
543d25e2d6 | ||
|
|
bc5a761312 | ||
|
|
3258d7dbdf | ||
|
|
b5d1aeda85 | ||
|
|
1cedbe5fda | ||
|
|
2c9bf58d1f | ||
|
|
a92b5b08df | ||
|
|
01d3fb47c4 | ||
|
|
9404d46782 | ||
|
|
926c72de42 | ||
|
|
9729737d7d | ||
|
|
97a8c11b50 | ||
|
|
4d654162eb | ||
|
|
33b1419bdf | ||
|
|
c28ba2e6a4 | ||
|
|
c7ba6ba8b2 | ||
|
|
7366c32df3 | ||
|
|
707e219ff8 | ||
|
|
dfe12d4ecb | ||
|
|
c653228fe7 | ||
|
|
352a196795 | ||
|
|
cef9b1efe5 | ||
|
|
7d6c54cff9 | ||
|
|
bd97ace974 | ||
|
|
58ad58f958 | ||
|
|
d907083d83 | ||
|
|
8371ff641a | ||
|
|
b1cd16f966 | ||
|
|
40a06921ea | ||
|
|
a7dc063e08 | ||
|
|
64b61d8fd0 | ||
|
|
5e7d4cc838 | ||
|
|
a0c80b13a4 | ||
|
|
3c051f5b1d | ||
|
|
940a796ba5 | ||
|
|
6ee5e4df19 | ||
|
|
d61397097c | ||
|
|
cfe45b368c | ||
|
|
6b0a0c1897 | ||
|
|
f27691340a | ||
|
|
c3a58aba9e | ||
|
|
1550dfb3f0 | ||
|
|
4762a0a725 |
@@ -30,6 +30,10 @@ on:
|
||||
- prod-with-staging-archon
|
||||
default: prod
|
||||
required: false
|
||||
app-version-override:
|
||||
description: Temporary app version override for updater testing
|
||||
type: string
|
||||
required: false
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -126,7 +130,10 @@ jobs:
|
||||
- name: Set application version and environment
|
||||
shell: bash
|
||||
run: |
|
||||
APP_VERSION="$(git describe --tags --always | sed -E 's/-([0-9]+)-(g[0-9a-fA-F]+)$/-canary+\1.\2/')"
|
||||
APP_VERSION="${{ inputs.app-version-override }}"
|
||||
if [ -z "$APP_VERSION" ]; then
|
||||
APP_VERSION="$(git describe --tags --always | sed -E 's/-([0-9]+)-(g[0-9a-fA-F]+)$/-canary+\1.\2/')"
|
||||
fi
|
||||
BUILD_ENVIRONMENT="${{ inputs.environment || 'prod' }}"
|
||||
echo "Setting application version to $APP_VERSION"
|
||||
echo "Using environment $BUILD_ENVIRONMENT"
|
||||
@@ -153,7 +160,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Build macOS app
|
||||
run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-dev.conf.json' }}
|
||||
run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || inputs.app-version-override != '') && 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-dev.conf.json' }}
|
||||
if: contains(matrix.platform, 'macos')
|
||||
env:
|
||||
TAURI_BUNDLER_DMG_IGNORE_CI: 'true'
|
||||
@@ -168,7 +175,7 @@ jobs:
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
|
||||
- name: Build Linux app
|
||||
run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json' }}
|
||||
run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || inputs.app-version-override != '') && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json' }}
|
||||
if: contains(matrix.platform, 'ubuntu')
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
@@ -179,7 +186,7 @@ jobs:
|
||||
[System.Convert]::FromBase64String("$env:DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_BASE64") | Set-Content -Path signer-client-cert.p12 -AsByteStream
|
||||
$env:DIGICERT_ONE_SIGNER_CREDENTIALS = "$env:DIGICERT_ONE_SIGNER_API_KEY|$PWD\signer-client-cert.p12|$env:DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD"
|
||||
$env:JAVA_HOME = "$env:JAVA_HOME_17_X64"
|
||||
${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles "nsis,updater"' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json --verbose --bundles "nsis,updater"' }}
|
||||
${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || inputs.app-version-override != '') && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles "nsis,updater"' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json --verbose --bundles "nsis,updater"' }}
|
||||
Remove-Item -Path signer-client-cert.p12 -ErrorAction SilentlyContinue
|
||||
if: contains(matrix.platform, 'windows')
|
||||
env:
|
||||
|
||||
@@ -57,8 +57,11 @@ jobs:
|
||||
|
||||
- name: Extract app changelog
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
VERSION: ${{ env.VERSION_TAG }}
|
||||
run: npx --yes tsx scripts/build-theseus-release-notes.ts
|
||||
run: |
|
||||
LAST_GITHUB_RELEASE_PUBLISHED_AT=$(gh api "repos/${{ github.repository }}/releases/latest" --jq '.published_at // ""' 2>/dev/null || true)
|
||||
LAST_GITHUB_RELEASE_PUBLISHED_AT="$LAST_GITHUB_RELEASE_PUBLISHED_AT" npx --yes tsx scripts/build-theseus-release-notes.ts
|
||||
|
||||
- name: Generate version manifest
|
||||
run: |
|
||||
|
||||
@@ -22,6 +22,7 @@ node_modules
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/i18n-ally-custom-framework.yml
|
||||
|
||||
# IDE - IntelliJ
|
||||
.idea/*
|
||||
|
||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"recommendations": ["esbenp.prettier-vscode", "Vue.volar", "rust-lang.rust-analyzer"]
|
||||
"recommendations": ["esbenp.prettier-vscode", "Vue.volar", "rust-lang.rust-analyzer", "lokalise.i18n-ally"]
|
||||
}
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
languageIds:
|
||||
- vue
|
||||
- typescript
|
||||
- javascript
|
||||
- typescriptreact
|
||||
|
||||
usageMatchRegex:
|
||||
- id:\s*['"]({key})['"]
|
||||
|
||||
monopoly: true
|
||||
Vendored
+12
-2
@@ -9,7 +9,7 @@
|
||||
"files.insertFinalNewline": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "always"
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[vue]": {
|
||||
@@ -31,5 +31,15 @@
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||
},
|
||||
"css.lint.unknownAtRules": "ignore",
|
||||
"scss.lint.unknownAtRules": "ignore"
|
||||
"scss.lint.unknownAtRules": "ignore",
|
||||
"i18n-ally.localesPaths": [
|
||||
"packages/ui/src/locales",
|
||||
"apps/frontend/src/locales",
|
||||
"packages/moderation/src/locales"
|
||||
],
|
||||
"i18n-ally.pathMatcher": "{locale}/index.{ext}",
|
||||
"i18n-ally.keystyle": "flat",
|
||||
"i18n-ally.sourceLanguage": "en-US",
|
||||
"i18n-ally.namespace": false,
|
||||
"i18n-ally.includeSubfolders": true
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ The website and app `prepr` commands
|
||||
|
||||
Each project may have its own `CLAUDE.md` with detailed instructions:
|
||||
|
||||
- [`apps/labrinth/CLAUDE.md`](apps/labrinth/CLAUDE.md) — Backend API
|
||||
- [`apps/labrinth/AGENTS.md`](apps/labrinth/AGENTS.md) — Backend API
|
||||
- [`apps/frontend/CLAUDE.md`](apps/frontend/CLAUDE.md) - Frontend Website
|
||||
|
||||
## Code Guidelines
|
||||
|
||||
Generated
+60
-19
@@ -1378,7 +1378,7 @@ dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools 0.12.1",
|
||||
"itertools 0.13.0",
|
||||
"log",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
@@ -2927,7 +2927,7 @@ version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
|
||||
dependencies = [
|
||||
"libloading 0.7.4",
|
||||
"libloading 0.8.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3260,7 +3260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4577,7 +4577,7 @@ dependencies = [
|
||||
"libc",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.10",
|
||||
"socket2 0.6.1",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
@@ -4817,7 +4817,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.16.0",
|
||||
"hashbrown 0.15.5",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
@@ -4974,7 +4974,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
||||
dependencies = [
|
||||
"hermit-abi 0.5.2",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5439,7 +5439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.48.5",
|
||||
"windows-targets 0.53.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7701,7 +7701,7 @@ dependencies = [
|
||||
"quinn-udp",
|
||||
"rustc-hash",
|
||||
"rustls 0.23.32",
|
||||
"socket2 0.5.10",
|
||||
"socket2 0.6.1",
|
||||
"thiserror 2.0.17",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@@ -7738,9 +7738,9 @@ dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2 0.5.10",
|
||||
"socket2 0.6.1",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8159,15 +8159,20 @@ dependencies = [
|
||||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.7.0",
|
||||
"hyper-rustls 0.27.7",
|
||||
"hyper-util",
|
||||
"js-sys",
|
||||
"log",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls 0.23.32",
|
||||
"rustls-pki-types",
|
||||
"rustls-platform-verifier",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
@@ -8413,7 +8418,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8426,7 +8431,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.11.0",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8509,6 +8514,33 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-platform-verifier"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
|
||||
dependencies = [
|
||||
"core-foundation 0.10.1",
|
||||
"core-foundation-sys",
|
||||
"jni",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls 0.23.32",
|
||||
"rustls-native-certs 0.8.1",
|
||||
"rustls-platform-verifier-android",
|
||||
"rustls-webpki 0.103.7",
|
||||
"security-framework 3.5.1",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-platform-verifier-android"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.101.7"
|
||||
@@ -9654,7 +9686,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"psm",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
@@ -10264,9 +10295,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-updater"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27cbc31740f4d507712550694749572ec0e43bdd66992db7599b89fbfd6b167b"
|
||||
version = "2.10.1"
|
||||
source = "git+https://github.com/modrinth/plugins-workspace?rev=0d30f2aa28ec668ce187d527da1c475da3c01cbc#0d30f2aa28ec668ce187d527da1c475da3c01cbc"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"dirs",
|
||||
@@ -10278,7 +10308,8 @@ dependencies = [
|
||||
"minisign-verify",
|
||||
"osakit",
|
||||
"percent-encoding",
|
||||
"reqwest 0.12.24",
|
||||
"reqwest 0.13.2",
|
||||
"rustls 0.23.32",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -10419,7 +10450,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.1.2",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10514,6 +10545,7 @@ dependencies = [
|
||||
"flate2",
|
||||
"fs4",
|
||||
"futures",
|
||||
"futures-lite 2.6.1",
|
||||
"heck 0.5.0",
|
||||
"hickory-resolver 0.25.2",
|
||||
"indicatif",
|
||||
@@ -11956,6 +11988,15 @@ dependencies = [
|
||||
"libwebp-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-root-certs"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.11"
|
||||
@@ -12077,7 +12118,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+2
-1
@@ -85,6 +85,7 @@ eyre = "0.6.12"
|
||||
flate2 = "1.1.4"
|
||||
fs4 = { version = "0.13.1", default-features = false }
|
||||
futures = "0.3.31"
|
||||
futures-lite = "2.6.1"
|
||||
futures-util = "0.3.31"
|
||||
heck = "0.5.0"
|
||||
hex = "0.4.3"
|
||||
@@ -191,7 +192,7 @@ tauri-plugin-http = "2.5.7"
|
||||
tauri-plugin-opener = "2.5.0"
|
||||
tauri-plugin-os = "2.3.1"
|
||||
tauri-plugin-single-instance = "2.3.4"
|
||||
tauri-plugin-updater = { version = "2.9.0", default-features = false, features = [
|
||||
tauri-plugin-updater = { git = "https://github.com/modrinth/plugins-workspace", rev = "0d30f2aa28ec668ce187d527da1c475da3c01cbc", default-features = false, features = [
|
||||
"rustls-tls",
|
||||
"zip",
|
||||
] }
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^10.0.0",
|
||||
"vue-router": "^4.6.0",
|
||||
"vue-virtual-scroller": "v2.0.0-beta.8"
|
||||
"vue-virtual-scroller": "v2.0.0-beta.8",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.1.1",
|
||||
|
||||
+281
-118
@@ -12,7 +12,6 @@ import {
|
||||
ArrowBigUpDashIcon,
|
||||
ChangeSkinIcon,
|
||||
CompassIcon,
|
||||
DownloadIcon,
|
||||
ExternalIcon,
|
||||
HomeIcon,
|
||||
LeftArrowIcon,
|
||||
@@ -36,6 +35,7 @@ import {
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
ContentInstallModal,
|
||||
ContentUpdaterModal,
|
||||
CreationFlowModal,
|
||||
defineMessages,
|
||||
I18nDebugPanel,
|
||||
@@ -44,7 +44,6 @@ import {
|
||||
NotificationPanel,
|
||||
OverflowMenu,
|
||||
PopupNotificationPanel,
|
||||
ProgressSpinner,
|
||||
provideModalBehavior,
|
||||
provideModrinthClient,
|
||||
provideNotificationManager,
|
||||
@@ -75,7 +74,6 @@ import Breadcrumbs from '@/components/ui/Breadcrumbs.vue'
|
||||
import ErrorModal from '@/components/ui/ErrorModal.vue'
|
||||
import FriendsList from '@/components/ui/friends/FriendsList.vue'
|
||||
import AddServerToInstanceModal from '@/components/ui/install_flow/AddServerToInstanceModal.vue'
|
||||
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
|
||||
import UnknownPackWarningModal from '@/components/ui/install_flow/UnknownPackWarningModal.vue'
|
||||
import MinecraftAuthErrorModal from '@/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue'
|
||||
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
|
||||
@@ -95,7 +93,7 @@ import { hide_ads_window, init_ads_window, show_ads_window } from '@/helpers/ads
|
||||
import { debugAnalytics, initAnalytics, trackEvent } from '@/helpers/analytics'
|
||||
import { check_reachable } from '@/helpers/auth.js'
|
||||
import { get_user, get_version } from '@/helpers/cache.js'
|
||||
import { command_listener, warning_listener } from '@/helpers/events.js'
|
||||
import { command_listener, notification_listener, warning_listener } from '@/helpers/events.js'
|
||||
import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.ts'
|
||||
import { create_profile_and_install_from_file } from '@/helpers/pack'
|
||||
import { list } from '@/helpers/profile.js'
|
||||
@@ -113,6 +111,16 @@ import {
|
||||
setRestartAfterPendingUpdate,
|
||||
} from '@/helpers/utils.js'
|
||||
import i18n from '@/i18n.config'
|
||||
import {
|
||||
appUpdateState,
|
||||
downloadAvailableAppUpdate,
|
||||
getNextAppUpdatePopupTime,
|
||||
installAvailableAppUpdate,
|
||||
markAppUpdateActionable,
|
||||
markAppUpdatePopupShown,
|
||||
openAppUpdateChangelog,
|
||||
setAppUpdateActions,
|
||||
} from '@/providers/app-update.ts'
|
||||
import { createContentInstall, provideContentInstall } from '@/providers/content-install'
|
||||
import {
|
||||
provideAppUpdateDownloadProgress,
|
||||
@@ -241,6 +249,7 @@ const {
|
||||
|
||||
const news = ref([])
|
||||
const availableSurvey = ref(false)
|
||||
const displayedServerInviteNotifications = new Set()
|
||||
|
||||
const offline = ref(!navigator.onLine)
|
||||
window.addEventListener('offline', () => {
|
||||
@@ -296,6 +305,7 @@ onUnmounted(async () => {
|
||||
document.querySelector('body').removeEventListener('click', handleClick)
|
||||
document.querySelector('body').removeEventListener('auxclick', handleAuxClick)
|
||||
unsubscribeSidebarToggle()
|
||||
clearDelayedUpdatePopup()
|
||||
|
||||
await unlistenUpdateDownload?.()
|
||||
})
|
||||
@@ -312,18 +322,6 @@ const messages = defineMessages({
|
||||
id: 'app.update.complete-toast.text',
|
||||
defaultMessage: 'Click here to view the changelog.',
|
||||
},
|
||||
reloadToUpdate: {
|
||||
id: 'app.update.reload-to-update',
|
||||
defaultMessage: 'Reload to install update',
|
||||
},
|
||||
downloadUpdate: {
|
||||
id: 'app.update.download-update',
|
||||
defaultMessage: 'Download update',
|
||||
},
|
||||
downloadingUpdate: {
|
||||
id: 'app.update.downloading-update',
|
||||
defaultMessage: 'Downloading update ({percent}%)',
|
||||
},
|
||||
authUnreachableHeader: {
|
||||
id: 'app.auth-servers.unreachable.header',
|
||||
defaultMessage: 'Cannot reach authentication servers',
|
||||
@@ -611,6 +609,16 @@ const {
|
||||
handleModpackDuplicateCreateAnyway: handleContentInstallModpackDuplicateCreateAnyway,
|
||||
handleModpackDuplicateGoToInstance: handleContentInstallModpackDuplicateGoToInstance,
|
||||
setIncompatibilityWarningModal: setContentIncompatibilityWarningModal,
|
||||
incompatibilityWarningVersions: contentInstallIncompatibilityWarningVersions,
|
||||
incompatibilityWarningCurrentGameVersion: contentInstallIncompatibilityWarningCurrentGameVersion,
|
||||
incompatibilityWarningCurrentLoader: contentInstallIncompatibilityWarningCurrentLoader,
|
||||
incompatibilityWarningProjectType: contentInstallIncompatibilityWarningProjectType,
|
||||
incompatibilityWarningProjectIconUrl: contentInstallIncompatibilityWarningProjectIconUrl,
|
||||
incompatibilityWarningProjectName: contentInstallIncompatibilityWarningProjectName,
|
||||
incompatibilityWarningMessage: contentInstallIncompatibilityWarningMessage,
|
||||
incompatibilityWarningInstalling: contentInstallIncompatibilityWarningInstalling,
|
||||
handleIncompatibilityWarningInstall: handleContentInstallIncompatibilityWarningInstall,
|
||||
handleIncompatibilityWarningCancel: handleContentInstallIncompatibilityWarningCancel,
|
||||
} = contentInstall
|
||||
|
||||
const serverInstall = createServerInstall({ router, handleError, popupNotificationManager })
|
||||
@@ -632,6 +640,12 @@ const updateToPlayModal = ref()
|
||||
|
||||
const modrinthLoginFlowWaitModal = ref()
|
||||
|
||||
watch(incompatibilityWarningModal, (modal) => {
|
||||
if (modal) {
|
||||
setContentIncompatibilityWarningModal(modal)
|
||||
}
|
||||
})
|
||||
|
||||
setupAuthProvider(credentials, async (_redirectPath) => {
|
||||
await signIn()
|
||||
})
|
||||
@@ -752,6 +766,86 @@ const accounts = ref(null)
|
||||
provide('accountsCard', accounts)
|
||||
|
||||
command_listener(handleCommand)
|
||||
notification_listener(handleLiveNotification)
|
||||
|
||||
async function markLiveNotificationRead(notification) {
|
||||
try {
|
||||
await tauriApiClient.labrinth.notifications_v2.markAsRead(notification.id)
|
||||
} catch (error) {
|
||||
if (error instanceof ModrinthApiError && error.statusCode === 404) {
|
||||
console.warn(`notification ${notification.id} could not be marked as read`, error)
|
||||
return
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function respondToServerInvite(notification, action) {
|
||||
const serverId = notification.body?.server_id
|
||||
if (typeof serverId !== 'string') {
|
||||
throw new Error('Missing server ID for invite notification.')
|
||||
}
|
||||
|
||||
await tauriApiClient.request(`/servers/${serverId}/invites/${action}`, {
|
||||
api: 'archon',
|
||||
version: 1,
|
||||
method: 'POST',
|
||||
})
|
||||
await markLiveNotificationRead(notification)
|
||||
|
||||
return serverId
|
||||
}
|
||||
|
||||
async function acceptServerInviteNotification(notification) {
|
||||
try {
|
||||
const serverId = await respondToServerInvite(notification, 'accept')
|
||||
await router.push(`/hosting/manage/${encodeURIComponent(serverId)}`)
|
||||
queryClient.invalidateQueries({ queryKey: ['servers'] })
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function declineServerInviteNotification(notification) {
|
||||
try {
|
||||
await respondToServerInvite(notification, 'decline')
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
}
|
||||
}
|
||||
|
||||
function openServerInviteInviterProfile(inviterName) {
|
||||
if (!inviterName) return
|
||||
openUrl(`${config.siteUrl}/user/${encodeURIComponent(inviterName)}`)
|
||||
}
|
||||
|
||||
async function handleLiveNotification(notification) {
|
||||
if (notification?.body?.type !== 'server_invite' || notification.read) return
|
||||
if (displayedServerInviteNotifications.has(notification.id)) return
|
||||
|
||||
displayedServerInviteNotifications.add(notification.id)
|
||||
|
||||
const serverName =
|
||||
typeof notification.body.server_name === 'string' ? notification.body.server_name : 'a server'
|
||||
const inviterId = notification.body.invited_by
|
||||
const invitedBy =
|
||||
typeof inviterId === 'string' ? await get_user(inviterId, 'bypass').catch(() => null) : null
|
||||
|
||||
addPopupNotification({
|
||||
title: serverName,
|
||||
autoCloseMs: null,
|
||||
toast: {
|
||||
type: 'server-invite',
|
||||
actorName: invitedBy?.username ?? null,
|
||||
actorAvatarUrl: invitedBy?.avatar_url ?? null,
|
||||
entityName: serverName,
|
||||
onAccept: () => acceptServerInviteNotification(notification),
|
||||
onDecline: () => declineServerInviteNotification(notification),
|
||||
onOpenActor: () => openServerInviteInviterProfile(invitedBy?.username ?? null),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function handleCommand(e) {
|
||||
if (!e) return
|
||||
|
||||
@@ -785,20 +879,21 @@ async function handleCommand(e) {
|
||||
}
|
||||
|
||||
const appUpdateDownload = {
|
||||
progress: ref(0),
|
||||
progress: appUpdateState.progress,
|
||||
version: ref(),
|
||||
}
|
||||
let unlistenUpdateDownload
|
||||
|
||||
const downloadProgress = computed(() => appUpdateDownload.progress.value)
|
||||
const downloadPercent = computed(() => Math.trunc(appUpdateDownload.progress.value * 100))
|
||||
|
||||
const metered = ref(true)
|
||||
const finishedDownloading = ref(false)
|
||||
const restarting = ref(false)
|
||||
const availableUpdate = ref(null)
|
||||
const updateSize = ref(null)
|
||||
const updatesEnabled = ref(true)
|
||||
const {
|
||||
metered,
|
||||
finishedDownloading,
|
||||
downloading,
|
||||
restarting,
|
||||
availableUpdate,
|
||||
updateSize,
|
||||
updatesEnabled,
|
||||
} = appUpdateState
|
||||
let delayedUpdatePopupTimeout = null
|
||||
|
||||
const updatePopupMessages = defineMessages({
|
||||
updateAvailable: {
|
||||
@@ -809,11 +904,6 @@ const updatePopupMessages = defineMessages({
|
||||
id: 'app.update-popup.download-complete',
|
||||
defaultMessage: 'Download complete',
|
||||
},
|
||||
body: {
|
||||
id: 'app.update-popup.body',
|
||||
defaultMessage:
|
||||
'Modrinth App v{version} is ready to install! Reload to update now, or automatically when you close Modrinth App.',
|
||||
},
|
||||
meteredBody: {
|
||||
id: 'app.update-popup.body.metered',
|
||||
defaultMessage: `Modrinth App v{version} is available now! Since you're on a metered network, we didn't automatically download it.`,
|
||||
@@ -829,7 +919,7 @@ const updatePopupMessages = defineMessages({
|
||||
},
|
||||
reload: {
|
||||
id: 'app.update-popup.reload',
|
||||
defaultMessage: 'Reload',
|
||||
defaultMessage: 'Reload to update',
|
||||
},
|
||||
download: {
|
||||
id: 'app.update-popup.download',
|
||||
@@ -841,6 +931,106 @@ const updatePopupMessages = defineMessages({
|
||||
},
|
||||
})
|
||||
|
||||
function clearDelayedUpdatePopup() {
|
||||
if (delayedUpdatePopupTimeout !== null) {
|
||||
clearTimeout(delayedUpdatePopupTimeout)
|
||||
delayedUpdatePopupTimeout = null
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentUpdatePromptStage() {
|
||||
return finishedDownloading.value ? 'downloaded' : 'available'
|
||||
}
|
||||
|
||||
function scheduleDelayedUpdatePopup() {
|
||||
clearDelayedUpdatePopup()
|
||||
|
||||
const version = availableUpdate.value?.version
|
||||
if (!version) {
|
||||
return
|
||||
}
|
||||
|
||||
const nextPopupTime = getNextAppUpdatePopupTime(version, getCurrentUpdatePromptStage())
|
||||
if (nextPopupTime === null) {
|
||||
return
|
||||
}
|
||||
|
||||
const delay = nextPopupTime - Date.now()
|
||||
if (delay <= 0) {
|
||||
showDelayedUpdatePopup()
|
||||
return
|
||||
}
|
||||
|
||||
delayedUpdatePopupTimeout = setTimeout(showDelayedUpdatePopup, Math.min(delay, 2_147_483_647))
|
||||
}
|
||||
|
||||
function showDelayedUpdatePopup() {
|
||||
const update = availableUpdate.value
|
||||
if (!update) {
|
||||
return
|
||||
}
|
||||
|
||||
const stage = getCurrentUpdatePromptStage()
|
||||
const nextPopupTime = getNextAppUpdatePopupTime(update.version, stage)
|
||||
if (nextPopupTime === null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Date.now() < nextPopupTime) {
|
||||
scheduleDelayedUpdatePopup()
|
||||
return
|
||||
}
|
||||
|
||||
if (metered.value && !finishedDownloading.value) {
|
||||
addPopupNotification({
|
||||
title: formatMessage(updatePopupMessages.updateAvailable),
|
||||
text: formatMessage(updatePopupMessages.meteredBody, { version: update.version }),
|
||||
type: 'info',
|
||||
autoCloseMs: null,
|
||||
buttons: [
|
||||
{
|
||||
label: formatMessage(updatePopupMessages.download, {
|
||||
size: formatBytes(updateSize.value ?? 0),
|
||||
}),
|
||||
action: () => downloadAvailableAppUpdate(),
|
||||
color: 'brand',
|
||||
},
|
||||
{
|
||||
label: formatMessage(updatePopupMessages.changelog),
|
||||
action: () => openAppUpdateChangelog(),
|
||||
keepOpen: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if (finishedDownloading.value) {
|
||||
addPopupNotification({
|
||||
title: formatMessage(updatePopupMessages.downloadComplete),
|
||||
text: formatMessage(updatePopupMessages.downloadedBody, {
|
||||
version: update.version,
|
||||
}),
|
||||
type: 'success',
|
||||
autoCloseMs: null,
|
||||
buttons: [
|
||||
{
|
||||
label: formatMessage(updatePopupMessages.reload),
|
||||
action: () => installAvailableAppUpdate(),
|
||||
color: 'brand',
|
||||
},
|
||||
{
|
||||
label: formatMessage(updatePopupMessages.changelog),
|
||||
action: () => openAppUpdateChangelog(),
|
||||
keepOpen: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
} else {
|
||||
scheduleDelayedUpdatePopup()
|
||||
return
|
||||
}
|
||||
|
||||
markAppUpdatePopupShown(update.version, stage)
|
||||
}
|
||||
|
||||
async function checkUpdates() {
|
||||
if (!(await areUpdatesEnabled())) {
|
||||
console.log('Skipping update check as updates are disabled in this build or environment')
|
||||
@@ -864,11 +1054,15 @@ async function checkUpdates() {
|
||||
|
||||
if (isExistingUpdate) {
|
||||
console.log('Update is already known')
|
||||
scheduleDelayedUpdatePopup()
|
||||
return
|
||||
}
|
||||
|
||||
appUpdateDownload.progress.value = 0
|
||||
finishedDownloading.value = false
|
||||
downloading.value = false
|
||||
updateSize.value = null
|
||||
availableUpdate.value = update
|
||||
|
||||
console.log(`Update ${update.version} is available.`)
|
||||
|
||||
@@ -878,34 +1072,11 @@ async function checkUpdates() {
|
||||
downloadUpdate(update)
|
||||
} else {
|
||||
console.log(`Metered connection detected, not auto-downloading update.`)
|
||||
getUpdateSize(update.rid).then((size) => {
|
||||
updateSize.value = size
|
||||
addPopupNotification({
|
||||
title: formatMessage(updatePopupMessages.updateAvailable),
|
||||
text: formatMessage(updatePopupMessages.meteredBody, { version: update.version }),
|
||||
type: 'info',
|
||||
autoCloseMs: null,
|
||||
buttons: [
|
||||
{
|
||||
label: formatMessage(updatePopupMessages.download, {
|
||||
size: formatBytes(updateSize.value ?? 0),
|
||||
}),
|
||||
action: () => downloadAvailableUpdate(),
|
||||
color: 'brand',
|
||||
},
|
||||
{
|
||||
label: formatMessage(updatePopupMessages.changelog),
|
||||
action: () => openUrl('https://modrinth.com/news/changelog?filter=app'),
|
||||
keepOpen: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
markAppUpdateActionable(update.version)
|
||||
scheduleDelayedUpdatePopup()
|
||||
}
|
||||
|
||||
getUpdateSize(update.rid).then((size) => (updateSize.value = size))
|
||||
|
||||
availableUpdate.value = update
|
||||
}
|
||||
|
||||
await performCheck()
|
||||
@@ -927,12 +1098,17 @@ async function checkLinuxUpdates() {
|
||||
const latestVersion = updates?.version
|
||||
|
||||
if (latestVersion && latestVersion !== currentVersion) {
|
||||
addPopupNotification({
|
||||
title: formatMessage(updatePopupMessages.updateAvailable),
|
||||
text: formatMessage(updatePopupMessages.linuxBody, { version: latestVersion }),
|
||||
type: 'info',
|
||||
autoCloseMs: null,
|
||||
})
|
||||
markAppUpdateActionable(latestVersion)
|
||||
const nextPopupTime = getNextAppUpdatePopupTime(latestVersion)
|
||||
if (nextPopupTime !== null && Date.now() >= nextPopupTime) {
|
||||
addPopupNotification({
|
||||
title: formatMessage(updatePopupMessages.updateAvailable),
|
||||
text: formatMessage(updatePopupMessages.linuxBody, { version: latestVersion }),
|
||||
type: 'info',
|
||||
autoCloseMs: null,
|
||||
})
|
||||
markAppUpdatePopupShown(latestVersion)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to check for updates:', e)
|
||||
@@ -946,55 +1122,48 @@ async function downloadAvailableUpdate() {
|
||||
async function downloadUpdate(versionToDownload) {
|
||||
if (!versionToDownload) {
|
||||
handleError(`Failed to download update: no version available`)
|
||||
return
|
||||
}
|
||||
|
||||
if (appUpdateDownload.progress.value !== 0) {
|
||||
if (downloading.value || appUpdateDownload.progress.value !== 0) {
|
||||
console.error(`Update ${versionToDownload.version} already downloading`)
|
||||
return
|
||||
}
|
||||
|
||||
console.log(`Downloading update ${versionToDownload.version}`)
|
||||
downloading.value = true
|
||||
|
||||
try {
|
||||
enqueueUpdateForInstallation(versionToDownload.rid).then(() => {
|
||||
finishedDownloading.value = true
|
||||
unlistenUpdateDownload?.().then(() => {
|
||||
unlistenUpdateDownload = null
|
||||
enqueueUpdateForInstallation(versionToDownload.rid)
|
||||
.then(() => {
|
||||
downloading.value = false
|
||||
finishedDownloading.value = true
|
||||
unlistenUpdateDownload?.().then(() => {
|
||||
unlistenUpdateDownload = null
|
||||
})
|
||||
console.log('Finished downloading!')
|
||||
markAppUpdateActionable(versionToDownload.version, 'downloaded')
|
||||
scheduleDelayedUpdatePopup()
|
||||
})
|
||||
console.log('Finished downloading!')
|
||||
|
||||
addPopupNotification({
|
||||
title: formatMessage(updatePopupMessages.downloadComplete),
|
||||
text: formatMessage(updatePopupMessages.downloadedBody, {
|
||||
version: versionToDownload.version,
|
||||
}),
|
||||
type: 'success',
|
||||
autoCloseMs: null,
|
||||
buttons: [
|
||||
{
|
||||
label: formatMessage(updatePopupMessages.reload),
|
||||
action: () => installUpdate(),
|
||||
color: 'brand',
|
||||
},
|
||||
{
|
||||
label: formatMessage(updatePopupMessages.changelog),
|
||||
action: () => openUrl('https://modrinth.com/news/changelog?filter=app'),
|
||||
keepOpen: true,
|
||||
},
|
||||
],
|
||||
.catch((e) => {
|
||||
downloading.value = false
|
||||
appUpdateDownload.progress.value = 0
|
||||
handleError(e)
|
||||
})
|
||||
})
|
||||
unlistenUpdateDownload = await subscribeToDownloadProgress(
|
||||
appUpdateDownload,
|
||||
versionToDownload.version,
|
||||
)
|
||||
} catch (e) {
|
||||
downloading.value = false
|
||||
appUpdateDownload.progress.value = 0
|
||||
handleError(e)
|
||||
}
|
||||
}
|
||||
|
||||
async function installUpdate() {
|
||||
restarting.value = true
|
||||
|
||||
try {
|
||||
await setRestartAfterPendingUpdate(true)
|
||||
} catch (e) {
|
||||
@@ -1007,6 +1176,12 @@ async function installUpdate() {
|
||||
}, 250)
|
||||
}
|
||||
|
||||
setAppUpdateActions({
|
||||
download: downloadAvailableUpdate,
|
||||
install: installUpdate,
|
||||
changelog: () => openUrl('https://modrinth.com/news/changelog?filter=app'),
|
||||
})
|
||||
|
||||
async function openModrinthProjectLinkInApp(parsed) {
|
||||
const { slug, pathSuffix, url } = parsed
|
||||
const loadToken = loading.begin()
|
||||
@@ -1276,33 +1451,6 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
|
||||
<PlusIcon />
|
||||
</NavButton>
|
||||
<div class="flex flex-grow"></div>
|
||||
<Transition name="nav-button-animated">
|
||||
<div v-if="availableUpdate && !restarting && (finishedDownloading || metered)">
|
||||
<NavButton
|
||||
v-tooltip.right="
|
||||
formatMessage(
|
||||
finishedDownloading
|
||||
? messages.reloadToUpdate
|
||||
: downloadProgress === 0
|
||||
? messages.downloadUpdate
|
||||
: messages.downloadingUpdate,
|
||||
{
|
||||
percent: downloadPercent,
|
||||
},
|
||||
)
|
||||
"
|
||||
:to="finishedDownloading ? installUpdate : downloadAvailableUpdate"
|
||||
>
|
||||
<ProgressSpinner
|
||||
v-if="downloadProgress > 0 && downloadProgress < 1"
|
||||
class="text-brand"
|
||||
:progress="downloadProgress"
|
||||
/>
|
||||
<RefreshCwIcon v-else-if="finishedDownloading" class="text-brand" />
|
||||
<DownloadIcon v-else class="text-brand" />
|
||||
</NavButton>
|
||||
</div>
|
||||
</Transition>
|
||||
<NavButton
|
||||
v-tooltip.right="formatMessage(commonMessages.settingsLabel)"
|
||||
:to="() => $refs.settingsModal.show()"
|
||||
@@ -1550,7 +1698,22 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
|
||||
@go-to-instance="handleModpackDuplicateGoToInstance"
|
||||
/>
|
||||
<AddServerToInstanceModal ref="addServerToInstanceModal" />
|
||||
<IncompatibilityWarningModal ref="incompatibilityWarningModal" />
|
||||
<ContentUpdaterModal
|
||||
ref="incompatibilityWarningModal"
|
||||
mode="incompatibility-warning"
|
||||
:versions="contentInstallIncompatibilityWarningVersions"
|
||||
:current-game-version="contentInstallIncompatibilityWarningCurrentGameVersion"
|
||||
:current-loader="contentInstallIncompatibilityWarningCurrentLoader"
|
||||
current-version-id=""
|
||||
:is-app="true"
|
||||
:project-type="contentInstallIncompatibilityWarningProjectType"
|
||||
:project-icon-url="contentInstallIncompatibilityWarningProjectIconUrl"
|
||||
:project-name="contentInstallIncompatibilityWarningProjectName"
|
||||
:warning="contentInstallIncompatibilityWarningMessage"
|
||||
:action-loading="contentInstallIncompatibilityWarningInstalling"
|
||||
@update="handleContentInstallIncompatibilityWarningInstall"
|
||||
@cancel="handleContentInstallIncompatibilityWarningCancel"
|
||||
/>
|
||||
<ModpackAlreadyInstalledModal
|
||||
ref="contentInstallModpackAlreadyInstalledModal"
|
||||
@create-anyway="handleContentInstallModpackDuplicateCreateAnyway"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="flex gap-4 items-center">
|
||||
<div class="flex gap-2 items-center">
|
||||
<ButtonStyled
|
||||
v-if="hasActiveLoadingBars && !hasVisibleActiveDownloadToasts"
|
||||
color="brand"
|
||||
@@ -14,6 +14,31 @@
|
||||
<UnplugIcon class="text-secondary" />
|
||||
<span class="text-sm text-contrast"> {{ formatMessage(messages.offline) }} </span>
|
||||
</div>
|
||||
<ButtonStyled color="brand" type="outlined" hover-color-fill="background">
|
||||
<button
|
||||
v-if="showUpdatePill"
|
||||
type="button"
|
||||
class="!h-[34px] overflow-hidden text-sm !transition-[width,opacity,transform,background-color,color,filter] !duration-200 ease-out"
|
||||
:class="[
|
||||
updatePillWidthClass,
|
||||
{
|
||||
'update-pill-ready-hidden': finishedDownloading && !animateReadyPill,
|
||||
'update-pill-ready-visible': finishedDownloading && animateReadyPill,
|
||||
},
|
||||
]"
|
||||
:disabled="isUpdateDownloading"
|
||||
:aria-busy="isUpdateDownloading"
|
||||
@click="handleUpdateClick"
|
||||
>
|
||||
<RefreshCwIcon v-if="finishedDownloading" :class="{ 'animate-spin': restarting }" />
|
||||
<DownloadIcon v-else />
|
||||
<span v-if="isUpdateDownloading">
|
||||
{{ formatMessage(messages.downloadingUpdate) }}
|
||||
<span class="inline-block w-[3ch] text-right tabular-nums">{{ downloadPercent }}%</span>
|
||||
</span>
|
||||
<span v-else>{{ updateLabel }}</span>
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<div
|
||||
class="flex border-solid border-surface-5 text-sm items-center gap-2 py-1.5 px-3 rounded-xl border"
|
||||
>
|
||||
@@ -119,6 +144,7 @@ import {
|
||||
DownloadIcon,
|
||||
DropdownIcon,
|
||||
OnlineIndicatorIcon,
|
||||
RefreshCwIcon,
|
||||
StarIcon,
|
||||
StopCircleIcon,
|
||||
TerminalSquareIcon,
|
||||
@@ -133,8 +159,9 @@ import {
|
||||
type PopupNotificationProgressItem,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||
import { Dropdown } from 'floating-vue'
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import { trackEvent } from '@/helpers/analytics'
|
||||
@@ -144,6 +171,11 @@ import { get_many as getInstances } from '@/helpers/profile.js'
|
||||
import type { LoadingBar } from '@/helpers/state'
|
||||
import { progress_bars_list } from '@/helpers/state'
|
||||
import type { GameInstance } from '@/helpers/types'
|
||||
import {
|
||||
appUpdateState,
|
||||
downloadAvailableAppUpdate,
|
||||
installAvailableAppUpdate,
|
||||
} from '@/providers/app-update'
|
||||
|
||||
const { handleError } = injectNotificationManager()
|
||||
const popupNotificationManager = injectPopupNotificationManager()
|
||||
@@ -208,8 +240,96 @@ const messages = defineMessages({
|
||||
id: 'app.action-bar.view-active-downloads',
|
||||
defaultMessage: 'View active downloads',
|
||||
},
|
||||
update: {
|
||||
id: 'app.action-bar.update',
|
||||
defaultMessage: 'Update',
|
||||
},
|
||||
downloadingUpdate: {
|
||||
id: 'app.action-bar.downloading-update',
|
||||
defaultMessage: 'Downloading update',
|
||||
},
|
||||
reloadToUpdate: {
|
||||
id: 'app.action-bar.reload-to-update',
|
||||
defaultMessage: 'Reload to update',
|
||||
},
|
||||
})
|
||||
|
||||
const {
|
||||
downloading,
|
||||
downloadPercent,
|
||||
downloadProgress,
|
||||
finishedDownloading,
|
||||
isVisible: isUpdateVisible,
|
||||
metered,
|
||||
restarting,
|
||||
} = appUpdateState
|
||||
|
||||
const isUpdateDownloading = computed(
|
||||
() =>
|
||||
downloading.value ||
|
||||
(downloadProgress.value > 0 && downloadProgress.value < 1 && !finishedDownloading.value),
|
||||
)
|
||||
const showUpdatePill = computed(
|
||||
() => isUpdateVisible.value && (finishedDownloading.value || metered.value),
|
||||
)
|
||||
const animateReadyPill = ref(false)
|
||||
const updateLabel = computed(() => {
|
||||
if (isUpdateDownloading.value) {
|
||||
return formatMessage(messages.downloadingUpdate)
|
||||
}
|
||||
|
||||
if (finishedDownloading.value) {
|
||||
return formatMessage(messages.reloadToUpdate)
|
||||
}
|
||||
|
||||
return formatMessage(messages.update)
|
||||
})
|
||||
const updatePillWidthClass = computed(() => {
|
||||
if (isUpdateDownloading.value) {
|
||||
return 'w-[219px]'
|
||||
}
|
||||
|
||||
if (finishedDownloading.value) {
|
||||
return 'w-[166px]'
|
||||
}
|
||||
|
||||
return '!w-[96px]'
|
||||
})
|
||||
let readyPillAnimationFrame: number | null = null
|
||||
watch([showUpdatePill, finishedDownloading], async ([show, ready], [wasShown, wasReady]) => {
|
||||
if (readyPillAnimationFrame !== null) {
|
||||
cancelAnimationFrame(readyPillAnimationFrame)
|
||||
readyPillAnimationFrame = null
|
||||
}
|
||||
|
||||
if (!show || !ready) {
|
||||
animateReadyPill.value = false
|
||||
return
|
||||
}
|
||||
|
||||
if (wasShown && wasReady) {
|
||||
return
|
||||
}
|
||||
|
||||
animateReadyPill.value = false
|
||||
await nextTick()
|
||||
readyPillAnimationFrame = requestAnimationFrame(() => {
|
||||
animateReadyPill.value = true
|
||||
readyPillAnimationFrame = null
|
||||
})
|
||||
})
|
||||
async function handleUpdateClick() {
|
||||
if (isUpdateDownloading.value) {
|
||||
return
|
||||
}
|
||||
|
||||
if (finishedDownloading.value) {
|
||||
await installAvailableAppUpdate()
|
||||
} else {
|
||||
await downloadAvailableAppUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
const currentProcesses = ref<RunningProcess[]>([])
|
||||
const selectedProcess = ref<RunningProcess | undefined>()
|
||||
|
||||
@@ -284,6 +404,7 @@ function goToTerminal(path?: string) {
|
||||
}
|
||||
|
||||
const currentLoadingBars = ref<LoadingBar[]>([])
|
||||
const currentLoadingBarIconUrls = ref<Record<string, string | null>>({})
|
||||
const notificationId = ref<string | number | null>(null)
|
||||
const dismissed = ref(false)
|
||||
|
||||
@@ -303,6 +424,16 @@ function getLoadingText(loadingBar: LoadingBar): string {
|
||||
return loadingBar.message ? `${percent}% ${loadingBar.message}` : `${percent}%`
|
||||
}
|
||||
|
||||
function getDisplayIconUrl(icon: string | null | undefined): string | null {
|
||||
if (!icon) {
|
||||
return null
|
||||
}
|
||||
if (/^(https?:|data:|blob:|asset:|tauri:)/.test(icon)) {
|
||||
return icon
|
||||
}
|
||||
return convertFileSrc(icon)
|
||||
}
|
||||
|
||||
function getNotification(): PopupNotification | null {
|
||||
if (!notificationId.value) {
|
||||
return null
|
||||
@@ -326,6 +457,7 @@ function buildDownloadItems(): PopupNotificationProgressItem[] {
|
||||
id: getLoadingBarKey(bar),
|
||||
title: bar.title ?? '',
|
||||
text: getLoadingText(bar),
|
||||
iconUrl: currentLoadingBarIconUrls.value[getLoadingBarKey(bar)] ?? null,
|
||||
progress: getLoadingProgress(bar),
|
||||
waiting: !bar.total || bar.total <= 0,
|
||||
}))
|
||||
@@ -400,6 +532,32 @@ async function refreshLoadingBars() {
|
||||
.map(formatLoadingBars)
|
||||
.filter((bar) => bar?.bar_type?.type !== 'launcher_update')
|
||||
|
||||
const profilePaths = Array.from(
|
||||
new Set(
|
||||
currentLoadingBars.value
|
||||
.map((bar) => bar.bar_type?.profile_path)
|
||||
.filter((path): path is string => !!path),
|
||||
),
|
||||
)
|
||||
const profiles = profilePaths.length
|
||||
? await getInstances(profilePaths).catch((error) => {
|
||||
handleError(error)
|
||||
return []
|
||||
})
|
||||
: []
|
||||
const profileIconUrls = new Map(
|
||||
profiles.map((profile) => [profile.path, getDisplayIconUrl(profile.icon_path)]),
|
||||
)
|
||||
currentLoadingBarIconUrls.value = Object.fromEntries(
|
||||
currentLoadingBars.value.map((bar) => {
|
||||
const barIconUrl = getDisplayIconUrl(bar.bar_type?.icon)
|
||||
const profileIconUrl = bar.bar_type?.profile_path
|
||||
? profileIconUrls.get(bar.bar_type.profile_path)
|
||||
: null
|
||||
return [getLoadingBarKey(bar), barIconUrl ?? profileIconUrl ?? null]
|
||||
}),
|
||||
)
|
||||
|
||||
currentLoadingBars.value.sort((a, b) => {
|
||||
const aKey = `${a.loading_bar_uuid ?? a.id ?? ''}`
|
||||
const bKey = `${b.loading_bar_uuid ?? b.id ?? ''}`
|
||||
@@ -430,5 +588,20 @@ onBeforeUnmount(() => {
|
||||
window.removeEventListener('online', handleOnline)
|
||||
unlistenProcess()
|
||||
unlistenLoading()
|
||||
if (readyPillAnimationFrame !== null) {
|
||||
cancelAnimationFrame(readyPillAnimationFrame)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.update-pill-ready-hidden {
|
||||
opacity: 0;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.update-pill-ready-visible {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -89,14 +89,9 @@ const initFiles = async () => {
|
||||
disabled:
|
||||
folder === 'profile.json' ||
|
||||
folder.startsWith('modrinth_logs') ||
|
||||
folder.startsWith('.fabric'),
|
||||
folder.startsWith('.fabric') ||
|
||||
folder.startsWith('__MACOSX'),
|
||||
}))
|
||||
.filter(
|
||||
(pathData) =>
|
||||
!pathData.path.includes('.DS_Store') &&
|
||||
pathData.path !== 'mods/.connector' &&
|
||||
!pathData.path.startsWith('mods/.connector/'),
|
||||
)
|
||||
.forEach((pathData) => {
|
||||
const parent = pathData.path.split(sep).slice(0, -1).join(sep)
|
||||
if (parent !== '') {
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
<template>
|
||||
<ModalWrapper ref="incompatibleModal" header="Incompatibility warning" :on-hide="onInstall">
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
This {{ versions?.length > 0 ? 'project' : 'version' }} is not compatible with the instance
|
||||
you're trying to install it on. Are you sure you want to continue? Dependencies will not be
|
||||
installed.
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="header">
|
||||
<th>{{ instance?.name }}</th>
|
||||
<th>{{ project.title }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="content">
|
||||
<td class="data">{{ instance?.loader }} {{ instance?.game_version }}</td>
|
||||
<td>
|
||||
<Combobox
|
||||
v-if="versions?.length > 1"
|
||||
v-model="selectedVersionId"
|
||||
:options="versionOptions"
|
||||
:searchable="true"
|
||||
placeholder="Select version"
|
||||
force-direction="up"
|
||||
:max-height="150"
|
||||
/>
|
||||
<span v-else>
|
||||
<span>{{ selectedVersionLabel }}</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="button-group">
|
||||
<ButtonStyled type="outlined">
|
||||
<button @click="() => incompatibleModal.hide()"><XIcon />Cancel</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled color="brand">
|
||||
<button :disabled="installing" @click="install()">
|
||||
<DownloadIcon /> {{ installing ? 'Installing' : 'Install' }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { DownloadIcon, XIcon } from '@modrinth/assets'
|
||||
import {
|
||||
ButtonStyled,
|
||||
Combobox,
|
||||
formatLoader,
|
||||
injectNotificationManager,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||
import { trackEvent } from '@/helpers/analytics'
|
||||
import { add_project_from_version as installMod } from '@/helpers/profile'
|
||||
|
||||
const { handleError } = injectNotificationManager()
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const instance = ref(null)
|
||||
const project = ref(null)
|
||||
const versions = ref(null)
|
||||
const selectedVersion = ref(null)
|
||||
const incompatibleModal = ref(null)
|
||||
const installing = ref(false)
|
||||
|
||||
const onInstall = ref(() => {})
|
||||
|
||||
const selectedVersionLabel = computed(() => {
|
||||
if (!selectedVersion.value) return ''
|
||||
return `${selectedVersion.value.name} (${selectedVersion.value.loaders
|
||||
.map((name) => formatLoader(formatMessage, name))
|
||||
.join(', ')} - ${selectedVersion.value.game_versions.join(', ')})`
|
||||
})
|
||||
|
||||
const versionOptions = computed(() =>
|
||||
(versions.value ?? []).map((version) => ({
|
||||
value: version.id,
|
||||
label: `${version.name} (${version.loaders
|
||||
.map((name) => formatLoader(formatMessage, name))
|
||||
.join(', ')} - ${version.game_versions.join(', ')})`,
|
||||
})),
|
||||
)
|
||||
|
||||
const selectedVersionId = computed({
|
||||
get: () => selectedVersion.value?.id ?? null,
|
||||
set: (value) => {
|
||||
if (!value) return
|
||||
selectedVersion.value = (versions.value ?? []).find((version) => version.id === value) ?? null
|
||||
},
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
show: (instanceVal, projectVal, projectVersions, selected, callback) => {
|
||||
instance.value = instanceVal
|
||||
versions.value = projectVersions ?? []
|
||||
selectedVersion.value = selected ?? projectVersions?.[0] ?? null
|
||||
|
||||
project.value = projectVal
|
||||
|
||||
onInstall.value = callback
|
||||
installing.value = false
|
||||
|
||||
incompatibleModal.value.show()
|
||||
|
||||
trackEvent('ProjectInstallStart', { source: 'ProjectIncompatibilityWarningModal' })
|
||||
},
|
||||
})
|
||||
|
||||
const install = async () => {
|
||||
installing.value = true
|
||||
await installMod(instance.value.path, selectedVersion.value.id, 'standalone').catch(handleError)
|
||||
installing.value = false
|
||||
onInstall.value(selectedVersion.value.id)
|
||||
incompatibleModal.value.hide()
|
||||
|
||||
trackEvent('ProjectInstall', {
|
||||
loader: instance.value.loader,
|
||||
game_version: instance.value.game_version,
|
||||
id: project.value,
|
||||
version_id: selectedVersion.value.id,
|
||||
project_type: project.value.project_type,
|
||||
title: project.value.title,
|
||||
source: 'ProjectIncompatibilityWarningModal',
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.data {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-radius: var(--radius-lg);
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 0 0 1px var(--color-button-bg);
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding: 1rem;
|
||||
background-color: var(--color-bg);
|
||||
overflow: hidden;
|
||||
border-bottom: 1px solid var(--color-button-bg);
|
||||
}
|
||||
|
||||
th:first-child {
|
||||
border-top-left-radius: var(--radius-lg);
|
||||
border-right: 1px solid var(--color-button-bg);
|
||||
}
|
||||
|
||||
th:last-child {
|
||||
border-top-right-radius: var(--radius-lg);
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
td:first-child {
|
||||
border-right: 1px solid var(--color-button-bg);
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -4,12 +4,14 @@ import {
|
||||
Avatar,
|
||||
ButtonStyled,
|
||||
Checkbox,
|
||||
Chips,
|
||||
defineMessages,
|
||||
injectNotificationManager,
|
||||
OverflowMenu,
|
||||
StyledInput,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { useQueryClient } from '@tanstack/vue-query'
|
||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||
import { open } from '@tauri-apps/plugin-dialog'
|
||||
import { computed, type Ref, ref, watch } from 'vue'
|
||||
@@ -25,14 +27,22 @@ import type { GameInstance } from '../../../helpers/types'
|
||||
const { handleError } = injectNotificationManager()
|
||||
const { formatMessage } = useVIntl()
|
||||
const router = useRouter()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const deleteConfirmModal = ref()
|
||||
|
||||
const { instance } = injectInstanceSettings()
|
||||
type ReleaseChannel = GameInstance['preferred_update_channel']
|
||||
const releaseChannelOptions: ReleaseChannel[] = ['release', 'beta', 'alpha']
|
||||
|
||||
const title = ref(instance.value.name)
|
||||
const icon: Ref<string | undefined> = ref(instance.value.icon_path)
|
||||
const groups = ref([...instance.value.groups])
|
||||
const savingReleaseChannel = ref(false)
|
||||
const selectedReleaseChannel = ref<ReleaseChannel>(instance.value.preferred_update_channel)
|
||||
const releaseChannelDisabledItems = computed<ReleaseChannel[]>(() =>
|
||||
savingReleaseChannel.value ? [...releaseChannelOptions] : [],
|
||||
)
|
||||
|
||||
const newCategoryInput = ref('')
|
||||
|
||||
@@ -51,6 +61,52 @@ const availableGroups = computed(() => [
|
||||
...new Set([...allInstances.value.flatMap((instance) => instance.groups), ...groups.value]),
|
||||
])
|
||||
|
||||
function formatReleaseChannelLabel(channel: ReleaseChannel) {
|
||||
switch (channel) {
|
||||
case 'release':
|
||||
return formatMessage(messages.updateChannelRelease)
|
||||
case 'beta':
|
||||
return formatMessage(messages.updateChannelBeta)
|
||||
case 'alpha':
|
||||
return formatMessage(messages.updateChannelAlpha)
|
||||
}
|
||||
}
|
||||
|
||||
function formatReleaseChannelDescription(channel: ReleaseChannel) {
|
||||
switch (channel) {
|
||||
case 'release':
|
||||
return formatMessage(messages.updateChannelReleaseDescription)
|
||||
case 'beta':
|
||||
return formatMessage(messages.updateChannelBetaDescription)
|
||||
case 'alpha':
|
||||
return formatMessage(messages.updateChannelAlphaDescription)
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [instance.value.path, instance.value.preferred_update_channel] as const,
|
||||
() => {
|
||||
if (!savingReleaseChannel.value) {
|
||||
selectedReleaseChannel.value = instance.value.preferred_update_channel
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
watch(selectedReleaseChannel, async (channel, previousChannel) => {
|
||||
const previousReleaseChannel = previousChannel ?? instance.value.preferred_update_channel
|
||||
if (channel === instance.value.preferred_update_channel) return
|
||||
|
||||
savingReleaseChannel.value = true
|
||||
const profilePath = instance.value.path
|
||||
await edit(profilePath, { preferred_update_channel: channel })
|
||||
.then(() => queryClient.invalidateQueries({ queryKey: ['linkedModpackInfo', profilePath] }))
|
||||
.catch((error) => {
|
||||
selectedReleaseChannel.value = previousReleaseChannel
|
||||
handleError(error)
|
||||
})
|
||||
savingReleaseChannel.value = false
|
||||
})
|
||||
|
||||
async function resetIcon() {
|
||||
icon.value = undefined
|
||||
await edit_icon(instance.value.path, null).catch(handleError)
|
||||
@@ -175,6 +231,38 @@ const messages = defineMessages({
|
||||
id: 'instance.settings.tabs.general.duplicate-button',
|
||||
defaultMessage: 'Duplicate',
|
||||
},
|
||||
updateChannel: {
|
||||
id: 'instance.settings.tabs.general.update-channel',
|
||||
defaultMessage: 'Update channel',
|
||||
},
|
||||
updateChannelReleaseDescription: {
|
||||
id: 'instance.settings.tabs.general.update-channel.release.description',
|
||||
defaultMessage: 'Only release versions will be shown as available updates.',
|
||||
},
|
||||
updateChannelBetaDescription: {
|
||||
id: 'instance.settings.tabs.general.update-channel.beta.description',
|
||||
defaultMessage: 'Release and beta versions will be shown as available updates.',
|
||||
},
|
||||
updateChannelAlphaDescription: {
|
||||
id: 'instance.settings.tabs.general.update-channel.alpha.description',
|
||||
defaultMessage: 'Release, beta, and alpha versions will be shown as available updates.',
|
||||
},
|
||||
updateChannelRelease: {
|
||||
id: 'instance.settings.tabs.general.update-channel.release',
|
||||
defaultMessage: 'Release',
|
||||
},
|
||||
updateChannelBeta: {
|
||||
id: 'instance.settings.tabs.general.update-channel.beta',
|
||||
defaultMessage: 'Beta',
|
||||
},
|
||||
updateChannelAlpha: {
|
||||
id: 'instance.settings.tabs.general.update-channel.alpha',
|
||||
defaultMessage: 'Alpha',
|
||||
},
|
||||
selectUpdateChannelAriaLabel: {
|
||||
id: 'instance.settings.tabs.general.update-channel.select',
|
||||
defaultMessage: 'Select update channel',
|
||||
},
|
||||
deleteInstance: {
|
||||
id: 'instance.settings.tabs.general.delete',
|
||||
defaultMessage: 'Delete instance',
|
||||
@@ -304,6 +392,23 @@ const messages = defineMessages({
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2.5 mt-6">
|
||||
<h2 class="m-0 text-lg font-semibold text-contrast block">
|
||||
{{ formatMessage(messages.updateChannel) }}
|
||||
</h2>
|
||||
<Chips
|
||||
v-model="selectedReleaseChannel"
|
||||
:items="releaseChannelOptions"
|
||||
:format-label="formatReleaseChannelLabel"
|
||||
:capitalize="false"
|
||||
:disabled-items="releaseChannelDisabledItems"
|
||||
:aria-label="formatMessage(messages.selectUpdateChannelAriaLabel)"
|
||||
/>
|
||||
<p class="m-0">
|
||||
{{ formatReleaseChannelDescription(selectedReleaseChannel) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2.5 mt-6">
|
||||
<h2 id="delete-instance-label" class="m-0 text-lg font-semibold text-contrast block">
|
||||
{{ formatMessage(messages.deleteInstance) }}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
InstallationSettingsLayout,
|
||||
provideAppBackup,
|
||||
provideInstallationSettings,
|
||||
useDebugLogger,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import type { GameVersionTag, PlatformTag } from '@modrinth/utils'
|
||||
@@ -34,9 +35,17 @@ import type { Manifest } from '../../../helpers/types'
|
||||
const { handleError } = injectNotificationManager()
|
||||
const { formatMessage } = useVIntl()
|
||||
const queryClient = useQueryClient()
|
||||
const debug = useDebugLogger('AppInstallationSettings')
|
||||
|
||||
const { instance, offline, isMinecraftServer, onUnlinked, closeModal } = injectInstanceSettings()
|
||||
|
||||
debug('metadata load: start', {
|
||||
instancePath: instance.value.path,
|
||||
loader: instance.value.loader,
|
||||
gameVersion: instance.value.game_version,
|
||||
installStage: instance.value.install_stage,
|
||||
})
|
||||
|
||||
const [
|
||||
fabric_versions,
|
||||
forge_versions,
|
||||
@@ -72,6 +81,15 @@ const [
|
||||
.catch(handleError),
|
||||
])
|
||||
|
||||
debug('metadata load: done', {
|
||||
hasFabricManifest: !!fabric_versions?.value,
|
||||
hasForgeManifest: !!forge_versions?.value,
|
||||
hasQuiltManifest: !!quilt_versions?.value,
|
||||
hasNeoforgeManifest: !!neoforge_versions?.value,
|
||||
gameVersions: all_game_versions?.value?.length ?? 0,
|
||||
availablePlatforms: loaders?.value?.map((loader) => loader.name) ?? [],
|
||||
})
|
||||
|
||||
const { data: modpackInfo } = useQuery({
|
||||
queryKey: computed(() => ['linkedModpackInfo', instance.value.path]),
|
||||
queryFn: () => get_linked_modpack_info(instance.value.path, 'must_revalidate'),
|
||||
@@ -95,11 +113,21 @@ function getManifest(loader: string) {
|
||||
quilt: quilt_versions,
|
||||
neoforge: neoforge_versions,
|
||||
}
|
||||
return map[loader]
|
||||
const manifest = map[loader]
|
||||
debug('getManifest:', {
|
||||
loader,
|
||||
hasManifest: !!manifest?.value,
|
||||
gameVersions: manifest?.value?.gameVersions?.length ?? 0,
|
||||
})
|
||||
return manifest
|
||||
}
|
||||
|
||||
provideAppBackup({
|
||||
async createBackup() {
|
||||
debug('createBackup: start', {
|
||||
instancePath: instance.value.path,
|
||||
instanceName: instance.value.name,
|
||||
})
|
||||
const allProfiles = await list()
|
||||
const prefix = `${instance.value.name} - Backup #`
|
||||
const existingNums = allProfiles
|
||||
@@ -109,6 +137,7 @@ provideAppBackup({
|
||||
const nextNum = existingNums.length > 0 ? Math.max(...existingNums) + 1 : 1
|
||||
const newPath = await duplicate(instance.value.path)
|
||||
await edit(newPath, { name: `${prefix}${nextNum}` })
|
||||
debug('createBackup: done', { newPath, backupName: `${prefix}${nextNum}` })
|
||||
},
|
||||
})
|
||||
|
||||
@@ -165,32 +194,72 @@ provideInstallationSettings({
|
||||
const manifest = getManifest(loader)
|
||||
return !!manifest?.value?.gameVersions?.some((x) => item.version === x.id)
|
||||
})
|
||||
return (showSnapshots ? filtered : filtered.filter((x) => x.version_type === 'release')).map(
|
||||
(x) => ({ value: x.version, label: x.version }),
|
||||
)
|
||||
const result = (
|
||||
showSnapshots ? filtered : filtered.filter((x) => x.version_type === 'release')
|
||||
).map((x) => ({ value: x.version, label: x.version }))
|
||||
debug('resolveGameVersions:', {
|
||||
loader,
|
||||
showSnapshots,
|
||||
totalVersions: versions.length,
|
||||
filteredVersions: filtered.length,
|
||||
resultVersions: result.length,
|
||||
})
|
||||
return result
|
||||
},
|
||||
|
||||
resolveLoaderVersions(loader, gameVersion) {
|
||||
if (loader === 'vanilla' || !gameVersion) return []
|
||||
const manifest = getManifest(loader)
|
||||
if (!manifest?.value) return []
|
||||
if (loader === 'fabric' || loader === 'quilt') {
|
||||
return manifest.value.gameVersions[0]?.loaders ?? []
|
||||
if (loader === 'vanilla' || !gameVersion) {
|
||||
debug('resolveLoaderVersions: skipped', { loader, gameVersion })
|
||||
return []
|
||||
}
|
||||
return manifest.value.gameVersions?.find((item) => item.id === gameVersion)?.loaders ?? []
|
||||
const manifest = getManifest(loader)
|
||||
if (!manifest?.value) {
|
||||
debug('resolveLoaderVersions: no manifest', { loader, gameVersion })
|
||||
return []
|
||||
}
|
||||
if (loader === 'fabric' || loader === 'quilt') {
|
||||
const result = manifest.value.gameVersions[0]?.loaders ?? []
|
||||
debug('resolveLoaderVersions: fabric/quilt result', {
|
||||
loader,
|
||||
gameVersion,
|
||||
count: result.length,
|
||||
})
|
||||
return result
|
||||
}
|
||||
const result =
|
||||
manifest.value.gameVersions?.find((item) => item.id === gameVersion)?.loaders ?? []
|
||||
debug('resolveLoaderVersions: result', { loader, gameVersion, count: result.length })
|
||||
return result
|
||||
},
|
||||
|
||||
resolveHasSnapshots(loader) {
|
||||
const versions = all_game_versions?.value ?? []
|
||||
if (loader === 'vanilla') return versions.some((x) => x.version_type !== 'release')
|
||||
if (loader === 'vanilla') {
|
||||
const result = versions.some((x) => x.version_type !== 'release')
|
||||
debug('resolveHasSnapshots: vanilla', { loader, result })
|
||||
return result
|
||||
}
|
||||
const manifest = getManifest(loader)
|
||||
const supported = versions.filter(
|
||||
(item) => !!manifest?.value?.gameVersions?.some((x) => item.version === x.id),
|
||||
)
|
||||
return supported.some((x) => x.version_type !== 'release')
|
||||
const result = supported.some((x) => x.version_type !== 'release')
|
||||
debug('resolveHasSnapshots:', {
|
||||
loader,
|
||||
totalVersions: versions.length,
|
||||
supportedVersions: supported.length,
|
||||
result,
|
||||
})
|
||||
return result
|
||||
},
|
||||
|
||||
async save(platform, gameVersion, loaderVersionId) {
|
||||
debug('save: called', {
|
||||
instancePath: instance.value.path,
|
||||
platform,
|
||||
gameVersion,
|
||||
loaderVersionId,
|
||||
})
|
||||
const editProfile: Record<string, string | undefined> = {
|
||||
loader: platform,
|
||||
game_version: gameVersion,
|
||||
@@ -199,17 +268,21 @@ provideInstallationSettings({
|
||||
editProfile.loader_version = loaderVersionId
|
||||
}
|
||||
await edit(instance.value.path, editProfile).catch(handleError)
|
||||
debug('save: edit complete', { editProfile })
|
||||
},
|
||||
|
||||
afterSave: async () => {
|
||||
debug('afterSave: installing', { instancePath: instance.value.path })
|
||||
await install(instance.value.path, false).catch(handleError)
|
||||
trackEvent('InstanceRepair', {
|
||||
loader: instance.value.loader,
|
||||
game_version: instance.value.game_version,
|
||||
})
|
||||
debug('afterSave: done')
|
||||
},
|
||||
|
||||
async repair() {
|
||||
debug('repair: called', { instancePath: instance.value.path })
|
||||
repairing.value = true
|
||||
await install(instance.value.path, true).catch(handleError)
|
||||
repairing.value = false
|
||||
@@ -217,9 +290,11 @@ provideInstallationSettings({
|
||||
loader: instance.value.loader,
|
||||
game_version: instance.value.game_version,
|
||||
})
|
||||
debug('repair: done')
|
||||
},
|
||||
|
||||
async reinstallModpack() {
|
||||
debug('reinstallModpack: called', { instancePath: instance.value.path })
|
||||
reinstalling.value = true
|
||||
await update_repair_modrinth(instance.value.path).catch(handleError)
|
||||
reinstalling.value = false
|
||||
@@ -227,9 +302,11 @@ provideInstallationSettings({
|
||||
loader: instance.value.loader,
|
||||
game_version: instance.value.game_version,
|
||||
})
|
||||
debug('reinstallModpack: done')
|
||||
},
|
||||
|
||||
async unlinkModpack() {
|
||||
debug('unlinkModpack: called', { instancePath: instance.value.path })
|
||||
await edit(instance.value.path, {
|
||||
linked_data: null as unknown as undefined,
|
||||
})
|
||||
@@ -237,27 +314,38 @@ provideInstallationSettings({
|
||||
queryKey: ['linkedModpackInfo', instance.value.path],
|
||||
})
|
||||
onUnlinked()
|
||||
debug('unlinkModpack: done')
|
||||
},
|
||||
|
||||
getCachedModpackVersions: () => null,
|
||||
async fetchModpackVersions() {
|
||||
debug('fetchModpackVersions: called', {
|
||||
projectId: instance.value.linked_data?.project_id,
|
||||
})
|
||||
const versions = await get_project_versions(instance.value.linked_data!.project_id!).catch(
|
||||
handleError,
|
||||
)
|
||||
debug('fetchModpackVersions: done', { count: versions?.length ?? 0 })
|
||||
return (versions ?? []) as Labrinth.Versions.v2.Version[]
|
||||
},
|
||||
|
||||
async getVersionChangelog(versionId: string) {
|
||||
debug('getVersionChangelog: called', { versionId })
|
||||
return (await get_version(versionId, 'must_revalidate').catch(
|
||||
() => null,
|
||||
)) as Labrinth.Versions.v2.Version | null
|
||||
},
|
||||
|
||||
async onModpackVersionConfirm(version) {
|
||||
debug('onModpackVersionConfirm: called', {
|
||||
versionId: version.id,
|
||||
instancePath: instance.value.path,
|
||||
})
|
||||
await update_managed_modrinth_version(instance.value.path, version.id)
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['linkedModpackInfo', instance.value.path],
|
||||
})
|
||||
debug('onModpackVersionConfirm: done')
|
||||
},
|
||||
|
||||
updaterModalProps: computed(() => ({
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
|
||||
import { login as login_flow, set_default_user } from '@/helpers/auth.js'
|
||||
import { handleSevereError } from '@/store/error.js'
|
||||
|
||||
import { type MinecraftAuthError, minecraftAuthErrors } from './minecraft-auth-errors'
|
||||
import { findMinecraftAuthError, type MinecraftAuthError } from './minecraft-auth-errors'
|
||||
|
||||
const modal = ref<InstanceType<typeof NewModal>>()
|
||||
const rawError = ref<string>('')
|
||||
@@ -26,7 +26,7 @@ const loadingSignIn = ref(false)
|
||||
function show(errorVal: { message?: string }) {
|
||||
rawError.value = errorVal?.message ?? String(errorVal)
|
||||
|
||||
matchedError.value = minecraftAuthErrors.find((e) => rawError.value.includes(e.errorCode)) ?? null
|
||||
matchedError.value = findMinecraftAuthError(rawError.value)
|
||||
|
||||
debugCollapsed.value = true
|
||||
hide_ads_window()
|
||||
|
||||
+111
-1
@@ -1,10 +1,93 @@
|
||||
export interface MinecraftAuthError {
|
||||
errorCode: string
|
||||
errorCode?: string
|
||||
errorMatchers?: string[]
|
||||
matches?: (message: string) => boolean
|
||||
whatHappened: string
|
||||
stepsToFix: string[]
|
||||
}
|
||||
|
||||
export const minecraftAuthErrors: MinecraftAuthError[] = [
|
||||
{
|
||||
errorMatchers: ['Failed to deserialize response to JSON during step RefreshOAuthToken:'],
|
||||
whatHappened:
|
||||
'Your saved Microsoft sign-in token has expired or was revoked, so Modrinth App cannot refresh your Minecraft session.',
|
||||
stepsToFix: [
|
||||
'Sign out of the affected Minecraft account in Modrinth App',
|
||||
'Sign in to the account again',
|
||||
'Once the new sign-in finishes, try launching Minecraft again',
|
||||
],
|
||||
},
|
||||
{
|
||||
errorMatchers: ['Failed to deserialize response to JSON during step SisuAuthenticate:'],
|
||||
whatHappened:
|
||||
'Xbox services rejected the first sign-in response. This is most often caused by your system clock or time zone being out of sync.',
|
||||
stepsToFix: [
|
||||
'Open your system date and time settings',
|
||||
'Turn on automatic time zone and automatic time, if available',
|
||||
'Use the sync option in your system settings to synchronize the clock',
|
||||
'Restart Modrinth App',
|
||||
'Try signing in again',
|
||||
],
|
||||
},
|
||||
{
|
||||
matches: (message) =>
|
||||
message.includes('Failed to deserialize response to JSON during step MinecraftToken:') &&
|
||||
message.includes('429 Too Many Requests'),
|
||||
whatHappened:
|
||||
'Microsoft or Minecraft temporarily blocked the sign-in request because there were too many recent attempts.',
|
||||
stepsToFix: [
|
||||
'Wait about an hour before trying again',
|
||||
'Restart Modrinth App after waiting',
|
||||
'Try signing in once more',
|
||||
'If the same message appears, wait longer before retrying so the temporary limit can clear',
|
||||
],
|
||||
},
|
||||
{
|
||||
matches: (message) =>
|
||||
message.includes('Failed to deserialize response to JSON during step MinecraftToken:') &&
|
||||
/Status Code: 5\d\d/.test(message),
|
||||
whatHappened:
|
||||
"Minecraft's authentication service is returning a server error, so Modrinth App cannot finish signing you in right now.",
|
||||
stepsToFix: [
|
||||
'Wait a few minutes and try signing in again',
|
||||
'Check <a href="https://support.xbox.com/xbox-live-status">Xbox Status</a> for current service issues',
|
||||
'Try signing in with the <a href="https://www.minecraft.net/en-us/download">official Minecraft Launcher</a> to confirm whether Minecraft sign-in is also affected there',
|
||||
'If the service is healthy and this keeps happening, contact support with the debug information below',
|
||||
],
|
||||
},
|
||||
{
|
||||
errorMatchers: ['Failed to fetch player profile'],
|
||||
whatHappened:
|
||||
'Minecraft services could not return a Java Edition profile for this account. This most often happens when the game was purchased recently, the Java profile has not finished being created, or the wrong Microsoft account is being used.',
|
||||
stepsToFix: [
|
||||
'Sign in with the <a href="https://www.minecraft.net/en-us/download">official Minecraft Launcher</a>',
|
||||
'Launch Minecraft: Java Edition once from the official launcher',
|
||||
'Wait up to an hour if the purchase or profile setup was recent',
|
||||
'Make sure you are using the Microsoft account that owns Minecraft. See <a href="https://support.modrinth.com/en/articles/9409136-finding-the-right-xbox-account">Finding the right Xbox account</a> for help',
|
||||
'Try signing in to Modrinth App again',
|
||||
],
|
||||
},
|
||||
{
|
||||
matches: (message) =>
|
||||
message.includes('error sending request for url (') &&
|
||||
[
|
||||
'minecraft.net',
|
||||
'minecraftservices.com',
|
||||
'mojang.com',
|
||||
'xbox.com',
|
||||
'xboxlive.com',
|
||||
'live.com',
|
||||
].some((domain) => message.includes(domain)),
|
||||
whatHappened:
|
||||
'Modrinth App could not connect to a Microsoft, Xbox, or Minecraft service needed for sign-in. This is usually caused by a local network, DNS, proxy, firewall, hosts file, VPN, or antivirus issue.',
|
||||
stepsToFix: [
|
||||
'Restart Modrinth App and try signing in again',
|
||||
'Check that your internet connection is working',
|
||||
'Allow Modrinth App through your firewall, antivirus, proxy, VPN, and hosts file rules',
|
||||
'Try a different network or temporarily disable VPN/proxy software if you use one',
|
||||
'If routing or DNS is the issue, a service like Cloudflare WARP can sometimes help',
|
||||
],
|
||||
},
|
||||
{
|
||||
errorCode: '2148916222',
|
||||
whatHappened:
|
||||
@@ -87,4 +170,31 @@ export const minecraftAuthErrors: MinecraftAuthError[] = [
|
||||
'Once finished, try signing in again',
|
||||
],
|
||||
},
|
||||
{
|
||||
errorMatchers: ['Failed to deserialize response to JSON during step XstsAuthorize:'],
|
||||
whatHappened:
|
||||
'Xbox services rejected the request to authorize this account for Minecraft services, but did not return a specific account restriction that Modrinth App recognizes.',
|
||||
stepsToFix: [
|
||||
'Sign in with the <a href="https://www.minecraft.net/en-us/download">official Minecraft Launcher</a>',
|
||||
'Complete any prompts shown by Microsoft, Xbox, or Minecraft',
|
||||
'Try signing in to Modrinth App again',
|
||||
'If the official launcher also fails, follow the error shown there or contact Xbox Support',
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
export function findMinecraftAuthError(message: string): MinecraftAuthError | null {
|
||||
return (
|
||||
minecraftAuthErrors.find((error) => {
|
||||
if (error.errorCode && message.includes(error.errorCode)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (error.errorMatchers?.some((matcher) => message.includes(matcher))) {
|
||||
return true
|
||||
}
|
||||
|
||||
return error.matches?.(message) ?? false
|
||||
}) ?? null
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,8 +10,9 @@ import type { ColorTheme, FeatureFlag } from '@/store/theme.ts'
|
||||
const themeStore = useTheming()
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const worldsInHomeFeatureFlag = 'worlds_in_home' as FeatureFlag
|
||||
const skipUnknownPackWarningFeatureFlag = 'skip_unknown_pack_warning' as FeatureFlag
|
||||
const worldsInHomeFlag: FeatureFlag = 'worlds_in_home'
|
||||
const skipUnknownPackWarningFlag: FeatureFlag = 'skip_unknown_pack_warning'
|
||||
const showPlayTimeFlag: FeatureFlag = 'show_instance_play_time'
|
||||
|
||||
const messages = defineMessages({
|
||||
colorThemeTitle: {
|
||||
@@ -100,6 +101,14 @@ const messages = defineMessages({
|
||||
defaultMessage:
|
||||
"If you attempt to install a Modrinth Pack file (.mrpack) that isn't hosted on Modrinth, we'll make sure you understand the risks before installing it.",
|
||||
},
|
||||
showPlayTimeTitle: {
|
||||
id: 'app.appearance-settings.show-play-time.title',
|
||||
defaultMessage: 'Show play time',
|
||||
},
|
||||
showPlayTimeDescription: {
|
||||
id: 'app.appearance-settings.show-play-time.description',
|
||||
defaultMessage: `Displays how much time you've spent playing an instance.`,
|
||||
},
|
||||
})
|
||||
|
||||
const os = ref(await getOS())
|
||||
@@ -153,25 +162,6 @@ watch(
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="m-0 text-lg font-semibold text-contrast">
|
||||
{{ formatMessage(messages.hideNametagTitle) }}
|
||||
</h2>
|
||||
<p class="m-0 mt-1">{{ formatMessage(messages.hideNametagDescription) }}</p>
|
||||
</div>
|
||||
<Toggle
|
||||
id="hide-nametag-skins-page"
|
||||
:model-value="themeStore.hideNametagSkinsPage"
|
||||
@update:model-value="
|
||||
(e) => {
|
||||
themeStore.hideNametagSkinsPage = !!e
|
||||
settings.hide_nametag_skins_page = themeStore.hideNametagSkinsPage
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="os !== 'MacOS'" class="mt-6 flex items-center justify-between gap-4">
|
||||
<div>
|
||||
<h2 class="m-0 text-lg font-semibold text-contrast">
|
||||
@@ -192,6 +182,44 @@ watch(
|
||||
<Toggle id="minimize-launcher" v-model="settings.hide_on_process_start" />
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="m-0 text-lg font-semibold text-contrast">
|
||||
{{ formatMessage(messages.showPlayTimeTitle) }}
|
||||
</h2>
|
||||
<p class="m-0 mt-1">{{ formatMessage(messages.showPlayTimeDescription) }}</p>
|
||||
</div>
|
||||
<Toggle
|
||||
:model-value="themeStore.getFeatureFlag(showPlayTimeFlag)"
|
||||
@update:model-value="
|
||||
() => {
|
||||
const newValue = !themeStore.getFeatureFlag(showPlayTimeFlag)
|
||||
themeStore.featureFlags[showPlayTimeFlag] = newValue
|
||||
settings.feature_flags[showPlayTimeFlag] = newValue
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="m-0 text-lg font-semibold text-contrast">
|
||||
{{ formatMessage(messages.hideNametagTitle) }}
|
||||
</h2>
|
||||
<p class="m-0 mt-1">{{ formatMessage(messages.hideNametagDescription) }}</p>
|
||||
</div>
|
||||
<Toggle
|
||||
id="hide-nametag-skins-page"
|
||||
:model-value="themeStore.hideNametagSkinsPage"
|
||||
@update:model-value="
|
||||
(e) => {
|
||||
themeStore.hideNametagSkinsPage = !!e
|
||||
settings.hide_nametag_skins_page = themeStore.hideNametagSkinsPage
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="m-0 text-lg font-semibold text-contrast">
|
||||
@@ -226,12 +254,12 @@ watch(
|
||||
<p class="m-0 mt-1">{{ formatMessage(messages.jumpBackIntoWorldsDescription) }}</p>
|
||||
</div>
|
||||
<Toggle
|
||||
:model-value="themeStore.getFeatureFlag(worldsInHomeFeatureFlag)"
|
||||
:model-value="themeStore.getFeatureFlag(worldsInHomeFlag)"
|
||||
@update:model-value="
|
||||
() => {
|
||||
const newValue = !themeStore.getFeatureFlag(worldsInHomeFeatureFlag)
|
||||
themeStore.featureFlags[worldsInHomeFeatureFlag] = newValue
|
||||
settings.feature_flags[worldsInHomeFeatureFlag] = newValue
|
||||
const newValue = !themeStore.getFeatureFlag(worldsInHomeFlag)
|
||||
themeStore.featureFlags[worldsInHomeFlag] = newValue
|
||||
settings.feature_flags[worldsInHomeFlag] = newValue
|
||||
}
|
||||
"
|
||||
/>
|
||||
@@ -245,13 +273,13 @@ watch(
|
||||
<p class="m-0 mt-1">{{ formatMessage(messages.unknownPackWarningDescription) }}</p>
|
||||
</div>
|
||||
<Toggle
|
||||
:model-value="!themeStore.getFeatureFlag(skipUnknownPackWarningFeatureFlag)"
|
||||
:model-value="!themeStore.getFeatureFlag(skipUnknownPackWarningFlag)"
|
||||
@update:model-value="
|
||||
(e) => {
|
||||
const warnBeforeUnknownPackInstall = !!e
|
||||
const skipUnknownPackWarning = !warnBeforeUnknownPackInstall
|
||||
themeStore.featureFlags[skipUnknownPackWarningFeatureFlag] = skipUnknownPackWarning
|
||||
settings.feature_flags[skipUnknownPackWarningFeatureFlag] = skipUnknownPackWarning
|
||||
themeStore.featureFlags[skipUnknownPackWarningFlag] = skipUnknownPackWarning
|
||||
settings.feature_flags[skipUnknownPackWarningFlag] = skipUnknownPackWarning
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
@@ -148,7 +148,6 @@ import { arrayBufferToBase64 } from '@modrinth/utils'
|
||||
import { computed, nextTick, ref, useTemplateRef, watch } from 'vue'
|
||||
|
||||
import {
|
||||
add_and_equip_custom_skin,
|
||||
type Cape,
|
||||
determineModelType,
|
||||
equip_skin,
|
||||
@@ -440,9 +439,22 @@ async function save() {
|
||||
const bytes: Uint8Array = new Uint8Array(await (await fetch(textureUrl)).arrayBuffer())
|
||||
|
||||
if (mode.value === 'new') {
|
||||
const addedSkin = await add_and_equip_custom_skin(bytes, variant.value, selectedCape.value)
|
||||
const addedSkin = await save_custom_skin(
|
||||
{
|
||||
texture_key: '',
|
||||
variant: variant.value,
|
||||
cape_id: selectedCape.value?.id,
|
||||
texture: textureUrl,
|
||||
source: 'custom',
|
||||
is_equipped: false,
|
||||
},
|
||||
bytes,
|
||||
variant.value,
|
||||
selectedCape.value,
|
||||
true,
|
||||
)
|
||||
emit('saved', {
|
||||
applied: true,
|
||||
applied: false,
|
||||
skin: addedSkin,
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
import { useElementSize, useWindowSize } from '@vueuse/core'
|
||||
import { Tooltip } from 'floating-vue'
|
||||
import { computed, nextTick, onUnmounted, ref, useTemplateRef, watch } from 'vue'
|
||||
import Draggable from 'vuedraggable'
|
||||
|
||||
import type { RenderResult } from '@/helpers/rendering/batch-skin-renderer.ts'
|
||||
import type { Skin } from '@/helpers/skins.ts'
|
||||
@@ -82,12 +83,14 @@ const props = defineProps<{
|
||||
isSkinSelected: (skin: Skin) => boolean
|
||||
isSkinActive: (skin: Skin) => boolean
|
||||
isAddSkinButtonDragActive: boolean
|
||||
readOnly?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
select: [skin: Skin]
|
||||
edit: [skin: Skin, event: MouseEvent]
|
||||
delete: [skin: Skin]
|
||||
'reorder-saved-skins': [skins: Skin[]]
|
||||
'add-skin': []
|
||||
'add-skin-dragenter': [event: DragEvent]
|
||||
'add-skin-dragover': [event: DragEvent]
|
||||
@@ -153,6 +156,11 @@ const sections = computed<SkinSection[]>(() => [
|
||||
})),
|
||||
])
|
||||
|
||||
const draggableSavedSkins = ref<Skin[]>([])
|
||||
const isDraggingSavedSkin = ref(false)
|
||||
const canReorderSavedSkins = computed(() => draggableSavedSkins.value.length > 1)
|
||||
const fixedSavedSkins = computed(() => props.savedSkins.filter((skin) => !canDragSavedSkin(skin)))
|
||||
|
||||
const sectionLayouts = computed(() => {
|
||||
const layouts: Array<{ section: SkinSection; top: number; height: number; index: number }> = []
|
||||
let top = 0
|
||||
@@ -209,6 +217,18 @@ watch(
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.savedSkins,
|
||||
(nextSkins) => {
|
||||
if (isDraggingSavedSkin.value) {
|
||||
return
|
||||
}
|
||||
|
||||
draggableSavedSkins.value = nextSkins.filter(canDragSavedSkin)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
watch(
|
||||
listWidth,
|
||||
(width) => {
|
||||
@@ -257,6 +277,40 @@ function skinKey(skin: Skin, prefix: string) {
|
||||
return `${prefix}-${skin.source}-${skin.texture_key}-${skin.variant}-${skin.cape_id ?? 'no-cape'}`
|
||||
}
|
||||
|
||||
function savedSkinKey(skin: Skin) {
|
||||
return skinKey(skin, 'saved-skin')
|
||||
}
|
||||
|
||||
function canDragSavedSkin(skin: Skin) {
|
||||
return skin.source === 'custom' || skin.source === 'custom_external'
|
||||
}
|
||||
|
||||
function doSkinOrdersMatch(firstSkins: Skin[], secondSkins: Skin[]) {
|
||||
const draggableSecondSkins = secondSkins.filter(canDragSavedSkin)
|
||||
|
||||
return (
|
||||
firstSkins.length === draggableSecondSkins.length &&
|
||||
firstSkins.every(
|
||||
(skin, index) => savedSkinKey(skin) === savedSkinKey(draggableSecondSkins[index]),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
function onSavedSkinDragStart() {
|
||||
isDraggingSavedSkin.value = true
|
||||
}
|
||||
|
||||
function onSavedSkinDragEnd() {
|
||||
isDraggingSavedSkin.value = false
|
||||
|
||||
if (doSkinOrdersMatch(draggableSavedSkins.value, props.savedSkins)) {
|
||||
draggableSavedSkins.value = props.savedSkins.filter(canDragSavedSkin)
|
||||
return
|
||||
}
|
||||
|
||||
emit('reorder-saved-skins', [...draggableSavedSkins.value])
|
||||
}
|
||||
|
||||
function isSectionOpen(key: string) {
|
||||
return openSectionKeys.value.has(key)
|
||||
}
|
||||
@@ -354,36 +408,140 @@ defineExpose({ getAddSkinButtonElement })
|
||||
</Tooltip>
|
||||
</template>
|
||||
|
||||
<div
|
||||
<Draggable
|
||||
v-if="section.kind === 'saved'"
|
||||
:list="draggableSavedSkins"
|
||||
class="grid w-full grid-cols-3 gap-3 min-[1300px]:grid-cols-4 min-[1750px]:grid-cols-5 min-[2050px]:grid-cols-6"
|
||||
:item-key="savedSkinKey"
|
||||
:disabled="readOnly || !canReorderSavedSkins"
|
||||
:animation="250"
|
||||
:swap-threshold="1"
|
||||
:invert-swap="false"
|
||||
:force-fallback="true"
|
||||
:fallback-on-body="true"
|
||||
:fallback-tolerance="4"
|
||||
ghost-class="skin-reorder-ghost"
|
||||
chosen-class="skin-reorder-chosen"
|
||||
drag-class="skin-reorder-drag"
|
||||
fallback-class="skin-reorder-fallback"
|
||||
@start="onSavedSkinDragStart"
|
||||
@end="onSavedSkinDragEnd"
|
||||
>
|
||||
<template #header>
|
||||
<SkinLikeTextButton
|
||||
ref="addSkinButton"
|
||||
class="aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
|
||||
dropzone
|
||||
:disabled="readOnly"
|
||||
:drag-active="!readOnly && isAddSkinButtonDragActive"
|
||||
@click="emit('add-skin')"
|
||||
@dragenter="emit('add-skin-dragenter', $event)"
|
||||
@dragover="emit('add-skin-dragover', $event)"
|
||||
@dragleave="emit('add-skin-dragleave', $event)"
|
||||
@drop="emit('add-skin-drop', $event)"
|
||||
>
|
||||
<template #icon>
|
||||
<PlusIcon class="size-8" />
|
||||
</template>
|
||||
{{ formatMessage(messages.addSkinButton) }}
|
||||
<template #subtitle>{{ formatMessage(messages.dragAndDropSubtitle) }}</template>
|
||||
</SkinLikeTextButton>
|
||||
</template>
|
||||
|
||||
<template #item="{ element: skin }">
|
||||
<div
|
||||
:key="savedSkinKey(skin)"
|
||||
class="relative aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
|
||||
>
|
||||
<SkinButton
|
||||
class="h-full w-full min-w-0 box-border rounded-[20px]"
|
||||
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
|
||||
:selected="isSkinSelected(skin)"
|
||||
:active="isSkinActive(skin)"
|
||||
:disabled="readOnly"
|
||||
:is-dragging="isDraggingSavedSkin"
|
||||
@select="emit('select', skin)"
|
||||
>
|
||||
<template v-if="!readOnly" #overlay-buttons>
|
||||
<ButtonStyled color="brand">
|
||||
<button
|
||||
:aria-label="formatMessage(messages.editSkinButton)"
|
||||
class="pointer-events-auto"
|
||||
@click.stop="(event: MouseEvent) => emit('edit', skin, event)"
|
||||
>
|
||||
<EditIcon /> {{ formatMessage(commonMessages.editButton) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-show="!skin.is_equipped" circular color="red">
|
||||
<button
|
||||
v-tooltip="formatMessage(messages.deleteSkinButton)"
|
||||
:aria-label="formatMessage(messages.deleteSkinButton)"
|
||||
class="!rounded-[100%] pointer-events-auto"
|
||||
@click.stop="emit('delete', skin)"
|
||||
>
|
||||
<TrashIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
</SkinButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div
|
||||
v-for="skin in fixedSavedSkins"
|
||||
:key="savedSkinKey(skin)"
|
||||
class="relative aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
|
||||
>
|
||||
<SkinButton
|
||||
class="h-full w-full min-w-0 box-border rounded-[20px]"
|
||||
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
|
||||
:selected="isSkinSelected(skin)"
|
||||
:active="isSkinActive(skin)"
|
||||
:disabled="readOnly"
|
||||
:is-dragging="isDraggingSavedSkin"
|
||||
@select="emit('select', skin)"
|
||||
>
|
||||
<template v-if="!readOnly" #overlay-buttons>
|
||||
<ButtonStyled color="brand">
|
||||
<button
|
||||
:aria-label="formatMessage(messages.editSkinButton)"
|
||||
class="pointer-events-auto"
|
||||
@click.stop="(event: MouseEvent) => emit('edit', skin, event)"
|
||||
>
|
||||
<EditIcon /> {{ formatMessage(commonMessages.editButton) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-show="!skin.is_equipped" circular color="red">
|
||||
<button
|
||||
v-tooltip="formatMessage(messages.deleteSkinButton)"
|
||||
:aria-label="formatMessage(messages.deleteSkinButton)"
|
||||
class="!rounded-[100%] pointer-events-auto"
|
||||
@click.stop="emit('delete', skin)"
|
||||
>
|
||||
<TrashIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
</SkinButton>
|
||||
</div>
|
||||
</template>
|
||||
</Draggable>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="grid w-full grid-cols-3 gap-3 min-[1300px]:grid-cols-4 min-[1750px]:grid-cols-5 min-[2050px]:grid-cols-6"
|
||||
>
|
||||
<SkinLikeTextButton
|
||||
ref="addSkinButton"
|
||||
class="aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
|
||||
dropzone
|
||||
:drag-active="isAddSkinButtonDragActive"
|
||||
@click="emit('add-skin')"
|
||||
@dragenter="emit('add-skin-dragenter', $event)"
|
||||
@dragover="emit('add-skin-dragover', $event)"
|
||||
@dragleave="emit('add-skin-dragleave', $event)"
|
||||
@drop="emit('add-skin-drop', $event)"
|
||||
>
|
||||
<template #icon>
|
||||
<PlusIcon class="size-8" />
|
||||
</template>
|
||||
{{ formatMessage(messages.addSkinButton) }}
|
||||
<template #subtitle>{{ formatMessage(messages.dragAndDropSubtitle) }}</template>
|
||||
</SkinLikeTextButton>
|
||||
|
||||
<SkinButton
|
||||
v-for="skin in section.skins"
|
||||
:key="skinKey(skin, 'saved-skin')"
|
||||
:key="skinKey(skin, section.key)"
|
||||
class="aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
|
||||
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
|
||||
:backward-image-src="getBakedSkinTextures(skin)?.backwards"
|
||||
:selected="isSkinSelected(skin)"
|
||||
:active="isSkinActive(skin)"
|
||||
:tooltip="skin.name"
|
||||
:disabled="readOnly"
|
||||
:is-dragging="isDraggingSavedSkin"
|
||||
@select="emit('select', skin)"
|
||||
>
|
||||
<template #overlay-buttons>
|
||||
@@ -396,37 +554,25 @@ defineExpose({ getAddSkinButtonElement })
|
||||
<EditIcon /> {{ formatMessage(commonMessages.editButton) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-show="!skin.is_equipped" circular color="red">
|
||||
<button
|
||||
v-tooltip="formatMessage(messages.deleteSkinButton)"
|
||||
:aria-label="formatMessage(messages.deleteSkinButton)"
|
||||
class="!rounded-[100%] pointer-events-auto"
|
||||
@click.stop="emit('delete', skin)"
|
||||
>
|
||||
<TrashIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
</SkinButton>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="grid w-full grid-cols-3 gap-3 min-[1300px]:grid-cols-4 min-[1750px]:grid-cols-5 min-[2050px]:grid-cols-6"
|
||||
>
|
||||
<SkinButton
|
||||
v-for="skin in section.skins"
|
||||
:key="skinKey(skin, section.key)"
|
||||
class="aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
|
||||
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
|
||||
:backward-image-src="getBakedSkinTextures(skin)?.backwards"
|
||||
:selected="isSkinSelected(skin)"
|
||||
:active="isSkinActive(skin)"
|
||||
:tooltip="skin.name"
|
||||
@select="emit('select', skin)"
|
||||
/>
|
||||
</div>
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:global(.skin-reorder-ghost) {
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
:global(.skin-reorder-drag) {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
:global(.skin-reorder-fallback) {
|
||||
opacity: 0.9;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -98,6 +98,10 @@ export async function friend_listener(callback) {
|
||||
return await listen('friend', (event) => callback(event.payload))
|
||||
}
|
||||
|
||||
export async function notification_listener(callback) {
|
||||
return await listen('notification', (event) => callback(event.payload))
|
||||
}
|
||||
|
||||
/// Payload for the 'log' event
|
||||
/*
|
||||
LogPayload {
|
||||
|
||||
@@ -197,11 +197,13 @@ export async function add_project_from_version(
|
||||
path: string,
|
||||
versionId: string,
|
||||
reason: DownloadReason,
|
||||
dependentOnVersionId?: string,
|
||||
): Promise<string> {
|
||||
return await invoke('plugin:profile|profile_add_project_from_version', {
|
||||
path,
|
||||
versionId,
|
||||
reason,
|
||||
dependentOnVersionId,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,10 @@ import { skinPreviewStorage } from '../storage/skin-preview-storage'
|
||||
|
||||
export interface RenderResult {
|
||||
forwards: string
|
||||
backwards: string
|
||||
}
|
||||
|
||||
export interface RawRenderResult {
|
||||
forwards: Blob
|
||||
backwards: Blob
|
||||
}
|
||||
|
||||
class BatchSkinRenderer {
|
||||
@@ -92,12 +90,9 @@ class BatchSkinRenderer {
|
||||
}
|
||||
|
||||
const frontCameraPos: [number, number, number] = [-1.3, 1, 6.3]
|
||||
const backCameraPos: [number, number, number] = [-1.3, 1, -2.5]
|
||||
|
||||
const forwards = await this.renderView(frontCameraPos, lookAtTarget)
|
||||
const backwards = await this.renderView(backCameraPos, lookAtTarget)
|
||||
|
||||
return { forwards, backwards }
|
||||
return { forwards }
|
||||
}
|
||||
|
||||
private async renderView(
|
||||
@@ -404,16 +399,15 @@ async function generateSkinPreviewsForGeneration(
|
||||
const headKey = headKeys[i]
|
||||
|
||||
const rawCached = cachedSkinPreviews[skinKey]
|
||||
if (rawCached) {
|
||||
if (rawCached && !skinBlobUrlMap.has(skinKey)) {
|
||||
const cached: RenderResult = {
|
||||
forwards: URL.createObjectURL(rawCached.forwards),
|
||||
backwards: URL.createObjectURL(rawCached.backwards),
|
||||
}
|
||||
skinBlobUrlMap.set(skinKey, cached)
|
||||
}
|
||||
|
||||
const cachedHead = cachedHeadPreviews[headKey]
|
||||
if (cachedHead) {
|
||||
if (cachedHead && !headBlobUrlMap.has(headKey)) {
|
||||
headBlobUrlMap.set(headKey, URL.createObjectURL(cachedHead))
|
||||
}
|
||||
}
|
||||
@@ -427,7 +421,6 @@ async function generateSkinPreviewsForGeneration(
|
||||
if (DEBUG_MODE) {
|
||||
const result = skinBlobUrlMap.get(key)!
|
||||
URL.revokeObjectURL(result.forwards)
|
||||
URL.revokeObjectURL(result.backwards)
|
||||
skinBlobUrlMap.delete(key)
|
||||
} else continue
|
||||
}
|
||||
@@ -456,7 +449,6 @@ async function generateSkinPreviewsForGeneration(
|
||||
|
||||
const renderResult: RenderResult = {
|
||||
forwards: URL.createObjectURL(rawRenderResult.forwards),
|
||||
backwards: URL.createObjectURL(rawRenderResult.backwards),
|
||||
}
|
||||
|
||||
skinBlobUrlMap.set(key, renderResult)
|
||||
|
||||
@@ -142,6 +142,12 @@ export async function remove_custom_skin(skin: Skin): Promise<void> {
|
||||
})
|
||||
}
|
||||
|
||||
export async function set_custom_skin_order(textureKeys: string[]): Promise<void> {
|
||||
await invoke('plugin:minecraft-skins|set_custom_skin_order', {
|
||||
textureKeys,
|
||||
})
|
||||
}
|
||||
|
||||
export async function save_custom_skin(
|
||||
skin: Skin,
|
||||
textureBlob: Uint8Array,
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface LoadingBarType {
|
||||
version?: string
|
||||
profile_path?: string
|
||||
pack_name?: string
|
||||
icon?: string | null
|
||||
}
|
||||
|
||||
export interface LoadingBar {
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { RawRenderResult } from '../rendering/batch-skin-renderer'
|
||||
|
||||
interface StoredPreview {
|
||||
forwards: Blob
|
||||
backwards: Blob
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
@@ -38,7 +37,6 @@ export class SkinPreviewStorage {
|
||||
|
||||
const storedPreview: StoredPreview = {
|
||||
forwards: result.forwards,
|
||||
backwards: result.backwards,
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
|
||||
@@ -67,7 +65,7 @@ export class SkinPreviewStorage {
|
||||
return
|
||||
}
|
||||
|
||||
resolve({ forwards: result.forwards, backwards: result.backwards })
|
||||
resolve({ forwards: result.forwards })
|
||||
}
|
||||
request.onerror = () => reject(request.error)
|
||||
})
|
||||
@@ -95,7 +93,7 @@ export class SkinPreviewStorage {
|
||||
const result = request.result as StoredPreview | undefined
|
||||
|
||||
if (result) {
|
||||
results[key] = { forwards: result.forwards, backwards: result.backwards }
|
||||
results[key] = { forwards: result.forwards }
|
||||
} else {
|
||||
results[key] = null
|
||||
}
|
||||
@@ -173,7 +171,7 @@ export class SkinPreviewStorage {
|
||||
const key = cursor.primaryKey as string
|
||||
const value = cursor.value as StoredPreview
|
||||
|
||||
const entrySize = value.forwards.size + value.backwards.size
|
||||
const entrySize = value.forwards.size
|
||||
totalSize += entrySize
|
||||
count++
|
||||
|
||||
|
||||
+3
@@ -14,6 +14,7 @@ export type GameInstance = {
|
||||
groups: string[]
|
||||
|
||||
linked_data?: LinkedData
|
||||
preferred_update_channel: ReleaseChannel
|
||||
|
||||
created: Date
|
||||
modified: Date
|
||||
@@ -46,6 +47,8 @@ type LinkedData = {
|
||||
locked: boolean
|
||||
}
|
||||
|
||||
type ReleaseChannel = 'release' | 'beta' | 'alpha'
|
||||
|
||||
export type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
|
||||
|
||||
type ContentFile = {
|
||||
|
||||
@@ -5,9 +5,36 @@
|
||||
"app.action-bar.downloads": {
|
||||
"message": "التنزيلات"
|
||||
},
|
||||
"app.action-bar.hide-more-running-instances": {
|
||||
"message": "إخفاء المزيد من الحالات قيد التشغيل"
|
||||
},
|
||||
"app.action-bar.make-primary-instance": {
|
||||
"message": "إنشاء نسخة أساسية"
|
||||
},
|
||||
"app.action-bar.no-instances-running": {
|
||||
"message": "لا توجد نسخ قيد التشغيل"
|
||||
},
|
||||
"app.action-bar.offline": {
|
||||
"message": "غير متصل"
|
||||
},
|
||||
"app.action-bar.primary-instance": {
|
||||
"message": "النسخة ألرئيسية"
|
||||
},
|
||||
"app.action-bar.show-more-running-instances": {
|
||||
"message": "عرض المزيد من النسخ قيد التشغيل"
|
||||
},
|
||||
"app.action-bar.stop-instance": {
|
||||
"message": "إيقاف النسخة"
|
||||
},
|
||||
"app.action-bar.view-active-downloads": {
|
||||
"message": "عرض التحميلات الفعالة"
|
||||
},
|
||||
"app.action-bar.view-instance": {
|
||||
"message": "عرض النسخة"
|
||||
},
|
||||
"app.action-bar.view-logs": {
|
||||
"message": "عرض التسجيل"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.home": {
|
||||
"message": "صفحة الرئيسية"
|
||||
},
|
||||
@@ -209,9 +236,6 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "إدارة الموارد"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "تطبيق Modrinth v{version} جاهز للتثبيت! أعد التحميل للتحديث الآن، أو تلقائيًا عند إغلاق تطبيق Modrinth."
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "انتهى تنزيل تطبيق Modrinth v{version}. أعد التحميل للتحديث الآن، أو تلقائيًا عند إغلاق تطبيق Modrinth."
|
||||
},
|
||||
@@ -242,15 +266,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "تم تثبيت الإصدار {version} بنجاح!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "تنزيل التحديث"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "جار تنزيل التحديث ({percent}٪)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "أعد التحميل لتثبيت التحديث"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "مثال.مودرنث.جج"
|
||||
},
|
||||
@@ -581,6 +596,9 @@
|
||||
"minecraft-account.select-account": {
|
||||
"message": "اختيار الحساب"
|
||||
},
|
||||
"minecraft-account.sign-in": {
|
||||
"message": "سجل دخولك لـ ماينكرافت"
|
||||
},
|
||||
"search.filter.locked.instance": {
|
||||
"message": "مقدَّم من النسخة"
|
||||
},
|
||||
@@ -604,5 +622,8 @@
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "يتم توفير المحمّل من قبل الخادم"
|
||||
},
|
||||
"unknown-pack-warning-modal.dont-show-again": {
|
||||
"message": "لا تعرض هذا التحذير مجددا"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,9 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Vyberte možnost"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Ukázat herní čas"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Umožňí přepínat zobrazení postranního panelu."
|
||||
},
|
||||
@@ -326,8 +329,35 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Správa zdrojů"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Aplikace Modrinth v{version} je připravena k instalaci! Nainstalujte aktualizaci nyní nebo automaticky po zavření aplikace Modrinth."
|
||||
"app.skins.add-button": {
|
||||
"message": "Přidat skin"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Použít"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Smazat skin"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Upravit skin"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Přidat skin"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Upravit skin"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Uložené skiny"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Stahování aplikace Modrinth v{version} bylo dokončeno. Nainstalujte aktualizaci nyní nebo automaticky po zavření aplikace Modrinth."
|
||||
@@ -359,15 +389,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Verze {version} byla úspěšně nainstalována!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Stáhnout aktualizaci"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Stahování aktualizace ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Restartovat aplikaci pro nainstalování aktualizace"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "priklad.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
"app.action-bar.view-logs": {
|
||||
"message": "Vis logs"
|
||||
},
|
||||
"app.appearance-settings.advanced-rendering.description": {
|
||||
"message": "Aktiverer avanceret gengivelse som sløringseffekter, der kan forårsage ydelsesproblemer uden hardwareaccelereret gengivelse."
|
||||
},
|
||||
"app.appearance-settings.advanced-rendering.title": {
|
||||
"message": "Avanceret rendering"
|
||||
},
|
||||
@@ -77,6 +80,18 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Vælg en mulighed"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Vis hvor meget tid du har brugt på at spille en instance."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Vis tid spillet"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Aktivere muligheden for at slå sidepanelet til og fra."
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.title": {
|
||||
"message": "Slå sidepanel til og fra"
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.description": {
|
||||
"message": "Hvis du prøver at installere en Modrinth Pack fil (.mrpack) som ikke er hosted på Modrinth, så skal vi nok sikre os du forstår riskoen før du installere den."
|
||||
},
|
||||
@@ -89,6 +104,15 @@
|
||||
"app.auth-servers.unreachable.header": {
|
||||
"message": "Kan ikke nå autentificeringsservere"
|
||||
},
|
||||
"app.browse.add-servers-to-instance": {
|
||||
"message": "Tilføjet server til instance"
|
||||
},
|
||||
"app.browse.add-to-an-instance": {
|
||||
"message": "Tilføj til en instance"
|
||||
},
|
||||
"app.browse.add-to-instance": {
|
||||
"message": "Tilføj til instance"
|
||||
},
|
||||
"app.browse.add-to-instance-name": {
|
||||
"message": "Tilføjet til {instanceName}"
|
||||
},
|
||||
@@ -98,18 +122,33 @@
|
||||
"app.browse.already-added": {
|
||||
"message": "Allerede tilføjet"
|
||||
},
|
||||
"app.browse.back-to-instance": {
|
||||
"message": "Tilbage til instance"
|
||||
},
|
||||
"app.browse.discover-content": {
|
||||
"message": "Opdag indhold"
|
||||
},
|
||||
"app.browse.discover-servers": {
|
||||
"message": "Opdag servere"
|
||||
},
|
||||
"app.browse.hide-added-servers": {
|
||||
"message": "Gem allerede tilføjet til servere"
|
||||
},
|
||||
"app.browse.project-type.modpacks": {
|
||||
"message": "Modpacks"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Ved at tilføje indhold kan der opstå kompatibilitetsproblemer, når du tilslutter dig serveren. Alt tilføjet indhold går desuden tabt, når du opdaterer indholdet på din server instance."
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Installere"
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
"app.creation-modal.installing-modpack.title": {
|
||||
"message": "Installere modpack..."
|
||||
},
|
||||
"app.export-modal.description-placeholder": {
|
||||
"message": "Indtast modpack beskrivelse..."
|
||||
},
|
||||
@@ -119,12 +158,18 @@
|
||||
"app.export-modal.header": {
|
||||
"message": "Eksporter modpack"
|
||||
},
|
||||
"app.export-modal.include-file-accessibility-label": {
|
||||
"message": "Inkludere \"{file}\"?"
|
||||
},
|
||||
"app.export-modal.modpack-name-label": {
|
||||
"message": "Modpack Navn"
|
||||
},
|
||||
"app.export-modal.modpack-name-placeholder": {
|
||||
"message": "Modpack navn"
|
||||
},
|
||||
"app.export-modal.select-files-label": {
|
||||
"message": "Konfigurer hvilke filer inkludere i denne eksport"
|
||||
},
|
||||
"app.export-modal.version-number-label": {
|
||||
"message": "Versionsnummer"
|
||||
},
|
||||
@@ -149,6 +194,12 @@
|
||||
"app.instance.modpack-already-installed.create": {
|
||||
"message": "Opret"
|
||||
},
|
||||
"app.instance.modpack-already-installed.header": {
|
||||
"message": "Modpack allerede installeret"
|
||||
},
|
||||
"app.instance.modpack-already-installed.instance": {
|
||||
"message": "Instance"
|
||||
},
|
||||
"app.instance.mods.content-type-project": {
|
||||
"message": "projekt"
|
||||
},
|
||||
@@ -167,6 +218,42 @@
|
||||
"app.instance.mods.successfully-uploaded": {
|
||||
"message": "Uploadet"
|
||||
},
|
||||
"app.instance.worlds.add-server": {
|
||||
"message": "Tilføj server"
|
||||
},
|
||||
"app.instance.worlds.browse-servers": {
|
||||
"message": "Søg servere"
|
||||
},
|
||||
"app.instance.worlds.delete-world-title": {
|
||||
"message": "Er du sikker på din vil slette denne verden permanent?"
|
||||
},
|
||||
"app.instance.worlds.filter-modded": {
|
||||
"message": "Moddet"
|
||||
},
|
||||
"app.instance.worlds.filter-offline": {
|
||||
"message": "Offline"
|
||||
},
|
||||
"app.instance.worlds.filter-online": {
|
||||
"message": "Online"
|
||||
},
|
||||
"app.instance.worlds.filter-vanilla": {
|
||||
"message": "Vanilla"
|
||||
},
|
||||
"app.instance.worlds.no-worlds-description": {
|
||||
"message": "Tilføj en server, eller søg efter en for at komme i gang"
|
||||
},
|
||||
"app.instance.worlds.no-worlds-heading": {
|
||||
"message": "Ingen servere eller verdener tilføjet"
|
||||
},
|
||||
"app.instance.worlds.remove-server-title": {
|
||||
"message": "Er du sikker på din vil fjerne {name}?"
|
||||
},
|
||||
"app.instance.worlds.search-worlds-placeholder": {
|
||||
"message": "Søg {count} verdener..."
|
||||
},
|
||||
"app.instance.worlds.this-server": {
|
||||
"message": "denne server"
|
||||
},
|
||||
"app.modal.install-to-play.content-required": {
|
||||
"message": "Indhold krævet"
|
||||
},
|
||||
@@ -203,6 +290,15 @@
|
||||
"app.modal.update-to-play.update-required-description": {
|
||||
"message": "En opdatering er krævet for at spille {name}. Venligst opdater til den seneste version for at køre spillet."
|
||||
},
|
||||
"app.project.install-button.already-installed": {
|
||||
"message": "Dette projekt er allerede installeret"
|
||||
},
|
||||
"app.project.install-context.back-to-browse": {
|
||||
"message": "Tilbage til udforsk"
|
||||
},
|
||||
"app.project.install-context.install-content-to-instance": {
|
||||
"message": "Installer indhold til instance"
|
||||
},
|
||||
"app.settings.developer-mode-enabled": {
|
||||
"message": "Udvikler-tilstand aktiveret."
|
||||
},
|
||||
@@ -227,8 +323,137 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Ressourcestyring"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} er klar til at blive installeret! Genindlæs for at opdatere nu, eller automatisk når du lukker Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Tilføj skin"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Træk og slip"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Brug"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Slet skin"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Dette vil permanent slette det valgte skin. Dette vil ikke kunne blive fortydes."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Er du sikker på, at du vil slette dette skin?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Fejl ved læsning af den afleverede fil."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Fejl under behandling af fil"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Rediger skin"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Tilføj skin"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Tilføjer et skin"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Slank"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Bred"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Kappe"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Kappe"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Rediger skin"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Rediger skinnet først!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Ingen kappe"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Ingen"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Gem skin"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Gemmer..."
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Upload et skin først!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Rediger skin"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Forhåndsvisning"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Du skifter dit skin for ofte. Mojang's servere har midlertidigt blokeret fremtidige anmodninger. Vent venligst et øjeblik for du prøver igen."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Ro på!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Standard skins"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Du modtog disse skins for at donere til en Modrinth Pride indsamling imens der er Pride Month."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Gemte skins"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Log Ind"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Venligst log ind til din Minecraft konto for at kunne funktionerne til at administrere dit skin i Modrinth appen."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Overrasket Modrinth Bot"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Venligst log ind"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Skin vælger"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} er færdig med at download. Genindlæs for at opdatere nu, eller automatisk når du lukker Modrinth App."
|
||||
@@ -260,14 +485,23 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Version {version} var installeret med succes!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Download opdatering"
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "eksemple.modrinth.gg"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Downloader opdatering ({percent}%)"
|
||||
"app.world.server-modal.select-an-option": {
|
||||
"message": "Vælg en mulighed"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Genindlæs for at installere opdatering"
|
||||
"app.world.world-item.incompatible-version": {
|
||||
"message": "Ikke kompatibel version {version}"
|
||||
},
|
||||
"app.world.world-item.not-played-yet": {
|
||||
"message": "Ikke spillet endnu"
|
||||
},
|
||||
"app.world.world-item.offline": {
|
||||
"message": "Offline"
|
||||
},
|
||||
"app.world.world-item.players-online": {
|
||||
"message": "{count} online"
|
||||
},
|
||||
"friends.action.add-friend": {
|
||||
"message": "Tilføj en ven"
|
||||
@@ -368,6 +602,12 @@
|
||||
"instance.edit-world.title": {
|
||||
"message": "Rediger verden"
|
||||
},
|
||||
"instance.files.adding-files": {
|
||||
"message": "Tilføjer filer ({completed}/{total})"
|
||||
},
|
||||
"instance.files.save-as": {
|
||||
"message": "Gem som..."
|
||||
},
|
||||
"instance.server-modal.address": {
|
||||
"message": "Adresse"
|
||||
},
|
||||
@@ -482,6 +722,9 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java og hukommelse"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Indskriv Java argumenter..."
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "Omgivelses variabler"
|
||||
},
|
||||
@@ -497,6 +740,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Allokeret hukommelse"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/vej/til/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Vindue"
|
||||
},
|
||||
@@ -569,6 +815,24 @@
|
||||
"instance.worlds.world_in_use": {
|
||||
"message": "Verden er i brug"
|
||||
},
|
||||
"minecraft-account.add-account": {
|
||||
"message": "Tilføj konto"
|
||||
},
|
||||
"minecraft-account.label": {
|
||||
"message": "Minecraft konto"
|
||||
},
|
||||
"minecraft-account.not-signed-in": {
|
||||
"message": "Ikke logged ind"
|
||||
},
|
||||
"minecraft-account.remove-account": {
|
||||
"message": "Fjern konto"
|
||||
},
|
||||
"minecraft-account.select-account": {
|
||||
"message": "Vælg konto"
|
||||
},
|
||||
"minecraft-account.sign-in": {
|
||||
"message": "Log ind på Minecraft"
|
||||
},
|
||||
"search.filter.locked.instance": {
|
||||
"message": "Givet af instanceen"
|
||||
},
|
||||
@@ -592,5 +856,20 @@
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader er givet af serveren"
|
||||
},
|
||||
"unknown-pack-warning-modal.body": {
|
||||
"message": "En fil behandles kun, hvis den uploades til Modrinth, uanset filformat (herunder .mrpack)."
|
||||
},
|
||||
"unknown-pack-warning-modal.dont-show-again": {
|
||||
"message": "Vis ikke denne advarsel igen"
|
||||
},
|
||||
"unknown-pack-warning-modal.header": {
|
||||
"message": "Bekræft installation"
|
||||
},
|
||||
"unknown-pack-warning-modal.install-anyway": {
|
||||
"message": "Installer alligevel"
|
||||
},
|
||||
"unknown-pack-warning-modal.warning.title": {
|
||||
"message": "Ukendt fil advarsel"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Option wählen"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Zeigt an, wie viel Zeit du mit dem Spielen einer Instanz verbracht hast."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Spielzeit anzeigen"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Ermöglicht das Umschalten der Seitenleiste."
|
||||
},
|
||||
@@ -143,6 +149,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Wird installiert"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Keine verfügbaren Versionen stimmen mit {compatibilityLabel} überein. Wähle eine Version aus, um sie trotzdem zu installieren. Abhängigkeiten werden nicht automatisch installiert."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -294,7 +303,7 @@
|
||||
"message": "Dieses Projekt ist bereits installiert"
|
||||
},
|
||||
"app.project.install-context.back-to-browse": {
|
||||
"message": "Zurück zum Entdecken"
|
||||
"message": "Zurück zu Entdecken"
|
||||
},
|
||||
"app.project.install-context.install-content-to-instance": {
|
||||
"message": "Inhalt in Instanz installieren"
|
||||
@@ -323,8 +332,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Ressourcenmanagement"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} ist bereit zur Installation! Lade die App neu um jetzt zu aktualisieren, oder automatisch nach dem schliessen der Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Skin hinzufügen"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Drag-and-Drop"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Anwenden"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Skin löschen"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Dies wird den ausgewählten Skin unwiderruflich löschen. Diese Aktion kann nicht rückgängig gemacht werden."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Bist du dir sicher, dass du diesen Skin löschen willst?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Fehler beim Lesen der abgelegten Datei."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Fehler bei der Dateiverarbeitung"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Skin bearbeiten"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Skin hinzufügen"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Skin wird hinzugefügt"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Arm Stil"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Schlank"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Breit"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Umhang"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Umhang"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Skin bearbeiten"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Nimm zuerst eine Änderung am Skin vor!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Kein Umhang"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Keines"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Textur ersetzen"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Skin speichern"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Speichern..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Textur"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Lade zuerst einen Skin hoch!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Skin bearbeiten"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Vorschau"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Du änderst deinen Skin zu oft. Die Server von Mojang haben weitere Anfragen vorübergehend blockiert. Bitte warte einen Moment, bevor du es erneut versuchst."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Nicht so schnell!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Standard-Skins"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Du hast diese Skins als Dankeschön für eine Spende bei der Modrinth Pride Spendenaktion während des Pride Month erhalten."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Gespeicherte Skins"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Anmelden"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Bitte melde dich in deinem Minecraft-Konto an, um die Skin-Verwaltungsfunktionen der Modrinth App zu nutzen."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Begeisterter Modrinth-Bot"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Bitte anmelden"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Skin-Auswahl"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} wurde heruntergeladen. Lade die App neu um jetzt zu aktualisieren, oder automatisch nach dem schliessen der Modrinth App."
|
||||
@@ -356,15 +503,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Version {version} wurde erfolgreich installiert!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Aktualisierung herunterladen"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Lade Aktualisierung herunter ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Lade neu um Aktualisierung zu installieren"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -602,6 +740,24 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java und Arbeitsspeicher"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "Benutzerdefinierte Umgebungsvariablen"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "Benutzerdefinierte Java-Argumente"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "Benutzerdefinierte Java-Installation"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "Benutzerdefinierte Speicherzuweisung"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "Umgebungsvariablen eingeben..."
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Java-Argumente eingeben..."
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "Umgebungsvariablen"
|
||||
},
|
||||
@@ -617,6 +773,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Zugewiesener Arbeitsspeicher"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/pfad/zu/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Spielfenster"
|
||||
},
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
"message": "Farbschema"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.description": {
|
||||
"message": "Ändere die Kategorie, die beim Öffnen des Launchers angezeigt wird."
|
||||
"message": "Ändere die Seite, die beim Öffnen des Launchers angezeigt wird."
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.home": {
|
||||
"message": "Start"
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Wähle eine Option"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Zeigt an, wie viel Zeit du damit verbracht hast, eine Instanz zu spielen."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Spielzeit anzeigen"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Ermöglicht das Umschalten der Seitenleiste."
|
||||
},
|
||||
@@ -143,6 +149,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Wird installiert"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Keine verfügbaren Versionen stimmen mit {compatibilityLabel} überein. Wähle eine Version aus, um sie trotzdem zu installieren. Abhängigkeiten werden nicht automatisch installiert."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -323,8 +332,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Ressourcenmanagement"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} ist bereit zur Installation! Neu laden, um jetzt zu aktualisieren, oder automatisch, wenn du die Modrinth App schließt."
|
||||
"app.skins.add-button": {
|
||||
"message": "Skin hinzufügen"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Ziehen und Ablegen"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Anwenden"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Skin löschen"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Dadurch wird der ausgewählte Skin permanent gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Möchtest du diesen Skin wirklich löschen?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Die abgelegte Datei konnte nicht gelesen werden."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Fehler bei der Verarbeitung der Datei"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Skin bearbeiten"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Skin hinzufügen"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Einen Skin hinzufügen"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Arm-Stil"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Schlank"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Breit"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Umhang"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Umhang"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Skin bearbeiten"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Nimm zuerst eine Änderung am Skin vor!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Kein Umhang"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Keinen"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Textur ersetzen"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Skin speichern"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Wird gespeichert..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Textur"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Lade zuerst ein Skin hoch!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Skin bearbeiten"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Vorschau"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Du wechselst dein Skin zu oft. Die Server von Mojang haben weitere Anfragen vorübergehend blockiert. Bitte warte einen Moment, bevor du es erneut versuchst."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Langsamer!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Standard-Skins"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Du hast diese Skins erhalten, da du während des Pride-Monats für eine Modrinth-Pride-Spendenaktion gespendet hast."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Gespeicherte Skins"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Anmelden"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Bitte melde dich bei deinem Minecraft-Konto an, um die Funktionen zur Skin-Verwaltung der Modrinth-App nutzen zu können."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Begeisterter Modrinth-Bot"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Bitte melde dich an"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Skin-Auswahl"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} wurde heruntergeladen. Neu laden, um jetzt zu aktualisieren, oder automatisch aktualisieren, wenn du die Modrinth App schließt."
|
||||
@@ -356,15 +503,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Version {version} wurde erfolgreich installiert!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Update herunterladen"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Update wird heruntergeladen ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Neu laden, um das Update zu installieren"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -602,6 +740,24 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java und Arbeitsspeicher"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "Benutzerdefinierte Umgebungsvariablen"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "Benutzerdefinierte Java-Argumente"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "Benutzerdefinierte Java-Installation"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "Benutzerdefinierte Speicherzuweisung"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "Umgebungsvariablen eingeben..."
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Java-Argumente eingeben..."
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "Umgebungsvariablen"
|
||||
},
|
||||
@@ -617,6 +773,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Zugewiesener Arbeitsspeicher"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/pfad/zu/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Fenster"
|
||||
},
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
"app.action-bar.downloading-java": {
|
||||
"message": "Downloading Java {version}"
|
||||
},
|
||||
"app.action-bar.downloading-update": {
|
||||
"message": "Downloading update"
|
||||
},
|
||||
"app.action-bar.downloads": {
|
||||
"message": "Downloads"
|
||||
},
|
||||
@@ -20,12 +23,18 @@
|
||||
"app.action-bar.primary-instance": {
|
||||
"message": "Primary instance"
|
||||
},
|
||||
"app.action-bar.reload-to-update": {
|
||||
"message": "Reload to update"
|
||||
},
|
||||
"app.action-bar.show-more-running-instances": {
|
||||
"message": "Show more running instances"
|
||||
},
|
||||
"app.action-bar.stop-instance": {
|
||||
"message": "Stop instance"
|
||||
},
|
||||
"app.action-bar.update": {
|
||||
"message": "Update"
|
||||
},
|
||||
"app.action-bar.view-active-downloads": {
|
||||
"message": "View active downloads"
|
||||
},
|
||||
@@ -86,6 +95,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Select an option"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Displays how much time you've spent playing an instance."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Show play time"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Enables the ability to toggle the sidebar."
|
||||
},
|
||||
@@ -143,6 +158,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Installing"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "No available versions match {compatibilityLabel}. Select a version to install anyway. Dependencies will not be installed automatically."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -419,6 +437,12 @@
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Slow down!"
|
||||
},
|
||||
"app.skins.reorder-error.text": {
|
||||
"message": "Your skin order could not be saved."
|
||||
},
|
||||
"app.skins.reorder-error.title": {
|
||||
"message": "Failed to reorder skins"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
@@ -473,9 +497,6 @@
|
||||
"app.skins.title": {
|
||||
"message": "Skin selector"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} is ready to install! Reload to update now, or automatically when you close Modrinth App."
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} has finished downloading. Reload to update now, or automatically when you close Modrinth App."
|
||||
},
|
||||
@@ -495,7 +516,7 @@
|
||||
"message": "Download complete"
|
||||
},
|
||||
"app.update-popup.reload": {
|
||||
"message": "Reload"
|
||||
"message": "Reload to update"
|
||||
},
|
||||
"app.update-popup.title": {
|
||||
"message": "Update available"
|
||||
@@ -506,15 +527,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Version {version} was successfully installed!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Download update"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Downloading update ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Reload to install update"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -704,6 +716,30 @@
|
||||
"instance.settings.tabs.general.name": {
|
||||
"message": "Name"
|
||||
},
|
||||
"instance.settings.tabs.general.update-channel": {
|
||||
"message": "Update channel"
|
||||
},
|
||||
"instance.settings.tabs.general.update-channel.alpha": {
|
||||
"message": "Alpha"
|
||||
},
|
||||
"instance.settings.tabs.general.update-channel.alpha.description": {
|
||||
"message": "Release, beta, and alpha versions will be shown as available updates."
|
||||
},
|
||||
"instance.settings.tabs.general.update-channel.beta": {
|
||||
"message": "Beta"
|
||||
},
|
||||
"instance.settings.tabs.general.update-channel.beta.description": {
|
||||
"message": "Release and beta versions will be shown as available updates."
|
||||
},
|
||||
"instance.settings.tabs.general.update-channel.release": {
|
||||
"message": "Release"
|
||||
},
|
||||
"instance.settings.tabs.general.update-channel.release.description": {
|
||||
"message": "Only release versions will be shown as available updates."
|
||||
},
|
||||
"instance.settings.tabs.general.update-channel.select": {
|
||||
"message": "Select update channel"
|
||||
},
|
||||
"instance.settings.tabs.hooks": {
|
||||
"message": "Launch hooks"
|
||||
},
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Selecciona una opción"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Muestra cuánto tiempo has estado jugando en una instancia."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Mostrar tiempo de juego"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Permite mostrar u ocultar la barra lateral."
|
||||
},
|
||||
@@ -143,6 +149,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Instalando"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "No hay versiones disponibles que coincidan con {compatibilityLabel}. Selecciona una versión para instalarla de todas formas. Las dependencias no se instalarán automáticamente."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -291,10 +300,10 @@
|
||||
"message": "Se requiere una actualización para jugar {name}. Por favor, actualiza a la versión más reciente para iniciar el juego."
|
||||
},
|
||||
"app.project.install-button.already-installed": {
|
||||
"message": "Este proyecto está actualmente instalado"
|
||||
"message": "Este proyecto ya está instalado"
|
||||
},
|
||||
"app.project.install-context.back-to-browse": {
|
||||
"message": "Volver al explorador"
|
||||
"message": "Volver a descubrir contenido"
|
||||
},
|
||||
"app.project.install-context.install-content-to-instance": {
|
||||
"message": "Instalar contenido a la instancia"
|
||||
@@ -323,8 +332,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Gestión de recursos"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "¡Modrinth App v{version} está lista para instalarse! Actualiza ahora o automáticamente al cerrar la Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Añadir skin"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Arrastrar y soltar"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Aplicar"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Eliminar skin"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Esto eliminará permanentemente el skin seleccionado. Esta acción no se puede deshacer."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "¿Estás seguro de que quieres eliminar este skin?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Error al leer el archivo arrastrado."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Error al procesar el archivo"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Editar skin"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Añadir skin"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Añadiendo un skin"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Estilo de brazo"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Delgado"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Ancho"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Capa"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Capa"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Editando skin"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "¡Primero edita el skin!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Sin capa"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Ninguna"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Remplazar textura"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Guardar skin"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Guardando..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Textura"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "¡Primero carga un skin!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Editar skin"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Previsualizando"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Estás cambiando tu skin muy frecuentemente. Los servidores de Mojang han bloqueado temporalmente las solicitdues futuras. Por favor, espera un momento antes de volver a intentarlo."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "¡Más despacio!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Constructores y Biomas"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Persigue los Cielos"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Skins predeterminadas"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Orgullo Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Has recibido estas skins por donar a la fundación Orgullo Modrinth durante el Mes del Orgullo."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Monturas del Caos"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Skins guardados"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "La Era del Cobre"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "El Jardín Despierta"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Bebés al Poder"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Iniciar sesión"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Por favor, inicia sesión en tu cuenta de Minecraft para poder utilizar las funciones de gestión de skins de la Modrinth App."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Modrinth Bot emocionado"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Por favor, inicia sesión"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Selector de skin"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "La descarga de la Modrinth App v{version} ha finalizado. Actualiza ahora o automáticamente al cerrar la Modrinth App."
|
||||
@@ -356,15 +503,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "¡La versión {version} se ha instalado correctamente!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Descargar actualización"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Descargando actualización ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Recarga para instalar la actualización"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "ejemplo.modrinth.gg"
|
||||
},
|
||||
@@ -636,7 +774,7 @@
|
||||
"message": "Memoria asignada"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/ruta/a/java"
|
||||
"message": "/ruta/de/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Ventana"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"message": "Ocultar más instancias en ejecución"
|
||||
},
|
||||
"app.action-bar.make-primary-instance": {
|
||||
"message": "Hacer instancia principal"
|
||||
"message": "Establecer como instancia principal"
|
||||
},
|
||||
"app.action-bar.no-instances-running": {
|
||||
"message": "Ninguna instancia en ejecución"
|
||||
@@ -24,16 +24,16 @@
|
||||
"message": "Mostrar más instancias en ejecución"
|
||||
},
|
||||
"app.action-bar.stop-instance": {
|
||||
"message": "Finalizar instancia"
|
||||
"message": "Detener instancia"
|
||||
},
|
||||
"app.action-bar.view-active-downloads": {
|
||||
"message": "Mostrar descargas activas"
|
||||
},
|
||||
"app.action-bar.view-instance": {
|
||||
"message": "Mostrar instancia"
|
||||
"message": "Ver instancia"
|
||||
},
|
||||
"app.action-bar.view-logs": {
|
||||
"message": "Mostrar registros"
|
||||
"message": "Ver registros"
|
||||
},
|
||||
"app.appearance-settings.advanced-rendering.description": {
|
||||
"message": "Habilita el renderizado avanzado, como los efectos de desenfoque, que pueden causar problemas de rendimiento sin renderizado acelerado por hardware."
|
||||
@@ -42,43 +42,43 @@
|
||||
"message": "Renderizado avanzado"
|
||||
},
|
||||
"app.appearance-settings.color-theme.description": {
|
||||
"message": "Seleccione su tema de color preferido para Modrinth en este dispositivo."
|
||||
"message": "Selecciona tu tema de color preferido para la Modrinth App."
|
||||
},
|
||||
"app.appearance-settings.color-theme.title": {
|
||||
"message": "Tema de color"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.description": {
|
||||
"message": "Cambia la página en la que el lanzador inicia."
|
||||
"message": "Cambia la página que se abre al iniciar el lanzador."
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.home": {
|
||||
"message": "Inicio"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.library": {
|
||||
"message": "Librería"
|
||||
"message": "Biblioteca"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.title": {
|
||||
"message": "Página predeterminada"
|
||||
"message": "Página de inicio predeterminada"
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.description": {
|
||||
"message": "Desactiva la etiqueta arriba de tu personaje en la página de skins."
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.title": {
|
||||
"message": "Ocultar etiqueta"
|
||||
"message": "Ocultar etiqueta de nombre"
|
||||
},
|
||||
"app.appearance-settings.jump-back-into-worlds.description": {
|
||||
"message": "Incluye los mundos más recientes en la sección \"Vuelve a jugar tus mundos\" en la página de inicio."
|
||||
"message": "Incluye los mundos recientes en la sección \"Volver a jugar\" de la página de inicio."
|
||||
},
|
||||
"app.appearance-settings.jump-back-into-worlds.title": {
|
||||
"message": "Vuelve a jugar tus mundos"
|
||||
"message": "Volver a jugar en tus mundos"
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.description": {
|
||||
"message": "Minimiza el lanzador cuando un proceso de Minecraft empieza."
|
||||
"message": "Minimiza el lanzador cuando se inicia un proceso de Minecraft."
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.title": {
|
||||
"message": "Minimiza el lanzador"
|
||||
"message": "Minimizar lanzador"
|
||||
},
|
||||
"app.appearance-settings.native-decorations.description": {
|
||||
"message": "Usa los sistemas de marco de Windows (se requiere resetear la aplicación)."
|
||||
"message": "Usa el marco de ventana del sistema (requiere reiniciar la aplicación)."
|
||||
},
|
||||
"app.appearance-settings.native-decorations.title": {
|
||||
"message": "Decoraciones nativas"
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Selecciona una opción"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Muestra cuánto tiempo has estado jugando en una instancia."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Mostrar tiempo de juego"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Activa la posibilidad de alternar la barra lateral."
|
||||
},
|
||||
@@ -96,7 +102,7 @@
|
||||
"message": "Si intentas instalar un archivo de paquete de Modrinth (.mrpack) que no esté alojado en Modrinth, debes comprender los riesgos que esto conlleva antes de instalarlo."
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.title": {
|
||||
"message": "Advertir antes de instalarme paquetes de mods desconocidos"
|
||||
"message": "Adviérteme antes de instalarme modpacks desconocidos"
|
||||
},
|
||||
"app.auth-servers.unreachable.body": {
|
||||
"message": "Los servidores de autenticación de Minecraft pueden no estar funcionando en este momento. Verifica tu conexión a internet e inténtalo de nuevo más tarde."
|
||||
@@ -105,7 +111,7 @@
|
||||
"message": "No se puede conectar con los servidores de autenticación"
|
||||
},
|
||||
"app.browse.add-servers-to-instance": {
|
||||
"message": "Añadir servidor a instancia"
|
||||
"message": "Añadiendo servidor a la instancia"
|
||||
},
|
||||
"app.browse.add-to-an-instance": {
|
||||
"message": "Añadir a una instancia"
|
||||
@@ -135,7 +141,7 @@
|
||||
"message": "Ocultar servidores ya añadidos"
|
||||
},
|
||||
"app.browse.project-type.modpacks": {
|
||||
"message": "Paquetes de Mods"
|
||||
"message": "Modpacks"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Añadir contenido puede comprometer la compatibilidad a la hora de unirse a un servidor. Cualquier contenido añadido se perderá cuando actualices la instancia del servidor."
|
||||
@@ -143,11 +149,14 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Instalando"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "No hay versiones disponibles que coincidan con {compatibilityLabel}. Selecciona una versión para instalarla de todas formas. Las dependencias no se instalarán automáticamente."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
"app.creation-modal.installing-modpack.title": {
|
||||
"message": "Instalando el modpack..."
|
||||
"message": "Instalando modpack..."
|
||||
},
|
||||
"app.export-modal.description-placeholder": {
|
||||
"message": "Escribe la descripción del modpack..."
|
||||
@@ -332,8 +341,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Gestión de recursos"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "¡La versión v{version} de Modrinth está lista para instalarse! Actualiza ahora o automáticamente al cerrar la aplicación."
|
||||
"app.skins.add-button": {
|
||||
"message": "Añadir skin"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Arrastrar y soltar"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Aplicar"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Borrar skin"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Esto borrará permanentemente la skin seleccionada. Esta acción no se puede deshacer."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "¿Estás seguro/a de que quieres eliminar está skin?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Error al leer el archivo arrastrado."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Error al procesar el archivo"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Editar skin"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Añadir skin"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Añadiendo una skin"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Estilo de brazo"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Delgado"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Ancho"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Capa"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Capa"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Editando skin"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "¡Modifica la skin primero!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Sin capa"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Nada"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Reemplazar textura"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Guardar skin"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Guardando..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Textura"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "¡Primero sube una skin!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Editar skin"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Previsualizando"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Estuviste cambiando tu skin demasiado rápido. Los servidores de Mojang han bloqueado temporalmente tus futuras solicitaciones. Por favor, espere un momento antes de intentar de nuevo."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "¡Cálmate!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders y Biomas"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Persigue los cielos"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Skins por defecto"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Orgullo Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Has recibido estas skins por donar a la fundación Orgullo Modrinth durante el Mes del Orgullo."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Monturas del Caos"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Skins guardadas"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "La Edad de Cobre"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "El Jardín Despierta"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Pequeña Invasión"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Iniciar Sesión"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Por favor, inicia sesión con tu cuenta de Minecraft para usar las funciones del administrador de Skins de la app de Modrinth."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Modrinth Bot emocionado"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Por favor, inicia sesión"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Selector de Skin"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} se ha descargado. Actualiza la página ahora o espera a que se actualice automáticamente al cerrar Modrinth App."
|
||||
@@ -365,15 +512,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "¡La versión {version} se ha instalado correctamente!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Descarga actualización"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Descargando actualización ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Recarga para instalar la actualización"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "ejemplo.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -332,9 +332,6 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Resurssien hallinta"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App versio {version} on valmis asennettavaksi. Voit käynnistää sovelluksen uudelleen päivittääksesi heti tai antaa päivityksen asentua automaattisesti, kun suljet Modrinth Appin."
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App versio {version} on ladattu. Voit käynnistää sovelluksen uudelleen päivittääksesi heti tai antaa päivityksen asentua automaattisesti, kun suljet Modrinth Appin."
|
||||
},
|
||||
@@ -365,15 +362,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Versio {version} asennettiin onnistuneesti!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Lataa päivitys"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Ladataan päivitystä ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Lataa uudelleen asentaaksesi päivityksen"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -104,6 +104,12 @@
|
||||
"app.auth-servers.unreachable.header": {
|
||||
"message": "Hindi maabot ang mga authentication server"
|
||||
},
|
||||
"app.browse.add-servers-to-instance": {
|
||||
"message": "Idinaragdag ang server sa instansiya"
|
||||
},
|
||||
"app.browse.add-to-an-instance": {
|
||||
"message": "Idagdag sa instansiya"
|
||||
},
|
||||
"app.browse.add-to-instance": {
|
||||
"message": "Idagdag sa instansiya"
|
||||
},
|
||||
@@ -116,6 +122,9 @@
|
||||
"app.browse.already-added": {
|
||||
"message": "Nadagdag na"
|
||||
},
|
||||
"app.browse.back-to-instance": {
|
||||
"message": "Bumalik sa instansiya"
|
||||
},
|
||||
"app.browse.discover-content": {
|
||||
"message": "Tumuklas ng kontento"
|
||||
},
|
||||
@@ -128,6 +137,9 @@
|
||||
"app.browse.project-type.modpacks": {
|
||||
"message": "Modpacks"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Maaaring makasisira sa pagkakatugma sa pagsasali ng server ang pagdaragdag ng kontento. Ang anumang kontento ay mawawala sa pag-update ng kontento ng instansiyang pang-server."
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Ini-install"
|
||||
},
|
||||
@@ -287,6 +299,12 @@
|
||||
"app.modal.update-to-play.update-required-description": {
|
||||
"message": "Kailangang mag-update upang malaro ang {name}. Mangyaring mag-update sa pinakabagong bersiyon upang ma-launch ang laro."
|
||||
},
|
||||
"app.project.install-button.already-installed": {
|
||||
"message": "Naka-install na ang proyektong ito"
|
||||
},
|
||||
"app.project.install-context.back-to-browse": {
|
||||
"message": "Bumalik sa pagtutuklas"
|
||||
},
|
||||
"app.settings.developer-mode-enabled": {
|
||||
"message": "Binuksan ang moda ng nagdi-develop."
|
||||
},
|
||||
@@ -311,8 +329,35 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Pamamahala ng paglalaan"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Ang Modrinth App v{version} ay handa nang ma-install. Mag-reload upang ma-update ngayon, o awtomatiko sa pagsara ng Modrinth App."
|
||||
"app.skins.apply-button": {
|
||||
"message": "Ilapat"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Payat"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Malapad"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Kapa"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Kapa"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Walang kapa"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Wala"
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Texture"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Tapos nang ma-download ang Modrinth App v{version}. Mag-reload upang ma-update ngayon, o awtomatiko sa pagsara ng Modrinth App."
|
||||
@@ -344,15 +389,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Tagumpay na na-install ang bersiyong {version}!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "I-download ang update"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Nagdadownload ng update ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Handang ma-install ang update"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -45,13 +45,13 @@
|
||||
"message": "Sélectionnez votre couleur préférée pour le thème de Modrinth App."
|
||||
},
|
||||
"app.appearance-settings.color-theme.title": {
|
||||
"message": "Thème couleur"
|
||||
"message": "Couleur du thème"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.description": {
|
||||
"message": "Modifier la page sur laquelle le lancheur s'ouvre."
|
||||
"message": "Modifier la page sur laquelle le lanceur s'ouvre."
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.home": {
|
||||
"message": "Acceuil"
|
||||
"message": "Accueil"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.library": {
|
||||
"message": "Bibliothèque"
|
||||
@@ -72,10 +72,10 @@
|
||||
"message": "Mondes sur partie rapide"
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.description": {
|
||||
"message": "Minimiser le launcher quand Minecraft démarre."
|
||||
"message": "Minimiser le lanceur quand Minecraft démarre."
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.title": {
|
||||
"message": "Minimiser le launcher"
|
||||
"message": "Minimiser le lanceur"
|
||||
},
|
||||
"app.appearance-settings.native-decorations.description": {
|
||||
"message": "Utiliser le cadre fenêtre du système (redémarrage de l'application requis)."
|
||||
@@ -86,8 +86,14 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Sélectionnez une option"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Affiche combien de temps vous avez passé sur une instance."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Afficher le temps de jeu"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Permet d'ouvrir de de fermer la barre latérale."
|
||||
"message": "Permet d'ouvrir de fermer la barre latérale."
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.title": {
|
||||
"message": "Tiroir latéral"
|
||||
@@ -143,6 +149,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Installation en cours"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Aucune version disponible ne correspond à {compatibilityLabel}. Sélectionnez une version pour l'installer malgré tout. Les dépendances ne seront pas installées automatiquement."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -323,8 +332,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Gestion des ressources"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} est prête à être installée ! Relancez l'application pour faire la mise à jour maintenant, ou automatiquement à la fermeture de Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Ajouter une skin"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Glisser et déposer"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Appliquer"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Supprimer le skin"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Cela va supprimer de manière permanente ce skin. Cette action est irréversible."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Êtes-vous sûr de vouloir supprimer cette skin ?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Impossible de lire le fichier déposé."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Erreur lors du traitement du fichier"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Modifier le skin"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Ajouter une skin"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Ajouter une skin"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Bras"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Mince"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Large"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Cape"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Cape"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Modification du skin"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Faites d'abord une modification à la skin !"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Aucune cape"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Aucune"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Remplacer la texture"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Sauvegarder le skin"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Sauvegarde..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Texture"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Importez d'abord une skin !"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Modifier le skin"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Aperçu"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Vous changez de skin trop vite. Les serveurs de Mojang ont temporairement bloqué certaines requêtes. Veuillez patienter un moment puis réessayez."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Du calme !"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chassez les cieux"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Skins par défaut"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Vous avez reçu ces skins pour avoir fait un don à une collecte de fonds Modrinth Pride pendant le mois de la fierté."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Montures en pagaille"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Skins sauvegardées"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "L'éveil du jardin"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Horde miniature"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Se connecter"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Veuillez vous connecter à votre compte Minecraft pour utiliser les fonctionnalités de gestion de skins de Modrinth App."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Bot Modrinth enthousiaste"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Veuillez vous connecter"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Sélecteur de skin"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} a finie d'être téléchargée. Rechargez pour mettre à jour maintenant, ou automatiquement quand vous fermez Modrinth App."
|
||||
@@ -356,15 +503,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "La version {version} a été téléchargée avec succès !"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Télécharger la mise à jour"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Téléchargement de la mise à jour ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Relancez l'application pour installer la mise à jour"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "exemple.modrinth.gg"
|
||||
},
|
||||
@@ -632,6 +770,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Mémoire allouée"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/chemin/vers/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Fenêtre"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
{
|
||||
"app.action-bar.downloads": {
|
||||
"message": "הורדות"
|
||||
},
|
||||
"app.action-bar.offline": {
|
||||
"message": "לא מקוון"
|
||||
},
|
||||
"app.action-bar.stop-instance": {
|
||||
"message": ""
|
||||
},
|
||||
"app.appearance-settings.advanced-rendering.description": {
|
||||
"message": "מאפשר עיבוד מתקדם כגון אפקטים טשטוש העלולים לגרום לבעיות ביצועים ללא עיבוד מואץ לחומרה."
|
||||
},
|
||||
"app.auth-servers.unreachable.body": {
|
||||
"message": "ייתכן ששרתי האימות של Minecraft מושבתים כרגע. יש לבדוק את חיבור האינטרנט שלך ולנסות שוב מאוחר יותר."
|
||||
},
|
||||
@@ -191,9 +203,6 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "ניהול משאבים"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} מוכנה להורדה!\nיש לרענן כדי לעדכן עכשיו, או באופן אוטומטי בעת סגירת האפליקציה."
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} סיימה את תהליך ההורדה. יש לרענן כדי לעדכן עכשיו, או באופן אוטומטי בעת סגירת האפליקציה."
|
||||
},
|
||||
@@ -224,15 +233,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "גרסה {version} הותקנה בהצלחה!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "הורדת עדכון"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "מוריד עדכון ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "צריך לרענן כדי להתקין את העדכון"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -6,31 +6,31 @@
|
||||
"message": "Letöltések"
|
||||
},
|
||||
"app.action-bar.hide-more-running-instances": {
|
||||
"message": "További futó profilok elrejtése"
|
||||
"message": "További futó példányok elrejtése"
|
||||
},
|
||||
"app.action-bar.make-primary-instance": {
|
||||
"message": "Beállítás elsődleges profilként"
|
||||
"message": "Beállítás elsődleges példányként"
|
||||
},
|
||||
"app.action-bar.no-instances-running": {
|
||||
"message": "Nincsenek futó profilok"
|
||||
"message": "Nincsenek futó példányok"
|
||||
},
|
||||
"app.action-bar.offline": {
|
||||
"message": "Offline"
|
||||
},
|
||||
"app.action-bar.primary-instance": {
|
||||
"message": "Elsődleges profil"
|
||||
"message": "Elsődleges példány"
|
||||
},
|
||||
"app.action-bar.show-more-running-instances": {
|
||||
"message": "További futó profilok megjelenítése"
|
||||
"message": "További futó pédányok megjelenítése"
|
||||
},
|
||||
"app.action-bar.stop-instance": {
|
||||
"message": "Profil megállítása"
|
||||
"message": "Példány leállítása"
|
||||
},
|
||||
"app.action-bar.view-active-downloads": {
|
||||
"message": "Aktív letöltések megtekintése"
|
||||
},
|
||||
"app.action-bar.view-instance": {
|
||||
"message": "Profil megtekintése"
|
||||
"message": "Példányok megtekintése"
|
||||
},
|
||||
"app.action-bar.view-logs": {
|
||||
"message": "Naplók megtekintése"
|
||||
@@ -60,7 +60,7 @@
|
||||
"message": "Alapértelmezett nyitóoldal"
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.description": {
|
||||
"message": "Letiltja a játékosod felett megjelenő névcímkét a Skinek oldalon."
|
||||
"message": "Letiltja a játékosod felett megjelenő névcímkét a Kinézetek oldalon."
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.title": {
|
||||
"message": "Névcímke eltüntetése"
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Válassz egy lehetőséget"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Megmutatja, mennyi időt töltöttél játszva egy profillal."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Játékidő megjelenítése"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Lehetővé teszi az oldalsáv be- és kikapcsolását."
|
||||
},
|
||||
@@ -105,13 +111,13 @@
|
||||
"message": "Nem lehet elérni a hitelesítési kiszolgálókat"
|
||||
},
|
||||
"app.browse.add-servers-to-instance": {
|
||||
"message": "Szerver hozzáadása a profilhoz"
|
||||
"message": "Szerver hozzáadása a példányhoz"
|
||||
},
|
||||
"app.browse.add-to-an-instance": {
|
||||
"message": "Hozzáadás egy profilhoz"
|
||||
"message": "Hozzáadás egy példányhoz"
|
||||
},
|
||||
"app.browse.add-to-instance": {
|
||||
"message": "Hozzáadás a profilhoz"
|
||||
"message": "Példányhoz adás"
|
||||
},
|
||||
"app.browse.add-to-instance-name": {
|
||||
"message": "Hozzáadás ehhez: {instanceName}"
|
||||
@@ -123,7 +129,7 @@
|
||||
"message": "Már hozzá van adva"
|
||||
},
|
||||
"app.browse.back-to-instance": {
|
||||
"message": "Vissza a profilhoz"
|
||||
"message": "Vissza a példányhoz"
|
||||
},
|
||||
"app.browse.discover-content": {
|
||||
"message": "Tartalom böngészése"
|
||||
@@ -143,6 +149,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Letöltés..."
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Nincs a(z) {compatibilityLabel} verziónak megfelelő elérhető verzió. Válassz ki egy verziót, ha mégis telepíteni szeretnéd. A függőségek nem települnek automatikusan."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -198,7 +207,7 @@
|
||||
"message": "A modcsomag már telepítve van"
|
||||
},
|
||||
"app.instance.modpack-already-installed.instance": {
|
||||
"message": "Profil"
|
||||
"message": "Példány"
|
||||
},
|
||||
"app.instance.mods.content-type-project": {
|
||||
"message": "projekt"
|
||||
@@ -329,8 +338,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Erőforráskezelés"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "A Modrinth App v{version} telepítésre kész! Frissítéshez válaszd ki a Frissítés opciót, vagy az alkalmazás a bezárásakor automatikusan frissül."
|
||||
"app.skins.add-button": {
|
||||
"message": "Kinézet hozzáadása"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Húzd ide a fájlt"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Alkalmazás"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Kinézet törlése"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Ezzel a kiválasztott kinézet véglegesen törlődik. Ez a művelet visszafordíthatatlan."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Biztos, hogy le akarod törölni ezt a kinézetet?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Nem sikerült beolvasni a feltöltött fájlt."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Hiba a fájl feldolgozása közben"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Kinézet szerkesztése"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Kinézet hozzáadása"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Kinézet hozzáadása"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Karstílus"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Vékony"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Széles"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Köpeny"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Köpeny"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Kinézet szerkesztése"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Előbb módosíts valamit!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Nincs köpeny"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Nincs"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Textúra cseréje"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Kinézet mentése"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Mentés..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Textúra"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Először tölts fel egy kinézetet!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Kinézet szerkesztése"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Előnézet"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Túl gyakran cseréled a kinézetedet. A Mojang szerverei ideiglenesen letiltották a további cseréket. Kérlek várj egy pillanatot, majd próbáld meg újra."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Lassíts!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Alap kinézetek"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Ezeket a kinézeteket azért kaptad, mert a Pride-hónap során adományoztál a Modrinth Pride jótékonysági gyűjtéséhez."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Mentett kinézetek"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Bejelentkezés"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Kérlek jelentkezz be a Minecraft-fiókodba, hogy használni tudd a Modrinth App kinézetkezelési funkcióit."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Izgatott Modrinth-bot"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Kérlek jelentkezz be"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Kinézetváltó"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "A Modrinth App v{version} letöltése befejeződött. Frissítéshez válaszd ki a Frissítés opciót, vagy az alkalmazás a bezárásakor automatikusan frissül."
|
||||
@@ -362,15 +509,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Verzió {version} sikeresen telepítve!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Frissítés letöltése"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Frissítés letöltése ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "A telepítéshez újraindítás szükséges"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "pelda.modrinth.gg"
|
||||
},
|
||||
@@ -605,6 +743,24 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java és memória"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "Egyéni környezeti változók"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "Egyéni Java argumentumok"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "Egyedi Java telepítés"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "Egyéni memóriakiosztás"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "Írja be a környezeti változókat..."
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Java argumentumok megadása..."
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "Környezeti változók"
|
||||
},
|
||||
@@ -620,6 +776,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Hozzárendelt memória"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/path/to/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Ablak"
|
||||
},
|
||||
@@ -663,7 +822,7 @@
|
||||
"message": "Ne mutasd a kezdőlapon"
|
||||
},
|
||||
"instance.worlds.game_already_open": {
|
||||
"message": "A profil már el van indítva"
|
||||
"message": "A példány már el van indítva"
|
||||
},
|
||||
"instance.worlds.hardcore": {
|
||||
"message": "Hardcore mód"
|
||||
@@ -687,7 +846,7 @@
|
||||
"message": "Játék a profillal"
|
||||
},
|
||||
"instance.worlds.view_instance": {
|
||||
"message": "Profil megtekintése"
|
||||
"message": "Példány megtekintése"
|
||||
},
|
||||
"instance.worlds.world_in_use": {
|
||||
"message": "A világ használatban van"
|
||||
@@ -711,13 +870,13 @@
|
||||
"message": "Bejelentkezés a Minecraftba"
|
||||
},
|
||||
"search.filter.locked.instance": {
|
||||
"message": "A profil által van megadva"
|
||||
"message": "Pédány által megadva"
|
||||
},
|
||||
"search.filter.locked.instance-game-version.title": {
|
||||
"message": "A játékverzió a profil által van megadva"
|
||||
"message": "A játékverziót az adott példány biztosítja"
|
||||
},
|
||||
"search.filter.locked.instance-loader.title": {
|
||||
"message": "A betöltő a profil által van megadva"
|
||||
"message": "A betöltőt az adott példány biztosítja"
|
||||
},
|
||||
"search.filter.locked.instance.sync": {
|
||||
"message": "Profil szinkronizálása"
|
||||
|
||||
@@ -56,21 +56,45 @@
|
||||
"app.appearance-settings.default-landing-page.library": {
|
||||
"message": "Pustaka"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.title": {
|
||||
"message": "Halaman arahan bawaan"
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.description": {
|
||||
"message": "Mematikan label nama di atas wujud pemain Anda pada halaman rupa."
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.title": {
|
||||
"message": "Sembunyikan label nama"
|
||||
},
|
||||
"app.appearance-settings.jump-back-into-worlds.description": {
|
||||
"message": "Menyertakan dunia terkini dalam bagian \"Masuk kembali\" pada Beranda."
|
||||
},
|
||||
"app.appearance-settings.jump-back-into-worlds.title": {
|
||||
"message": "Masuk kembali ke dunia"
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.description": {
|
||||
"message": "Kecilkan pluncur ketika proses Minecraft berjalan."
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.title": {
|
||||
"message": "Kecilkan peluncur"
|
||||
},
|
||||
"app.appearance-settings.native-decorations.description": {
|
||||
"message": "Gunakan bingkai jendela sistem (wajib menjalankan ulang aplikasi)."
|
||||
},
|
||||
"app.appearance-settings.native-decorations.title": {
|
||||
"message": "Hiasan asli"
|
||||
},
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Pilih opsi"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Menghidupkan kemampuan untuk menghidupkan dan mematikan bilah sisi."
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.title": {
|
||||
"message": "Hidup/matikan bilah sisi"
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.description": {
|
||||
"message": "Bila Anda mencoba memasangkan berkas Modrinth Pack (.mrpack) yang tidak dihoskan pada Modrinth, kami akan memastikan Anda untuk memahami risikonya sebelum memasangkannya."
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.title": {
|
||||
"message": "Peringatkan saya sebelum memasang paket mod tidak dikenal"
|
||||
},
|
||||
@@ -113,6 +137,9 @@
|
||||
"app.browse.project-type.modpacks": {
|
||||
"message": "Paket Mod"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Menambah konten dapat merusak kompatibilitas saat bergabung ke server. Konten tambahan apa pun akan hilang ketika Anda memperbarui konten instans server."
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Memasang"
|
||||
},
|
||||
@@ -269,6 +296,12 @@
|
||||
"app.modal.update-to-play.update-required-description": {
|
||||
"message": "{name} perlu diperbarui sebelum dimainkan. Mohon perbarui ke versi terkini untuk meluncurkan permainan."
|
||||
},
|
||||
"app.project.install-button.already-installed": {
|
||||
"message": "Proyek ini sudah terpasang"
|
||||
},
|
||||
"app.project.install-context.back-to-browse": {
|
||||
"message": "Kembali ke halaman pencarian"
|
||||
},
|
||||
"app.project.install-context.install-content-to-instance": {
|
||||
"message": "Pasang konten ke instans"
|
||||
},
|
||||
@@ -296,8 +329,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Manajemen sumber"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} siap dipasang! Muat ulang untuk memperbarui sekarang, atau secara otomatis saat Anda menutup Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Tambah rupa"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Seret dan lepas"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Terapkan"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Hapus rupa"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Ini akan menghapus rupa terpilih secara permanen. Tindakan ini tidak dapat dibatalkan."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Apakah Anda yakin ingin menghapus rupa ini?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Gagal membaca berkas yang diletakkan."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Kesalahan dalam memroses berkas"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Sunting rupa"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Tambah rupa"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Menambah rupa"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Gaya lengan"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Ramping"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Lebar"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Jubah"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Jubah"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Menyunting rupa"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Sunting rupa terlebih dahulu!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Tanpa jubah"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Tidak ada"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Ganti tekstur"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Simpan rupa"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Menyimpan..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Tekstur"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Unggah rupa terlebih dahulu!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Sunting rupa"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Mempratinjau"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Anda terlalu sering mengganti rupa Anda. Server Mojang telah memblokir permintaan lebih lanjut untuk sementara. Mohon tunggu sebentar sebelum mencoba lagi."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Pelan-pelan!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Rupa bawaan"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Anda mendapat rupa ini karena telah berdonasi ke penggalangan dana Modrinth Pride saat Pride Month."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Rupa tersimpan"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Masuk"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Mohon masuk ke akun Minecraft Anda untuk menggunakan fitur pengelolaan rupa dari Modrinth App."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Bot Modrinth penuh antusias"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Silakan masuk"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Pemilih rupa"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} telah selesai mengunduh. Muat ulang untuk memperbarui sekarang, atau secara otomatis saat Anda menutup Modrinth App."
|
||||
@@ -329,15 +500,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Versi {version} berhasil dipasang!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Unduh pembaruan"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Mengunduh pembaruan ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Muat ulang untuk memasang pembaruan"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -572,6 +734,24 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java dan memori"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "Variabel lingkungan tersuai"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "Argumen Java tersuai"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "Pemasangan Java tersuai"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "Alokasi memori tersuai"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "Masukkan variabel lingkungan..."
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Masukkan argumen Java..."
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "Variabel lingkungan"
|
||||
},
|
||||
@@ -587,6 +767,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Memori yang teralokasikan"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/jalur/ke/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Jendela"
|
||||
},
|
||||
@@ -674,6 +857,9 @@
|
||||
"minecraft-account.select-account": {
|
||||
"message": "Pilih akun"
|
||||
},
|
||||
"minecraft-account.sign-in": {
|
||||
"message": "Masuk ke Minecraft"
|
||||
},
|
||||
"search.filter.locked.instance": {
|
||||
"message": "Disediakan oleh instans"
|
||||
},
|
||||
@@ -698,6 +884,9 @@
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Pemuat disediakan oleh server"
|
||||
},
|
||||
"unknown-pack-warning-modal.body": {
|
||||
"message": "Berkas hanya akan ditinjau bila ia diunggah ke Modrinth, tak peduli format berkasnya (termasuk .mrpack)."
|
||||
},
|
||||
"unknown-pack-warning-modal.dont-show-again": {
|
||||
"message": "Jangan tampilkan peringatan ini lagi"
|
||||
},
|
||||
@@ -707,6 +896,9 @@
|
||||
"unknown-pack-warning-modal.install-anyway": {
|
||||
"message": "Tetap pasang"
|
||||
},
|
||||
"unknown-pack-warning-modal.malware-statement": {
|
||||
"message": "Program jahat (malware) dibagikan melalui berkas paket mod dengan membagikannya melalui platform seperti Discord."
|
||||
},
|
||||
"unknown-pack-warning-modal.warning.body": {
|
||||
"message": "Kami tidak dapat menemukan berkas ini di Modrinth. Kami sangat menyarankan Anda untuk hanya memasang berkas dari sumber-sumber terpercaya."
|
||||
},
|
||||
|
||||
@@ -86,14 +86,20 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Seleziona"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Mostra quanto tempo hai speso giocando a un'istanza."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Mostra tempo di gioco"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Scegli se mostrare o nascondere la barra laterale."
|
||||
"message": "Mostra o nascondi la barra laterale."
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.title": {
|
||||
"message": "Abilita la barra laterale"
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.description": {
|
||||
"message": "Visti i rischi, apparirà un avviso prima di installare un file Modrinth Pack (.mrpack) non proveniente da Modrinth."
|
||||
"message": "Mostrerà un avviso prima di installare un file Modrinth Pack (.mrpack) non proveniente da Modrinth, a causa dei possibili rischi."
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.title": {
|
||||
"message": "Avvisami se installo pacchetti sconosciuti"
|
||||
@@ -138,11 +144,14 @@
|
||||
"message": "Pacchetti di mod"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Aggiungere dei contenuti potrebbe portare problemi entrando nel server. Qualsiasi contenuto aggiunto sarà anche perso aggiornando i contenuti dell'istanza del server."
|
||||
"message": "Aggiungere dei contenuti potrebbe causare problemi entrando nel server. Inoltre, qualsiasi contenuto aggiunto sarà perso a ogni aggiornamento dei contenuti dell'istanza."
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Installazione"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Nessuna versione disponibile corrisponde a {compatibilityLabel}. Seleziona una versione da installare comunque. Le dipendenze non verranno scaricate automaticamente."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -320,8 +329,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Gestione delle risorse"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} è pronta per essere installata! Ricarica per aggiornare ora, o avverrà in automatico alla chiusura dell'app."
|
||||
"app.skins.add-button": {
|
||||
"message": "Nuova skin"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Trascina e rilascia"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Applica"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Elimina"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Questa skin sarà rimossa per sempre. Quest'azione non può essere annullata."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Vuoi davvero eliminare questa skin?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Non è stato possibile leggere il file rilasciato."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Impossibile processare il file"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Modifica"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Salva"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Aggiungi una nuova skin"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Modello del giocatore"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Snello"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Largo"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Mantello"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Mantello"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Modifica la skin"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Modifica la skin prima!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Nessun mantello"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Nessuno"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Sfoglia"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Salva"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Salvataggio..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "File della skin"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Carica una skin prima!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Modifica"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Anteprima"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Stai modificando la skin troppo spesso. I server di Mojang hanno limitato le nostre richieste. Aspetta un momento prima di riprovare."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Rallenta!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Skin predefinite"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Pride Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Hai ottenuto queste skin per aver donato alla raccolta fondi per il Pride durante il Pride Month."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Raccolta"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Accedi"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Accedi col tuo account Minecraft per usare la gestione delle skin."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Modrinth Bot emozionato"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Accedi"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Seleziona una skin"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} è stata scaricata. Ricarica per aggiornare ora, o avverrà in automatico alla chiusura dell'app."
|
||||
@@ -353,15 +500,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "La versione {version} è stata installata con successo!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Scarica aggiornamento"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Scaricando l'aggiornamento ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Ricarica per installare l'aggiornamento"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -302,8 +302,14 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "リソース管理"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} のインストール準備が整いました!今すぐ更新するには再読み込みするか、Modrinth Appを閉じる際に自動更新されます。"
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "置きかえる"
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "テクスチャ"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "編集"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} のダウンロードが完了しました。今すぐ更新するには再読み込みするか、Modrinth Appを閉じる際に自動更新されます。"
|
||||
@@ -335,15 +341,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "バージョン {version} が正常にインストールされました!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "アップデートをダウンロード"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "アップデートをダウンロード中 ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "再起動して今すぐ更新"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -593,6 +590,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "メモリ割り当て"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/path/to/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "ウィンドウ"
|
||||
},
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "옵션 선택"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "인스턴스의 플레이 시간을 표시합니다."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "플레이 시간 표시"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "사이드바를 접거나 펼칠 수 있는 기능을 활성화합니다."
|
||||
},
|
||||
@@ -143,6 +149,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "설치 중"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "{compatibilityLabel} 버전과 일치하는 버전이 없습니다. 설치할 버전을 선택하세요. 종속성은 자동으로 설치되지 않습니다."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -332,8 +341,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "리소스 관리"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version}을 설치할 준비가 완료되었습니다! 새로고침하거나 Modrinth App을 종료하면 자동으로 업데이트됩니다."
|
||||
"app.skins.add-button": {
|
||||
"message": "스킨 추가"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "드레그 엔 드롭"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "적용"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "스킨 지우기"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "선택한 스킨이 영구적으로 삭제됩니다. 이 작업은 되돌릴 수 없습니다."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "이 스킨을 정말 삭제하시겠습니까?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "삭제된 파일을 읽는 데 실패했습니다."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "파일 처리 중 오류가 발생했습니다."
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "스킨 편집"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "스킨 추가"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "스킨 추가"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "팔 형테"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Slim"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Wide"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "망토"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "망토"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "스킨 수정"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "먼저 스킨을 수정하세요"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "망토 없음"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "망토 없음"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "찾아보기"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "스킨 저장하기"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "저장중..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "스킨 파일"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "먼저 스킨을 업로드하세요"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "스킨 수정"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "미리보기"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "스킨을 너무 자주 변경하고 있습니다. Mojang 서버에서 일시적으로 추가 요청을 차단했습니다. 잠시 후 다시 시도해 주세요."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "잠시 기다려주세요."
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "기본 스킨"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth 프라이드"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "프라이드 월간 동안 Modrinth 프라이드 모금 행사에 기부하여 이 스킨들을 받았습니다."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "저장된 스킨"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "로그인"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Modrinth 앱의 스킨 관리 기능을 사용하려면 Minecraft 계정에 로그인하세요."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Excited Modrinth Bot"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "로그인하세요"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "스킨 선택"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} 다운로드가 완료되었습니다. 새로고침하거나 Modrinth App을 종료하면 자동으로 업데이트됩니다."
|
||||
@@ -365,15 +512,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "{version} 버전이 성공적으로 설치되었습니다!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "업데이트 다운로드"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "업데이트 다운로드 중 ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "새로고침하여 업데이트 설치"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -143,6 +143,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Sedang memasang"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Tiada versi tersedia yang sepadan dengan {compatibilityLabel}. Pilih versi untuk dipasang juga. Kebergantungan tidak akan dipasang secara automatik."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -299,6 +302,9 @@
|
||||
"app.project.install-button.already-installed": {
|
||||
"message": "Projek ini sudah dipasang"
|
||||
},
|
||||
"app.project.install-context.back-to-browse": {
|
||||
"message": "Kembali menemukan"
|
||||
},
|
||||
"app.project.install-context.install-content-to-instance": {
|
||||
"message": "Pasang kandungan ke dalam pemasangan"
|
||||
},
|
||||
@@ -326,8 +332,110 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Pengurusan sumber"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} sudah bersedia untuk dipasang! Muat semula untuk kemas kini sekarang, atau kemas kini secara automatik apabila anda menutup Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Tambah kekulit"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Terapkan"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Padam kekulit"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Ini akan memadamkan kekulit yang dipilih selama-lamanya. Tindakan ini tidak boleh dibuat asal."
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Sunting kekulit"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Tambah kekulit"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Gaya lengan"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Kurus"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Lebar"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Mantel"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Mantel"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Menyunting kekulit"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Tiada mantel"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Tiada"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Simpan kekulit"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Sedang menyimpan..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Tekstur"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Sunting kekulit"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Sedang pralihat"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Anda terlalu kerap menukar kekulit anda. Pelayan Mojang telah menyekat permintaan selanjutnya buat sementara waktu. Sila tunggu sebentar sebelum mencuba lagi."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Perlahanlah sikit!"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Anda menerima kekulit ini kerana menderma kepada acara pengumpulan dana Modrinth Pride semasa Pride Month."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Kekulit yang disimpan"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Daftar Masuk"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Sila daftar masuk ke akaun Minecraft anda untuk menggunakan ciri pengurusan kekulit milik Modrinth App."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Bot Modrinth yang Teruja"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Sila daftar masuk"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Pemilih kekulit"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} sudah selesai dimuat turun! Muat semula untuk kemas kini sekarang, atau kemas kini secara automatik apabila anda menutup Modrinth App."
|
||||
@@ -359,15 +467,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Versi {version} telah berjaya dipasang!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Muat turun kemas kini"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Sedang memuat turun kemas kini ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Muat semula untuk memasang kemas kini"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -602,6 +701,24 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java dan ingatan"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "Pembolehubah persekitaran tersuai"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "Argumen Java tersuai"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "Pemasangan Java tersuai"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "Peruntukan ingatan tersuai"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "Masukkan pembolehubah persekitaran..."
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Masukkan argumen Java..."
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "Pembolehubah persekitaran"
|
||||
},
|
||||
@@ -617,6 +734,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Ingatan yang diperuntukkan"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/laluan/ke/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Tetingkap"
|
||||
},
|
||||
|
||||
@@ -323,9 +323,6 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Bronnenbeheer"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} is klaar om geïnstalleerd te worden! Herlaad om nu te updaten, of automatisch wanneer je de Modrinth App afsluit."
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} is klaar met downloaden. Herlaad om nu te updaten, of automatisch wanneer je de Modrinth App afsluit."
|
||||
},
|
||||
@@ -356,15 +353,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Versie {version} is succesvol geïnstalleerd!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Download update"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Update downloaden ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Herlaad om de update te installeren"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "voorbeeld.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -59,15 +59,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Versjon {version} ble installert!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Last ned oppdatering"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Laster ned oppdatering ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Last inn på nytt for å installere oppdateringen"
|
||||
},
|
||||
"friends.action.add-friend": {
|
||||
"message": "Legg til en venn"
|
||||
},
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Wybierz opcję"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Pokazuje czas gry spędzony w danej instancji."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Pokaż czas gry"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Umożliwia przełączenie paska bocznego."
|
||||
},
|
||||
@@ -143,6 +149,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "Instalowanie"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Nie znaleziono żadnych wersji pasujących do {compatibilityLabel}. Wybierz wersję, by zainstalować ją mimo tego. Zależności nie zostaną zainstalowane automatycznie."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -326,8 +335,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Zarządzanie zasobami"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Wersja Modrinth App v{version} jest gotowa do zainstalowania! Załaduj ponownie, żeby zaktualizować teraz, albo automatycznie, gdy zamkniesz Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Dodaj skórkę"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Przeciągnij i upuść"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Zastosuj"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Usuń skórkę"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "To trwale usunie wybraną skórkę. Tej akcji nie można odwrócić."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Czy na pewno chcesz usunąć tą skórkę?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Nie udało się odczytać wybranego pliku."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Błąd podczas przetwarzania pliku"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Edytuj skina"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Dodaj skina"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Dodawanie skina"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Styl ramion"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Smukły"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Szeroki"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Peleryna"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Peleryny"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Edytuj skina"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Wpierw zmień jakoś skórkę!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Brak peleryny"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Brak"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Zamień teksturę"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Zapisz skina"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Zapisywanie..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Tekstura"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Wpierw prześlij skórkę!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Edytuj skórkę"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Podgląd"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Zbyt często zmieniasz swoją skórkę. Serwery Mojang tymczasowo zablokowały dalsze żądania. Odczekaj chwilę i spróbuj ponownie."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Zwolnij!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Domyślne skórki"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Duma Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Zdobyłeś te skórki poprzez dotację na zbiórkę Dumy Modrinth w okresie Miesiąca Dumy."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Zapisane skórki"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Zaloguj się"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Zaloguj się na konto Minecraft, by móc zarządzać skórkami poprzez Modrinth App."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Podekscytowany Modrinth Bot"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Zaloguj się"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Wybierz skórkę"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Wersja Modrinth App v{version} została pobrana. Załaduj ponownie, żeby zaktualizować teraz, albo automatycznie, gdy zamkniesz Modrinth App."
|
||||
@@ -359,15 +506,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Wersja {version} została pomyślnie zainstalowana!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Pobierz aktualizację"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Pobieranie aktualizacji ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Załaduj ponownie, aby zainstalować aktualizację"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -602,6 +740,24 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java i pamięć"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "Zmienne środowiskowe"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "Niestandardowe argumenty Java"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "Niestandardowa instalacja Javy"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "Niestandardowa alokacja pamięci"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "Zmienne środowiskowe..."
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Argumenty Javy..."
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "Zmienne środowiskowe"
|
||||
},
|
||||
@@ -617,6 +773,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Przypisana pamięć"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/path/to/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Okno"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"app.action-bar.downloading-java": {
|
||||
"message": "Baixando java {version}"
|
||||
"message": "Baixando Java {version}"
|
||||
},
|
||||
"app.action-bar.downloads": {
|
||||
"message": "Downloads"
|
||||
@@ -9,19 +9,19 @@
|
||||
"message": "Ocultar mais instâncias em execução"
|
||||
},
|
||||
"app.action-bar.make-primary-instance": {
|
||||
"message": "Criar instância primária"
|
||||
"message": "Tornar instância principal"
|
||||
},
|
||||
"app.action-bar.no-instances-running": {
|
||||
"message": "Nenhuma instância em execução"
|
||||
},
|
||||
"app.action-bar.offline": {
|
||||
"message": "Offline"
|
||||
"message": "Inativo"
|
||||
},
|
||||
"app.action-bar.primary-instance": {
|
||||
"message": "Instância primária"
|
||||
"message": "Instância principal"
|
||||
},
|
||||
"app.action-bar.show-more-running-instances": {
|
||||
"message": "Mostrar mais instâncias em execução"
|
||||
"message": "Exibir mais instâncias em execução"
|
||||
},
|
||||
"app.action-bar.stop-instance": {
|
||||
"message": "Parar instância"
|
||||
@@ -33,10 +33,10 @@
|
||||
"message": "Ver instância"
|
||||
},
|
||||
"app.action-bar.view-logs": {
|
||||
"message": "Ver logs"
|
||||
"message": "Ver registros"
|
||||
},
|
||||
"app.appearance-settings.advanced-rendering.description": {
|
||||
"message": "Ativa a renderização avançada, como efeitos de desfoque que podem causar problemas de desempenho sem a renderização acelerada de hardware."
|
||||
"message": "Ativa a renderização avançada, como desfoque que talvez afete o desempenho sem renderização acelerada do hardware."
|
||||
},
|
||||
"app.appearance-settings.advanced-rendering.title": {
|
||||
"message": "Renderização avançada"
|
||||
@@ -45,10 +45,10 @@
|
||||
"message": "Selecione seu tema de cores preferido para o Modrinth App."
|
||||
},
|
||||
"app.appearance-settings.color-theme.title": {
|
||||
"message": "Tema de Cores"
|
||||
"message": "Tema de cores"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.description": {
|
||||
"message": "Alterar a página em que o launcher é aberto."
|
||||
"message": "Altera a página que o launcher é aberto."
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.home": {
|
||||
"message": "Início"
|
||||
@@ -60,25 +60,25 @@
|
||||
"message": "Página inicial padrão"
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.description": {
|
||||
"message": "Desativa o nome acima do seu jogador na página de skins."
|
||||
"message": "Desativa o nametag acima do seu jogador na página de Skins."
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.title": {
|
||||
"message": "Ocultar nome"
|
||||
"message": "Ocultar nametag"
|
||||
},
|
||||
"app.appearance-settings.jump-back-into-worlds.description": {
|
||||
"message": "Inclui mundos recentes na seção \"Voltar à ação\" na página inicial."
|
||||
"message": "Inclui mundos recentes na seção \"Retomar\" na página inicial."
|
||||
},
|
||||
"app.appearance-settings.jump-back-into-worlds.title": {
|
||||
"message": "Volte aos mundos"
|
||||
"message": "Retomar aos mundos"
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.description": {
|
||||
"message": "Minimize o launcher quando um processo do Minecraft for iniciado."
|
||||
"message": "Minimize o launcher assim que algum processo do Minecraft iniciar."
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.title": {
|
||||
"message": "Minimizar launcher"
|
||||
},
|
||||
"app.appearance-settings.native-decorations.description": {
|
||||
"message": "Usar molduras de janela do sistema (requer reiniciar o aplicativo)."
|
||||
"message": "Usar molduras de janela do sistema (exige reinicialização do aplicativo)."
|
||||
},
|
||||
"app.appearance-settings.native-decorations.title": {
|
||||
"message": "Decorações nativas"
|
||||
@@ -86,14 +86,20 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Selecione uma opção"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Exibe a quantidade de tempo jogado de uma instância."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Exibir tempo jogado"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Ativa a capacidade de alternar a visibilidade da barra lateral."
|
||||
"message": "Permite alternar a barra lateral."
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.title": {
|
||||
"message": "Alternar barra lateral"
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.description": {
|
||||
"message": "Se você tentar instalar um arquivo Modrinth Pack (.mrpack) que não esteja hospedado no Modrinth, garantiremos que você entenda os riscos antes de instalá-lo."
|
||||
"message": "Se você tentar instalar um arquivo Modrinth Pack (.mrpack) não hospedado no Modrinth, garantiremos que você entenda os riscos antes de instalá-lo."
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.title": {
|
||||
"message": "Avise-me antes de instalar pacotes de mods desconhecidos"
|
||||
@@ -123,13 +129,13 @@
|
||||
"message": "Já adicionado"
|
||||
},
|
||||
"app.browse.back-to-instance": {
|
||||
"message": "Voltar a instância"
|
||||
"message": "Voltar à instância"
|
||||
},
|
||||
"app.browse.discover-content": {
|
||||
"message": "Descubra conteúdo"
|
||||
"message": "Descobrir conteúdo"
|
||||
},
|
||||
"app.browse.discover-servers": {
|
||||
"message": "Descubra servidores"
|
||||
"message": "Descobrir servidores"
|
||||
},
|
||||
"app.browse.hide-added-servers": {
|
||||
"message": "Ocultar servidores já adicionados"
|
||||
@@ -138,11 +144,14 @@
|
||||
"message": "Pacotes de mods"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Adicionar conteúdo pode quebrar a compatibilidade ao entrar no servidor. Qualquer conteúdo adicionado também será perdido ao atualizar o conteúdo da instância do servidor."
|
||||
"message": "Adicionar conteúdo talvez quebre a compatibilidade ao entrar no servidor. Qualquer conteúdo adicionado será perdido ao atualizar o conteúdo da instância do servidor."
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Instalando"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Nenhuma versão disponível corresponde a {compatibilityLabel}. Selecione uma versão para instalar mesmo assim. As dependências não serão instaladas automaticamente."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -168,7 +177,7 @@
|
||||
"message": "Nome do pacote de mods"
|
||||
},
|
||||
"app.export-modal.select-files-label": {
|
||||
"message": "Configure quais arquivos serão incluídos nessa exportação"
|
||||
"message": "Configure quais arquivos serão incluídos na exportação"
|
||||
},
|
||||
"app.export-modal.version-number-label": {
|
||||
"message": "Número da versão"
|
||||
@@ -177,7 +186,7 @@
|
||||
"message": "1.0.0"
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-body": {
|
||||
"message": "Todos os dados da sua instância serão permanentemente excluídos, incluindo seus mundos, configurações e todo o conteúdo instalado."
|
||||
"message": "Todos os dados para sua instância serão excluídos permanentemente, incluindo seus mundos, configs e todo o conteúdo instalado."
|
||||
},
|
||||
"app.instance.confirm-delete.admonition-header": {
|
||||
"message": "Esta ação não pode ser desfeita"
|
||||
@@ -189,7 +198,7 @@
|
||||
"message": "Excluir instância"
|
||||
},
|
||||
"app.instance.modpack-already-installed.body": {
|
||||
"message": "Este pacote de mods já está instalado na instância <bold>{instanceName}</bold>. Tem certeza de que deseja duplicá-lo?"
|
||||
"message": "Este pacote de mods já foi instalado na instância <bold>{instanceName}</bold>. Deseja mesmo duplicá-lo?"
|
||||
},
|
||||
"app.instance.modpack-already-installed.create": {
|
||||
"message": "Criar"
|
||||
@@ -210,10 +219,10 @@
|
||||
"message": "{count} projetos foram adicionados"
|
||||
},
|
||||
"app.instance.mods.share-text": {
|
||||
"message": "Confira os projetos que estou usando no meu pacote de mods!"
|
||||
"message": "Dê uma olhada nos projetos que estou usando no meu pacote de mods!"
|
||||
},
|
||||
"app.instance.mods.share-title": {
|
||||
"message": "Compartilhando conteúdo do pacote de mods\n\n\n \t\t\t\t\t\t\n \t\t\t\t\t\t\t\n \t\t\t\t\t\t\n \t\t\t\t\t\t"
|
||||
"message": "Compartilhando conteúdo do pacote de mods"
|
||||
},
|
||||
"app.instance.mods.successfully-uploaded": {
|
||||
"message": "Adicionado com sucesso"
|
||||
@@ -225,19 +234,19 @@
|
||||
"message": "Explorar servidores"
|
||||
},
|
||||
"app.instance.worlds.delete-world-description": {
|
||||
"message": "'{name}' será excluído permanentemente, e não haverá como recuperá-lo."
|
||||
"message": "'{name}' será **excluído permanentemente**, e não poderá ser recuperado."
|
||||
},
|
||||
"app.instance.worlds.delete-world-title": {
|
||||
"message": "Tem certeza de que deseja excluir este mundo permanentemente?"
|
||||
"message": "Deseja mesmo excluir este mundo permanentemente?"
|
||||
},
|
||||
"app.instance.worlds.filter-modded": {
|
||||
"message": "Modificado"
|
||||
},
|
||||
"app.instance.worlds.filter-offline": {
|
||||
"message": "Offline"
|
||||
"message": "Inativo"
|
||||
},
|
||||
"app.instance.worlds.filter-online": {
|
||||
"message": "Online"
|
||||
"message": "Ativo"
|
||||
},
|
||||
"app.instance.worlds.filter-vanilla": {
|
||||
"message": "Jogo padrão"
|
||||
@@ -249,13 +258,13 @@
|
||||
"message": "Nenhum servidor ou mundo adicionado"
|
||||
},
|
||||
"app.instance.worlds.remove-server-description": {
|
||||
"message": "'{name}' será removido da sua lista, inclusive no jogo, e não haverá como recuperá-lo."
|
||||
"message": "'{name}' será removido da lista, inclusive no jogo, e não poderá ser recuperado."
|
||||
},
|
||||
"app.instance.worlds.remove-server-description-with-address": {
|
||||
"message": "'{name}' ({address}) será removido da sua lista, inclusive no jogo, e não haverá como recuperá-lo."
|
||||
"message": "'{name}' ({address}) será removido da lista, inclusive no jogo, e não poderá ser recuperado."
|
||||
},
|
||||
"app.instance.worlds.remove-server-title": {
|
||||
"message": "Tem certeza de que deseja remover {name}?"
|
||||
"message": "Deseja mesmo remover {name}?"
|
||||
},
|
||||
"app.instance.worlds.search-worlds-placeholder": {
|
||||
"message": "Buscar {count} mundos..."
|
||||
@@ -276,7 +285,7 @@
|
||||
"message": "Pacote de mods necessário"
|
||||
},
|
||||
"app.modal.install-to-play.server-requires-mods": {
|
||||
"message": "Este servidor requer mods para jogar. Clique em Instalar para configurar os arquivos necessários a partir do Modrinth, e iniciar diretamente no servidor."
|
||||
"message": "Este servidor exige mods para jogar. Clique em instalar para configurar os arquivos necessários através do Modrinth, e então iniciar diretamente no servidor."
|
||||
},
|
||||
"app.modal.install-to-play.shared-instance": {
|
||||
"message": "Instância compartilhada"
|
||||
@@ -285,7 +294,7 @@
|
||||
"message": "Instância de servidor compartilhada"
|
||||
},
|
||||
"app.modal.install-to-play.view-contents": {
|
||||
"message": "Ver conteúdos"
|
||||
"message": "Ver conteúdo"
|
||||
},
|
||||
"app.modal.update-to-play.header": {
|
||||
"message": "Atualize para jogar"
|
||||
@@ -294,19 +303,19 @@
|
||||
"message": "Atualização necessária"
|
||||
},
|
||||
"app.modal.update-to-play.update-required-description": {
|
||||
"message": "É necessária uma atualização para jogar {name}. Atualize para a versão mais recente para iniciar o jogo."
|
||||
"message": "Uma atualização é necessária para jogar {name}. Atualize para a versão mais recente para iniciar o jogo."
|
||||
},
|
||||
"app.project.install-button.already-installed": {
|
||||
"message": "Este projeto já foi instalado"
|
||||
},
|
||||
"app.project.install-context.back-to-browse": {
|
||||
"message": "Voltar ao descobrir"
|
||||
"message": "Voltar a descobrir"
|
||||
},
|
||||
"app.project.install-context.install-content-to-instance": {
|
||||
"message": "Instalar conteúdo para a instância"
|
||||
},
|
||||
"app.settings.developer-mode-enabled": {
|
||||
"message": "Modo de desenvolvedor ativado."
|
||||
"message": "Modo desenvolvedor ativado."
|
||||
},
|
||||
"app.settings.downloading": {
|
||||
"message": "Baixando v{version}"
|
||||
@@ -329,8 +338,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Gerenciamento de recursos"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "O Modrinth App v{version} está pronto para ser instalado! Você pode recarregar para atualizar agora ou a atualização será feita automaticamente ao fechar o Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Adicionar skin"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Arraste e solte"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Aplicar"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Excluir skin"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Isso excluirá permanentemente a skin. Esta ação não pode ser desfeita."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Deseja mesmo excluir esta skin?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Falha ao ler o arquivo solto."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Erro ao processar arquivo"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Editar skin"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Adicionar skin"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Adicionando uma skin"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Estilo do braço"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Fino"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Largo"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Capa"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Capas"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Editando a skin"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Primeiramente, faça uma edição na skin!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Sem capa"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Nenhum"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Substituir textura"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Salvar skin"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Salvando..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Textura"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Primeiramente, envie uma skin!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Editar skin"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Prévia"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Você está mudando de skin muitas vezes. Os servidores da Mojang bloquearam temporariamente novas solicitações. Aguarde um momento antes de tentar novamente."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Mais lento!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Construtores & Biomas"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Skins padrões"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Você recebeu estas skins por doar para uma campanha de arrecadação do Modrinth Pride durante o Mês de Orgulho."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Skins salvas"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "A Era do Cobre"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Iniciar sessão"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Faça login na sua conta do Minecraft para usar os recursos de gerenciamento de skins do Modrinth app."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Modrinth Bot animado"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Por favor, inicie sessão"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Seletor de skins"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "O Modrinth App v{version} foi baixado. Recarregue para atualizar agora ou a atualização será aplicada automaticamente ao fechar o Modrinth App."
|
||||
@@ -339,7 +486,7 @@
|
||||
"message": "O Modrinth App v{version} está disponível. Use seu gerenciador de pacotes para atualizar e obter os recursos e correções mais recentes!"
|
||||
},
|
||||
"app.update-popup.body.metered": {
|
||||
"message": "O Modrinth App v{version} já está disponível! Como você está em uma rede limitada, não o baixamos automaticamente."
|
||||
"message": "O Modrinth App v{version} já está disponível! Já que sua rede é limitada, não a instalamos automaticamente."
|
||||
},
|
||||
"app.update-popup.changelog": {
|
||||
"message": "Mudanças"
|
||||
@@ -348,7 +495,7 @@
|
||||
"message": "Baixar ({size})"
|
||||
},
|
||||
"app.update-popup.download-complete": {
|
||||
"message": "Download concluído"
|
||||
"message": "Instalação concluída"
|
||||
},
|
||||
"app.update-popup.reload": {
|
||||
"message": "Recarregar"
|
||||
@@ -362,15 +509,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Versão {version} instalada!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Baixar atualização"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Baixando atualização ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Recarregue para instalar a atualização"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "exemplo.modrinth.gg"
|
||||
},
|
||||
@@ -384,22 +522,25 @@
|
||||
"message": "Ainda não jogado"
|
||||
},
|
||||
"app.world.world-item.offline": {
|
||||
"message": "Offline"
|
||||
"message": "Inativo"
|
||||
},
|
||||
"app.world.world-item.players-online": {
|
||||
"message": "{count} online"
|
||||
"message": "{count} ativo(s)"
|
||||
},
|
||||
"friends.action.add-friend": {
|
||||
"message": "Adicionar um amigo"
|
||||
"message": "Adicionar amigo"
|
||||
},
|
||||
"friends.action.view-friend-requests": {
|
||||
"message": "{count} {count, plural, one {pedido} other {pedidos}} de amizade"
|
||||
},
|
||||
"friends.add-friend.submit": {
|
||||
"message": "Enviar amizade"
|
||||
"message": "Enviar pedido de amizade"
|
||||
},
|
||||
"friends.add-friend.title": {
|
||||
"message": "Adicionando amigo"
|
||||
"message": "Adicionar um amigo"
|
||||
},
|
||||
"friends.add-friend.username.description": {
|
||||
"message": "Pode ser diferente do nome que ele usa no Minecraft!"
|
||||
"message": "Pode diferir do nome de usuário do Minecraft!"
|
||||
},
|
||||
"friends.add-friend.username.placeholder": {
|
||||
"message": "Insira o nome de usuário..."
|
||||
@@ -675,13 +816,13 @@
|
||||
"message": "Servidor de Minecraft"
|
||||
},
|
||||
"instance.worlds.cant_connect": {
|
||||
"message": "Não foi possível se conectar ao servidor"
|
||||
"message": "Não foi possível conectar ao servidor"
|
||||
},
|
||||
"instance.worlds.copy_address": {
|
||||
"message": "Copiar endereço"
|
||||
},
|
||||
"instance.worlds.dont_show_on_home": {
|
||||
"message": "Não mostrar na tela inicial"
|
||||
"message": "Não mostrar no início"
|
||||
},
|
||||
"instance.worlds.game_already_open": {
|
||||
"message": "A instância já está aberta"
|
||||
|
||||
@@ -239,9 +239,6 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Gestão de recursos"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} está pronta para ser instalada! Recarrega para atualizar agora, ou automaticamente quando fechares a Modrinth App."
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} acabou de ser transferida. Recarrega para atualizar agora, ou automaticamente quando fechares a Modrinth App."
|
||||
},
|
||||
@@ -272,15 +269,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Versão {version} foi instalada com sucesso!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Transferir atualização"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "A transferir atualização ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Recarrega para instalar a atualização"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "exemplo.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -65,9 +65,6 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Administrare resurse"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Aplicația Modrinth v{version} este gata de instalat! Reîncărcați pentru a actualiza acum sau automat când închideți aplicația Modrinth."
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Aplicația Modrinth v{version} a terminat descărcarea. Reîncărcați pentru a actualiza acum sau automat când închideți aplicația Modrinth."
|
||||
},
|
||||
@@ -98,15 +95,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Versiunea {version} a fost instalată cu succes!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Descarcă actualizarea"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Se descarcă actualizarea ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Reîncarcă pentru a instala actualizarea"
|
||||
},
|
||||
"app.world.server-modal.select-an-option": {
|
||||
"message": "Selectează o opțiune"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"message": "Скачивание Java {version}"
|
||||
},
|
||||
"app.action-bar.downloads": {
|
||||
"message": "Скачивание"
|
||||
"message": "Загрузки"
|
||||
},
|
||||
"app.action-bar.hide-more-running-instances": {
|
||||
"message": "Скрыть другие активные сборки"
|
||||
@@ -27,7 +27,7 @@
|
||||
"message": "Остановить сборку"
|
||||
},
|
||||
"app.action-bar.view-active-downloads": {
|
||||
"message": "Посмотреть текущие скачивания"
|
||||
"message": "Посмотреть текущие загрузки"
|
||||
},
|
||||
"app.action-bar.view-instance": {
|
||||
"message": "Посмотреть сборку"
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Выберите вариант"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Показывать время, проведённое в сборке."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Время игры"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Показывать кнопку скрытия боковой панели."
|
||||
},
|
||||
@@ -138,11 +144,14 @@
|
||||
"message": "Сборки"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Добавление контента может нарушить совместимость при подключении к серверу. Также весь добавленный контент будет удалён при обновлении содержимого серверной сборки."
|
||||
"message": "Добавление контента может сломать совместимость при подключении к серверу. Весь добавленный контент также будет удалён при обновлении сервера."
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Установка"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Не найдено доступных версий, совместимых с {compatibilityLabel}. Выберите версию для установки вручную. Зависимости не будут установлены автоматически."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -314,8 +323,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Управление ресурсами"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Версия Modrinth App {version} готова к установке! Перезапустите приложение, чтобы обновить его, или оно обновится автоматически после закрытия."
|
||||
"app.skins.add-button": {
|
||||
"message": "Добавить скин"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Перетащите сюда"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Применить"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Удалить скин"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Выбранный скин будет удалён навсегда. Это действие необратимо."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Вы действительно хотите удалить этот скин?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Не удалось прочитать перетащенный файл."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Ошибка обработки файла"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Изменить скин"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Добавить скин"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Добавление скина"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Руки"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Тонкие"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Широкие"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Плащ"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Плащ"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Настройка скина"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Сначала внесите изменения в скин!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Без плаща"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Нет"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Заменить текстуру"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Сохранить скин"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Сохранение..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Текстура"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Сначала загрузите скин!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Изменить"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Предпросмотр"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Вы слишком часто меняете скин. Серверы Mojang временно заблокировали дальнейшие запросы. Подождите немного, прежде чем попробовать снова."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Не так быстро!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Стандартные скины"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Эти скины получены за участие в сборе средств Modrinth Pride в месяц гордости."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Сохранённые скины"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Войти"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Пожалуйста, войдите в свой аккаунт Minecraft, чтобы воспользоваться функциями управления скинами в приложении Modrinth."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Восторженный Modrinth Bot"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Войдите"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Выбор скина"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Скачивание версии Modrinth App {version} завершено. Перезапустите приложение, чтобы обновить его, или оно обновится автоматически после закрытия."
|
||||
@@ -347,15 +494,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Версия {version} успешно установлена!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Скачать обновление"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Скачивание обновления ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Перезапустить и обновить"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -588,19 +726,19 @@
|
||||
"message": "Java и память"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "Пользовательские настройки запуска"
|
||||
"message": "Переопределение переменных среды"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "Пользовательские аргументы Java"
|
||||
"message": "Переопределение аргументов Java"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "Пользовательская установка Java"
|
||||
"message": "Переопределение расположения Java"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "Пользовательский объём памяти"
|
||||
"message": "Переопределение выделенной памяти"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "Введите дополнительные параметры системы..."
|
||||
"message": "Введите переменные среды..."
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Введите аргументы Java..."
|
||||
|
||||
@@ -47,21 +47,51 @@
|
||||
"app.appearance-settings.color-theme.title": {
|
||||
"message": "Färgtema"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.description": {
|
||||
"message": "Ändrar sidan som launchern öppnas på."
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.home": {
|
||||
"message": "Hem"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.library": {
|
||||
"message": "Bibliotek"
|
||||
},
|
||||
"app.appearance-settings.default-landing-page.title": {
|
||||
"message": "Standardlandingssida"
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.description": {
|
||||
"message": "Inaktiverar namnskylten ovanför din spelare på utseende-sidan."
|
||||
},
|
||||
"app.appearance-settings.hide-nametag.title": {
|
||||
"message": "Dölj namnskylt"
|
||||
},
|
||||
"app.appearance-settings.minimize-launcher.title": {
|
||||
"message": "Minimera programstartare"
|
||||
},
|
||||
"app.appearance-settings.native-decorations.description": {
|
||||
"message": "Använd systemets fönsterram (omstart av app krävs)."
|
||||
},
|
||||
"app.appearance-settings.native-decorations.title": {
|
||||
"message": "Inbyggda fönsterdekorationer"
|
||||
},
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Välj ett alternativ"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Låter dig växla sidofältet."
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.title": {
|
||||
"message": "Växla sidofält"
|
||||
},
|
||||
"app.auth-servers.unreachable.body": {
|
||||
"message": "Minecrafts autentiseringsservrar kan vara nere just nu. Kontrollera din internetanslutning och försök igen senare."
|
||||
},
|
||||
"app.auth-servers.unreachable.header": {
|
||||
"message": "Kan ej nå autentiseringsservrarna"
|
||||
},
|
||||
"app.browse.add-to-an-instance": {
|
||||
"message": "Lägg till i en instans"
|
||||
},
|
||||
"app.browse.add-to-instance": {
|
||||
"message": "Lägg till i instans"
|
||||
},
|
||||
@@ -74,18 +104,30 @@
|
||||
"app.browse.already-added": {
|
||||
"message": "Redan tillagd"
|
||||
},
|
||||
"app.browse.back-to-instance": {
|
||||
"message": "Tillbaka till instans"
|
||||
},
|
||||
"app.browse.discover-content": {
|
||||
"message": "Upptäck innehåll"
|
||||
},
|
||||
"app.browse.discover-servers": {
|
||||
"message": "Upptäck servrar"
|
||||
},
|
||||
"app.browse.hide-added-servers": {
|
||||
"message": "Dölj servrar som redan är tillagda"
|
||||
},
|
||||
"app.browse.project-type.modpacks": {
|
||||
"message": "Modpaket"
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Installerar"
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
"app.creation-modal.installing-modpack.title": {
|
||||
"message": "Installerar modpaket..."
|
||||
},
|
||||
"app.export-modal.description-placeholder": {
|
||||
"message": "Ange modpaketets beskrivning..."
|
||||
},
|
||||
@@ -95,6 +137,9 @@
|
||||
"app.export-modal.header": {
|
||||
"message": "Exportera modpaket"
|
||||
},
|
||||
"app.export-modal.include-file-accessibility-label": {
|
||||
"message": "Inkludera \"{file}\"?"
|
||||
},
|
||||
"app.export-modal.modpack-name-label": {
|
||||
"message": "Modpaketets namn"
|
||||
},
|
||||
@@ -254,8 +299,59 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Resurshantering"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} är redo att laddas ner! Ladda om för att uppdatera nu, eller automatiskt när du stänger Modrinth App."
|
||||
"app.skins.add-button": {
|
||||
"message": "Lägg till utseende"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Ta bort utseende"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Redigera utseende"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Lägg till utseende"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Lägga till ett utseende"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Arm stil"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Smal"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Bred"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Mantel"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Mantel"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Redigerar utseende"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Gör en ändring på utseendet först!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Ingen mantel"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Ingen"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Byt ut textur"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Spara utseende"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Sparar..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Textur"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} har laddats ner. Ladda om för att uppdatera nu, eller automatiskt när du stänger Modrinth App."
|
||||
@@ -287,15 +383,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Version {version} har installerats!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Ladda ner uppdatering"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Laddar ner uppdatering ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Ladda om för att installera uppdatering"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -620,6 +707,24 @@
|
||||
"instance.worlds.world_in_use": {
|
||||
"message": "Värld används"
|
||||
},
|
||||
"minecraft-account.add-account": {
|
||||
"message": "Lägg till konto"
|
||||
},
|
||||
"minecraft-account.label": {
|
||||
"message": "Minecraft konto"
|
||||
},
|
||||
"minecraft-account.not-signed-in": {
|
||||
"message": "Inte inloggad"
|
||||
},
|
||||
"minecraft-account.remove-account": {
|
||||
"message": "Ta bort konto"
|
||||
},
|
||||
"minecraft-account.select-account": {
|
||||
"message": "Välj konto"
|
||||
},
|
||||
"minecraft-account.sign-in": {
|
||||
"message": "Logga in till Minecraft"
|
||||
},
|
||||
"search.filter.locked.instance": {
|
||||
"message": "Tillhandahållet av instansen"
|
||||
},
|
||||
@@ -643,5 +748,8 @@
|
||||
},
|
||||
"search.filter.locked.server-loader.title": {
|
||||
"message": "Loader tillhandahålls av servern"
|
||||
},
|
||||
"unknown-pack-warning-modal.install-anyway": {
|
||||
"message": "Installera ändå"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,9 +308,6 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "การจัดการทรัพยากร"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth v{version} พร้อมสำหรับการติดตั้งแล้ว! เปิดโปรแกรมใหม่อีกครั้งเพื่ออัปเดตตอนนี้ หรือจะรออัปเดตอัตโนมัติ ซึ่งจะเกิดขึ้นเมื่อคุณกดปิดโปรแกรม Modrinth"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "ดาวน์โหลด Modrinth v{version} สำเร็จแล้ว เปิดโปรแกรมใหม่อีกครั้งเพื่ออัปเดตตอนนี้ หรือจะรออัปเดตอัตโนมัติ ซึ่งจะเกิดขึ้นเมื่อคุณกดปิดโปรแกรม Modrinth"
|
||||
},
|
||||
@@ -341,15 +338,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "เวอร์ชั่น {version} ถูกติดตั้งแล้ว"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "ดาวน์โหลดอัปเดต"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "ดาวน์โหลดอัปเดตไปแล้ว ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "รีโหลดเพื่อติดตั้งอัปเดต"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Bir seçenek seçin"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Bir oyun oturumunda ne kadar zaman geçirdiğinizi gösterir."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Oynama Süresini Göster"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Kenar çubuğunu ayarlama özelliğini aktifleştirir."
|
||||
},
|
||||
@@ -104,6 +110,12 @@
|
||||
"app.auth-servers.unreachable.header": {
|
||||
"message": "Doğrulama sunucularına erişilemedi"
|
||||
},
|
||||
"app.browse.add-servers-to-instance": {
|
||||
"message": "Sunucuyu kuruluma ekle"
|
||||
},
|
||||
"app.browse.add-to-an-instance": {
|
||||
"message": "Bir kuruluma ekle"
|
||||
},
|
||||
"app.browse.add-to-instance": {
|
||||
"message": "Kuruluma ekle"
|
||||
},
|
||||
@@ -116,6 +128,9 @@
|
||||
"app.browse.already-added": {
|
||||
"message": "Zaten ekli"
|
||||
},
|
||||
"app.browse.back-to-instance": {
|
||||
"message": "Kuruluma dön"
|
||||
},
|
||||
"app.browse.discover-content": {
|
||||
"message": "İçerik keşfet"
|
||||
},
|
||||
@@ -128,9 +143,15 @@
|
||||
"app.browse.project-type.modpacks": {
|
||||
"message": "Mod paketleri"
|
||||
},
|
||||
"app.browse.server-instance-content-warning": {
|
||||
"message": "Yeni bir içerik eklemek sunucuya girerkenki uyumluluğu bozabilir. Herhangi eklenmiş içerik ise sunucu kurulumunu güncellemeye çalıştığınızda kaybolacaktır."
|
||||
},
|
||||
"app.browse.server.installing": {
|
||||
"message": "Yükleniyor"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "Kullanılabilir sürümler {compatibilityLabel} ile eşleşmiyor. Yine de kurulacak bir sürüm seçin. Bağımlılıklar otomatik olarak yüklenmeyecektir."
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -146,11 +167,17 @@
|
||||
"app.export-modal.header": {
|
||||
"message": "Mod paketini dışa aktar"
|
||||
},
|
||||
"app.export-modal.include-file-accessibility-label": {
|
||||
"message": "\"{file}\" dahil mi?"
|
||||
},
|
||||
"app.export-modal.modpack-name-label": {
|
||||
"message": "Mod Paketi Adı"
|
||||
},
|
||||
"app.export-modal.modpack-name-placeholder": {
|
||||
"message": "Modpaketi adı"
|
||||
"message": "Mod paketi adı"
|
||||
},
|
||||
"app.export-modal.select-files-label": {
|
||||
"message": "Bu dışa aktarmaya hangi dosyaların dahil edileceğini yapılandırma"
|
||||
},
|
||||
"app.export-modal.version-number-label": {
|
||||
"message": "Sürüm numarası"
|
||||
@@ -165,10 +192,10 @@
|
||||
"message": "Bu eylem geri alınamaz"
|
||||
},
|
||||
"app.instance.confirm-delete.delete-button": {
|
||||
"message": "Kurulumu sil"
|
||||
"message": "Oturumu sil"
|
||||
},
|
||||
"app.instance.confirm-delete.header": {
|
||||
"message": "Kurulumu sil"
|
||||
"message": "Oturumu sil"
|
||||
},
|
||||
"app.instance.modpack-already-installed.body": {
|
||||
"message": "Bu mod paketi zaten <bold>{instanceName}</bold> kurulumunda yüklü. Kopyalamak istediğinizden emin misiniz?"
|
||||
@@ -255,7 +282,7 @@
|
||||
"message": "Yükle"
|
||||
},
|
||||
"app.modal.install-to-play.mod-count": {
|
||||
"message": "{count, plural,one {#mod}other {#modlar}}"
|
||||
"message": "{count, plural, one {#mod} other {#mods}}"
|
||||
},
|
||||
"app.modal.install-to-play.required-modpack": {
|
||||
"message": "Gerekli mod paketi"
|
||||
@@ -281,6 +308,15 @@
|
||||
"app.modal.update-to-play.update-required-description": {
|
||||
"message": "{name} oyununu oynamak için güncelleme gereklidir. Oyunu başlatmak için lütfen en son sürüme güncelleyin."
|
||||
},
|
||||
"app.project.install-button.already-installed": {
|
||||
"message": "Bu proje zaten kurulu"
|
||||
},
|
||||
"app.project.install-context.back-to-browse": {
|
||||
"message": "Keşfete geri dön"
|
||||
},
|
||||
"app.project.install-context.install-content-to-instance": {
|
||||
"message": "İçeriği kuruluma yükle"
|
||||
},
|
||||
"app.settings.developer-mode-enabled": {
|
||||
"message": "Geliştirici modu açıldı."
|
||||
},
|
||||
@@ -305,11 +341,149 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Kaynak yönetimi"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} güncellemesi indirilmeye hazır! Hemen güncellemek için yeniden başlatın veya Modrinth App’i kapattığınızda otomatik olarak güncellenecek."
|
||||
"app.skins.add-button": {
|
||||
"message": "Skin ekle"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Sürükle ve bırak"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Uygula"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Skin'i sil"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Bu seçilmiş skin'i kalıcı olarak silecektir. Bu işlem geri alınamaz."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Bu skin'i silmek istediğinize gerçekten emin misiniz?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Bıraktığınız dosya okunamadı."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Dosya işlenirken hata oluştu"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Skin'i düzenle"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Skin ekle"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Skin ekleme"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Kol stili"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "İnce"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Klasik"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Pelerin"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Pelerin"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Skin düzenleme"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Önce skin'e bir düzenleme yapın!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Pelerin yok"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Hiçbiri"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Dokuyu değiştir"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Skin'i kaydet"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Kaydediliyor..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Doku"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "İlk başta skin yükleyin!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Skin'i düzenle"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Önizleme"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Skin'inizi çok hızlı değiştiriyorsunuz. Mojang'ın sunucuları geçici olarak diğer istekleri engelledi. Lütfen tekrar denemeden önce biraz bekleyin."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Yavaşla!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "İnşaatçılar & Biyomlar"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Gökyüzünü kovala"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Varsayılan skinler"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Onuru"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Bu skinleri, Onur Ayı boyunca Modrinth'in düzenlediği bir bağış kampanyasına yaptığınız bağış karşılığında aldınız."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Kaos Dağları"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Kaydedilen Skinler"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Yürüyen Kahraman"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "Bakır Çağı"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "Bahçe Uyanıyor"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Küçük Devralma"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Giriş Yap"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Modrinth appdeki skin yönetim özelliklerini kullanmak için lütfen Minecraft hesabınıza giriş yapın."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Heyecanlı Modrinth Bot'u"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Lütfen giriş yapın"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Skin seçici"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} indirildi. Güncellemek için yeniden başlatın veya Modrinth App’i kapattığınızda otomatik olarak güncellenecek."
|
||||
"message": "Modrinth App v{version} indirildi. Güncellemek için yeniden başlatın veya Modrinth App’i kapattığınızda otomatik olarak güncellenecektir."
|
||||
},
|
||||
"app.update-popup.body.linux": {
|
||||
"message": "Modrinth App v{version} yayımlandı. En yeni özellikler ve hata düzeltmeleri için paket yöneticin üzerinden güncelle!"
|
||||
@@ -333,20 +507,11 @@
|
||||
"message": "Güncelleme mevcut"
|
||||
},
|
||||
"app.update.complete-toast.text": {
|
||||
"message": "Değişiklikleri görüntülemek için buraya tıklayın."
|
||||
"message": "Yama notlarını görüntülemek için buraya tıklayın."
|
||||
},
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "{version} sürümü başarıyla kuruldu!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Güncellemeyi indir"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Güncelleme indiriliyor (%{percent})"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Güncellemeyi kurmak için yeniden başlatın"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -360,7 +525,7 @@
|
||||
"message": "Henüz oynanmadı"
|
||||
},
|
||||
"app.world.world-item.offline": {
|
||||
"message": "Çevrim dışı"
|
||||
"message": "Çevrimdışı"
|
||||
},
|
||||
"app.world.world-item.players-online": {
|
||||
"message": "{count} çevrimiçi"
|
||||
@@ -396,16 +561,16 @@
|
||||
"message": "Arkadaşlık isteği gönderildi"
|
||||
},
|
||||
"friends.friend.view-profile": {
|
||||
"message": "Profili gör"
|
||||
"message": "Profili görüntüle"
|
||||
},
|
||||
"friends.heading": {
|
||||
"message": "Arkadaşlar"
|
||||
},
|
||||
"friends.heading.active": {
|
||||
"message": "Aktif"
|
||||
"message": "Çevrimiçi"
|
||||
},
|
||||
"friends.heading.offline": {
|
||||
"message": "Çevrim dışı"
|
||||
"message": "Çevrimdışı"
|
||||
},
|
||||
"friends.heading.online": {
|
||||
"message": "Çevrim içi"
|
||||
@@ -471,7 +636,7 @@
|
||||
"message": "Adres"
|
||||
},
|
||||
"instance.server-modal.name": {
|
||||
"message": "Ad"
|
||||
"message": "Sunucu Adı"
|
||||
},
|
||||
"instance.server-modal.placeholder-name": {
|
||||
"message": "Minecraft Sunucusu"
|
||||
@@ -498,7 +663,7 @@
|
||||
"message": "Çoğalt"
|
||||
},
|
||||
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
|
||||
"message": "İndirilirken çoğaltılamaz."
|
||||
"message": "Kurulurken çoğaltılamaz."
|
||||
},
|
||||
"instance.settings.tabs.general.duplicate-instance": {
|
||||
"message": "Profili çoğalt"
|
||||
@@ -537,7 +702,7 @@
|
||||
"message": "Başlatma kancaları"
|
||||
},
|
||||
"instance.settings.tabs.hooks.custom-hooks": {
|
||||
"message": "Özel başlatma kancası"
|
||||
"message": "Özel başlatma kancaları"
|
||||
},
|
||||
"instance.settings.tabs.hooks.description": {
|
||||
"message": "Kancalar gelişmiş kullanıcıların oyunu başlattıktan önce ve sonra belirli sistem komutları çalıştırmasını sağlar."
|
||||
@@ -564,13 +729,13 @@
|
||||
"message": "Oyun başlatma kancaları"
|
||||
},
|
||||
"instance.settings.tabs.hooks.wrapper": {
|
||||
"message": "Sarmalayıcı"
|
||||
"message": "Paketleyici"
|
||||
},
|
||||
"instance.settings.tabs.hooks.wrapper.description": {
|
||||
"message": "Minecraft'ı başlatmak için sarmalayıcı komutu."
|
||||
"message": "Minecraft'ı başlatmak için paketleyici komutu."
|
||||
},
|
||||
"instance.settings.tabs.hooks.wrapper.enter": {
|
||||
"message": "Sarmalayıcı komutu girin..."
|
||||
"message": "Paketleyici komutu girin..."
|
||||
},
|
||||
"instance.settings.tabs.installation": {
|
||||
"message": "Kurulum"
|
||||
@@ -581,6 +746,24 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java ve bellek"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "Özel ortam değişkenleri"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "Özel Java argümanları"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "Özel Java kurulumu"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "Özel bellek tahsisi"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "Ortam değişkenlerini girin..."
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "Java argümanlarını girin..."
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "Ortam değişkenleri"
|
||||
},
|
||||
@@ -596,6 +779,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "Ayrılan bellek"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/java/kurulum/yolu"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "Pencere"
|
||||
},
|
||||
@@ -657,7 +843,7 @@
|
||||
"message": "Yalnızca Minecraft Alpha 1.0.5 veya daha yüksek sunuculara hızlıca girebilirsin"
|
||||
},
|
||||
"instance.worlds.no_singleplayer_quick_play": {
|
||||
"message": "Yalnızca Minecraft 1.20 veya daha yüksek sürümlerde tek oyunculu dünyalara doğrudan girebilirsin"
|
||||
"message": "Yalnızca Minecraft 1.20+ sürümlerde tek oyunculu dünyalara doğrudan girebilirsin"
|
||||
},
|
||||
"instance.worlds.play_instance": {
|
||||
"message": "Kurulumu oyna"
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Виберіть опцію"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Показує, скільки часу ви провели в цьому профілі."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Час гри"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Умикає можливість перемикання бокової панелі."
|
||||
},
|
||||
@@ -96,7 +102,7 @@
|
||||
"message": "Якщо ви спробуєте встановити файл пакета Modrinth (.mrpack), який не розміщено на Modrinth, ми переконаємося, що ви розумієте ризики, перш ніж установлювати його."
|
||||
},
|
||||
"app.appearance-settings.unknown-pack-warning.title": {
|
||||
"message": "Попереджати мене перед установленням невідомих збірок"
|
||||
"message": "Попередження перед установленням невідомих збірок"
|
||||
},
|
||||
"app.auth-servers.unreachable.body": {
|
||||
"message": "Сервери автентифікації Minecraft можуть зараз не працювати. Перевірте з’єднання з інтернетом та спробуйте пізніше."
|
||||
@@ -320,8 +326,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Керування ресурсами"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} готовий до встановлення! Перезапустіть, щоб оновити зараз. Або, оновлення буде здійснено автоматично, коли закриєте застосунок Modrinth."
|
||||
"app.skins.add-button": {
|
||||
"message": "Додати скін"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Перетягніть і вставте"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Застосувати"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Видалити скін"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Це видалить вибраний скін назавжди. Ця дія не може бути скасована."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Чи ви впевнені що хочете видалити цей скін?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Неможливо відкрити вибраний файл."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Помилка обробки файлу"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Редагувати скін"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Додати скін"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Додавання скіна"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Стиль рук"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Тонкі"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Широкі"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Плащ"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Плащ"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Редагування скіна"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Відредагуйте скін для початку!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Без плаща"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Без"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Замінити текстуру"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Зберегти вигляд"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Збереження…"
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Текстура"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Завантажте скін для початку!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Редагувати скін"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Попередній перегляд"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Ви змінюєте свій скін дуже часто. Сервери Mojang тимчасово заблокували подальші запити. Зачекайте трохи перш ніж спробувати знову."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Шановний!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Усталені скіни"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Ви отримали ці скіни за участь у благодійній акції Modrinth Pride під час місяця прайду."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Збережені скіни"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Увійдіть"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Будь ласка, увійдіть у свій обліковий запис Minecraft, щоб використовувати особливості керування скінами в Modrinth App."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Схвильований бот Modrinth"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Увійдіть"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Вибір скіну"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} завантажено. Перезапустіть зараз, щоб оновити його, або це відбудеться автоматично після закриття Modrinth App."
|
||||
@@ -353,15 +497,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Версію {version} успішно встановлено!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Завантажити оновлення"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Завантаження оновлення ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Перезавантажте, щоб установити оновлення"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -708,10 +843,10 @@
|
||||
"message": "Додати обліковий запис"
|
||||
},
|
||||
"minecraft-account.label": {
|
||||
"message": "Майнкрафт аккаунт"
|
||||
"message": "Обліковий запис Minecraft"
|
||||
},
|
||||
"minecraft-account.not-signed-in": {
|
||||
"message": "Не ввійдено в систему"
|
||||
"message": "Не авторизовано"
|
||||
},
|
||||
"minecraft-account.remove-account": {
|
||||
"message": "Видалити обліковий запис"
|
||||
@@ -720,7 +855,7 @@
|
||||
"message": "Обрати обліковий запис"
|
||||
},
|
||||
"minecraft-account.sign-in": {
|
||||
"message": "Увійти в Майнкрафт"
|
||||
"message": "Увійти в Minecraft"
|
||||
},
|
||||
"search.filter.locked.instance": {
|
||||
"message": "Надано профілем"
|
||||
@@ -753,10 +888,10 @@
|
||||
"message": "Не показувати більше це попередження"
|
||||
},
|
||||
"unknown-pack-warning-modal.header": {
|
||||
"message": "Підтвердити інсталяцію"
|
||||
"message": "Підтвердити встановлення"
|
||||
},
|
||||
"unknown-pack-warning-modal.install-anyway": {
|
||||
"message": "Усе одно інсталювати"
|
||||
"message": "Усе одно встановити"
|
||||
},
|
||||
"unknown-pack-warning-modal.malware-statement": {
|
||||
"message": "Шкідливе програмне забезпечення часто поширюють через файли збірок, які публікуються на таких платформах, як Discord."
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "Chọn một tuỳ chọn"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "Hiển thị thời gian bạn đã dành để chơi bằng một cấu hình."
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "Hiện thời gian chơi"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "Bật tính năng ẩn hiển thị thanh menu bên."
|
||||
},
|
||||
@@ -272,9 +278,6 @@
|
||||
"app.modal.install-to-play.install-button": {
|
||||
"message": "Tải xuống"
|
||||
},
|
||||
"app.modal.install-to-play.mod-count": {
|
||||
"message": "{count, plural, one {# mod} other {# mods}}"
|
||||
},
|
||||
"app.modal.install-to-play.required-modpack": {
|
||||
"message": "Yêu cầu modpack"
|
||||
},
|
||||
@@ -332,8 +335,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "Quản lý tài nguyên"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Phiên bản v{version} của Modrinth đã được chuẩn bị để cài đặt! Khởi động lại ứng dụng để cập nhật ngay bây giờ, hoặc cập nhật tự động khi bạn đóng Modrinth."
|
||||
"app.skins.add-button": {
|
||||
"message": "Skin tự tạo"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "Kéo và thả"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "Áp dụng"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "Xóa skin"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "Hành động này sẽ xóa skin trên vĩnh viễn. Hành động này không thể khôi phục lại."
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "Bạn hoàn toàn muốn xóa skin này chứ?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "Không đọc được file thả."
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "Có lỗi khi đọc file"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "Sửa skin"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "Tạo skin"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "Tạo skin"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "Độ rộng cánh tay"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "Gầy"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "Béo"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "Cape"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "Cape"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "Sửa skin"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "Sửa skin trước đã!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "Không cape"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "Không"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "Đổi skin"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "Lưu skin"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "Đang lưu..."
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "Skin"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "Nhập skin vào trước đã!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "Sửa skin"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "Xem trước"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "Bạn đang chỉnh skin quá thường xuyên. Mãy chủ của Mojang đã tạm thời chặn lại các yêu cầu hiện thời. Đợi một lúc trước khi thử lại lần nữa."
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "Bình tĩnh lại!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "Builders & Biomes"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "Chase the Skies"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "Skin mặc định"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth Pride"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "Bạn đã được tặng những skin này sau khi quyên góp cho Modrinth trong tháng tự hào LGBT thế giới."
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "Mounts of Mayhem"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "Skin đã lưu"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "The Copper Age"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "The Garden Awakens"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "Tiny Takeover"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "Đăng nhập"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "Đặng nhập vào mội tài khoản Minecraft để đổi skin Skin trong ứng dụng này."
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "Bot phấn khích"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "Đăng nhập đã"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "Đổi skin"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Phiên bản v{version} của Modrinth đã sẵn sàng để có thể cài đặt. Khởi động lại ứng dụng để cập nhật ngay bây giờ, hoặc tự động cập nhật sau khi bạn tắt Modrinth."
|
||||
@@ -365,15 +506,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Phiên bản {version} đã được cài đặt thành công!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "Tải về bản cập nhật"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "Đang tải xuống bản cập nhật ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "Hãy khởi động lại để cài đặt bản cập nhật"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -395,9 +527,6 @@
|
||||
"friends.action.add-friend": {
|
||||
"message": "Thêm một người bạn"
|
||||
},
|
||||
"friends.action.view-friend-requests": {
|
||||
"message": "{count} yêu cầu kết bạn {count, plural, one {request} other {requests}}"
|
||||
},
|
||||
"friends.add-friend.submit": {
|
||||
"message": "Gửi yêu cầu kết bạn"
|
||||
},
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "选择一个选项"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "显示你在每个实例中游玩的时间。"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "显示总游玩时间"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "启用切换侧边栏的功能。"
|
||||
},
|
||||
@@ -120,7 +126,7 @@
|
||||
"message": "已添加"
|
||||
},
|
||||
"app.browse.already-added": {
|
||||
"message": "已添加过"
|
||||
"message": "已经添加"
|
||||
},
|
||||
"app.browse.back-to-instance": {
|
||||
"message": "返回实例"
|
||||
@@ -143,6 +149,9 @@
|
||||
"app.browse.server.installing": {
|
||||
"message": "安装中"
|
||||
},
|
||||
"app.content-install.no-compatible-versions": {
|
||||
"message": "没有与 {compatibilityLabel} 匹配的可用版本。如果仍要安装,请选择一个版本。依赖项将不会自动安装。"
|
||||
},
|
||||
"app.creation-modal.installing-modpack.description": {
|
||||
"message": "{fileName}"
|
||||
},
|
||||
@@ -320,8 +329,146 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "资源管理"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} 更新已就绪!立即重启更新,或退出时自动安装。"
|
||||
"app.skins.add-button": {
|
||||
"message": "添加皮肤"
|
||||
},
|
||||
"app.skins.add-button.drag-and-drop": {
|
||||
"message": "拖放"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "应用"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "删除皮肤"
|
||||
},
|
||||
"app.skins.delete-modal.description": {
|
||||
"message": "这会永久删除所选皮肤。这操作无法撤销。"
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "你确定要删除这个皮肤吗?"
|
||||
},
|
||||
"app.skins.dropped-file-error.text": {
|
||||
"message": "无法读取拖放的文件。"
|
||||
},
|
||||
"app.skins.dropped-file-error.title": {
|
||||
"message": "处理文件时出错"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "编辑皮肤"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "添加皮肤"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "添加皮肤中"
|
||||
},
|
||||
"app.skins.modal.arm-style-section": {
|
||||
"message": "手臂样式"
|
||||
},
|
||||
"app.skins.modal.arm-style-slim": {
|
||||
"message": "细"
|
||||
},
|
||||
"app.skins.modal.arm-style-wide": {
|
||||
"message": "粗"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "披风"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "披风"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "编辑皮肤中"
|
||||
},
|
||||
"app.skins.modal.make-edit-first-tooltip": {
|
||||
"message": "请先对皮肤进行编辑!"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "无披风"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "无"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "替换纹理"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "保存皮肤"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "保存中……"
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "纹理"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "请先上传皮肤!"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "编辑皮肤"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "预览"
|
||||
},
|
||||
"app.skins.rate-limit.text": {
|
||||
"message": "你更改皮肤过于频繁。Mojang服务器已暂时阻止了后续请求。请稍等片刻后再试。"
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "慢点!"
|
||||
},
|
||||
"app.skins.section.builders-and-biomes": {
|
||||
"message": "建造者与生物群系"
|
||||
},
|
||||
"app.skins.section.chase-the-skies": {
|
||||
"message": "追逐天空"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "默认皮肤"
|
||||
},
|
||||
"app.skins.section.minecon-earth-2017": {
|
||||
"message": "MINECON Earth 2017"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.modrinth-pride": {
|
||||
"message": "Modrinth 精选"
|
||||
},
|
||||
"app.skins.section.modrinth-pride.tooltip": {
|
||||
"message": "你在骄傲月期间为 Modrinth 的骄傲月筹款活动捐款,因此获得了这些皮肤。"
|
||||
},
|
||||
"app.skins.section.mounts-of-mayhem": {
|
||||
"message": "群骑纷争"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "已保存皮肤"
|
||||
},
|
||||
"app.skins.section.striding-hero": {
|
||||
"message": "Striding Hero"
|
||||
},
|
||||
"app.skins.section.the-copper-age": {
|
||||
"message": "铜器时代"
|
||||
},
|
||||
"app.skins.section.the-garden-awakens": {
|
||||
"message": "苍园觉醒"
|
||||
},
|
||||
"app.skins.section.tiny-takeover": {
|
||||
"message": "小鬼当家"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "登录"
|
||||
},
|
||||
"app.skins.sign-in.description": {
|
||||
"message": "请登录您的 Minecraft 账号,以便使用 Modrinth 应用的皮肤管理功能。"
|
||||
},
|
||||
"app.skins.sign-in.rinthbot-alt": {
|
||||
"message": "兴奋的 Modrinth Bot"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "请登录"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "皮肤选择器"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} 更新已下载完成!立即重启更新,或退出时自动安装。"
|
||||
@@ -353,15 +500,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "版本 {version} 已成功安装!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "下载更新"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "下载更新中({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "重启以安装更新"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
@@ -596,6 +734,24 @@
|
||||
"instance.settings.tabs.java": {
|
||||
"message": "Java 及内存"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-environment-variables": {
|
||||
"message": "自定义环境变量"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-arguments": {
|
||||
"message": "自定义Java参数"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-java-installation": {
|
||||
"message": "自定义Java安装"
|
||||
},
|
||||
"instance.settings.tabs.java.custom-memory-allocation": {
|
||||
"message": "自定义内存分配"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-environment-variables": {
|
||||
"message": "输入环境变量……"
|
||||
},
|
||||
"instance.settings.tabs.java.enter-java-arguments": {
|
||||
"message": "输入 Java 参数……"
|
||||
},
|
||||
"instance.settings.tabs.java.environment-variables": {
|
||||
"message": "环境变量"
|
||||
},
|
||||
@@ -611,6 +767,9 @@
|
||||
"instance.settings.tabs.java.java-memory": {
|
||||
"message": "内存分配"
|
||||
},
|
||||
"instance.settings.tabs.java.java-path-placeholder": {
|
||||
"message": "/path/to/java"
|
||||
},
|
||||
"instance.settings.tabs.window": {
|
||||
"message": "游戏窗口"
|
||||
},
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
"app.appearance-settings.select-option": {
|
||||
"message": "選擇選項"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.description": {
|
||||
"message": "顯示您在該實例的遊玩時間"
|
||||
},
|
||||
"app.appearance-settings.show-play-time.title": {
|
||||
"message": "顯示遊玩時間"
|
||||
},
|
||||
"app.appearance-settings.toggle-sidebar.description": {
|
||||
"message": "啟用切換側邊欄的功能。"
|
||||
},
|
||||
@@ -320,8 +326,83 @@
|
||||
"app.settings.tabs.resource-management": {
|
||||
"message": "資源管理"
|
||||
},
|
||||
"app.update-popup.body": {
|
||||
"message": "Modrinth App v{version} 已準備好安裝!立即重新載入以更新,或在關閉 Modrinth App 時自動更新。"
|
||||
"app.skins.add-button": {
|
||||
"message": "新增皮膚"
|
||||
},
|
||||
"app.skins.apply-button": {
|
||||
"message": "確認"
|
||||
},
|
||||
"app.skins.delete-button": {
|
||||
"message": "刪除皮膚"
|
||||
},
|
||||
"app.skins.delete-modal.title": {
|
||||
"message": "你確定要刪除這個皮膚嗎"
|
||||
},
|
||||
"app.skins.edit-button": {
|
||||
"message": "編輯皮膚"
|
||||
},
|
||||
"app.skins.modal.add-skin-button": {
|
||||
"message": "新增皮膚"
|
||||
},
|
||||
"app.skins.modal.add-title": {
|
||||
"message": "正在新增皮膚"
|
||||
},
|
||||
"app.skins.modal.cape-fallback-name": {
|
||||
"message": "披風"
|
||||
},
|
||||
"app.skins.modal.cape-section": {
|
||||
"message": "披風"
|
||||
},
|
||||
"app.skins.modal.edit-title": {
|
||||
"message": "編輯皮膚"
|
||||
},
|
||||
"app.skins.modal.no-cape-tooltip": {
|
||||
"message": "無披風"
|
||||
},
|
||||
"app.skins.modal.none-cape-option": {
|
||||
"message": "無"
|
||||
},
|
||||
"app.skins.modal.replace-texture-button": {
|
||||
"message": "覆蓋材質包"
|
||||
},
|
||||
"app.skins.modal.save-skin-button": {
|
||||
"message": "儲存皮膚"
|
||||
},
|
||||
"app.skins.modal.saving-tooltip": {
|
||||
"message": "正在儲存"
|
||||
},
|
||||
"app.skins.modal.texture-section": {
|
||||
"message": "材質包"
|
||||
},
|
||||
"app.skins.modal.upload-skin-first-tooltip": {
|
||||
"message": "馬上新增一個皮膚"
|
||||
},
|
||||
"app.skins.preview.edit-button": {
|
||||
"message": "編輯皮膚"
|
||||
},
|
||||
"app.skins.previewing-badge": {
|
||||
"message": "正在預覽"
|
||||
},
|
||||
"app.skins.rate-limit.title": {
|
||||
"message": "慢一點"
|
||||
},
|
||||
"app.skins.section.default-skins": {
|
||||
"message": "預設皮膚"
|
||||
},
|
||||
"app.skins.section.modrinth": {
|
||||
"message": "Modrinth"
|
||||
},
|
||||
"app.skins.section.saved-skins": {
|
||||
"message": "皮膚已儲存"
|
||||
},
|
||||
"app.skins.sign-in.button": {
|
||||
"message": "登入"
|
||||
},
|
||||
"app.skins.sign-in.title": {
|
||||
"message": "請登入"
|
||||
},
|
||||
"app.skins.title": {
|
||||
"message": "皮膚選擇"
|
||||
},
|
||||
"app.update-popup.body.download-complete": {
|
||||
"message": "Modrinth App v{version} 已完成下載!立即重新載入以更新,或在關閉 Modrinth App 時自動更新。"
|
||||
@@ -353,15 +434,6 @@
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "版本 {version} 已成功安裝!"
|
||||
},
|
||||
"app.update.download-update": {
|
||||
"message": "下載更新"
|
||||
},
|
||||
"app.update.downloading-update": {
|
||||
"message": "正在下載更新 ({percent}%)"
|
||||
},
|
||||
"app.update.reload-to-update": {
|
||||
"message": "重新載入即可安裝更新"
|
||||
},
|
||||
"app.world.server-modal.placeholder-address": {
|
||||
"message": "example.modrinth.gg"
|
||||
},
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
import { useQueryClient } from '@tanstack/vue-query'
|
||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||
import type { Ref } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import type { LocationQuery } from 'vue-router'
|
||||
import { onBeforeRouteLeave, useRoute, useRouter } from 'vue-router'
|
||||
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
get_search_results_v3,
|
||||
get_version_many,
|
||||
} from '@/helpers/cache.js'
|
||||
import { profile_listener } from '@/helpers/events.js'
|
||||
import { get_loader_versions as getLoaderManifest } from '@/helpers/metadata'
|
||||
import {
|
||||
get as getInstance,
|
||||
@@ -181,6 +182,28 @@ watchServerContextChanges()
|
||||
|
||||
await initInstanceContext()
|
||||
|
||||
async function refreshInstalledProjectIds() {
|
||||
if (!route.query.i) return
|
||||
|
||||
if (route.query.from === 'worlds') {
|
||||
const worlds = await get_profile_worlds(route.query.i as string).catch(handleError)
|
||||
if (!worlds) return
|
||||
|
||||
const serverProjectIds = worlds
|
||||
.filter((w) => w.type === 'server' && 'project_id' in w && w.project_id)
|
||||
.map((w) => (w as { project_id: string }).project_id)
|
||||
debugLog('installedServerProjectIds loaded', { count: serverProjectIds.length })
|
||||
installedProjectIds.value = serverProjectIds
|
||||
return
|
||||
}
|
||||
|
||||
const ids = await getInstalledProjectIds(route.query.i as string).catch(handleError)
|
||||
if (!ids) return
|
||||
|
||||
debugLog('installedProjectIds loaded', { count: ids.length })
|
||||
installedProjectIds.value = ids
|
||||
}
|
||||
|
||||
async function initInstanceContext() {
|
||||
debugLog('initInstanceContext', {
|
||||
queryI: route.query.i,
|
||||
@@ -199,24 +222,7 @@ async function initInstanceContext() {
|
||||
gameVersion: instance.value?.game_version,
|
||||
})
|
||||
|
||||
if (route.query.from === 'worlds') {
|
||||
get_profile_worlds(route.query.i as string)
|
||||
.then((worlds) => {
|
||||
const serverProjectIds = worlds
|
||||
.filter((w) => w.type === 'server' && 'project_id' in w && w.project_id)
|
||||
.map((w) => (w as { project_id: string }).project_id)
|
||||
debugLog('installedServerProjectIds loaded', { count: serverProjectIds.length })
|
||||
installedProjectIds.value = serverProjectIds
|
||||
})
|
||||
.catch(handleError)
|
||||
} else {
|
||||
getInstalledProjectIds(route.query.i as string)
|
||||
.then((ids) => {
|
||||
debugLog('installedProjectIds loaded', { count: ids?.length })
|
||||
installedProjectIds.value = ids
|
||||
})
|
||||
.catch(handleError)
|
||||
}
|
||||
await refreshInstalledProjectIds()
|
||||
|
||||
if (instance.value?.linked_data?.project_id) {
|
||||
debugLog('checking linked project for server status', instance.value.linked_data.project_id)
|
||||
@@ -805,10 +811,10 @@ function getCardActions(
|
||||
selectedInstall.versionId,
|
||||
instance.value ? instance.value.path : null,
|
||||
'SearchCard',
|
||||
(versionId) => {
|
||||
(versionId, installedProjectIds) => {
|
||||
setProjectInstalling(projectResult.project_id, false)
|
||||
if (versionId) {
|
||||
onSearchResultInstalled(projectResult.project_id)
|
||||
onSearchResultsInstalled(installedProjectIds ?? [projectResult.project_id])
|
||||
}
|
||||
},
|
||||
(profile) => {
|
||||
@@ -834,7 +840,19 @@ function onSearchResultInstalled(id: string) {
|
||||
markServerProjectInstalled(id)
|
||||
return
|
||||
}
|
||||
newlyInstalled.value.push(id)
|
||||
if (!newlyInstalled.value.includes(id)) {
|
||||
newlyInstalled.value = [...newlyInstalled.value, id]
|
||||
}
|
||||
}
|
||||
|
||||
function onSearchResultsInstalled(ids: string[]) {
|
||||
if (isServerContext.value) {
|
||||
for (const id of ids) {
|
||||
markServerProjectInstalled(id)
|
||||
}
|
||||
return
|
||||
}
|
||||
newlyInstalled.value = Array.from(new Set([...newlyInstalled.value, ...ids]))
|
||||
}
|
||||
|
||||
async function search(requestParams: string) {
|
||||
@@ -966,6 +984,38 @@ if (instance.value?.game_version) {
|
||||
|
||||
await searchState.refreshSearch()
|
||||
|
||||
type UnlistenFn = () => void
|
||||
|
||||
let isUnmounted = false
|
||||
let unlistenProfiles: UnlistenFn | null = null
|
||||
|
||||
onMounted(() => {
|
||||
profile_listener(async (event: { event: string; profile_path_id: string }) => {
|
||||
if (
|
||||
instance.value &&
|
||||
event.profile_path_id === instance.value.path &&
|
||||
event.event === 'synced'
|
||||
) {
|
||||
await refreshInstalledProjectIds()
|
||||
await searchState.refreshSearch()
|
||||
}
|
||||
})
|
||||
.then((unlisten) => {
|
||||
if (isUnmounted) {
|
||||
unlisten()
|
||||
return
|
||||
}
|
||||
|
||||
unlistenProfiles = unlisten
|
||||
})
|
||||
.catch(handleError)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
isUnmounted = true
|
||||
unlistenProfiles?.()
|
||||
})
|
||||
|
||||
function getProjectBrowseQuery() {
|
||||
if (!installContext.value) return undefined
|
||||
return {
|
||||
|
||||
@@ -30,7 +30,7 @@ import type AccountsCard from '@/components/ui/AccountsCard.vue'
|
||||
import EditSkinModal from '@/components/ui/skin/EditSkinModal.vue'
|
||||
import VirtualSkinSectionList from '@/components/ui/skin/VirtualSkinSectionList.vue'
|
||||
import { trackEvent } from '@/helpers/analytics'
|
||||
import { get_default_user, login as login_flow, users } from '@/helpers/auth'
|
||||
import { check_reachable, get_default_user, login as login_flow, users } from '@/helpers/auth'
|
||||
import type { RenderResult } from '@/helpers/rendering/batch-skin-renderer.ts'
|
||||
import { generateSkinPreviews, skinBlobUrlMap } from '@/helpers/rendering/batch-skin-renderer.ts'
|
||||
import type { Cape, Skin, SkinTextureUrl } from '@/helpers/skins.ts'
|
||||
@@ -46,6 +46,8 @@ import {
|
||||
get_normalized_skin_texture,
|
||||
normalize_skin_texture,
|
||||
remove_custom_skin,
|
||||
save_custom_skin,
|
||||
set_custom_skin_order,
|
||||
} from '@/helpers/skins.ts'
|
||||
import { hasPride26Badge } from '@/helpers/user-campaigns.ts'
|
||||
import { handleSevereError } from '@/store/error'
|
||||
@@ -129,6 +131,14 @@ const messages = defineMessages({
|
||||
id: 'app.skins.dropped-file-error.text',
|
||||
defaultMessage: 'Failed to read the dropped file.',
|
||||
},
|
||||
reorderSkinErrorTitle: {
|
||||
id: 'app.skins.reorder-error.title',
|
||||
defaultMessage: 'Failed to reorder skins',
|
||||
},
|
||||
reorderSkinErrorText: {
|
||||
id: 'app.skins.reorder-error.text',
|
||||
defaultMessage: 'Your skin order could not be saved.',
|
||||
},
|
||||
deleteSkinTitle: {
|
||||
id: 'app.skins.delete-modal.title',
|
||||
defaultMessage: 'Are you sure you want to delete this skin?',
|
||||
@@ -181,6 +191,7 @@ const client = injectModrinthClient()
|
||||
const themeStore = useTheming()
|
||||
const skins = ref<Skin[]>([])
|
||||
const capes = ref<Cape[]>([])
|
||||
const offline = ref(!navigator.onLine)
|
||||
|
||||
const accountsCard = inject('accountsCard') as Ref<typeof AccountsCard>
|
||||
const currentUser = ref(undefined)
|
||||
@@ -200,6 +211,16 @@ const savedSkins = computed(() => {
|
||||
return []
|
||||
}
|
||||
})
|
||||
const authServerQuery = useQuery({
|
||||
queryKey: ['authServerReachability'],
|
||||
queryFn: async () => {
|
||||
await check_reachable()
|
||||
return true
|
||||
},
|
||||
refetchInterval: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
refetchOnWindowFocus: false,
|
||||
})
|
||||
const { data: modrinthUser } = useQuery({
|
||||
queryKey: computed(() => ['authenticated-user', 'campaigns', auth.user.value?.id]),
|
||||
queryFn: () => client.labrinth.users_v3.getAuthenticated(),
|
||||
@@ -249,8 +270,18 @@ const currentCape = computed(() => {
|
||||
})
|
||||
|
||||
const skinTexture = computedAsync(async () => {
|
||||
if (selectedSkin.value?.texture) {
|
||||
return await get_normalized_skin_texture(selectedSkin.value)
|
||||
const skin = selectedSkin.value
|
||||
if (skin?.texture) {
|
||||
try {
|
||||
return await get_normalized_skin_texture(skin)
|
||||
} catch (error) {
|
||||
if (skin.texture.startsWith('data:image/')) {
|
||||
return skin.texture
|
||||
}
|
||||
|
||||
handleError(error as Error)
|
||||
return ''
|
||||
}
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
@@ -258,6 +289,9 @@ const skinTexture = computedAsync(async () => {
|
||||
const capeTexture = computed(() => currentCape.value?.texture)
|
||||
const skinVariant = computed(() => selectedSkin.value?.variant)
|
||||
const skinNametag = computed(() => (themeStore.hideNametagSkinsPage ? undefined : username.value))
|
||||
const isSkinManagementReadOnly = computed(
|
||||
() => offline.value || (authServerQuery.isError.value && !authServerQuery.isLoading.value),
|
||||
)
|
||||
const hasPendingSkinChange = computed(
|
||||
() => !skinsMatch(selectedSkin.value, originalSelectedSkin.value),
|
||||
)
|
||||
@@ -274,11 +308,15 @@ const deleteSkinModal = ref()
|
||||
const skinToDelete = ref<Skin | null>(null)
|
||||
|
||||
function confirmDeleteSkin(skin: Skin) {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
skinToDelete.value = skin
|
||||
deleteSkinModal.value?.show()
|
||||
}
|
||||
|
||||
async function deleteSkin() {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
const deletedSkin = skinToDelete.value
|
||||
if (!deletedSkin) return
|
||||
|
||||
@@ -304,7 +342,23 @@ async function loadCapes() {
|
||||
|
||||
async function loadSkins() {
|
||||
try {
|
||||
skins.value = (await get_available_skins()) ?? []
|
||||
const loadedSkins = (await get_available_skins()) ?? []
|
||||
const loadedEquippedSkin = loadedSkins.find((s) => s.is_equipped)
|
||||
const locallyKnownEquippedSkin =
|
||||
originalSelectedSkin.value &&
|
||||
(loadedSkins.find((skin) => skinsMatch(skin, originalSelectedSkin.value)) ??
|
||||
(originalSelectedSkin.value.texture.startsWith('data:image/')
|
||||
? originalSelectedSkin.value
|
||||
: undefined))
|
||||
const shouldPreserveKnownEquippedSkin =
|
||||
isSkinManagementReadOnly.value &&
|
||||
locallyKnownEquippedSkin &&
|
||||
!skinsMatch(loadedEquippedSkin, locallyKnownEquippedSkin)
|
||||
|
||||
skins.value =
|
||||
shouldPreserveKnownEquippedSkin && locallyKnownEquippedSkin
|
||||
? mergeEquippedSkin(loadedSkins, locallyKnownEquippedSkin)
|
||||
: loadedSkins
|
||||
generateSkinPreviews(skins.value, capes.value)
|
||||
selectedSkin.value = skins.value.find((s) => s.is_equipped) ?? null
|
||||
originalSelectedSkin.value = selectedSkin.value
|
||||
@@ -315,6 +369,28 @@ async function loadSkins() {
|
||||
}
|
||||
}
|
||||
|
||||
function mergeEquippedSkin(list: Skin[], equippedSkin: Skin) {
|
||||
let foundEquippedSkin = false
|
||||
const mergedSkins = list.map((skin) => {
|
||||
const isEquipped = skinsMatch(skin, equippedSkin)
|
||||
foundEquippedSkin ||= isEquipped
|
||||
|
||||
return {
|
||||
...skin,
|
||||
is_equipped: isEquipped,
|
||||
}
|
||||
})
|
||||
|
||||
if (!foundEquippedSkin) {
|
||||
mergedSkins.unshift({
|
||||
...equippedSkin,
|
||||
is_equipped: true,
|
||||
})
|
||||
}
|
||||
|
||||
return mergedSkins
|
||||
}
|
||||
|
||||
function skinsMatch(a?: Skin | null, b?: Skin | null) {
|
||||
return (
|
||||
a?.source === b?.source &&
|
||||
@@ -324,6 +400,14 @@ function skinsMatch(a?: Skin | null, b?: Skin | null) {
|
||||
)
|
||||
}
|
||||
|
||||
function skinsMatchIgnoringSource(a?: Skin | null, b?: Skin | null) {
|
||||
return (
|
||||
a?.texture_key === b?.texture_key &&
|
||||
a?.variant === b?.variant &&
|
||||
(a?.cape_id ?? null) === (b?.cape_id ?? null)
|
||||
)
|
||||
}
|
||||
|
||||
function isSkinSelected(skin: Skin) {
|
||||
return skinsMatch(selectedSkin.value, skin)
|
||||
}
|
||||
@@ -385,6 +469,8 @@ function getDefaultSkinSectionSortIndex(section: string) {
|
||||
}
|
||||
|
||||
function changeSkin(newSkin: Skin) {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
selectedSkin.value = newSkin
|
||||
}
|
||||
|
||||
@@ -423,6 +509,19 @@ function setLocallyEquippedSkin(skinToApply: Skin) {
|
||||
void accountsCard.value?.setEquippedSkin(originalSelectedSkin.value)
|
||||
}
|
||||
|
||||
function insertLocalSkin(savedSkin: Skin) {
|
||||
const firstNonCustomSkinIndex = skins.value.findIndex((skin) => skin.source !== 'custom')
|
||||
|
||||
if (firstNonCustomSkinIndex === -1) {
|
||||
skins.value = [...skins.value, savedSkin]
|
||||
return
|
||||
}
|
||||
|
||||
const nextSkins = [...skins.value]
|
||||
nextSkins.splice(firstNonCustomSkinIndex, 0, savedSkin)
|
||||
skins.value = nextSkins
|
||||
}
|
||||
|
||||
function updateLocalSkin(savedSkin: Skin, applied: boolean, previousSkin?: Skin) {
|
||||
let foundSkin = false
|
||||
const replacesSelectedSkin =
|
||||
@@ -451,7 +550,7 @@ function updateLocalSkin(savedSkin: Skin, applied: boolean, previousSkin?: Skin)
|
||||
})
|
||||
|
||||
if (!foundSkin) {
|
||||
skins.value.unshift({
|
||||
insertLocalSkin({
|
||||
...savedSkin,
|
||||
is_equipped: applied || savedSkin.is_equipped,
|
||||
})
|
||||
@@ -480,6 +579,81 @@ function updateLocalSkin(savedSkin: Skin, applied: boolean, previousSkin?: Skin)
|
||||
generateSkinPreviews(skins.value, capes.value)
|
||||
}
|
||||
|
||||
async function reorderSavedSkins(orderedSkins: Skin[]) {
|
||||
const previousSkins = skins.value
|
||||
const previousSelectedSkin = selectedSkin.value
|
||||
const previousOriginalSelectedSkin = originalSelectedSkin.value
|
||||
const orderedTextureKeys = orderedSkins.map((skin) => skin.texture_key)
|
||||
const orderedTextureKeySet = new Set(orderedTextureKeys)
|
||||
const remainingSavedSkins = previousSkins.filter(
|
||||
(skin) => skin.source !== 'default' && !orderedTextureKeySet.has(skin.texture_key),
|
||||
)
|
||||
const defaultSkins = previousSkins.filter((skin) => skin.source === 'default')
|
||||
const nextSavedSkins = [...orderedSkins, ...remainingSavedSkins]
|
||||
|
||||
skins.value = [...nextSavedSkins, ...defaultSkins]
|
||||
generateSkinPreviews(skins.value, capes.value)
|
||||
|
||||
try {
|
||||
const persistedSavedSkins = await preserveExternalSkins(nextSavedSkins)
|
||||
|
||||
if (persistedSavedSkins.some((skin, index) => skin !== nextSavedSkins[index])) {
|
||||
skins.value = [...persistedSavedSkins, ...defaultSkins]
|
||||
generateSkinPreviews(skins.value, capes.value)
|
||||
}
|
||||
|
||||
await set_custom_skin_order(
|
||||
persistedSavedSkins
|
||||
.filter((skin) => skin.source === 'custom')
|
||||
.map((skin) => skin.texture_key),
|
||||
)
|
||||
} catch (error) {
|
||||
skins.value = previousSkins
|
||||
selectedSkin.value = previousSelectedSkin
|
||||
originalSelectedSkin.value = previousOriginalSelectedSkin
|
||||
generateSkinPreviews(skins.value, capes.value)
|
||||
addNotification({
|
||||
type: 'error',
|
||||
title: formatMessage(messages.reorderSkinErrorTitle),
|
||||
text: error instanceof Error ? error.message : formatMessage(messages.reorderSkinErrorText),
|
||||
})
|
||||
await loadSkins()
|
||||
}
|
||||
}
|
||||
|
||||
async function preserveExternalSkins(skinsToPersist: Skin[]) {
|
||||
const preservedSkins: Skin[] = []
|
||||
|
||||
for (const skin of skinsToPersist) {
|
||||
if (skin.source !== 'custom_external') {
|
||||
preservedSkins.push(skin)
|
||||
continue
|
||||
}
|
||||
|
||||
const textureBlob = await normalize_skin_texture(skin.texture)
|
||||
const capeId = skin.cape_id ? capes.value.find((cape) => cape.id === skin.cape_id) : undefined
|
||||
const savedSkin = await save_custom_skin(skin, textureBlob, skin.variant, capeId, false)
|
||||
const preservedSkin: Skin = {
|
||||
...savedSkin,
|
||||
source: 'custom',
|
||||
is_equipped: skin.is_equipped,
|
||||
}
|
||||
|
||||
if (skinsMatchIgnoringSource(selectedSkin.value, skin)) {
|
||||
selectedSkin.value = preservedSkin
|
||||
}
|
||||
|
||||
if (skinsMatchIgnoringSource(originalSelectedSkin.value, skin)) {
|
||||
originalSelectedSkin.value = preservedSkin
|
||||
void accountsCard.value?.setEquippedSkin(preservedSkin)
|
||||
}
|
||||
|
||||
preservedSkins.push(preservedSkin)
|
||||
}
|
||||
|
||||
return preservedSkins
|
||||
}
|
||||
|
||||
function schedulePendingSkinRefresh() {
|
||||
if (pendingSkinRefreshTimeout !== null) {
|
||||
window.clearTimeout(pendingSkinRefreshTimeout)
|
||||
@@ -517,7 +691,13 @@ function schedulePendingSkinRefresh() {
|
||||
|
||||
async function applySelectedSkin() {
|
||||
const skinToApply = selectedSkin.value
|
||||
if (!skinToApply || !hasPendingSkinChange.value || isApplyingSkin.value) return
|
||||
if (
|
||||
!skinToApply ||
|
||||
!hasPendingSkinChange.value ||
|
||||
isApplyingSkin.value ||
|
||||
isSkinManagementReadOnly.value
|
||||
)
|
||||
return
|
||||
|
||||
isApplyingSkin.value = true
|
||||
try {
|
||||
@@ -586,10 +766,14 @@ async function login() {
|
||||
}
|
||||
|
||||
function openAddSkinFileBrowser() {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
addSkinFileInput.value?.click()
|
||||
}
|
||||
|
||||
async function onAddSkinFileInputChange(e: Event) {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
const files = (e.target as HTMLInputElement).files
|
||||
const file = files?.[0]
|
||||
|
||||
@@ -632,6 +816,8 @@ function isPositionOverAddSkinButton(position: { x: number; y: number }) {
|
||||
}
|
||||
|
||||
async function handleAddSkinNativeDragDrop(event: { payload: DragDropEvent }) {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
const payload = event.payload
|
||||
|
||||
if (payload.type === 'leave') {
|
||||
@@ -680,6 +866,8 @@ async function handleAddSkinNativeDragDrop(event: { payload: DragDropEvent }) {
|
||||
}
|
||||
|
||||
function onAddSkinDragOver(event: DragEvent) {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
if (!isSkinFileDrag(event)) {
|
||||
return
|
||||
}
|
||||
@@ -688,10 +876,14 @@ function onAddSkinDragOver(event: DragEvent) {
|
||||
}
|
||||
|
||||
function onAddSkinDragLeave() {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
isAddSkinButtonDragActive.value = false
|
||||
}
|
||||
|
||||
async function onAddSkinDrop(event: DragEvent) {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
isAddSkinButtonDragActive.value = false
|
||||
|
||||
const file = Array.from(event.dataTransfer?.files ?? []).find(
|
||||
@@ -721,6 +913,8 @@ async function setupAddSkinDragDropListener() {
|
||||
}
|
||||
|
||||
async function processSkinFileBuffer(buffer: Uint8Array | ArrayBuffer) {
|
||||
if (isSkinManagementReadOnly.value) return
|
||||
|
||||
const fakeEvent = new MouseEvent('click')
|
||||
const originalSkinTexUrl = `data:image/png;base64,` + arrayBufferToBase64(buffer)
|
||||
try {
|
||||
@@ -740,13 +934,24 @@ watch(
|
||||
() => {},
|
||||
)
|
||||
|
||||
watch(isSkinManagementReadOnly, (readOnly) => {
|
||||
if (readOnly) {
|
||||
isDraggingSkinFile.value = false
|
||||
isAddSkinButtonDragActive.value = false
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('offline', onOffline)
|
||||
window.addEventListener('online', onOnline)
|
||||
userCheckInterval = window.setInterval(checkUserChanges, 250)
|
||||
void setupAddSkinDragDropListener()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
isUnmounted = true
|
||||
window.removeEventListener('offline', onOffline)
|
||||
window.removeEventListener('online', onOnline)
|
||||
|
||||
if (userCheckInterval !== null) {
|
||||
window.clearInterval(userCheckInterval)
|
||||
@@ -763,6 +968,15 @@ onUnmounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
function onOffline() {
|
||||
offline.value = true
|
||||
}
|
||||
|
||||
function onOnline() {
|
||||
offline.value = false
|
||||
void authServerQuery.refetch()
|
||||
}
|
||||
|
||||
async function checkUserChanges() {
|
||||
try {
|
||||
const defaultId = await get_default_user()
|
||||
@@ -834,7 +1048,7 @@ await loadSkins()
|
||||
>
|
||||
<button
|
||||
class="flex h-10 min-w-0 cursor-pointer items-center justify-center gap-2 rounded-[14px] border-0 bg-surface-4 px-4 py-2.5 text-base font-semibold leading-5 text-contrast shadow-md transition-[filter,transform] duration-200 enabled:hover:brightness-[--hover-brightness] enabled:focus-visible:brightness-[--hover-brightness] enabled:active:scale-95 disabled:cursor-not-allowed disabled:opacity-50 [&>svg]:size-5 [&>svg]:shrink-0"
|
||||
:disabled="isApplyingSkin"
|
||||
:disabled="isApplyingSkin || isSkinManagementReadOnly"
|
||||
@click="resetSelectedSkin"
|
||||
>
|
||||
<RotateCounterClockwiseIcon />
|
||||
@@ -842,7 +1056,7 @@ await loadSkins()
|
||||
</button>
|
||||
<button
|
||||
class="flex h-10 min-w-0 cursor-pointer items-center justify-center gap-2 rounded-[14px] border-0 bg-brand px-4 py-2.5 text-base font-semibold leading-5 text-[rgba(0,0,0,0.9)] shadow-md transition-[filter,transform] duration-200 enabled:hover:brightness-[--hover-brightness] enabled:focus-visible:brightness-[--hover-brightness] enabled:active:scale-95 disabled:cursor-not-allowed disabled:opacity-50 [&>svg]:size-5 [&>svg]:shrink-0"
|
||||
:disabled="isApplyingSkin"
|
||||
:disabled="isApplyingSkin || isSkinManagementReadOnly"
|
||||
@click="applySelectedSkin"
|
||||
>
|
||||
<SpinnerIcon v-if="isApplyingSkin" class="animate-spin" />
|
||||
@@ -853,7 +1067,7 @@ await loadSkins()
|
||||
<button
|
||||
v-else
|
||||
class="flex h-10 min-w-0 cursor-pointer items-center justify-center gap-2 rounded-[14px] border-0 bg-surface-4 px-4 py-2.5 text-base font-semibold leading-5 shadow-md transition-[filter,transform] duration-200 enabled:hover:brightness-[--hover-brightness] enabled:focus-visible:brightness-[--hover-brightness] enabled:active:scale-95 disabled:cursor-not-allowed disabled:opacity-50 [&>svg]:size-5 [&>svg]:shrink-0"
|
||||
:disabled="!selectedSkin"
|
||||
:disabled="!selectedSkin || isSkinManagementReadOnly"
|
||||
@click="(e: MouseEvent) => selectedSkin && editSkinModal?.show(e, selectedSkin)"
|
||||
>
|
||||
<EditIcon />
|
||||
@@ -873,9 +1087,11 @@ await loadSkins()
|
||||
:is-skin-selected="isSkinSelected"
|
||||
:is-skin-active="isSkinActive"
|
||||
:is-add-skin-button-drag-active="isAddSkinButtonDragActive"
|
||||
:read-only="isSkinManagementReadOnly"
|
||||
@select="changeSkin"
|
||||
@edit="(skin, event) => editSkinModal?.show(event, skin)"
|
||||
@delete="confirmDeleteSkin"
|
||||
@reorder-saved-skins="reorderSavedSkins"
|
||||
@add-skin="openAddSkinFileBrowser"
|
||||
@add-skin-dragenter="onAddSkinDragOver"
|
||||
@add-skin-dragover="onAddSkinDragOver"
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
injectModrinthClient,
|
||||
injectModrinthServerContext,
|
||||
ServersManageAccessPage,
|
||||
} from '@modrinth/ui'
|
||||
import { useQueryClient } from '@tanstack/vue-query'
|
||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
|
||||
const client = injectModrinthClient()
|
||||
const { serverId } = injectModrinthServerContext()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
queryClient.ensureQueryData({
|
||||
queryKey: ['servers', 'users', 'v1', serverId],
|
||||
queryFn: () => client.archon.server_users_v1.list(serverId),
|
||||
staleTime: 30_000,
|
||||
}),
|
||||
queryClient.ensureQueryData({
|
||||
queryKey: ['servers', 'v1', 'detail', serverId],
|
||||
queryFn: () => client.archon.servers_v1.get(serverId),
|
||||
staleTime: 30_000,
|
||||
}),
|
||||
])
|
||||
} catch {
|
||||
// Let mounted layouts' useQuery surface errors; do not fail route setup.
|
||||
}
|
||||
|
||||
function userProfileLink(username: string) {
|
||||
return () => openUrl(`https://modrinth.com/user/${encodeURIComponent(username)}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ServersManageAccessPage :user-profile-link="userProfileLink" />
|
||||
</template>
|
||||
@@ -1,7 +1,8 @@
|
||||
import Access from './Access.vue'
|
||||
import Backups from './Backups.vue'
|
||||
import Content from './Content.vue'
|
||||
import Files from './Files.vue'
|
||||
import Index from './Index.vue'
|
||||
import Overview from './Overview.vue'
|
||||
|
||||
export { Backups, Content, Files, Index, Overview }
|
||||
export { Access, Backups, Content, Files, Index, Overview }
|
||||
|
||||
@@ -32,14 +32,16 @@
|
||||
{{ instance.loader }} {{ instance.game_version }}
|
||||
</div>
|
||||
|
||||
<div class="w-1.5 h-1.5 rounded-full bg-surface-5"></div>
|
||||
<template v-if="showInstancePlayTime">
|
||||
<div class="w-1.5 h-1.5 rounded-full bg-surface-5"></div>
|
||||
|
||||
<div class="flex items-center gap-2 font-medium">
|
||||
<template v-if="timePlayed > 0">
|
||||
{{ timePlayedHumanized }}
|
||||
</template>
|
||||
<template v-else> Never played </template>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 font-medium">
|
||||
<template v-if="timePlayed > 0">
|
||||
{{ timePlayedHumanized }}
|
||||
</template>
|
||||
<template v-else> Never played </template>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
@@ -326,7 +328,7 @@ import { showProfileInFolder } from '@/helpers/utils.js'
|
||||
import { get_server_status, refreshWorlds } from '@/helpers/worlds'
|
||||
import { injectServerInstall } from '@/providers/server-install'
|
||||
import { handleSevereError } from '@/store/error.js'
|
||||
import { useBreadcrumbs } from '@/store/state'
|
||||
import { useBreadcrumbs, useTheming } from '@/store/state'
|
||||
|
||||
dayjs.extend(duration)
|
||||
dayjs.extend(relativeTime)
|
||||
@@ -338,6 +340,8 @@ const route = useRoute()
|
||||
|
||||
const router = useRouter()
|
||||
const breadcrumbs = useBreadcrumbs()
|
||||
const themeStore = useTheming()
|
||||
const showInstancePlayTime = computed(() => themeStore.getFeatureFlag('show_instance_play_time'))
|
||||
const contentSubpageRouteNames = new Set(['Mods', 'ModsFilter'])
|
||||
|
||||
const offline = ref(!navigator.onLine)
|
||||
|
||||
@@ -99,7 +99,7 @@ import { useRouter } from 'vue-router'
|
||||
import ExportModal from '@/components/ui/ExportModal.vue'
|
||||
import ShareModalWrapper from '@/components/ui/modal/ShareModalWrapper.vue'
|
||||
import { trackEvent } from '@/helpers/analytics'
|
||||
import { get_project_versions, get_version } from '@/helpers/cache.js'
|
||||
import { get_project_versions, get_version, get_version_many } from '@/helpers/cache.js'
|
||||
import { profile_listener } from '@/helpers/events.js'
|
||||
import { type InstanceContentData, loadInstanceContentData } from '@/helpers/instance-content'
|
||||
import {
|
||||
@@ -297,6 +297,58 @@ function isActiveUpdateRequest(requestId: number) {
|
||||
return activeUpdateRequestId.value === requestId
|
||||
}
|
||||
|
||||
function sortVersionsByPublishedDate(versions: Labrinth.Versions.v2.Version[]) {
|
||||
return [...versions].sort(
|
||||
(a, b) => new Date(b.date_published).getTime() - new Date(a.date_published).getTime(),
|
||||
)
|
||||
}
|
||||
|
||||
function mergeVersionIntoList(
|
||||
versions: Labrinth.Versions.v2.Version[],
|
||||
version: Labrinth.Versions.v2.Version,
|
||||
) {
|
||||
const existingIndex = versions.findIndex((v) => v.id === version.id)
|
||||
if (existingIndex === -1) {
|
||||
return sortVersionsByPublishedDate([version, ...versions])
|
||||
}
|
||||
|
||||
const mergedVersions = [...versions]
|
||||
mergedVersions[existingIndex] = version
|
||||
return sortVersionsByPublishedDate(mergedVersions)
|
||||
}
|
||||
|
||||
async function getUpdaterProjectVersions(projectId: string, pinnedVersionId?: string) {
|
||||
let fetchError: unknown = null
|
||||
let versions = (await get_project_versions(projectId, 'bypass').catch((err) => {
|
||||
fetchError = err
|
||||
return null
|
||||
})) as Labrinth.Versions.v2.Version[] | null
|
||||
|
||||
if (!versions) {
|
||||
versions = (await get_project_versions(projectId).catch(() => null)) as
|
||||
| Labrinth.Versions.v2.Version[]
|
||||
| null
|
||||
}
|
||||
|
||||
if (!versions && fetchError) {
|
||||
handleError(fetchError as Error)
|
||||
}
|
||||
|
||||
let mergedVersions = sortVersionsByPublishedDate(versions ?? [])
|
||||
|
||||
if (pinnedVersionId && !mergedVersions.some((version) => version.id === pinnedVersionId)) {
|
||||
const pinnedVersion = (await get_version(pinnedVersionId, 'bypass').catch(
|
||||
() => null,
|
||||
)) as Labrinth.Versions.v2.Version | null
|
||||
|
||||
if (pinnedVersion) {
|
||||
mergedVersions = mergeVersionIntoList(mergedVersions, pinnedVersion)
|
||||
}
|
||||
}
|
||||
|
||||
return mergedVersions
|
||||
}
|
||||
|
||||
async function handleBrowseContent() {
|
||||
if (!props.instance) return
|
||||
await router.push({
|
||||
@@ -399,6 +451,63 @@ async function removeMod(mod: ContentItem) {
|
||||
}
|
||||
}
|
||||
|
||||
function isBreakingDependency(dependency: Labrinth.Versions.v2.Dependency) {
|
||||
return dependency.dependency_type === 'required' || dependency.dependency_type === 'embedded'
|
||||
}
|
||||
|
||||
function dependencyTargetsItem(dependency: Labrinth.Versions.v2.Dependency, item: ContentItem) {
|
||||
return (
|
||||
(!!dependency.project_id && dependency.project_id === item.project?.id) ||
|
||||
('version_id' in dependency &&
|
||||
!!dependency.version_id &&
|
||||
dependency.version_id === item.version?.id)
|
||||
)
|
||||
}
|
||||
|
||||
async function getDeleteDependencyWarning(items: ContentItem[]) {
|
||||
if (props.isServerInstance) return null
|
||||
|
||||
const deletingIds = new Set(items.map(getContentItemId))
|
||||
const remainingItems = projects.value.filter((item) => !deletingIds.has(getContentItemId(item)))
|
||||
const versionIds = [
|
||||
...new Set(remainingItems.map((item) => item.version?.id).filter((id): id is string => !!id)),
|
||||
]
|
||||
|
||||
if (versionIds.length === 0) return null
|
||||
|
||||
const versions = (await get_version_many(versionIds).catch((err) => {
|
||||
handleError(err as Error)
|
||||
return null
|
||||
})) as Labrinth.Versions.v2.Version[] | null
|
||||
|
||||
if (!versions) return null
|
||||
|
||||
const versionsById = new Map(versions.map((version) => [version.id, version]))
|
||||
|
||||
const dependents = remainingItems
|
||||
.map((candidate) => {
|
||||
const version = candidate.version?.id ? versionsById.get(candidate.version.id) : null
|
||||
if (!version) return null
|
||||
|
||||
const dependencies = items.filter((item) => {
|
||||
if (!item.project?.id && !item.version?.id) return false
|
||||
|
||||
return version.dependencies?.some(
|
||||
(dependency) =>
|
||||
isBreakingDependency(dependency) && dependencyTargetsItem(dependency, item),
|
||||
)
|
||||
})
|
||||
|
||||
return dependencies.length > 0 ? { item: candidate, dependencies } : null
|
||||
})
|
||||
.filter(
|
||||
(dependent): dependent is { item: ContentItem; dependencies: ContentItem[] } =>
|
||||
dependent !== null,
|
||||
)
|
||||
|
||||
return dependents.length > 0 ? { items, dependents } : null
|
||||
}
|
||||
|
||||
async function updateProject(mod: ContentItem) {
|
||||
if (!mod.file_path) return
|
||||
const operation = beginContentOperation(mod)
|
||||
@@ -429,6 +538,7 @@ async function updateProject(mod: ContentItem) {
|
||||
})
|
||||
} catch (err) {
|
||||
handleError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
await refreshContentState('must_revalidate')
|
||||
finishContentOperation(mod, operation)
|
||||
@@ -543,16 +653,14 @@ async function handleUpdate(id: string) {
|
||||
})
|
||||
contentUpdaterModal.value?.show(initialVersionId)
|
||||
|
||||
const versions = (await get_project_versions(item.project.id).catch((e) => {
|
||||
return handleError(e)
|
||||
})) as Labrinth.Versions.v2.Version[] | null
|
||||
const versions = await getUpdaterProjectVersions(item.project.id, initialVersionId)
|
||||
|
||||
if (!isActiveUpdateRequest(requestId) || getContentItemId(updatingProject.value) !== itemId)
|
||||
return
|
||||
|
||||
loadingVersions.value = false
|
||||
|
||||
if (!versions) {
|
||||
if (versions.length === 0) {
|
||||
debug('handleUpdate: no versions returned', { projectId: item.project.id })
|
||||
return
|
||||
}
|
||||
@@ -571,9 +679,6 @@ async function handleUpdate(id: string) {
|
||||
updateVersionInList: versions.some((v) => v.id === item.update_version_id),
|
||||
})
|
||||
|
||||
versions.sort(
|
||||
(a, b) => new Date(b.date_published).getTime() - new Date(a.date_published).getTime(),
|
||||
)
|
||||
const preselectedVersion =
|
||||
versions.find((version) => version.id === initialVersionId) ?? versions[0] ?? null
|
||||
debug('handleUpdate: resolved content updater preselection', {
|
||||
@@ -611,23 +716,16 @@ async function handleSwitchVersion(item: ContentItem) {
|
||||
|
||||
await nextTick()
|
||||
|
||||
contentUpdaterModal.value?.show(item.version.id, { switchMode: true })
|
||||
const initialVersionId = item.version.id
|
||||
contentUpdaterModal.value?.show(initialVersionId, { switchMode: true })
|
||||
|
||||
const versions = (await get_project_versions(item.project.id).catch((e) => {
|
||||
return handleError(e)
|
||||
})) as Labrinth.Versions.v2.Version[] | null
|
||||
const versions = await getUpdaterProjectVersions(item.project.id, initialVersionId)
|
||||
|
||||
if (!isActiveUpdateRequest(requestId) || getContentItemId(updatingProject.value) !== itemId)
|
||||
return
|
||||
|
||||
loadingVersions.value = false
|
||||
|
||||
if (!versions) return
|
||||
|
||||
versions.sort(
|
||||
(a, b) => new Date(b.date_published).getTime() - new Date(a.date_published).getTime(),
|
||||
)
|
||||
|
||||
updatingProjectVersions.value = versions
|
||||
}
|
||||
|
||||
@@ -713,19 +811,17 @@ async function handleModpackUpdate() {
|
||||
})
|
||||
contentUpdaterModal.value?.show(initialVersionId)
|
||||
|
||||
const versions = (await get_project_versions(props.instance.linked_data.project_id).catch(
|
||||
handleError,
|
||||
)) as Labrinth.Versions.v2.Version[] | null
|
||||
const versions = await getUpdaterProjectVersions(
|
||||
props.instance.linked_data.project_id,
|
||||
initialVersionId,
|
||||
)
|
||||
|
||||
if (!isActiveUpdateRequest(requestId) || !updatingModpack.value) return
|
||||
|
||||
loadingVersions.value = false
|
||||
|
||||
if (!versions) return
|
||||
if (versions.length === 0) return
|
||||
|
||||
versions.sort(
|
||||
(a, b) => new Date(b.date_published).getTime() - new Date(a.date_published).getTime(),
|
||||
)
|
||||
const preselectedVersion =
|
||||
versions.find((version) => version.id === initialVersionId) ?? versions[0] ?? null
|
||||
debug('handleModpackUpdate: resolved modpack updater preselection', {
|
||||
@@ -760,12 +856,7 @@ async function fetchAndSpliceVersion(
|
||||
)) as Labrinth.Versions.v2.Version | null
|
||||
if (!isActiveUpdateRequest(requestId)) return
|
||||
if (!fullVersion) return
|
||||
const index = updatingProjectVersions.value.findIndex((v) => v.id === versionId)
|
||||
if (index !== -1) {
|
||||
const newVersions = [...updatingProjectVersions.value]
|
||||
newVersions[index] = fullVersion
|
||||
updatingProjectVersions.value = newVersions
|
||||
}
|
||||
updatingProjectVersions.value = mergeVersionIntoList(updatingProjectVersions.value, fullVersion)
|
||||
}
|
||||
|
||||
async function handleVersionSelect(version: Labrinth.Versions.v2.Version) {
|
||||
@@ -852,13 +943,15 @@ async function handleModalUpdate(
|
||||
} else if (updatingProject.value) {
|
||||
const mod = updatingProject.value
|
||||
|
||||
if (mod.has_update && mod.update_version_id === selectedVersion.id) {
|
||||
await updateProject(mod)
|
||||
} else {
|
||||
await switchProjectVersion(mod, selectedVersion)
|
||||
try {
|
||||
if (mod.has_update && mod.update_version_id === selectedVersion.id) {
|
||||
await updateProject(mod)
|
||||
} else {
|
||||
await switchProjectVersion(mod, selectedVersion)
|
||||
}
|
||||
} finally {
|
||||
resetUpdateState()
|
||||
}
|
||||
|
||||
resetUpdateState()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1048,6 +1141,7 @@ provideContentManager({
|
||||
deleteItem: removeMod,
|
||||
bulkDeleteItems: (items: ContentItem[]) =>
|
||||
Promise.all(items.map((item) => removeMod(item))).then(() => {}),
|
||||
getDeleteDependencyWarning,
|
||||
refresh: () => initProjects('must_revalidate'),
|
||||
browse: handleBrowseContent,
|
||||
uploadFiles: handleUploadFiles,
|
||||
@@ -1194,6 +1288,15 @@ watch(
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.instance?.preferred_update_channel,
|
||||
async (newValue, oldValue) => {
|
||||
if (newValue !== oldValue) {
|
||||
await initProjects('must_revalidate')
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
onUnmounted(() => {
|
||||
isUnmounted = true
|
||||
removeBeforeEach()
|
||||
|
||||
@@ -406,6 +406,20 @@ function buildProjectHref(path, extraQuery = {}) {
|
||||
return qs ? `${path}?${qs}` : path
|
||||
}
|
||||
|
||||
function buildBrowseHref(path) {
|
||||
const params = new URLSearchParams()
|
||||
for (const [key, val] of Object.entries(route.query)) {
|
||||
if (key === 'b') continue
|
||||
if (Array.isArray(val)) {
|
||||
for (const v of val) params.append(key, v)
|
||||
} else if (val) {
|
||||
params.append(key, String(val))
|
||||
}
|
||||
}
|
||||
const qs = params.toString()
|
||||
return qs ? `${path}?${qs}` : path
|
||||
}
|
||||
|
||||
const projectDescriptionHref = computed(() => buildProjectHref(`/project/${route.params.id}`))
|
||||
const versionsHref = computed(() =>
|
||||
buildProjectHref(`/project/${route.params.id}/versions`, instanceFilters.value),
|
||||
@@ -416,7 +430,7 @@ const projectBrowseBackUrl = computed(() => {
|
||||
const browsePath = route.query.b
|
||||
if (typeof browsePath === 'string' && browsePath.startsWith('/browse/')) return browsePath
|
||||
const type = data.value?.project_type ? `${data.value.project_type}` : 'mod'
|
||||
return `/browse/${type}`
|
||||
return buildBrowseHref(`/browse/${type}`)
|
||||
})
|
||||
|
||||
const projectInstallContext = computed(() => {
|
||||
@@ -725,10 +739,11 @@ async function install(version) {
|
||||
version,
|
||||
instance.value ? instance.value.path : null,
|
||||
'ProjectPage',
|
||||
(version) => {
|
||||
(version, installedProjectIds) => {
|
||||
installing.value = false
|
||||
|
||||
if (instance.value && version) {
|
||||
const installedIds = installedProjectIds ?? [data.value.id]
|
||||
if (instance.value && version && installedIds.includes(data.value.id)) {
|
||||
installed.value = true
|
||||
installedVersion.value = version
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
:current-title="version.name"
|
||||
:link-stack="[
|
||||
{
|
||||
href: `/project/${route.params.id}/versions`,
|
||||
href: buildProjectHref(`/project/${route.params.id}/versions`),
|
||||
label: 'Versions',
|
||||
},
|
||||
]"
|
||||
@@ -249,6 +249,19 @@ const author = computed(() =>
|
||||
|
||||
const displayDependencies = ref({})
|
||||
|
||||
function buildProjectHref(path) {
|
||||
const params = new URLSearchParams()
|
||||
for (const [key, val] of Object.entries(route.query)) {
|
||||
if (Array.isArray(val)) {
|
||||
for (const v of val) params.append(key, v)
|
||||
} else if (val) {
|
||||
params.append(key, String(val))
|
||||
}
|
||||
}
|
||||
const qs = params.toString()
|
||||
return qs ? `${path}?${qs}` : path
|
||||
}
|
||||
|
||||
async function refreshDisplayDependencies() {
|
||||
const projectIds = new Set()
|
||||
const versionIds = new Set()
|
||||
@@ -282,7 +295,7 @@ async function refreshDisplayDependencies() {
|
||||
icon: project?.icon_url,
|
||||
title: project?.title || project?.name,
|
||||
subtitle: `Version ${version.version_number} is ${dependency.dependency_type}`,
|
||||
link: `/project/${project.slug}/version/${version.id}`,
|
||||
link: buildProjectHref(`/project/${project.slug}/version/${version.id}`),
|
||||
}
|
||||
} else {
|
||||
const project = dependencies.projects.find((obj) => obj.id === dependency.project_id)
|
||||
@@ -292,7 +305,7 @@ async function refreshDisplayDependencies() {
|
||||
icon: project?.icon_url,
|
||||
title: project?.title || project?.name,
|
||||
subtitle: `${dependency.dependency_type}`,
|
||||
link: `/project/${project.slug}`,
|
||||
link: buildProjectHref(`/project/${project.slug}`),
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
:game-versions="gameVersions"
|
||||
:versions="versions"
|
||||
:project="project"
|
||||
:version-link="(version) => `/project/${project.id}/version/${version.id}`"
|
||||
:version-link="(version) => buildProjectHref(`/project/${project.id}/version/${version.id}`)"
|
||||
>
|
||||
<template #actions="{ version }">
|
||||
<ButtonStyled circular type="transparent">
|
||||
@@ -73,6 +73,7 @@ import {
|
||||
ProjectPageVersions,
|
||||
} from '@modrinth/ui'
|
||||
import { ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { SwapIcon } from '@/assets/icons/index.js'
|
||||
import { get_game_versions, get_loaders } from '@/helpers/tags.js'
|
||||
@@ -109,6 +110,20 @@ defineProps({
|
||||
})
|
||||
|
||||
const { handleError } = injectNotificationManager()
|
||||
const route = useRoute()
|
||||
|
||||
function buildProjectHref(path) {
|
||||
const params = new URLSearchParams()
|
||||
for (const [key, val] of Object.entries(route.query)) {
|
||||
if (Array.isArray(val)) {
|
||||
for (const v of val) params.append(key, v)
|
||||
} else if (val) {
|
||||
params.append(key, String(val))
|
||||
}
|
||||
}
|
||||
const qs = params.toString()
|
||||
return qs ? `${path}?${qs}` : path
|
||||
}
|
||||
|
||||
const [loaders, gameVersions] = await Promise.all([
|
||||
get_loaders().catch(handleError).then(ref),
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
export const APP_UPDATE_POPUP_DELAY_MS = 24 * 60 * 60 * 1000
|
||||
|
||||
const UPDATE_PROMPT_STORAGE_KEY = 'modrinth-app-update-prompt-state'
|
||||
|
||||
export interface AppUpdate {
|
||||
rid: number
|
||||
version: string
|
||||
currentVersion?: string
|
||||
}
|
||||
|
||||
interface UpdatePromptState {
|
||||
version: string
|
||||
stage: AppUpdatePromptStage
|
||||
actionableSince: number
|
||||
lastUserActionAt?: number
|
||||
popupShownAt?: number
|
||||
}
|
||||
|
||||
export type AppUpdatePromptStage = 'available' | 'downloaded'
|
||||
|
||||
interface AppUpdateActions {
|
||||
download?: () => Promise<void> | void
|
||||
install?: () => Promise<void> | void
|
||||
changelog?: () => Promise<void> | void
|
||||
}
|
||||
|
||||
const progress = ref(0)
|
||||
const metered = ref(true)
|
||||
const finishedDownloading = ref(false)
|
||||
const downloading = ref(false)
|
||||
const restarting = ref(false)
|
||||
const availableUpdate = ref<AppUpdate | null>(null)
|
||||
const updateSize = ref<number | null>(null)
|
||||
const updatesEnabled = ref(true)
|
||||
|
||||
let actions: AppUpdateActions = {}
|
||||
|
||||
function getCurrentAppUpdatePromptStage(): AppUpdatePromptStage {
|
||||
return finishedDownloading.value ? 'downloaded' : 'available'
|
||||
}
|
||||
|
||||
export const appUpdateState = {
|
||||
progress,
|
||||
metered,
|
||||
finishedDownloading,
|
||||
downloading,
|
||||
restarting,
|
||||
availableUpdate,
|
||||
updateSize,
|
||||
updatesEnabled,
|
||||
downloadProgress: computed(() => progress.value),
|
||||
downloadPercent: computed(() => Math.trunc(progress.value * 100)),
|
||||
isVisible: computed(() => !!availableUpdate.value && !restarting.value && updatesEnabled.value),
|
||||
}
|
||||
|
||||
function readPromptState(): UpdatePromptState | null {
|
||||
try {
|
||||
const raw = localStorage.getItem(UPDATE_PROMPT_STORAGE_KEY)
|
||||
if (!raw) {
|
||||
return null
|
||||
}
|
||||
|
||||
const parsed = JSON.parse(raw) as Partial<UpdatePromptState>
|
||||
if (!parsed.version || typeof parsed.actionableSince !== 'number') {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
...parsed,
|
||||
stage: parsed.stage ?? 'available',
|
||||
} as UpdatePromptState
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function writePromptState(state: UpdatePromptState): void {
|
||||
try {
|
||||
localStorage.setItem(UPDATE_PROMPT_STORAGE_KEY, JSON.stringify(state))
|
||||
} catch (error) {
|
||||
console.warn('Failed to persist update prompt state:', error)
|
||||
}
|
||||
}
|
||||
|
||||
export function markAppUpdateActionable(
|
||||
version: string,
|
||||
stage: AppUpdatePromptStage = 'available',
|
||||
now = Date.now(),
|
||||
): void {
|
||||
const existing = readPromptState()
|
||||
if (existing?.version === version && existing.stage === stage) {
|
||||
return
|
||||
}
|
||||
|
||||
writePromptState({
|
||||
version,
|
||||
stage,
|
||||
actionableSince: now,
|
||||
})
|
||||
}
|
||||
|
||||
export function recordAppUpdateUserAction(
|
||||
version = availableUpdate.value?.version,
|
||||
stage: AppUpdatePromptStage = getCurrentAppUpdatePromptStage(),
|
||||
): void {
|
||||
if (!version) {
|
||||
return
|
||||
}
|
||||
|
||||
const now = Date.now()
|
||||
const existing = readPromptState()
|
||||
const isSamePrompt = existing?.version === version && existing.stage === stage
|
||||
writePromptState({
|
||||
version,
|
||||
stage,
|
||||
actionableSince: isSamePrompt ? existing.actionableSince : now,
|
||||
lastUserActionAt: now,
|
||||
popupShownAt: isSamePrompt ? existing.popupShownAt : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
export function markAppUpdatePopupShown(
|
||||
version: string,
|
||||
stage: AppUpdatePromptStage = 'available',
|
||||
now = Date.now(),
|
||||
): void {
|
||||
const existing = readPromptState()
|
||||
const isSamePrompt = existing?.version === version && existing.stage === stage
|
||||
writePromptState({
|
||||
version,
|
||||
stage,
|
||||
actionableSince: isSamePrompt ? existing.actionableSince : now,
|
||||
lastUserActionAt: isSamePrompt ? existing.lastUserActionAt : undefined,
|
||||
popupShownAt: now,
|
||||
})
|
||||
}
|
||||
|
||||
export function getNextAppUpdatePopupTime(
|
||||
version: string,
|
||||
stage: AppUpdatePromptStage = 'available',
|
||||
): number | null {
|
||||
const existing = readPromptState()
|
||||
if (existing?.version !== version || existing.stage !== stage || existing.popupShownAt) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
Math.max(existing.actionableSince, existing.lastUserActionAt ?? 0) + APP_UPDATE_POPUP_DELAY_MS
|
||||
)
|
||||
}
|
||||
|
||||
export function setAppUpdateActions(nextActions: AppUpdateActions): void {
|
||||
actions = nextActions
|
||||
}
|
||||
|
||||
export async function downloadAvailableAppUpdate(): Promise<void> {
|
||||
recordAppUpdateUserAction(undefined, 'available')
|
||||
await actions.download?.()
|
||||
}
|
||||
|
||||
export async function installAvailableAppUpdate(): Promise<void> {
|
||||
recordAppUpdateUserAction(undefined, 'downloaded')
|
||||
await actions.install?.()
|
||||
}
|
||||
|
||||
export async function openAppUpdateChangelog(): Promise<void> {
|
||||
recordAppUpdateUserAction()
|
||||
await actions.changelog?.()
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import type { ContentInstallInstance, ContentInstallProjectInfo, ContentItem } from '@modrinth/ui'
|
||||
import { createContext } from '@modrinth/ui'
|
||||
import { createContext, defineMessage, useVIntl } from '@modrinth/ui'
|
||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
import dayjs from 'dayjs'
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
} from '@/store/install.js'
|
||||
|
||||
interface ModalRef {
|
||||
show: () => void
|
||||
show: (initialVersionId?: string) => void
|
||||
hide: () => void
|
||||
}
|
||||
|
||||
@@ -42,19 +42,16 @@ interface ModpackAlreadyInstalledModalRef {
|
||||
show: (instanceName: string, instancePath: string) => void
|
||||
}
|
||||
|
||||
interface IncompatibilityWarningModalRef {
|
||||
show: (
|
||||
instance: GameInstance,
|
||||
project: Labrinth.Projects.v2.Project,
|
||||
versions: Labrinth.Versions.v2.Version[],
|
||||
version: Labrinth.Versions.v2.Version,
|
||||
callback: (versionId?: string) => void,
|
||||
) => void
|
||||
}
|
||||
export type ContentInstallCallback = (versionId?: string, installedProjectIds?: string[]) => void
|
||||
|
||||
const LOADER_ORDER = ['vanilla', 'fabric', 'quilt', 'neoforge', 'forge']
|
||||
const SUPPORTED_LOADERS: Set<string> = new Set(['vanilla', 'forge', 'fabric', 'quilt', 'neoforge'])
|
||||
const VANILLA_COMPATIBLE_LOADERS: Set<string> = new Set(['minecraft', 'datapack'])
|
||||
const noCompatibleVersionsMessage = defineMessage({
|
||||
id: 'app.content-install.no-compatible-versions',
|
||||
defaultMessage:
|
||||
'No available versions match {compatibilityLabel}. Select a version to install anyway. Dependencies will not be installed automatically.',
|
||||
})
|
||||
|
||||
function sortLoaders(loaders: string[]): string[] {
|
||||
return loaders.slice().sort((a, b) => {
|
||||
@@ -91,13 +88,23 @@ export interface ContentInstallContext {
|
||||
setModpackAlreadyInstalledModal: (ref: ModpackAlreadyInstalledModalRef) => void
|
||||
handleModpackDuplicateCreateAnyway: () => Promise<void>
|
||||
handleModpackDuplicateGoToInstance: (instancePath: string) => void
|
||||
setIncompatibilityWarningModal: (ref: IncompatibilityWarningModalRef) => void
|
||||
setIncompatibilityWarningModal: (ref: ModalRef) => void
|
||||
incompatibilityWarningVersions: Ref<Labrinth.Versions.v2.Version[]>
|
||||
incompatibilityWarningCurrentGameVersion: Ref<string>
|
||||
incompatibilityWarningCurrentLoader: Ref<string>
|
||||
incompatibilityWarningProjectType: Ref<string | undefined>
|
||||
incompatibilityWarningProjectIconUrl: Ref<string | undefined>
|
||||
incompatibilityWarningProjectName: Ref<string | undefined>
|
||||
incompatibilityWarningMessage: Ref<string | undefined>
|
||||
incompatibilityWarningInstalling: Ref<boolean>
|
||||
handleIncompatibilityWarningInstall: (version: Labrinth.Versions.v2.Version) => Promise<void>
|
||||
handleIncompatibilityWarningCancel: () => void
|
||||
install: (
|
||||
projectId: string,
|
||||
versionId?: string | null,
|
||||
instancePath?: string | null,
|
||||
source?: string,
|
||||
callback?: (versionId?: string) => void,
|
||||
callback?: ContentInstallCallback,
|
||||
createInstanceCallback?: (profile: string) => void,
|
||||
hints?: { preferredLoader?: string; preferredGameVersion?: string; showProjectInfo?: boolean },
|
||||
) => Promise<void>
|
||||
@@ -113,6 +120,7 @@ export function createContentInstall(opts: {
|
||||
router: Router
|
||||
handleError: (err: unknown) => void
|
||||
}): ContentInstallContext {
|
||||
const { formatMessage } = useVIntl()
|
||||
const instances = ref<ContentInstallInstance[]>([])
|
||||
const compatibleLoaders = ref<string[]>([])
|
||||
const gameVersions = ref<string[]>([])
|
||||
@@ -124,6 +132,14 @@ export function createContentInstall(opts: {
|
||||
|
||||
const projectInfo = ref<ContentInstallProjectInfo | null>(null)
|
||||
const installingItems = ref<Map<string, ContentItem[]>>(new Map())
|
||||
const incompatibilityWarningVersions = ref<Labrinth.Versions.v2.Version[]>([])
|
||||
const incompatibilityWarningCurrentGameVersion = ref('')
|
||||
const incompatibilityWarningCurrentLoader = ref('')
|
||||
const incompatibilityWarningProjectType = ref<string | undefined>(undefined)
|
||||
const incompatibilityWarningProjectIconUrl = ref<string | undefined>(undefined)
|
||||
const incompatibilityWarningProjectName = ref<string | undefined>(undefined)
|
||||
const incompatibilityWarningMessage = ref<string | undefined>(undefined)
|
||||
const incompatibilityWarningInstalling = ref(false)
|
||||
|
||||
function addInstallingItem(
|
||||
instancePath: string,
|
||||
@@ -239,24 +255,28 @@ export function createContentInstall(opts: {
|
||||
|
||||
let modalRef: ModalRef | null = null
|
||||
let modpackAlreadyInstalledModalRef: ModpackAlreadyInstalledModalRef | null = null
|
||||
let incompatibilityWarningModalRef: IncompatibilityWarningModalRef | null = null
|
||||
let incompatibilityWarningModalRef: ModalRef | null = null
|
||||
let currentProject: Labrinth.Projects.v2.Project | null = null
|
||||
let currentVersions: Labrinth.Versions.v2.Version[] = []
|
||||
let currentCallback: (versionId?: string) => void = () => {}
|
||||
let currentCallback: ContentInstallCallback = () => {}
|
||||
let profileMap: Record<string, GameInstance> = {}
|
||||
let incompatibilityWarningInstance: GameInstance | null = null
|
||||
let incompatibilityWarningProject: Labrinth.Projects.v2.Project | null = null
|
||||
let incompatibilityWarningCallback: ContentInstallCallback = () => {}
|
||||
let incompatibilityWarningInstalled = false
|
||||
|
||||
let pendingModpackInstall: {
|
||||
project: Labrinth.Projects.v2.Project
|
||||
version: string
|
||||
source: string
|
||||
callback: (versionId?: string) => void
|
||||
callback: ContentInstallCallback
|
||||
createInstanceCallback: (profile: string) => void
|
||||
} | null = null
|
||||
|
||||
async function showModInstallModal(
|
||||
project: Labrinth.Projects.v2.Project,
|
||||
versions: Labrinth.Versions.v2.Version[],
|
||||
onInstall: (versionId?: string) => void,
|
||||
onInstall: ContentInstallCallback,
|
||||
hints?: { preferredLoader?: string; preferredGameVersion?: string; showProjectInfo?: boolean },
|
||||
) {
|
||||
currentProject = project
|
||||
@@ -410,15 +430,35 @@ export function createContentInstall(opts: {
|
||||
async function handleInstallToInstance(instance: ContentInstallInstance) {
|
||||
const profile = profileMap[instance.id]
|
||||
const storeInstance = instances.value.find((i) => i.id === instance.id)
|
||||
if (storeInstance) storeInstance.installing = true
|
||||
if (!currentProject || !profile) {
|
||||
opts.handleError('No project or instance found')
|
||||
return
|
||||
}
|
||||
|
||||
const version = findPreferredVersion(currentVersions, currentProject, profile)
|
||||
if (!version) {
|
||||
if (storeInstance) storeInstance.installing = false
|
||||
opts.handleError('No compatible version found')
|
||||
if (currentVersions.length > 0 && incompatibilityWarningModalRef) {
|
||||
const onIncompatibleInstall = (versionId?: string) => {
|
||||
if (versionId && storeInstance) {
|
||||
storeInstance.installed = true
|
||||
}
|
||||
currentCallback(versionId, versionId && currentProject ? [currentProject.id] : undefined)
|
||||
}
|
||||
await showIncompatibilityWarning(
|
||||
profile,
|
||||
currentProject,
|
||||
currentVersions,
|
||||
currentVersions[0],
|
||||
onIncompatibleInstall,
|
||||
)
|
||||
} else {
|
||||
opts.handleError('No version found')
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (storeInstance) storeInstance.installing = true
|
||||
|
||||
const installedProjectIds: string[] = []
|
||||
if (currentProject) {
|
||||
addInstallingItem(instance.id, currentProject, version)
|
||||
@@ -449,7 +489,7 @@ export function createContentInstall(opts: {
|
||||
title: currentProject!.title,
|
||||
source: 'ProjectInstallModal',
|
||||
})
|
||||
currentCallback(version.id)
|
||||
currentCallback(version.id, installedProjectIds)
|
||||
} catch (err) {
|
||||
if (storeInstance) storeInstance.installing = false
|
||||
opts.handleError(err)
|
||||
@@ -458,6 +498,73 @@ export function createContentInstall(opts: {
|
||||
}
|
||||
}
|
||||
|
||||
async function showIncompatibilityWarning(
|
||||
instance: GameInstance,
|
||||
project: Labrinth.Projects.v2.Project,
|
||||
versions: Labrinth.Versions.v2.Version[],
|
||||
version: Labrinth.Versions.v2.Version,
|
||||
callback: ContentInstallCallback,
|
||||
) {
|
||||
incompatibilityWarningInstance = instance
|
||||
incompatibilityWarningProject = project
|
||||
incompatibilityWarningCallback = callback
|
||||
incompatibilityWarningInstalled = false
|
||||
incompatibilityWarningInstalling.value = false
|
||||
incompatibilityWarningVersions.value = versions
|
||||
incompatibilityWarningCurrentGameVersion.value = instance.game_version ?? ''
|
||||
incompatibilityWarningCurrentLoader.value = instance.loader ?? ''
|
||||
incompatibilityWarningProjectType.value = project.project_type
|
||||
incompatibilityWarningProjectIconUrl.value = project.icon_url ?? undefined
|
||||
incompatibilityWarningProjectName.value = project.title
|
||||
|
||||
const compatibilityLabel =
|
||||
project.project_type === 'resourcepack' || project.project_type === 'datapack'
|
||||
? (instance.game_version ?? '')
|
||||
: `${instance.loader ?? ''} ${instance.game_version ?? ''}`.trim()
|
||||
incompatibilityWarningMessage.value = formatMessage(noCompatibleVersionsMessage, {
|
||||
compatibilityLabel,
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
incompatibilityWarningModalRef?.show(version.id)
|
||||
trackEvent('ProjectInstallStart', { source: 'ProjectIncompatibilityWarningModal' })
|
||||
}
|
||||
|
||||
async function handleIncompatibilityWarningInstall(version: Labrinth.Versions.v2.Version) {
|
||||
if (!incompatibilityWarningInstance || !incompatibilityWarningProject) return
|
||||
|
||||
incompatibilityWarningInstalling.value = true
|
||||
try {
|
||||
await add_project_from_version(incompatibilityWarningInstance.path, version.id, 'standalone')
|
||||
} catch (err) {
|
||||
opts.handleError(err)
|
||||
incompatibilityWarningInstalling.value = false
|
||||
return
|
||||
}
|
||||
|
||||
incompatibilityWarningInstalling.value = false
|
||||
incompatibilityWarningInstalled = true
|
||||
incompatibilityWarningCallback(version.id, [incompatibilityWarningProject.id])
|
||||
incompatibilityWarningModalRef?.hide()
|
||||
|
||||
trackEvent('ProjectInstall', {
|
||||
loader: incompatibilityWarningInstance.loader,
|
||||
game_version: incompatibilityWarningInstance.game_version,
|
||||
id: incompatibilityWarningProject.id,
|
||||
version_id: version.id,
|
||||
project_type: incompatibilityWarningProject.project_type,
|
||||
title: incompatibilityWarningProject.title,
|
||||
source: 'ProjectIncompatibilityWarningModal',
|
||||
})
|
||||
}
|
||||
|
||||
function handleIncompatibilityWarningCancel() {
|
||||
if (!incompatibilityWarningInstalled) {
|
||||
incompatibilityWarningCallback()
|
||||
}
|
||||
incompatibilityWarningInstalled = false
|
||||
}
|
||||
|
||||
async function handleCreateAndInstall(data: {
|
||||
name: string
|
||||
iconPath: string | null
|
||||
@@ -525,7 +632,7 @@ export function createContentInstall(opts: {
|
||||
versionId?: string | null,
|
||||
instancePath?: string | null,
|
||||
source: string = 'unknown',
|
||||
callback: (versionId?: string) => void = () => {},
|
||||
callback: ContentInstallCallback = () => {},
|
||||
createInstanceCallback: (profile: string) => void = () => {},
|
||||
hints?: { preferredLoader?: string; preferredGameVersion?: string; showProjectInfo?: boolean },
|
||||
) {
|
||||
@@ -609,12 +716,12 @@ export function createContentInstall(opts: {
|
||||
title: project.title,
|
||||
source,
|
||||
})
|
||||
callback(version.id)
|
||||
callback(version.id, installedProjectIds)
|
||||
} finally {
|
||||
removeInstallingItems(instancePath, installedProjectIds)
|
||||
}
|
||||
} else {
|
||||
incompatibilityWarningModalRef?.show(instance, project, projectVersions, version, callback)
|
||||
await showIncompatibilityWarning(instance, project, projectVersions, version, callback)
|
||||
}
|
||||
} else {
|
||||
let versions = (
|
||||
@@ -668,9 +775,19 @@ export function createContentInstall(opts: {
|
||||
pendingModpackInstall = null
|
||||
opts.router.push(`/instance/${encodeURIComponent(instancePath)}`)
|
||||
},
|
||||
setIncompatibilityWarningModal(ref: IncompatibilityWarningModalRef) {
|
||||
setIncompatibilityWarningModal(ref: ModalRef) {
|
||||
incompatibilityWarningModalRef = ref
|
||||
},
|
||||
incompatibilityWarningVersions,
|
||||
incompatibilityWarningCurrentGameVersion,
|
||||
incompatibilityWarningCurrentLoader,
|
||||
incompatibilityWarningProjectType,
|
||||
incompatibilityWarningProjectIconUrl,
|
||||
incompatibilityWarningProjectName,
|
||||
incompatibilityWarningMessage,
|
||||
incompatibilityWarningInstalling,
|
||||
handleIncompatibilityWarningInstall,
|
||||
handleIncompatibilityWarningCancel,
|
||||
install,
|
||||
installingItems,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { AbstractPopupNotificationManager, AbstractWebNotificationManager } from '@modrinth/ui'
|
||||
|
||||
import { setupCreationModal } from './setup/creation-modal'
|
||||
import { setupFileDropProvider } from './setup/file-drop'
|
||||
import { setupFilePickerProvider } from './setup/file-picker'
|
||||
import { setupInstanceImportProvider } from './setup/instance-import'
|
||||
import { setupTagsProvider } from './setup/tags'
|
||||
@@ -10,6 +11,7 @@ export function setupProviders(
|
||||
popupNotificationManager: AbstractPopupNotificationManager,
|
||||
) {
|
||||
setupTagsProvider(notificationManager)
|
||||
setupFileDropProvider()
|
||||
setupFilePickerProvider()
|
||||
setupInstanceImportProvider(notificationManager)
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import { provideFileDrop } from '@modrinth/ui'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import type { DragDropEvent } from '@tauri-apps/api/webview'
|
||||
import { getCurrentWebview } from '@tauri-apps/api/webview'
|
||||
|
||||
function getFileName(path: string) {
|
||||
return path.split(/[\\/]/).pop() || 'file'
|
||||
}
|
||||
|
||||
function toLogicalPosition(position: { x: number; y: number }) {
|
||||
const scale = window.devicePixelRatio || 1
|
||||
return {
|
||||
x: position.x / scale,
|
||||
y: position.y / scale,
|
||||
}
|
||||
}
|
||||
|
||||
async function readDraggedFile(path: string) {
|
||||
const data = await invoke<number[]>('plugin:files|file_read_dragged_file', { path })
|
||||
return new Uint8Array(data)
|
||||
}
|
||||
|
||||
export function setupFileDropProvider() {
|
||||
let nativeFileDropPaths: string[] = []
|
||||
|
||||
provideFileDrop({
|
||||
async listenNativeFileDrop(handler) {
|
||||
return await getCurrentWebview().onDragDropEvent((event: { payload: DragDropEvent }) => {
|
||||
const payload = event.payload
|
||||
|
||||
if (payload.type === 'leave') {
|
||||
nativeFileDropPaths = []
|
||||
void handler({
|
||||
type: 'leave',
|
||||
paths: [],
|
||||
position: { x: 0, y: 0 },
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (payload.type === 'enter' || payload.type === 'drop') {
|
||||
nativeFileDropPaths = payload.paths
|
||||
}
|
||||
|
||||
void handler({
|
||||
type: payload.type,
|
||||
paths: nativeFileDropPaths,
|
||||
position: toLogicalPosition(payload.position),
|
||||
})
|
||||
|
||||
if (payload.type === 'drop') {
|
||||
nativeFileDropPaths = []
|
||||
}
|
||||
})
|
||||
},
|
||||
async createFilesFromNativePaths(paths) {
|
||||
return await Promise.all(
|
||||
paths.map(async (path) => new File([await readDraggedFile(path)], getFileName(path))),
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export function setupFilePickerProvider() {
|
||||
const file = await createFileFromPath(path, 'icon')
|
||||
return { file, path, previewUrl: convertFileSrc(path) }
|
||||
},
|
||||
async pickModpackFile() {
|
||||
async pickModpackFile(options) {
|
||||
const result = await open({
|
||||
multiple: false,
|
||||
filters: [{ name: 'Modpack', extensions: ['mrpack'] }],
|
||||
@@ -34,12 +34,19 @@ export function setupFilePickerProvider() {
|
||||
if (!result) return null
|
||||
const path = result.path ?? result
|
||||
if (!path) return null
|
||||
const file = await createFileFromPath(
|
||||
if (options?.readFile === false) {
|
||||
// Instance imports stream from the native path, keeping large packs out of JS memory.
|
||||
return { path, previewUrl: '' }
|
||||
}
|
||||
return {
|
||||
file: await createFileFromPath(
|
||||
path,
|
||||
'modpack.mrpack',
|
||||
'application/x-modrinth-modpack+zip',
|
||||
),
|
||||
path,
|
||||
'modpack.mrpack',
|
||||
'application/x-modrinth-modpack+zip',
|
||||
)
|
||||
return { file, path, previewUrl: '' }
|
||||
previewUrl: '',
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -73,6 +73,14 @@ export default new createRouter({
|
||||
breadcrumb: [{ name: '?Server' }],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'access',
|
||||
name: 'ServerManageAccess',
|
||||
component: Hosting.Access,
|
||||
meta: {
|
||||
breadcrumb: [{ name: '?Server' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -240,7 +248,6 @@ export default new createRouter({
|
||||
component: Instance.Logs,
|
||||
meta: {
|
||||
useRootContext: true,
|
||||
// renderMode: 'fixed',
|
||||
breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Logs' }],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
import { findMinecraftAuthError } from '@/components/ui/minecraft-auth-error-modal/minecraft-auth-errors'
|
||||
|
||||
export const useError = defineStore('errorsStore', {
|
||||
state: () => ({
|
||||
errorModal: null,
|
||||
@@ -15,7 +17,8 @@ export const useError = defineStore('errorsStore', {
|
||||
showError(error, context, closable = true, source = null) {
|
||||
if (
|
||||
error.message &&
|
||||
error.message.includes('Minecraft authentication error:') &&
|
||||
(error.message.includes('Minecraft authentication error:') ||
|
||||
findMinecraftAuthError(error.message)) &&
|
||||
this.minecraftAuthErrorModal
|
||||
) {
|
||||
this.minecraftAuthErrorModal.show(error)
|
||||
|
||||
@@ -71,7 +71,7 @@ export const installVersionDependencies = async (profile, version, reason, onDep
|
||||
return installed
|
||||
}
|
||||
|
||||
const queueInstall = async (projectId, resolvedVersion) => {
|
||||
const queueInstall = async (projectId, resolvedVersion, dependentOn) => {
|
||||
if (!resolvedVersion?.id) return false
|
||||
|
||||
const versionId = resolvedVersion.id
|
||||
@@ -91,7 +91,11 @@ export const installVersionDependencies = async (profile, version, reason, onDep
|
||||
if (resolvedProjectId) {
|
||||
queuedProjectVersions.set(resolvedProjectId, versionId)
|
||||
}
|
||||
queuedInstalls.push({ versionId, projectId: resolvedProjectId })
|
||||
queuedInstalls.push({
|
||||
versionId,
|
||||
projectId: resolvedProjectId,
|
||||
dependentOnVersionId: dependentOn?.id,
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -159,7 +163,7 @@ export const installVersionDependencies = async (profile, version, reason, onDep
|
||||
if (!resolved) continue
|
||||
|
||||
const { depVersion, depProjectId } = resolved
|
||||
const queued = await queueInstall(depProjectId, depVersion)
|
||||
const queued = await queueInstall(depProjectId, depVersion, inputVersion)
|
||||
if (queued && depProjectId) {
|
||||
await announceDependency(depProjectId, depVersion)
|
||||
}
|
||||
@@ -176,8 +180,8 @@ export const installVersionDependencies = async (profile, version, reason, onDep
|
||||
for (let i = 0; i < queuedInstalls.length; i += batchSize) {
|
||||
const batch = queuedInstalls.slice(i, i + batchSize)
|
||||
await Promise.all(
|
||||
batch.map(async ({ versionId }) => {
|
||||
await add_project_from_version(profile.path, versionId, reason)
|
||||
batch.map(async ({ versionId, dependentOnVersionId }) => {
|
||||
await add_project_from_version(profile.path, versionId, reason, dependentOnVersionId)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
let systemThemeMq: MediaQueryList | null = null
|
||||
|
||||
export const DEFAULT_FEATURE_FLAGS = {
|
||||
project_background: false,
|
||||
page_path: false,
|
||||
@@ -11,6 +13,7 @@ export const DEFAULT_FEATURE_FLAGS = {
|
||||
skip_unknown_pack_warning: false,
|
||||
pride_fundraiser: true,
|
||||
i18n_debug: false,
|
||||
show_instance_play_time: true,
|
||||
}
|
||||
|
||||
export const THEME_OPTIONS = ['dark', 'light', 'oled', 'system'] as const
|
||||
@@ -52,21 +55,22 @@ export const useTheming = defineStore('themeStore', {
|
||||
this.setThemeClass()
|
||||
},
|
||||
setThemeClass() {
|
||||
const html = document.getElementsByTagName('html')[0]
|
||||
for (const theme of THEME_OPTIONS) {
|
||||
document.getElementsByTagName('html')[0].classList.remove(`${theme}-mode`)
|
||||
html.classList.remove(`${theme}-mode`)
|
||||
}
|
||||
|
||||
systemThemeMq?.removeEventListener('change', this.setThemeClass)
|
||||
systemThemeMq = null
|
||||
|
||||
let theme = this.selectedTheme
|
||||
if (this.selectedTheme === 'system') {
|
||||
const darkThemeMq = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
if (darkThemeMq.matches) {
|
||||
theme = 'dark'
|
||||
} else {
|
||||
theme = 'light'
|
||||
}
|
||||
systemThemeMq = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
systemThemeMq.addEventListener('change', this.setThemeClass)
|
||||
theme = systemThemeMq.matches ? 'dark' : 'light'
|
||||
}
|
||||
|
||||
document.getElementsByTagName('html')[0].classList.add(`${theme}-mode`)
|
||||
html.classList.add(`${theme}-mode`)
|
||||
},
|
||||
getFeatureFlag(key: FeatureFlag) {
|
||||
return this.featureFlags[key] ?? DEFAULT_FEATURE_FLAGS[key]
|
||||
|
||||
+6
-1
@@ -117,6 +117,7 @@ fn main() {
|
||||
"equip_skin",
|
||||
"remove_custom_skin",
|
||||
"save_custom_skin",
|
||||
"set_custom_skin_order",
|
||||
"unequip_skin",
|
||||
"flush_pending_skin_change",
|
||||
"flush_pending_skin_change_for_profile",
|
||||
@@ -270,7 +271,11 @@ fn main() {
|
||||
.plugin(
|
||||
"files",
|
||||
InlinedPlugin::new()
|
||||
.commands(&["file_extract_zip", "file_save_as"])
|
||||
.commands(&[
|
||||
"file_extract_zip",
|
||||
"file_save_as",
|
||||
"file_read_dragged_file",
|
||||
])
|
||||
.default_permission(
|
||||
DefaultPermissionRule::AllowAllCommands,
|
||||
),
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
{
|
||||
"url": "https://api.purpurmc.org/*"
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:8000/*"
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:8000/*"
|
||||
},
|
||||
{
|
||||
"url": "http://*.taila228c5.ts.net/*"
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@ pub fn init<R: Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
file_extract_zip,
|
||||
file_save_as,
|
||||
file_read_dragged_file,
|
||||
])
|
||||
.build()
|
||||
}
|
||||
@@ -21,6 +22,19 @@ pub struct ExtractDryRunResult {
|
||||
conflicting_files: Vec<String>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn file_read_dragged_file(path: String) -> Result<Vec<u8>> {
|
||||
let metadata = tokio::fs::metadata(&path).await?;
|
||||
if !metadata.is_file() {
|
||||
return Err(theseus::Error::from(theseus::ErrorKind::OtherError(
|
||||
"Dropped path is not a file".to_string(),
|
||||
))
|
||||
.into());
|
||||
}
|
||||
|
||||
Ok(tokio::fs::read(path).await?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn file_extract_zip(
|
||||
instance_path: &str,
|
||||
|
||||
@@ -14,6 +14,7 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
||||
equip_skin,
|
||||
remove_custom_skin,
|
||||
save_custom_skin,
|
||||
set_custom_skin_order,
|
||||
unequip_skin,
|
||||
flush_pending_skin_change,
|
||||
flush_pending_skin_change_for_profile,
|
||||
@@ -91,6 +92,14 @@ pub async fn save_custom_skin(
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// `invoke('plugin:minecraft-skins|set_custom_skin_order', texture_keys)`
|
||||
///
|
||||
/// See also: [minecraft_skins::set_custom_skin_order]
|
||||
#[tauri::command]
|
||||
pub async fn set_custom_skin_order(texture_keys: Vec<String>) -> Result<()> {
|
||||
Ok(minecraft_skins::set_custom_skin_order(texture_keys).await?)
|
||||
}
|
||||
|
||||
/// `invoke('plugin:minecraft-skins|unequip_skin')`
|
||||
///
|
||||
/// See also: [minecraft_skins::unequip_skin]
|
||||
|
||||
@@ -251,8 +251,15 @@ pub async fn profile_add_project_from_version(
|
||||
path: &str,
|
||||
version_id: &str,
|
||||
reason: DownloadReason,
|
||||
dependent_on_version_id: Option<String>,
|
||||
) -> Result<String> {
|
||||
Ok(profile::add_project_from_version(path, version_id, reason).await?)
|
||||
Ok(profile::add_project_from_version(
|
||||
path,
|
||||
version_id,
|
||||
reason,
|
||||
dependent_on_version_id,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
// Adds a project to a profile from a path
|
||||
@@ -385,6 +392,7 @@ pub struct EditProfile {
|
||||
with = "serde_with::rust::double_option"
|
||||
)]
|
||||
pub linked_data: Option<Option<LinkedData>>,
|
||||
pub preferred_update_channel: Option<ReleaseChannel>,
|
||||
|
||||
#[serde(
|
||||
default,
|
||||
@@ -449,6 +457,11 @@ pub async fn profile_edit(path: &str, edit_profile: EditProfile) -> Result<()> {
|
||||
if let Some(linked_data) = edit_profile.linked_data.clone() {
|
||||
prof.linked_data = linked_data;
|
||||
}
|
||||
if let Some(preferred_update_channel) =
|
||||
edit_profile.preferred_update_channel
|
||||
{
|
||||
prof.preferred_update_channel = preferred_update_channel;
|
||||
}
|
||||
if let Some(groups) = edit_profile.groups.clone() {
|
||||
prof.groups = groups;
|
||||
}
|
||||
|
||||
@@ -307,6 +307,11 @@ fn main() {
|
||||
}
|
||||
|
||||
set_changelog_toast(Some(update.version.clone()));
|
||||
let update = if should_restart {
|
||||
(**update).clone()
|
||||
} else {
|
||||
(**update).clone().restart_after_install(false)
|
||||
};
|
||||
match update.install(data) {
|
||||
Ok(()) => {
|
||||
if should_restart {
|
||||
|
||||
@@ -31,7 +31,10 @@
|
||||
"plugins": {
|
||||
"updater": {
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDIwMzM5QkE0M0FCOERBMzkKUldRNTJyZzZwSnN6SUdPRGdZREtUUGxMblZqeG9OVHYxRUlRTzJBc2U3MUNJaDMvZDQ1UytZZmYK",
|
||||
"endpoints": ["https://launcher-files.modrinth.com/updates.json"]
|
||||
"endpoints": ["https://launcher-files.modrinth.com/updates.json"],
|
||||
"windows": {
|
||||
"installMode": "quiet"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,3 @@ These composables are deprecated and should not be used in new code:
|
||||
|
||||
- **`useAsyncData`** - we use tanstack, not nuxt's built in async data utility.
|
||||
- **`useBaseFetch`** (`src/composables/fetch.js`) — legacy Labrinth fetch wrapper. Use `client.labrinth.*` modules instead.
|
||||
- **`useServersFetch`** (`src/composables/servers/servers-fetch.ts`) — legacy Archon fetch wrapper with manual retry/circuit-breaker. Use `client.archon.*` modules instead — refer to the `packages/api-client/CLAUDE.md` for more information.
|
||||
|
||||
@@ -224,6 +224,7 @@ export default defineNuxtConfig({
|
||||
globalThis.INTERCOM_APP_ID ||
|
||||
'ykeritl9',
|
||||
production: isProduction(),
|
||||
cookieSecure: isProduction(),
|
||||
buildEnv: process.env.BUILD_ENV,
|
||||
preview: process.env.PREVIEW === 'true',
|
||||
featureFlagOverrides: getFeatureFlagOverrides(),
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"@types/semver": "^7.7.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"glob": "^10.2.7",
|
||||
"nuxt": "^3.20.2",
|
||||
"nuxt": "=3.20.2",
|
||||
"postcss": "^8.4.39",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"sass": "^1.58.0",
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@
|
||||
>
|
||||
<div
|
||||
v-if="showLegendTopFade"
|
||||
class="pointer-events-none absolute left-0 right-0 top-0 z-10 h-5 bg-gradient-to-b from-surface-3 to-transparent"
|
||||
class="z-1 pointer-events-none absolute left-0 right-0 top-0 h-5 bg-gradient-to-b from-surface-3 to-transparent"
|
||||
/>
|
||||
</Transition>
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
>
|
||||
<div
|
||||
v-if="showLegendBottomFade"
|
||||
class="pointer-events-none absolute bottom-0 left-0 right-0 z-10 h-5 bg-gradient-to-t from-surface-3 to-transparent"
|
||||
class="z-1 pointer-events-none absolute bottom-0 left-0 right-0 h-5 bg-gradient-to-t from-surface-3 to-transparent"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@
|
||||
:href="event.announcement_url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="mt-1.5 inline-flex items-center gap-1 text-sm font-medium text-primary underline !transition-all hover:text-contrast"
|
||||
class="my-0.5 inline-flex items-center gap-1 text-xs font-medium text-primary underline !transition-all hover:text-contrast"
|
||||
>
|
||||
{{ formatMessage(analyticsChartMessages.seeAnnouncement) }}
|
||||
<ExternalIcon class="size-3.5" aria-hidden="true" />
|
||||
|
||||
+8
-7
@@ -18,7 +18,7 @@
|
||||
({{ durationLabel }})
|
||||
</span>
|
||||
</span>
|
||||
<span v-if="previousRangeLabel" class="min-w-0 truncate text-xs text-primary">
|
||||
<span v-if="previousRangeLabel" class="min-w-0 space-x-1 truncate text-xs text-primary">
|
||||
<span class="font-medium">{{ previousRangeLabel }}</span>
|
||||
<span class="font-normal text-secondary">
|
||||
{{ formatMessage(analyticsChartMessages.previousPeriodShort) }}
|
||||
@@ -197,6 +197,7 @@ function getEntryAriaLabel(entry: AnalyticsChartTooltipEntry) {
|
||||
const ONE_DAY_MS = 24 * 60 * 60 * 1000
|
||||
const ONE_HOUR_MS = 60 * 60 * 1000
|
||||
const ONE_MINUTE_MS = 60 * 1000
|
||||
const DATE_LOCALE = 'en-US'
|
||||
|
||||
function formatRangeLabel(
|
||||
start: Date,
|
||||
@@ -225,13 +226,13 @@ function formatRangeLabel(
|
||||
}
|
||||
|
||||
if (includeTime) {
|
||||
const startLabel = new Intl.DateTimeFormat(undefined, startOptions).format(start)
|
||||
const endLabel = new Intl.DateTimeFormat(undefined, timeOptions).format(end)
|
||||
const startLabel = new Intl.DateTimeFormat(DATE_LOCALE, startOptions).format(start)
|
||||
const endLabel = new Intl.DateTimeFormat(DATE_LOCALE, timeOptions).format(end)
|
||||
const range = `${startLabel}–${endLabel}`
|
||||
|
||||
if (!showTrailingYear) return range
|
||||
|
||||
const yearLabel = new Intl.DateTimeFormat(undefined, { year: 'numeric' }).format(end)
|
||||
const yearLabel = new Intl.DateTimeFormat(DATE_LOCALE, { year: 'numeric' }).format(end)
|
||||
return `${range}, ${yearLabel}`
|
||||
}
|
||||
|
||||
@@ -244,13 +245,13 @@ function formatRangeLabel(
|
||||
endOptions = { day: 'numeric' }
|
||||
}
|
||||
|
||||
const startLabel = new Intl.DateTimeFormat(undefined, startOptions).format(start)
|
||||
const endLabel = new Intl.DateTimeFormat(undefined, endOptions).format(end)
|
||||
const startLabel = new Intl.DateTimeFormat(DATE_LOCALE, startOptions).format(start)
|
||||
const endLabel = new Intl.DateTimeFormat(DATE_LOCALE, endOptions).format(end)
|
||||
const range = `${startLabel}–${endLabel}`
|
||||
|
||||
if (!showTrailingYear) return range
|
||||
|
||||
const yearLabel = new Intl.DateTimeFormat(undefined, { year: 'numeric' }).format(end)
|
||||
const yearLabel = new Intl.DateTimeFormat(DATE_LOCALE, { year: 'numeric' }).format(end)
|
||||
return `${range}, ${yearLabel}`
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -168,6 +168,14 @@ const {
|
||||
onRangeSelected: (start, end, groupBy) => emit('range-select', start, end, groupBy),
|
||||
})
|
||||
|
||||
function getTooltipTotalMetricValue(value: number): number {
|
||||
if (props.activeStat === 'revenue' && Math.abs(value) < 1) {
|
||||
return Math.round(value * 100) / 100
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
const hoverTotalValue = computed(() => {
|
||||
if (hoverState.sliceIndex === null) return 0
|
||||
const sliceIndex = hoverState.sliceIndex
|
||||
@@ -176,7 +184,7 @@ const hoverTotalValue = computed(() => {
|
||||
return props.currentLegendEntries.reduce((sum, legendEntry) => {
|
||||
if (legendEntry.hidden) return sum
|
||||
const dataset = props.chartDatasetById.get(legendEntry.id)
|
||||
return sum + (dataset?.data[sliceIndex] ?? 0)
|
||||
return sum + getTooltipTotalMetricValue(dataset?.data[sliceIndex] ?? 0)
|
||||
}, 0)
|
||||
})
|
||||
|
||||
|
||||
-1
@@ -40,7 +40,6 @@ export function useAnalyticsChartEvents(
|
||||
placeholderData: [],
|
||||
refetchOnMount: 'always',
|
||||
retry: false,
|
||||
staleTime: 0,
|
||||
})
|
||||
|
||||
const localAnalyticsChartEvents = computed(() => analyticsEvents.value ?? [])
|
||||
|
||||
+11
-4
@@ -109,7 +109,7 @@ function getRegionDisplayNames(locale: string): Intl.DisplayNames | null {
|
||||
function formatCountryCode(countryCode: string, formatMessage: FormatMessage): string {
|
||||
const normalized = countryCode.trim().toUpperCase()
|
||||
if (normalized === OTHER_COUNTRY_CODE) {
|
||||
return formatMessage(analyticsMessages.unknown)
|
||||
return formatMessage(analyticsMessages.other)
|
||||
}
|
||||
|
||||
if (!REGION_CODE_PATTERN.test(normalized)) {
|
||||
@@ -146,6 +146,9 @@ export function formatBreakdownLabel(
|
||||
normalizedLowercaseValue === 'other' ||
|
||||
normalizedLowercaseValue === 'unknown'
|
||||
) {
|
||||
if (selectedBreakdown === 'country') {
|
||||
return formatMessage(analyticsMessages.other)
|
||||
}
|
||||
return formatMessage(analyticsMessages.unknown)
|
||||
}
|
||||
if (selectedBreakdown === 'country') {
|
||||
@@ -753,7 +756,7 @@ export function formatMetricValue(
|
||||
case 'playtime': {
|
||||
const hours = value / 3600
|
||||
return formatMessage(analyticsStatCardMessages.playtimeHours, {
|
||||
hours: hours.toFixed(1),
|
||||
hours: Math.abs(hours) < 1 ? hours.toFixed(2) : hours.toFixed(1),
|
||||
})
|
||||
}
|
||||
case 'views':
|
||||
@@ -770,7 +773,11 @@ function formatSmallAxisNumber(value: number): string {
|
||||
}
|
||||
|
||||
const formattedValue = Math.abs(value) < 1 ? value.toFixed(2) : value.toFixed(1)
|
||||
return formattedValue.replace(/\.?0+$/, '')
|
||||
return trimTrailingFractionZeros(formattedValue)
|
||||
}
|
||||
|
||||
function trimTrailingFractionZeros(value: string): string {
|
||||
return value.replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '')
|
||||
}
|
||||
|
||||
const COMPACT_AXIS_UNITS = [
|
||||
@@ -814,7 +821,7 @@ function formatCompactAxisValue(value: number): string {
|
||||
return String(truncatedValue)
|
||||
}
|
||||
|
||||
return roundedValue.toFixed(fractionDigitCount).replace(/\.?0+$/, '')
|
||||
return trimTrailingFractionZeros(roundedValue.toFixed(fractionDigitCount))
|
||||
}
|
||||
|
||||
export function formatAxisValue(
|
||||
|
||||
@@ -39,6 +39,14 @@ export const analyticsMessages = defineMessages({
|
||||
id: 'analytics.project.all',
|
||||
defaultMessage: 'All projects',
|
||||
},
|
||||
yourProjects: {
|
||||
id: 'analytics.project.your',
|
||||
defaultMessage: 'Your projects',
|
||||
},
|
||||
userProjects: {
|
||||
id: 'analytics.project.user',
|
||||
defaultMessage: "{username}'s projects",
|
||||
},
|
||||
selectProjects: {
|
||||
id: 'analytics.project.select',
|
||||
defaultMessage: 'Select projects',
|
||||
@@ -224,6 +232,19 @@ export const analyticsGraphTitleMessages = defineMessages({
|
||||
})
|
||||
|
||||
export const analyticsStatCardMessages = defineMessages({
|
||||
monetizationBannerTitle: {
|
||||
id: 'analytics.stat.monetization-banner.title',
|
||||
defaultMessage: 'How does monetization work?',
|
||||
},
|
||||
monetizationBannerBody: {
|
||||
id: 'analytics.stat.monetization-banner.body',
|
||||
defaultMessage:
|
||||
'Only views and downloads made through Modrinth are eligible for monetization and must pass fraud-prevention filtering. Modrinth App downloads also require the user to be logged in. Because all projects have a similar ratio of monetized downloads, your revenue would not meaningfully change if all downloads were counted.',
|
||||
},
|
||||
monetizationBannerLearnMore: {
|
||||
id: 'analytics.stat.monetization-banner.learn-more',
|
||||
defaultMessage: 'Learn more',
|
||||
},
|
||||
revenueValue: {
|
||||
id: 'analytics.stat.revenue-value',
|
||||
defaultMessage: '${value}',
|
||||
|
||||
@@ -146,6 +146,7 @@ const QUERY_KEY_TABLE_SORT = 'a_table_sort'
|
||||
const QUERY_KEY_TABLE_SORT_DIRECTION = 'a_table_sort_direction'
|
||||
const QUERY_KEY_LEGACY_GRAPH_TOP_BREAKDOWN_FILTER = 'a_top_breakdown'
|
||||
const QUERY_KEY_LEGACY_GRAPH_LEGEND_EXPANSION = 'a_legend_expanded'
|
||||
const PROJECT_SELECTION_ALL_QUERY_VALUE = 'all'
|
||||
|
||||
const URL_FILTER_CATEGORIES: Exclude<AnalyticsQueryFilterCategory, 'project'>[] = [
|
||||
'project_status',
|
||||
@@ -405,9 +406,10 @@ export function buildDefaultAnalyticsGraphState(
|
||||
|
||||
export function buildDefaultAnalyticsQueryBuilderState(
|
||||
availableProjectIds: string[],
|
||||
defaultProjectIds: string[] = availableProjectIds,
|
||||
): AnalyticsQueryBuilderState {
|
||||
return {
|
||||
selectedProjectIds: [...availableProjectIds],
|
||||
selectedProjectIds: [...defaultProjectIds],
|
||||
selectedTimeframeMode: DEFAULT_TIMEFRAME_MODE,
|
||||
selectedTimeframe: DEFAULT_TIMEFRAME_PRESET,
|
||||
selectedLastTimeframeAmount: DEFAULT_LAST_TIMEFRAME_AMOUNT,
|
||||
@@ -415,7 +417,7 @@ export function buildDefaultAnalyticsQueryBuilderState(
|
||||
selectedCustomTimeframeStartDate: getDefaultCustomStartDate(),
|
||||
selectedCustomTimeframeEndDate: getDefaultCustomEndDate(),
|
||||
selectedGroupBy: DEFAULT_GROUP_BY_PRESET,
|
||||
selectedBreakdowns: getDefaultAnalyticsBreakdownPresets(availableProjectIds),
|
||||
selectedBreakdowns: getDefaultAnalyticsBreakdownPresets(defaultProjectIds),
|
||||
selectedFilters: buildEmptySelectedFilters(),
|
||||
}
|
||||
}
|
||||
@@ -475,12 +477,16 @@ export function getAnalyticsBreakdownPresetForProjectSelection(
|
||||
export function isAnalyticsQueryBuilderStateDefault(
|
||||
state: AnalyticsQueryBuilderState,
|
||||
availableProjectIds: string[],
|
||||
defaultProjectIds: string[] = availableProjectIds,
|
||||
): boolean {
|
||||
const defaultState = buildDefaultAnalyticsQueryBuilderState(availableProjectIds)
|
||||
const defaultState = buildDefaultAnalyticsQueryBuilderState(
|
||||
availableProjectIds,
|
||||
defaultProjectIds,
|
||||
)
|
||||
const areDefaultProjectsSelected =
|
||||
availableProjectIds.length === 0
|
||||
defaultProjectIds.length === 0
|
||||
? state.selectedProjectIds.length === 0
|
||||
: areAllProjectsSelected(state.selectedProjectIds, availableProjectIds)
|
||||
: areAllProjectsSelected(state.selectedProjectIds, defaultProjectIds)
|
||||
|
||||
return (
|
||||
areDefaultProjectsSelected &&
|
||||
@@ -666,13 +672,19 @@ export function readAnalyticsTableSortState(
|
||||
export function readAnalyticsQueryBuilderState(
|
||||
query: LocationQuery,
|
||||
availableProjectIds: string[],
|
||||
defaultProjectIds: string[] = availableProjectIds,
|
||||
): AnalyticsQueryBuilderState {
|
||||
const defaultState = buildDefaultAnalyticsQueryBuilderState(availableProjectIds)
|
||||
const defaultState = buildDefaultAnalyticsQueryBuilderState(
|
||||
availableProjectIds,
|
||||
defaultProjectIds,
|
||||
)
|
||||
const selectedProjectIdsFromQuery = parseListQueryValue(query[QUERY_KEY_PROJECT_IDS])
|
||||
const selectedProjectIds =
|
||||
selectedProjectIdsFromQuery.length > 0
|
||||
? selectedProjectIdsFromQuery
|
||||
: defaultState.selectedProjectIds
|
||||
let selectedProjectIds = defaultState.selectedProjectIds
|
||||
if (selectedProjectIdsFromQuery.includes(PROJECT_SELECTION_ALL_QUERY_VALUE)) {
|
||||
selectedProjectIds = [...availableProjectIds]
|
||||
} else if (selectedProjectIdsFromQuery.length > 0) {
|
||||
selectedProjectIds = selectedProjectIdsFromQuery
|
||||
}
|
||||
|
||||
const selectedFilters = buildEmptySelectedFilters()
|
||||
for (const category of URL_FILTER_CATEGORIES) {
|
||||
@@ -779,14 +791,17 @@ export function buildAnalyticsQueryBuilderRouteQuery(
|
||||
state: AnalyticsQueryBuilderState,
|
||||
availableProjectIds: string[],
|
||||
graphState?: AnalyticsGraphState,
|
||||
defaultProjectIds: string[] = availableProjectIds,
|
||||
): MutableRouteQuery {
|
||||
const nextRouteQuery = {
|
||||
...currentRouteQuery,
|
||||
} as MutableRouteQuery
|
||||
|
||||
const projectIdsQueryValue = areAllProjectsSelected(state.selectedProjectIds, availableProjectIds)
|
||||
const projectIdsQueryValue = areAllProjectsSelected(state.selectedProjectIds, defaultProjectIds)
|
||||
? undefined
|
||||
: serializeListQueryValue(state.selectedProjectIds)
|
||||
: areAllProjectsSelected(state.selectedProjectIds, availableProjectIds)
|
||||
? PROJECT_SELECTION_ALL_QUERY_VALUE
|
||||
: serializeListQueryValue(state.selectedProjectIds)
|
||||
const isCustomTimeframeMode =
|
||||
state.selectedTimeframeMode === 'custom_range' ||
|
||||
state.selectedTimeframeMode === 'custom_datetime_range'
|
||||
|
||||
+2
@@ -66,6 +66,7 @@ export function buildAnalyticsTableColumns({
|
||||
key: getAnalyticsTableBreakdownColumnKey(breakdown),
|
||||
label: getAnalyticsTableBreakdownColumnLabel(breakdown, formatMessage),
|
||||
enableSorting: true,
|
||||
width: breakdown === 'project' ? '25%' : undefined,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -75,6 +76,7 @@ export function buildAnalyticsTableColumns({
|
||||
key: 'project',
|
||||
label: formatAnalyticsBreakdownLabel('project', formatMessage),
|
||||
enableSorting: true,
|
||||
width: '25%',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -40,10 +40,12 @@ export function formatAnalyticsTableCompactPlaytime(
|
||||
formatMessage: FormatMessage,
|
||||
): string {
|
||||
const totalSeconds = Math.max(0, Math.round(value))
|
||||
const hours = totalSeconds / SECONDS_PER_HOUR
|
||||
const fractionDigits = hours < 1 ? 2 : 1
|
||||
return formatMessage(analyticsStatCardMessages.playtimeHours, {
|
||||
hours: (totalSeconds / SECONDS_PER_HOUR).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 1,
|
||||
maximumFractionDigits: 1,
|
||||
hours: hours.toLocaleString(undefined, {
|
||||
minimumFractionDigits: fractionDigits,
|
||||
maximumFractionDigits: fractionDigits,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
+17
-1
@@ -12,6 +12,7 @@ import {
|
||||
getSliceCount,
|
||||
} from '../analytics-chart/analytics-chart-utils'
|
||||
import type { FormatMessage } from '../analytics-messages'
|
||||
import { analyticsMessages } from '../analytics-messages'
|
||||
import {
|
||||
ALL_BREAKDOWN_VALUE,
|
||||
COMBINED_BREAKDOWN_LABEL_SEPARATOR,
|
||||
@@ -64,6 +65,8 @@ export function buildAnalyticsTableRows({
|
||||
|
||||
const timeRange = fetchRequest.time_range
|
||||
const sliceCount = getSliceCount(timeRange, timeSlices.length)
|
||||
const currentTimeSlices =
|
||||
timeSlices.length > sliceCount ? timeSlices.slice(timeSlices.length - sliceCount) : timeSlices
|
||||
const includeDate = mode === 'date_breakdown'
|
||||
const breakdownDisplayValues = new Map<string, string>()
|
||||
const projectDisplayValues = new Map<string, string>()
|
||||
@@ -119,9 +122,22 @@ export function buildAnalyticsTableRows({
|
||||
}
|
||||
|
||||
function getCombinedBreakdownDisplay(displays: AnalyticsTableBreakdownDisplayValues) {
|
||||
const unknownBreakdownLabel = formatMessage(analyticsMessages.unknown)
|
||||
let hasUnknownBreakdownLabel = false
|
||||
|
||||
return selectedBreakdowns
|
||||
.map((breakdown) => displays[breakdown])
|
||||
.filter((displayValue): displayValue is string => Boolean(displayValue))
|
||||
.filter((displayValue) => {
|
||||
if (displayValue !== unknownBreakdownLabel) {
|
||||
return true
|
||||
}
|
||||
if (hasUnknownBreakdownLabel) {
|
||||
return false
|
||||
}
|
||||
hasUnknownBreakdownLabel = true
|
||||
return true
|
||||
})
|
||||
.join(COMBINED_BREAKDOWN_LABEL_SEPARATOR)
|
||||
}
|
||||
|
||||
@@ -184,7 +200,7 @@ export function buildAnalyticsTableRows({
|
||||
}
|
||||
}
|
||||
|
||||
timeSlices.forEach((slice, sliceIndex) => {
|
||||
currentTimeSlices.forEach((slice, sliceIndex) => {
|
||||
const bucketLabel = includeDate ? getBucketLabel(sliceIndex) : undefined
|
||||
|
||||
for (const point of slice) {
|
||||
|
||||
@@ -30,9 +30,10 @@ export function getAnalyticsBreakdownValue(
|
||||
case 'user_agent': {
|
||||
const downloadSource = normalizeBreakdownValue(
|
||||
'user_agent' in point ? point.user_agent : undefined,
|
||||
UNKNOWN_BREAKDOWN_VALUE,
|
||||
)
|
||||
return downloadSource === ALL_BREAKDOWN_VALUE
|
||||
? ALL_BREAKDOWN_VALUE
|
||||
return downloadSource === UNKNOWN_BREAKDOWN_VALUE
|
||||
? UNKNOWN_BREAKDOWN_VALUE
|
||||
: getDownloadSourceLabel(downloadSource, formatMessage)
|
||||
}
|
||||
case 'download_reason':
|
||||
@@ -98,5 +99,12 @@ function normalizeBreakdownValue(
|
||||
fallback = ALL_BREAKDOWN_VALUE,
|
||||
): string {
|
||||
const normalized = value?.trim()
|
||||
const normalizedLowercase = normalized?.toLowerCase()
|
||||
if (
|
||||
fallback === UNKNOWN_BREAKDOWN_VALUE &&
|
||||
(normalizedLowercase === 'unknown' || normalizedLowercase === 'other')
|
||||
) {
|
||||
return fallback
|
||||
}
|
||||
return normalized && normalized.length > 0 ? normalized : fallback
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user