Compare commits

...
Author SHA1 Message Date
François-X. T. e14e3c924e Fix windows artifacts 2026-01-30 15:25:26 -05:00
François-X. T. dd63c00945 Figure out where windows artifacts are 2026-01-30 15:02:26 -05:00
François-X. T. 73eecfe637 Remove the damn emojis 2026-01-30 14:35:59 -05:00
François-X. T. 8feeae724b Don't sign windows binaries by default 2026-01-30 14:35:05 -05:00
François-X. T. bca04fbe97 Fix application loading 2026-01-30 14:33:41 -05:00
François-X. T. a059b2af8a Remove unused binding 2026-01-30 13:35:51 -05:00
François-X. T. a0af476e55 Remove patch file 2026-01-30 13:34:01 -05:00
François-X. T. f6613ccf6e Remove old updater stuff 2026-01-30 13:33:24 -05:00
François-X. T. af719362fb Propagate app_identifier via State 2026-01-30 13:31:11 -05:00
François-X. T. 9ef2889a35 Workflow changes 2026-01-30 13:17:55 -05:00
NotchArrowandGitHub 0875a8a0bc Fixed Payout Source Code Link (#5251) 2026-01-30 16:51:20 +00:00
Calum H.andGitHub 5624e86c2b fix: stale cache handling (#5253)
* fix: allow stale cache

* fix: cache amnt

* fix: other one asw
2026-01-30 16:41:03 +00:00
Prospector c622a9281f changelog 2026-01-30 07:51:57 -08:00
Prospector 937d385241 Revert "remove imgur from proxy whitelist (#5239)"
This reverts commit deaa57fa15.
2026-01-30 07:50:38 -08:00
Calum H.andGitHub 3ec9bcf7e7 fix: caching problems frontend for version upload (#5252) 2026-01-30 14:50:57 +00:00
Prospector 3dd5314062 Add loading state to envs 2026-01-28 17:52:32 -08:00
Prospector d77823c5f4 Fix reference to props on members page 2026-01-28 17:19:51 -08:00
Prospector 41b48bd353 changelog 2026-01-28 16:42:42 -08:00
6225ece6be Add Tangled to common source links (#5236)
* Add Tangled to common source links

* prepr

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-28 16:41:31 -08:00
ProspectorandGitHub 3f8805b953 fix some issues with latest PRs (#5242) 2026-01-28 16:41:17 -08:00
ProspectorandGitHub 6d68c0983f fix quilt svg (#5241) 2026-01-28 16:35:28 -08:00
Prospector 3ac0eb896c changelog 2026-01-28 13:54:54 -08:00
Truman GaoandGitHub 9c309e6da2 fix: various fixes for versions (#5238)
* fix: environment not showing when has mod loaders

* fix: weird snapshot format by only grouping consecutive tags with 3 or more

* fix: 26.1 snapshots not grouped properly in mc version picker

* remove debug console.log
2026-01-28 13:46:07 -08:00
ProspectorandGitHub deaa57fa15 remove imgur from proxy whitelist (#5239) 2026-01-28 13:45:37 -08:00
ProspectorandGitHub 8053fec29f Fix iris logo color (#5240) 2026-01-28 13:45:24 -08:00
78aca7e5c0 feat: shared components for worlds + p2p instances (#5135)
* feat: base content card component

* fix: tooltips + colors

* feat: fix orgs

* feat: add ContentModpackCard

* fix: extract types

* feat: selection v-model

* add show icon in selected for combobox with stories

* feat: add project combobox

* clean up project combobox

* feat: start install to play modal

* fix: events

* feat: figma alignments

* feat: migrate toggle to tailwind

* fix: row borders

* feat: disabled state

* feat: virtual list impl for card table based on window scroll

* fix: lint

* feat: virtualization + smaller contentcard items

* feat: fix gap + border issues on last elm

* fix: use TeleportOverflowMenu

* fix: hasUpdate type

* fix: fallback to svg if src is invalid on avatar component

* fix: storybook

* feat: start on updater modal

* feat: finish content updater modal

* feat: i18n pass

* remove install to play modal from ui package

* pnpm prepr

* feat: reusable table component

* feat: add column width prop for table and fix stories

* feat: add table overflow menu story example

* feat: add surface-1.5 and use in table

* chore: export table in index

* fix: allow more loose typing on columns

* feat: update table component to derive key from column instead of data

* feat: surface 1.5 for oled + refactor story for contentcardtable + yeet sorting funcs

* fix: lint

* feat: add no padding story for new modal

---------

Signed-off-by: Calum H. <contact@cal.engineer>
Co-authored-by: tdgao <mr.trumgao@gmail.com>
2026-01-28 20:09:24 +00:00
ProspectorandGitHub 728f8db7b9 Add game version warning for shaders (#5227) 2026-01-28 19:43:58 +00:00
Calum H.andGitHub 4c14339b4b fix: locale loading for ui + moderation nags (#5235)
* fix: locale loading

* fix: locale problems

* fix: lint
2026-01-28 19:41:03 +00:00
ProspectorandGitHub 16ac2aae6b Make tags translatable, move icons to frontend, a few other things (#5229)
* Make tags translatable, move icons to frontend, a few other things

* Migrate more things

* fix import

* more import fixes

* export tag-messages

* lint
2026-01-28 19:01:56 +00:00
6d68d50699 Deduplicate common strings in translation (#5085)
* deduplicate common strings, part 1

* deduplicate common strings, part 2

* typo and general import mess fixes

* detail common string

* fix lint

* fix lint TWO

* adress review concerns + lint

* app lint too

* actually leave privateLabel untouched

* lint fix THREE

* fix: broken msg

* fix: lint

---------

Co-authored-by: Calum H. <contact@cal.engineer>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-28 18:10:50 +00:00
Calum H.andGitHub 400c571fe6 refactor: project saving logic (#5225)
* fix: project data saving not visually shown immediately

* feat: useSavable improvements

* feat: migrate where possible to useSavable

* fix: gitignore

* feat: use es-toolkit
2026-01-28 16:46:14 +00:00
aecsocketandGitHub e57c15b3ce Add SQLx operation tracing (#5223)
* wip: vendor sqlx-tracing

* (compiles) standardize pg types used

* more standardization

* general log message improvements

* wip: improve sqlx-tracing architecture

* unify sqlx::Executor type

* wip: try fix sqlx tracing

* wip: sqlx-tracing compiles

* so close

* it compiles

* fix ci
2026-01-28 13:38:57 +00:00
Prospector 7cb7e881fa Revert "changelog"
This reverts commit 638bb55649.
2026-01-27 16:31:20 -08:00
Prospector 2cf82349a5 Revert "feat: badge for tax 2025 bug (#5230)"
This reverts commit 6d1b0eef15.
2026-01-27 16:31:15 -08:00
Prospector 638bb55649 changelog 2026-01-27 14:09:10 -08:00
Calum H.andGitHub 6d1b0eef15 feat: badge for tax 2025 bug (#5230) 2026-01-27 19:03:54 +00:00
03658b6a62 feat: show update available notif for modrinth app in linux (#5181)
* feat: show update available notif for modrinth app in linux

* remove changelog button

* update copy

* pnpm prepr

* add restart app changelog

* pnpm prepr

* use env var to check for updates are disabled

* update copy

* pnpm prepr

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-27 14:20:11 +00:00
François-Xavier TalbotandGitHub f998a8dca5 Allow node transfer field to recv more than 1 node (#5220) 2026-01-26 22:49:21 +00:00
Modrinth BotandGitHub 0d6bee3a5b New translations from Crowdin (main) (#5217) 2026-01-26 07:47:29 +00:00
Prospector 7ce334aeb2 changelog 2026-01-25 13:22:14 -08:00
ProspectorandGitHub fe3a1b2058 Fix versions not loading in settings page (#5214)
* Fix versions not loading in settings page

* prepr
2026-01-25 13:21:25 -08:00
662b73211a Fix CSP issue when changing capes (#5177)
* Update tauri.conf.json

Signed-off-by: Felix <60808107+ItsFelix5@users.noreply.github.com>

* feat: add https for futureproofing asw

---------

Signed-off-by: Felix <60808107+ItsFelix5@users.noreply.github.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-25 20:59:06 +00:00
c453a03a02 fix: dont await lock releasing (#5161)
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-25 20:57:43 +00:00
aecsocketandGitHub 05f8113bd0 Fix CI on main (#5213) 2026-01-25 12:40:22 -08:00
Prospector 63dfc3f636 changelog 2026-01-25 12:31:44 -08:00
Calum H.andGitHub c96a303d8a fix: optimistically updating on moderation mutations (#5200)
* fix: moderation optimistically update

* fix: gallery settings
2026-01-25 12:27:45 -08:00
François-Xavier TalbotandGitHub 2d7e87a4cb Local cache lock (#5193) 2026-01-24 00:35:46 +01:00
Prospector fa421b4b83 changelog 2026-01-23 12:59:29 -08:00
François-Xavier TalbotandGitHub 79217e78b4 Theseus circuit breaker (#5196)
* Impl request fence

* Reduce max FETCH_ATTEMPTS

* Tweak fail threshold & window

* Check block status every retry iteration

* Fix fmt

* Fix fmt 2
2026-01-23 20:28:50 +00:00
Prospector bdd808c279 changelog 2026-01-23 12:17:44 -08:00
986a7e6216 feat: ssr fixes + switch project page to tanstack (#5192)
* feat: ssr fixes

* feat: lazy load non-core data

* feat: ssr timing debugging

* feat: go back to all parallel

* feat: migrate to DI + set up mutators

* feat: remove double get versions request, only call v3

* refactor: [version].vue page to use composition API and typescript

* feat: gallery.vue start

* fix: remove left behind console log

* fix: type issues + gallery

* fix: versionsummary modal + version page direct join

* fix: projectRaw guard

* fix: currentMember val fix

* fix: actualProjectType

* fix: vers summary link same page

* fix: lint

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
2026-01-23 12:12:50 -08:00
lumiscosityandGitHub b54fcaa0b1 feat: Make hosting marketing page translatable (#5145)
* feat: make hosting marketing page translatable, part 1

* format what we've got so far

* lint and fix locale setting

* the rest of the owl, almost

still one more message in MedalPlanPromotion that's a bit annoying because of all the inline styles

* finishing touches

some things just shouldn't be questioned, i guess. that's two for two on issues that occur even though i seem to have done everything right. i give up

* whoops, that's literal

* get back in the span, you

* fix typo + lint

* and now it works

* one more fix
2026-01-23 19:54:24 +00:00
Michael H. 1cf782c298 Revert "Implement redis clustering (#5189)"
This reverts commit fb1050e409.
2026-01-23 16:08:07 +01:00
fb1050e409 Implement redis clustering (#5189)
Co-authored-by: Jai Agrawal <geometrically@Jais-MacBook-Pro.local>
2026-01-23 13:51:17 +01:00
François-Xavier TalbotandGitHub 5c29a8c7dd Batched search indexing (#5191)
* Use RO pool for search indexing

* Batched search indexing that actually works

* Query cache
2026-01-23 12:32:02 +00:00
Prospector 09dead50d2 changelog 2026-01-22 11:40:47 -08:00
ProspectorandGitHub 772e0ee220 Update app download page to use flathub (#5188) 2026-01-22 11:36:56 -08:00
ProspectorandGitHub 86b0de3cee Update linux icon (#5186) 2026-01-22 19:02:12 +00:00
ProspectorandGitHub d174d96b74 Add flathub verification token (#5184) 2026-01-22 09:47:04 -08:00
aecsocketandGitHub 1d193ed01b More tracing spans for Labrinth Redis (#5182)
* more tracing in redis ops

* Improve Redis tracing

* improve messages

* make lpush and brpop use traced cmds
2026-01-22 17:46:37 +01:00
Prospector adf365d99d changelog 2026-01-21 14:50:48 -08:00
ProspectorandGitHub f3f48c3c6f Fix .some error (#5180) 2026-01-21 14:48:47 -08:00
aecsocketandGitHub e072f2237b Improve Labrinth Sentry integration (#5174)
* Improve Sentry integration

* remove debug routes

* fix ci

* sentry tracing stuff

* Add spans to Sentry logging

* Fix CI

* Redis op instrumentation

* pr comments
2026-01-21 18:59:05 +00:00
aecsocketandGitHub 306eee3a21 Fix changing Delphi report issue detail verdict if already exists (#5172)
* Fix changing Delphi report issue detail verdict if already exists

* cargo sqlx prepare
2026-01-21 16:12:21 +00:00
François-Xavier TalbotandGitHub ca1d66d070 Increase index swap timeout, better index swap task o11y (#5171) 2026-01-21 15:54:34 +00:00
Truman GaoandGitHub 7e1400d111 feat: use tanstack query for changelog tab (#5175)
* use tanstack query for changelog tab

* fix query key
2026-01-21 09:10:05 +00:00
Truman GaoandGitHub 7595e77170 fix: showing dependencies stage for modpack (#5176) 2026-01-21 09:08:54 +00:00
08fcc61d35 Make Maven file resolution case-insensitive (#4917)
* Make Maven file resolution case-insensitive

* fix string reference

* fixed formatting

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: aecsocket <aecsocket@tutanota.com>
2026-01-21 01:15:33 +00:00
ProspectorandGitHub b36801c5ed Reduce some more sentry errors (#5173)
* short-circuit user menu options if no user

* misc null checks
2026-01-20 15:58:45 -08:00
ProspectorandGitHub 4ed1a1ae7f attempt to safeguard some potential errors on user and collection pages (#5169)
* attempt to safeguard some potential errors on user and collection pages

* prepr
2026-01-20 13:51:25 -08:00
ProspectorandGitHub 04db01cb55 Fix settings page error for non-members (#5168)
* Fix settings page error for non-members

* prepr
2026-01-20 13:51:12 -08:00
ProspectorandGitHub 8f5185de1c Error on state fail in prod and log endpoint errors (#5167)
* Error on state fail in prod and log endpoint errors

* brint back eslint suppress

* lint
2026-01-20 21:16:25 +00:00
ProspectorandGitHub 9f6db31785 update Modrinth Hosting issue template + misc comments (#5166) 2026-01-20 12:40:11 -08:00
a869086ce9 polish(frontend): technical review QA (#5097)
* feat: filtering + sorting alignment

* polish: malicious summary modal changes

* feat: better filter row using floating panel

* fix: re-enable request

* fix: lint

* polish: jump back to files tab qol

* feat: scroll to top of next card when done

* fix: show lock icon on preview msg

* feat: download no _blank

* feat: show also marked in notif

* feat: auto expand if only one class in the file

* feat: proper page titles

* fix: text-contrast typo

* fix: lint

* feat: QA changes

* feat: individual report page + more qa

* fix: back btn

* fix: broken import

* feat: quick reply msgs

* fix: in other queue filter

* fix: caching threads wrongly

* fix: flag filter

* feat: toggle enabled by default

* fix: dont make btns opacity 50

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-20 19:56:24 +00:00
Michael H. 2af6a1b36f Fix wrangler formatting 2026-01-20 20:56:56 +01:00
ProspectorandGitHub d4381f513f Add 10 second timeout to requests made server-side (#5164)
* add worker timeout for get requests

* make it timeout only on server-side
2026-01-20 20:52:34 +01:00
Michael H. a281f13f15 Enable smart placement 2026-01-20 20:52:20 +01:00
a9641dadff Meilisearch task management, improved task o11y, timeout & batch size adjustments (#5158)
* Better observability

* Search management routes

* Probably fluke

* Use utoipa routes

* Update apps/labrinth/src/routes/internal/search.rs

Co-authored-by: aecsocket <aecsocket@tutanota.com>
Signed-off-by: François-Xavier Talbot <108630700+fetchfern@users.noreply.github.com>

* Update apps/labrinth/src/search/indexing/mod.rs

Co-authored-by: aecsocket <aecsocket@tutanota.com>
Signed-off-by: François-Xavier Talbot <108630700+fetchfern@users.noreply.github.com>

* Update apps/labrinth/src/routes/internal/search.rs

Co-authored-by: aecsocket <aecsocket@tutanota.com>
Signed-off-by: François-Xavier Talbot <108630700+fetchfern@users.noreply.github.com>

* Fix

---------

Signed-off-by: François-Xavier Talbot <108630700+fetchfern@users.noreply.github.com>
Co-authored-by: aecsocket <aecsocket@tutanota.com>
2026-01-20 19:06:37 +00:00
aecsocketandGitHub c94dde9b47 Fix updating mod version if file hash is the same (#5138)
* Start fixing infinite update glitch

* adjust app cache logic

* more cache logic

* cleanup

* add v2 redirect

* add v2 version file route to config
2026-01-19 21:40:44 +00:00
Calum H.andGitHub 976644d1e6 fix: conditionally fetch (#5157)
* fix: conditionally fetch

* fix: yeet
2026-01-19 13:57:49 -08:00
Michael H. 11fe90a69b deploy: nerf cpu time to 5s 2026-01-19 22:27:38 +01:00
Michael H. 1108086854 Revert "Remove dev check in payload/pojo debugger (#5152)"
This reverts commit 3f3e6f5199.
2026-01-19 22:27:15 +01:00
Michael H. 5aea892a39 deploy: raise cpu limit to 10s 2026-01-19 22:12:31 +01:00
Calum H.andGitHub 3f3e6f5199 Remove dev check in payload/pojo debugger (#5152)
* Remove dev dcheck in payload/pojo debugger

Signed-off-by: Calum H. <contact@cal.engineer>

* feat: better payload debugger

---------

Signed-off-by: Calum H. <contact@cal.engineer>
2026-01-19 10:28:25 -08:00
Modrinth BotandGitHub 2efcd383bb New translations from Crowdin (main) (#5154) 2026-01-19 07:35:48 +00:00
Prospector faec9c2965 changelog 2026-01-18 11:28:51 -08:00
Calum H.andGitHub a0e8c7f924 feat: more o11y for i18n pojo (#5148) 2026-01-18 11:18:07 -08:00
Emma AlexiaandGitHub 6efdfdf17e chore: 100k Modrinth projects 🎉 (#5150)
Signed-off-by: Emma Alexia <emma@modrinth.com>
2026-01-18 19:10:47 +00:00
Truman GaoandGitHub aec268c6e9 fix: duplicate changelogs not grouping (#5146)
* fix: changelogs not grouping

* fix changelog check
2026-01-17 23:42:59 +00:00
François-Xavier TalbotandGitHub 2c096a85d6 Better observability for search indexing, fix remove_documents (#5143)
* Better observability for search timeout, fix remove_documents

* Log client idx
2026-01-16 21:51:51 +00:00
240e5455cc Auto create NeoForge instance from mod version (#5142)
* Auto create NeoForge instance from mod version

* prioritise fabric over nf

* pnpm prepr

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
2026-01-16 21:21:14 +00:00
Prospector c538a9ec6d changelog 2026-01-16 11:58:48 -08:00
Calum H.andGitHub 72458f5c41 feat: non-POJO check in rendered hook (#5137)
* feat: non-POJO check in rendered hook

Signed-off-by: Calum H. <contact@cal.engineer>

* fix: lint

* move to plugin

---------

Signed-off-by: Calum H. <contact@cal.engineer>
2026-01-16 11:56:46 -08:00
Calum H.andGitHub 82e4eb7b40 feat: light mode fixes for navtab + files tab (#5134) 2026-01-16 18:23:43 +00:00
Calum H.andGitHub c9bfc4e9b6 fix: analytics.js using old i18n impl (#5132)
* fix i18n

* fix: lint
2026-01-16 09:07:40 +00:00
Calum H.andGitHub 1ea96df00e fix: broken infinite query on files.vue (#5133) 2026-01-16 09:03:56 +00:00
566 changed files with 26748 additions and 8760 deletions
@@ -1,6 +1,6 @@
name: 👥 Bug with Modrinth Servers
description: For issues with a Modrinth Servers product.
labels: [servers]
name: 👥 Bug with Modrinth Hosting
description: For issues with a Modrinth Hosting product.
labels: [hosting]
type: 'bug'
body:
- type: checkboxes
+1 -1
View File
@@ -19,7 +19,7 @@ body:
options:
- Modrinth App
- Modrinth.com website
- Modrinth Servers
- Modrinth Hosting
- Modrinth API for developers
- type: textarea
attributes:
+39 -18
View File
@@ -19,7 +19,7 @@ on:
sign-windows-binaries:
description: Sign Windows binaries
type: boolean
default: true
default: false
required: false
jobs:
@@ -40,33 +40,48 @@ jobs:
runs-on: ${{ matrix.platform }}
steps:
- name: 📥 Check out code
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 🧰 Setup Rust toolchain
- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
rustflags: ''
target: ${{ startsWith(matrix.platform, 'macos') && 'x86_64-apple-darwin' || '' }}
- name: 🧰 Install pnpm
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: 🧰 Setup Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: pnpm
- name: 🧰 Install Linux build dependencies
- name: Generate tauri-dev.conf.json
shell: bash
run: |
GIT_HASH=$(git rev-parse --short HEAD)
cat > apps/app/tauri-dev.conf.json <<EOF
{
"productName": "Modrinth App (dev-${GIT_HASH})",
"mainBinaryName": "Modrinth App (dev-${GIT_HASH})",
"identifier": "ModrinthApp-dev-${GIT_HASH}",
"bundle": {
"fileAssociations": []
}
}
EOF
- name: Install Linux build dependencies
if: startsWith(matrix.platform, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -yq libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev
- name: 🧰 Setup Dasel
- name: Setup Dasel
uses: jaxxstorm/action-install-gh-release@v2.1.0
with:
repo: TomWright/dasel
@@ -75,7 +90,7 @@ jobs:
rename-to: ${{ startsWith(matrix.platform, 'windows') && 'dasel.exe' || 'dasel' }}
chmod: 0755
- name: ⚙️ Set application version and environment
- 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/')"
@@ -86,13 +101,13 @@ jobs:
cp packages/app-lib/.env.prod packages/app-lib/.env
- name: 💨 Setup Turbo cache
- name: Setup Turbo cache
uses: rharkor/caching-for-turbo@v1.8
- name: 🧰 Install dependencies
- name: Install dependencies
run: pnpm install
- name: ✍️ Set up Windows code signing
- name: Set up Windows code signing
if: startsWith(matrix.platform, 'windows')
shell: bash
run: |
@@ -102,8 +117,8 @@ jobs:
dasel delete -f apps/app/tauri-release.conf.json 'bundle.windows.signCommand'
fi
- name: 🔨 Build macOS app
run: pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json
- name: Build macOS app
run: ${{ github.ref == 'refs/heads/main' && '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: startsWith(matrix.platform, 'macos')
env:
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
@@ -116,19 +131,19 @@ jobs:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
- name: 🔨 Build Linux app
run: pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json
- name: Build Linux app
run: ${{ github.ref == 'refs/heads/main' && '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: startsWith(matrix.platform, 'ubuntu')
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
- name: 🔨 Build Windows app
- name: Build Windows app
run: |
[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"
pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles 'nsis,updater'
${{ github.ref == 'refs/heads/main' && '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: startsWith(matrix.platform, 'windows')
env:
@@ -138,7 +153,7 @@ jobs:
DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_BASE64: ${{ secrets.DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_BASE64 }}
DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD: ${{ secrets.DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD }}
- name: 📤 Upload app bundles
- name: Upload app bundles
uses: actions/upload-artifact@v4
with:
name: App bundle (${{ matrix.artifact-target-name }})
@@ -146,7 +161,13 @@ jobs:
target/release/bundle/appimage/Modrinth App_*.AppImage*
target/release/bundle/deb/Modrinth App_*.deb*
target/release/bundle/rpm/Modrinth App-*.rpm*
target/release/bundle/appimage/Modrinth App (dev-*)_*.AppImage*
target/release/bundle/deb/Modrinth App (dev-*)_*.deb*
target/release/bundle/rpm/Modrinth App (dev-*)-*.rpm*
target/universal-apple-darwin/release/bundle/macos/Modrinth App.app.tar.gz*
target/universal-apple-darwin/release/bundle/macos/Modrinth App (dev-*)*.app.tar.gz
target/universal-apple-darwin/release/bundle/dmg/Modrinth App (dev-*)*.dmg
target/universal-apple-darwin/release/bundle/dmg/Modrinth App_*.dmg*
target/release/bundle/nsis/Modrinth App_*-setup.exe*
target/release/bundle/nsis/Modrinth App (dev-*)_*-setup.exe*
target/release/bundle/nsis/Modrinth App_*-setup.nsis.zip*
+1
View File
@@ -65,6 +65,7 @@ app-playground-data/*
.astro
.claude
.letta
# labrinth demo fixtures
apps/labrinth/fixtures/demo
Generated
+593 -17
View File
@@ -521,6 +521,22 @@ dependencies = [
"zbus",
]
[[package]]
name = "astral-tokio-tar"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec179a06c1769b1e42e1e2cbe74c7dcdb3d6383c838454d063eaac5bbb7ebbe5"
dependencies = [
"filetime",
"futures-core",
"libc",
"portable-atomic",
"rustc-hash",
"tokio",
"tokio-stream",
"xattr",
]
[[package]]
name = "async-broadcast"
version = "0.7.2"
@@ -671,6 +687,28 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "async-stream"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
dependencies = [
"async-stream-impl",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-stream-impl"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "async-stripe"
version = "0.41.0"
@@ -892,6 +930,49 @@ dependencies = [
"thiserror 2.0.17",
]
[[package]]
name = "axum"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
dependencies = [
"axum-core",
"bytes",
"futures-util",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"serde_core",
"sync_wrapper",
"tower",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum-core"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
dependencies = [
"bytes",
"futures-core",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"mime",
"pin-project-lite",
"sync_wrapper",
"tower-layer",
"tower-service",
]
[[package]]
name = "backtrace"
version = "0.3.76"
@@ -1066,6 +1147,83 @@ dependencies = [
"piper",
]
[[package]]
name = "bollard"
version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87a52479c9237eb04047ddb94788c41ca0d26eaff8b697ecfbb4c32f7fdc3b1b"
dependencies = [
"async-stream",
"base64 0.22.1",
"bitflags 2.9.4",
"bollard-buildkit-proto",
"bollard-stubs",
"bytes",
"chrono",
"futures-core",
"futures-util",
"hex",
"home",
"http 1.3.1",
"http-body-util",
"hyper 1.7.0",
"hyper-named-pipe",
"hyper-rustls 0.27.7",
"hyper-util",
"hyperlocal",
"log",
"num",
"pin-project-lite",
"rand 0.9.2",
"rustls 0.23.32",
"rustls-native-certs 0.8.1",
"rustls-pemfile 2.2.0",
"rustls-pki-types",
"serde",
"serde_derive",
"serde_json",
"serde_repr",
"serde_urlencoded",
"thiserror 2.0.17",
"tokio",
"tokio-stream",
"tokio-util",
"tonic 0.14.2",
"tower-service",
"url",
"winapi",
]
[[package]]
name = "bollard-buildkit-proto"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85a885520bf6249ab931a764ffdb87b0ceef48e6e7d807cfdb21b751e086e1ad"
dependencies = [
"prost 0.14.3",
"prost-types",
"tonic 0.14.2",
"tonic-prost",
"ureq",
]
[[package]]
name = "bollard-stubs"
version = "1.49.1-rc.28.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5731fe885755e92beff1950774068e0cae67ea6ec7587381536fca84f1779623"
dependencies = [
"base64 0.22.1",
"bollard-buildkit-proto",
"bytes",
"chrono",
"prost 0.14.3",
"serde",
"serde_json",
"serde_repr",
"serde_with",
]
[[package]]
name = "borsh"
version = "1.5.7"
@@ -2378,6 +2536,17 @@ dependencies = [
"const-random",
]
[[package]]
name = "docker_credential"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d89dfcba45b4afad7450a99b39e751590463e45c04728cf555d36bb66940de8"
dependencies = [
"base64 0.21.7",
"serde",
"serde_json",
]
[[package]]
name = "document-features"
version = "0.2.11"
@@ -2679,6 +2848,17 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "etcetera"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6"
dependencies = [
"cfg-if",
"home",
"windows-sys 0.59.0",
]
[[package]]
name = "event-listener"
version = "2.5.3"
@@ -3801,6 +3981,21 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-named-pipe"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278"
dependencies = [
"hex",
"hyper 1.7.0",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
"winapi",
]
[[package]]
name = "hyper-rustls"
version = "0.24.2"
@@ -3835,6 +4030,19 @@ dependencies = [
"webpki-roots 1.0.3",
]
[[package]]
name = "hyper-timeout"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
dependencies = [
"hyper 1.7.0",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]]
name = "hyper-tls"
version = "0.6.0"
@@ -3877,6 +4085,21 @@ dependencies = [
"windows-registry",
]
[[package]]
name = "hyperlocal"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7"
dependencies = [
"hex",
"http-body-util",
"hyper 1.7.0",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]]
name = "iana-time-zone"
version = "0.1.64"
@@ -4523,6 +4746,7 @@ dependencies = [
"const_format",
"dashmap",
"deadpool-redis",
"derive_more 2.0.1",
"dotenv-build",
"dotenvy",
"either",
@@ -4558,7 +4782,6 @@ dependencies = [
"rustls 0.23.32",
"rusty-money",
"sentry",
"sentry-actix",
"serde",
"serde_json",
"serde_with",
@@ -4566,6 +4789,7 @@ dependencies = [
"sha2",
"spdx",
"sqlx",
"sqlx-tracing",
"strum",
"thiserror 2.0.17",
"tikv-jemalloc-ctl",
@@ -4888,6 +5112,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "matchit"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "maxminddb"
version = "0.26.0"
@@ -5061,6 +5291,7 @@ version = "0.0.0"
dependencies = [
"dotenvy",
"eyre",
"sentry",
"tracing",
"tracing-ecs",
"tracing-subscriber",
@@ -5872,6 +6103,124 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "opentelemetry"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf416e4cb72756655126f7dd7bb0af49c674f4c1b9903e80c009e0c37e552e6"
dependencies = [
"futures-core",
"futures-sink",
"js-sys",
"pin-project-lite",
"thiserror 2.0.17",
"tracing",
]
[[package]]
name = "opentelemetry-appender-tracing"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e68f63eca5fad47e570e00e893094fc17be959c80c79a7d6ec1abdd5ae6ffc16"
dependencies = [
"opentelemetry",
"tracing",
"tracing-core",
"tracing-log",
"tracing-opentelemetry",
"tracing-subscriber",
]
[[package]]
name = "opentelemetry-http"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f6639e842a97dbea8886e3439710ae463120091e2e064518ba8e716e6ac36d"
dependencies = [
"async-trait",
"bytes",
"http 1.3.1",
"opentelemetry",
"reqwest",
]
[[package]]
name = "opentelemetry-otlp"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b"
dependencies = [
"http 1.3.1",
"opentelemetry",
"opentelemetry-http",
"opentelemetry-proto",
"opentelemetry_sdk",
"prost 0.13.5",
"reqwest",
"thiserror 2.0.17",
"tokio",
"tonic 0.13.1",
"tracing",
]
[[package]]
name = "opentelemetry-proto"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e046fd7660710fe5a05e8748e70d9058dc15c94ba914e7c4faa7c728f0e8ddc"
dependencies = [
"opentelemetry",
"opentelemetry_sdk",
"prost 0.13.5",
"tonic 0.13.1",
]
[[package]]
name = "opentelemetry-semantic-conventions"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83d059a296a47436748557a353c5e6c5705b9470ef6c95cfc52c21a8814ddac2"
[[package]]
name = "opentelemetry-testing"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562407eb254fea88076c8a410a733a8ee2075fd9c7fbde3da2a03d29e2cef104"
dependencies = [
"anyhow",
"opentelemetry",
"opentelemetry-appender-tracing",
"opentelemetry-otlp",
"opentelemetry-semantic-conventions",
"opentelemetry_sdk",
"serde",
"serde_json",
"serial_test",
"tempfile",
"testcontainers",
"tokio",
"tracing-opentelemetry",
"tracing-subscriber",
]
[[package]]
name = "opentelemetry_sdk"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11f644aa9e5e31d11896e024305d7e3c98a88884d9f8919dbf37a9991bc47a4b"
dependencies = [
"futures-channel",
"futures-executor",
"futures-util",
"opentelemetry",
"percent-encoding",
"rand 0.9.2",
"serde_json",
"thiserror 2.0.17",
"tokio",
"tokio-stream",
]
[[package]]
name = "option-ext"
version = "0.2.0"
@@ -5996,6 +6345,31 @@ dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "parse-display"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a"
dependencies = [
"parse-display-derive",
"regex",
"regex-syntax",
]
[[package]]
name = "parse-display-derive"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281"
dependencies = [
"proc-macro2",
"quote",
"regex",
"regex-syntax",
"structmeta",
"syn 2.0.106",
]
[[package]]
name = "parse-size"
version = "1.1.0"
@@ -6383,7 +6757,7 @@ dependencies = [
"inferno",
"num",
"paste",
"prost",
"prost 0.13.5",
]
[[package]]
@@ -6589,7 +6963,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
dependencies = [
"bytes",
"prost-derive",
"prost-derive 0.13.5",
]
[[package]]
name = "prost"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
dependencies = [
"bytes",
"prost-derive 0.14.3",
]
[[package]]
@@ -6605,6 +6989,28 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "prost-derive"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
dependencies = [
"anyhow",
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "prost-types"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7"
dependencies = [
"prost 0.14.3",
]
[[package]]
name = "protobuf"
version = "3.7.2"
@@ -7632,6 +8038,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scc"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc"
dependencies = [
"sdd",
]
[[package]]
name = "schannel"
version = "0.1.28"
@@ -7723,6 +8138,12 @@ dependencies = [
"untrusted",
]
[[package]]
name = "sdd"
version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
[[package]]
name = "seahash"
version = "4.1.0"
@@ -7846,19 +8267,6 @@ dependencies = [
"ureq",
]
[[package]]
name = "sentry-actix"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc694e6ffc8d5d7fdb2a33923b0358f6ad41c0b428ced034b349b9e2b08260bc"
dependencies = [
"actix-http",
"actix-web",
"bytes",
"futures-util",
"sentry-core",
]
[[package]]
name = "sentry-backtrace"
version = "0.45.0"
@@ -8182,6 +8590,32 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "serial_test"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555"
dependencies = [
"futures-executor",
"futures-util",
"log",
"once_cell",
"parking_lot",
"scc",
"serial_test_derive",
]
[[package]]
name = "serial_test_derive"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "serialize-to-javascript"
version = "0.1.2"
@@ -8588,7 +9022,7 @@ dependencies = [
"chrono",
"crc",
"dotenvy",
"etcetera",
"etcetera 0.8.0",
"futures-channel",
"futures-core",
"futures-util",
@@ -8641,6 +9075,20 @@ dependencies = [
"uuid 1.18.1",
]
[[package]]
name = "sqlx-tracing"
version = "0.2.0"
dependencies = [
"derive_more 2.0.1",
"futures",
"opentelemetry",
"opentelemetry-testing",
"sqlx",
"testcontainers",
"tokio",
"tracing",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -9417,6 +9865,35 @@ dependencies = [
"winapi",
]
[[package]]
name = "testcontainers"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f3ac71069f20ecfa60c396316c283fbf35e6833a53dff551a31b5458da05edc"
dependencies = [
"astral-tokio-tar",
"async-trait",
"bollard",
"bytes",
"docker_credential",
"either",
"etcetera 0.10.0",
"futures",
"log",
"memchr",
"parse-display",
"pin-project-lite",
"serde",
"serde_json",
"serde_with",
"thiserror 2.0.17",
"tokio",
"tokio-stream",
"tokio-util",
"ulid",
"url",
]
[[package]]
name = "theseus"
version = "1.0.0-local"
@@ -9454,6 +9931,7 @@ dependencies = [
"notify",
"notify-debouncer-mini",
"p256",
"parking_lot",
"paste",
"path-util",
"phf 0.13.1",
@@ -9882,6 +10360,72 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
[[package]]
name = "tonic"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9"
dependencies = [
"async-trait",
"base64 0.22.1",
"bytes",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"hyper 1.7.0",
"hyper-timeout",
"hyper-util",
"percent-encoding",
"pin-project",
"prost 0.13.5",
"tokio",
"tokio-stream",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tonic"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203"
dependencies = [
"async-trait",
"axum",
"base64 0.22.1",
"bytes",
"h2 0.4.12",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"hyper 1.7.0",
"hyper-timeout",
"hyper-util",
"percent-encoding",
"pin-project",
"socket2 0.6.1",
"sync_wrapper",
"tokio",
"tokio-stream",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tonic-prost"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67"
dependencies = [
"bytes",
"prost 0.14.3",
"tonic 0.14.2",
]
[[package]]
name = "totp-rs"
version = "5.7.0"
@@ -9904,11 +10448,15 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [
"futures-core",
"futures-util",
"indexmap 2.11.4",
"pin-project-lite",
"slab",
"sync_wrapper",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
@@ -10024,6 +10572,24 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-opentelemetry"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddcf5959f39507d0d04d6413119c04f33b623f4f951ebcbdddddfad2d0623a9c"
dependencies = [
"js-sys",
"once_cell",
"opentelemetry",
"opentelemetry_sdk",
"smallvec",
"tracing",
"tracing-core",
"tracing-log",
"tracing-subscriber",
"web-time",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.20"
@@ -10119,6 +10685,16 @@ dependencies = [
"winapi",
]
[[package]]
name = "ulid"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe"
dependencies = [
"rand 0.9.2",
"web-time",
]
[[package]]
name = "uname"
version = "0.1.1"
+4 -2
View File
@@ -116,6 +116,7 @@ native-dialog = "0.9.2"
notify = { version = "8.2.0", default-features = false }
notify-debouncer-mini = { version = "0.7.0", default-features = false }
p256 = "0.13.2"
parking_lot = "0.12.5"
paste = "1.0.15"
path-util = { path = "packages/path-util" }
phf = { version = "0.13.1", features = ["macros"] }
@@ -150,7 +151,6 @@ sentry = { version = "0.45.0", default-features = false, features = [
"reqwest",
"rustls",
] }
sentry-actix = "0.45.0"
serde = "1.0.228"
serde_bytes = "0.11.19"
serde_cbor = "0.11.2"
@@ -164,6 +164,7 @@ sha2 = "0.10.9"
shlex = "1.3.0"
spdx = "0.12.0"
sqlx = { version = "0.8.6", default-features = false }
sqlx-tracing = { path = "packages/sqlx-tracing" }
strum = "0.27.2"
sysinfo = { version = "0.37.2", default-features = false }
tar = "0.4.44"
@@ -239,7 +240,7 @@ manual_assert = "warn"
manual_instant_elapsed = "warn"
manual_is_variant_and = "warn"
manual_let_else = "warn"
map_unwrap_or = "warn"
map_unwrap_or = "allow"
match_bool = "warn"
needless_collect = "warn"
negative_feature_names = "warn"
@@ -269,4 +270,5 @@ codegen-units = 1 # Compile crates one after another so the compiler can optimi
# Specific profile for labrinth production builds
[profile.release-labrinth]
inherits = "release"
strip = false # Keep debug symbols for Sentry
panic = "unwind" # Don't exit the whole app on panic in production
+8 -2
View File
@@ -71,6 +71,7 @@ import PromotionWrapper from '@/components/ui/PromotionWrapper.vue'
import QuickInstanceSwitcher from '@/components/ui/QuickInstanceSwitcher.vue'
import RunningAppBar from '@/components/ui/RunningAppBar.vue'
import SplashScreen from '@/components/ui/SplashScreen.vue'
import UpdateAvailableToast from '@/components/ui/UpdateAvailableToast.vue'
import UpdateToast from '@/components/ui/UpdateToast.vue'
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
@@ -143,6 +144,7 @@ const showOnboarding = ref(false)
const nativeDecorations = ref(false)
const os = ref('')
const isDevEnvironment = ref(false)
const stateInitialized = ref(false)
@@ -247,6 +249,7 @@ async function setupApp() {
os.value = await getOS()
const dev = await isDev()
isDevEnvironment.value = dev
const version = await getVersion()
showOnboarding.value = !onboarded
@@ -505,21 +508,23 @@ const restarting = ref(false)
const updateToastDismissed = ref(false)
const availableUpdate = ref(null)
const updateSize = ref(null)
const updatesEnabled = ref(true)
async function checkUpdates() {
if (!(await areUpdatesEnabled())) {
console.log('Skipping update check as updates are disabled in this build or environment')
updatesEnabled.value = false
return
}
async function performCheck() {
const update = await invoke('plugin:updater|check')
const isExistingUpdate = update.version === availableUpdate.value?.version
if (!update) {
console.log('No update available')
return
}
const isExistingUpdate = update.version === availableUpdate.value?.version
if (isExistingUpdate) {
console.log('Update is already known')
return
@@ -769,6 +774,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
@restart="installUpdate"
@download="downloadAvailableUpdate"
/>
<UpdateAvailableToast v-else-if="!updatesEnabled && os === 'Linux' && !isDevEnvironment" />
</Transition>
</Suspense>
<Transition name="fade">
@@ -1,7 +1,6 @@
<script setup lang="ts">
import { GameIcon, LeftArrowIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled } from '@modrinth/ui'
import { formatCategory } from '@modrinth/utils'
import { Avatar, ButtonStyled, FormattedTag } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
type Instance = {
@@ -37,7 +36,8 @@ defineProps<{
</span>
<span class="text-secondary flex items-center gap-2 font-semibold">
<GameIcon class="h-5 w-5 text-secondary" />
{{ formatCategory(instance.loader) }} {{ instance.game_version }}
<FormattedTag :tag="instance.loader" enforce-type="loader" />
{{ instance.game_version }}
</span>
</span>
</span>
@@ -1,7 +1,7 @@
<script setup>
import { DownloadIcon, HeartIcon, TagIcon } from '@modrinth/assets'
import { Avatar, TagItem } from '@modrinth/ui'
import { formatCategory, formatNumber } from '@modrinth/utils'
import { Avatar, FormattedTag, TagItem } from '@modrinth/ui'
import { formatNumber } from '@modrinth/utils'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { computed } from 'vue'
@@ -107,7 +107,7 @@ const toTransparent = computed(() => {
<div class="flex items-center gap-1 pr-2">
<TagIcon />
<TagItem>
{{ formatCategory(featuredCategory) }}
<FormattedTag :tag="featuredCategory" />
</TagItem>
</div>
</div>
@@ -67,7 +67,7 @@
:key="tag"
class="text-sm font-semibold text-secondary flex gap-1 px-[0.375rem] py-0.5 bg-button-bg rounded-full"
>
{{ formatCategory(tag.name) }}
<FormattedTag :tag="tag.name" />
</div>
</div>
</div>
@@ -118,8 +118,8 @@
<script setup>
import { CheckIcon, DownloadIcon, HeartIcon, PlusIcon, TagsIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled, injectNotificationManager } from '@modrinth/ui'
import { formatCategory, formatNumber } from '@modrinth/utils'
import { Avatar, ButtonStyled, FormattedTag, injectNotificationManager } from '@modrinth/ui'
import { formatNumber } from '@modrinth/utils'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { computed, ref } from 'vue'
@@ -0,0 +1,84 @@
<script setup lang="ts">
import { XIcon } from '@modrinth/assets'
import { ButtonStyled, commonMessages, defineMessages, useVIntl } from '@modrinth/ui'
import { getVersion } from '@tauri-apps/api/app'
import { onMounted, onUnmounted, ref } from 'vue'
const { formatMessage } = useVIntl()
const dismissed = ref(false)
const availableUpdate = ref<{ version: string } | null>(null)
let checkInterval: ReturnType<typeof setInterval> | null = null
async function checkForUpdate() {
try {
const [response, currentVersion] = await Promise.all([
fetch('https://launcher-files.modrinth.com/updates.json'),
getVersion(),
])
const updates = await response.json()
const latestVersion = updates?.version
if (latestVersion && latestVersion !== currentVersion) {
if (latestVersion !== availableUpdate.value?.version) {
availableUpdate.value = { version: latestVersion }
dismissed.value = false
}
}
} catch (e) {
console.error('Failed to check for updates:', e)
}
}
function dismiss() {
dismissed.value = true
}
onMounted(() => {
checkForUpdate()
checkInterval = setInterval(checkForUpdate, 5 * 60 * 1000)
})
onUnmounted(() => {
if (checkInterval) {
clearInterval(checkInterval)
}
})
const messages = defineMessages({
title: {
id: 'app.update-toast.title',
defaultMessage: 'Update available',
},
body: {
id: 'app.update-toast.body.linux',
defaultMessage:
'Modrinth App v{version} is available. Use your package manager to update for the latest features and fixes!',
},
download: {
id: 'app.update-toast.download-page',
defaultMessage: 'Download',
},
})
</script>
<template>
<div
v-if="availableUpdate && !dismissed"
class="grid grid-cols-[min-content] fixed card-shadow rounded-2xl top-[--top-bar-height] mt-6 right-6 p-4 z-10 bg-bg-raised border-divider border-solid border-[2px]"
>
<div class="flex min-w-[25rem] gap-4">
<h2 class="whitespace-nowrap text-base text-contrast font-semibold m-0 grow">
{{ formatMessage(messages.title) }}
</h2>
<ButtonStyled size="small" circular>
<button v-tooltip="formatMessage(commonMessages.closeButton)" @click="dismiss">
<XIcon />
</button>
</ButtonStyled>
</div>
<p class="text-sm mt-2 mb-0">
{{ formatMessage(messages.body, { version: availableUpdate.version }) }}
</p>
</div>
</template>
@@ -159,20 +159,21 @@ const reset_icon = () => {
const createInstance = async () => {
creatingInstance.value = true
const loader =
versions.value[0].loaders[0] !== 'forge' &&
versions.value[0].loaders[0] !== 'fabric' &&
versions.value[0].loaders[0] !== 'quilt'
? 'vanilla'
: versions.value[0].loaders[0]
const gameVersions = versions.value[0].game_versions
const gameVersion = gameVersions[0]
const id = await create(
name.value,
versions.value[0].game_versions[0],
loader,
'latest',
icon.value,
).catch(handleError)
const loaders = versions.value[0].loaders
const loader = loaders.contains('fabric')
? 'fabric'
: loaders.contains('neoforge')
? 'neoforge'
: loaders.contains('forge')
? 'forge'
: loaders.contains('quilt')
? 'quilt'
: 'vanilla'
const id = await create(name.value, gameVersion, loader, 'latest', icon.value).catch(handleError)
await installMod(id, versions.value[0].id).catch(handleError)
@@ -1,6 +1,7 @@
<script setup lang="ts">
import {
DownloadIcon,
getLoaderIcon,
HammerIcon,
IssuesIcon,
SpinnerIcon,
@@ -17,16 +18,11 @@ import {
Chips,
Combobox,
defineMessages,
getTagMessageOrDefault,
injectNotificationManager,
useVIntl,
} from '@modrinth/ui'
import {
formatCategory,
type GameVersionTag,
type PlatformTag,
type Project,
type Version,
} from '@modrinth/utils'
import type { GameVersionTag, PlatformTag, Project, Version } from '@modrinth/utils'
import dayjs from 'dayjs'
import { computed, type ComputedRef, type Ref, ref, shallowRef, watch } from 'vue'
@@ -129,9 +125,7 @@ if (props.instance.linked_data && props.instance.linked_data.project_id && !prop
fetching.value = false
}
const currentLoaderIcon = computed(
() => loaders?.value.find((x) => x.name === props.instance.loader)?.icon,
)
const currentLoaderIcon = computed(() => getLoaderIcon(props.instance.loader))
const gameVersionsForLoader = computed(() => {
return all_game_versions?.value.filter((item) => {
@@ -550,7 +544,7 @@ const messages = defineMessages({
v-else
class="w-10 h-10 flex items-center justify-center rounded-full bg-button-bg border-solid border-[1px] border-button-border p-2 [&_svg]:h-full [&_svg]:w-full"
>
<div v-if="!!currentLoaderIcon" class="contents" v-html="currentLoaderIcon" />
<component :is="currentLoaderIcon" v-if="currentLoaderIcon" />
<WrenchIcon v-else />
</div>
<div class="flex flex-col gap-2 justify-center">
@@ -569,7 +563,10 @@ const messages = defineMessages({
? modpackVersion
? modpackVersion?.version_number
: 'Unknown version'
: formatCategory(instance.loader)
: (() => {
const message = getTagMessageOrDefault(instance.loader, 'loader')
return typeof message === 'string' ? message : formatMessage(message)
})()
}}
<template v-if="instance.loader !== 'vanilla' && !modpackProject">
{{ instance.loader_version || formatMessage(messages.unknownVersion) }}
@@ -677,7 +674,14 @@ const messages = defineMessages({
</div>
<template v-if="loader !== 'vanilla'">
<h2 class="m-0 mt-4 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.loaderVersion, { loader: formatCategory(loader) }) }}
{{
formatMessage(messages.loaderVersion, {
loader: (() => {
const message = getTagMessageOrDefault(loader, 'loader')
return typeof message === 'string' ? message : formatMessage(message)
})(),
})
}}
</h2>
<Combobox
v-if="selectableLoaderVersions"
@@ -709,7 +713,10 @@ const messages = defineMessages({
? messages.alreadyInstalledVanilla
: messages.alreadyInstalledModded,
{
platform: formatCategory(loader),
platform: (() => {
const message = getTagMessageOrDefault(loader, 'loader')
return typeof message === 'string' ? message : formatMessage(message)
})(),
version: instance.loader_version,
game_version: gameVersion,
},
@@ -7,7 +7,14 @@ import {
MonitorIcon,
WrenchIcon,
} from '@modrinth/assets'
import { Avatar, defineMessage, TabbedModal, type TabbedModalTab, useVIntl } from '@modrinth/ui'
import {
Avatar,
commonMessages,
defineMessage,
TabbedModal,
type TabbedModalTab,
useVIntl,
} from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { ref } from 'vue'
@@ -74,11 +81,6 @@ function show() {
}
defineExpose({ show })
const titleMessage = defineMessage({
id: 'instance.settings.title',
defaultMessage: 'Settings',
})
</script>
<template>
<ModalWrapper ref="modal">
@@ -90,7 +92,9 @@ const titleMessage = defineMessage({
:tint-by="props.instance.path"
/>
{{ instance.name }} <ChevronRightIcon />
<span class="font-extrabold text-contrast">{{ formatMessage(titleMessage) }}</span>
<span class="font-extrabold text-contrast">{{
formatMessage(commonMessages.settingsLabel)
}}</span>
</span>
</template>
@@ -33,7 +33,7 @@
"message": "إدارة الموارد"
},
"app.update-toast.body": {
"message": "تطبيق Modrinth الإصدار {version} جاهز للتثبيت! أعد التحميل لتحديث التطبيق الآن، أو سيتم التحديث تلقائيًا عند إغلاق تطبيق Modrinth."
"message": "تطبيق Modrinth الإصدار {version} جاهز للتثبيت!\nأعد التحميل لتحديث التطبيق الآن، أو سيتم التحديث تلقائيًا عند إغلاق تطبيق Modrinth."
},
"app.update-toast.body.download-complete": {
"message": "تطبيق Modrinth الإصدار {version} جاهز للتثبيت!\nأعد التحميل لتحديث التطبيق الآن، أو سيتم التحديث تلقائيًا عند إغلاق تطبيق Modrinth."
@@ -87,7 +87,7 @@
"message": "جار إضافة صديق"
},
"friends.add-friend.username.description": {
"message": "قد يختلف عن اسم المستخدم الخاص بهم في Minecraft!"
"message": "قد يختلف عن اسم المستخدم الخاص بهم في ماينكرافت!"
},
"friends.add-friend.username.placeholder": {
"message": "أدخل اسم مستخدم Modrinth..."
@@ -141,7 +141,7 @@
"message": "إضافة واللعب"
},
"instance.add-server.add-server": {
"message": "إضافة الخادم"
"message": "إضافة خادم"
},
"instance.add-server.resource-pack.disabled": {
"message": "معطَّل"
@@ -186,7 +186,7 @@
"message": "الاسم"
},
"instance.server-modal.placeholder-name": {
"message": "خادم ماين كرافت"
"message": "خادم ماينكرافت"
},
"instance.server-modal.resource-pack": {
"message": "حزمة الموارد"
@@ -279,7 +279,7 @@
"message": "مُغلِّف"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "أمر غلاف لتشغيل ماين كرافت."
"message": "أمر غلاف لتشغيل ماينكرافت."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "أدخل أمر الغلاف..."
@@ -288,7 +288,7 @@
"message": "تثبيت"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} لماين كرافت {game_version} مثبت بالفعل"
"message": "{platform} {version} لماينكرافت {game_version} مثبت بالفعل"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "فانيلا {game_version} مُثبّتة بالفعل"
@@ -77,6 +77,9 @@
"friends.action.add-friend": {
"message": "Přidat přítele"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural, one {žádost} few {žádosti} other {žádostí}} o přátelství"
},
"friends.add-friend.submit": {
"message": "Poslat žádost o přátelství"
},
@@ -1,6 +1,6 @@
{
"app.auth-servers.unreachable.body": {
"message": "Minecraft autentificeringsservere kan måske være nede lige nu. Tjek din internet forbindelse og prøv igen senere."
"message": "Minecraft authentication servere kan måske være nede lige nu. Tjek din internet forbindelse og prøv igen senere."
},
"app.auth-servers.unreachable.header": {
"message": "Kan ikke nå autentificeringsservere"
@@ -23,6 +23,9 @@
"app.settings.tabs.java-installations": {
"message": "Javainstallationer"
},
"app.settings.tabs.language": {
"message": "Sprog"
},
"app.settings.tabs.privacy": {
"message": "Privatliv"
},
@@ -33,10 +33,10 @@
"message": "Ressourcenmanagement"
},
"app.update-toast.body": {
"message": "Modrinth App v{version} ist bereit zur Installation! Jetzt neu laden, um zu aktualisieren, oder automatisch beim Schließen der Modrinth App."
"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.update-toast.body.download-complete": {
"message": "Modrinth App v{version} ist bereit zur Installation! Jetzt neu laden, um zu aktualisieren, oder automatisch beim Schließen der Modrinth App."
"message": "Modrinth App v{version} wurde heruntergeladen. Neu laden, um jetzt zu aktualisieren, oder automatisch, wenn du die Modrinth App schließt."
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} ist jetzt verfügbar! Da du ein getaktetes Netzwerk nutzt, haben wir den Download nicht automatisch gestartet."
@@ -72,7 +72,7 @@
"message": "Update wird heruntergeladen ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Neu laden um Update zu installieren"
"message": "Neu laden, um das Update zu installieren"
},
"friends.action.add-friend": {
"message": "Freund hinzufügen"
@@ -105,7 +105,7 @@
"message": "Freund entfernen"
},
"friends.friend.request-sent": {
"message": "Freundesanfrage gesendet"
"message": "Freundschaftsanfrage gesendet"
},
"friends.friend.view-profile": {
"message": "Profil anzeigen"
@@ -270,7 +270,7 @@
"message": "Wird vor dem Starten der Instanz ausgeführt."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Vor Spielstart auszuführender Befehl eingeben..."
"message": "Vor Spielstart auszuführenden Befehl eingeben..."
},
"instance.settings.tabs.hooks.title": {
"message": "Start-Hooks"
@@ -38,6 +38,9 @@
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version} has finished downloading. Reload to update now, or automatically when you close Modrinth App."
},
"app.update-toast.body.linux": {
"message": "Modrinth App v{version} is available. Use your package manager to update for the latest features and fixes!"
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} is available now! Since you're on a metered network, we didn't automatically download it."
},
@@ -47,6 +50,9 @@
"app.update-toast.download": {
"message": "Download ({size})"
},
"app.update-toast.download-page": {
"message": "Download"
},
"app.update-toast.downloading": {
"message": "Downloading..."
},
@@ -470,9 +476,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Enter width..."
},
"instance.settings.title": {
"message": "Settings"
},
"instance.worlds.a_minecraft_server": {
"message": "A Minecraft Server"
},
@@ -189,7 +189,7 @@
"message": "Servidor de Minecraft"
},
"instance.server-modal.resource-pack": {
"message": "Resource pack"
"message": "Paquete de recursos"
},
"instance.settings.tabs.general": {
"message": "General"
@@ -1,4 +1,10 @@
{
"app.auth-servers.unreachable.body": {
"message": "Los servidores de autenticación de Minecraft podrían estar inactivos. Comprueba tu conexión a internet e inténtalo más tarde."
},
"app.auth-servers.unreachable.header": {
"message": ""
},
"app.settings.developer-mode-enabled": {
"message": "Modo desarrollador activado."
},
@@ -18,7 +24,7 @@
"message": "Instalaciones de Java"
},
"app.settings.tabs.language": {
"message": "Lenguaje"
"message": "Idioma"
},
"app.settings.tabs.privacy": {
"message": "Privacidad"
@@ -23,6 +23,9 @@
"app.settings.tabs.java-installations": {
"message": "Java asennukset"
},
"app.settings.tabs.language": {
"message": "Kieli"
},
"app.settings.tabs.privacy": {
"message": "Yksityisyys"
},
@@ -48,7 +51,7 @@
"message": "Ladataan..."
},
"app.update-toast.reload": {
"message": "Lataa uudelleen"
"message": "Uudelleen lataa"
},
"app.update-toast.title": {
"message": "Päivitys saatavilla"
@@ -78,13 +81,13 @@
"message": "{count} ystävä{count, plural, one {pyyntö} other {pyyntöä}}"
},
"friends.add-friend.submit": {
"message": "Lähetä ystäväpyyntö"
"message": "Lähetä kaveripyyntö"
},
"friends.add-friend.title": {
"message": "Lisätään ystävää"
"message": "Lisätään kaveria"
},
"friends.add-friend.username.description": {
"message": "Se voi olla eri kuin heidän Minecraft-käyttäjänimensä!"
"message": "Se ei voi olla eri kuin heidän Minecraft-käyttäjänimi!"
},
"friends.add-friend.username.placeholder": {
"message": "Syötä Modrinth-käyttäjätunnus..."
@@ -33,13 +33,13 @@
"message": "Gestion des ressources"
},
"app.update-toast.body": {
"message": "L'application Modrinth v{version} est prête à être installée ! Relancez l'application pour faire la mise à jour maintenant, ou automatiquement à la fermeture de l'application Modrinth."
"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.update-toast.body.download-complete": {
"message": "Le téléchargement de l'application Modrinth v{version} est terminé ! Relancez l'application pour faire la mise à jour maintenant, ou automatiquement à la fermeture de l'application Modrinth."
"message": "Le téléchargement de Modrinth App v{version} est terminé ! Relancez l'application pour mettre à jour maintenant, ou automatiquement à la fermeture de Modrinth App."
},
"app.update-toast.body.metered": {
"message": "L'application Modrinth v{version} est disponible dès maintenant ! Lorsque vous êtes sur un réseau limité ou en données mobiles, nous ne téléchargerons pas les mises à jour automatiquement."
"message": "Modrinth App v{version} est disponible dès maintenant ! Lorsque vous êtes sur un réseau limité ou en données mobiles, nous ne téléchargerons pas les mises à jour automatiquement."
},
"app.update-toast.changelog": {
"message": "Journal des modifications"
@@ -78,7 +78,7 @@
"message": "Ajouter un ami"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural,one {demande}other {demandes}} d'ami"
"message": "{count} {count, plural, one {demande} other {demandes}} d'ami"
},
"friends.add-friend.submit": {
"message": "Envoyer une demande d'ami"
@@ -126,7 +126,7 @@
"message": "En attente"
},
"friends.no-friends-match": {
"message": "Aucuns amis ne correspondent à \"{query}\""
"message": "Aucuns amis ne correspondent à « {query} »"
},
"friends.search-friends-placeholder": {
"message": "Chercher des amis..."
@@ -249,7 +249,7 @@
"message": "Crochets de lancement"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Crochets de lancement custom"
"message": "Crochets de lancement personnalisés"
},
"instance.settings.tabs.hooks.description": {
"message": "Les crochets permettent aux usagers avancés d'exécuter certaines commandes systèmes avant et après le lancement du jeu."
@@ -258,7 +258,7 @@
"message": "Post-fermeture"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "Exécuté après fermeture."
"message": "Exécuté après la fermeture du jeu."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Entrer commande de post-fermeture..."
@@ -369,7 +369,7 @@
"message": "Réparation"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "La réparation réinstalle les dépendances de Minecraft et vérifie la corruption. Cela peut résoudre les problèmes de lancement du jeu en raison d'erreurs liées au lanceur, mais ne résoudra pas les problèmes ou plantages liés aux mods installés."
"message": "La réparation réinstalle les dépendances de Minecraft et vérifie la corruption. Cela peut résoudre les problèmes de lancement du jeu en raison d'erreurs liées au launcher, mais ne résoudra pas les problèmes ou plantages liés aux mods installés."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Réparer l'instance ?"
@@ -384,7 +384,7 @@
"message": "Voir toutes les versions"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "Changer la version"
"message": "changer la version"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "installer"
@@ -23,6 +23,9 @@
"app.settings.tabs.java-installations": {
"message": "התקנות ג'אווה"
},
"app.settings.tabs.language": {
"message": "שפה"
},
"app.settings.tabs.privacy": {
"message": "פרטיות"
},
@@ -80,6 +83,9 @@
"friends.add-friend.title": {
"message": "מוסיף חבר"
},
"friends.add-friend.username.description": {
"message": "זה יכול להיות שונה מהמשתמש מיינקראפט שלהם!"
},
"friends.add-friend.username.placeholder": {
"message": "הכנס שם משתמש של Modrinth..."
},
+13 -13
View File
@@ -1,9 +1,9 @@
{
"app.auth-servers.unreachable.body": {
"message": "Peladen autentikasi Minecraft mungkin sedang tidak tersedia saat ini. Periksa koneksi internet Anda dan coba lagi nanti."
"message": "Server autentikasi Minecraft mungkin sedang tidak tersedia saat ini. Periksa koneksi internet Anda dan coba lagi nanti."
},
"app.auth-servers.unreachable.header": {
"message": "Tidak dapat terhubung ke peladen autentikasi"
"message": "Tidak dapat terhubung ke server autentikasi"
},
"app.settings.developer-mode-enabled": {
"message": "Mode pengembang dihidupkan."
@@ -93,7 +93,7 @@
"message": "Masukkan nama pengguna Modrinth..."
},
"friends.add-friend.username.title": {
"message": "Apakah nama pengguna Modrinth teman Anda?"
"message": "Apa nama pengguna Modrinth teman Anda?"
},
"friends.add-friends-to-share": {
"message": "<link>Tambah teman</link> untuk melihat apa yang mereka mainkan!"
@@ -141,7 +141,7 @@
"message": "Tambah dan mainkan"
},
"instance.add-server.add-server": {
"message": "Tambah peladen"
"message": "Tambah server"
},
"instance.add-server.resource-pack.disabled": {
"message": "Dimatikan"
@@ -153,10 +153,10 @@
"message": "Konfirmasi"
},
"instance.add-server.title": {
"message": "Tambah peladen"
"message": "Tambah server"
},
"instance.edit-server.title": {
"message": "Sunting peladen"
"message": "Sunting server"
},
"instance.edit-world.hide-from-home": {
"message": "Sembunyikan dari Beranda"
@@ -186,7 +186,7 @@
"message": "Nama"
},
"instance.server-modal.placeholder-name": {
"message": "Peladen Minecraft"
"message": "Server Minecraft"
},
"instance.server-modal.resource-pack": {
"message": "Paket sumber"
@@ -474,10 +474,10 @@
"message": "Pengaturan"
},
"instance.worlds.a_minecraft_server": {
"message": "Peladen Minecraft"
"message": "Server Minecraft"
},
"instance.worlds.cant_connect": {
"message": "Tidak dapat menghubungkan ke peladen"
"message": "Tidak dapat menghubungkan ke server"
},
"instance.worlds.copy_address": {
"message": "Salin alamat"
@@ -495,13 +495,13 @@
"message": "Mode Menantang"
},
"instance.worlds.incompatible_server": {
"message": "Peladen tidak cocok"
"message": "Server tidak cocok"
},
"instance.worlds.no_contact": {
"message": "Peladen tidak dapat dihubungi"
"message": "Server tidak dapat dihubungi"
},
"instance.worlds.no_server_quick_play": {
"message": "Anda hanya dapat memasuki peladen secara langsung pada Minecraft versi Alpha 1.0.5 ke atas"
"message": "Anda hanya dapat memasuki server secara langsung pada Minecraft versi Alpha 1.0.5 ke atas"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Anda hanya dapat memasuki dunia bermain sendiri secara langsung pada Minecraft versi Alpha 1.20 ke atas"
@@ -510,7 +510,7 @@
"message": "Mainkan wujud"
},
"instance.worlds.type.server": {
"message": "Peladen"
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Bermain sendiri"
@@ -42,7 +42,7 @@
"message": "Modrinth App v{version} è ora disponibile! Poiché sei su una rete a consumo, non l''abbiamo scaricata automaticamente."
},
"app.update-toast.changelog": {
"message": "Changelog"
"message": "Novità"
},
"app.update-toast.download": {
"message": "Scarica ({size})"
@@ -60,7 +60,7 @@
"message": "Download completato"
},
"app.update.complete-toast.text": {
"message": "Clicca qui per leggere il changelog."
"message": "Clicca qui per leggere le ultime novità in inglese."
},
"app.update.complete-toast.title": {
"message": "La versione {version} è stata installata con successo!"
@@ -12,7 +12,7 @@
"message": "v{version}をダウンロード中"
},
"app.settings.tabs.appearance": {
"message": "外観"
"message": "表示設定"
},
"app.settings.tabs.default-instance-options": {
"message": "インスタンスの基本設定"
@@ -21,25 +21,25 @@
"message": "機能設定"
},
"app.settings.tabs.java-installations": {
"message": "Javaのインストール"
"message": "Javaのインストール設定"
},
"app.settings.tabs.language": {
"message": "言語"
},
"app.settings.tabs.privacy": {
"message": "プライバシー"
"message": "プライバシー設定"
},
"app.settings.tabs.resource-management": {
"message": "リソース管理"
},
"app.update-toast.body": {
"message": "Modrinth App v{version}は今すぐインストールできます!再起動して今すぐ更新するか、アプリを閉じた際に自動で更新されます。"
"message": "Modrinth App v{version}インストールの準備ができました。再起動して今すぐ更新するか、アプリを閉じた際に自動で更新されます。"
},
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version}のダウンロードが完了しました。再起動して今すぐ更新するか、アプリを閉じた際に自動で更新されます。"
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version}は今すぐダウンロードできます従量課金制ネットワークを使用しているため自動ダウンロードはされていません。"
"message": "Modrinth App v{version}は今すぐダウンロードできます従量課金制ネットワークを使用しているため自動ダウンロードはされていません。"
},
"app.update-toast.changelog": {
"message": "更新履歴"
@@ -54,7 +54,7 @@
"message": "再起動"
},
"app.update-toast.title": {
"message": "アップデートが可能"
"message": "アップデートが利用可能です"
},
"app.update-toast.title.download-complete": {
"message": "ダウンロード完了"
@@ -63,7 +63,7 @@
"message": "クリックすると更新履歴を表示できます。"
},
"app.update.complete-toast.title": {
"message": "バージョン {version} インストールが正常に完了しました!"
"message": "バージョン {version} が正常にインストールされました!"
},
"app.update.download-update": {
"message": "アップデートをダウンロード"
@@ -93,7 +93,7 @@
"message": "Modrinthユーザーネームを入力..."
},
"friends.add-friend.username.title": {
"message": "あなたのフレンドのModrinthユーザーネームは何ですか?"
"message": "あなたのフレンドのModrinthユーザーは何ですか?"
},
"friends.add-friends-to-share": {
"message": "<link>友達を追加</link>して、彼らが何をしているか見てみよう!"
+14 -14
View File
@@ -1,6 +1,6 @@
{
"app.auth-servers.unreachable.body": {
"message": "Minecraft 인증 서버가 현재 다운되었을 수 있습니다. 인터넷 연결을 확인한 후 나중에 다시 시도하세요."
"message": "Minecraft 인증 서버가 일시적으로 중단되었을 수 있습니다. 인터넷 연결을 확인한 후 나중에 다시 시도하세요."
},
"app.auth-servers.unreachable.header": {
"message": "인증 서버에 연결할 수 없습니다"
@@ -27,7 +27,7 @@
"message": "언어"
},
"app.settings.tabs.privacy": {
"message": "개인정보 보호"
"message": "개인정보"
},
"app.settings.tabs.resource-management": {
"message": "리소스 관리"
@@ -78,7 +78,7 @@
"message": "친구 추가"
},
"friends.action.view-friend-requests": {
"message": "{count} 친구 요청 {count, plural, one {건의} other {건의}}"
"message": "{count} 친구 요청 {count, plural, one {요청} other {요청}}"
},
"friends.add-friend.submit": {
"message": "친구 요청 보내기"
@@ -87,7 +87,7 @@
"message": "친구 추가 중"
},
"friends.add-friend.username.description": {
"message": "마인크래프트 사용자명과 다를 수 있습니다!"
"message": "Minecraft 사용자명과 다를 수 있습니다!"
},
"friends.add-friend.username.placeholder": {
"message": "Modrinth 사용자명 입력..."
@@ -129,7 +129,7 @@
"message": "\"{query}\"와 일치하는 친구가 없습니다"
},
"friends.search-friends-placeholder": {
"message": "친구 검색 중..."
"message": "친구 찾는 중..."
},
"friends.section.heading": {
"message": "{title} - {count}"
@@ -201,22 +201,22 @@
"message": "인스턴스 삭제"
},
"instance.settings.tabs.general.delete.description": {
"message": "기기에서 인스턴스를 완전히 삭제합니다. 월드, 설정, 설치된 모든 콘텐츠가 함께 제됩니다. 주의하세요, 한 번 삭제하면 인스턴스를 복구할 방법은 없습니다."
"message": "기기에서 인스턴스를 완전히 삭제합니다. 세계, 설정, 설치된 모든 콘텐츠가 함께 제됩니다. 주의하세요, 한 번 삭제하면 인스턴스를 복구할 없습니다."
},
"instance.settings.tabs.general.deleting.button": {
"message": "삭제중..."
"message": "삭제 중..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "복제"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "설치중에는 복제할 수 없습니다."
"message": "설치 중에는 복제할 수 없습니다."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "인스턴스 복제"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "인스턴스의 복사본을 생성합니다. 월드, 설정, 모드, 기타 등등도 함께 복사됩니다."
"message": "인스턴스의 복사본을 생성합니다. 세계, 설정, 모드, 기타 등등도 함께 복사됩니다."
},
"instance.settings.tabs.general.edit-icon": {
"message": "아이콘 수정"
@@ -279,7 +279,7 @@
"message": "래퍼"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "Minecraft 실행을 위한 래퍼 명령어 입니다."
"message": "Minecraft 실행을 위한 래퍼 명령어 입니다."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "래퍼 명령어 입력..."
@@ -351,7 +351,7 @@
"message": "모드팩 재설치 중"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "재설치하면 설치 또는 수정된 모든 콘텐츠가 모드팩에서 제공하는 콘텐츠로 초기화되며, 기존 팩에 추가한 모드나 콘텐츠는 모두 제거됩니다. 인스턴스에 변경 사항이 있는 경우 예상치 못한 동작은 해결할 수 있지만, 현재 월드가 추가로 설치된 콘텐츠에 의존하고 있다면 기존 월드가 손상될 수 있습니다."
"message": "재설치하면 설치 또는 수정된 모든 콘텐츠가 모드팩에서 제공하는 콘텐츠로 초기화되며, 기존 팩에 추가한 모드나 콘텐츠는 모두 제거됩니다. 인스턴스에 변경 사항이 있는 경우 예상치 못한 동작은 해결할 수 있지만, 현재 세계가 추가로 설치된 콘텐츠에 의존하고 있다면 기존 세계가 손상될 수 있습니다."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "정말로 이 인스턴스를 다시 설치하시겠습니까?"
@@ -501,10 +501,10 @@
"message": "서버가 응답하지 않음"
},
"instance.worlds.no_server_quick_play": {
"message": "Minecraft 알파 1.0.5 이후 버전에서만 서버에 바로 진입할 수 있습니다."
"message": "Minecraft 알파 1.0.5 이후 버전에서만 서버에 바로 진입할 수 있습니다"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Minecraft 1.20 이후 버전에서만 싱글플레이 세계로 바로 진입할 수 있습니다."
"message": "Minecraft 1.20 이후 버전에서만 싱글플레이 세계로 바로 진입할 수 있습니다"
},
"instance.worlds.play_instance": {
"message": "인스턴스 플레이"
@@ -519,7 +519,7 @@
"message": "인스턴스 보기"
},
"instance.worlds.world_in_use": {
"message": "사용중인 월드"
"message": "사용 중인 세계"
},
"search.filter.locked.instance": {
"message": "인스턴스에서 관리"
@@ -1,6 +1,6 @@
{
"app.auth-servers.unreachable.body": {
"message": "Minecraft verificatie servers zijn misschien offline. Check je internetverbinding en probeer opnieuw later."
"message": "Minecraft verificatie servers zijn mogelijk offline. Check je internetverbinding en probeer opnieuw later."
},
"app.auth-servers.unreachable.header": {
"message": "Authenticatieservers kunnen niet worden bereikt"
@@ -42,7 +42,7 @@
"message": "Modrinth App v{version} is nu beschikbaar! Omdat je nu op een netwerk met datalimiet zit, is de download niet automatisch gestart."
},
"app.update-toast.changelog": {
"message": "Changelog"
"message": "Wijzigingenlogboek"
},
"app.update-toast.download": {
"message": "Download ({size})"
@@ -60,7 +60,7 @@
"message": "Downloaden voltooid"
},
"app.update.complete-toast.text": {
"message": "Klik hier om de changelog te bekijken."
"message": "Klik hier om het wijzigingenlogboek te bekijken."
},
"app.update.complete-toast.title": {
"message": "Versie {version} is succesvol geïnstalleerd!"
@@ -201,7 +201,7 @@
"message": "Verwijder instantie"
},
"instance.settings.tabs.general.delete.description": {
"message": "Verwijdert permanent een instantie van je apparaat, inclusief je werelden, instellingen en alle geïnstalleerde inhoud. Wees voorzichtig, want zodra je een instantie verwijdert, is het niet meer mogelijk om deze te herstellen."
"message": "Verwijdert permanent een instantie van je apparaat, inclusief je werelden, instellingen en alle geïnstalleerde inhoud. Wees voorzichtig, zodra je een instantie verwijdert, is het niet meer mogelijk om deze te herstellen."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Verwijderen..."
@@ -33,7 +33,7 @@
"message": "Zarządzanie zasobami"
},
"app.update-toast.body": {
"message": "Wersja Modrinth App v{version} jest gotowa do pobrania! Odśwież, żeby zaktualizować teraz, albo automatycznie, gdy zamkniesz Modrinth App."
"message": "Wersja Modrinth App v{version} jest gotowa do zainstalowania! Odśwież, żeby zaktualizować teraz, albo automatycznie, gdy zamkniesz Modrinth App."
},
"app.update-toast.body.download-complete": {
"message": "Wersja Modrinth App v{version} została pobrana. Odśwież, żeby zaktualizować teraz, albo automatycznie, gdy zamkniesz Modrinth App."
@@ -252,7 +252,7 @@
"message": "Ganchos de inicio personalizados"
},
"instance.settings.tabs.hooks.description": {
"message": "Ganchos permitem a utilizadores avançados executarem certos comandos de sistema antes e depois de abrir o jogo."
"message": "Ganchos permitem a utilizadores avançados executarem certos comandos de sistema antes e após abrir o jogo."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "Pós-saída"
+68 -2
View File
@@ -1,4 +1,10 @@
{
"app.auth-servers.unreachable.body": {
"message": "Serverele de autentificare Minecraft pot fi indisponibile în acest moment. Verificați conexiunea la internet și încercați din nou mai târziu."
},
"app.auth-servers.unreachable.header": {
"message": "Nu se pot accesa serverele de autentificare"
},
"app.settings.developer-mode-enabled": {
"message": "Modul dezvoltator activat."
},
@@ -17,6 +23,9 @@
"app.settings.tabs.java-installations": {
"message": "Instalări Java"
},
"app.settings.tabs.language": {
"message": "Limbă"
},
"app.settings.tabs.privacy": {
"message": "Confidențialitate"
},
@@ -65,6 +74,63 @@
"app.update.reload-to-update": {
"message": "Reîncarcă pentru a instala actualizarea"
},
"friends.action.add-friend": {
"message": "Adaugă un prieten"
},
"friends.add-friend.submit": {
"message": "Trimite cerere de prietenie"
},
"friends.add-friend.title": {
"message": "Adăugarea unui prieten"
},
"friends.add-friend.username.description": {
"message": "Poate fi diferit de numele lor de utilizator Minecraft!"
},
"friends.add-friend.username.placeholder": {
"message": "Introduceți numele de utilizator Modrinth..."
},
"friends.add-friend.username.title": {
"message": "Care este numele de utilizator Modrinth al prietenului tău?"
},
"friends.add-friends-to-share": {
"message": "<link>Adaugă prieteni</link> pentru a vedea ce joacă!"
},
"friends.friend.cancel-request": {
"message": "Anulează cererea"
},
"friends.friend.remove-friend": {
"message": "Eliminare prieten"
},
"friends.friend.request-sent": {
"message": "Cerere de prietenie trimisă"
},
"friends.friend.view-profile": {
"message": "Vizualizați profilul"
},
"friends.heading": {
"message": "Prieteni"
},
"friends.heading.active": {
"message": "Activ"
},
"friends.heading.offline": {
"message": "Inactiv"
},
"friends.heading.online": {
"message": "Online"
},
"friends.heading.pending": {
"message": "În așteptare"
},
"friends.no-friends-match": {
"message": "Nu există prieteni care să corespundă cu \"{query}”"
},
"friends.search-friends-placeholder": {
"message": "Caută prieteni..."
},
"friends.sign-in-to-add-friends": {
"message": "<link>Conectează-te la un cont Modrinth</link> pentru a adăuga prieteni și a vedea ce joacă!"
},
"instance.add-server.add-and-play": {
"message": "Adaugă și joacă"
},
@@ -432,10 +498,10 @@
"message": "Poți să intri direct pe servere doar pe Minecraft Alpha 1.0.5+"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Poți să intri direct în lumile singleplayer numai pe Minecraft 1.20+"
"message": "Poți să intri direct în lumile de jucător simplu numai pe Minecraft 1.20+"
},
"instance.worlds.play_instance": {
"message": "Joacă instanța"
"message": "Joacă pe instanța"
},
"instance.worlds.type.server": {
"message": "Server"
+10 -10
View File
@@ -90,7 +90,7 @@
"message": "Оно может быть не таким, как в Minecraft!"
},
"friends.add-friend.username.placeholder": {
"message": "Введите имя на Modrinth..."
"message": "Введите имя с Modrinth..."
},
"friends.add-friend.username.title": {
"message": "Какое имя у друга на Modrinth?"
@@ -114,7 +114,7 @@
"message": "Друзья"
},
"friends.heading.active": {
"message": "Активно"
"message": "В игре"
},
"friends.heading.offline": {
"message": "Не в сети"
@@ -123,7 +123,7 @@
"message": "В сети"
},
"friends.heading.pending": {
"message": "В ожидании"
"message": "В ожидании"
},
"friends.no-friends-match": {
"message": "Нет друзей по запросу «{query}»"
@@ -219,16 +219,16 @@
"message": "Создаёт копию сборки, включая миры, настройки, моды и т. д."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Изменить значок"
"message": "Изменить иконку"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Удалить значок"
"message": "Удалить иконку"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "Заменить значок"
"message": "Заменить иконку"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "Выбрать значок"
"message": "Выбрать иконку"
},
"instance.settings.tabs.general.library-groups": {
"message": "Группировка"
@@ -249,7 +249,7 @@
"message": "Команды запуска"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Изменение команд запуска"
"message": "Переопределение команд запуска"
},
"instance.settings.tabs.hooks.description": {
"message": "Позволяет опытным пользователям задать системные команды, выполняемые до и после запуска игры."
@@ -444,7 +444,7 @@
"message": "Окно"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "Изменение настроек окна"
"message": "Переопределение настроек окна"
},
"instance.settings.tabs.window.fullscreen": {
"message": "Полноэкранный режим"
@@ -498,7 +498,7 @@
"message": "Сервер несовместим"
},
"instance.worlds.no_contact": {
"message": "Не удалось связаться с сервером"
"message": "Не удалось связаться с сервером"
},
"instance.worlds.no_server_quick_play": {
"message": "Подключаться к серверам напрямую можно только в Minecraft Alpha 1.0.5 и выше"
+16 -16
View File
@@ -1,6 +1,6 @@
{
"app.auth-servers.unreachable.body": {
"message": "Minecraft doğrulama sunucuları çökmüş olabilir. İnternet bağlantını kontrol et ve daha sonra tekrar dene."
"message": "Minecraft doğrulama sunucuları kapalı olabilir. İnternet bağlantını kontrol et ve daha sonra tekrar dene."
},
"app.auth-servers.unreachable.header": {
"message": "Doğrulama sunucularına erişilemedi"
@@ -33,7 +33,7 @@
"message": "Kaynak yönetimi"
},
"app.update-toast.body": {
"message": "Modrinth App v{version} kurulmaya hazır! Şimdi güncellemek için uygulamayı yeniden yükle ya da sen Modrinth App'i kapatınca otomatik olarak güncellensin."
"message": "Modrinth App v{version} kuruluma hazır! Şimdi güncellemek için uygulamayı yeniden yükle ya da sen Modrinth App'i kapatınca otomatik olarak güncellensin."
},
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version} indirildi. Şimdi güncellemek için uygulamayı yeniden yükle ya da Modrinth App'i kapatınca otomatik olarak güncellensin."
@@ -60,7 +60,7 @@
"message": "Yükleme tamamlandı"
},
"app.update.complete-toast.text": {
"message": "Değişiklikleri görüntülemek için buraya tıklayın."
"message": "Değişiklik günlüğü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!"
@@ -84,10 +84,10 @@
"message": "Arkadaşlık isteği gönder"
},
"friends.add-friend.title": {
"message": "Bir arkadaş ekleme"
"message": "Arkadaş ekleme"
},
"friends.add-friend.username.description": {
"message": "Onun Minecraft kullanıcı adından farklı olabilir!"
"message": "Minecraft kullanıcı adlarından farklı olabilir!"
},
"friends.add-friend.username.placeholder": {
"message": "Modrinth kullanıcı adını girin..."
@@ -135,7 +135,7 @@
"message": "{title} - {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>Modrinth hesabına giriş yaparak</link> arkadaş ekle ve ne oynadıklarını gör!"
"message": "Arkadaş eklemek ve ne oynadıklarını görmek için bir <link>Modrinth hesabına giriş yap</link>!"
},
"instance.add-server.add-and-play": {
"message": "Ekle ve oyna"
@@ -144,10 +144,10 @@
"message": "Sunucu ekle"
},
"instance.add-server.resource-pack.disabled": {
"message": "Kapalı"
"message": "Devre dışı"
},
"instance.add-server.resource-pack.enabled": {
"message": "Açık"
"message": "Etkin"
},
"instance.add-server.resource-pack.prompt": {
"message": "Sor"
@@ -159,7 +159,7 @@
"message": "Sunucuyu düzenle"
},
"instance.edit-world.hide-from-home": {
"message": "Ana Sayfadan gizle"
"message": "Ana sayfada gizle"
},
"instance.edit-world.name": {
"message": "Dünya Adı"
@@ -246,13 +246,13 @@
"message": "Ad"
},
"instance.settings.tabs.hooks": {
"message": "Başlatma bağları"
"message": "Başlatma kancaları"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Özel başlantı bağları"
"message": "Özel başlatma kancası"
},
"instance.settings.tabs.hooks.description": {
"message": "Bağlar kullanıcılara oyunu başlatmadan önce veya başlattıktan sonra sistem komutları çalıştırmalarını sağlar."
"message": "Kancalar gelişmiş kullanıcıların oyunu başlattıktan önce ve sonra belirli sistem komutları çalıştırmasını sağlar."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "Çıkış-sonrası"
@@ -408,7 +408,7 @@
"message": "(bilinmeyen sürüm)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Kurulum bağını koparr"
"message": "Kurulum bağlantısını kes"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Devam edersen bu kurulumu geri bağlayamazsın. Mod paketi güncellemeleri almazsın ve bu kurulum normal kuruluma dönüşür."
@@ -474,7 +474,7 @@
"message": "Ayarlar"
},
"instance.worlds.a_minecraft_server": {
"message": "Bir Minecraft Sunucusu"
"message": "Minecraft Sunucusu"
},
"instance.worlds.cant_connect": {
"message": "Sunucuya bağlanılamıyor"
@@ -483,7 +483,7 @@
"message": "Adresi kopyala"
},
"instance.worlds.dont_show_on_home": {
"message": "Ana Sayfada gösterme"
"message": "Ana sayfada gösterme"
},
"instance.worlds.filter.available": {
"message": "Kullanılabilir"
@@ -531,6 +531,6 @@
"message": "Yükleyici veren kurulumlar"
},
"search.filter.locked.instance.sync": {
"message": "Kurulum ile senkronize et"
"message": "Kurulumla senkronize et"
}
}
+40 -40
View File
@@ -1,6 +1,6 @@
{
"app.auth-servers.unreachable.body": {
"message": "Сервери автентифікації Minecraft можливо зараз не працюють. Перевірте з’єднання з Інтернетом та спробуйте пізніше."
"message": "Сервери автентифікації Minecraft можуть зараз не працювати. Перевірте з’єднання з інтернетом та спробуйте пізніше."
},
"app.auth-servers.unreachable.header": {
"message": "Не вдається зв’язатися зі серверами автентифікації"
@@ -9,13 +9,13 @@
"message": "Увімкнено режим розробника."
},
"app.settings.downloading": {
"message": "Завантаження v{version}"
"message": "Завантаження версії {version}"
},
"app.settings.tabs.appearance": {
"message": "Вигляд"
},
"app.settings.tabs.default-instance-options": {
"message": "Налаштування усталеного профілю"
"message": "Усталені налашт. профілю"
},
"app.settings.tabs.feature-flags": {
"message": "Спеціальні функції"
@@ -33,13 +33,13 @@
"message": "Керування ресурсами"
},
"app.update-toast.body": {
"message": "Modrinth App v{version} готова до встановлення! Перезапустіть, щоб оновити зараз. Або, оновлення буде здійснено автоматично, коли закриєте Modrinth App."
"message": "Modrinth App v{version} готовий до встановлення! Перезапустіть, щоб оновити зараз. Або, оновлення буде здійснено автоматично, коли закриєте Modrinth App."
},
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version} уже завантажилась. Перезапустіть, щоб оновити зараз. Або, оновлення буде здійснено автоматично, коли закриєте Modrinth App."
"message": "Версія {version} Modrinth App уже завантажилася. Перезапустіть, щоб оновити зараз, або дозвольте оновитися автоматично, коли закриватимете Modrinth App."
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} доступна зараз! Оскільки ви на лімітному з’єднанні, ми не завантажили її автоматично."
"message": "Версія {version} Modrinth App доступна для завантаження! Оскільки ви на лімітному з’єднанні, ми не завантажили її автоматично."
},
"app.update-toast.changelog": {
"message": "Журнал змін"
@@ -54,13 +54,13 @@
"message": "Перезапустити"
},
"app.update-toast.title": {
"message": "Оновлення доступне"
"message": "Доступне оновлення"
},
"app.update-toast.title.download-complete": {
"message": "Завантаження завершено"
},
"app.update.complete-toast.text": {
"message": "Натисніть тут, щоб побачити список змін."
"message": "Натисніть тут, щоб побачити журнал змін."
},
"app.update.complete-toast.title": {
"message": "Версію {version} успішно встановлено!"
@@ -72,7 +72,7 @@
"message": "Завантаження оновлення ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Перезавантажте, щоб установити оновлення"
"message": "Перезавантажте, аби встановити оновлення"
},
"friends.action.add-friend": {
"message": "Додати друга"
@@ -90,13 +90,13 @@
"message": "Може відрізнятися від його або її імені користувача Minecraft!"
},
"friends.add-friend.username.placeholder": {
"message": "Уведіть ім’я користувача Modrinth…"
"message": "Уведіть ім’я користувача…"
},
"friends.add-friend.username.title": {
"message": "Яке ім’я користувача Modrinth у вашого друга?"
},
"friends.add-friends-to-share": {
"message": "<link>Додайте друзів</link>, щоб бачити, у що вони грають!"
"message": "<link>Додайте друзів</link>, аби бачити, у що вони грають!"
},
"friends.friend.cancel-request": {
"message": "Скасувати запит"
@@ -126,7 +126,7 @@
"message": "Очікується"
},
"friends.no-friends-match": {
"message": "Немає друзів, котрі збігаються з «{query}»"
"message": "Немає друзів, які збігаються з «{query}»"
},
"friends.search-friends-placeholder": {
"message": "Шукати друзів…"
@@ -156,7 +156,7 @@
"message": "Додати сервер"
},
"instance.edit-server.title": {
"message": "Змінити сервер"
"message": "Редагувати сервер"
},
"instance.edit-world.hide-from-home": {
"message": "Не показувати на головній сторінці"
@@ -177,7 +177,7 @@
"message": "Вимкнені проєкти"
},
"instance.filter.updates-available": {
"message": "Наявні оновлення"
"message": "Оновлення доступні"
},
"instance.server-modal.address": {
"message": "Адреса"
@@ -195,13 +195,13 @@
"message": "Загальні"
},
"instance.settings.tabs.general.delete": {
"message": "Видалити примірник"
"message": "Видалити профіль"
},
"instance.settings.tabs.general.delete.button": {
"message": "Видалити профіль"
},
"instance.settings.tabs.general.delete.description": {
"message": "Назавжди видаляє профіль з вашого пристрою, включно з вашими світами, налаштуваннями та всім встановленим контентом.\nБудьте обережні, після видалення, відновити профіль буде неможливо."
"message": "Назавжди видаляє профіль з вашого пристрою, включно з вашими світами, налаштуваннями та всім установленим умістом. Будьте обережні, після видалення, відновити профіль буде неможливо."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Видалення…"
@@ -210,13 +210,13 @@
"message": "Клонувати"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "Неможливо клонувати під час встановлення."
"message": "Неможливо клонувати під час установлення."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Клонувати профіль"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Створює копію інсталяції, включно зі світами, налаштуваннями, модами тощо."
"message": "Створює копію профілю, включно зі світами, налаштуваннями, модами тощо."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Редагувати значок"
@@ -228,7 +228,7 @@
"message": "Замінити значок"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "Обрати значок"
"message": "Вибрати значок"
},
"instance.settings.tabs.general.library-groups": {
"message": "Групи бібліотеки"
@@ -270,13 +270,13 @@
"message": "Запускається перед відкриттям профілю."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Уведіть команду, що виконується перед запуском..."
"message": "Уведіть команду, що виконуватиметься перед запуском"
},
"instance.settings.tabs.hooks.title": {
"message": "Гуки запуску гри"
},
"instance.settings.tabs.hooks.wrapper": {
"message": "Обгортач"
"message": "Під час гри"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "Обгортальна команда для запуску Minecraft."
@@ -285,10 +285,10 @@
"message": "Уведіть обгортальну команду…"
},
"instance.settings.tabs.installation": {
"message": "Інсталяція"
"message": "Установлення"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} для Minecraft {game_version} вже встановлена"
"message": "{platform} {version} для Minecraft {game_version} вже встановлено"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Ванільна {game_version} вже встановлена"
@@ -324,7 +324,7 @@
"message": "Установити"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Відбувається встановлення"
"message": "Установлення триває"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Версія {loader}"
@@ -339,7 +339,7 @@
"message": "{loader} недоступний для Minecraft {version}. Спробуйте інший завантажувач модів."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Цей екземпляр пов’язана з пакетом модів, проте сам пакет модів не вдалося знайти на Modrinth."
"message": "Цей профіль пов’язаний зі збіркою, проте саму збірку не вдалося знайти на Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Платформа"
@@ -351,13 +351,13 @@
"message": "Перевстановлення збірки"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Перевстановлення скине увесь доданий або модифікований уміст до наданого пакета модів, прибираючи будь-які, додатково встановлені вами моди чи вміст.\nЯкщо ви змінювали екземпляр, це може виправити непередбачувану поведінку, однак, якщо ваші світи залежать від додаткового вмісту, це може зламати ці світи."
"message": "Перевстановлення скине ввесь доданий або модифікований уміст до наданого збіркою, прибираючи будь-які додатково встановлені вами моди чи вміст. Якщо ви змінювали профіль, це може виправити непередбачувану поведінку, однак, якщо ваші світи залежать від додаткового вмісту, світи можуть пошкодитися."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Ви впевнені, що хочете перевстановити цей профіль?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Скидає вміст інсталяції до початкового стану, прибираючи будь-які моди чи вміст, що було додано поверх оригінального пакета модів."
"message": "Скидає вміст профілю до початкового стану, прибираючи будь-які моди чи вміст, що було додано поверх оригінальної збірки."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Перевстановити збірку"
@@ -369,13 +369,13 @@
"message": "Лагодження"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Відновлення перевстановлює залежності Minecraft та перевіряє їх на наявність пошкоджень. Це може розв’язати проблеми, якщо ваша гра не запускається через помилки запускача, але не розв’яже проблеми або збої, пов’язані зі встановленими модифікаціями."
"message": "Відновлення перевстановлює залежності Minecraft та перевіряє їх на наявність пошкоджень. Це може розв’язати проблеми, якщо ваша гра не запускається через помилки запускача, але не розв’яже проблеми або збої, пов’язані зі встановленими модами."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Відновити профіль?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Лагодження в процесі"
"message": "Лагодження триває"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Скинути до поточного"
@@ -399,7 +399,7 @@
"message": "Неможливо {action} під час установлення"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Неможливо {action} без з’єднання з Інтернетом"
"message": "Неможливо {action} без з’єднання з інтернетом"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Неможливо {action} під час лагодження"
@@ -411,13 +411,13 @@
"message": "Відв’язати профіль"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Якщо ви продовжите, ви не зможете повторно підв’язати його без створення повністю нової інсталяції. Ви більше не будете отримувати оновлення пакета модів та вона стане звичайною."
"message": "Якщо ви продовжите, ви не зможете повторно підв’язати його без створення повністю нового профілю. Ви більше не будете отримувати оновлення збірки та цей профіль стане звичайним."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Ви впевнені, що хочете відв’язати цей екземпляр?"
"message": "Ви впевнені, що хочете відв’язати цей профіль?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Цей профіль пов’язаний з пакетом модів, тобто, не можна оновлювати моди та не можна змінювати завантажувач чи версію Minecraft. Відв’язання призведе до остаточного від’єднання цієї інсталяції від пакета модів."
"message": "Цей профіль пов’язаний зі збіркою, тобто, не можна оновлювати моди та не можна змінювати завантажувач чи версію Minecraft. Відв’язання призведе до остаточного від’єднання цього профілю від збірки."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Відв’язати від збірки"
@@ -435,7 +435,7 @@
"message": "Аргументи Java"
},
"instance.settings.tabs.java.java-installation": {
"message": "Установлення Java"
"message": "Інсталяції Java"
},
"instance.settings.tabs.java.java-memory": {
"message": "Виділена пам’ять"
@@ -450,7 +450,7 @@
"message": "Повний екран"
},
"instance.settings.tabs.window.fullscreen.description": {
"message": "Змусити гру запускатися на повний екран (використовуючи options.txt)."
"message": "Запускати гру в повноекранному режимі (за допомогою options.txt)."
},
"instance.settings.tabs.window.height": {
"message": "Висота"
@@ -483,7 +483,7 @@
"message": "Скопіювати адресу"
},
"instance.worlds.dont_show_on_home": {
"message": "Не показувати на Головній"
"message": "Не показувати на головній"
},
"instance.worlds.filter.available": {
"message": "Доступно"
@@ -495,10 +495,10 @@
"message": "Режим гардкору"
},
"instance.worlds.incompatible_server": {
"message": "Несумісний сервер"
"message": "Сервер несумісний"
},
"instance.worlds.no_contact": {
"message": "Не вдалося зв’язатися з сервером"
"message": "Не вдалося зв’язатися зі сервером"
},
"instance.worlds.no_server_quick_play": {
"message": "Запускатися у сервери напряму можливо лише починаючи з версії Minecraft Alpha 1.0.5"
@@ -519,7 +519,7 @@
"message": "Переглянути профіль"
},
"instance.worlds.world_in_use": {
"message": "Світ зараз використовується"
"message": "Світ наразі використовується"
},
"search.filter.locked.instance": {
"message": "Надано профілем"
@@ -528,7 +528,7 @@
"message": "Версія гри надана профілем"
},
"search.filter.locked.instance-loader.title": {
"message": "Запускач наданий профілем"
"message": "Завантажувач наданий профілем"
},
"search.filter.locked.instance.sync": {
"message": "Синхронізувати з профілем"
@@ -78,7 +78,7 @@
"message": "Thêm một người bạn"
},
"friends.action.view-friend-requests": {
"message": "{count} yêu cầu kết bạn"
"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"
+22 -22
View File
@@ -36,7 +36,7 @@
"message": "Modrinth App v{version} 更新已就绪!立即重启更新,或退出时自动安装。"
},
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version} 下载完成。立即重启更新,或退出时自动安装。"
"message": "Modrinth App v{version} 已经完成下载。现在重新启动以更新,或在关闭 Modrinth App 时自动更新。"
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} 现已发布!由于你正在使用按流量计费的网络,该更新未自动下载。"
@@ -63,7 +63,7 @@
"message": "点击此处查看更新日志。"
},
"app.update.complete-toast.title": {
"message": "版本{version} 已成功安装!"
"message": "版本 {version} 已成功安装!"
},
"app.update.download-update": {
"message": "下载更新"
@@ -96,7 +96,7 @@
"message": "好友的 Modrinth 用户名是什么?"
},
"friends.add-friends-to-share": {
"message": "<link>添加好友</link>看看他们在玩什么!"
"message": "<link>添加好友</link>看看他们在玩什么!"
},
"friends.friend.cancel-request": {
"message": "取消请求"
@@ -129,7 +129,7 @@
"message": "没有对应名字“{query}”的好友"
},
"friends.search-friends-placeholder": {
"message": "搜索好友…"
"message": "搜索好友…"
},
"friends.section.heading": {
"message": "{title} - {count}"
@@ -165,7 +165,7 @@
"message": "名称"
},
"instance.edit-world.placeholder-name": {
"message": "Minecraft 存档"
"message": "Minecraft 世界"
},
"instance.edit-world.reset-icon": {
"message": "重置图标"
@@ -195,10 +195,10 @@
"message": "通用"
},
"instance.settings.tabs.general.delete": {
"message": "删除实例"
"message": "删除实例"
},
"instance.settings.tabs.general.delete.button": {
"message": "删除实例"
"message": "删除实例"
},
"instance.settings.tabs.general.delete.description": {
"message": "将从设备中永久删除该实例,包括所有存档、配置文件及已安装内容。此操作不可撤销,请谨慎操作。"
@@ -246,13 +246,13 @@
"message": "名称"
},
"instance.settings.tabs.hooks": {
"message": "启动钩子"
"message": "启动Hooks"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "自定义启动钩子"
"message": "自定义启动Hooks"
},
"instance.settings.tabs.hooks.description": {
"message": "钩子允许高级用户在启动游戏前后运行特定的系统命令。"
"message": "Hooks允许高级用户在启动游戏前后运行特定的系统命令。"
},
"instance.settings.tabs.hooks.post-exit": {
"message": "退出后"
@@ -276,13 +276,13 @@
"message": "游戏启动钩子"
},
"instance.settings.tabs.hooks.wrapper": {
"message": "包装命令"
"message": "包装命令"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "用于启动 Minecraft 的包装命令。"
"message": "用于启动 Minecraft 的包装命令。"
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "输入包装命令……"
"message": "输入包装命令……"
},
"instance.settings.tabs.installation": {
"message": "安装"
@@ -351,13 +351,13 @@
"message": "正在重新安装整合包"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "重新安装实例将重置所有已安装或修改的内容,恢复到整合包的初始状态,移除在原来的安装内容上另的所有模组或内容。该操作有可能修复因实例更改导致的异常,但你的世界目前依赖额外安装的内容的操作,此举可能会损坏现有世界。"
"message": "重新安装实例将重置所有已安装或修改的内容,恢复到整合包的初始状态,移除在原来的安装内容上另外添加的的所有模组或内容。该操作有可能修复因实例更改导致的异常,但如果你的世界依赖已安装的额外内容,此举可能会损坏现有世界。"
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "你确定要重新安装该实例吗?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "重置实例至原始状态,移除你在原整合包上添加的所有模组及其数据。"
"message": "重置实例至原始状态,移除你在原整合包上添加的所有模组及内容。"
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "重新安装整合包"
@@ -369,19 +369,19 @@
"message": "修复中"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "修复实例时,会将重新安装 Minecraft 依赖,并检查文件完整性。该操作可能解决因启动器错误导致的启动失败问题,但不能解决由模组引发的问题崩溃。"
"message": "修复实例将重新安装 Minecraft 依赖,并检查文件完整性。该操作可能解决因启动器错误导致的启动失败问题,但不能解决由模组引发的问题崩溃。"
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "确定修复该实例吗?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "修复中,请闭目养神,少安毋躁"
"message": "正在修复"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "重置为当前版本"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "列出所有版本"
"message": "显示所有版本"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "切换版本"
@@ -405,7 +405,7 @@
"message": "修复时无法{action}"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "嗯?未知版本)"
"message": "(未知版本)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "解除关联实例"
@@ -438,10 +438,10 @@
"message": "Java 安装路径"
},
"instance.settings.tabs.java.java-memory": {
"message": "分配内存"
"message": "内存分配"
},
"instance.settings.tabs.window": {
"message": "窗口"
"message": "游戏窗口"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "自定义窗口设置"
@@ -510,7 +510,7 @@
"message": "游玩实例"
},
"instance.worlds.type.server": {
"message": "服务"
"message": "服务"
},
"instance.worlds.type.singleplayer": {
"message": "单人游戏"
@@ -135,7 +135,7 @@
"message": "{title} - {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>登入 Modrinth 帳號</link>即可新增好友並查看對方正在玩什麼!"
"message": "<link>登入 Modrinth 帳號</link>即可新增好友並查看他們正在玩什麼!"
},
"instance.add-server.add-and-play": {
"message": "新增並遊玩"
+2 -2
View File
@@ -38,10 +38,10 @@ pub async fn authenticate_run() -> theseus::Result<Credentials> {
async fn main() -> theseus::Result<()> {
println!("Starting.");
let _log_guard = theseus::start_logger();
let _log_guard = theseus::start_logger("ModrinthApp");
// Initialize state
State::init().await?;
State::init("ModrinthApp".to_owned()).await?;
let worlds = get_recent_worlds(4, EnumSet::all()).await?;
for world in worlds {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 21 KiB

+4 -1
View File
@@ -29,6 +29,9 @@ pub async fn settings_set(settings: Settings) -> Result<()> {
#[tauri::command]
pub async fn cancel_directory_change() -> Result<()> {
settings::cancel_directory_change().await?;
let state = State::get().await?;
let identifier = &state.app_identifier;
settings::cancel_directory_change(identifier).await?;
Ok(())
}
+6 -4
View File
@@ -107,10 +107,12 @@ pub async fn open_path<R: Runtime>(app: tauri::AppHandle<R>, path: PathBuf) {
#[tauri::command]
pub async fn show_launcher_logs_folder<R: Runtime>(app: tauri::AppHandle<R>) {
let path = DirectoryInfo::launcher_logs_dir().unwrap_or_default();
// failure to get folder just opens filesystem
// (ie: if in debug mode only and launcher_logs never created)
open_path(app, path).await;
if let Some(d) = DirectoryInfo::global_handle_if_ready() {
let path = d.launcher_logs_dir().unwrap_or_default();
// failure to get folder just opens filesystem
// (ie: if in debug mode only and launcher_logs never created)
open_path(app, path).await;
}
}
// Get opening command
+6 -3
View File
@@ -28,7 +28,7 @@ async fn initialize_state(app: tauri::AppHandle) -> api::Result<()> {
theseus::EventState::init(app.clone()).await?;
tracing::info!("Initializing app state...");
State::init().await?;
State::init(app.config().identifier.clone()).await?;
let state = State::get().await?;
app.asset_protocol_scope()
@@ -110,7 +110,10 @@ fn main() {
RUST_LOG="theseus=trace" {run command}
*/
let _log_guard = theseus::start_logger();
let tauri_context = tauri::generate_context!();
let _log_guard = theseus::start_logger(&tauri_context.config().identifier);
tracing::info!("Initialized tracing subscriber. Loading Modrinth App!");
@@ -243,7 +246,7 @@ fn main() {
]);
tracing::info!("Initializing app...");
let app = builder.build(tauri::generate_context!());
let app = builder.build(tauri_context);
match app {
Ok(app) => {
+1 -1
View File
@@ -87,7 +87,7 @@
"capabilities": ["ads", "core", "plugins"],
"csp": {
"default-src": "'self' customprotocol: asset:",
"connect-src": "ipc: http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.posthog.com https://*.sentry.io https://api.mclo.gs 'self' data: blob:",
"connect-src": "ipc: http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.posthog.com https://*.sentry.io https://api.mclo.gs http://textures.minecraft.net https://textures.minecraft.net 'self' data: blob:",
"font-src": ["https://cdn-raw.modrinth.com/fonts/"],
"img-src": "https: 'unsafe-inline' 'self' asset: http://asset.localhost http://textures.minecraft.net blob: data:",
"style-src": "'unsafe-inline' 'self'",
+11
View File
@@ -166,6 +166,17 @@ export default defineNuxtConfig({
await fs.writeFile('./src/generated/state.json', JSON.stringify(state))
// throw if errors and building for prod (preview & staging allowed to have errors)
if (
process.env.BUILD_ENV === 'production' &&
process.env.PREVIEW !== 'true' &&
generatedState.errors.length > 0
) {
throw new Error(
`Production build failed: State generation encountered errors. Error codes: ${JSON.stringify(generatedState.errors)}; API URL: ${API_URL}`,
)
}
console.log('Tags generated!')
const robotsContent =
+2 -2
View File
@@ -11,8 +11,8 @@
"lint": "eslint . && prettier --check .",
"fix": "eslint . --fix && prettier --write .",
"intl:extract": "formatjs extract \"src/{components,composables,layouts,middleware,modules,pages,plugins,utils}/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" \"src/error.vue\" --ignore \"**/*.d.ts\" --ignore node_modules --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
"cf-deploy": "pnpm run build && wrangler deploy --env preview",
"cf-dev": "pnpm run build && wrangler dev --env preview",
"cf-deploy": "pnpm run build && wrangler deploy --env staging",
"cf-dev": "pnpm run build && wrangler dev --env staging",
"cf-typegen": "wrangler types"
},
"devDependencies": {
@@ -223,10 +223,7 @@
:where(input) {
box-sizing: border-box;
max-height: 40px;
&:not(.stylized-toggle) {
max-width: 100%;
}
max-width: 100%;
}
:where(.adjacent-input, &.adjacent-input) {
@@ -271,10 +268,6 @@
&:not(&.small) {
flex-direction: column;
align-items: flex-start;
.stylized-toggle {
flex-basis: 0;
}
}
}
}
@@ -650,64 +643,6 @@ tr.button-transparent {
}
}
.switch {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
-webkit-tap-highlight-color: transparent;
cursor: pointer;
&:focus {
//outline: 0; Bad for accessibility
}
}
.stylized-toggle {
@extend .button-base;
box-sizing: content-box;
min-height: 32px;
height: 32px;
width: 52px;
max-width: 52px;
border-radius: var(--size-rounded-max);
display: inline-block;
position: relative;
margin: 0;
transition: all 0.2s ease;
background: var(--color-button-bg);
&:after {
content: '';
position: absolute;
top: 7px;
left: 7px;
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--color-toggle-handle);
transition: all 0.2s cubic-bezier(0.5, 0.1, 0.75, 1.35);
outline: 2px solid transparent;
@media (prefers-reduced-motion) {
transition: none;
}
}
&:checked {
background-color: var(--color-brand);
&:after {
transform: translatex(20px);
background: var(--color-brand-inverted);
}
}
&:hover &:focus {
background: var(--color-button-bg);
}
}
.textarea-wrapper {
display: flex;
flex-direction: column;
@@ -60,8 +60,6 @@ html {
--color-button-bg-active: #c3c6cb;
--color-button-text-active: var(--color-button-text-hover);
--color-toggle-handle: var(--color-icon);
--color-dropdown-bg: var(--color-button-bg);
--color-dropdown-text: var(--color-button-text);
@@ -177,8 +175,6 @@ html {
--color-button-bg-active: #616570;
--color-button-text-active: var(--color-button-text-hover);
--color-toggle-handle: var(--color-button-text);
--color-dropdown-bg: var(--color-button-bg);
--color-dropdown-text: var(--color-button-text);
+186 -139
View File
@@ -2,71 +2,54 @@
<nav
ref="scrollContainer"
class="experimental-styles-within relative flex w-fit overflow-x-auto rounded-full bg-bg-raised p-1 text-sm font-bold"
:class="[mode === 'navigation' ? 'card-shadow' : undefined]"
:class="{ 'card-shadow': mode === 'navigation' }"
>
<template v-if="mode === 'navigation'">
<NuxtLink
v-for="(link, index) in filteredLinks"
v-show="link.shown === undefined ? true : link.shown"
v-show="link.shown ?? true"
:key="link.href"
ref="tabLinkElements"
:to="query ? (link.href ? `?${query}=${link.href}` : '?') : link.href"
class="button-animation z-[1] flex flex-row items-center gap-2 px-4 py-2 focus:rounded-full"
:class="getSSRFallbackClasses(index)"
@mouseenter="link.onHover?.()"
@focus="link.onHover?.()"
>
<component
:is="link.icon"
v-if="link.icon"
class="size-5"
:class="{
'text-brand': currentActiveIndex === index && !subpageSelected,
'text-secondary': currentActiveIndex !== index || subpageSelected,
}"
/>
<span class="text-nowrap text-contrast">{{ link.label }}</span>
<component :is="link.icon" v-if="link.icon" class="size-5" :class="getIconClasses(index)" />
<span class="text-nowrap" :class="getLabelClasses(index)">
{{ link.label }}
</span>
</NuxtLink>
</template>
<template v-else>
<div
v-for="(link, index) in filteredLinks"
v-show="link.shown === undefined ? true : link.shown"
v-show="link.shown ?? true"
:key="link.href"
ref="tabLinkElements"
class="button-animation z-[1] flex flex-row items-center gap-2 px-4 py-2 hover:cursor-pointer focus:rounded-full"
:class="getSSRFallbackClasses(index)"
@click="emit('tabClick', index, link)"
>
<component
:is="link.icon"
v-if="link.icon"
class="size-5"
:class="{
'text-brand': currentActiveIndex === index && !subpageSelected,
'text-secondary': currentActiveIndex !== index || subpageSelected,
}"
/>
<span
class="text-nowrap"
:class="{
'text-brand': currentActiveIndex === index && !subpageSelected,
'text-contrast': currentActiveIndex !== index || subpageSelected,
}"
>{{ link.label }}</span
>
<component :is="link.icon" v-if="link.icon" class="size-5" :class="getIconClasses(index)" />
<span class="text-nowrap" :class="getLabelClasses(index)">
{{ link.label }}
</span>
</div>
</template>
<!-- Animated slider background -->
<div
:class="`navtabs-transition pointer-events-none absolute h-[calc(100%-0.5rem)] overflow-hidden rounded-full p-1 ${
subpageSelected ? 'bg-button-bg' : 'bg-button-bgSelected'
}`"
:style="{
left: sliderLeftPx,
top: sliderTopPx,
right: sliderRightPx,
bottom: sliderBottomPx,
opacity:
sliderLeft === 4 && sliderLeft === sliderRight ? 0 : currentActiveIndex === -1 ? 0 : 1,
}"
class="pointer-events-none absolute h-[calc(100%-0.5rem)] overflow-hidden rounded-full p-1"
:class="[
subpageSelected ? 'bg-button-bg' : 'bg-button-bgSelected',
{ 'navtabs-transition': transitionsEnabled },
]"
:style="sliderStyle"
aria-hidden="true"
></div>
/>
</nav>
</template>
@@ -82,6 +65,7 @@ interface Tab {
shown?: boolean
icon?: Component
subpages?: string[]
onHover?: () => void
}
const props = withDefaults(
@@ -102,124 +86,194 @@ const emit = defineEmits<{
tabClick: [index: number, tab: Tab]
}>()
// DOM refs
const scrollContainer = ref<HTMLElement | null>(null)
const tabLinkElements = ref<HTMLElement[]>()
// Slider pos state
const sliderLeft = ref(4)
const sliderTop = ref(4)
const sliderRight = ref(4)
const sliderBottom = ref(4)
// active tab state
const currentActiveIndex = ref(-1)
const subpageSelected = ref(false)
const filteredLinks = computed(() =>
props.links.filter((x) => (x.shown === undefined ? true : x.shown)),
// SSR state
const sliderReady = ref(false) // Slider is positioned and should be visible
const transitionsEnabled = ref(false) // CSS transitions should apply (after first paint)
const filteredLinks = computed(() => props.links.filter((link) => link.shown ?? true))
const sliderStyle = computed(() => ({
left: `${sliderLeft.value}px`,
top: `${sliderTop.value}px`,
right: `${sliderRight.value}px`,
bottom: `${sliderBottom.value}px`,
opacity: sliderReady.value && currentActiveIndex.value !== -1 ? 1 : 0,
}))
const isActiveAndNotSubpage = computed(
() => (index: number) => currentActiveIndex.value === index && !subpageSelected.value,
)
const sliderLeftPx = computed(() => `${sliderLeft.value}px`)
const sliderTopPx = computed(() => `${sliderTop.value}px`)
const sliderRightPx = computed(() => `${sliderRight.value}px`)
const sliderBottomPx = computed(() => `${sliderBottom.value}px`)
const tabLinkElements = ref()
function getSSRFallbackClasses(index: number) {
if (sliderReady.value) return {}
if (currentActiveIndex.value !== index) return {}
function pickLink() {
let index = -1
subpageSelected.value = false
return {
'rounded-full': true,
'bg-button-bgSelected': !subpageSelected.value,
'bg-button-bg': subpageSelected.value,
}
}
function getIconClasses(index: number) {
return {
'text-button-textSelected': isActiveAndNotSubpage.value(index),
'text-secondary': !isActiveAndNotSubpage.value(index),
}
}
function getLabelClasses(index: number) {
return {
'text-button-textSelected': isActiveAndNotSubpage.value(index),
'text-contrast': !isActiveAndNotSubpage.value(index),
}
}
function computeActiveIndex(): { index: number; isSubpage: boolean } {
if (props.mode === 'local' && props.activeIndex !== undefined) {
index = Math.min(props.activeIndex, filteredLinks.value.length - 1)
} else {
for (let i = filteredLinks.value.length - 1; i >= 0; i--) {
const link = filteredLinks.value[i]
if (props.query) {
if (route.query[props.query] === link.href || (!route.query[props.query] && !link.href)) {
index = i
break
}
} else if (decodeURIComponent(route.path) === link.href) {
index = i
break
} else if (
decodeURIComponent(route.path).includes(link.href) ||
(link.subpages &&
link.subpages.some((subpage) => decodeURIComponent(route.path).includes(subpage)))
) {
index = i
subpageSelected.value = true
break
}
return {
index: Math.min(props.activeIndex, filteredLinks.value.length - 1),
isSubpage: false,
}
}
currentActiveIndex.value = index
for (let i = filteredLinks.value.length - 1; i >= 0; i--) {
const link = filteredLinks.value[i]
const decodedPath = decodeURIComponent(route.path)
if (currentActiveIndex.value !== -1) {
nextTick(() => startAnimation())
// Query-based matching
if (props.query) {
const queryValue = route.query[props.query]
if (queryValue === link.href || (!queryValue && !link.href)) {
return { index: i, isSubpage: false }
}
continue
}
// Exact path match
if (decodedPath === link.href) {
return { index: i, isSubpage: false }
}
// Subpage match
const isSubpageMatch =
decodedPath.includes(link.href) ||
link.subpages?.some((subpage) => decodedPath.includes(subpage))
if (isSubpageMatch) {
return { index: i, isSubpage: true }
}
}
return { index: -1, isSubpage: false }
}
function getTabElement(index: number): HTMLElement | null {
if (!tabLinkElements.value?.[index]) return null
// In navigation mode, elements are NuxtLinks with $el property
// In local mode, elements are plain divs
const element = tabLinkElements.value[index]
return props.mode === 'navigation' ? (element as any).$el : element
}
function positionSlider() {
const el = getTabElement(currentActiveIndex.value)
if (!el?.offsetParent) return
const parent = el.offsetParent as HTMLElement
const newPosition = {
left: el.offsetLeft,
top: el.offsetTop,
right: parent.offsetWidth - el.offsetLeft - el.offsetWidth,
bottom: parent.offsetHeight - el.offsetTop - el.offsetHeight,
}
const isInitialPosition = sliderLeft.value === 4 && sliderRight.value === 4
if (isInitialPosition) {
// Initial positioning: set position instantly, no animation
sliderLeft.value = newPosition.left
sliderRight.value = newPosition.right
sliderTop.value = newPosition.top
sliderBottom.value = newPosition.bottom
sliderReady.value = true
// enable transitions after slider is painted, so future changes animate
requestAnimationFrame(() => {
transitionsEnabled.value = true
})
} else {
animateSliderTo(newPosition)
}
}
function animateSliderTo(newPosition: {
left: number
top: number
right: number
bottom: number
}) {
const STAGGER_DELAY = 200
// Horizontal animation - lead with the direction of movement
if (newPosition.left < sliderLeft.value) {
sliderLeft.value = newPosition.left
setTimeout(() => (sliderRight.value = newPosition.right), STAGGER_DELAY)
} else {
sliderRight.value = newPosition.right
setTimeout(() => (sliderLeft.value = newPosition.left), STAGGER_DELAY)
}
// Vertical animation - lead with the direction of movement
if (newPosition.top < sliderTop.value) {
sliderTop.value = newPosition.top
setTimeout(() => (sliderBottom.value = newPosition.bottom), STAGGER_DELAY)
} else {
sliderBottom.value = newPosition.bottom
setTimeout(() => (sliderTop.value = newPosition.top), STAGGER_DELAY)
}
}
function updateActiveTab() {
const { index, isSubpage } = computeActiveIndex()
currentActiveIndex.value = index
subpageSelected.value = isSubpage
if (index !== -1) {
nextTick(positionSlider)
} else {
sliderLeft.value = 0
sliderRight.value = 0
}
}
function startAnimation() {
// In navigation mode, elements are NuxtLinks with $el property
// In local mode, elements are plain divs
const el =
props.mode === 'navigation'
? tabLinkElements.value[currentActiveIndex.value]?.$el
: tabLinkElements.value[currentActiveIndex.value]
const initialActive = computeActiveIndex()
currentActiveIndex.value = initialActive.index
subpageSelected.value = initialActive.isSubpage
if (!el || !el.offsetParent) return
const newValues = {
left: el.offsetLeft,
top: el.offsetTop,
right: el.offsetParent.offsetWidth - el.offsetLeft - el.offsetWidth,
bottom: el.offsetParent.offsetHeight - el.offsetTop - el.offsetHeight,
}
if (sliderLeft.value === 4 && sliderRight.value === 4) {
sliderLeft.value = newValues.left
sliderRight.value = newValues.right
sliderTop.value = newValues.top
sliderBottom.value = newValues.bottom
} else {
const delay = 200
if (newValues.left < sliderLeft.value) {
sliderLeft.value = newValues.left
setTimeout(() => {
sliderRight.value = newValues.right
}, delay)
} else {
sliderRight.value = newValues.right
setTimeout(() => {
sliderLeft.value = newValues.left
}, delay)
}
if (newValues.top < sliderTop.value) {
sliderTop.value = newValues.top
setTimeout(() => {
sliderBottom.value = newValues.bottom
}, delay)
} else {
sliderBottom.value = newValues.bottom
setTimeout(() => {
sliderTop.value = newValues.top
}, delay)
}
}
}
onMounted(() => {
pickLink()
})
onMounted(updateActiveTab)
watch(
() => [route.path, route.query],
() => {
if (props.mode === 'navigation') {
pickLink()
updateActiveTab()
}
},
)
@@ -228,19 +282,12 @@ watch(
() => props.activeIndex,
() => {
if (props.mode === 'local') {
pickLink()
updateActiveTab()
}
},
)
watch(
() => props.links,
() => {
// Re-trigger animation when links change
pickLink()
},
{ deep: true },
)
watch(() => props.links, updateActiveTab, { deep: true })
</script>
<style scoped>
@@ -458,9 +458,11 @@ function getMessages() {
}
function getLoaderCategories(ver) {
return tags.value.loaders.filter((loader) => {
return ver?.loaders?.includes(loader.name)
})
return tags.value.loaders
.filter((loader) => {
return ver?.loaders?.includes(loader.name)
})
.map((loader) => loader.name)
}
</script>
@@ -91,10 +91,9 @@
<script>
import { CalendarIcon, DownloadIcon, HeartIcon, UpdatedIcon } from '@modrinth/assets'
import { Avatar, ProjectStatusBadge, useRelativeTime } from '@modrinth/ui'
import { Avatar, Categories, ProjectStatusBadge, useRelativeTime } from '@modrinth/ui'
import EnvironmentIndicator from '~/components/ui/EnvironmentIndicator.vue'
import Categories from '~/components/ui/search/Categories.vue'
export default {
components: {
@@ -9,13 +9,13 @@
<ButtonStyled color="brand">
<button class="brand-button" @click="acceptInvite()">
<CheckIcon />
{{ getFormattedMessage(messages.accept) }}
{{ getFormattedMessage(commonMessages.acceptButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="red">
<button @click="declineInvite">
<XIcon />
{{ getFormattedMessage(messages.decline) }}
{{ getFormattedMessage(commonMessages.declineButton) }}
</button>
</ButtonStyled>
</div>
@@ -26,6 +26,7 @@
import { CheckIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
commonMessages,
defineMessages,
injectNotificationManager,
type MessageDescriptor,
@@ -81,14 +82,6 @@ const messages = defineMessages({
defaultMessage:
"You've been invited to join this project. Please accept or decline the invitation.",
},
accept: {
id: 'project-member-header.accept',
defaultMessage: 'Accept',
},
decline: {
id: 'project-member-header.decline',
defaultMessage: 'Decline',
},
successJoin: {
id: 'project-member-header.success-join',
defaultMessage: 'You have joined the project team',
@@ -105,14 +98,6 @@ const messages = defineMessages({
id: 'project-member-header.error-decline',
defaultMessage: 'Failed to decline team invitation',
},
success: {
id: 'project-member-header.success',
defaultMessage: 'Success',
},
error: {
id: 'project-member-header.error',
defaultMessage: 'Error',
},
})
const { formatMessage } = useVIntl()
@@ -171,13 +156,13 @@ async function acceptInvite(): Promise<void> {
await acceptTeamInvite(props.project.team)
await handleUpdateMembers()
addNotification({
title: formatMessage(messages.success),
title: formatMessage(commonMessages.successLabel),
text: formatMessage(messages.successJoin),
type: 'success',
})
} catch {
addNotification({
title: formatMessage(messages.error),
title: formatMessage(commonMessages.errorLabel),
text: formatMessage(messages.errorJoin),
type: 'error',
})
@@ -192,13 +177,13 @@ async function declineInvite(): Promise<void> {
await removeTeamMember(props.project.team, props.auth.user.id)
await handleUpdateMembers()
addNotification({
title: formatMessage(messages.success),
title: formatMessage(commonMessages.successLabel),
text: formatMessage(messages.successDecline),
type: 'success',
})
} catch {
addNotification({
title: formatMessage(messages.error),
title: formatMessage(commonMessages.errorLabel),
text: formatMessage(messages.errorDecline),
type: 'error',
})
@@ -46,20 +46,20 @@
Node hostnames
<span class="text-brand-red">*</span>
</span>
<span>Add nodes to transfer.</span>
<span>Add nodes to transfer (comma or space-separated).</span>
</label>
<div class="flex items-center gap-2">
<input
id="node-input"
v-model="nodeInput"
class="w-40"
class="w-64"
type="text"
autocomplete="off"
placeholder="us-vin200"
@keydown.enter.prevent="addNode"
placeholder="us-vin200, us-vin201"
@keydown.enter.prevent="addNodes"
/>
<ButtonStyled color="blue" color-fill="text">
<button class="shrink-0" @click="addNode">
<button class="shrink-0" @click="addNodes">
<PlusIcon />
Add
</button>
@@ -282,18 +282,37 @@ function hide() {
modal.value?.hide()
}
function addNode() {
const v = nodeInput.value.trim()
if (!v) return
if (!nodeHostnames.value.includes(v)) {
function addNodes() {
const input = nodeInput.value.trim()
if (!input) return
const nodes = input
.split(/[,\s]+/)
.map((s) => s.trim())
.filter((s) => s.length > 0)
const unknownNodes: string[] = []
const addedNodes: string[] = []
for (const v of nodes) {
if (!nodeHostnames.value.includes(v)) {
unknownNodes.push(v)
continue
}
if (!selectedNodes.value.includes(v)) {
selectedNodes.value.push(v)
addedNodes.push(v)
}
}
if (unknownNodes.length > 0) {
addNotification({
title: 'Unknown node',
text: "This hostname doesn't exist",
title: `Unknown node${unknownNodes.length > 1 ? 's' : ''}`,
text: unknownNodes.join(', '),
type: 'error',
})
return
}
if (!selectedNodes.value.includes(v)) selectedNodes.value.push(v)
nodeInput.value = ''
}
@@ -27,8 +27,8 @@
"
:style="`--_color: var(--color-platform-${loader.name})`"
>
<div v-html="loader.icon"></div>
{{ formatCategory(loader.name) }}
<component :is="getLoaderIcon(loader.name)" v-if="getLoaderIcon(loader.name)" />
<FormattedTag :tag="loader.name" enforce-type="loader" />
</TagItem>
</div>
</div>
@@ -40,8 +40,8 @@
<script lang="ts" setup>
import type { Labrinth } from '@modrinth/api-client'
import { Chips, TagItem } from '@modrinth/ui'
import { formatCategory } from '@modrinth/utils'
import { getLoaderIcon } from '@modrinth/assets'
import { Chips, FormattedTag, TagItem } from '@modrinth/ui'
const selectedLoaders = defineModel<string[]>({ default: [] })
@@ -155,7 +155,7 @@ function groupVersions(gameVersions: GameVersion[]) {
const groups: Record<string, string[]> = {}
let currentGroupKey = getSnapshotGroupKey(gameVersions.find((v) => v.major)?.version || '')
let currentGroupKey
gameVersions.forEach((gameVersion) => {
if (gameVersion.version_type === 'release') {
@@ -29,8 +29,8 @@
class="border !border-solid border-surface-5 !transition-all hover:bg-button-bgHover hover:no-underline"
:style="`--_color: var(--color-platform-${loader.name})`"
>
<div v-html="loader.icon"></div>
{{ formatCategory(loader.name) }}
<component :is="getLoaderIcon(loader.name)" v-if="getLoaderIcon(loader.name)" />
<FormattedTag :tag="loader.name" enforce-type="loader" />
<XIcon class="text-secondary" />
</TagItem>
</template>
@@ -41,9 +41,8 @@
</template>
<script lang="ts" setup>
import { XIcon } from '@modrinth/assets'
import { ButtonStyled, TagItem } from '@modrinth/ui'
import { formatCategory } from '@modrinth/utils'
import { getLoaderIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, FormattedTag, TagItem } from '@modrinth/ui'
import { injectManageVersionContext } from '~/providers/version/manage-version-modal'
@@ -72,8 +72,8 @@
class="border !border-solid border-surface-5 hover:no-underline"
:style="`--_color: var(--color-platform-${loader.name})`"
>
<div v-html="loader.icon"></div>
{{ formatCategory(loader.name) }}
<component :is="getLoaderIcon(loader.name)" v-if="getLoaderIcon(loader.name)" />
<FormattedTag :tag="loader.name" enforce-type="loader" />
</TagItem>
</template>
@@ -189,16 +189,16 @@
<script lang="ts" setup>
import type { Labrinth } from '@modrinth/api-client'
import { EditIcon, UnknownIcon } from '@modrinth/assets'
import { EditIcon, getLoaderIcon, UnknownIcon } from '@modrinth/assets'
import {
ButtonStyled,
defineMessages,
ENVIRONMENTS_COPY,
FormattedTag,
injectProjectPageContext,
TagItem,
useVIntl,
} from '@modrinth/ui'
import { formatCategory } from '@modrinth/utils'
import { useGeneratedState } from '~/composables/generated'
import { injectManageVersionContext } from '~/providers/version/manage-version-modal'
@@ -43,7 +43,7 @@
<ButtonStyled class="w-24">
<button @click="modal.hide()">
<XIcon aria-hidden="true" />
{{ formatMessage(messages.cancel) }}
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand" class="w-36">
@@ -60,6 +60,7 @@
import { PlusIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
commonMessages,
defineMessages,
injectNotificationManager,
NewModal,
@@ -102,18 +103,10 @@ const messages = defineMessages({
defaultMessage:
'Your new collection will be created as a public collection with {count, plural, =0 {no projects} one {# project} other {# projects}}.',
},
cancel: {
id: 'create.collection.cancel',
defaultMessage: 'Cancel',
},
createCollection: {
id: 'create.collection.create-collection',
defaultMessage: 'Create collection',
},
errorTitle: {
id: 'create.collection.error-title',
defaultMessage: 'An error occurred',
},
})
const name = ref('')
@@ -150,7 +143,7 @@ async function create() {
await router.push(`/collection/${result.id}`)
} catch (err) {
addNotification({
title: formatMessage(messages.errorTitle),
title: formatMessage(commonMessages.errorNotificationTitle),
text: err?.data?.description || err?.message || err,
type: 'error',
})
@@ -65,7 +65,7 @@
<ButtonStyled class="w-24">
<button @click="hide">
<XIcon aria-hidden="true" />
{{ formatMessage(messages.cancel) }}
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand" class="w-40">
@@ -83,6 +83,7 @@
import { PlusIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
commonMessages,
defineMessages,
injectNotificationManager,
NewModal,
@@ -130,18 +131,10 @@ const messages = defineMessages({
defaultMessage:
'You will be the owner of this organization, but you can invite other members and transfer ownership at any time.',
},
cancel: {
id: 'create.organization.cancel',
defaultMessage: 'Cancel',
},
createOrganization: {
id: 'create.organization.create-organization',
defaultMessage: 'Create organization',
},
errorTitle: {
id: 'create.organization.error-title',
defaultMessage: 'An error occurred',
},
})
const name = ref<string>('')
@@ -172,7 +165,7 @@ async function createOrganization(): Promise<void> {
} catch (err: any) {
console.error(err)
addNotification({
title: formatMessage(messages.errorTitle),
title: formatMessage(commonMessages.errorNotificationTitle),
text: err.data ? err.data.description : err,
type: 'error',
})
@@ -43,7 +43,7 @@
<div class="flex flex-col gap-2">
<label for="visibility" class="flex flex-col gap-1">
<span class="text-lg font-semibold text-contrast">
{{ formatMessage(messages.visibilityLabel) }}
{{ formatMessage(commonMessages.visibilityLabel) }}
<span class="text-brand-red">*</span>
</span>
<span>{{ formatMessage(messages.visibilityDescription) }}</span>
@@ -79,7 +79,7 @@
<ButtonStyled class="w-24">
<button @click="cancel">
<XIcon aria-hidden="true" />
{{ formatMessage(messages.cancel) }}
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand" class="w-32">
@@ -98,6 +98,7 @@ import { PlusIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
Chips,
commonMessages,
defineMessages,
injectNotificationManager,
NewModal,
@@ -127,10 +128,6 @@ const messages = defineMessages({
id: 'create.project.url-label',
defaultMessage: 'URL',
},
visibilityLabel: {
id: 'create.project.visibility-label',
defaultMessage: 'Visibility',
},
visibilityDescription: {
id: 'create.project.visibility-description',
defaultMessage: 'The visibility of your project after it has been approved.',
@@ -147,18 +144,10 @@ const messages = defineMessages({
id: 'create.project.summary-placeholder',
defaultMessage: 'This project adds...',
},
cancel: {
id: 'create.project.cancel',
defaultMessage: 'Cancel',
},
createProject: {
id: 'create.project.create-project',
defaultMessage: 'Create project',
},
errorTitle: {
id: 'create.project.error-title',
defaultMessage: 'An error occurred',
},
visibilityPublic: {
id: 'create.project.visibility-public',
defaultMessage: 'Public',
@@ -256,7 +245,7 @@ async function createProject() {
await router.push(`/project/${slug.value}/settings`)
} catch (err) {
addNotification({
title: formatMessage(messages.errorTitle),
title: formatMessage(commonMessages.errorNotificationTitle),
text: err.data ? err.data.description : err,
type: 'error',
})
@@ -37,7 +37,10 @@
v-model="isUSCitizen"
:items="['yes', 'no']"
:format-label="
(item) => (item === 'yes' ? formatMessage(messages.yes) : formatMessage(messages.no))
(item) =>
item === 'yes'
? formatMessage(commonMessages.yesLabel)
: formatMessage(commonMessages.noLabel)
"
:never-empty="false"
:capitalize="true"
@@ -162,6 +165,7 @@ import {
Admonition,
ButtonStyled,
Chips,
commonMessages,
defineMessages,
injectNotificationManager,
IntlFormatted,
@@ -228,8 +232,6 @@ const messages = defineMessages({
id: 'dashboard.creator-tax-form-modal.us-citizen.question',
defaultMessage: 'Are you a US citizen?',
},
yes: { id: 'common.yes', defaultMessage: 'Yes' },
no: { id: 'common.no', defaultMessage: 'No' },
entityQuestion: {
id: 'dashboard.creator-tax-form-modal.entity.question',
defaultMessage: 'Are you a private individual or part of a foreign entity?',
@@ -60,7 +60,7 @@
<div v-if="currentStage === 'completion'" class="mt-4 flex w-full gap-3">
<ButtonStyled class="flex-1">
<button class="w-full text-contrast" @click="handleClose">
{{ formatMessage(messages.closeButton) }}
{{ formatMessage(commonMessages.closeButton) }}
</button>
</ButtonStyled>
<ButtonStyled class="flex-1">
@@ -601,26 +601,10 @@ const messages = defineMessages({
id: 'dashboard.creator-withdraw-modal.stage.method-selection',
defaultMessage: 'Method',
},
tremendousDetailsStage: {
id: 'dashboard.creator-withdraw-modal.stage.tremendous-details',
defaultMessage: 'Details',
},
muralpayKycStage: {
id: 'dashboard.creator-withdraw-modal.stage.muralpay-kyc',
defaultMessage: 'Verification',
},
muralpayDetailsStage: {
id: 'dashboard.creator-withdraw-modal.stage.muralpay-details',
defaultMessage: 'Account Details',
},
completionStage: {
id: 'dashboard.creator-withdraw-modal.stage.completion',
defaultMessage: 'Complete',
},
detailsLabel: {
id: 'dashboard.creator-withdraw-modal.details-label',
defaultMessage: 'Details',
},
completeTaxForm: {
id: 'dashboard.creator-withdraw-modal.complete-tax-form',
defaultMessage: 'Complete tax form',
@@ -629,14 +613,14 @@ const messages = defineMessages({
id: 'dashboard.creator-withdraw-modal.continue-with-limit',
defaultMessage: 'Continue with limit',
},
detailsLabel: {
id: 'dashboard.creator-withdraw-modal.details-label',
defaultMessage: 'Details',
},
withdrawButton: {
id: 'dashboard.creator-withdraw-modal.withdraw-button',
defaultMessage: 'Withdraw',
},
closeButton: {
id: 'dashboard.withdraw.completion.close-button',
defaultMessage: 'Close',
},
transactionsButton: {
id: 'dashboard.withdraw.completion.transactions-button',
defaultMessage: 'Transactions',
@@ -287,13 +287,5 @@ const messages = defineMessages({
defaultMessage:
"You'll receive an email at <b>{email}</b> with instructions to redeem your withdrawal.",
},
closeButton: {
id: 'dashboard.withdraw.completion.close-button',
defaultMessage: 'Close',
},
transactionsButton: {
id: 'dashboard.withdraw.completion.transactions-button',
defaultMessage: 'Transactions',
},
})
</script>
@@ -57,8 +57,8 @@
<SaveIcon v-else />
{{
venmoSaveSuccess
? formatMessage(messages.savedButton)
: formatMessage(messages.saveButton)
? formatMessage(commonMessages.savedLabel)
: formatMessage(commonMessages.saveButton)
}}
</button>
</ButtonStyled>
@@ -107,6 +107,7 @@ import { CheckIcon, PayPalColorIcon, SaveIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
Checkbox,
commonMessages,
defineMessages,
financialMessages,
formFieldLabels,
@@ -342,14 +343,6 @@ const messages = defineMessages({
id: 'dashboard.creator-withdraw-modal.paypal-details.disconnect-account',
defaultMessage: 'Disconnect account',
},
saveButton: {
id: 'dashboard.creator-withdraw-modal.paypal-details.save-button',
defaultMessage: 'Save',
},
savedButton: {
id: 'dashboard.creator-withdraw-modal.paypal-details.saved-button',
defaultMessage: 'Saved',
},
saveSuccess: {
id: 'dashboard.creator-withdraw-modal.paypal-details.save-success',
defaultMessage: 'Venmo handle saved successfully!',
@@ -1,6 +1,6 @@
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import { ClipboardCopyIcon, LoaderCircleIcon, XIcon } from '@modrinth/assets'
import { ClipboardCopyIcon, DownloadIcon, LoaderCircleIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, CopyCode, NewModal } from '@modrinth/ui'
import { ref, useTemplateRef } from 'vue'
@@ -38,15 +38,16 @@ async function fetchVersionHashes(versionIds: string[]) {
// TODO: switch to api-client once truman's vers stuff is merged
const version = (await useBaseFetch(`version/${versionId}`)) as {
files: Array<{
id?: string
filename: string
file_name?: string
hashes: { sha512: string; sha1: string }
}>
}
const filesMap = new Map<string, string>()
for (const file of version.files) {
const name = file.file_name ?? file.filename
filesMap.set(name, file.hashes.sha512)
if (file.id) {
filesMap.set(file.id, file.hashes.sha512)
}
}
versionDataCache.value.set(versionId, { files: filesMap, loading: false })
} catch (error) {
@@ -60,8 +61,8 @@ async function fetchVersionHashes(versionIds: string[]) {
}
}
function getFileHash(versionId: string, fileName: string): string | undefined {
return versionDataCache.value.get(versionId)?.files.get(fileName)
function getFileHash(versionId: string, fileId: string): string | undefined {
return versionDataCache.value.get(versionId)?.files.get(fileId)
}
function isHashLoading(versionId: string): boolean {
@@ -114,6 +115,7 @@ defineExpose({ show, hide })
<th class="pb-2">Version ID</th>
<th class="pb-2">File Name</th>
<th class="pb-2">CDN Link</th>
<th class="pb-2">Download</th>
</tr>
</thead>
<tbody>
@@ -124,11 +126,11 @@ defineExpose({ show, hide })
class="size-4 animate-spin text-secondary"
/>
<ButtonStyled
v-else-if="getFileHash(item.file.version_id, item.file.file_name)"
v-else-if="getFileHash(item.file.version_id, item.file.file_id)"
size="small"
type="standard"
>
<button @click="copy(getFileHash(item.file.version_id, item.file.file_name)!)">
<button @click="copy(getFileHash(item.file.version_id, item.file.file_id)!)">
<ClipboardCopyIcon class="size-4" />
Copy
</button>
@@ -141,7 +143,7 @@ defineExpose({ show, hide })
<td class="py-1 pr-2">
<CopyCode :text="item.file.file_name" />
</td>
<td class="py-1">
<td class="py-1 pr-2">
<ButtonStyled size="small" type="standard">
<button @click="copy(item.file.download_url)">
<ClipboardCopyIcon class="size-4" />
@@ -149,6 +151,13 @@ defineExpose({ show, hide })
</button>
</ButtonStyled>
</td>
<td class="py-1">
<ButtonStyled circular size="small">
<a :href="item.file.download_url" :download="item.file.file_name" target="_blank">
<DownloadIcon />
</a>
</ButtonStyled>
</td>
</tr>
</tbody>
</table>
@@ -78,6 +78,7 @@
</template>
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import {
AsteriskIcon,
ChevronRightIcon,
@@ -90,7 +91,6 @@ import {
import type { Nag, NagContext, NagStatus } from '@modrinth/moderation'
import { nags } from '@modrinth/moderation'
import { ButtonStyled, defineMessages, type MessageDescriptor, useVIntl } from '@modrinth/ui'
import type { Project, User, Version } from '@modrinth/utils'
import type { Component } from 'vue'
import { computed } from 'vue'
@@ -98,16 +98,10 @@ interface Tags {
rejectedStatuses: string[]
}
interface Member {
accepted?: boolean
project_role?: string
user?: Partial<User>
}
interface Props {
project: Project
versions?: Version[]
currentMember?: Member | null
project: Labrinth.Projects.v2.Project
versions?: Labrinth.Versions.v2.Version[]
currentMember?: Labrinth.Projects.v3.TeamMember | null
collapsed?: boolean
routeName?: string
tags: Tags
@@ -179,7 +173,7 @@ const emit = defineEmits<{
const nagContext = computed<NagContext>(() => ({
project: props.project,
versions: props.versions,
currentMember: props.currentMember as User,
currentMember: props.currentMember?.user as Labrinth.Users.v2.User,
currentRoute: props.routeName,
tags: props.tags,
submitProject: submitForReview,
@@ -12,6 +12,7 @@ import {
LinkIcon,
LoaderCircleIcon,
ShieldCheckIcon,
TimerIcon,
} from '@modrinth/assets'
import { type TechReviewContext, techReviewQuickReplies } from '@modrinth/moderation'
import {
@@ -113,8 +114,8 @@ const quickActions = computed<OverflowMenuOption[]>(() => {
navigator.clipboard.writeText(props.item.project.id).then(() => {
addNotification({
type: 'success',
title: 'Technical Report ID copied',
text: 'The ID of this report has been copied to your clipboard.',
title: 'Project ID copied',
text: 'The ID of this project has been copied to your clipboard.',
})
})
},
@@ -265,6 +266,13 @@ const severityColor = computed(() => {
}
})
const isProjectApproved = computed(() => {
const status = props.item.project.status
return (
status === 'approved' || status === 'archived' || status === 'unlisted' || status === 'private'
)
})
const formattedDate = computed(() => {
const dates = props.item.reports.map((r) => new Date(r.created))
const earliest = new Date(Math.min(...dates.map((d) => d.getTime())))
@@ -369,12 +377,16 @@ async function updateDetailStatus(detailId: string, verdict: 'safe' | 'unsafe')
if (detailKey) break
}
let otherMatchedCount = 0
if (detailKey) {
for (const report of props.item.reports) {
for (const issue of report.issues) {
for (const detail of issue.details) {
if (detail.key === detailKey) {
detailDecisions.value.set(detail.id, decision)
if (detail.id !== detailId) {
otherMatchedCount++
}
}
}
}
@@ -391,17 +403,31 @@ async function updateDetailStatus(detailId: string, verdict: 'safe' | 'unsafe')
}
}
// Jump back to Files tab when all flags in the current file are marked
if (selectedFile.value) {
const markedCount = getFileMarkedCount(selectedFile.value)
const totalCount = getFileDetailCount(selectedFile.value)
if (markedCount === totalCount) {
backToFileList()
}
}
const otherText =
otherMatchedCount > 0
? ` (${otherMatchedCount} other trace${otherMatchedCount === 1 ? '' : 's'} also marked)`
: ''
if (verdict === 'safe') {
addNotification({
type: 'success',
title: 'Issue marked as pass',
text: 'This issue has been marked as a false positive.',
text: `This issue has been marked as a false positive.${otherText}`,
})
} else {
addNotification({
type: 'success',
title: 'Issue marked as fail',
text: 'This issue has been flagged as malicious.',
text: `This issue has been flagged as malicious.${otherText}`,
})
}
} catch (error) {
@@ -472,6 +498,17 @@ const groupedByClass = computed<ClassGroup[]>(() => {
})
})
// Auto-expand if there's only one class in the file
watch(
groupedByClass,
(classes) => {
if (classes.length === 1) {
expandedClasses.value.add(classes[0].filePath)
}
},
{ immediate: true },
)
function getHighestSeverityInClass(
flags: ClassGroup['flags'],
): Labrinth.TechReview.Internal.DelphiSeverity {
@@ -623,7 +660,7 @@ const threadWithPreview = computed(() => {
body: {
type: 'text',
body: reviewSummaryPreview.value,
private: false,
private: true,
replying_to: null,
associated_images: [],
},
@@ -747,9 +784,21 @@ async function handleSubmitReview(verdict: 'safe' | 'unsafe') {
</div>
<div
class="rounded-full border border-solid border-surface-5 bg-surface-4 px-2.5 py-1"
class="flex items-center gap-1 rounded-full border border-solid px-2.5 py-1"
:class="
isProjectApproved
? 'border-green bg-highlight-green'
: 'border-orange bg-highlight-orange'
"
>
<span class="text-sm font-medium text-secondary">Auto-Flagged</span>
<CheckIcon v-if="isProjectApproved" aria-hidden="true" class="h-4 w-4 text-green" />
<TimerIcon v-else aria-hidden="true" class="h-4 w-4 text-orange" />
<span
class="text-sm font-medium"
:class="isProjectApproved ? 'text-green' : 'text-orange'"
>
{{ isProjectApproved ? 'Live' : 'In review' }}
</span>
</div>
<div class="rounded-full px-2.5 py-1" :class="severityColor">
@@ -929,8 +978,6 @@ async function handleSubmitReview(verdict: 'safe' | 'unsafe') {
:href="file.download_url"
:title="`Download ${file.file_name}`"
:download="file.file_name"
target="_blank"
rel="noopener noreferrer"
class="!border-px !border-surface-4"
tabindex="0"
>
@@ -1008,15 +1055,21 @@ async function handleSubmitReview(verdict: 'safe' | 'unsafe') {
v-for="flag in classItem.flags"
:key="`${flag.issueId}-${flag.detail.id}`"
class="grid grid-cols-[1fr_auto_auto] items-center rounded-lg border-[1px] border-b border-solid border-surface-5 bg-surface-3 py-2 pl-4 last:border-b-0"
:class="{
'opacity-50': isPreReviewed(flag.detail.id, flag.detail.status),
}"
>
<span class="text-base font-semibold text-contrast">{{
flag.issueType.replace(/_/g, ' ')
}}</span>
<span
class="text-base font-semibold text-contrast"
:class="{
'opacity-50': isPreReviewed(flag.detail.id, flag.detail.status),
}"
>{{ flag.issueType.replace(/_/g, ' ') }}</span
>
<div class="flex w-20 justify-center">
<div
class="flex w-20 justify-center"
:class="{
'opacity-50': isPreReviewed(flag.detail.id, flag.detail.status),
}"
>
<div
class="rounded-full border-solid px-2.5 py-1"
:class="getSeverityBadgeColor(flag.detail.severity)"
@@ -692,17 +692,23 @@ const emit = defineEmits<{
async function handleExit() {
// Release if we own the lock, or if there was an error checking (we might still own it)
if (lockStatus.value?.isOwnLock || lockError.value) {
const released = await moderationStore.releaseLock(projectV2.value.id)
const projectId = projectV2.value?.id
if (projectId && (lockStatus.value?.isOwnLock || lockError.value)) {
const released = await moderationStore.releaseLock(projectId)
if (!released && lockStatus.value?.isOwnLock) {
console.warn('Failed to release moderation lock for project:', projectV2.value.id)
console.warn('Failed to release moderation lock for project:', projectId)
}
}
emit('exit')
}
async function retryAcquireLock() {
const result = await moderationStore.acquireLock(projectV2.value.id)
const projectId = projectV2.value?.id
if (!projectId) {
console.warn('[retryAcquireLock] No project ID available')
return
}
const result = await moderationStore.acquireLock(projectId)
if (result.success) {
handleLockAcquired()
@@ -790,6 +796,8 @@ async function maintainPrefetchQueue() {
if (isPrefetching.value) return
if (!moderationStore.isQueueMode) return
const currentProjectId = projectV2.value?.id
isPrefetching.value = true
try {
@@ -798,7 +806,9 @@ async function maintainPrefetchQueue() {
prefetchQueue.value = prefetchQueue.value.filter((p) => now - p.validatedAt < PREFETCH_STALE_MS)
// 2. Remove entries for current project
prefetchQueue.value = prefetchQueue.value.filter((p) => p.projectId !== projectV2.value.id)
if (currentProjectId) {
prefetchQueue.value = prefetchQueue.value.filter((p) => p.projectId !== currentProjectId)
}
// 3. If queue is full enough, exit early
if (prefetchQueue.value.length >= PREFETCH_TARGET_COUNT) {
@@ -808,7 +818,7 @@ async function maintainPrefetchQueue() {
// 4. Get remaining queue items (excluding current and already prefetched)
const prefetchedIds = new Set(prefetchQueue.value.map((p) => p.projectId))
const queueItems = [...moderationStore.currentQueue.items]
const currentIndex = queueItems.indexOf(projectV2.value.id)
const currentIndex = currentProjectId ? queueItems.indexOf(currentProjectId) : -1
const remainingItems =
currentIndex >= 0 ? queueItems.slice(currentIndex + 1) : queueItems.slice(1)
@@ -873,7 +883,11 @@ const MAX_SKIP_ATTEMPTS = 10
async function skipToNextProject() {
// Skip the current project
const currentProjectId = projectV2.value.id
const currentProjectId = projectV2.value?.id
if (!currentProjectId) {
console.warn('[skipToNextProject] No current project ID, aborting')
return
}
debug('[skipToNextProject] Starting. Current project:', currentProjectId)
debug('[skipToNextProject] Queue before complete:', [...moderationStore.currentQueue.items])
@@ -1822,16 +1836,30 @@ function generateModpackMessage(allFiles: {
const hasNextProject = ref(false)
async function sendMessage(status: ProjectStatus) {
// Capture project data upfront to avoid null issues during async operations
const projectId = projectV2.value?.id
const threadId = projectV2.value?.thread_id
const projectType = projectV2.value?.project_type
if (!projectId) {
addNotification({
title: 'Error submitting moderation',
text: 'Project data unavailable. Please try again.',
type: 'error',
})
return
}
try {
await useBaseFetch(`project/${projectV2.value.id}`, {
await useBaseFetch(`project/${projectId}`, {
method: 'PATCH',
body: {
status,
},
})
if (message.value) {
await useBaseFetch(`thread/${projectV2.value.thread_id}`, {
if (message.value && threadId) {
await useBaseFetch(`thread/${threadId}`, {
method: 'POST',
body: {
body: {
@@ -1842,10 +1870,7 @@ async function sendMessage(status: ProjectStatus) {
})
}
if (
projectV2.value.project_type === 'modpack' &&
Object.keys(modpackJudgements.value).length > 0
) {
if (projectType === 'modpack' && Object.keys(modpackJudgements.value).length > 0) {
await useBaseFetch(`moderation/project`, {
internal: true,
method: 'POST',
@@ -1853,12 +1878,16 @@ async function sendMessage(status: ProjectStatus) {
})
}
const willHaveNext = moderationStore.completeCurrentProject(projectId, 'completed')
moderationStore.releaseLock(projectId).catch((err) => {
console.warn('Failed to release lock:', err)
})
// Set both states together - hasNextProject MUST be set before done
// to avoid the race condition where done=true renders with hasNextProject=false
hasNextProject.value = willHaveNext
done.value = true
// Release the lock after successful submission
await moderationStore.releaseLock(projectV2.value.id)
hasNextProject.value = moderationStore.completeCurrentProject(projectV2.value.id, 'completed')
} catch (error) {
console.error('Error submitting moderation:', error)
addNotification({
@@ -1900,7 +1929,7 @@ async function endChecklist(status?: string) {
if (!(await navigateToNextUnlockedProject())) {
// Fallback: batch check remaining projects with metadata
const remainingIds: string[] = []
const currentProjectId = projectV2.value.id
const currentProjectId = projectV2.value?.id
const queueItems = moderationStore.currentQueue.items
// Build list of remaining projects, excluding current
@@ -1971,10 +2000,21 @@ async function endChecklist(status?: string) {
}
async function skipCurrentProject() {
// Release the lock before skipping
await moderationStore.releaseLock(projectV2.value.id)
const projectId = projectV2.value?.id
if (!projectId) {
addNotification({
title: 'Error skipping project',
text: 'Project data unavailable. Please try again.',
type: 'error',
})
return
}
hasNextProject.value = moderationStore.completeCurrentProject(projectV2.value.id, 'skipped')
moderationStore.releaseLock(projectId).catch((err) => {
console.warn('Failed to release lock:', err)
})
hasNextProject.value = moderationStore.completeCurrentProject(projectId, 'skipped')
await endChecklist('skipped')
}
@@ -1,72 +0,0 @@
<template>
<div class="categories">
<slot />
<span
v-for="category in categoriesFiltered"
:key="category.name"
v-html="category.icon + formatCategory(category.name)"
/>
</div>
</template>
<script>
import { formatCategory } from '@modrinth/utils'
export default {
props: {
categories: {
type: Array,
default() {
return []
},
},
type: {
type: String,
required: true,
},
},
setup() {
const tags = useGeneratedState()
return { tags }
},
computed: {
categoriesFiltered() {
return this.tags.categories
.concat(this.tags.loaders)
.filter(
(x) =>
this.categories.includes(x.name) && (!x.project_type || x.project_type === this.type),
)
},
},
methods: { formatCategory },
}
</script>
<style lang="scss" scoped>
.categories {
display: flex;
flex-direction: row;
flex-wrap: wrap;
:deep(span) {
display: flex;
align-items: center;
flex-direction: row;
&:not(:last-child) {
margin-right: var(--spacing-card-md);
}
&:not(.badge) {
color: var(--color-icon);
}
svg {
width: 1rem;
margin-right: 0.2rem;
}
}
}
</style>
@@ -132,17 +132,24 @@
:loader="'Vanilla'"
class="size-5 flex-none"
/>
<svg
v-else
<component
:is="getLoaderIcon(filtersRef.selectedPlatforms[0])"
v-else-if="
filtersRef?.selectedPlatforms[0] && getLoaderIcon(filtersRef.selectedPlatforms[0])
"
class="size-5 flex-none"
v-html="tags.loaders.find((x) => x.name === filtersRef?.selectedPlatforms[0])?.icon"
></svg>
/>
<div class="w-full truncate text-left">
{{
filtersRef?.selectedPlatforms.length === 0
? 'All platforms'
: filtersRef?.selectedPlatforms.map((x) => formatCategory(x)).join(', ')
: filtersRef?.selectedPlatforms
.map((x) => {
const message = getTagMessageOrDefault(x, 'loader')
return typeof message === 'string' ? message : formatMessage(message)
})
.join(', ')
}}
</div>
</template>
@@ -242,6 +249,7 @@ import {
DropdownIcon,
ExternalIcon,
GameIcon,
getLoaderIcon,
LockOpenIcon,
XIcon,
} from '@modrinth/assets'
@@ -252,10 +260,12 @@ import {
Checkbox,
Combobox,
CopyCode,
getTagMessageOrDefault,
NewModal,
TagItem,
useVIntl,
} from '@modrinth/ui'
import TagItem from '@modrinth/ui/src/components/base/TagItem.vue'
import { formatCategory, formatVersionsForDisplay, type Mod, type Version } from '@modrinth/utils'
import { formatVersionsForDisplay, type Mod, type Version } from '@modrinth/utils'
import { computed, ref } from 'vue'
import Accordion from '~/components/ui/Accordion.vue'
@@ -265,6 +275,8 @@ import ContentVersionFilter, {
} from '~/components/ui/servers/ContentVersionFilter.vue'
import LoaderIcon from '~/components/ui/servers/icons/LoaderIcon.vue'
const { formatMessage } = useVIntl()
const props = defineProps<{
type: 'Mod' | 'Plugin'
loader: string
@@ -424,7 +436,10 @@ const formattedVersions = computed(() => {
if (secondLoaderPosition === -1) return -1
return firstLoaderPosition - secondLoaderPosition
})
.map((loader: string) => formatCategory(loader)),
.map((loader: string) => {
const message = getTagMessageOrDefault(loader, 'loader')
return typeof message === 'string' ? message : formatMessage(message)
}),
}
})
@@ -237,7 +237,7 @@ function navigateToFolder() {
const newPath = currentPath.endsWith('/')
? `${currentPath}${props.name}`
: `${currentPath}/${props.name}`
router.push({ query: { path: newPath, page: 1 } })
router.push({ query: { path: newPath } })
}
const isNavigating = ref(false)
@@ -32,12 +32,7 @@
<label class="w-full text-lg font-bold text-contrast" for="modpack-hard-reset">
Erase all data
</label>
<input
id="modpack-hard-reset"
v-model="hardReset"
class="switch stylized-toggle shrink-0"
type="checkbox"
/>
<Toggle id="modpack-hard-reset" v-model="hardReset" class="shrink-0" />
</div>
<div>
If enabled, existing mods, worlds, and configurations, will be deleted before installing
@@ -69,7 +64,7 @@
<script setup lang="ts">
import { DownloadIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, Combobox, injectNotificationManager, NewModal } from '@modrinth/ui'
import { ButtonStyled, Combobox, injectNotificationManager, NewModal, Toggle } from '@modrinth/ui'
import { ModrinthServersFetchError } from '@modrinth/utils'
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'
@@ -158,9 +153,3 @@ const hide = () => modal.value?.hide()
defineExpose({ show, hide })
</script>
<style scoped>
.stylized-toggle:checked::after {
background: var(--color-accent-contrast) !important;
}
</style>
@@ -53,12 +53,7 @@
<label class="w-full text-lg font-bold text-contrast" for="hard-reset">
Erase all data
</label>
<input
id="hard-reset"
v-model="hardReset"
class="switch stylized-toggle shrink-0"
type="checkbox"
/>
<Toggle id="hard-reset" v-model="hardReset" class="shrink-0" />
</div>
<div>
Removes all data on your server, including your worlds, mods, and configuration
@@ -128,6 +123,7 @@ import {
ButtonStyled,
injectNotificationManager,
NewModal,
Toggle,
} from '@modrinth/ui'
import { ModrinthServersFetchError } from '@modrinth/utils'
import { onMounted, onUnmounted } from 'vue'
@@ -255,9 +251,3 @@ const hide = () => mrpackModal.value?.hide()
defineExpose({ show, hide })
</script>
<style scoped>
.stylized-toggle:checked::after {
background: var(--color-accent-contrast) !important;
}
</style>
@@ -143,12 +143,7 @@
<label class="w-full text-lg font-bold text-contrast" for="hard-reset">
Erase all data
</label>
<input
id="hard-reset"
v-model="hardReset"
class="switch stylized-toggle shrink-0"
type="checkbox"
/>
<Toggle id="hard-reset" v-model="hardReset" class="shrink-0" />
</div>
<div>
Removes all data on your server, including your worlds, mods, and configuration files,
@@ -542,9 +537,3 @@ const hide = () => versionSelectModal.value?.hide()
defineExpose({ show, hide })
</script>
<style scoped>
.stylized-toggle:checked::after {
background: var(--color-accent-contrast) !important;
}
</style>
@@ -274,10 +274,6 @@ watch(
</script>
<style scoped>
.stylized-toggle:checked::after {
background: var(--color-accent-contrast) !important;
}
.button-base:active {
scale: none !important;
}
@@ -1,22 +1,15 @@
<template>
<div v-if="loaderData?.icon" v-html="loaderData.icon" />
<component :is="icon" v-if="icon" />
<LoaderIcon v-else />
</template>
<script setup lang="ts">
import { LoaderIcon } from '@modrinth/assets'
import { getLoaderIcon, LoaderIcon } from '@modrinth/assets'
import { computed } from 'vue'
import { useGeneratedState } from '~/composables/generated'
const props = defineProps<{
loader: string
}>()
const tags = useGeneratedState()
// Find the loader by name (case-insensitive comparison)
const loaderData = computed(() =>
tags.value.loaders.find((l) => l.name.toLowerCase() === props.loader.toLowerCase()),
)
const icon = computed(() => getLoaderIcon(props.loader))
</script>
@@ -10,12 +10,14 @@
<MedalIcon class="h-8 w-auto text-contrast md:h-10" />
<div class="flex flex-col items-start gap-1">
<span>
Try a free
<span class="text-medal-orange">3GB server</span> for 5 days powered by
<span class="text-medal-orange">Medal</span>
<IntlFormatted :message-id="messages.info">
<template #orange="{ children }">
<span class="text-medal-orange"><component :is="() => children" /></span>
</template>
</IntlFormatted>
</span>
<span class="text-xs font-medium text-secondary md:text-sm">
Limited-time offer. No credit card required. Available for US servers.
{{ formatMessage(messages.textSecondary) }}
</span>
</div>
</div>
@@ -23,7 +25,7 @@
<nuxt-link
to="https://medal.tv/modrinth"
class="z-10 flex w-full items-center justify-center gap-1 md:mt-0 md:w-auto"
>Learn more <ExternalIcon
>{{ formatMessage(messages.learnMoreButton) }} <ExternalIcon
/></nuxt-link>
</ButtonStyled>
</div>
@@ -31,9 +33,33 @@
<script lang="ts" setup>
import { ExternalIcon } from '@modrinth/assets'
import { ButtonStyled, MedalBackgroundImage } from '@modrinth/ui'
import {
ButtonStyled,
defineMessages,
IntlFormatted,
MedalBackgroundImage,
useVIntl,
} from '@modrinth/ui'
import MedalIcon from '~/assets/images/illustrations/medal_icon.svg?component'
const { formatMessage } = useVIntl()
const messages = defineMessages({
info: {
id: 'hosting-marketing.medal.info',
defaultMessage:
'Try a free <orange>3GB server</orange> for 5 days powered by <orange>Medal</orange>',
},
textSecondary: {
id: 'hosting-marketing.medal.text-secondary',
defaultMessage: 'Limited-time offer. No credit card required. Available for US servers.',
},
learnMoreButton: {
id: 'hosting-marketing.medal.learn-more',
defaultMessage: 'Learn more',
},
})
</script>
<style scoped lang="scss">
@@ -1,6 +1,6 @@
<script setup lang="ts">
import type { MessageDescriptor } from '@modrinth/ui'
import { ButtonStyled, defineMessage, ServersSpecs, useVIntl } from '@modrinth/ui'
import { ButtonStyled, defineMessage, defineMessages, ServersSpecs, useVIntl } from '@modrinth/ui'
import { formatPrice } from '@modrinth/utils'
const { formatMessage, locale } = useVIntl()
@@ -11,6 +11,17 @@ const emit = defineEmits<{
type Plan = 'small' | 'medium' | 'large'
const messages = defineMessages({
outOfStock: {
id: 'hosting.plan.out-of-stock',
defaultMessage: 'Out of stock',
},
selectPlanButton: {
id: 'hosting.plan.select-plan',
defaultMessage: 'Select plan',
},
})
const plans: Record<
Plan,
{
@@ -134,8 +145,12 @@ const billingMonths = computed(() => {
:type="plans[plan].mostPopular ? 'standard' : 'highlight-colored-text'"
size="large"
>
<span v-if="outOfStock" class="button-like disabled"> Out of Stock </span>
<button v-else @click="() => emit('select')">Select plan</button>
<span v-if="outOfStock" class="button-like disabled">{{
formatMessage(messages.outOfStock)
}}</span>
<button v-else @click="() => emit('select')">
{{ formatMessage(messages.selectPlanButton) }}
</button>
</ButtonStyled>
<ServersSpecs
:ram="ram"
+4 -1
View File
@@ -55,5 +55,8 @@ export const useBaseFetch = async (url, options = {}, skipAuth = false) => {
delete options.apiVersion
}
return await $fetch(`${base}${url}`, options)
return await $fetch(`${base}${url}`, {
timeout: import.meta.server ? 10000 : undefined,
...options,
})
}
@@ -0,0 +1,52 @@
import type { AbstractModrinthClient } from '@modrinth/api-client'
const STALE_TIME = 1000 * 60 * 5 // 5 minutes
export const projectQueryOptions = {
v2: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', 'v2', projectId] as const,
queryFn: () => client.labrinth.projects_v2.get(projectId),
staleTime: STALE_TIME,
}),
v3: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', 'v3', projectId] as const,
queryFn: () => client.labrinth.projects_v3.get(projectId),
staleTime: STALE_TIME,
}),
members: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', projectId, 'members'] as const,
queryFn: () => client.labrinth.projects_v3.getMembers(projectId),
staleTime: STALE_TIME,
}),
dependencies: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', projectId, 'dependencies'] as const,
queryFn: () => client.labrinth.projects_v2.getDependencies(projectId),
staleTime: STALE_TIME,
}),
versionsV2: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', projectId, 'versions', 'v2'] as const,
queryFn: () =>
client.labrinth.versions_v3.getProjectVersions(projectId, { include_changelog: false }),
staleTime: STALE_TIME,
}),
versionsV3: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', projectId, 'versions', 'v3'] as const,
queryFn: () =>
client.labrinth.versions_v3.getProjectVersions(projectId, {
include_changelog: false,
apiVersion: 3,
}),
staleTime: STALE_TIME,
}),
organization: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', projectId, 'organization'] as const,
queryFn: () => client.labrinth.projects_v3.getOrganization(projectId),
staleTime: STALE_TIME,
}),
}
@@ -0,0 +1,14 @@
import type { QueryClient } from '@tanstack/vue-query'
import { useQueryClient } from '@tanstack/vue-query'
import { getCurrentInstance } from 'vue'
export function useAppQueryClient(): QueryClient {
// In components, use the standard composable
if (getCurrentInstance()) {
return useQueryClient()
}
// In middleware/server context, use the provided instance
const nuxtApp = useNuxtApp()
return nuxtApp.$queryClient as QueryClient
}
+11 -11
View File
@@ -470,7 +470,7 @@
<CurrencyIcon aria-hidden="true" /> {{ formatMessage(messages.revenue) }}
</template>
<template #analytics>
<ChartIcon aria-hidden="true" /> {{ formatMessage(messages.analytics) }}
<ChartIcon aria-hidden="true" /> {{ formatMessage(commonMessages.analyticsButton) }}
</template>
<template #moderation>
<ScaleIcon aria-hidden="true" /> {{ formatMessage(commonMessages.moderationLabel) }}
@@ -754,9 +754,10 @@ const route = useNativeRoute()
const router = useNativeRouter()
const link = config.public.siteUrl + route.path.replace(/\/+$/, '')
const { data: payoutBalance } = await useAsyncData('payout/balance', () =>
useBaseFetch('payout/balance', { apiVersion: 3 }),
)
const { data: payoutBalance } = await useAsyncData('payout/balance', () => {
if (!auth.value.user) return null
return useBaseFetch('payout/balance', { apiVersion: 3 })
})
const showTaxComplianceBanner = computed(() => {
if (flags.value.testTaxForm && auth.value.user) return true
@@ -898,10 +899,6 @@ const messages = defineMessages({
id: 'layout.nav.revenue',
defaultMessage: 'Revenue',
},
analytics: {
id: 'layout.nav.analytics',
defaultMessage: 'Analytics',
},
activeReports: {
id: 'layout.nav.active-reports',
defaultMessage: 'Active reports',
@@ -989,16 +986,19 @@ const navRoutes = computed(() => [
])
const userMenuOptions = computed(() => {
const user = auth.value.user
if (!user) return []
let options = [
{
id: 'profile',
link: `/user/${auth.value.user.username}`,
link: `/user/${user.username}`,
},
{
id: 'plus',
link: '/plus',
color: 'purple',
shown: !flags.value.hidePlusPromoInUserMenu && !isPermission(auth.value.user.badges, 1 << 0),
shown: !flags.value.hidePlusPromoInUserMenu && !isPermission(user.badges, 1 << 0),
},
{
id: 'servers',
@@ -1051,7 +1051,7 @@ const userMenuOptions = computed(() => {
{
id: 'affiliate-links',
link: '/dashboard/affiliate-links',
shown: auth.value.user.badges & UserBadge.AFFILIATE,
shown: user.badges & UserBadge.AFFILIATE,
},
{
id: 'revenue',
+9 -3
View File
@@ -38,9 +38,6 @@
"app-marketing.download.terms": {
"message": "خلال تنزيل Modrinth App فإنك توافق على <terms-link>الشروط</terms-link> و <privacy-link>سياسة الخصوصية</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "حزم الطرف الثالث"
},
"app-marketing.download.title": {
"message": "تنزيل Modrinth App (النسخة التجريبية)"
},
@@ -368,9 +365,18 @@
"collection.button.edit-icon": {
"message": "تعديل الأيقونة"
},
"collection.button.remove-icon": {
"message": "حذف الأيقونة"
},
"collection.button.remove-project": {
"message": "إزالة المشروع"
},
"collection.button.replace-icon": {
"message": "تغيير الأيقونة"
},
"collection.button.select-icon": {
"message": "تحديد الأيقونة"
},
"collection.button.unfollow-project": {
"message": "إلغاء متابعة المشروع"
},
+2 -2
View File
@@ -1,10 +1,10 @@
{
"displayName": {
"description": "Please enter the name of the language in its specific variant or regional form (e.g., English (US) for American English, not just English). If the language does not have any specific variant, simply enter the name of the language (e.g., Français, Deutsch).",
"message": "الإنجليزية (الولايات المتحدة)"
"message": "العربية (المملكة العربية السعودية)"
},
"searchTerms": {
"description": "Please provide additional search terms associated with the language, if needed, to enhance the search functionality (e.g., American English, Deutschland). Each search term should be entered on a separate line. Translate as a hyphen (-) if no additional terms are needed.",
"message": "الولايات المتحدة الأمريكية\nالإنجليزية الأمريكية"
"message": "المملكة العربية السعودية \nالعربية السعودية"
}
}
+9 -3
View File
@@ -38,9 +38,6 @@
"app-marketing.download.terms": {
"message": "Stažením aplikace Modrinth souhlasíte s našimi <terms-link>Podmínkami</terms-link> a <privacy-link>Zásadami ochrany osobních údajů</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Balíčky třetích stran"
},
"app-marketing.download.title": {
"message": "Stáhnout Modrinth App (Beta)"
},
@@ -590,6 +587,9 @@
"dashboard.collections.long-title": {
"message": "Vaše kolekce"
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Hotovo! 🎉"
},
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Jste občan USA?"
},
@@ -599,6 +599,12 @@
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Zvolte vaši zemi"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Vyhladaj štát..."
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Región"
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Majitel účtu"
},
+63 -3
View File
@@ -38,9 +38,6 @@
"app-marketing.download.terms": {
"message": "Ved at download Modrinth du acceptere vores <terms-link>servicevilkår</terms-link> og <privacy-link>privatlivspolitik</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Tredjepartspakker"
},
"app-marketing.download.title": {
"message": "Download Modrinth (Beta)"
},
@@ -191,6 +188,9 @@
"app-marketing.hero.download-modrinth-app-for-os": {
"message": "Hent Modrinth Appen til {os}"
},
"app-marketing.hero.more-download-options": {
"message": "Flere Download Muligheder"
},
"auth.authorize.action.authorize": {
"message": "Godkend"
},
@@ -287,6 +287,66 @@
"auth.sign-up.label.username": {
"message": "Brugernavn"
},
"auth.sign-up.legal-dislaimer": {
"message": "Ved at oprette en konto, accepterer du Modrinth's <terms-link>Vilkår</terms-link> og <privacy-policy-link>Privatlivspolitik</privacy-policy-link>."
},
"auth.sign-up.notification.password-mismatch.text": {
"message": "Adgangskoderne er ikke ens!"
},
"auth.sign-up.password.label": {
"message": "Adgangskode"
},
"auth.sign-up.sign-in-option.title": {
"message": "Har du allerede en konto?"
},
"auth.sign-up.subscribe.label": {
"message": "Abonner på opdateringer om Modrinth"
},
"auth.sign-up.title": {
"message": "Tilmeld"
},
"auth.sign-up.title.create-account": {
"message": "Eller opret en konto selv"
},
"auth.sign-up.title.sign-up-with": {
"message": "Tilmeld dig med"
},
"auth.verify-email.action.account-settings": {
"message": "Kontoindstillinger"
},
"auth.verify-email.action.sign-in": {
"message": "Log ind"
},
"auth.verify-email.already-verified.description": {
"message": "Din e-mail er allerede bekræftet!"
},
"auth.verify-email.already-verified.title": {
"message": "E-mail allerede bekræftet"
},
"auth.verify-email.failed-verification.action": {
"message": "Send bekræftelsesmail igen"
},
"auth.verify-email.failed-verification.description": {
"message": "Vi kunne ikke bekræfte din e-mail. Prøv at sende bekræftelsesmailen igen via dit dashboard ved at logge ind."
},
"auth.verify-email.failed-verification.description.logged-in": {
"message": "Vi kunne ikke bekræfte din e-mail. Prøv at sende bekræftelsesmailen igen via knappen nedenfor."
},
"auth.verify-email.failed-verification.title": {
"message": "E-mailbekræftelse mislykkedes"
},
"auth.verify-email.post-verification.description": {
"message": "Din e-mailadresse er blevet bekræftet!"
},
"auth.verify-email.post-verification.title": {
"message": "E-mailbekræftelse"
},
"auth.verify-email.title": {
"message": "Bekræft E-mail"
},
"auth.welcome.checkbox.subscribe": {
"message": "Abonner på opdateringer om Modrinth"
},
"collection.button.remove-project": {
"message": "Slet projekt"
},
+230 -8
View File
@@ -23,6 +23,9 @@
"app-marketing.download.download-rpm": {
"message": "Lade das RPM herunter"
},
"app-marketing.download.flathub": {
"message": "Auf Flathub herunterladen"
},
"app-marketing.download.linux": {
"message": "Linux"
},
@@ -38,9 +41,6 @@
"app-marketing.download.terms": {
"message": "Durch das herunterladen der Modrinth App stimmst du unseren <terms-link>Nutzungsbedingungen</terms-link> und <privacy-link>Datenschutzrichtlinien</privacy-link> zu."
},
"app-marketing.download.third-party-packages": {
"message": "Drittanbieter Pakete"
},
"app-marketing.download.title": {
"message": "Modrinth App (Beta) herunterladen"
},
@@ -197,6 +197,15 @@
"app-marketing.hero.more-download-options": {
"message": "Weitere Downloadoptionen"
},
"app-marketing.hide-other-packages": {
"message": "Andere Pakete verstecken"
},
"app-marketing.not-recommended": {
"message": "Wir empfehlen, diese nicht zu verwenden, ausser du weisst was du tust."
},
"app-marketing.show-other-packages": {
"message": "Andere Pakete anzeigen"
},
"auth.authorize.action.authorize": {
"message": "Autorisieren"
},
@@ -897,7 +906,7 @@
"message": "Geschätzt {date}"
},
"dashboard.revenue.processing": {
"message": "Verarbeitet"
"message": "In verarbeitung"
},
"dashboard.revenue.processing.tooltip": {
"message": "Einnahmen bleiben in bearbeitung bis zum ende des Monats, und werden 60 Tage danach verfügbar."
@@ -987,19 +996,19 @@
"message": "Konto nicht verknüpft"
},
"dashboard.withdraw.error.email-verification.text": {
"message": "Du musst deine E-Mail-Adresse bestätigen, bevor du Geld abheben kannst."
"message": "Du musst deine E-Mail-Adresse bestätigen, bevor du Geld auszahlen kannst."
},
"dashboard.withdraw.error.email-verification.title": {
"message": "E-Mail-Bestätigung erforderlich"
},
"dashboard.withdraw.error.generic.text": {
"message": "Wir konnten deine Auszahlungsanforderung nicht übermitteln. Bitte überprüfe deine Angaben oder wende dich an den Support.\n{error}"
"message": "Wir konnten deine Auszahlungsanforderung nicht übermitteln. Bitte überprüfe deine Angaben oder kontaktiere den Support.\n{error}"
},
"dashboard.withdraw.error.generic.title": {
"message": "Abheben nicht möglich"
},
"dashboard.withdraw.error.insufficient-balance.text": {
"message": "Du hast nicht genug Guthaben, um eine Auszahlung vorzunehmen."
"message": "Du hast nicht genug Guthaben, um diese Auszahlung vorzunehmen."
},
"dashboard.withdraw.error.insufficient-balance.title": {
"message": "Unzureichender Kontostand"
@@ -1029,7 +1038,7 @@
"message": "Menge zu gering"
},
"dashboard.withdraw.error.paypal-country-mismatch.text": {
"message": "Bitte nutze die richtige PayPal-Überweisungsoption für deine Region (USA oder International)."
"message": "Bitte nutze die richtige PayPal-Überweisungsoption für deine Region (US oder International)."
},
"dashboard.withdraw.error.paypal-country-mismatch.title": {
"message": "PayPal-Region stimmt nicht überein"
@@ -1142,6 +1151,213 @@
"frog.title": {
"message": "Frosch"
},
"hosting-marketing.available-locations": {
"message": "Verfügbar in Nordamerika, Europa und Südostasien für eine breite Abdeckung."
},
"hosting-marketing.billing.monthly": {
"message": "Monatlich zahlen"
},
"hosting-marketing.billing.quarterly": {
"message": "Vierteljährlich zahlen"
},
"hosting-marketing.billing.save-with-quarterly": {
"message": "Spare 16 % mit vierteljährlicher Abrechnung!"
},
"hosting-marketing.billing.starting-at": {
"message": "Ab {price} / Monat"
},
"hosting-marketing.billing.yearly": {
"message": "Jährlich zahlen"
},
"hosting-marketing.faq.burst-threads": {
"message": "Wie funktionieren CPU-Burst-Threads?"
},
"hosting-marketing.faq.burst-threads.answer": {
"message": "Wenn dein Server stark ausgelastet ist, geben wir ihm vorübergehend Zugriff auf zusätzliche CPU-Threads, um Lagspikes und Instabilität zu verringern. So wird verhindert, dass die TPS unter 20 fällt, und ein möglichst reibungsloses Erlebnis gewährleistet. Da diese zusätzlichen CPU-Threads nur kurzzeitig während Zeiten hoher Auslastung verfügbar sind, werden sie möglicherweise nicht in Spark-Berichten oder anderen Profiling-Tools angezeigt."
},
"hosting-marketing.faq.cpu-kind": {
"message": "Auf welchen CPUs laufen die Server von Modrinth Hosting?"
},
"hosting-marketing.faq.cpu-kind.answer": {
"message": "Die Server von Modrinth Hosting werden von AMD Ryzen 7900 und 7950X3D-äquivalenten CPUs mit 5+ GHz betrieben, kombiniert mit DDR5-Speicher."
},
"hosting-marketing.faq.currency": {
"message": "In welcher Währung sind die Preise angegeben?"
},
"hosting-marketing.faq.currency.answer": {
"message": "Alle Preise sind in US-Dollar (USD) angegeben."
},
"hosting-marketing.faq.ddos-protection": {
"message": "Haben die Server von Modrinth Hosting einen DDoS-Schutz?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Ja. Alle Server von Modrinth Hosting sind mit DDoS-Schutz ausgestattet, an einigen Standorten mit einer Kapazität von bis zu 17 Tbit/s."
},
"hosting-marketing.faq.heading": {
"message": "Häufig gestellte Fragen"
},
"hosting-marketing.faq.how-fast": {
"message": "Wie schnell sind die Server von Modrinth Hosting?"
},
"hosting-marketing.faq.how-fast.answer.one": {
"message": "Server von Modrinth Hosting werden auf sehr moderner, leistungsstarker Hardware gehostet, doch es ist schwer zu sagen, wie sich dies genau auf die Geschwindigkeit deines Servers auswirkt, da es so viele Faktoren gibt, die diese beeinflussen, wie beispielsweise die Mods, Datenpakete oder Plugins, die du auf deinem Server ausführst, und sogar das Verhalten der Nutzer."
},
"hosting-marketing.faq.how-fast.answer.two": {
"message": "Die meisten Leistungsprobleme entstehen in der Regel durch ein nicht optimiertes Modpack, Mod, Datenpaket oder Plugin, das zu Lag auf dem Server führt. Da unsere Server sehr leistungsstark sind, solltest du keine großen Probleme haben, solange du einen geeigneten Plan für die Inhalte wählst, die du auf dem Server ausführst."
},
"hosting-marketing.faq.increase-storage": {
"message": "Kann ich den Speicherplatz meines Servers erhöhen?"
},
"hosting-marketing.faq.increase-storage.answer": {
"message": "Ja, der Speicherplatz auf deinem Server kann ohne zusätzliche Kosten erweitert werden. Wenn du mehr Speicherplatz benötigst, wende dich bitte an den Modrinth-Support."
},
"hosting-marketing.faq.location": {
"message": "Wo befinden sich Server von Modrinth Hosting? Kann ich eine Region auswählen?"
},
"hosting-marketing.faq.location.answer": {
"message": "Derzeit sind Server in Nordamerika, Europa und Südostasien verfügbar, die du beim Kauf auswählen kannst. Weitere Regionen werden in Zukunft dazukommen! Falls du deine Region wechseln möchtest, wende dich bitte an den Support."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Welche Minecraft-Versionen und Loader können verwendet werden?"
},
"hosting-marketing.faq.versions-loaders.answer.one": {
"message": "Server von Modrinth Hosting können jede Version von Minecraft: Java Edition bis zurück zur Version 1.2.5 ausführen, einschließlich Snapshot-Versionen."
},
"hosting-marketing.faq.versions-loaders.answer.two": {
"message": "Wir unterstützen außerdem eine Vielzahl von Mod- und Plugin-Loadern, darunter Fabric, Quilt, Forge und NeoForge für Mods sowie Paper und Purpur für Plugins. Die Verfügbarkeit hängt davon ab, ob der Mod- oder Plugin-Loader die ausgewählte Minecraft-Version unterstützt."
},
"hosting-marketing.get-started": {
"message": "Loslegen"
},
"hosting-marketing.hero.button.manage-your-servers": {
"message": "Verwalte deine Server"
},
"hosting-marketing.hero.button.start-a-new-server": {
"message": "Starte einen neuen Server"
},
"hosting-marketing.hero.button.start-your-server": {
"message": "Starte deinen Server"
},
"hosting-marketing.hero.host-with-modrinth": {
"message": "Hoste deinen nächsten Server mit Modrinth Hosting"
},
"hosting-marketing.hero.hosting-description": {
"message": "Modrinth Hosting ist der einfachste Weg, deinen eigenen Minecraft: Java Edition-Server zu hosten. Installiere und spiele deine Lieblings-Mods und Modpacks nahtlos innerhalb der Modrinth-Plattform."
},
"hosting-marketing.included.advanced-networking": {
"message": "Fortgeschrittenes Netzwerkmanagement"
},
"hosting-marketing.included.advanced-networking.description": {
"message": "Füge deinem Server deine eigene Domain hinzu, reserviere bis zu 15 Ports für Mods, die diese benötigen, und vieles mehr."
},
"hosting-marketing.included.backups-included": {
"message": "Backups enthalten"
},
"hosting-marketing.included.backups-included.description": {
"message": "Jeder Server verfügt über 15 Backups, die sicher an einem externen Standort gespeichert werden."
},
"hosting-marketing.included.custom-url": {
"message": "Benutzerdefinierte URL"
},
"hosting-marketing.included.custom-url.description": {
"message": "Teile deinen Server mit einer benutzerdefinierten <contrast>modrinth.gg</contrast>-URL."
},
"hosting-marketing.included.description": {
"message": "Jeder Server verfügt über eine Vielzahl von Funktionen, die ein Hosting-Erlebnis ermöglichen, wie es nur Modrinth bieten kann."
},
"hosting-marketing.included.file-manager": {
"message": "Einfach zu bedienender Dateimanager"
},
"hosting-marketing.included.file-manager.description": {
"message": "Suche, verwalte, bearbeite und lade Dateien ganz einfach direkt auf deinen Server hoch."
},
"hosting-marketing.included.heading": {
"message": "Mit allen Funktionen, die du benötigst."
},
"hosting-marketing.included.help": {
"message": "Hilfe wenn du sie brauchst"
},
"hosting-marketing.included.help.description": {
"message": "Wende dich jederzeit an das Modrinth-Team, falls du Hilfe mit deinem Server benötigst."
},
"hosting-marketing.included.powerful-console": {
"message": "Eine leistungsstarke Konsole, ein Servereigenschaften-Manager und vieles mehr"
},
"hosting-marketing.included.powerful-console.description": {
"message": "Modrinth Hosting bietet leistungsstarke Tools zur Verwaltung deines Servers."
},
"hosting-marketing.included.sftp-access": {
"message": "Zugriff über SFTP"
},
"hosting-marketing.included.sftp-access.description": {
"message": "Greife mit dem in Modrinth Hosting integrierten SFTP direkt auf die Dateien deines Servers zu."
},
"hosting-marketing.included.with-your-server": {
"message": "Bei deinem Server enthalten"
},
"hosting-marketing.know-what-you-need": {
"message": "Du weißt genau, was du brauchst?"
},
"hosting-marketing.medal.info": {
"message": "Teste 5 Tage lang kostenlos einen <orange>3 GB Server</orange>, unterstützt von <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Mehr erfahren"
},
"hosting-marketing.medal.text-secondary": {
"message": "Zeitlich begrenztes Angebot. Keine Kreditkarte erforderlich. Verfügbar für US-Server."
},
"hosting-marketing.pick-customized-plan": {
"message": "Wähle einen individuellen Plan mit genau den Spezifikationen, die du benötigst."
},
"hosting-marketing.server-for-everyone": {
"message": "Für jeden gibt es einen Server"
},
"hosting-marketing.why.all-on-modrinth": {
"message": "Verwalte alles auf Modrinth"
},
"hosting-marketing.why.all-on-modrinth.description": {
"message": "Dein Server, deine Mods, deine Spieler und vieles mehr befinden sich alle auf Modrinth. Du musst nicht zwischen verschiedenen Plattformen wechseln."
},
"hosting-marketing.why.consistently-fast": {
"message": "Konstant schnell"
},
"hosting-marketing.why.consistently-fast.description": {
"message": "Unsere Infrastruktur ist niemals überlastet, was bedeutet, dass jeder bei Modrinth gehostete Server stets mit voller Leistung läuft."
},
"hosting-marketing.why.description": {
"message": "Wähle aus Tausenden von Modpacks auf Modrinth oder erstelle dein eigenes. Lade deine Freunde ein, wenn du bereit bist zu spielen."
},
"hosting-marketing.why.heading": {
"message": "Finde ein Modpack. Jetzt ist es ein Server."
},
"hosting-marketing.why.modern-reliable-hosting": {
"message": "Entdecke modernes, zuverlässiges Hosting"
},
"hosting-marketing.why.modern-reliable-hosting.description": {
"message": "Server von Modrinth Hosting werden auf <contrast>leistungsstarken AMD-CPUs mit DDR5-Arbeitsspeicher</contrast> gehostet und laufen mit speziell entwickelter Software, um einen reibungslosen Betrieb deines Servers zu ermöglichen."
},
"hosting-marketing.why.where-mods-are": {
"message": "Spiele da, wo deine Mods sind"
},
"hosting-marketing.why.where-mods-are.description": {
"message": "Modrinth Hosting integriert die Installation von Mods und Modpacks nahtlos in deinen Server."
},
"hosting-marketing.why.why-modrinth-hosting": {
"message": "Warum Modrinth Hosting?"
},
"hosting-marketing.why.your-favorite-mods": {
"message": "Alle deine Lieblingsmods"
},
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Wähle zwischen Vanilla, Fabric, Forge, Quilt und NeoForge. Was auf Modrinth ist, kann auf deinem Server laufen."
},
"hosting.plan.out-of-stock": {
"message": "Nicht verfügbar"
},
"hosting.plan.select-plan": {
"message": "Plan auswählen"
},
"landing.button.discover-mods": {
"message": "Entdecke Mods"
},
@@ -1337,6 +1553,12 @@
"layout.banner.build-fail.title": {
"message": "Fehler beim generieren des Status von der API beim erstellen."
},
"layout.banner.preview.description": {
"message": "Falls du die offizielle Modrinth-Website aufrufen wolltest, besuch <link>https://modrinth.com</link>. Diese Vorschauversion wird von Modrinth-Mitarbeitern zu Testzwecken genutzt. Sie wurde unter Verwendung von <branch-link>{owner}/{branch}</branch-link> @ {commit} erstellt."
},
"layout.banner.preview.title": {
"message": "Dies ist eine Vorschauversion der Modrinth-Webseite."
},
"layout.banner.staging.description": {
"message": "Die Staging-Umgebung ist komplett separat von der Produktions-Datenbank von Modrinth. Sie wird zu Test- und Debugging-Zwecken verwendet und könnte Entwicklungsversionen des Modrinth-Backends oder -Frontends, welche neuer als die Produkionsinstanz sind, ausführen."
},
+234 -12
View File
@@ -23,6 +23,9 @@
"app-marketing.download.download-rpm": {
"message": "Lade das RPM herunter"
},
"app-marketing.download.flathub": {
"message": "Jetzt auf Flathub"
},
"app-marketing.download.linux": {
"message": "Linux"
},
@@ -38,9 +41,6 @@
"app-marketing.download.terms": {
"message": "Mit dem Herunterladen der Modrinth App stimmst du unseren <terms-link>Nutzungsbedingungen</terms-link> und der <privacy-link>Datenschutzrichtlinie</privacy-link> zu."
},
"app-marketing.download.third-party-packages": {
"message": "Pakete von Drittanbietern"
},
"app-marketing.download.title": {
"message": "Modrinth App (Beta) herunterladen"
},
@@ -99,7 +99,7 @@
"message": "Der Modrinth-Launcher ist vollständig quelloffen. Den Quellcode kannst du auf unserem <github-link>GitHub</github-link> einsehen!"
},
"app-marketing.features.open-source.title": {
"message": "Quelloffen"
"message": "Open Source"
},
"app-marketing.features.performance.activity-monitor": {
"message": "Aktivitätsmonitor"
@@ -114,7 +114,7 @@
"message": "Discord"
},
"app-marketing.features.performance.good-performance": {
"message": "Gute Performance"
"message": "Gute Leistung"
},
"app-marketing.features.performance.google-chrome": {
"message": "Google Chrome"
@@ -197,6 +197,15 @@
"app-marketing.hero.more-download-options": {
"message": "Mehr Downloadoptionen"
},
"app-marketing.hide-other-packages": {
"message": "Andere Pakete ausblenden"
},
"app-marketing.not-recommended": {
"message": "Wir empfehlen, diese nur zu verwenden, wenn du weißt, was du tust."
},
"app-marketing.show-other-packages": {
"message": "Andere Pakete anzeigen"
},
"auth.authorize.action.authorize": {
"message": "Autorisieren"
},
@@ -621,7 +630,7 @@
"message": "Dein {formType} Steuerformular wurde erfolgreich eingereicht!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Du kannst jetzt frei abheben. Wenn du Fragen hast oder deine Angaben aktualisieren musst, <support-link>wende dich an den Support</support-link>."
"message": "Du kannst jetzt jederzeit auszahlen. Falls du Fragen hast oder deine Angaben aktualisieren möchtest, <support-link>kontaktiere den Support</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Du bist startklar! 🎉"
@@ -897,7 +906,7 @@
"message": "Geschätzt {date}"
},
"dashboard.revenue.processing": {
"message": "Verarbeitet"
"message": "In Verarbeitung"
},
"dashboard.revenue.processing.tooltip": {
"message": "Einnahmen bleiben in bearbeitung bis zum ende des Monats, und werden 60 Tage danach verfügbar."
@@ -912,7 +921,7 @@
"message": "Ausgezahlt"
},
"dashboard.revenue.tos": {
"message": "Durch das hochladen von Projekten auf Modrinth, und das abheben von Geld von deinem Konto, stimmst du den <terms-link>Bedingungen des Rewards-Programm</terms-link> zu. Erfahre mehr über das <info-link>Reward-Programm</info-link>."
"message": "Durch das Hochladen von Projekten auf Modrinth und das Auszahlen von Geld von deinem Konto stimmst du unseren <terms-link>Bedingungen für das Prämienprogramm</terms-link> zu. Erfahre mehr über das <info-link>Prämienprogramm</info-link>."
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Als CSV herunterladen"
@@ -936,10 +945,10 @@
"message": "Hebe von deinem Verfügbaren Guthaben über einen Zahlungsmethode ab."
},
"dashboard.revenue.withdraw.card.title": {
"message": "Abheben"
"message": "Auszahlen"
},
"dashboard.revenue.withdraw.header": {
"message": "Abheben"
"message": "Auszahlen"
},
"dashboard.withdraw.completion.account": {
"message": "Konto"
@@ -987,7 +996,7 @@
"message": "Konto nicht verknüpft"
},
"dashboard.withdraw.error.email-verification.text": {
"message": "Du musst deine E-Mail-Adresse bestätigen, bevor du Geld abheben kannst."
"message": "Du musst deine E-Mail-Adresse bestätigen, bevor du Geld auszahlen kannst."
},
"dashboard.withdraw.error.email-verification.title": {
"message": "E-Mail-Bestätigung erforderlich"
@@ -996,7 +1005,7 @@
"message": "Wir konnten deine Auszahlungsanforderung nicht übermitteln. Bitte überprüfe deine Angaben oder wende dich an den Support.\n{error}"
},
"dashboard.withdraw.error.generic.title": {
"message": "Abheben nicht möglich"
"message": "Auszahlung nicht möglich"
},
"dashboard.withdraw.error.insufficient-balance.text": {
"message": "Du hast nicht genug Guthaben, um eine Auszahlung vorzunehmen."
@@ -1142,6 +1151,213 @@
"frog.title": {
"message": "Frosch"
},
"hosting-marketing.available-locations": {
"message": "Verfügbar in Nordamerika, Europa und Südostasien für eine breite Abdeckung."
},
"hosting-marketing.billing.monthly": {
"message": "Monatlich zahlen"
},
"hosting-marketing.billing.quarterly": {
"message": "Vierteljährlich zahlen"
},
"hosting-marketing.billing.save-with-quarterly": {
"message": "Spare 16 % mit vierteljährlicher Abrechnung!"
},
"hosting-marketing.billing.starting-at": {
"message": "Ab {price} / Monat"
},
"hosting-marketing.billing.yearly": {
"message": "Jährlich zahlen"
},
"hosting-marketing.faq.burst-threads": {
"message": "Wie funktionieren CPU-Burst-Threads?"
},
"hosting-marketing.faq.burst-threads.answer": {
"message": "Wenn dein Server stark ausgelastet ist, geben wir ihm vorübergehend Zugriff auf zusätzliche CPU-Threads, um Lagspikes und Instabilität zu verringern. So wird verhindert, dass die TPS unter 20 fällt, und ein möglichst reibungsloses Erlebnis gewährleistet. Da diese zusätzlichen CPU-Threads nur kurzzeitig während Zeiten hoher Auslastung verfügbar sind, werden sie möglicherweise nicht in Spark-Berichten oder anderen Profiling-Tools angezeigt."
},
"hosting-marketing.faq.cpu-kind": {
"message": "Auf welchen CPUs laufen die Server von Modrinth Hosting?"
},
"hosting-marketing.faq.cpu-kind.answer": {
"message": "Die Server von Modrinth Hosting werden von AMD Ryzen 7900 und 7950X3D-äquivalenten CPUs mit 5+ GHz betrieben, kombiniert mit DDR5-Speicher."
},
"hosting-marketing.faq.currency": {
"message": "In welcher Währung sind die Preise angegeben?"
},
"hosting-marketing.faq.currency.answer": {
"message": "Alle Preise sind in US-Dollar (USD) angegeben."
},
"hosting-marketing.faq.ddos-protection": {
"message": "Haben die Server von Modrinth Hosting einen DDoS-Schutz?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Ja. Alle Server von Modrinth Hosting sind mit DDoS-Schutz ausgestattet, an einigen Standorten mit einer Kapazität von bis zu 17 Tbit/s."
},
"hosting-marketing.faq.heading": {
"message": "Häufig gestellte Fragen"
},
"hosting-marketing.faq.how-fast": {
"message": "Wie schnell sind die Server von Modrinth Hosting?"
},
"hosting-marketing.faq.how-fast.answer.one": {
"message": "Server von Modrinth Hosting werden auf sehr moderner, leistungsstarker Hardware gehostet, doch es ist schwer zu sagen, wie sich dies genau auf die Geschwindigkeit deines Servers auswirkt, da es so viele Faktoren gibt, die diese beeinflussen, wie beispielsweise die Mods, Datenpakete oder Plugins, die du auf deinem Server ausführst, und sogar das Verhalten der Nutzer."
},
"hosting-marketing.faq.how-fast.answer.two": {
"message": "Die meisten Leistungsprobleme entstehen in der Regel durch ein nicht optimiertes Modpack, Mod, Datenpaket oder Plugin, das zu Lag auf dem Server führt. Da unsere Server sehr leistungsstark sind, solltest du keine großen Probleme haben, solange du einen geeigneten Plan für die Inhalte wählst, die du auf dem Server ausführst."
},
"hosting-marketing.faq.increase-storage": {
"message": "Kann ich den Speicherplatz meines Servers erhöhen?"
},
"hosting-marketing.faq.increase-storage.answer": {
"message": "Ja, der Speicherplatz auf deinem Server kann ohne zusätzliche Kosten erweitert werden. Wenn du mehr Speicherplatz benötigst, wende dich bitte an den Modrinth-Support."
},
"hosting-marketing.faq.location": {
"message": "Wo befinden sich Server von Modrinth Hosting? Kann ich eine Region auswählen?"
},
"hosting-marketing.faq.location.answer": {
"message": "Derzeit sind Server in Nordamerika, Europa und Südostasien verfügbar, die du beim Kauf auswählen kannst. Weitere Regionen werden in Zukunft dazukommen! Falls du deine Region wechseln möchtest, wende dich bitte an den Support."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Welche Minecraft-Versionen und Loader können verwendet werden?"
},
"hosting-marketing.faq.versions-loaders.answer.one": {
"message": "Server von Modrinth Hosting können jede Version von Minecraft: Java Edition bis zurück zur Version 1.2.5 ausführen, einschließlich Snapshot-Versionen."
},
"hosting-marketing.faq.versions-loaders.answer.two": {
"message": "Wir unterstützen außerdem eine Vielzahl von Mod- und Plugin-Loadern, darunter Fabric, Quilt, Forge und NeoForge für Mods sowie Paper und Purpur für Plugins. Die Verfügbarkeit hängt davon ab, ob der Mod- oder Plugin-Loader die ausgewählte Minecraft-Version unterstützt."
},
"hosting-marketing.get-started": {
"message": "Loslegen"
},
"hosting-marketing.hero.button.manage-your-servers": {
"message": "Verwalte deine Server"
},
"hosting-marketing.hero.button.start-a-new-server": {
"message": "Starte einen neuen Server"
},
"hosting-marketing.hero.button.start-your-server": {
"message": "Starte deinen Server"
},
"hosting-marketing.hero.host-with-modrinth": {
"message": "Hoste deinen nächsten Server mit Modrinth Hosting"
},
"hosting-marketing.hero.hosting-description": {
"message": "Modrinth Hosting ist der einfachste Weg, deinen eigenen Minecraft: Java Edition-Server zu hosten. Installiere und spiele deine Lieblings-Mods und Modpacks nahtlos innerhalb der Modrinth-Plattform."
},
"hosting-marketing.included.advanced-networking": {
"message": "Fortgeschrittenes Netzwerkmanagement"
},
"hosting-marketing.included.advanced-networking.description": {
"message": "Füge deinem Server deine eigene Domain hinzu, reserviere bis zu 15 Ports für Mods, die diese benötigen, und vieles mehr."
},
"hosting-marketing.included.backups-included": {
"message": "Backups enthalten"
},
"hosting-marketing.included.backups-included.description": {
"message": "Jeder Server verfügt über 15 Backups, die sicher an einem externen Standort gespeichert werden."
},
"hosting-marketing.included.custom-url": {
"message": "Benutzerdefinierte URL"
},
"hosting-marketing.included.custom-url.description": {
"message": "Teile deinen Server mit einer benutzerdefinierten <contrast>modrinth.gg</contrast>-URL."
},
"hosting-marketing.included.description": {
"message": "Jeder Server verfügt über eine Vielzahl von Funktionen, die ein Hosting-Erlebnis ermöglichen, wie es nur Modrinth bieten kann."
},
"hosting-marketing.included.file-manager": {
"message": "Einfach zu bedienender Dateimanager"
},
"hosting-marketing.included.file-manager.description": {
"message": "Suche, verwalte, bearbeite und lade Dateien ganz einfach direkt auf deinen Server hoch."
},
"hosting-marketing.included.heading": {
"message": "Mit allen Funktionen, die du benötigst."
},
"hosting-marketing.included.help": {
"message": "Hilfe wenn du sie brauchst"
},
"hosting-marketing.included.help.description": {
"message": "Wende dich jederzeit an das Modrinth-Team, falls du Hilfe mit deinem Server benötigst."
},
"hosting-marketing.included.powerful-console": {
"message": "Eine leistungsstarke Konsole, ein Servereigenschaften-Manager und vieles mehr"
},
"hosting-marketing.included.powerful-console.description": {
"message": "Modrinth Hosting bietet leistungsstarke Tools zur Verwaltung deines Servers."
},
"hosting-marketing.included.sftp-access": {
"message": "Zugriff über SFTP"
},
"hosting-marketing.included.sftp-access.description": {
"message": "Greife mit dem in Modrinth Hosting integrierten SFTP direkt auf die Dateien deines Servers zu."
},
"hosting-marketing.included.with-your-server": {
"message": "Bei deinem Server enthalten"
},
"hosting-marketing.know-what-you-need": {
"message": "Du weißt genau, was du brauchst?"
},
"hosting-marketing.medal.info": {
"message": "Teste 5 Tage lang kostenlos einen <orange>3 GB Server</orange>, unterstützt von <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Mehr erfahren"
},
"hosting-marketing.medal.text-secondary": {
"message": "Zeitlich begrenztes Angebot. Keine Kreditkarte erforderlich. Verfügbar für US-Server."
},
"hosting-marketing.pick-customized-plan": {
"message": "Wähle einen individuellen Plan mit genau den Spezifikationen, die du benötigst."
},
"hosting-marketing.server-for-everyone": {
"message": "Für jeden gibt es einen Server"
},
"hosting-marketing.why.all-on-modrinth": {
"message": "Verwalte alles auf Modrinth"
},
"hosting-marketing.why.all-on-modrinth.description": {
"message": "Dein Server, deine Mods, deine Spieler und vieles mehr befinden sich alle auf Modrinth. Du musst nicht zwischen verschiedenen Plattformen wechseln."
},
"hosting-marketing.why.consistently-fast": {
"message": "Konstant schnell"
},
"hosting-marketing.why.consistently-fast.description": {
"message": "Unsere Infrastruktur ist niemals überlastet, was bedeutet, dass jeder bei Modrinth gehostete Server stets mit voller Leistung läuft."
},
"hosting-marketing.why.description": {
"message": "Wähle aus Tausenden von Modpacks auf Modrinth oder erstelle dein eigenes. Lade deine Freunde ein, wenn du bereit bist zu spielen."
},
"hosting-marketing.why.heading": {
"message": "Finde ein Modpack. Jetzt ist es ein Server."
},
"hosting-marketing.why.modern-reliable-hosting": {
"message": "Entdecke modernes, zuverlässiges Hosting"
},
"hosting-marketing.why.modern-reliable-hosting.description": {
"message": "Server von Modrinth Hosting werden auf <contrast>leistungsstarken AMD-CPUs mit DDR5-Arbeitsspeicher</contrast> gehostet und laufen mit speziell entwickelter Software, um einen reibungslosen Betrieb deines Servers zu ermöglichen."
},
"hosting-marketing.why.where-mods-are": {
"message": "Spiele da, wo deine Mods sind"
},
"hosting-marketing.why.where-mods-are.description": {
"message": "Modrinth Hosting integriert die Installation von Mods und Modpacks nahtlos in deinen Server."
},
"hosting-marketing.why.why-modrinth-hosting": {
"message": "Warum Modrinth Hosting?"
},
"hosting-marketing.why.your-favorite-mods": {
"message": "Alle deine Lieblingsmods"
},
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Wähle zwischen Vanilla, Fabric, Forge, Quilt und NeoForge. Was auf Modrinth ist, kann auf deinem Server laufen."
},
"hosting.plan.out-of-stock": {
"message": "Nicht verfügbar"
},
"hosting.plan.select-plan": {
"message": "Plan auswählen"
},
"landing.button.discover-mods": {
"message": "Entdecke Mods"
},
@@ -1337,6 +1553,12 @@
"layout.banner.build-fail.title": {
"message": "Fehler beim Generieren des Status aus der API beim Erstellen."
},
"layout.banner.preview.description": {
"message": "Falls du die offizielle Modrinth-Website aufrufen wolltest, besuch <link>https://modrinth.com</link>. Diese Vorschauversion wird von Modrinth-Mitarbeitern zu Testzwecken genutzt. Sie wurde unter Verwendung von <branch-link>{owner}/{branch}</branch-link> @ {commit} erstellt."
},
"layout.banner.preview.title": {
"message": "Dies ist eine Vorschauversion der Modrinth-Website."
},
"layout.banner.staging.description": {
"message": "Die Staging-Umgebung ist vollständig von der Modrinth Produktionsdatenbank getrennt. Sie wird zu Test- und Debugging-Zwecken verwendet und kann Entwicklungsversionen des Modrinth Backends oder -Frontends ausführen, die neuer sind als die Produktionsinstanz."
},
+222 -168
View File
@@ -23,6 +23,9 @@
"app-marketing.download.download-rpm": {
"message": "Download the RPM"
},
"app-marketing.download.flathub": {
"message": "Get it on Flathub"
},
"app-marketing.download.linux": {
"message": "Linux"
},
@@ -38,9 +41,6 @@
"app-marketing.download.terms": {
"message": "By downloading Modrinth App you agree to our <terms-link>Terms</terms-link> and <privacy-link>Privacy Policy</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Third-party packages"
},
"app-marketing.download.title": {
"message": "Download Modrinth App (Beta)"
},
@@ -197,6 +197,15 @@
"app-marketing.hero.more-download-options": {
"message": "More Download Options"
},
"app-marketing.hide-other-packages": {
"message": "Hide other packages"
},
"app-marketing.not-recommended": {
"message": "We don't recommend you use these unless you know what you're doing."
},
"app-marketing.show-other-packages": {
"message": "Show other packages"
},
"auth.authorize.action.authorize": {
"message": "Authorize"
},
@@ -221,12 +230,6 @@
"auth.reset-password.method-choice.description": {
"message": "Enter your email below and we'll send a recovery link to allow you to recover your account."
},
"auth.reset-password.method-choice.email-username.label": {
"message": "Email or username"
},
"auth.reset-password.method-choice.email-username.placeholder": {
"message": "Email"
},
"auth.reset-password.notification.email-sent.text": {
"message": "An email with instructions has been sent to you if the email was previously saved on your account."
},
@@ -266,12 +269,6 @@
"auth.sign-in.additional-options": {
"message": "<forgot-password-link>Forgot password?</forgot-password-link> • <create-account-link>Create an account</create-account-link>"
},
"auth.sign-in.email-username.label": {
"message": "Email or username"
},
"auth.sign-in.password.label": {
"message": "Password"
},
"auth.sign-in.sign-in-with": {
"message": "Sign in with"
},
@@ -284,24 +281,12 @@
"auth.sign-up.action.create-account": {
"message": "Create account"
},
"auth.sign-up.confirm-password.label": {
"message": "Confirm password"
},
"auth.sign-up.email.label": {
"message": "Email"
},
"auth.sign-up.label.username": {
"message": "Username"
},
"auth.sign-up.legal-dislaimer": {
"message": "By creating an account, you agree to Modrinth's <terms-link>Terms</terms-link> and <privacy-policy-link>Privacy Policy</privacy-policy-link>."
},
"auth.sign-up.notification.password-mismatch.text": {
"message": "Passwords do not match!"
},
"auth.sign-up.password.label": {
"message": "Password"
},
"auth.sign-up.sign-in-option.title": {
"message": "Already have an account?"
},
@@ -320,9 +305,6 @@
"auth.verify-email.action.account-settings": {
"message": "Account settings"
},
"auth.verify-email.action.sign-in": {
"message": "Sign in"
},
"auth.verify-email.already-verified.description": {
"message": "Your email is already verified!"
},
@@ -407,12 +389,6 @@
"collection.label.curated-by": {
"message": "Curated by"
},
"collection.label.description": {
"message": "Description"
},
"collection.label.details": {
"message": "Details"
},
"collection.label.no-projects": {
"message": "No projects in collection yet"
},
@@ -431,27 +407,15 @@
"collection.title": {
"message": "{name} - Collection"
},
"common.no": {
"message": "No"
},
"common.yes": {
"message": "Yes"
},
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "Supplementary files are for supporting resources like source code, not for alternative versions or variants."
},
"create.collection.cancel": {
"message": "Cancel"
},
"create.collection.collection-info": {
"message": "Your new collection will be created as a public collection with {count, plural, =0 {no projects} one {# project} other {# projects}}."
},
"create.collection.create-collection": {
"message": "Create collection"
},
"create.collection.error-title": {
"message": "An error occurred"
},
"create.collection.name-label": {
"message": "Name"
},
@@ -503,15 +467,9 @@
"create.limit-alert.type-project": {
"message": "project"
},
"create.organization.cancel": {
"message": "Cancel"
},
"create.organization.create-organization": {
"message": "Create organization"
},
"create.organization.error-title": {
"message": "An error occurred"
},
"create.organization.name-label": {
"message": "Name"
},
@@ -536,15 +494,9 @@
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "Cancel"
},
"create.project.create-project": {
"message": "Create project"
},
"create.project.error-title": {
"message": "An error occurred"
},
"create.project.name-label": {
"message": "Name"
},
@@ -569,9 +521,6 @@
"create.project.visibility-description": {
"message": "The visibility of your project after it has been approved."
},
"create.project.visibility-label": {
"message": "Visibility"
},
"create.project.visibility-private": {
"message": "Private"
},
@@ -779,15 +728,9 @@
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Connect your PayPal account to receive payments directly."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Save"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Venmo handle saved successfully!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Saved"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Sign in with PayPal"
},
@@ -806,18 +749,9 @@
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Method"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Account Details"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Verification"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Tax form"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Details"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "To withdraw your full <b>{available}</b> available balance please complete the form below. It is required for tax reporting and only needs to be done once."
},
@@ -947,9 +881,6 @@
"dashboard.withdraw.completion.amount": {
"message": "Amount"
},
"dashboard.withdraw.completion.close-button": {
"message": "Close"
},
"dashboard.withdraw.completion.date": {
"message": "Date"
},
@@ -1142,6 +1073,213 @@
"frog.title": {
"message": "Frog"
},
"hosting-marketing.available-locations": {
"message": "Available in North America, Europe, and Southeast Asia for wide coverage."
},
"hosting-marketing.billing.monthly": {
"message": "Pay monthly"
},
"hosting-marketing.billing.quarterly": {
"message": "Pay quarterly"
},
"hosting-marketing.billing.save-with-quarterly": {
"message": "Save 16% with quarterly billing!"
},
"hosting-marketing.billing.starting-at": {
"message": "Starting at {price} / month"
},
"hosting-marketing.billing.yearly": {
"message": "Pay yearly"
},
"hosting-marketing.faq.burst-threads": {
"message": "How do CPU burst threads work?"
},
"hosting-marketing.faq.burst-threads.answer": {
"message": "When your server is under heavy load, we temporarily give it access to additional CPU threads to help mitigate lag spikes and instability. This helps prevent the TPS from going below 20, ensuring the smoothest experience possible. Since those extra CPU threads are only shortly available during high load periods, they might not show up in Spark reports or other profiling tools."
},
"hosting-marketing.faq.cpu-kind": {
"message": "What kind of CPUs do Modrinth Hosting servers run on?"
},
"hosting-marketing.faq.cpu-kind.answer": {
"message": "Modrinth Hosting servers are powered by AMD Ryzen 7900 and 7950X3D equivalent CPUs at 5+ GHz, paired with DDR5 memory."
},
"hosting-marketing.faq.currency": {
"message": "What currency are the prices in?"
},
"hosting-marketing.faq.currency.answer": {
"message": "All prices are listed in United States Dollars (USD)."
},
"hosting-marketing.faq.ddos-protection": {
"message": "Do Modrinth Hosting servers have DDoS protection?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Yes. All Modrinth Hosting servers come with DDoS protection, with up to 17Tbps capacity in some locations."
},
"hosting-marketing.faq.heading": {
"message": "Frequently Asked Questions"
},
"hosting-marketing.faq.how-fast": {
"message": "How fast are Modrinth Hosting servers?"
},
"hosting-marketing.faq.how-fast.answer.one": {
"message": "Modrinth Hosting servers are hosted on very modern high-performance hardware, but it's tough to say how exactly that will translate into how fast your server will run because there are so many factors that affect it, such as the mods, data packs, or plugins you're running on your server, and even user behavior."
},
"hosting-marketing.faq.how-fast.answer.two": {
"message": "Most performance issues that arise tend to be the fault of an unoptimized modpack, mod, data pack, or plugin that causes the server to lag. Since our servers are very high-end, you shouldn't run into much trouble as long as you pick an appropriate plan for the content you're running on the server."
},
"hosting-marketing.faq.increase-storage": {
"message": "Can I increase the storage on my server?"
},
"hosting-marketing.faq.increase-storage.answer": {
"message": "Yes, storage can be increased on your server at no additional cost. If you need more storage, reach out to Modrinth Support."
},
"hosting-marketing.faq.location": {
"message": "Where are Modrinth Hosting servers located? Can I choose a region?"
},
"hosting-marketing.faq.location.answer": {
"message": "We have servers available in North America, Europe, and Southeast Asia at the moment that you can choose upon purchase. More regions to come in the future! If you'd like to switch your region, please contact support."
},
"hosting-marketing.faq.versions-loaders": {
"message": "What Minecraft versions and loaders can be used?"
},
"hosting-marketing.faq.versions-loaders.answer.one": {
"message": "Modrinth Hosting servers can run any version of Minecraft: Java Edition going all the way back to version 1.2.5, including snapshot versions."
},
"hosting-marketing.faq.versions-loaders.answer.two": {
"message": "We also support a wide range of mod and plugin loaders, including Fabric, Quilt, Forge, and NeoForge for mods, as well as Paper and Purpur for plugins. Availability depends on whether the mod or plugin loader supports the selected Minecraft version."
},
"hosting-marketing.get-started": {
"message": "Get started"
},
"hosting-marketing.hero.button.manage-your-servers": {
"message": "Manage your servers"
},
"hosting-marketing.hero.button.start-a-new-server": {
"message": "Start a new server"
},
"hosting-marketing.hero.button.start-your-server": {
"message": "Start your server"
},
"hosting-marketing.hero.host-with-modrinth": {
"message": "Host your next server with Modrinth Hosting"
},
"hosting-marketing.hero.hosting-description": {
"message": "Modrinth Hosting is the easiest way to host your own Minecraft: Java Edition server. Seamlessly install and play your favorite mods and modpacks, all within the Modrinth platform."
},
"hosting-marketing.included.advanced-networking": {
"message": "Advanced networking management"
},
"hosting-marketing.included.advanced-networking.description": {
"message": "Add your own domain to your server, reserve up to 15 ports for mods that require them, and more."
},
"hosting-marketing.included.backups-included": {
"message": "Backups included"
},
"hosting-marketing.included.backups-included.description": {
"message": "Every server comes with 15 backups stored securely off-site."
},
"hosting-marketing.included.custom-url": {
"message": "Custom URL"
},
"hosting-marketing.included.custom-url.description": {
"message": "Share your server with a custom <contrast>modrinth.gg</contrast> URL."
},
"hosting-marketing.included.description": {
"message": "Included with every server is a suite of features designed to provide a hosting experience that only Modrinth can offer."
},
"hosting-marketing.included.file-manager": {
"message": "Easy to use file manager"
},
"hosting-marketing.included.file-manager.description": {
"message": "Search, manage, edit, and upload files directly to your server with ease."
},
"hosting-marketing.included.heading": {
"message": "Comes with all the features you need."
},
"hosting-marketing.included.help": {
"message": "Help when you need it"
},
"hosting-marketing.included.help.description": {
"message": "Reach out to the Modrinth team for help with your server at any time."
},
"hosting-marketing.included.powerful-console": {
"message": "A powerful console, server properties manager, and more"
},
"hosting-marketing.included.powerful-console.description": {
"message": "Modrinth Hosting comes with powerful tools to manage your server."
},
"hosting-marketing.included.sftp-access": {
"message": "SFTP access"
},
"hosting-marketing.included.sftp-access.description": {
"message": "Access your server's files directly with SFTP built into Modrinth Hosting."
},
"hosting-marketing.included.with-your-server": {
"message": "Included with your server"
},
"hosting-marketing.know-what-you-need": {
"message": "Know exactly what you need?"
},
"hosting-marketing.medal.info": {
"message": "Try a free <orange>3GB server</orange> for 5 days powered by <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Learn more"
},
"hosting-marketing.medal.text-secondary": {
"message": "Limited-time offer. No credit card required. Available for US servers."
},
"hosting-marketing.pick-customized-plan": {
"message": "Pick a customized plan with just the specs you need."
},
"hosting-marketing.server-for-everyone": {
"message": "There's a server for everyone"
},
"hosting-marketing.why.all-on-modrinth": {
"message": "Manage it all on Modrinth"
},
"hosting-marketing.why.all-on-modrinth.description": {
"message": "Your server, mods, players, and more are all on Modrinth. No need to switch between platforms."
},
"hosting-marketing.why.consistently-fast": {
"message": "Consistently fast"
},
"hosting-marketing.why.consistently-fast.description": {
"message": "Our infrastructure is never overloaded, meaning each server hosted with Modrinth always runs at its full performance."
},
"hosting-marketing.why.description": {
"message": "Choose from the thousands of modpacks on Modrinth or create your own. Invite your friends when you're ready to play."
},
"hosting-marketing.why.heading": {
"message": "Find a modpack. Now it's a server."
},
"hosting-marketing.why.modern-reliable-hosting": {
"message": "Experience modern, reliable hosting"
},
"hosting-marketing.why.modern-reliable-hosting.description": {
"message": "Modrinth Hosting servers are hosted on <contrast>high-performance AMD CPUs with DDR5 RAM</contrast>, running on custom-built software to ensure your server performs smoothly."
},
"hosting-marketing.why.where-mods-are": {
"message": "Play where your mods are"
},
"hosting-marketing.why.where-mods-are.description": {
"message": "Modrinth Hosting seamlessly integrates the mod and modpack installation process into your server."
},
"hosting-marketing.why.why-modrinth-hosting": {
"message": "Why Modrinth Hosting?"
},
"hosting-marketing.why.your-favorite-mods": {
"message": "All your favorite mods"
},
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Choose between Vanilla, Fabric, Forge, Quilt and NeoForge. If it's on Modrinth, it can run on your server."
},
"hosting.plan.out-of-stock": {
"message": "Out of stock"
},
"hosting.plan.select-plan": {
"message": "Select plan"
},
"landing.button.discover-mods": {
"message": "Discover mods"
},
@@ -1253,15 +1391,6 @@
"landing.notifications.version-released": {
"message": "Version {version} has been released for {gameVersion}"
},
"landing.search.label": {
"message": "Search"
},
"landing.search.placeholder": {
"message": "Search..."
},
"landing.search.sort-by.label": {
"message": "Sort by"
},
"landing.section.for-creators.description": {
"message": "Give an online home to your creations and reach a massive audience of dedicated players."
},
@@ -1487,9 +1616,6 @@
"layout.nav.active-reports": {
"message": "Active reports"
},
"layout.nav.analytics": {
"message": "Analytics"
},
"layout.nav.discover": {
"message": "Discover"
},
@@ -1538,9 +1664,6 @@
"layout.nav.upgrade-to-modrinth-plus": {
"message": "Upgrade to Modrinth+"
},
"moderation.filter.by": {
"message": "Filter by"
},
"moderation.moderate": {
"message": "Moderate"
},
@@ -1553,12 +1676,6 @@
"moderation.page.technicalReview": {
"message": "Technical Review"
},
"moderation.search.placeholder": {
"message": "Search..."
},
"moderation.sort.by": {
"message": "Sort by"
},
"muralpay.account-type.checking": {
"message": "Checking"
},
@@ -1886,18 +2003,12 @@
"profile.label.collection": {
"message": "Collection"
},
"profile.label.details": {
"message": "Details"
},
"profile.label.downloads": {
"message": "{count} {count, plural, one {download} other {downloads}}"
},
"profile.label.joined": {
"message": "Joined"
},
"profile.label.no": {
"message": "No"
},
"profile.label.no-collections": {
"message": "This user has no collections!"
},
@@ -1919,9 +2030,6 @@
"profile.label.saving": {
"message": "Saving..."
},
"profile.label.yes": {
"message": "Yes"
},
"profile.meta.description": {
"message": "Download {username}'s projects on Modrinth"
},
@@ -1934,15 +2042,6 @@
"profile.user-id": {
"message": "User ID: {id}"
},
"project-member-header.accept": {
"message": "Accept"
},
"project-member-header.decline": {
"message": "Decline"
},
"project-member-header.error": {
"message": "Error"
},
"project-member-header.error-decline": {
"message": "Failed to decline team invitation"
},
@@ -1958,9 +2057,6 @@
"project-member-header.invitation-with-role": {
"message": "You've been invited to be a member of this project with the role of ''{role}''."
},
"project-member-header.success": {
"message": "Success"
},
"project-member-header.success-decline": {
"message": "You have declined the team invitation"
},
@@ -2588,6 +2684,9 @@
"scopes.versionWrite.label": {
"message": "Write versions"
},
"search.filter.game-version-shader-message": {
"message": "Shader packs for older versions most likely work on newer versions with only minor issues."
},
"search.filter.locked.server": {
"message": "Provided by the server"
},
@@ -2675,9 +2774,6 @@
"settings.billing.payment_method.action.primary": {
"message": "Make primary"
},
"settings.billing.payment_method.card_display": {
"message": "{card_brand} ending in {last_four}"
},
"settings.billing.payment_method.card_expiry": {
"message": "Expires {month}/{year}"
},
@@ -2690,42 +2786,6 @@
"settings.billing.payment_method.title": {
"message": "Payment methods"
},
"settings.billing.payment_method_type.amazon_pay": {
"message": "Amazon Pay"
},
"settings.billing.payment_method_type.amex": {
"message": "American Express"
},
"settings.billing.payment_method_type.cashapp": {
"message": "Cash App"
},
"settings.billing.payment_method_type.diners": {
"message": "Diners Club"
},
"settings.billing.payment_method_type.discover": {
"message": "Discover"
},
"settings.billing.payment_method_type.eftpos": {
"message": "EFTPOS"
},
"settings.billing.payment_method_type.jcb": {
"message": "JCB"
},
"settings.billing.payment_method_type.mastercard": {
"message": "MasterCard"
},
"settings.billing.payment_method_type.paypal": {
"message": "PayPal"
},
"settings.billing.payment_method_type.unionpay": {
"message": "UnionPay"
},
"settings.billing.payment_method_type.unknown": {
"message": "Unknown payment method"
},
"settings.billing.payment_method_type.visa": {
"message": "Visa"
},
"settings.billing.pyro_subscription.description": {
"message": "Manage your Modrinth Server subscriptions."
},
@@ -2879,18 +2939,12 @@
"settings.profile.profile-info": {
"message": "Profile information"
},
"settings.profile.profile-picture.reset": {
"message": "Reset"
},
"settings.profile.profile-picture.title": {
"message": "Profile picture"
},
"settings.profile.username.description": {
"message": "A unique case-insensitive name to identify your profile."
},
"settings.profile.username.title": {
"message": "Username"
},
"settings.sessions.action.revoke-session": {
"message": "Revoke session"
},
+61 -4
View File
@@ -23,6 +23,9 @@
"app-marketing.download.download-rpm": {
"message": "Descargar RPM"
},
"app-marketing.download.flathub": {
"message": "Obténgalo en Flathub"
},
"app-marketing.download.linux": {
"message": "Linux"
},
@@ -38,9 +41,6 @@
"app-marketing.download.terms": {
"message": "Al descargar la Modrinth App, aceptas nuestros <terms-link>Términos de uso</terms-link> y nuestra <privacy-link>Política de privacidad</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Paquetes de terceros"
},
"app-marketing.download.title": {
"message": "Descargar la Modrinth App (Beta)"
},
@@ -197,6 +197,9 @@
"app-marketing.hero.more-download-options": {
"message": "Más opciones de descarga"
},
"app-marketing.not-recommended": {
"message": "No recomendamos usar esos al menos que sepas lo que estas haciendo."
},
"auth.authorize.action.authorize": {
"message": "Autorizar"
},
@@ -1142,6 +1145,54 @@
"frog.title": {
"message": "Rana"
},
"hosting-marketing.billing.monthly": {
"message": "Paga Mensualmente"
},
"hosting-marketing.billing.starting-at": {
"message": "Desde {price} / mes"
},
"hosting-marketing.billing.yearly": {
"message": "Paga Anualmente"
},
"hosting-marketing.faq.currency": {
"message": "¿En que moneda están los precios?"
},
"hosting-marketing.faq.currency.answer": {
"message": "Todos los precios están en Dolares Estadounidenses (USD)."
},
"hosting-marketing.faq.ddos-protection": {
"message": "¿Los servidores de Modrinth Hosting tendrán protección contra DDoS?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Si. Todos los servidores de Modrinth Hosting vienen con protección contra DDoS, con hasta 17 terabits por segundo (Tbps) en algunos lugares."
},
"hosting-marketing.faq.heading": {
"message": "Preguntas Frecuentes (FAQ)"
},
"hosting-marketing.faq.how-fast": {
"message": "¿Qué tan rápidos son los servidores de Modrinth Hosting?"
},
"hosting-marketing.hero.button.start-a-new-server": {
"message": "Inicia un nuevo servidor"
},
"hosting-marketing.hero.button.start-your-server": {
"message": "Inicia tu servidor"
},
"hosting-marketing.medal.info": {
"message": "Prueba un <orange>servidor de 3GB</orange> gratis por 5 días a través de <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Aprender más"
},
"hosting-marketing.medal.text-secondary": {
"message": "Oferta limitada. Sin necesidad de tarjeta de crédito. Disponible para servidores de EE. UU."
},
"hosting-marketing.pick-customized-plan": {
"message": "Elige un plan personalizado con solo las especificaciones que necesites."
},
"hosting-marketing.server-for-everyone": {
"message": "Hay un servidor para todos"
},
"landing.button.discover-mods": {
"message": "Descubre mods"
},
@@ -1206,7 +1257,7 @@
"message": "Encuentra lo que buscas, rápido y fácil"
},
"landing.heading.the-place-for-minecraft": {
"message": "El lugar para Minecraft {content}"
"message": "El lugar para {content} de Minecraft"
},
"landing.heading.the-place-for-minecraft.data-packs": {
"message": "data packs"
@@ -1337,6 +1388,12 @@
"layout.banner.build-fail.title": {
"message": "Error al generar el estado desde la API durante la compilación."
},
"layout.banner.preview.description": {
"message": "Si desea acceder al sitio web oficial de Modrinth, visite <link>https://modrinth.com</link>. El equipo de Modrinth utiliza esta versión preliminar para realizar pruebas. Se creó con <branch-link>{owner}/{branch}</branch-link> @ {commit}.."
},
"layout.banner.preview.title": {
"message": "Esta es una vista previa de la implementación del sitio web de Modrinth."
},
"layout.banner.staging.description": {
"message": "El entorno de prueba está completamente separado de la base de datos de producción de Modrinth. Se utiliza con fines de prueba y depuración, y puede estar ejecutando versiones en desarrollo del backend o frontend de Modrinth más recientes que la instancia de producción."
},
+16 -4
View File
@@ -38,9 +38,6 @@
"app-marketing.download.terms": {
"message": "Al descargar la aplicación Modrinth, aceptas nuestros <terms-link>Términos</terms-link> y nuestra <privacy-link>Política de Privacidad</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Paquetes de terceros"
},
"app-marketing.download.title": {
"message": "Descargar la aplicación Modrinth (Beta)"
},
@@ -809,18 +806,30 @@
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Formulario fiscal"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Detalles"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "Para retirar el saldo total <b>{available}</b> disponible, rellene el siguiente formulario. Es necesario para la declaración de impuestos y solo hay que hacerlo una vez."
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Método de pago"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Recompensa"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Recompensas"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "Email no verificado"
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Retirada"
},
"dashboard.revenue.available-now": {
"message": "Ya disponible"
},
"dashboard.revenue.tos": {
"message": "Al subir proyectos a Modrinth y retirar dinero de tu cuenta, aceptas nuestros <terms-link>Términos del programa de recompensas</terms-link>. Más información sobre el <info-link>Programa de recompensas</info-link>."
},
@@ -836,6 +845,9 @@
"dashboard.withdraw.completion.method": {
"message": "Método"
},
"dashboard.withdraw.completion.wallet": {
"message": "Cartera"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": ""
},
@@ -1002,7 +1014,7 @@
"message": "Encuentre lo que busca, de forma rápida y sencilla"
},
"landing.heading.the-place-for-minecraft": {
"message": "El lugar para Minecraft {content}"
"message": "El lugar para {content} de Minecraft"
},
"landing.heading.the-place-for-minecraft.data-packs": {
"message": "paquetes de datos"
@@ -38,9 +38,6 @@
"app-marketing.download.terms": {
"message": "Lataamalla Modrinth Appin hyväksyt meidän <terms-link>Ehdot</terms-link> ja <privacy-link>Tietosuojaselosteen</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Kolmannen osapuolen paketit"
},
"app-marketing.download.title": {
"message": "Lataa Modrinth App (Beta)"
},
+106 -4
View File
@@ -23,6 +23,9 @@
"app-marketing.download.download-rpm": {
"message": "I-download ang RPM"
},
"app-marketing.download.flathub": {
"message": "Kunin ito sa Flathub"
},
"app-marketing.download.linux": {
"message": "Linux"
},
@@ -38,9 +41,6 @@
"app-marketing.download.terms": {
"message": "Sa pagdownload ng Modrinth App, sumasang-ayon ka sa aming <terms-link>Mga Tuntunin</terms-link> at <privacy-link>Patakaran sa Pribasiya</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Mga third-party package"
},
"app-marketing.download.title": {
"message": "I-download ang Modrinth App (Beta)"
},
@@ -197,6 +197,15 @@
"app-marketing.hero.more-download-options": {
"message": "Higit na Pagpipilian sa Pagdownload"
},
"app-marketing.hide-other-packages": {
"message": "Itago ang ibang mga package"
},
"app-marketing.not-recommended": {
"message": "Hindi namin inumumungkahi ang mga ito sa iyo maliban lang kung alam mo ang ginagawa mo."
},
"app-marketing.show-other-packages": {
"message": "Ipakita ang ibang mga package"
},
"auth.authorize.action.authorize": {
"message": "Pahintulotan"
},
@@ -1142,6 +1151,93 @@
"frog.title": {
"message": "Palaka"
},
"hosting-marketing.available-locations": {
"message": "Magagamit sa Hilagang Amerika, Yuropa, at Timog-Silangang Asya para malawakang abot."
},
"hosting-marketing.billing.monthly": {
"message": "Buwanang pagbayad"
},
"hosting-marketing.billing.quarterly": {
"message": "Tatluhang-buwanang pagbayad"
},
"hosting-marketing.billing.save-with-quarterly": {
"message": "Makatipid nang 16% sa tatluhang-buwanang pagbabayad!"
},
"hosting-marketing.billing.starting-at": {
"message": "Nagsisimula sa {price} / buwan"
},
"hosting-marketing.billing.yearly": {
"message": "Taunang pagbayad"
},
"hosting-marketing.faq.burst-threads": {
"message": "Paaano gumagana ang CPU burst thread?"
},
"hosting-marketing.faq.burst-threads.answer": {
"message": "Kapag nabibigatan ang iyong server, pansamantala naming dinaragdagan ng karagdagang CPU thread upang mabawasan nang bisa ang lag spike at instabilidad. Ito ay nakatutulong sa TPS na hindi ito bababa sa 20, sinisiguro ang maayos na karanasan. Dahil pansamantalaan lamang sa mabibigat na pagproseso ang dinagdag na CPU thread, maaaring hindi ito lilitaw sa ulat ng Spark o sa ibang kagamitang pagpo-profile."
},
"hosting-marketing.faq.cpu-kind": {
"message": "Anong uri ng CPU pinatatakbo ang mga server ng Modrinth Hosting?"
},
"hosting-marketing.faq.cpu-kind.answer": {
"message": "Ang mga server ng Modrinth Hosting ay pinapagana ng AMD Ryzen 7900 at 7950X3D katumbas na CPU sa 5+ GHz, pinares nang memoryang DDR5."
},
"hosting-marketing.faq.currency": {
"message": "Saang salapi pinipresyo ito?"
},
"hosting-marketing.faq.currency.answer": {
"message": "Lahat ng presyo ay nasa United States Dollar (USD)."
},
"hosting-marketing.faq.ddos-protection": {
"message": "Protekdado ba nang proteksiyong DDos ang Modrinth Hosting?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Oo. Lahat ng server ng Modrinth Hosting ay may proteksiyong DDoS, umaabot ang kapasidad nang hanggang 17Tbps sa iilang lokasyon."
},
"hosting-marketing.faq.heading": {
"message": "Kadalasang Tinatanong"
},
"hosting-marketing.faq.how-fast": {
"message": "Gaano ba kabilis ang mga server ng Modrinth Hosting?"
},
"hosting-marketing.faq.increase-storage": {
"message": "Maaari ko bang mapalaki ang storage ng aking server?"
},
"hosting-marketing.faq.increase-storage.answer": {
"message": "Oo, ang storage ay maaaring mapalaki para sa iyong server nang walang dagdag na bayarin. Kung kakailanganin mo ang higit pang storage, maaaring abutin ang Modrinth Support."
},
"hosting-marketing.get-started": {
"message": "Magsimula na"
},
"hosting-marketing.hero.button.manage-your-servers": {
"message": "Pamahalaan ang iyong mga server"
},
"hosting-marketing.hero.button.start-a-new-server": {
"message": "Magsimula nang bagong server"
},
"hosting-marketing.hero.button.start-your-server": {
"message": "Simulan ang iyong server"
},
"hosting-marketing.hero.hosting-description": {
"message": "Ang Modrinth Hosting ang pinakamadaling daan na makaho-host ka nang sarili mong Minecraft: Java Edition na server. Walang hadlang nang sarili makapag-install at makapaglaro nang mga paboritong mod at modpack, lahat sa loob ng plataporma ng Modrinth."
},
"hosting-marketing.included.advanced-networking": {
"message": "Dalubhasang pamamahala ng network"
},
"hosting-marketing.included.advanced-networking.description": {
"message": "Dumagdag ng sarili mong domain sa iyong server, magreserba nang hanggang 15 port para sa mod na mangangailangan nito, at iba pa."
},
"hosting-marketing.included.backups-included": {
"message": "Kasama ang pag-backup"
},
"hosting-marketing.included.backups-included.description": {
"message": "Lahat ng servers and may 15 backup na ligtas na nakaimbak sa off-site."
},
"hosting-marketing.included.custom-url": {
"message": "Pasadyang URL"
},
"hosting-marketing.included.custom-url.description": {
"message": "Ibahagi ang iyong server gamit ang pasadyang <contrast>modrinth.gg</contrast> na URL."
},
"landing.button.discover-mods": {
"message": "Magtuklas ng mga mod"
},
@@ -1337,6 +1433,12 @@
"layout.banner.build-fail.title": {
"message": "May error sa pagbuo ng estado galing sa API habang nagpapatayo."
},
"layout.banner.preview.description": {
"message": "Kung ibig mong maakses ang opisyal na website ng Modrinth, bisitahin ang <link>https://modrinth.com</link>. Ito ay isang pinakalat na pasilip na ginagamit lamang ng kawani ng Modrinth sa pagsusubok nito. Ito ay pinatayo gamit ang <branch-link>{owner}/{branch}</branch-link> @ {commit}."
},
"layout.banner.preview.title": {
"message": "Ito ay isang pinakalat na pasilip ng website ng Modrinth."
},
"layout.banner.staging.description": {
"message": "Buong magkahiwalay ang staging environment sa production Modrinth database. Ginagamit ito sa pagsusuri at pag-debug, at maaaring pinatatakbo sa mga bersiyong in-development ng backend o frontend sa bagong production instance ng Modrinth."
},
@@ -1398,7 +1500,7 @@
"message": "Legal"
},
"layout.footer.legal-disclaimer": {
"message": "HINDI OPISYAL NA SERBISYO NG MINECRAFT. HINDI APRUBADO O KAAKIBAT NG MOJANG O MICROSOFT."
"message": "HINDI OPISYAL NA SERBISYO NG MINECRAFT. HINDI APRUBADO O KAAKIBAT NG MOJANG O NG MICROSOFT."
},
"layout.footer.legal.copyright-policy": {
"message": "Patakaran sa Copyright at DMCA"
+365 -38
View File
@@ -23,11 +23,14 @@
"app-marketing.download.download-rpm": {
"message": "Télécharger le RPM"
},
"app-marketing.download.flathub": {
"message": "L'obtenir sur Flathub"
},
"app-marketing.download.linux": {
"message": "Linux"
},
"app-marketing.download.linux-disclaimer": {
"message": "Les versions Linux de l'application Modrinth sont <issues-link>connues pour présenter des problèmes</issues-link> sur certains systèmes et configurations. Si l'application Modrinth est instable sur votre système, nous vous encourageons à essayer d'autres applications telles que <prism-link>Prism Launcher</prism-link> pour installer facilement le contenu Modrinth."
"message": "Les versions Linux de Modrinth App sont <issues-link>connues pour présenter des problèmes</issues-link> sur certains systèmes et configurations. Si Modrinth App est instable sur votre système, nous vous encourageons à essayer d'autres applications telles que <prism-link>Prism Launcher</prism-link> pour installer facilement le contenu Modrinth."
},
"app-marketing.download.mac": {
"message": "Mac"
@@ -36,10 +39,7 @@
"message": "Options de téléchargement"
},
"app-marketing.download.terms": {
"message": "En téléchargeant l'application Modrinth, vous acceptez nos <terms-link>Conditions générales</terms-link> et notre <privacy-link>Politique de confidentialité</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Paquets tiers"
"message": "En téléchargeant Modrinth App, vous acceptez nos <terms-link>Conditions générales</terms-link> et notre <privacy-link>Politique de confidentialité</privacy-link>."
},
"app-marketing.download.title": {
"message": "Télécharger lapplication Modrinth (bêta)"
@@ -54,7 +54,7 @@
"message": "Suivre des projets"
},
"app-marketing.features.importing.description": {
"message": "Importez tous vos profils depuis votre launcher précédent, et utilisez les dans l'application Modrinth en quelques secondes !"
"message": "Importez tous vos profils préférés depuis votre launcher habituel et plongez dans Modrinth App en quelques secondes !"
},
"app-marketing.features.importing.gdlauncher-alt": {
"message": "GDLauncher"
@@ -108,7 +108,7 @@
"message": "% CPU"
},
"app-marketing.features.performance.description": {
"message": "Lapplication Modrinth est plus performante que la plupart des autres gestionnaires de mods, tout en nutilisant que 150Mo de RAM !"
"message": "Modrinth App est plus performante que la plupart des autres gestionnaires de mods, tout en nutilisant que 150 Mo de RAM !"
},
"app-marketing.features.performance.discord": {
"message": "Discord"
@@ -147,10 +147,10 @@
"message": "Performant"
},
"app-marketing.features.play.description": {
"message": "Utilisez l'application Modrinth pour télécharger et jouer avec vos mods et modpacks favoris."
"message": "Utilisez Modrinth App pour télécharger et jouer avec vos mods et modpacks préférés."
},
"app-marketing.features.play.title": {
"message": "Jouez avec vos mods favoris"
"message": "Jouez avec vos mods préférés"
},
"app-marketing.features.sharing.description": {
"message": "Créez, partagez et jouez sur des modpacks avec les milliers de mods et modpack présents ici sur Modrinth."
@@ -162,25 +162,25 @@
"message": "Partager"
},
"app-marketing.features.sharing.title": {
"message": "Partager des modpacks"
"message": "Partagez des modpacks"
},
"app-marketing.features.unlike-any-launcher": {
"message": "Différent de tous les autres launchers"
"message": "Un launcher comme"
},
"app-marketing.features.website.description": {
"message": "L'application Modrinth est entièrement intégrée au site Web, vous pouvez donc accéder à tous vos projets préférés depuis l'application !"
"message": "Modrinth App est entièrement intégrée au site Web, vous pouvez donc accéder à tous vos projets préférés depuis l'application !"
},
"app-marketing.features.website.title": {
"message": "Intégration au site Web"
},
"app-marketing.features.youve-used-before": {
"message": "vous avez utilisé avant"
"message": "vous n'en avez jamais vu"
},
"app-marketing.hero.app-screenshot-alt": {
"message": "Capture d'écran de l'application Modrinth avec une instance Cobblemon ouverte sur la page \"Contenu\"."
"message": "Capture d'écran de Modrinth App avec une instance Cobblemon ouverte sur la page « Contenu »."
},
"app-marketing.hero.description": {
"message": "L'application Modrinth est un launcher unique et open source qui vous permet de jouer à vos mods favoris et de les maintenir à jour, le tout dans une seule petite application."
"message": "Modrinth App est un launcher unique et open source qui vous permet de jouer à vos mods préférés et de les maintenir à jour, le tout dans une seule petite application."
},
"app-marketing.hero.download-button": {
"message": "Télécharger l'application Modrinth"
@@ -197,6 +197,15 @@
"app-marketing.hero.more-download-options": {
"message": "Plus d'options de téléchargement"
},
"app-marketing.hide-other-packages": {
"message": "Cacher les autres packages"
},
"app-marketing.not-recommended": {
"message": "Nous vous déconseillons de les utiliser si vous ne savez pas ce que vous faites."
},
"app-marketing.show-other-packages": {
"message": "Montrer les autres packages"
},
"auth.authorize.action.authorize": {
"message": "Autoriser"
},
@@ -288,7 +297,7 @@
"message": "Confirmer le mot de passe"
},
"auth.sign-up.email.label": {
"message": "Adressse e-mail"
"message": "Adresse e-mail"
},
"auth.sign-up.label.username": {
"message": "Nom d'utilisateur"
@@ -417,7 +426,7 @@
"message": "Pas de projet dans la collection actuellement"
},
"collection.label.projects-count": {
"message": "{count, plural, =0 {Aucun projets actuellement} one {<stat>{count}</stat> project} other {<stat>{count}</stat> {type}}}"
"message": "{count, plural, =0 {Aucun projets actuellement} one {<stat>{count}</stat> projet} other {<stat>{count}</stat> {type}}}"
},
"collection.label.updated-at": {
"message": "Mis à jour {ago}"
@@ -459,7 +468,7 @@
"message": "Entrez le nom de la collection..."
},
"create.collection.summary-description": {
"message": "Une ou deux phrases qui décrivent vôtre collection."
"message": "Une phrase ou deux qui décrivent votre collection."
},
"create.collection.summary-label": {
"message": "Sommaire"
@@ -1128,13 +1137,13 @@
"message": "Utilisateur introuvable"
},
"frog": {
"message": "Vous avez été grenouillé ! 🐸"
"message": "Grenouille surprise ! 🐸"
},
"frog.altText": {
"message": "Un tableau photoréaliste d'un labyrinthe amphibien"
},
"frog.froggedPeople": {
"message": "{count, plural, one {{count} autre personne a été grenouillée !} other {{count} autres personnes ont été grenouillées !}}"
"message": "{count, plural, one {{count} autre personne a eu} other {{count} autres personnes ont eu}} une grenouille surprise !"
},
"frog.sinceOpened": {
"message": "Cette page a été ouverte {ago}"
@@ -1142,6 +1151,213 @@
"frog.title": {
"message": "Grenouille"
},
"hosting-marketing.available-locations": {
"message": "Disponible en Amérique du Nord, en Europe et en Asie du Sud-Est pour une une couverture étendue."
},
"hosting-marketing.billing.monthly": {
"message": "Payer mensuellement"
},
"hosting-marketing.billing.quarterly": {
"message": "Payer trimestriellement"
},
"hosting-marketing.billing.save-with-quarterly": {
"message": "Économisez 16% avec facturation trimestrielle !"
},
"hosting-marketing.billing.starting-at": {
"message": "À partir de {price} par mois"
},
"hosting-marketing.billing.yearly": {
"message": "Payer annuellement"
},
"hosting-marketing.faq.burst-threads": {
"message": "Comment les pics de puissance CPU fonctionnent-ils ?"
},
"hosting-marketing.faq.burst-threads.answer": {
"message": "Lorsque votre serveur est fortement sollicité, nous lui accordons temporairement l'accès à des threads CPU supplémentaires afin d'atténuer les pics de latence et l'instabilité. Cela permet d'éviter que le TPS ne descende en dessous de 20, garantissant ainsi une expérience aussi fluide que possible. Étant donné que ces threads CPU supplémentaires ne sont disponibles que brièvement pendant les périodes de forte charge, ils peuvent ne pas apparaître dans les rapports Spark ou d'autres outils de profilage."
},
"hosting-marketing.faq.cpu-kind": {
"message": "Sur quelle sorte de CPU Modrinth Hosting exécute-t-il les serveurs ?"
},
"hosting-marketing.faq.cpu-kind.answer": {
"message": "Les serveurs de Modrinth Hosting sont équipés de processeurs AMD Ryzen 7900 et 7950X3D équivalents cadencés à plus de 5 GHz, associés à une mémoire DDR5."
},
"hosting-marketing.faq.currency": {
"message": "Dans quelle devise sont les prix ?"
},
"hosting-marketing.faq.currency.answer": {
"message": "Tous les prix sont indiqués en dollars américains (USD)."
},
"hosting-marketing.faq.ddos-protection": {
"message": "Les serveurs de Modrinth Hosting ont-ils une protection DDoS ?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Oui. Tous les serveurs de Modrinth Hosting sont équipés dune protection DDoS, avec une capacité allant jusqu’à 17 Tbps dans certains endroits."
},
"hosting-marketing.faq.heading": {
"message": "Foire aux Questions"
},
"hosting-marketing.faq.how-fast": {
"message": "À quel point les serveurs de Modrinth Hosting sont-ils rapides ?"
},
"hosting-marketing.faq.how-fast.answer.one": {
"message": "Les serveurs de Modrinth Hosting sont hébergés sur du matériel très moderne et performant, mais il est difficile de dire exactement comment cela se traduira par la vitesse à laquelle votre serveur fonctionnera, car il y a tellement de facteurs qui laffectent, tels que les mods, les packs de données ou les plugins que vous exécutez sur votre serveur, et même le comportement de lutilisateur."
},
"hosting-marketing.faq.how-fast.answer.two": {
"message": "La plupart des problèmes de performance qui surviennent ont tendance à être la faute dun modpack, mod, pack de données ou plugin non optimisé qui provoque du lag chez le serveur. Puisque nos serveurs sont très haut de gamme, vous ne devriez pas rencontrer beaucoup de problèmes tant que vous choisissez un plan approprié pour le contenu que vous diffusez sur le serveur."
},
"hosting-marketing.faq.increase-storage": {
"message": "Puis-je augmenter le stockage sur mon serveur ?"
},
"hosting-marketing.faq.increase-storage.answer": {
"message": "Oui, le stockage peut être augmenté sur votre serveur sans coût supplémentaire. Si vous avez besoin de plus de stockage, contactez Modrinth Support."
},
"hosting-marketing.faq.location": {
"message": "Où se trouvent les serveurs de Modrinth Hosting ? Puis-je choisir une région ?"
},
"hosting-marketing.faq.location.answer": {
"message": "Nous avons des serveurs disponibles en Amérique du Nord, en Europe et en Asie du Sud-Est en ce moment-même que vous pouvez choisir dès l'achat. Plus de régions à venir dans le futur ! Si vous souhaitez changer de région, veuillez contacter le support."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Quelles versions de Minecraft et loaders peuvent-être utilisés ?"
},
"hosting-marketing.faq.versions-loaders.answer.one": {
"message": "Les serveurs de Modrinth Hosting peuvent exécuter nimporte quelle version de Minecraft : Java Edition jusqu’à la version 1.2.5, y compris les snapshots."
},
"hosting-marketing.faq.versions-loaders.answer.two": {
"message": "Nous prenons également en charge une large gamme de mod loaders et de plugins, y compris Fabric, Quilt, Forge et NeoForge pour les mods, ainsi que Paper et Purpur pour les plugins. La disponibilité dépend si le chargeur de mod ou de plugin prend en charge la version sélectionnée de Minecraft."
},
"hosting-marketing.get-started": {
"message": "Commencer"
},
"hosting-marketing.hero.button.manage-your-servers": {
"message": "Gérer vos serveurs"
},
"hosting-marketing.hero.button.start-a-new-server": {
"message": "Commencer un nouveau serveur"
},
"hosting-marketing.hero.button.start-your-server": {
"message": "Commencer votre serveur"
},
"hosting-marketing.hero.host-with-modrinth": {
"message": "Hébergez votre prochain serveur avec Modrinth Hosting"
},
"hosting-marketing.hero.hosting-description": {
"message": "Modrinth Hosting le moyen le plus simple d'héberger votre propre serveur pour Minecraft : Java Edition. Installez et jouez sans problème avec vos mods et modpacks préférés, le tout sur la plateforme Modrinth."
},
"hosting-marketing.included.advanced-networking": {
"message": "Gestion de réseautage avancé"
},
"hosting-marketing.included.advanced-networking.description": {
"message": "Ajoutez votre propre domaine à votre serveur, réservez jusqu’à 15 ports pour les mods qui en ont besoin, et plus encore."
},
"hosting-marketing.included.backups-included": {
"message": "Sauvegardes de secours incluses"
},
"hosting-marketing.included.backups-included.description": {
"message": "Chaque serveur est livré avec 15 sauvegardes de secours stockées en toute sécurité hors site."
},
"hosting-marketing.included.custom-url": {
"message": "URL personnalisée"
},
"hosting-marketing.included.custom-url.description": {
"message": "Partagez votre serveur avec une URL <contrast>modrinth.gg</contrast> personnalisée."
},
"hosting-marketing.included.description": {
"message": "Une suite de fonctionnalités conçues pour offrir une expérience dhébergement que seul Modrinth peut offrir est incluse avec chaque serveur."
},
"hosting-marketing.included.file-manager": {
"message": "Gestionnaire de fichiers facile à utiliser"
},
"hosting-marketing.included.file-manager.description": {
"message": "Recherchez, gérez, modifiez et téléchargez des fichiers directement sur votre serveur avec facilité."
},
"hosting-marketing.included.heading": {
"message": "Équipé de toutes les fonctionnalités dont vous rêvez."
},
"hosting-marketing.included.help": {
"message": "De l'aide quand vous en avez besoin"
},
"hosting-marketing.included.help.description": {
"message": "Contactez l’équipe Modrinth pour obtenir de laide avec votre serveur à tout moment."
},
"hosting-marketing.included.powerful-console": {
"message": "Une console puissante, un gestionnaire des propriétés du serveur, et plus encore"
},
"hosting-marketing.included.powerful-console.description": {
"message": "Modrinth Hosting est livré avec des outils puissants pour gérer votre serveur."
},
"hosting-marketing.included.sftp-access": {
"message": "Accès SFTP"
},
"hosting-marketing.included.sftp-access.description": {
"message": "Accédez aux fichiers de votre serveur directement avec SFTP intégré dans Modrinth Hosting."
},
"hosting-marketing.included.with-your-server": {
"message": "Inclus avec votre serveur"
},
"hosting-marketing.know-what-you-need": {
"message": "Livré avec toutes les fonctionnalités souhaitées?"
},
"hosting-marketing.medal.info": {
"message": "Essayez un <orange>serveur 3GB</orange> gratuit pour 5 jours alimenté par <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "En savoir plus"
},
"hosting-marketing.medal.text-secondary": {
"message": "Offre à durée limitée. Aucune carte de crédit requise. Disponible pour les serveurs américains."
},
"hosting-marketing.pick-customized-plan": {
"message": "Choisissez un plan personnalisé avec seulement les spécifications dont vous avez besoin."
},
"hosting-marketing.server-for-everyone": {
"message": "Il y a un serveur pour tout le monde"
},
"hosting-marketing.why.all-on-modrinth": {
"message": "Gérez tout cela sur Modrinth"
},
"hosting-marketing.why.all-on-modrinth.description": {
"message": "Vos serveurs, vos mods, vous joueurs, et plus encore, le tout sur Modrinth. Pas besoin de passer dune plateforme à lautre."
},
"hosting-marketing.why.consistently-fast": {
"message": "Constamment rapide"
},
"hosting-marketing.why.consistently-fast.description": {
"message": "Notre infrastructure reste non surchargée, garantissant des performances optimales pour chaque serveur Modrinth."
},
"hosting-marketing.why.description": {
"message": "Choisissez parmi les milliers de modpacks disponibles sur Modrinth ou créez le vôtre. Invitez vos amis lorsque vous êtes prêt à jouer."
},
"hosting-marketing.why.heading": {
"message": "Trouvez un modpack. Pouf, c'est un serveur."
},
"hosting-marketing.why.modern-reliable-hosting": {
"message": "Profitez d'un hébergement moderne et fiable"
},
"hosting-marketing.why.modern-reliable-hosting.description": {
"message": "Les serveurs dhébergement Modrinth sont hébergés sur des <contrast>processeurs AMD hautes performances avec une RAM DDR5</contrast>, fonctionnant sur un logiciel sur mesure pour assurer le bon fonctionnement de votre serveur."
},
"hosting-marketing.why.where-mods-are": {
"message": "Jouez là où se trouvent vos mods"
},
"hosting-marketing.why.where-mods-are.description": {
"message": "Modrinth Hosting intègre parfaitement le processus dinstallation de mods et de modpacks dans votre serveur."
},
"hosting-marketing.why.why-modrinth-hosting": {
"message": "Pourquoi Modrinth Hosting ?"
},
"hosting-marketing.why.your-favorite-mods": {
"message": "Tous vos mods préférés"
},
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Choisissez entre Vanilla, Fabric, Forge, Quilt et NeoForge. Tout le contenu de Modrinth est compatible avec votre serveur."
},
"hosting.plan.out-of-stock": {
"message": "En rupture de stock"
},
"hosting.plan.select-plan": {
"message": "Sélectionner un plan"
},
"landing.button.discover-mods": {
"message": "Découvrez des mods"
},
@@ -1197,7 +1413,7 @@
"message": "LAPI open-source de Modrinth permet aux launchers dajouter des intégrations à Modrinth. Vous pouvez utiliser Modrinth depuis notre <link>application officielle</link> ou depuis les launchers les plus populaires, par exemple ATLauncher, MultiMC et Prism Launcher."
},
"landing.feature.launcher.heading": {
"message": "Jouez avec vos launchers favoris"
"message": "Jouez avec vos launchers préférés"
},
"landing.feature.search.description": {
"message": "La recherche ultra-rapide de Modrinth et ses filtres puissants vous permettent de trouver ce que vous cherchez au fur et à mesure que vous tapez."
@@ -1206,10 +1422,10 @@
"message": "Trouvez ce que vous souhaitez, rapidement et facilement"
},
"landing.heading.the-place-for-minecraft": {
"message": "Lendroit idéal pour les {content} Minecraft"
"message": "Savourez Minecraft avec des {content}"
},
"landing.heading.the-place-for-minecraft.data-packs": {
"message": "data packs"
"message": "packs de données"
},
"landing.heading.the-place-for-minecraft.modpacks": {
"message": "modpacks"
@@ -1236,7 +1452,7 @@
"message": "Une représentation simplifiée d'une fenêtre Minecraft, avec le logo de Mojang Studios en vert."
},
"landing.launcher.modrinth-app-label": {
"message": "Application Modrinth"
"message": "Modrinth App"
},
"landing.launcher.prism-launcher-label": {
"message": "Prism Launcher"
@@ -1337,6 +1553,12 @@
"layout.banner.build-fail.title": {
"message": "Erreur lors de la génération de l’état à partir de lAPI pendant la construction."
},
"layout.banner.preview.description": {
"message": "Si vous souhaitez accéder au site officiel de Modrinth, visitez <link>https://modrinth.com</link>. Ce déploiement d'aperçu est utilisé par le personnel de Modrinth à des fins de test. Il a été construit en utilisant <branch-link>{owner}/{branch}</branch-link> @ {commit}."
},
"layout.banner.preview.title": {
"message": "Ceci est un déploiement de prévisualisation du site Modrinth."
},
"layout.banner.staging.description": {
"message": "L'environnement d'essai fonctionne sur une copie de la base de données en production de Modrinth. Il est utilisé à des fins de test et de débogage, et peut exécuter des versions en cours de développement du backend ou du frontend de Modrinth plus récentes que l'instance en production."
},
@@ -1425,13 +1647,13 @@
"message": "Produits"
},
"layout.footer.products.app": {
"message": "Application Modrinth"
"message": "Modrinth App"
},
"layout.footer.products.plus": {
"message": "Modrinth+"
},
"layout.footer.products.servers": {
"message": "Hébergement Modrinth"
"message": "Modrinth Hosting"
},
"layout.footer.resources": {
"message": "Ressources"
@@ -1494,7 +1716,7 @@
"message": "Fonctionnalités expérimentales"
},
"layout.nav.get-modrinth-app": {
"message": "Obtenir lapplication Modrinth"
"message": "Obtenir Modrinth App"
},
"layout.nav.home": {
"message": "Accueil"
@@ -1503,7 +1725,7 @@
"message": "Héberger un serveur"
},
"layout.nav.modrinth-app": {
"message": "Application Modrinth"
"message": "Modrinth App"
},
"layout.nav.modrinth-home-page": {
"message": "Page d'accueil de Modrinth"
@@ -1622,6 +1844,9 @@
"muralpay.document-type.resident-id": {
"message": "Carte d'identité résidente"
},
"muralpay.document-type.ruc": {
"message": "RUC"
},
"muralpay.document-type.tax-id": {
"message": "Numéro d'identification fiscale"
},
@@ -1646,9 +1871,18 @@
"muralpay.field.branch-code": {
"message": "Identifiant de branche"
},
"muralpay.field.clabe": {
"message": "CLABE"
},
"muralpay.field.country": {
"message": "Pays"
},
"muralpay.field.cpf-cnpj": {
"message": "CPF/CNPJ"
},
"muralpay.field.cuit-cuil": {
"message": "CUIT/CUIL"
},
"muralpay.field.document-type": {
"message": "Type de document"
},
@@ -1658,6 +1892,15 @@
"muralpay.field.phone-number": {
"message": "Numéro de téléphone"
},
"muralpay.field.pix-email": {
"message": "Adresse e-mail PIX"
},
"muralpay.field.pix-key-type": {
"message": "Type de clef PIX"
},
"muralpay.field.pix-phone": {
"message": "Téléphone PIX"
},
"muralpay.field.routing-number": {
"message": "Numéro de routage"
},
@@ -1668,11 +1911,14 @@
"message": "Adresse du portefeuille"
},
"muralpay.help.cbu-cvu": {
"message": ""
"message": "Code Bancaire Uniforme ou Code Virtuel Uniforme"
},
"muralpay.help.cci": {
"message": "Code interbancaire"
},
"muralpay.help.clabe": {
"message": "Clave Bancaria Estandarizada (numéro de compte bancaire mexicain)"
},
"muralpay.help.cpf-cnpj": {
"message": "Numéro d'identification fiscale brésilien"
},
@@ -1700,15 +1946,45 @@
"muralpay.placeholder.account-number": {
"message": "Entrée le numéro de compte"
},
"muralpay.placeholder.cbu-cvu": {
"message": "Saisissez votre CBU ou CVU"
},
"muralpay.placeholder.cbu-cvu-type": {
"message": "CBU ou CVU"
},
"muralpay.placeholder.cci": {
"message": "Saisissez le code CCI à 20 chiffres"
},
"muralpay.placeholder.cuit-cuil": {
"message": "Saisissez votre CUIT ou CUIL"
},
"muralpay.placeholder.enter-account-number": {
"message": "Saisissez le numéro de compte"
},
"muralpay.placeholder.enter-branch-code": {
"message": "Saisissez le code de l'agence"
},
"muralpay.placeholder.enter-clabe": {
"message": "Entrez la CLABE à 18 chiffres"
},
"muralpay.placeholder.enter-cpf-cnpj": {
"message": "Saisissez votre CPF ou CNPJ"
},
"muralpay.placeholder.enter-iban": {
"message": "Saisissez l'IBAN"
},
"muralpay.placeholder.enter-pix-email": {
"message": "Saisissez votre adresse e-mail PIX"
},
"muralpay.placeholder.enter-routing-number": {
"message": "Saisissez le numéro de routage à 9 chiffres"
},
"muralpay.placeholder.enter-swift-bic": {
"message": "Saisissez le code SWIFT/BIC"
},
"muralpay.placeholder.iban-crc": {
"message": "Saisissez votre IBAN costaricien"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
@@ -1718,15 +1994,51 @@
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"muralpay.rail.fiat-ars.name": {
"message": "Virement bancaire (ARS)"
},
"muralpay.rail.fiat-brl.name": {
"message": "Virement PIX (BRL)"
},
"muralpay.rail.fiat-clp.name": {
"message": "Virement bancaire (CLP)"
},
"muralpay.rail.fiat-cop.name": {
"message": "Virement bancaire (COP)"
},
"muralpay.rail.fiat-crc.name": {
"message": "Virement bancaire (CRC)"
},
"muralpay.rail.fiat-eur.name": {
"message": "Transfert bancaire (EUR)"
},
"muralpay.rail.fiat-mxn.name": {
"message": "Transfert bancaire (MXN)"
},
"muralpay.rail.fiat-pen.name": {
"message": "Virement bancaire (PEN)"
},
"muralpay.rail.fiat-usd-peru.name": {
"message": "Virement bancaire (USD - Pérou)"
},
"muralpay.rail.fiat-usd.name": {
"message": "Virement bancaire (USD)"
},
"muralpay.rail.fiat-zar.name": {
"message": "Virement bancaire (ZAR)"
},
"muralpay.rail.usdc-base.name": {
"message": "USDC (Base)"
},
"muralpay.rail.usdc-celo.name": {
"message": "USDC (Celo)"
},
"muralpay.rail.usdc-ethereum.name": {
"message": "USDC (Ethereum)"
},
"muralpay.rail.usdc-polygon.name": {
"message": "Crypto (USDC)"
},
"muralpay.warning.wallet-address": {
"message": "Vérifiez votre adresse. Les fonds envoyés à une adresse incorrecte ne pourront pas être récupérés."
},
@@ -1754,12 +2066,21 @@
"profile.button.set-affiliate": {
"message": "Se mettre comme affilié"
},
"profile.details.label.auth-providers": {
"message": "Fournisseurs dauthentification"
},
"profile.details.label.email": {
"message": "Adresse e-mail"
},
"profile.details.label.email-verified": {
"message": "Adresse e-mail vérifiée"
},
"profile.details.label.has-password": {
"message": "Dispose d'un mot de passe"
},
"profile.details.label.has-totp": {
"message": "Dispose d'un TOTP"
},
"profile.details.label.payment-methods": {
"message": "Moyens de paiements"
},
@@ -1787,6 +2108,9 @@
"profile.label.downloads": {
"message": "{count} {count, plural, one {téléchargement} other {téléchargements}}"
},
"profile.label.joined": {
"message": "Rejoint"
},
"profile.label.no": {
"message": "Non"
},
@@ -1947,7 +2271,7 @@
"message": "Sous licence {license}"
},
"project.about.details.published": {
"message": "Publié le {date}"
"message": "Publié {date}"
},
"project.about.details.submitted": {
"message": "Soumis le {date}"
@@ -2004,10 +2328,10 @@
"message": "{title} ne supporte pas {gameVersion} pour {platform}"
},
"project.download.install-with-app": {
"message": "Installer avec l'application Modrinth"
"message": "Installer avec Modrinth App"
},
"project.download.no-app": {
"message": "Vous n'avez pas l'application Modrinth ?"
"message": "Vous n'avez pas Modrinth App ?"
},
"project.download.no-versions-available": {
"message": "Aucune version disponible pour {gameVersion} et {platform}."
@@ -2051,6 +2375,9 @@
"project.environment.migration.learn-more": {
"message": "En apprendre davantage au sujet de cette modification"
},
"project.environment.migration.message": {
"message": "Nous venons de refaire le système denvironnements sur Modrinth et de nouvelles options sont désormais disponibles. Veuillez vérifier que les métadonnées sont correctes."
},
"project.environment.migration.review-button": {
"message": "Vérifier les paramètres d'environnement"
},
@@ -2085,7 +2412,7 @@
"message": "Journal des modifications"
},
"project.notification.icon-updated.message": {
"message": "."
"message": "L'icône de votre projet a été mis à jour."
},
"project.notification.icon-updated.title": {
"message": "Icône du projet mis à jour"
@@ -2148,10 +2475,10 @@
"message": "Visiter le tableau de contrôle des projets"
},
"project.stats.downloads-label": {
"message": "Téléchargement{count, plural, one {} other {s}}"
"message": "téléchargement{count, plural, one {} other {s}}"
},
"project.stats.followers-label": {
"message": "Abonné{count, plural, one {} other {s}}"
"message": "abonné{count, plural, one {} other {s}}"
},
"project.status.archived.message": {
"message": "{title} a été archivé. {title} ne recevra plus de mises à jour jusqu'à ce que l'auteur du projet décide de désarchiver le projet."
@@ -2511,7 +2838,7 @@
"message": "Niveau"
},
"servers.notice.undismissable": {
"message": "Non rejetable"
"message": "Non rejetable"
},
"servers.notices.create-notice": {
"message": "Créer un avis"
@@ -2682,10 +3009,10 @@
"message": "Ouvre les liens externes dans un nouvel onglet"
},
"settings.display.sidebar.hide-app-promos.description": {
"message": "Cache les boutons \"Obtenir l'Application Modrinth\" de la navigation principale. La page de l'application Modrinth peut toujours être trouvée sur la page d'accueil ou dans le pied de page."
"message": "Cache les boutons \"Obtenir Modrinth App\" de la navigation principale. La page de Modrinth App peut toujours être trouvée sur la page d'accueil ou dans le pied de page."
},
"settings.display.sidebar.hide-app-promos.title": {
"message": "Cache les publicités de l'application Modrinth"
"message": "Cache les publicités de Modrinth App"
},
"settings.display.sidebar.left-aligned-content-sidebar.title": {
"message": "Barre latérale alignée à gauche sur les pages de contenus"
@@ -13,7 +13,7 @@
"en-US": "Anglais (États-Unis)",
"en-x-lolcat": "LOLCAT",
"en-x-pirate": "Anglais (Pirate)",
"en-x-updown": "Anglais (à l'envers)",
"en-x-updown": "Anglais (À l'envers)",
"en-x-uwu": "Anglais (UwU)",
"eo": "Espéranto",
"es": "Espagnol",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"displayName": {
"description": "Please enter the name of the language in its specific variant or regional form (e.g., English (US) for American English, not just English). If the language does not have any specific variant, simply enter the name of the language (e.g., Français, Deutsch).",
"message": "Français (France)"
"message": "Anglais (États-Unis)"
},
"searchTerms": {
"description": "Please provide additional search terms associated with the language, if needed, to enhance the search functionality (e.g., American English, Deutschland). Each search term should be entered on a separate line. Translate as a hyphen (-) if no additional terms are needed.",
+27 -3
View File
@@ -38,9 +38,6 @@
"app-marketing.download.terms": {
"message": "בהורדת אפליקציית מודרינת' אתה מסכים ל<terms-link>תנאים</terms-link> ול<privacy-link>מדיניות הפרטיות</privacy-link> שלנו."
},
"app-marketing.download.third-party-packages": {
"message": "חבילות צד שלישי"
},
"app-marketing.download.title": {
"message": "הורד את אפליקציית מודרינת' (בטא)"
},
@@ -368,12 +365,24 @@
"collection.button.edit-icon": {
"message": "ערוך סמל"
},
"collection.button.remove-icon": {
"message": "מחק אייקון"
},
"collection.button.remove-project": {
"message": "מחק פרוייקט"
},
"collection.button.replace-icon": {
"message": "החלף אייקון"
},
"collection.button.select-icon": {
"message": "בחר אייקון"
},
"collection.button.unfollow-project": {
"message": "הסר מעקב מפרוייקט"
},
"collection.delete-modal.description": {
"message": "זה הולך למחוק את האוסף הזאת. פעולה זו אינה הפיכה."
},
"collection.delete-modal.title": {
"message": "אתה בטוח שאתה רוצה למחוק את הקולקציה?"
},
@@ -383,6 +392,9 @@
"collection.description.following": {
"message": "אוסף שנוצר אוטומטית של כל הפרויקטים שאתה עוקב אחריו."
},
"collection.editing": {
"message": "צור אוסף"
},
"collection.error.not-found": {
"message": "אוסף לא נמצא"
},
@@ -392,9 +404,21 @@
"collection.label.curated-by": {
"message": "נוצר על ידי"
},
"collection.label.description": {
"message": "תיאור"
},
"collection.label.details": {
"message": "פרטים"
},
"collection.label.no-projects": {
"message": "אין פרוייקטים באוסף עדיין"
},
"collection.label.updated-at": {
"message": "עודכן {ago}"
},
"collection.return-link.dashboard-collections": {
"message": "האוספים שלך"
},
"collection.title": {
"message": "{name} - אוסף"
},
+4 -4
View File
@@ -38,9 +38,6 @@
"app-marketing.download.terms": {
"message": "A Modrinth App letöltésével elfogadod <terms-link>feltételeket</terms-link> és a <privacy-link>biztonsági szabályzatot</privacy-link>."
},
"app-marketing.download.third-party-packages": {
"message": "Harmadik féltül származó csomagok"
},
"app-marketing.download.title": {
"message": "Modrinth App etöltése (béta)"
},
@@ -1026,7 +1023,7 @@
"message": "Találd meg gyorsan és egyszerűen, amit keresel"
},
"landing.heading.the-place-for-minecraft": {
"message": "Hely a Minecraft {content}"
"message": "Egy hely a Minecraft {content}"
},
"landing.heading.the-place-for-minecraft.data-packs": {
"message": "adatcsomagoknak"
@@ -1250,6 +1247,9 @@
"layout.nav.home": {
"message": "Kezdőlap"
},
"layout.nav.host-a-server": {
"message": "Hozz létre egy szervert"
},
"layout.nav.modrinth-app": {
"message": "Modrinth App"
},
+6 -9
View File
@@ -38,9 +38,6 @@
"app-marketing.download.terms": {
"message": "Dengan mengunduh Modrinth App, Anda menyetujui <terms-link>Syarat</terms-link> dan <privacy-link>Kebijakan Privasi</privacy-link> kami."
},
"app-marketing.download.third-party-packages": {
"message": "Paket pihak ketiga"
},
"app-marketing.download.title": {
"message": "Unduh Modrinth App (Beta)"
},
@@ -1056,7 +1053,7 @@
"message": "Periksa apakah Modrinth sedang mengalami gangguan di <status-link>halaman Status</status-link>."
},
"error.generic.default.list_item.2": {
"message": "Bila hal ini terus terjadi, Anda mungkin ingin memberi tahu Tim Modrinth dengan bergabung ke <discord-link>peladen Discord</discord-link> kami."
"message": "Bila hal ini terus terjadi, Anda mungkin ingin memberi tahu Tim Modrinth dengan bergabung ke <discord-link>server Discord</discord-link> kami."
},
"error.generic.default.list_title": {
"message": "Silakan coba lagi dalam beberapa menit."
@@ -1146,7 +1143,7 @@
"message": "Data dan Statistik"
},
"landing.creator.feature.discovery.description": {
"message": "Kesempatan untuk proyek Anda agar dapat ditemukan oleh ribuan pengguna melalui pencarian, halaman beranda kami, peladen Discord, dan cara-cara lainnya akan hadir di masa mendatang!"
"message": "Kesempatan untuk proyek Anda agar dapat ditemukan oleh ribuan pengguna melalui pencarian, halaman beranda kami, server Discord, dan cara-cara lainnya akan hadir di masa mendatang!"
},
"landing.creator.feature.discovery.title": {
"message": "Penemuan"
@@ -1209,7 +1206,7 @@
"message": "paket sumber"
},
"landing.heading.the-place-for-minecraft.servers": {
"message": "peladen"
"message": "server"
},
"landing.heading.the-place-for-minecraft.shaders": {
"message": "pencorak"
@@ -1284,7 +1281,7 @@
"message": "Kelola tautan afiliasi"
},
"layout.action.manage-server-notices": {
"message": "Kelola pemberitahuan peladen"
"message": "Kelola pemberitahuan server"
},
"layout.action.new-collection": {
"message": "Koleksi baru"
@@ -1485,7 +1482,7 @@
"message": "Beranda"
},
"layout.nav.host-a-server": {
"message": "Jalankan peladen"
"message": "Jalankan server"
},
"layout.nav.modrinth-app": {
"message": "Modrinth App"
@@ -1494,7 +1491,7 @@
"message": "Beranda Modrinth"
},
"layout.nav.my-servers": {
"message": "Peladen saya"
"message": "Server saya"
},
"layout.nav.organizations": {
"message": "Organisasi"

Some files were not shown because too many files have changed in this diff Show More