Compare commits

...
Author SHA1 Message Date
aecsocket 7c3e448239 lint fix 2026-04-23 12:10:43 +01:00
aecsocket e368ffd3d7 make fetching https-only 2026-04-22 14:30:16 +01:00
aecsocket 89df2464b9 split secure/insecure reqwest client 2026-04-22 13:01:02 +01:00
aecsocket 30ea90938b Add set of trusted download hosts for mrpacks 2026-04-21 18:27:06 +01:00
Truman GaoandGitHub cb93c641d6 fix: moderation checklist showing for unlisted status (#5875)
* fix: moderation checklist showing for unlisted status

* refactor: remove unused function
2026-04-20 21:01:31 +00:00
Calum H.andGitHub eebb353547 feat: changelog (#5874) 2026-04-20 22:51:31 +02:00
Truman GaoandGitHub 694ab09a01 fix: sort by not using relevance as default type (#5872) 2026-04-20 20:34:40 +00:00
Calum H.andGitHub da47c50320 fix: sticky header regression (#5869)
* fix: sticky header regression

* fix: github release changelog format for app release workflow

* fix: lint
2026-04-20 15:20:54 +00:00
Modrinth BotandGitHub bee4391df1 New translations from Crowdin (main) (#5867) 2026-04-20 11:11:42 +00:00
SychicandGitHub d1b122fb21 fix(maven): return escaped summary for project description (#5839)
* fix(maven): return escaped summary for project description

* build: add quickxml to labrinth

* fix(maven): use quickxml to escape xml special chars
2026-04-19 14:58:32 +00:00
François-Xavier TalbotandGitHub 281bf066de Fix typo lint (#5860) 2026-04-19 04:40:41 +00:00
coolbotandGitHub 68fde3ff97 Update all guidance URLs (#5858) 2026-04-19 02:52:51 +00:00
Prospector 7d6d938b99 changelog 2026-04-18 17:08:30 -07:00
Calum H.andGitHub 065759d1b8 fix: window on ssr error + cors problem with launcher meta (#5856) 2026-04-18 16:55:57 -07:00
Calum H.andGitHub 9b3fe6390e feat: fix bugs with layout + window controls (#5855) 2026-04-18 15:29:22 -07:00
Calum H.andGitHub 2236dd8ade fix: moderation locking fixes (#5843)
* fix: moderation locking fixes

* fix: lint

* wip: override always available

* fix: newmodal base z

* fix: cargo fmt
2026-04-18 18:55:33 +00:00
Calum H.andGitHub 3a44def301 chore: changelog (#5851)
* fix: modrinth hosting changelog in app changelog for github releases

* chore: changelog
2026-04-18 21:06:18 +02:00
Calum H.andGitHub 176d4301c3 feat: shared loading state + cleanup loading state management (#5835)
* feat: implement shared loading bar component and polished loading states across the app

* feat: align loading states + ensureQueryData changes

* fix: lint + bugs

* fix: skeleton for manage servers page

* fix: merge conflict fix
2026-04-18 18:46:39 +00:00
Calum H.andGitHub 3e32901737 feat: paper channel badges (#5850) 2026-04-18 18:13:08 +00:00
Calum H.andGitHub ab623dc325 feat: uncomment custom key event handler (#5831) 2026-04-18 17:50:20 +00:00
Truman GaoandGitHub bb6e24640c fix: project card having margin due to get actions fn (#5849) 2026-04-18 17:47:05 +00:00
Truman GaoandGitHub 15fc6d4e38 fix: upgrade to modrinth+ no longer fixed to bottom right (#5848) 2026-04-18 17:22:19 +00:00
Truman GaoandGitHub ed2f04322f feat: add edit version pages tabs (#5841)
* feat: add edit version pages tabs

* feat: switch to nav tabs instead of chips

* feat: show "Edit version" as modal title instead of specific page
2026-04-18 17:13:03 +00:00
b9e7b54b4e feat: improve recent worlds loading performance (#5079)
* Improve recent worlds loading performance

* Make recent worlds not cause a layout shift by loading them asynchronously

* Fix formatting

* fix formatting

---------

Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Calum H. <contact@cal.engineer>
Co-authored-by: Calum H. <calum@modrinth.com>
2026-04-18 17:01:54 +00:00
Calum H.andGitHub dd51c08a18 feat: clean up server power action buttons (#5836) 2026-04-17 17:11:52 +00:00
Calum H.andGitHub 5244060588 feat: refactor splash screen component (#5833) 2026-04-17 16:34:58 +00:00
aecsocketandGitHub 9483656881 Fix issues relating to app directory changes (#5826)
* Fix canceling app directory change

* Improve directory moving error messages

* tombi
2026-04-17 14:00:08 +00:00
Modrinth BotandGitHub 7c642f7078 New translations from Crowdin (main) (#5763) 2026-04-17 13:36:38 +00:00
3c2cc7568d feat: add collapsible library groups in app (#5739)
* feat: add collapsible library groups in app

* feat: use accordion rather than custom

---------

Co-authored-by: Calum H. <calum@modrinth.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-04-16 13:44:52 +00:00
7b5c746757 fix(query): set default query retry to 1 (#5743)
* fix(query): set default query retry to 1

* fix(query): don't retry 404s and limit default retries to 3

* feat: expand status skipping checks

* feat: parallel fetch v2 and v3 in middleware

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-04-16 11:31:26 +00:00
5b5c8c06e3 feat: properly impl find for files (#5741)
* Initial file search impl

* Add replace functionality

* Rename to find, remove extra icon

* Put into seperate component

* Fix lint

* Change remaining search stuff to find

* Use ButtonStyled for buttons, use types from ace editor

* Make results label oriented left, add clear button to replace input

* Run fix

---------

Signed-off-by: Arthur <creeperkatze.dev@gmail.com>
Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
2026-04-16 10:59:38 +00:00
Calum H.andGitHub 4d68f3cea4 chore: changelog (#5823) 2026-04-15 22:09:54 +02:00
aecsocketandGitHub 546b117437 Tweak token prioritization in Typesense (#5776)
* Tweak toke prioritization in typesense

* tweaks

* allow configuring max_candidates

* tweak max_candidates

* final changes
2026-04-15 19:45:41 +00:00
Calum H.andGitHub 3d5f29a7a2 feat: continued post qa for servers in app (#5818)
* fix: intercom in app

* feat: Logs.vue dynamic console resizing with window + padding problem

* fix: search highlight with decorator + change to be better

* fix: qa

* fix: allow paper+purpur into app csp

* fix: lint
2026-04-15 19:16:05 +00:00
Truman GaoandGitHub 37b0f7ff98 fix: displayUrlEnding is undefined at times (#5811) 2026-04-15 18:50:05 +00:00
Truman GaoandGitHub 1603796856 feat: implement overlay scrollbar for app sidebar (#5820)
* feat: implement overlay scrollbar for app sidebar

* pnpm prepr
2026-04-15 16:53:08 +00:00
Truman GaoandGitHub 7c9a9f22d4 fix: project page header in mobile (#5817) 2026-04-15 16:14:19 +00:00
Truman GaoandGitHub d38d23dbf3 fix: post servers in app release QA (#5815)
* fix: billing page server plan heading

* fix: matching server page spacing with instance page

* feat: update server header buttons

* feat: add show ram as bytes always on

* fix: revert to large buttons

* feat: add hostname and server states in info card
2026-04-15 14:55:11 +00:00
aecsocketandGitHub f12bd7b4b8 Add utoipa info for v2 routes (#5775)
* wip: add v2 docs, routes to config, paths

* fix up path prefixes

* fix leading slashes

* fix slash route

* fix more slashes

* wip: full utopification of v2

* convert last few v2 routes to utoipa
2026-04-15 13:25:35 +00:00
Truman GaoandGitHub baee34b0b6 feat: add moderation checklist back to project page (#5814)
* fix: billing page server plan heading

* fix: matching server page spacing with instance page

* feat: update server header buttons

* feat: add show ram as bytes always on

* fix: revert to large buttons

* feat: add hostname and server states in info card

* feat: add publishing checklist to project page

* fix: markdown table style and max width

* fix: teleport overflow menu bad anchoring
2026-04-15 09:12:31 +00:00
Calum H.andGitHub 74bad7456c fix: blog wording (#5807)
* fix: blog wording

* fix: lint
2026-04-13 18:10:24 +00:00
a6f67581d7 chore: add hosting in app blog post (#5787)
* add blog post

* feat: update image

---------

Co-authored-by: Calum H. <calum@modrinth.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-04-13 16:57:09 +00:00
Truman GaoandGitHub 02be7a8b82 fix: properties tab height with alert (#5802) 2026-04-13 14:56:53 +00:00
Calum H.andGitHub d5ad1cb823 fix: log sharing in app + clearing (#5801)
* fix: log wiping app

* fix: share modal rounded
2026-04-13 14:52:35 +00:00
Calum H.andGitHub b666747bc2 feat: guard null stats (#5800) 2026-04-13 14:23:31 +00:00
Calum H.andGitHub c1b0e4a692 fix: modal positioning (#5796) 2026-04-13 14:01:52 +00:00
Calum H.andGitHub 0713814d0c fix: prerelease fixes (#5793) 2026-04-12 23:58:50 +00:00
Calum H.andGitHub 0b8b4fb516 fix: modal stacking (#5792)
* fix: modal stacking

* fix: lint
2026-04-12 15:59:34 -07:00
Calum H.andGitHub d6e366b488 fix: workflow release (#5791) 2026-04-12 22:48:29 +00:00
Prospector 0682cc3c4f changelog 2026-04-12 15:13:51 -07:00
693a371d61 feat: server management in app (#5628)
* start new server settings tabs

* update properties tab to match design

* better stying in general tab

* feat: add suffix input for hostname field

* implement tables for allocations and DNS records

* add tags for dns record type

* small gap adjustment

* polish advanced page

* adjust properties page hierarchy

* fix searching properties, empty state and projection radius appearing

* pnpm prepr

* update copy to match designs

* fix suffix input component

* style fixes and match heading size

* small fix

* fix search allocations placeholder

* adjust table styles

* move all installation settings helper text to below input

* update icon to use overflow menu buttons

* fix modal to be consistent

* open advanced properties when search

* remove other and custom properties, and update styles

* remove hide/show all java versions

* handle mc 26

* refactor: move server settings pages into /ui and add app ServerSettingsModal

* hook up server pages for app

* add server page header to app

* hook up server settings modal

* use large size

* fix card box shadow style

* fix hostname input for app

* fix app/website card containers

* implement external tabs for billing and admin billing

* fix save banner fixed to parent instead of page body

* remove unused prop to FriendsList causing warning in app

* fix client-only not available for app

* fix bottom cut off

* wire node auth

* implement full copy buttons

* dedup copy button tailwind styles

* fix hover class not working in @apply

* fix spacing

* fix error validation styles

* apply consistent styles and spacing

* feat: update hosting server card (#5609)

* fix type errors

* fix some stylesheets not imported for storybook

* add server listing stories

* add fix for frontend stylesheet imports

* remove props.

* convert copy code to use tailwind

* update server listing component styles

* update server info label styles

* start status/player count info label, more style updates and fixes

* add new server card buttons

* hook up server cards and implement updated styles

* hook up on download button

* fix tauri throwing error when api returns 204 No Content

* hook up purchase server modal in app

* fix upgrading state loading icon

* pnpm prepr

* filter out servers past 30 days after cancellation

* do not apply opacity on lock or spiner icons

* fix disabled server icon background

* update pending change stage

* handle known suspension states

* refactor: reduce code duplication for server listing

* update disabled state text color

* fix loading icon color

* clean up copy

* fix disabled opacity for server card

* update server listing files kept to be countdown

* implement resubscribe modal

* implement proper provisioning state for resubscribe

* fix duplicate attribute and pnpm prepr

* feat: add shared UI package auth DI

* feat: update purchase server flow (#5714)

* implement server list empty state component

* fix stories and adjust spacing

* implement select plan design refresh

* implement auth for empty server list

* use refs instead of reactive

* pnpm prepr

* fix auth usage for empty servers list

* move app auth provider setup to src/providers/setup

* pnpm prepr

* fix max height

* style fix

* fix getCreds no auth is blocking api client

* implement servers guest plan modal and signin which redirects back to modal's next step

* refactor guest plan select logic into provider

* implement sign in or create account popup

* remove force empty serverList

* add download button for suspended mod and generic

* add handling for when user logs out

* QA pass style fixes

* more consistent page styles

* fix duplicate export

* refactor: remove all fallback stuff from resubscribe modal

* implement shared download latest backup util

* i18n pass

* pnpm prepr

* fix region being selected if ping failed

* pnpm prepr

* feat: servers in app finalization (#5744)

* feat: start on shared console implementation into logs and overview pages

* fix: terminal gap issues

* feat: swap word wrap for full screen

* fix: stats cards alignment

* fix: stats

* feat: fix console clear + remove copy

* fix: lint

* fix: use reset not clear

* feat: shared server header & overview page for app and website (#5736)

* feat: implement shared server header for app and website

* feat: implement wrapped overview page with shared composable and hook it up

* pnpm prepr

* fix: bugs

* qa: cleanup

* feat: root.vue shared layout

* feat: delete old options pages + fix discovery frontend

* fix: discovery

* fix: misc style/layout issues

* fix page padding

* fix: modal height jankiness

* feat: implement server install content in app and server setup modal with DI

* fix: spacing

* remove servers in app feature flag

* Revert "remove servers in app feature flag"

This reverts commit 86e284c4bd.

* fix: qa

* feat: remove legacy components from apps/frontend/src/components/ui/servers

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>

* qa pass (#5738)

* fix: qa

* feat: qa

* fix: server icon fetch fails due to global node auth race condition overriding each other

* fix: lint

* fix: server icon upload/sync and centralize logic

* fix: server settings modal not closing for server reset

* fix: better server sorting

* feat: copy address in server listing card

* fix: notification panel in modal and when overlapping with action bar

* fix: empty server list empty state flashing when refresh, fixed by adding isReady auth flag

* feat: use floating action bar for save banner

* fix: saving state in save bar

* fix: edit server icon styling

* fix: confirm modal to have consistent buttons

* feat: loading animation for server panel + caching improvements for app

* pnpm prepr

* feat: search page deduplication (#5754)

* fix: action bar behind modal

* fix: remove warning modal for stopping

* fix: server cards states

* we hate webkit we hate webkit

* fix: update allocation creation to not use modal

* fix: properties tab spacing and styles

* feat: add files tab copy

* fix: advanced properties icon

* fix: remove back to all servers link

* feat: add files tab link in copy

* fix: server header styles to be consistent with instance

* fix: add header icons back

* feat: update instance settings icon to be consistent

* fix: icon container

* feat: upload state persistence across tabs

* fix: server labels text wrapping

* fix: use surface-5 border

* fix: loading spinner showing with onboarding below

* feat: new server button shows purchase modal in website

* fix: billing page not showing quarterly interval

* fix: server downgrade not showing updated subscription notification

* fix: server settings invalidate saved state and remove server context provider since its already provided in the page

* pnpm prepr

* add stripe publishable key to app build

* feat: console highlighting

* fix: rename servers title to modrinth hosting

* feat: search fix

* fix: qa/styles

* fix: ip click active and remove power dont ask again

* fix: qa

* feat: highlighting fix console

* fix: disable conflicts action

* fix: error dismiss bug

* feat: modal clarification

* fix: files perms issue

* fix: lint

* feat: modal fix

* enable show uptime

* fix: add loading state to edit server icon

* fix: notification panel take in has sidebar from settings

* fix: consistency pass on app settings

* fix: consistency pass on instance settings

* pnpm prepr

* fix: nagivate to billing button in app to go to website

* fix: stripe return url in app causing app to open modrinth.com in tauri

* refactor: better show polling UI code

* fix: new server polling comparison to use server ids instead of length

* fix: buttonstyled story

* fix: button styling

* fix: content.vue regression

* feat: project url redirects

* fix: breadcrumbs

* fix: purchase with newly added card

* fix: console ordering problems

* fix: app-frontend missing env config and staging environment

* fix: log syncing for instances and server panel accidentally

* fix: QA issues

* fix: server page loading state

* fix: stats card logic

* fix: lint

* fix: qa

* fix: console height padding

* fix: terminal padding + loading indicator

* feat: update medal server listing styling

* fix: no upgrade button for medal server listing in app

* fix: go to overview instead of content tab after onboarding

* fix: qa

* fix: teleport modals to body

* fix: logs tab + qa

* fix: local storage for user preferences

* fix: qa loading indic

* feat: considitonal debug and trace

* fix: jump to top on install bug

* feat: swap out server hard drive icon to server stack icon

* feat: servers in app feature flag default true

* fix: highlight row ufll

* fix: webkit thing onto a tag

* fix: input field

* fix: clear fix

* fix: lint

* fix: fmt

* feat: improve share modal and bring it back for sharing log

* pnpm prepr

* fix: menu overflowing

* feat: remove servers in app feature flag

* fix: server stat charts no longer showing color

* fix: library nav no primary state

* fix: better modal height and width

* fix: highlighting bugs

* fix: empty states

* fix: delay import to fix overview page slow load on MacOS

* fix: medal server listing too bright on light mode

* fix: admon analysis + fix logs

* fix: bug

* fix: clear purchase intent from sign-in after closing modal

* performance: improve server manage stats loading by splitting reactivity

* fix: deploy + admon + disable highlighting

* fix: clippy

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com>

* feat: temp wrangler

* fix: lint

* fix: logs upload

* fix: console empty state and admon regressions

* fix: fields

* feat: log deleting + prefetch for Logs.vue

* feat: move delete before share

* feat: clear endpoint

* feat: we ball!

---------

Co-authored-by: Calum H. <calum@modrinth.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-04-12 21:38:08 +00:00
shellawaandGitHub a2a97d1313 fix: use nullish coalescing instead of OR on fraction digits (#5788) 2026-04-12 16:14:44 +00:00
aecsocketandGitHub 71e4f7cb91 Update ad webview logic (#5774)
* add clarifying comments to ad webview code

* properly manage adview show/hiding

* check if webviews manage visibility on Windows

* comment out testing code

* add clarifying comments
2026-04-11 15:49:52 +00:00
Truman GaoandGitHub 1a51e58297 fix: orgs member settings not persisting by shallow-clones each member object (#5772) 2026-04-08 17:57:58 +00:00
aecsocketandGitHub a9c417d1d1 Switch from Swagger to Scalar for OpenAPI docs (#5766)
* Switch from Swagger to Scalar for OpenAPI docs

* remove old comments
2026-04-07 22:14:26 +00:00
aecsocketandGitHub de4f0bffb0 Add server ID to Intercom JWT payload (#5769) 2026-04-07 22:14:15 +00:00
aecsocketandGitHub e71a8c10fa Fix passing intercom identity from CF v2 (#5753) 2026-04-04 14:50:32 -07:00
ProspectorandGitHub c4b3c6e8d6 add sign in redirect path (#5746) 2026-04-04 20:33:09 +00:00
aecsocketandGitHub 54c45ac9f3 Fix passing intercom identity from CF (#5752) 2026-04-04 10:40:26 -07:00
aecsocketandGitHub e5f600ddd7 Fix buffer allocations in server pinging code (#5751) 2026-04-04 17:22:40 +00:00
4a7525d0a1 Fix mobile navigation media query (#5749)
Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
2026-04-04 15:50:04 +00:00
Prospector d0d3aaf09b changelog 2026-04-04 08:48:57 -07:00
aecsocketandGitHub bb3506823d Add secure support connection to website (#5750)
* wip: icom jwts

* should fix auth token passing

* add to wrangler
2026-04-04 08:47:03 -07:00
ProspectorandGitHub 3091021194 fix: no gap after navtabs on collections (#5740)
* fix: no gap after navtabs on collections

* fix collection sorting
2026-04-04 14:53:53 +00:00
Prospector dc96043adc app changelog 2026-04-03 16:38:43 -07:00
aecsocketandGitHub 92bf2e5c29 Install transitive dependencies of versions properly (#5745)
* install recursive deps properly

* fix up
2026-04-03 20:29:08 +00:00
Prospector a6d359e9c1 Revert "beenz"
This reverts commit 35033ccc03.
2026-04-02 13:18:20 -07:00
Calum H.andGitHub ddd1a36506 feat: allow changelog comment from 3rd party PRs (#5724) 2026-04-02 19:41:53 +00:00
Prospector 933fdba388 Revert "give beenz"
This reverts commit c52abece44.
2026-04-02 12:40:39 -07:00
Calum H.andGitHub fa4711ff7b feat: implement improved flow for server panel edit installation (#5711)
* feat: implement improved flow for server panel edit installation

* feat: installation form finalized

* feat: error state for InstallingBanner

* feat: action button refactor + save banner text fix

* fix: lint

* fix: content card alignment

* feat: better copy

* fix: lint

* fix: hide shift click + fix NeoForge chip

* fix: lint
2026-04-01 17:53:19 +00:00
Prospector c52abece44 give beenz 2026-04-01 03:03:26 -07:00
Prospector 35033ccc03 beenz 2026-04-01 01:42:18 -07:00
Prospector 97734a98f9 fix error 2026-04-01 01:42:01 -07:00
Calum H.andGitHub 3978e3dead fix: try fix virtual scrolling regression (#5723) 2026-03-31 20:40:04 +00:00
Calum H.andGitHub 5939d2a4e7 fix: mobile tooltip bug for files tab (#5722) 2026-03-31 20:33:02 +00:00
Truman GaoandGitHub 4224ef45b3 feat: add shared UI package auth DI (#5720)
* feat: add shared UI package auth DI

* use refs instead of reactive

* pnpm prepr

* move app auth provider setup to src/providers/setup
2026-03-31 17:15:35 +00:00
xinyihlandGitHub e2bfed177d fix: billing charges error 500 (#5718) 2026-03-31 07:06:26 +00:00
Truman GaoandGitHub 7f92706e5f improve app error modal (#5710) 2026-03-31 07:00:59 +00:00
François-Xavier TalbotandGitHub 90deb7310e Fix daedalus NeoForge (#5713)
* Support NeoForge version for year-based Minecraft versions

* Run on CI

* Fix

* Fix branch

* Undo branch switch
2026-03-30 17:53:29 +00:00
Truman GaoandGitHub 4cd6c1a72d fix modpacks no loader (#5707) 2026-03-30 09:21:20 +00:00
NitrrineandGitHub 3a8561cf35 fix: save banner is getting hidden by some parts of the ui (#5697) 2026-03-30 09:20:55 +00:00
Modrinth BotandGitHub a3f80dcb66 New translations from Crowdin (main) (#5708) 2026-03-30 09:20:30 +00:00
Calum H.andGitHub 0ee58867e8 feat: warning filter + remove client only filter as it's useless (#5690)
* feat: warning filter

* fix: remove client_only filter
2026-03-27 22:00:02 +00:00
Prospector d4c2fdb9ef Revert "revert release workflow changes"
This reverts commit fc87506745.
2026-03-27 15:01:52 -07:00
Calum H.andGitHub e6b061f38c fix: paper/purpur vers mismatch (#5687)
* fix: paper/purpur

* fix: use fill api

* fix: lint
2026-03-27 17:24:16 +00:00
Calum H.andGitHub 87122cf9bd feat: console component (#5685) 2026-03-27 15:44:08 +00:00
Prospector fc87506745 revert release workflow changes 2026-03-26 18:30:02 -07:00
Prospector 6ba41ba17f clean up changelog, remove unnecessary technical details 2026-03-26 18:21:12 -07:00
Prospector 628634772e changelog 2026-03-26 18:04:59 -07:00
François-Xavier TalbotandGitHub b68aeddedc hosting: Copy ID button for backups when developer mode is on (#5681)
* Copy ID button in backups tab

* Remove codex slop
2026-03-27 00:18:33 +00:00
Calum H.andGitHub c5a0c71424 feat: vite 8 app frontend (#5680) 2026-03-27 00:17:51 +00:00
Calum H.andGitHub 4394092928 feat: better tooltips for mods in content tab hosting panel (#5679)
* feat: better tooltips for mods in content tab hosting panel

* feat: qa
2026-03-26 22:55:08 +00:00
aecsocketandGitHub ef1ffa6577 Fix payout sync response schema (#5644) 2026-03-26 22:44:54 +00:00
Calum H.andGitHub b11b54cbc9 fix: various content fixes (#5676)
* fix: wrong lock field

* fix: install_stage locking up due to previous failure stored as stale snapshot

* fix: Error when updating instance
Fixes #5671

* fix: prepr
2026-03-26 22:30:17 +00:00
ProspectorandGitHub 36f62a3285 refactor: move flags into settings, change icon (#5678)
* refactor: move flags into settings, change icon

* fix: use ButtonStyled for app
2026-03-26 21:10:01 +00:00
Calum H.andGitHub 381ea51cce refactor: align files tab with content tab design (#5621)
* fix: files.vue bugs before styling changes

* feat: move files tab to shared layout structure

* fix: qa

* fix: qa

* fix: bugs

* fix: lint

* fix: admonition cleanup with progress + actions

* fix: cleanup

* fix: modals

* fix: admon title

* fix: i18n standard

* fix: lint + i18n pass

* fix: remove transition

* fix: type errors

* feat: files tab in app

* fix: qa

* fix: backup item minmax

* fix: use ContentPageHeader for server panel

* fix: lint

* fix: lint

* fix: lint

* feat: page leave safety

* fix: lint

* fix: cargo fmt fix

* fix: blank in prod

* fix: content card table stuff

* Revert "fix: blank in prod"

This reverts commit 74758fe185.

* fix: import

* feat: browse worlds/servers flow

* fix: worlds tab parity with content tab

* fix: perf bug + shader filter pill copy

* feat: singleplayer filter

* fix: ordering

* fix: breadcrumbs

* fix: lint

* fix: qa

* feat: store server proj id when adding to a non-linked instance

* fix: lint

* fix: i18n + qa

* fix: conflict

* qa: already installed modal + placeholders not server-specific

* fix: qa

* fix: add + edit server modals

* fix: qa

* fix: security

* fix: devin flags

* fix: lint

* chore: change file to break build cache

* fix: admon

* fix: import path stuff

* feat: qa

* fix: fmt fmt idiot

---------

Signed-off-by: Calum H. <calum@modrinth.com>
2026-03-26 18:55:15 +00:00
Truman GaoandGitHub 706eb800cb fix: website visual issues (#5675)
* fix no modpack loader showing as resource pack loader

* fix table overflow, add game version tags "+ {num}" overflow menu

* pnpm prepr
2026-03-26 18:40:44 +00:00
Calum H.andGitHub f1648298c4 fix: neoforge not existing for 26.1 breaking vers picker (#5674)
* fix: neoforge for 26.1 -> other vers being picked not existing causing version picker to break

* fix: lint
2026-03-26 17:53:27 +00:00
Prospector 3c3cde1908 changelog 2026-03-26 00:22:40 -07:00
ProspectorandGitHub 274325d97c fix: settings page error (#5668) 2026-03-26 00:21:19 -07:00
aecsocketandGitHub da48a12551 Only mark servers as offline if they fail pings 3+ times (#5664)
* wip: online status fix

* use INCR

* properly clear cache
2026-03-26 06:34:20 +00:00
François-Xavier TalbotandGitHub bf24ed8d12 Add feature flag to force Archon requests to be traced (#5666) 2026-03-26 06:34:04 +00:00
aecsocketandGitHub 0731654a1c maybe fix daedalus (#5665) 2026-03-26 06:33:58 +00:00
Calum H.andGitHub 81f19eeb8d fix: various content tab hosting bugs (#5662)
* fix: qa

* fix: lint
2026-03-25 17:58:13 +00:00
Calum H.andGitHub 4b4282cfbf fix: 500 on oauth authorize page (#5661) 2026-03-25 17:52:12 +00:00
François-Xavier TalbotandGitHub 7b3471944d hosting: "Reset to onboarding" support-only action (#5659)
* Reset to onboarding button

* Lint

* Intl
2026-03-25 14:50:31 +00:00
Prospector d2abeb434c changelog 2026-03-24 14:21:31 -07:00
François-Xavier TalbotandGitHub 0aecfa3140 hosting: support java 25 (#5654)
* Add Java 25, handle new version format

* Changelog

* Revert "Changelog"

This reverts commit 0c1c7e2fe8.
2026-03-24 20:39:04 +00:00
Modrinth BotandGitHub f9004dc2f6 New translations from Crowdin (main) (#5638) 2026-03-23 23:44:53 +00:00
Calum H.andGitHub cf7c77700a fix: bugs with changelog collect (#5648) 2026-03-23 20:39:40 +00:00
Calum H.andGitHub c09f7fd5e6 devex: changelog system (#5309)
* devex: changelog system

* feat: changelog CIs

* feat: web alias for platform + hosting

* feat: upload binaries to gh release

* feat: improve copy text

* fix: release workflow

* fix: changelog CIs + PR health check comment

* fix: action

* fix: comment style

* fix: comment

* fix: remove health

* fix: deploy use Modrinth bot machine account

* feat: new system

* fix: pr comment structure
2026-03-23 17:45:43 +00:00
Truman GaoandGitHub 67fd759d9b fix: add poster attribute to configuredXss (#5646) 2026-03-23 17:27:59 +00:00
Calum H.andGitHub a3eb981058 fix: env filters + properties (#5642)
* fix: env filters

* fix: server

* fix: lint

* fix: properties
2026-03-23 16:47:51 +00:00
Calum H.andGitHub 92eddbe832 feat: move switch version inline like update btn for content tab (#5631)
* fix: switch version inline same as update btn

* fix: lint
2026-03-21 18:06:03 +00:00
Calum H.andGitHub 9e6a6cd385 fix: withdraw flow bug (zero bal) (#5629) 2026-03-21 18:04:55 +00:00
aecsocketandGitHub 3c5bd0756d Index search by original and split title (#5589)
* Index search by original and split title

* better normalization of title/author names for indexing

* replace println with warn

* fix test
2026-03-20 04:01:19 +00:00
Calum H.andGitHub 00e81adbbd fix: reinstall soft_override: true (#5623) 2026-03-19 20:53:58 +00:00
Truman GaoandGitHub 2128fa7ade refactor: TabbedModal to use NewModal and DI (#5612)
* refactor: tabbed modal to use NewModal

* refactor: use DI for instance settings modal instead of passing down props

* pnpm prepr
2026-03-19 16:53:53 +00:00
Calum H.andGitHub 93c81631a9 fix: NaN cmp-info (#5619)
* fix: NaN cmp-info

* fix: ssr

* fix: lint
2026-03-19 15:26:15 +00:00
aecsocketandGitHub 3b604cfdc0 Get AutoMod to ignore .rpo files (#5616) 2026-03-19 00:16:30 +00:00
Truman GaoandGitHub 922b72d1a4 fix: new PAT not in list and cmp revenue (#5614)
* fix cmp info revenue not showing #5610

* fix use head referencing undefined

* fix new PAT not pushed to list and use new modal

* remove flex wrap in header nav
2026-03-19 00:06:35 +00:00
Calum H.andGitHub 1d10af09f5 fix: final content tab qa (#5611)
* fix: queued admonition always showing

* fix: dont apply grayscale to checkbox in content card item

* fix: actual stable id for disable/enable/bulk state

* fix: vue-router resolve workaround

* fix: show disable/enable btns same time

* fix: remove mr-2 on toggle

* fix: type errors + add ModpackAlreadyInstalledModal

* fix: bulk actions + overflow menu hitting ad container

* fix: responsiveness of ContentSelectionBar

* feat: better backup naming for inline backups + sorting fixes

* fix: lint

* fix: typo
2026-03-18 18:03:55 +00:00
xinyihlandGitHub cf1b5f5e2d Make settings page localizable (#5294)
* make settings localizable

* move plan names to common messages

* unknown -> plan-unknown

* prepr:frontend
2026-03-18 16:16:04 +00:00
Prospector 61754efca4 Fix changelog prerender issue 2026-03-17 19:26:40 -07:00
Prospector 235934abd7 changelog 2026-03-17 18:56:10 -07:00
ProspectorandGitHub 22d1b900f6 Fix environment tag missing from app (#5607) 2026-03-18 00:23:42 +00:00
Calum H.andGitHub 1cfbefff02 fix: various fixes related to content tab on app and panel (#5605)
* fix: content filtering client only

* fix: browse content bug

Fixes #5570

* fix: Applying Mods & Updates filters at the same time doesn't work

Fixes #5602

* fix: Browsing content: going back resets filters and installed state

Fixes #5598

* fix: Mod tile background flickers when toggling enabled/disabled state

Fixes #5600

* fix: Overhaul of "Content" tab on instances broke a lot
Fixes #5567

* fix: Latest App update replacing all mods icons with a datapack/rescourcepack
Fixes #5556

* fix: billing page api-client ditch useBaseFetch

* fix: remove org icon from project card items

* fix: lint
2026-03-17 21:49:46 +00:00
7852529915 Fix developer mode secret toggle not requiring the right amount of clicks (#5437)
* the world is right again

* Move increment to top of function

Signed-off-by: Prospector <6166773+Prospector@users.noreply.github.com>

---------

Signed-off-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-03-17 20:08:06 +00:00
c556624d0e Add GitHub Pages content in Markdown support (#5522)
* add `allowedHostnameSuffixes` with `.github.io` support

* apply `prettier`

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-03-17 20:07:25 +00:00
Calum H.andGitHub 87c86c7d0d refactor: remove useBaseFetch for @modrinth/api-client (#5596)
* Reapply "fix: start swapping useBaseFetch usages to api-client"

This reverts commit f4f33db701.

* fix: bugs

* fix: analytics

* fix: lint
2026-03-17 20:06:19 +00:00
JerozgenandGitHub 58c1e225c8 Sort filters and add translations for servers (#5493)
* Translate and sort server filters

* Set team_members to unknown[]

* Additional fixes after merge

* Additional translations

* Replace "IP" with "server address"

* Prioritize English and user language
2026-03-17 19:56:01 +00:00
Calum H.andGitHub 900a4df1b7 fix: error on admin billing (#5603) 2026-03-17 12:40:07 -07:00
Prospector 5b968a1486 update blog + changelog 2026-03-17 12:37:38 -07:00
ProspectorandGitHub 3a917631d5 Fix PATs page (#5599) 2026-03-17 12:37:28 -07:00
Calum H.andGitHub 63ea8230ba feat: content tab QA fixes for panel pre-release (#5588)
* feat: use new_filters + other qa fixes

* fix: double admons + lint
2026-03-17 17:47:58 +00:00
Truman GaoandGitHub 496bbae8a0 fix: server search (#5591)
* fix: server search regression

* fix badly passed props
2026-03-16 22:11:30 +00:00
1848ba3b29 fix: server-only project middleware (#5538)
* fix(navigation): use replaceState for project filters to prevent history pollution

* fix: add replace prop to NavTabs and enable it on project and discover pages

* style: run pnpm run fix on affected files

* enable NavTabs replace prop on collection, user, and org pages

* fix: guard project middleware on client

* fix: lint

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com>
2026-03-16 22:09:43 +00:00
681ae5d1d8 refactor: removing useAsyncData for tanstack query (#5262)
* refactor: most places with useAsyncData replaced with tanstack query

* refactor report list and report view

* refactor organization page to use tanstack query

* fix types

* refactor collection page and include proper loading state

* fix followed projects proper loading state

* fix 404 handling

* fix organization loading and 404 states

* pnpm prepr

* refactor: remove useAsyncData on newsletter button

* refactor: remove useAsyncData on auth globals fetch

* refactor: settings/billing/index.vue to useQuery instead of useAsyncData

* refactor: user page to remove useAsyncData

* pnpm prepr

* fix reports pages

* fix notifications page

* fix billing page cannot read properties of null and prop warnings

* fix refresh causing 404 by removing useBaseFetch and use api-client

* fix stale data after removing organization from project

* pnpm prepr

* fix news erroring in build

* fix: project page loads header only after content

* fix: user page tanstack problems (start on migrating away from useBaseFetch)

* fix: start swapping useBaseFetch usages to api-client

* Revert "fix: start swapping useBaseFetch usages to api-client"

This reverts commit 3df3fab11d.

* fix: remove debug logging

* fix: lint

---------

Co-authored-by: Calum H. <calum@modrinth.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-03-16 19:10:29 +00:00
Calum H.andGitHub d0c7575a23 feat: move notion docs to standards folder (#5590)
* feat: move notion docs to standards folder

* fix: remove skills mention (automatic now)
2026-03-16 17:30:05 +00:00
d9c7608ade fix: deeplink modal use new modal & DI stability (#5577)
* fix: deeplink

* feat: DI stability

* fix: lint

* fix: play server project deep link

* switch toggle icons

* pnpm prepr

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
2026-03-16 17:10:55 +00:00
Truman GaoandGitHub 7d3935a38d fix: misc fixes (#5584)
* fix: PATs editing bug #4908

* fix: gallery edit do not do falsy check on title and description

* feat: add aspect ratio on gallery images

* change aspect ratio to 16:9

* fix: mobile nav bar #5580

* use css::after instead for navbar fix

* adjust after content to fix thin line

* add save area inset for transform
2026-03-16 15:32:07 +00:00
Truman GaoandGitHub a67f596524 feat: remove project editing has moved helper banner (#5583)
* feat: remove project editing moved helper banner

* pnpm prepr
2026-03-16 12:52:32 +00:00
Truman GaoandGitHub 7fa0a277c6 feat: handle geyser extension (#5582)
* feat: add geyser extension detection

* feat: only show geyser if inferred
2026-03-16 12:52:16 +00:00
Truman GaoandGitHub 01c9dee612 refactor: no more vue multiselect (#5523)
* start multiselect component

* update styles

* small fix

* fix padding and styles

* add border bottom on sticky items

* add border bottom to search as well

* fix select all showing line

* use multi-select component for languages field

* add no options story for empty state

* refactor: remove vue-multiselect, replace with either our own combobox and multiselect

* pnpm prepr

* pnpm prepr

* fix combobox in transfer organization
2026-03-16 12:46:48 +00:00
Modrinth BotandGitHub d50a8efb26 New translations from Crowdin (main) (#5585) 2026-03-16 09:20:59 +00:00
Calum H.andGitHub be5ebacd84 fix: switching vers fix (#5574) 2026-03-15 12:58:10 +00:00
Calum H.andGitHub 989f282de3 fixes: post content tab release issues (#5566)
* fix: migrate old cache entries for CachedFileUpdate

* feat: toggle goofy fix + switch version reimpl in app and panel

* fix: multimc detection

* fix: add tie breaker for sorting

* feat: toggle hover state

* fix: lint
2026-03-14 22:43:59 +00:00
Calum H.andGitHub 8a2125ef16 feat: backups alignment with Figma (#5559)
* feat: backup admonitions

* feat: align modals + fix backupitem

* fix: body needs opac 80

* fix: lint
2026-03-13 22:27:06 +00:00
aecsocketandGitHub 31b541007d Revert "Unify server pinging implementations between app and backend (#5510)" (#5558) 2026-03-13 13:58:57 -07:00
Calum H.andGitHub 4792985e52 fix: search v3 proj type frontend (#5557) 2026-03-13 20:34:26 +00:00
Calum H.andGitHub 86c0937616 fix: app problems post release qa (#5554)
* fix: app problems post release qa

* fix: lint

* fix: dont prefill

* fix: toggle gap

* feat: macs thing

* fix: lint
2026-03-13 13:18:11 -07:00
Truman GaoandGitHub 51deba8cd1 feat: multi-select component (#5486)
* start multiselect component

* update styles

* small fix

* fix padding and styles

* add border bottom on sticky items

* add border bottom to search as well

* fix select all showing line

* use multi-select component for languages field

* add no options story for empty state

* fix height
2026-03-13 18:59:37 +00:00
Truman GaoandGitHub b2d40af9cd feat: confirm transfer project/org modals (#5532)
* feat: implement confirm transfer project/org modals

* pnpm prepr

* update warning banner copy

* update warning banner again
2026-03-13 18:56:32 +00:00
Prospector fc382e957b add basic changelog 2026-03-13 12:20:52 -07:00
ProspectorandGitHub c9547bb988 Added content tab blog post (#5540)
* Added content tab blog post

* dont know why this change was in here

* update date
2026-03-13 12:18:16 -07:00
Prospector adef71b89a 0.12.2 changelog
(cherry picked from commit 4439c25b8d1d7894a81a25d8d67c9f9334a11273)
2026-03-13 12:12:28 -07:00
Calum H.andGitHub c44cc38b3a fix: backups resilience improvements (#5555)
* fix: backups

* fix: stability
2026-03-13 12:10:13 -07:00
aecsocketandGitHub 455a4f527d Add title stemming to typesense (#5553) 2026-03-13 17:03:54 +00:00
f918df2d7a feat(app): add more free official Java Edition skin packs as default skins (#5529)
Signed-off-by: Pendonym <265675176+Pendonym@users.noreply.github.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Calum H. <calum@modrinth.com>
2026-03-13 17:00:12 +00:00
aecsocketandGitHub c8279481f8 Revert last canary flag PR and use a better method (#5535)
* Revert "Implement Labrinth Canary API flag (#5531)"

This reverts commit 3b21944a75.

* Use Labrinth-Canary header instead of cookie for API canary

* prepr

* fix rebase
2026-03-13 16:29:08 +00:00
aecsocketandGitHub d14360aba5 Unify server pinging implementations between app and backend (#5510)
* Improve ping impl to bring parity to app lib impl

* Fix issue with new impl

* fix labrinth compile

* wip: why do servers not provide server info..

* Fix ping impl overriding port

* fix theseus_gui

* remove unneeded recursion lmit
2026-03-13 16:21:09 +00:00
aecsocketandGitHub 991b4d8c13 Fix Typesense tests (#5541)
* Fix Typesense tests

* fix

* add back author

* Split project title and authors by words and index on that

* clippy
2026-03-13 13:34:51 +00:00
Truman GaoandGitHub cc9059fb4a fix: search pagination (#5548) 2026-03-12 23:27:09 -07:00
Calum H.andGitHub 32d76b8025 fix: lint (#5544) 2026-03-13 00:09:26 +01:00
Calum H.andGitHub ba06c89a0e fix: content tab fixes (#5543)
* fix: search again

* fix: navigation bug

* fix: switch to stable key for toggle disable

* feat: inline backup slow warning icon

* fix: qa

* feat: fix installation state
2026-03-12 23:52:55 +01:00
Prospector 52d46b8aaa App 0.12.0 changelog 2026-03-12 13:59:19 -07:00
Truman GaoandGitHub bdc204eebd fix: misc server projects fixes (#5537)
* fix: add server to instance modal opens slow

* fix: creators section org doesnt display for project pages in app

* feat: separate modpacks and servers tabs in instances library
2026-03-12 13:26:14 -07:00
7d92e4ec7f feat: content tab rewrite for worlds (#5136)
* feat: base content card component

* fix: tooltips + colors

* feat: fix orgs

* feat: base content tab internals rewrite

* feat: fix invalidmodal

* feat: add ContentModpackCard

* fix: extract types

* draft: layout

* feat: unlink modal

* feat: impl content tab

* fix: lint

* fix: toggling

* temp: disable updating stuff

* feat: selection v-model

* feat: bulk selection

* feat: mods tab rough draft

* feat: use fuse.js

* feat: add project combobox

* clean up project combobox

* feat: start install to play modal

* fix: events

* feat: use v-on

* feat: bulk actions + fix floating action bar width

* 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: use ContentCardTable + ContentCardItems

* feat: fix gap + border issues on last elm

* feat: cleanup + use proper searching

* fix: use TeleportOverflowMenu

* 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

* feat: impl modal

* feat(app): backend changes for content tab refactor (#5237)

* feat: include_changelog=false for updater modal

* fix: hash overrides

* feat: update checking for modpack

* feat: qa

* feat: modpack content modal

* fix: padding in table to match modals + tightness

* fix: lint

* feat: delete modal

* feat: fix toggle bugs

* fix: prepr

* fix: duplicate messages

* qa: full width search

* qa: use bg-surface-1.5

* qa: animation for filter pills

* qa: standardize hover colors

* fix: border-[1px] is border

* qa: mass de-select actually mass selecting

* qa: match figma designs for floating action bar

* qa: modal fixes

* q: modal fixes x2

* fix: table border

* qa: confirm modals

* qa: modal alignment

* qa: re-add stuck heading + dedupe logic

* qa: dedupe virtual scrolling + remove dead components

* qa: responsiveness for content table + link fixes

* qa: version column link, tooltips + lint fixes

* qa: instance busy protections

* fix: installation freeze bug

* chore: remove old mods page

* refactor: deduplicate layout

* chore: delete old content page(s)

* qa

* qa

* qa

* feat: sort btn - to iterate

* fix: ml

* feat: date added

* fix: lint

* fix: formatting.ts removal

* feat: get_dependencies_as_content_items

* qa: final QA changes

* refactor: deduplicate + polish content.rs

* feat: hook up content.vue with v1

* feat: hide v1 content api behind frontend feature flag

* fix: query keys + copy on empty state

* chore: i18n pass

* feat: reimpl unlink + upload endpoint

* feat: use bulk endpoints v1

* fix: lint

* fix: flags

* fix: responsiveness via container queries

* fix: lint

* qa: 1

* qa: fixes

* qa: fix ssr issues with browse content

* qa: header page divider

* qa: modals

* fix: prepr

* fix: issues

* fix: lint

* fix: toggle v1 ff

* qa: 5

* qa: delete modal copy

* feat: creation flow modals (#5383)

* refactor: delete content v0 usages + impl

* feat: qa + fixes

* feat: installing banner using state event

* feat: fix modpack card bugs + filtering issues

* refactor: delete backups v0 api module

* feat: v1 servers GET endpoint

* fix: backups

* feat: swap to kyros upload v1 addon

* fix: use tanstack for loader.vue

* feat: finish install from discovery modal

* qa: bug fixes

* feat: set up installation settings

* fix: lint

* fix: typos

* fix: bugs

* fix: disable inline content

* feat: content tab improvements — upload UX, installation settings, and client-only indicators

   Upload cancellation and navigation guard:
   - Add ConfirmLeaveModal that prompts when navigating away during upload
   - Cancel in-flight XHR uploads when user confirms leaving the page
   - Add beforeunload handler to warn on browser/tab close during upload
   - Track uploadedBytes/totalBytes in UploadState for progress display
   - Replace Collapsible with Transition for upload progress admonition
   - Show byte progress and percentage in upload banner
   - Clamp upload progress to prevent exceeding 100%

   Installation settings (server.properties):
   - Add KnownPropertiesFields and PropertiesFields types to Archon types
   - Add buildProperties() to creation flow context to collect gamemode,
     difficulty, seed, world type, structures, and generator settings
   - Pass properties through installContent on onboarding, discovery, and
     ServerSetupModal flows

   Server setup and discovery flow improvements:
   - Migrate ServerSetupModal from servers_v0.reinstall to content_v1.installContent
   - Replace loaderApiNames lookup with toApiLoader() helper
   - Remove eraseDataOnInstall toggle — always use soft_override: false
   - Simplify modpack install on discovery page to use first available version
     and route through creation flow modal for both onboarding and non-onboarding
   - Differentiate post-install navigation: content page for onboarding,
     loader options for existing servers

   Modpack update flow:
   - Replace updateModpack() call with installContent() using soft_override: true
     to support version selection in the content updater modal

   Client-only mod indicators:
   - Add environment field to AddonVersion (reuses Labrinth.Projects.v3.Environment)
   - Add environment to ContentItem and isClientOnly to ContentCardTableItem
   - Show orange TriangleAlertIcon with tooltip on client-only mods in content table
   - Add "Client-only" filter pill to content filtering (controlled via
     showClientOnlyFilter on ContentManagerContext)
   - Apply client-only indicators in both ContentPageLayout and ModpackContentModal

   Misc:
   - Add CLAUDE.md note about using prepr commands for lint checks
   - Export ConfirmLeaveModal from instances barrel

* fix: piping

* fix: switch content disable for linked server instances

* feat: client only filter

* fix: prepr

* feat: hasUpdate shape update

* feat: bulk update endpoint impl for content in panel

* feat: websocket state impl again with new phases

* fix: ws

* fix: use timeout fn for sync admon + fix content card layout scroll for browsers with overflow anchor bug

* fix: qa bugs

* fix: lint, a11y and i18n

* refactor: set up layouts folder properly

* fix: linked data cache stuff + lint

* feat: move installationsettings to shared layout

* fix: lint

* fix: issues

* feat: temp fuck staging up

* fix: lockfile

* fix: data sync issues on loader.vue

* fix: lint

* Hide shader configuration files from content list (#5499)

* feat: workaround search problem + split out reset

* fix: qa

* fix: changelog not showing on first open

* fix: qa + optimistic updating improvements

* fix: prepr+lint

* fix: qa

* feat: qa

* fix: lint

* fix: lint

* fix: build

* fix: build

* fix: type errors

* fix: fade and JAVA_HOME passthrough

* feat: qa

* feat: impl diff shit

* fix: qa

* fix: app qa

* feat: update diff modal

* fix: endpoint

* fix: qa

* fix: qa

* fix: use bulk in modpack modal

* feat: abort signal impl + fix issues

* fix: diff modal trunc

* feat: qa

* fix: qa

* feat: tooltip content tab

* fix: prepr

* fix: dismiss on settings btn

* feat: qa

* feat: dont clear handlers on disconnect

* fix: lint

* fix: wrangler + introduce staging-archon env file

---------

Signed-off-by: Calum H. <calum@modrinth.com>
Co-authored-by: tdgao <mr.trumgao@gmail.com>
Co-authored-by: Artyom Ezri <61311568+Artezon@users.noreply.github.com>
2026-03-12 13:24:32 -07:00
aecsocketandGitHub f0224dfff7 Search backend refactor with typesense impl (#5528)
* initial elasticsearch impl

* working elastic cluster

* replace SearchError with ApiError for preparation of search backend

* start factoring meili out to trait

* move meili to backend

* update routes to use search backend trait

* wip

* Update projects.rs

* search backend is only init'd once in config

* wip

* wip: backend agnostic

* change search internal routes to delegate to backend

* initial elasticsearch impl

* fix filtering

* elastic impl

* refactor indexing into its own module

* clean up elastic code

* fix ci

* fix tests

* fix elastic health check

* fix up env rebase

* fix compile

* dummy commit to update github pr

* Fix rebase

* Elastic basic https auth

* Fix duplicate projects showing up

* Fix up tests

* Replace search `ApiErrors` with `eyre::Reports`, propagate background task errors

* clean up agents files

* make index chunk size configurable

* make `match_phrase` in elastic case-insensitive

* use current/next indices and swap between them

* test case for error body

* Fix failing case

* da merge

* factor out common stuff from search backends

* allow fetching hit metadata from search results

* allow customising elasticsearch search config

* bit of docs

* add mappings to indices for elastic

* Implement Typesense

* wip

* fix up some sort fields stuff

* use different approach to filterable field sets

* remove a bunch of search fields which weren't used for filtering

* bucket text matches

* Bucketing by text_match for typesense

* fix tombi lint

* fix some sentry errors and dont prioritise 2+ term matches

* tweak ts query settings

* expose some more search settings

* query sort changes

* small fixes

* should fix pagination stuff

* fix healthcheck maybe

* ragebait ci

* tests

* tests

* revert environment
2026-03-12 18:58:55 +01:00
aecsocketandGitHub 1c1683adb6 Fix various user/project deletion queries (#5511) 2026-03-12 12:46:39 +00:00
aecsocketandGitHub 407e6217f5 Fix permissions on project component edits (#5526) 2026-03-11 19:09:44 +00:00
Truman GaoandGitHub 83ea7f684b fix: permissions for server compatibility (#5525)
* disable buttons for server compatibility settings

* update permissions checkboxes
2026-03-11 18:45:06 +00:00
aecsocketandGitHub 3b21944a75 Implement Labrinth Canary API flag (#5531) 2026-03-11 15:28:09 +00:00
1143 changed files with 127914 additions and 43316 deletions
+14 -152
View File
@@ -1,156 +1,18 @@
# Adding a New API Module
---
name: api-module
description: Add a new API endpoint module to packages/api-client from an OpenAPI schema. Use when adding new backend endpoints, creating API client modules, or when an openapi.yml is provided.
argument-hint: <path-to-openapi.yml>
---
How to add a new API endpoint module to `packages/api-client`.
Refer to the standard: @standards/frontend/ADDING_API_MODULES.md
## Steps
### 1. Define types in the module's `types.ts`
Types must match 1:1 with the backend API response. Do not reshape, rename, or omit fields.
Add to an existing namespace or create a new one:
```ts
// modules/labrinth/types.ts (existing namespace)
export namespace Labrinth {
export namespace MyDomain {
export namespace v3 {
export type Thing = {
id: string
name: string
created: string
// ... matches API response exactly
}
export type CreateThingRequest = {
name: string
}
}
}
}
```
For a new API service, create `modules/<service>/types.ts` with a new top-level namespace and re-export it from `modules/types.ts`.
### 2. Create the module class
Create `modules/<api>/<domain>/v<N>.ts`:
```ts
// modules/labrinth/things/v3.ts
import { AbstractModule } from '../../../core/abstract-module'
import type { Labrinth } from '../types'
export class LabrinthThingsV3Module extends AbstractModule {
public getModuleID(): string {
return 'labrinth_things_v3'
}
public async get(id: string): Promise<Labrinth.MyDomain.v3.Thing> {
return this.client.request<Labrinth.MyDomain.v3.Thing>(`/thing/${id}`, {
api: 'labrinth',
version: 3,
method: 'GET',
})
}
public async create(data: Labrinth.MyDomain.v3.CreateThingRequest): Promise<Labrinth.MyDomain.v3.Thing> {
return this.client.request<Labrinth.MyDomain.v3.Thing>(`/thing`, {
api: 'labrinth',
version: 3,
method: 'POST',
body: data,
})
}
public async delete(id: string): Promise<void> {
return this.client.request(`/thing/${id}`, {
api: 'labrinth',
version: 3,
method: 'DELETE',
})
}
}
```
#### Request options
| Field | Values | Purpose |
|-------|--------|---------|
| `api` | `'labrinth'`, `'archon'`, or a full URL | Which base URL to use |
| `version` | `2`, `3`, `'internal'`, `'modrinth/v0'`, etc. | URL version segment |
| `method` | `'GET'`, `'POST'`, `'PUT'`, `'PATCH'`, `'DELETE'` | HTTP method |
| `body` | object | JSON request body |
| `params` | `Record<string, string>` | Query parameters |
| `skipAuth` | `boolean` | Skip auth feature for this request |
| `useNodeAuth` | `boolean` | Use node-level auth (kyros) |
| `timeout` | `number` | Request timeout in ms |
| `retry` | `boolean \| number` | Override retry behavior |
#### For uploads
Return an `UploadHandle` instead of a `Promise`:
```ts
public uploadThing(id: string, file: File): UploadHandle<void> {
return this.client.upload<void>(`/thing/${id}/file`, {
api: 'labrinth',
version: 3,
file,
})
}
// Or with FormData for multipart:
public createWithFiles(data: CreateRequest, files: File[]): UploadHandle<Thing> {
const formData = new FormData()
formData.append('data', JSON.stringify(data))
files.forEach((f, i) => formData.append(`file-${i}`, f, f.name))
return this.client.upload<Thing>(`/thing`, {
api: 'labrinth',
version: 3,
formData,
timeout: 60 * 5 * 1000, // longer timeout for uploads
})
}
```
### 3. Register in the MODULE_REGISTRY
Add to `modules/index.ts`:
```ts
import { LabrinthThingsV3Module } from './labrinth/things/v3'
export const MODULE_REGISTRY = {
// ... existing modules
labrinth_things_v3: LabrinthThingsV3Module,
} as const
```
The naming convention is `<api>_<domain>_<version>`. This flat key gets transformed into nested access: `client.labrinth.things_v3`.
### 4. Export types
If you added to an existing namespace, types are already re-exported. If you created a new `types.ts`, add it to `modules/types.ts`:
```ts
export * from './<service>/types'
```
## Naming Conventions
| Convention | Example |
|-----------|---------|
| Module class | `LabrinthThingsV3Module``{Api}{Domain}V{N}Module` |
| Module ID | `labrinth_things_v3``{api}_{domain}_v{n}` |
| Type namespace | `Labrinth.MyDomain.v3.Thing` |
| File path | `modules/labrinth/things/v3.ts` |
## Key Files
- `src/core/abstract-module.ts` — base class all modules extend
- `src/core/abstract-client.ts``request()` and `upload()` methods
- `src/modules/index.ts``MODULE_REGISTRY` and `buildModuleStructure()`
- `src/modules/<api>/types.ts` — type definitions per API
- `src/types/upload.ts``UploadHandle`, `UploadProgress`, `UploadRequestOptions`
1. **Read the OpenAPI schema** at `$ARGUMENTS` — identify the endpoints, request/response shapes, and path parameters.
2. **Read the standard above** for naming conventions, type rules, and the module registration pattern.
3. **Determine the service and version** — the URL path prefix tells you which service directory and version namespace to use (e.g. `/v3/projects``labrinth/v3/`).
4. **Define types in `types.ts`** — types must match the API response 1:1. Use the OpenAPI schema as the source of truth. Do not reshape or rename fields.
5. **Create the module class** — extend `BaseModule`, implement each endpoint as a method. Use the correct HTTP verb and request options pattern from the standard.
6. **Register in `MODULE_REGISTRY`** — add the module entry so it's auto-instantiated on the client.
7. **Export types** from the service's barrel `index.ts`.
8. **Verify** — check that the module compiles and the types are accessible from `@modrinth/api-client`.
+23 -141
View File
@@ -1,144 +1,26 @@
# Cross-Platform Page System
---
name: cross-platform-pages
description: Convert a page to the cross-platform page system so it works in both the website and the desktop app. Use when moving a page into packages/ui/src/layouts/, creating shared or wrapped layouts, or setting up DI contracts for platform abstraction.
argument-hint: <path-to-page>
---
When a page needs to exist in both the Modrinth App (`apps/app-frontend`) and the Modrinth Website (`apps/frontend`), use the cross-platform page system.
Refer to the standards: @standards/frontend/CROSS_PLATFORM_PAGES.md and @standards/frontend/DEPENDENCY_INJECTION.md
## How It Works
## Steps
1. **Pages live as Vue SFCs in `packages/ui`** — either in `src/pages/` or `src/layout/` (if `src/pages/` doesn't exist, it's been renamed to `src/layout/`).
2. **Platform-dependent data flows via DI** — the app uses Tauri `invoke` commands, the website uses `api-client` or the legacy `useBaseFetch` composable. The shared page never knows which. See the `dependency-injection` skill for full DI docs.
3. **Non-platform-dependent data flows via props** — if data doesn't change based on _how_ it's fetched, just pass it as a prop.
## Example: Content Page
`ContentPageLayout` demonstrates the full pattern.
### 1. Define a DI contract in `packages/ui/src/providers/`
The provider interface abstracts all platform-specific operations:
```ts
// packages/ui/src/providers/content-manager.ts
export interface ContentManagerContext {
items: Ref<ContentItem[]>
loading: Ref<boolean>
error: Ref<Error | null>
contentTypeLabel: Ref<string>
// These are the platform-abstracted operations:
// App uses invoke(), website uses api-client
toggleEnabled: (item: ContentItem) => Promise<void>
deleteItem: (item: ContentItem) => Promise<void>
refresh: () => Promise<void>
browse: () => void
uploadFiles: () => void
// Optional capabilities — not every platform supports everything
hasUpdateSupport: boolean
updateItem?: (item: ContentItem) => Promise<void>
bulkUpdateItem?: (items: ContentItem[]) => Promise<void>
mapToTableItem: (item: ContentItem) => ContentCardTableItem
}
export const [injectContentManager, provideContentManager] =
createContext<ContentManagerContext>('ContentManager')
```
### 2. Build the shared page in `packages/ui`
The page component injects the context and handles all UI logic (search, filtering, selection, bulk operations, empty states, modals) without knowing the platform:
```vue
<!-- packages/ui/src/components/instances/ContentPageLayout.vue -->
<script setup lang="ts">
import { injectContentManager } from '../../providers/content-manager'
const { items, loading, toggleEnabled, deleteItem, refresh, mapToTableItem } =
injectContentManager()
// All UI logic lives here — search, filters, sort, bulk ops, etc.
</script>
<template>
<ContentCardTable :items="filteredItems" />
</template>
```
### 3. Each platform provides its implementation
**Website (Nuxt)** — uses `api-client` or `useBaseFetch`:
```vue
<!-- apps/frontend/src/pages/hosting/manage/[id]/content.vue -->
<script setup lang="ts">
import { provideContentManager, ContentPageLayout } from '@modrinth/ui'
const { labrinth } = injectModrinthClient()
const { data: items } = useQuery({
queryKey: ['content', serverId],
queryFn: () => labrinth.servers_v0.getAddons(serverId),
})
provideContentManager({
items: computed(() => items.value?.map(addonToContentItem) ?? []),
deleteItem: async (item) => {
await labrinth.servers_v0.deleteAddon(serverId, item.id)
},
// ... rest of the contract
})
</script>
<template>
<ContentPageLayout />
</template>
```
**App (Tauri)** — uses `invoke`:
```vue
<!-- apps/app-frontend/src/pages/instance/Content.vue -->
<script setup lang="ts">
import { provideContentManager, ContentPageLayout } from '@modrinth/ui'
import { invoke } from '@tauri-apps/api/core'
const items = ref<ContentItem[]>([])
await invoke('get_instance_content', { instanceId }).then(/* map to ContentItem[] */)
provideContentManager({
items,
deleteItem: async (item) => {
await invoke('delete_content', { instanceId, path: item.file_path })
},
// ... rest of the contract
})
</script>
<template>
<ContentPageLayout />
</template>
```
## When to Use Props vs DI
| Use | When |
| --------- | -------------------------------------------------------------------------------------------------------- |
| **DI** | The data depends on _how_ it's fetched (different per platform) — API calls, file operations, navigation |
| **Props** | The data is the same regardless of platform — configuration flags, display options |
## Composables for Shared Logic
Extract reusable stateful logic into composables in `packages/ui/src/composables/`. The shared page orchestrates them internally:
- Search (Fuse.js fuzzy search over items)
- Filtering (dynamic filter pills)
- Selection (multi-select with bulk operations)
- Bulk operations (sequential execution with progress tracking)
## Key Files
- `packages/ui/src/pages/` (or `src/layout/`) — shared page components
- `packages/ui/src/providers/` — DI contracts
- `packages/ui/src/composables/` — shared stateful logic
- `apps/frontend/src/app.vue` — website root provider setup
- `apps/app-frontend/src/App.vue` — app root provider setup
- `apps/app-frontend/src/routes.js` — app route definitions
1. **Read the target page** at `$ARGUMENTS` and understand its data sources, mutations, and navigation.
2. **Read the standards above** to understand the shared vs wrapped distinction and the DI pattern.
3. **Decide the category:**
- **Wrapped** (`layouts/wrapped/`) — if the page uses the same API source on both platforms (e.g. web requests, not Tauri plugins). Just move the page component into `packages/ui` and import it from both frontends.
- **Shared** (`layouts/shared/`) — if the page has different data-fetching logic per platform (e.g. website uses `api-client`, app uses Tauri `invoke`). Requires a DI contract.
4. **For shared layouts:**
- Define a DI contract interface in `providers/` capturing all platform-specific operations.
- Create the layout component that injects the context and handles all UI logic.
- Extract reusable stateful logic (search, filtering, selection) into `composables/`.
- Implement the contract separately in each frontend (`apps/frontend/`, `apps/app-frontend/`).
5. **For wrapped pages:**
- Move the page component into `packages/ui/src/layouts/wrapped/` matching the route structure.
- Replace any platform-specific imports with shared utilities.
- Import and render the wrapped page from both frontends as a simple component.
- If the layout uses TanStack Query for initial route paint with `ReadyTransition` / `useReadyState`, each platform route shell must call `ensureQueryData` for those queries with matching keys and fetchers — see **Platform route shells: prefetch with `ensureQueryData`** in `standards/frontend/CROSS_PLATFORM_PAGES.md`.
6. **Verify** the page renders correctly by checking for missing imports and that all DI contracts are satisfied.
+19 -42
View File
@@ -1,45 +1,22 @@
# Figma MCP Usage
---
name: figma-mcp
description: Use the Figma MCP server to translate a Figma design into a Vue page or component layout. Use when the user provides a Figma URL, asks to implement a design, or wants to draft a page layout from Figma.
argument-hint: <figma-url>
---
When the Figma MCP server is connected, use it to translate Figma designs into production-ready Vue components for this monorepo.
Refer to the standard: @standards/frontend/FIGMA_MCP_USAGE.md
Also read @packages/ui/CLAUDE.md for color token mapping and component conventions.
## Workflow
## Steps
### 1. Get the design context
Use `get_design_context` with the node ID from a Figma URL. If the URL is `https://figma.com/design/:fileKey/:fileName?node-id=1-2`, the node ID is `1:2`.
```
get_design_context(nodeId: "1:2", clientLanguages: "typescript,html,css", clientFrameworks: "vue")
```
This returns reference code, a screenshot, and metadata. Always start here.
### 2. Get a screenshot for visual reference
Use `get_screenshot` if you need to see the design without full code context:
```
get_screenshot(nodeId: "1:2")
```
### 3. Get variable definitions
Use `get_variable_defs` to see what design tokens are applied to a node:
```
get_variable_defs(nodeId: "1:2")
```
### 4. Get metadata for structure overview
Use `get_metadata` to get an XML overview of node IDs, layer types, names, positions and sizes — useful for understanding the structure of a complex frame before diving into individual nodes.
## Adapting Figma Output
The Figma MCP returns generic reference code. Adapt it to match the Modrinth codebase:
1. **Read `packages/ui/CLAUDE.md`** for color usage rules, surface token mapping, and component patterns.
2. **Map Figma color variables to `surface-*` tokens** — never use Figma's aliased names like `bg/default` or `bg/raised` directly. The CLAUDE.md has the full mapping table.
3. **Check `packages/assets/styles/variables.scss`** for tokens not exposed in Figma (brand highlights, semantic backgrounds, shadows).
4. **Check for existing components** in `packages/ui/src/components/` before building from scratch.
5. **Match spacing exactly** — do not approximate values from the design.
1. **Parse the Figma URL** from `$ARGUMENTS` — extract the `fileKey` and `nodeId`. Convert `-` to `:` in the node ID.
2. **Read the standards above** for the available tools, adaptation rules, and color usage.
3. **Call `get_design_context`** with the extracted `nodeId` and `fileKey`, using `clientLanguages: "typescript,html,css"` and `clientFrameworks: "vue"`. This is always the first tool to call.
5. **Adapt the output to the Modrinth codebase:**
- Map Figma color variables to `surface-*` / `text-*` tokens — never use Figma's aliased names directly.
- Check `packages/ui/src/components/` for existing components that match elements in the design (buttons, cards, modals, inputs, etc.).
- Check `packages/assets/styles/variables.scss` for tokens not exposed in Figma.
- Match spacing values exactly from the design.
6. **Use `get_screenshot`** if you need a closer visual reference of specific nodes.
7. **Use `get_variable_defs`** to verify which design tokens are applied to ambiguous elements.
8. **Build the component** as a Vue SFC using Tailwind classes and the project's existing component library.
-105
View File
@@ -1,105 +0,0 @@
# i18n String Conversion
Convert hard-coded natural-language strings in Vue SFCs into the localization system using utilities from `@modrinth/ui`.
## Rules
### 1. Identify translatable strings
- Scan `<template>` for all user-visible strings: inner text, alt attributes, placeholders, button labels, etc.
- Check `<script>` too: dropdown option labels, notification messages, etc.
- Do NOT extract dynamic expressions (`{{ user.name }}`) or HTML tags — only static human-readable text.
### 2. Create message definitions
Import `defineMessage` or `defineMessages` from `@modrinth/ui` in `<script setup>`. Define messages with a unique `id` (descriptive prefix based on component path) and `defaultMessage` equal to the original English string:
```ts
const messages = defineMessages({
welcomeTitle: { id: 'auth.welcome.title', defaultMessage: 'Welcome' },
welcomeDescription: { id: 'auth.welcome.description', defaultMessage: "You're now part of the community…" },
})
```
### 3. Handle variables and ICU formats
- Dynamic parts become ICU placeholders: `"Hello, ${user.name}!"``defaultMessage: 'Hello, {name}!'`
- Numbers/dates/times use ICU options: `{price, number, ::currency/USD}`
- Plurals/selects use ICU: `'{count, plural, one {# message} other {# messages}}'`
### 4. Rich-text messages (links/markup)
Wrap link/markup ranges with tags in `defaultMessage`:
```
"By creating an account, you agree to our <terms-link>Terms</terms-link> and <privacy-link>Privacy Policy</privacy-link>."
```
Render with `<IntlFormatted>` from `@modrinth/ui` using named slots:
```vue
<IntlFormatted :message-id="messages.tosLabel">
<template #terms-link="{ children }">
<NuxtLink to="/terms">
<component :is="() => children" />
</NuxtLink>
</template>
<template #privacy-link="{ children }">
<NuxtLink to="/privacy">
<component :is="() => children" />
</NuxtLink>
</template>
</IntlFormatted>
```
For simple emphasis: `'Welcome to <strong>Modrinth</strong>!'` with a slot:
```vue
<template #strong="{ children }">
<strong><component :is="() => children" /></strong>
</template>
```
For complex child handling, use `normalizeChildren` from `@modrinth/ui`:
```vue
<template #bold="{ children }">
<strong><component :is="() => normalizeChildren(children)" /></strong>
</template>
```
### 5. Formatting in templates
Use `useVIntl()` from `@modrinth/ui`; prefer `formatMessage` for simple strings:
```ts
const { formatMessage } = useVIntl()
```
```vue
<button>{{ formatMessage(messages.welcomeTitle) }}</button>
{{ formatMessage(messages.greeting, { name: user.name }) }}
```
### 6. Naming conventions
Make `id`s descriptive and stable (e.g., `error.generic.default.title`). Group related messages with `defineMessages`.
### 7. Avoid Vue/ICU delimiter collisions
If an ICU placeholder ends right before `}}` in a Vue template, insert a space: `} }` to avoid parsing issues.
### 8. Imports
Ensure these are imported from `@modrinth/ui` as needed: `defineMessage`/`defineMessages`, `useVIntl`, `IntlFormatted`, `normalizeChildren`.
### 9. Preserve functionality
Do not change logic, layout, reactivity, or bindings — only refactor strings into i18n.
## Reference Examples
- Variables/plurals: `apps/frontend/src/pages/frog.vue`
- Rich-text link tags: `apps/frontend/src/pages/auth/welcome.vue` and `apps/frontend/src/error.vue`
When finished, there should be no hard-coded English strings left in the template — everything comes from `formatMessage` or `<IntlFormatted>`.
+24
View File
@@ -0,0 +1,24 @@
---
name: i18n-pass
description: Perform an i18n localization pass on changed files or a pull request, converting hard-coded English strings to the @modrinth/ui i18n system. Use when internationalizing a set of changes, reviewing a PR for untranslated strings, or converting a specific component.
argument-hint: [file-path-or-pr-number]
---
Refer to the standard: @standards/frontend/INTERNATIONALIZATION.md
## Steps
1. **Identify the scope of changes:**
- If `$ARGUMENTS` is a PR number, run `gh pr diff $ARGUMENTS` to get the changed files.
- If `$ARGUMENTS` is a file path, use that directly.
- If no argument, check `git diff` for uncommitted changes.
2. **Read the standard above** for the message definition pattern, ICU format rules, and `IntlFormatted` usage.
3. **Filter to Vue SFCs** — only `.vue` files need i18n passes. Skip non-component files.
4. **For each file, scan for hard-coded strings:**
- `<template>`: inner text, `alt`, `placeholder`, `aria-label`, button labels, tooltip text.
- `<script>`: string literals passed to user-visible UI (notification messages, dropdown labels, error messages).
- Skip: dynamic expressions, HTML tag names, CSS classes, internal identifiers, log messages.
5. **Define messages** with `defineMessages` — use descriptive, stable `id`s based on the component's domain (e.g. `project.settings.title`).
6. **Replace strings in templates** with `formatMessage()` calls, or `<IntlFormatted>` for strings containing links or markup.
7. **Handle ICU edge cases** — add a space before `}}` if an ICU placeholder ends at a Vue template delimiter boundary.
8. **Verify** no hard-coded English strings remain in the changed templates. Do not alter logic, layout, or reactivity.
-215
View File
@@ -1,215 +0,0 @@
# Multistage Modals
The `MultiStageModal` component (`packages/ui/src/components/base/MultiStageModal.vue`) provides a wizard-like modal with progress tracking, conditional stages, and per-stage button configuration.
## Architecture
A multistage modal has three parts:
1. **Context** — A DI provider that holds all state, business logic, and stage configs
2. **Stage configs** — Data objects describing each stage (title, component, buttons, skip conditions)
3. **Stage components** — Vue components rendered inside the modal, consuming the context
## Building a Multistage Modal
### 1. Define the context
Create a DI provider with all the state your wizard needs. Include the modal ref and stage configs.
```ts
// providers/my-feature/my-modal.ts
import type { ShallowRef } from 'vue'
import type { ComponentExposed } from 'vue-component-type-helpers'
import type { MultiStageModal, StageConfigInput } from '@modrinth/ui'
import { createContext } from '@modrinth/ui'
export interface MyModalContext {
// State
formData: Ref<MyFormData>
isSubmitting: Ref<boolean>
// Modal control
modal: ShallowRef<ComponentExposed<typeof MultiStageModal> | null>
stageConfigs: StageConfigInput<MyModalContext>[]
// Business logic
handleSubmit: () => Promise<void>
}
export const [injectMyModalContext, provideMyModalContext] =
createContext<MyModalContext>('MyModal')
export function createMyModalContext(
modal: ShallowRef<ComponentExposed<typeof MultiStageModal> | null>,
): MyModalContext {
const formData = ref<MyFormData>({ ... })
const isSubmitting = ref(false)
async function handleSubmit() {
isSubmitting.value = true
try {
await saveData(formData.value)
modal.value?.hide()
} finally {
isSubmitting.value = false
}
}
return { formData, isSubmitting, modal, stageConfigs, handleSubmit }
}
```
### 2. Define stage configs
Each stage is a `StageConfigInput<T>` where `T` is your context type. Most fields accept either a static value or a function receiving the context (`MaybeCtxFn<T, R>`).
```ts
// providers/my-feature/stages/details-stage.ts
import { markRaw } from 'vue'
import type { StageConfigInput } from '@modrinth/ui'
import type { MyModalContext } from '../my-modal'
import DetailsStage from './DetailsStage.vue'
import { RightArrowIcon, SaveIcon } from '@modrinth/assets'
export const detailsStageConfig: StageConfigInput<MyModalContext> = {
id: 'details',
stageContent: markRaw(DetailsStage),
title: 'Details',
// Conditional behavior based on context
skip: (ctx) => ctx.shouldSkipDetails.value,
cannotNavigateForward: (ctx) => !ctx.formData.value.name,
disableClose: (ctx) => ctx.isSubmitting.value,
leftButtonConfig: (ctx) => ({
label: 'Cancel',
onClick: () => ctx.modal.value?.hide(),
}),
rightButtonConfig: (ctx) => ({
label: 'Next',
icon: RightArrowIcon,
iconPosition: 'after',
disabled: !ctx.formData.value.name,
onClick: () => ctx.modal.value?.nextStage(),
}),
}
```
**Stage config fields:**
| Field | Type | Purpose |
|-------|------|---------|
| `id` | `string` | Unique stage identifier (used with `setStage()`) |
| `stageContent` | `Component` | Vue component to render (wrap with `markRaw()`) |
| `title` | `MaybeCtxFn<T, string>` | Stage title in breadcrumbs |
| `skip` | `MaybeCtxFn<T, boolean>` | Skip this stage conditionally |
| `nonProgressStage` | `MaybeCtxFn<T, boolean>` | Exclude from progress bar (for edit sub-flows) |
| `hideStageInBreadcrumb` | `MaybeCtxFn<T, boolean>` | Hide from breadcrumb nav |
| `cannotNavigateForward` | `MaybeCtxFn<T, boolean>` | Block forward navigation (validation) |
| `disableClose` | `MaybeCtxFn<T, boolean>` | Disable closing the modal |
| `leftButtonConfig` | `MaybeCtxFn<T, StageButtonConfig \| null>` | Left action button |
| `rightButtonConfig` | `MaybeCtxFn<T, StageButtonConfig \| null>` | Right action button |
| `maxWidth` | `MaybeCtxFn<T, string>` | Per-stage max width (default `560px`) |
**Button config fields:**
| Field | Purpose |
|-------|---------|
| `label` | Button text |
| `icon` | Icon component |
| `iconPosition` | `'before'` or `'after'` |
| `color` | ButtonStyled color prop |
| `disabled` | Disable the button |
| `onClick` | Click handler |
### 3. Create stage components
Stage components inject the context and render their UI:
```vue
<!-- providers/my-feature/stages/DetailsStage.vue -->
<script setup lang="ts">
import { injectMyModalContext } from '../my-modal'
const { formData } = injectMyModalContext()
</script>
<template>
<div class="flex flex-col gap-4">
<StyledInput v-model="formData.name" label="Name" />
<StyledInput v-model="formData.description" label="Description" />
</div>
</template>
```
### 4. Create the wrapper component
The wrapper provides context and renders `MultiStageModal`:
```vue
<!-- components/MyModalWrapper.vue -->
<script setup lang="ts">
import { shallowRef } from 'vue'
import { MultiStageModal } from '@modrinth/ui'
import { createMyModalContext, provideMyModalContext } from '../providers/my-feature/my-modal'
const modal = shallowRef<InstanceType<typeof MultiStageModal> | null>(null)
const ctx = createMyModalContext(modal)
provideMyModalContext(ctx)
defineExpose({ show: () => modal.value?.show() })
</script>
<template>
<MultiStageModal ref="modal" :stages="ctx.stageConfigs" :context="ctx" />
</template>
```
## Modal API
`MultiStageModal` exposes via ref:
| Method/Property | Description |
|----------------|-------------|
| `show()` | Open the modal |
| `hide()` | Close the modal |
| `setStage(indexOrId)` | Jump to stage by index or string id |
| `nextStage()` | Advance to next non-skipped stage |
| `prevStage()` | Go back to previous stage |
| `currentStageIndex` | Ref to current stage index |
## Non-Progress Stages (Edit Sub-Flows)
For stages that shouldn't appear in the progress bar (e.g. editing a specific field from a summary page):
```ts
export const editLoadersStageConfig: StageConfigInput<MyContext> = {
id: 'edit-loaders',
nonProgressStage: true,
stageContent: markRaw(EditLoadersStage),
title: 'Edit loaders',
leftButtonConfig: (ctx) => ({
label: 'Back',
onClick: () => ctx.modal.value?.setStage('summary'),
}),
rightButtonConfig: (ctx) => ({
...ctx.saveButtonConfig(),
label: 'Save',
}),
}
```
Navigate to it with `modal.value?.setStage('edit-loaders')` — it won't affect the progress indicator.
## Reference Implementation
The version creation/edit modal is the most complete example:
| File | Purpose |
|------|---------|
| `apps/frontend/src/providers/version/manage-version-modal.ts` | Context creation + business logic |
| `apps/frontend/src/providers/version/stages/index.ts` | Stage config barrel export |
| `apps/frontend/src/providers/version/stages/*-stage.ts` | Individual stage configs |
The context includes computed properties for conditional UI, watchers for auto-fetching dependencies, loading states for granular button disabling, and both "create" and "edit" flows sharing the same stages with different button configs.
+36
View File
@@ -0,0 +1,36 @@
---
name: review-changelog
description: Review the latest changelog entry in packages/blog/changelog.ts against the project's changelog style guide and flag bullets that need rewriting. Use when checking a freshly added changelog entry before opening a PR, or when the user asks to review/lint the latest changelog.
argument-hint: [product?]
---
Refer to the standard: @standards/maintaining/CHANGELOG.md
## Steps
1. **Locate the latest entry:**
- Open `packages/blog/changelog.ts`.
- The latest entries are at the top of the `VERSIONS` array.
- If `$ARGUMENTS` specifies a product (`web`, `hosting`, `app`), review the most recent entry for that product. Otherwise, review the most recent entry overall, plus any sibling entries sharing the same `date` (coordinated releases ship together).
2. **Read the standard above** in full before reviewing. The bullet rules, section/verb agreement, and "Don't" list are the source of truth.
3. **Check the entry shell:**
- `date` is a valid ISO 8601 timestamp.
- `product` is one of `web`, `hosting`, `app`.
- `version` is present for `app` entries and omitted for `web`/`hosting`.
- Section headings use `## Added`, `## Changed`, `## Fixed`, `## Security` (or a featured-release linked heading). Flag legacy `## Improvements`.
4. **Review each bullet** against the standard. For each bullet, check:
- Voice/tense matches the section heading.
- Opening verb agrees with its section.
- Describes observable behavior, not implementation.
- Specific enough to identify the surface (names the tab/page/modal).
- One sentence, ends with a period, sentence case.
- Uses branded names (Modrinth App, Modrinth Hosting) correctly.
- No filler ("issue with", "issue where", "various", "some"), no vague intensifiers, no apologies, no PR/commit references (unless crediting a third-party contributor with a linked GitHub profile).
- Not a duplicate sub-fix of a bigger change already listed.
5. **Report findings** as a short list grouped by entry. For each problem bullet, show the original line and a suggested rewrite. If the entry is clean, say so explicitly. Do not edit the file unless the user asks - this skill is a review pass, not a rewrite pass.
6. **If the user then asks to apply fixes**, edit `packages/blog/changelog.ts` directly using the suggested rewrites. Preserve tab indentation and template literal formatting.
+24 -151
View File
@@ -1,154 +1,27 @@
# TanStack Query
---
name: tanstack-query
description: Convert a page or component from useAsyncData/manual ref patterns to TanStack Query for server state management. Use when migrating data fetching to useQuery/useMutation, adding cache invalidation, or replacing useAsyncData with TanStack Query.
argument-hint: <path-to-file>
---
TanStack Query (`@tanstack/vue-query` v5) is used for server state management — caching, background refetching, and cache invalidation. Use it instead of manual `ref()` + `await` patterns for any data that comes from an API.
Refer to the standard: @standards/frontend/FETCHING_DATA.md
A TanStack MCP server is available — use `tanstack_doc` and `tanstack_search_docs` tools to look up API details when needed.
## Steps
## Setup
TanStack Query is configured in `apps/frontend/src/plugins/tanstack.ts` as a Nuxt plugin with SSR hydration support. Default stale time is 5 seconds. The `QueryClient` is available via `useQueryClient()` or `useAppQueryClient()` (which also works in middleware).
## Queries
Use `useQuery` with the api-client for data fetching:
```ts
const client = injectModrinthClient()
const { data, isPending, isError, error } = useQuery({
queryKey: ['project', 'v3', projectId],
queryFn: () => client.labrinth.projects_v3.get(projectId),
staleTime: 1000 * 60 * 5,
})
```
In templates:
```vue
<span v-if="isPending">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<div v-else>{{ data.title }}</div>
```
### Query Option Factories
For queries used across multiple components, define reusable query option factories in `packages/ui/src/queries/`:
```ts
// composables/queries/project.ts
export const STALE_TIME = 1000 * 60 * 5
export const STALE_TIME_LONG = 1000 * 60 * 10
export const projectQueryOptions = {
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,
}),
}
```
Then use them:
```ts
const { data } = useQuery(projectQueryOptions.v3(projectId, client))
```
### Conditional Queries
Use `enabled` as a computed for queries that depend on other data:
```ts
const { data: members } = useQuery({
queryKey: ['project', projectId, 'members'],
queryFn: () => client.labrinth.projects_v3.getMembers(projectId),
enabled: computed(() => !!projectId.value),
})
```
## Mutations
Use `useMutation` for create/update/delete operations. Invalidate related queries on success:
```ts
const queryClient = useQueryClient()
const client = injectModrinthClient()
const createMutation = useMutation({
mutationFn: (name: string) => client.archon.backups_v0.create(serverId, { name }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['backups', 'list', serverId] }),
})
```
Use `createMutation.isPending.value` to disable buttons during submission.
### Optimistic Updates
For mutations where responsiveness matters, use optimistic updates with rollback:
```ts
const patchMutation = useMutation({
mutationFn: async ({ projectId, data }) => {
await client.labrinth.projects_v3.patch(projectId, data)
return data
},
onMutate: async ({ projectId, data }) => {
await queryClient.cancelQueries({ queryKey: ['project', 'v3', projectId] })
const previous = queryClient.getQueryData(['project', 'v3', projectId])
queryClient.setQueryData(['project', 'v3', projectId], (old) => {
if (!old) return old
return { ...old, ...data }
})
return { previous }
},
onError: (_err, _variables, context) => {
if (context?.previous) {
queryClient.setQueryData(['project', 'v3', projectId], context.previous)
}
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['project', 'v3', projectId] })
},
})
```
## Query Keys
Keys use a hierarchical array pattern:
```ts
// Resource type → version/qualifier → ID
['project', 'v3', projectId]
// Resource type → ID → sub-resource
['project', projectId, 'members']
['project', projectId, 'versions', 'v3']
// Domain → action → ID
['backups', 'list', serverId]
['tech-reviews']
```
Use `as const` for type safety. Put the resource ID last when possible — this makes partial key matching work for invalidation:
```ts
// Invalidates all project queries for this ID
queryClient.invalidateQueries({ queryKey: ['project', projectId] })
```
## Key Files
- `apps/frontend/src/plugins/tanstack.ts` — QueryClient setup + SSR hydration
- `apps/frontend/src/composables/query-client.ts``useAppQueryClient()` helper
- `apps/frontend/src/composables/queries/` — reusable query option factories
1. **Read the target file** at `$ARGUMENTS` and identify all data-fetching patterns: `useAsyncData`, `useFetch`, manual `ref()` + `await`, or `onMounted` fetch calls.
2. **Read the standard above** for the query/mutation patterns, query key conventions, and optimistic update approach.
3. **Convert queries:**
- Replace `useAsyncData` / `useFetch` / manual fetches with `useQuery`.
- Use the `api-client` via `injectModrinthClient()` for the `queryFn`.
- Design query keys with the `['resource', 'version', ...params]` convention.
- Use `computed` query keys for reactive parameters.
- Use the `enabled` option for conditional queries that depend on other data.
4. **Convert mutations:**
- Replace manual `try/catch` + `ref` patterns with `useMutation`.
- Add `onSuccess` handlers that invalidate or update related query caches.
- Consider optimistic updates for UI-critical mutations (follow the pattern in the standard).
5. **Clean up:**
- Remove manual loading/error `ref()`s that are now handled by TanStack Query's return values (`isPending`, `isError`, `error`).
- Remove manual `onMounted` fetch calls.
- Ensure SSR compatibility — queries in Nuxt pages are automatically awaited during SSR.
6. **Verify** the page still renders correctly and that cache invalidation triggers re-fetches where expected.
+121
View File
@@ -0,0 +1,121 @@
name: Changelog Comment
on:
pull_request_target:
types: [opened, reopened]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to post the changelog comment on (for testing)'
required: true
type: number
jobs:
comment:
name: Post changelog comment
runs-on: ubuntu-latest
steps:
- name: 💬 Post or update changelog comment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.CROWDIN_GH_TOKEN }}
script: |
const marker = '<!-- changelog -->';
const mergedMarker = '<!-- changelog-merged -->';
const sections = ['### Added', '', '### Changed', '', '### Deprecated', '', '### Removed', '', '### Fixed', '', '### Security'].join('\n');
const productBlock = (name) => `<details>\n<summary>${name}</summary>\n\n${sections}\n\n</details>`;
const template = [
marker,
'## Pull request changelog',
'',
'<!-- Fill in the changelog under each product area this PR affects.',
' Empty sections are ignored. Leave a product collapsed/empty',
' if it doesn\'t apply. -->',
'',
productBlock('App'),
'',
productBlock('Website'),
'',
productBlock('Hosting'),
].join('\n');
// Resolve PR number from event or workflow_dispatch input
const prNumber = context.payload.pull_request?.number
?? parseInt('${{ github.event.inputs.pr_number }}', 10);
if (!prNumber || isNaN(prNumber)) {
core.setFailed('Could not determine PR number');
return;
}
// Get PR details (need base ref for child PR detection)
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
// Check if bot comment already exists
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const existingComment = comments.find(c => c.body.includes(marker));
if (existingComment) {
core.info('Changelog comment already exists, skipping');
return;
}
// Post the template comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: template,
});
core.info(`Posted changelog comment on PR #${prNumber}`);
// Detect child PR: check if this PR's base branch is another open PR's head branch
const baseRef = pr.base.ref;
if (baseRef === 'main' || baseRef === 'prod') {
return;
}
// Look for a parent PR whose head branch matches our base branch
const { data: candidatePRs } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
head: `${context.repo.owner}:${baseRef}`,
});
if (candidatePRs.length === 0) {
return;
}
const parentPR = candidatePRs[0];
core.info(`Detected parent PR #${parentPR.number} for child PR #${prNumber}`);
// Add admonition to child PR's changelog comment
const { data: childComments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const childChangelogComment = childComments.find(c => c.body.includes(marker));
if (childChangelogComment && !childChangelogComment.body.includes(mergedMarker)) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: childChangelogComment.id,
body: `${mergedMarker}\n> [!NOTE]\n> This changelog has been merged into the changelog for #${parentPR.number}\n\n${childChangelogComment.body}`,
});
}
+2 -1
View File
@@ -50,14 +50,15 @@ jobs:
uses: peter-evans/find-comment@v3
id: fc
with:
token: ${{ secrets.CROWDIN_GH_TOKEN }}
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: Frontend previews
- name: Comment deploy URL on PR
if: github.event_name == 'pull_request'
uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ secrets.CROWDIN_GH_TOKEN }}
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.fc.outputs.comment-id }}
body: |
+3
View File
@@ -27,12 +27,15 @@ on:
options:
- prod
- staging
- prod-with-staging-archon
default: prod
required: false
jobs:
build:
name: Build
env:
VITE_STRIPE_PUBLISHABLE_KEY: pk_live_51JbFxJJygY5LJFfKLVVldb10HlLt24p421OWRsTOWc5sXYFOnFUXWieSc6HD3PHo25ktx8db1WcHr36XGFvZFVUz00V9ixrCs5
strategy:
fail-fast: false
matrix:
+52 -17
View File
@@ -1,47 +1,68 @@
name: Modrinth App release
on:
workflow_dispatch:
inputs:
version-tag:
description: Version tag to release to the wide public
type: string
required: true
release-notes:
description: Release notes to include in the Tauri version manifest
default: A new release of the Modrinth App is available!
type: string
required: true
workflow_run:
workflows: ['Modrinth App build']
types: [completed]
jobs:
release:
name: Release Modrinth App
if: >-
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
startsWith(github.event.workflow_run.head_branch, 'v')
runs-on: ubuntu-latest
env:
VERSION_TAG: ${{ github.event.workflow_run.head_branch }}
LINUX_X64_BUNDLE_ARTIFACT_NAME: App bundle (x86_64-unknown-linux-gnu)
WINDOWS_X64_BUNDLE_ARTIFACT_NAME: App bundle (x86_64-pc-windows-msvc)
MACOS_UNIVERSAL_BUNDLE_ARTIFACT_NAME: App bundle (universal-apple-darwin)
LAUNCHER_FILES_BUCKET_BASE_URL: https://launcher-files.modrinth.com
steps:
- name: 📥 Check out code
uses: actions/checkout@v4
- name: 🔒 Verify ref is a tag
env:
GH_TOKEN: ${{ github.token }}
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
run: |
tag_sha=$(gh api "repos/${{ github.repository }}/git/refs/tags/${VERSION_TAG}" --jq '.object.sha' 2>/dev/null || true)
if [ -z "$tag_sha" ]; then
echo "::error::${VERSION_TAG} is not a git tag in this repo"
exit 1
fi
if [ "$tag_sha" != "$HEAD_SHA" ]; then
commit_sha=$(gh api "repos/${{ github.repository }}/git/tags/${tag_sha}" --jq '.object.sha' 2>/dev/null || echo "$tag_sha")
if [ "$commit_sha" != "$HEAD_SHA" ]; then
echo "::error::Tag ${VERSION_TAG} (${commit_sha}) does not match build head_sha (${HEAD_SHA})"
exit 1
fi
fi
echo "Verified ${VERSION_TAG} is a tag pointing at ${HEAD_SHA}"
- name: 📥 Download Modrinth App artifacts
uses: dawidd6/action-download-artifact@v11
with:
workflow: theseus-build.yml
workflow_conclusion: success
event: push
branch: ${{ inputs.version-tag }}
branch: ${{ env.VERSION_TAG }}
use_unzip: true
- name: 🛠️ Generate version manifest
- name: 📝 Extract app changelog
env:
VERSION_TAG: ${{ inputs.version-tag }}
RELEASE_NOTES: ${{ inputs.release-notes }}
VERSION: ${{ env.VERSION_TAG }}
run: npx --yes tsx scripts/build-theseus-release-notes.ts
- name: 🛠️ Generate version manifest
run: |
# Reference: https://tauri.app/plugin/updater/#server-support
jq -nc \
--arg versionTag "${VERSION_TAG#v}" \
--arg releaseNotes "$RELEASE_NOTES" \
--rawfile releaseNotes release-notes.md \
--rawfile macOsAarch64UpdateArtifactSignature "${MACOS_UNIVERSAL_BUNDLE_ARTIFACT_NAME}/universal-apple-darwin/release/bundle/macos/Modrinth App.app.tar.gz.sig" \
--rawfile macOsX64UpdateArtifactSignature "${MACOS_UNIVERSAL_BUNDLE_ARTIFACT_NAME}/universal-apple-darwin/release/bundle/macos/Modrinth App.app.tar.gz.sig" \
--rawfile linuxX64UpdateArtifactSignature "${LINUX_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/appimage/Modrinth App_${VERSION_TAG#v}_amd64.AppImage.tar.gz.sig" \
@@ -83,7 +104,6 @@ jobs:
- name: 📤 Upload release artifacts
env:
VERSION_TAG: ${{ inputs.version-tag }}
AWS_ACCESS_KEY_ID: ${{ secrets.LAUNCHER_FILES_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.LAUNCHER_FILES_BUCKET_SECRET_ACCESS_KEY }}
AWS_BUCKET: ${{ secrets.LAUNCHER_FILES_BUCKET_NAME }}
@@ -116,3 +136,18 @@ jobs:
done
aws s3 cp updates.json "s3://${AWS_BUCKET}"
- name: 🏷️ Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION="${VERSION_TAG#v}"
gh release create "$VERSION_TAG" \
--title "Modrinth App ${VERSION}" \
--notes-file release-notes.md \
"${WINDOWS_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/nsis/Modrinth App_${VERSION}_x64-setup.exe" \
"${MACOS_UNIVERSAL_BUNDLE_ARTIFACT_NAME}/universal-apple-darwin/release/bundle/dmg/Modrinth App_${VERSION}_universal.dmg" \
"${LINUX_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/appimage/Modrinth App_${VERSION}_amd64.AppImage" \
"${LINUX_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/deb/Modrinth App_${VERSION}_amd64.deb" \
"${LINUX_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/rpm/Modrinth App-${VERSION}-1.x86_64.rpm"
+6
View File
@@ -78,3 +78,9 @@ storybook-static
# frontend robots.txt
apps/frontend/src/public/robots.txt
# Oh My Code
.omc/
# Local dry-run output for scripts/build-theseus-release-notes.mjs
/test_result.md
+3 -1
View File
@@ -29,5 +29,7 @@
},
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer"
}
},
"css.lint.unknownAtRules": "ignore",
"scss.lint.unknownAtRules": "ignore"
}
-1
View File
@@ -1 +0,0 @@
See [CLAUDE.md](./CLAUDE.md) for all project instructions and guidelines.
+25 -13
View File
@@ -30,7 +30,7 @@ This is the Modrinth monorepo — it contains all Modrinth projects, both fronte
| `api-client` | API client for Nuxt, Tauri, and Node/browser |
| `app-lib` | Shared app library |
| `blog` | Blog system and changelog data |
| `utils` | Shared utility functions |
| `utils` | Shared utility functions (mostly deprecated) |
| `moderation` | Moderation utilities |
| `daedalus` | Daedalus protocol |
| `tooling-config` | ESLint, Prettier, TypeScript configs |
@@ -70,7 +70,7 @@ Each project may have its own `CLAUDE.md` with detailed instructions:
## Code Guidelines
### Comments
- DO NOT use "heading" comments like: // === Helper methods === .
- DO NOT use "heading" comments like: `=== Helper methods ===`.
- Use doc comments, but avoid inline comments unless ABSOLUTELY necessary for clarity. Code should aim to be self documenting!
## Bash Guidelines
@@ -78,21 +78,33 @@ Each project may have its own `CLAUDE.md` with detailed instructions:
### Output handling
- DO NOT pipe output through `head`, `tail`, `less`, or `more`
- NEVER use `| head -n X` or `| tail -n X` to truncate output
- Run commands directly without pipes when possible
- If you need to limit output, use command-specific flags (e.g. `git log -n 10` instead of `git log | head -10`)
- IMPORTANT: Run commands directly without pipes when possible
- IMPORTANT: If you need to limit output, use command-specific flags (e.g. `git log -n 10` instead of `git log | head -10`)
- ALWAYS read the full output — never pipe through filters
### General
- Do not create new non-source code files (e.g. Bash scripts, SQL scripts) unless explicitly prompted to
- For Frontend, when doing lint checks, only use the `prepr` commands, do not use `typecheck` or `tsc` etc.
- Types in `@modrinth/utils` are considered highly outdated, if a component needs them, check if you can switch said component to use types from `packages/api-client`
- When provided problems, do not say "I didn't introduce these problems" (shifting the blame/effort) - just fix them.
## Skills
## Edit Tool - Whitespace Handling (CLAUDE ONLY)
Project-specific skills (patterns, conventions, and implementation guides) are located in [`.claude/skills/`](./.claude/skills/). Each skill has a `SKILL.md` describing the pattern:
The Read tool uses `→` to mark where line numbers end and file content begins.
- **[Dependency Injection](./.claude/skills/dependency-injection/SKILL.md)** — Vue provide/inject DI layer using `createContext`
- **[Cross-Platform Pages](./.claude/skills/cross-platform-pages/SKILL.md)** — Shared component architecture across Nuxt and Tauri frontends
- **[Multistage Modals](./.claude/skills/multistage-modals/SKILL.md)** — Wizard-like modal flows with `MultiStageModal`
- **[Figma MCP](./.claude/skills/figma-mcp/SKILL.md)** — Translating Figma designs to Modrinth Vue components
- **[i18n Convert](./.claude/skills/i18n-convert/SKILL.md)** — Converting hard-coded strings to vue-i18n localization
- **[API Module](./.claude/skills/api-module/SKILL.md)** — Adding new endpoint modules to `@modrinth/api-client`
- **[TanStack Query](./.claude/skills/tanstack-query/SKILL.md)** — Server state management with `@tanstack/vue-query` v5
**Rule:** Copy the EXACT whitespace that appears after the `→` marker.
- Whatever appears between `→` and the code text is what's actually in the file
- That whitespace must be used EXACTLY in Edit tool's old_string
- Don't count arrows, don't interpret - just copy what's after the `→`
**Example:**
14→ private byte tag;
For Edit, use: ` private byte tag;` (copy everything after →, including the two tabs)
**If Edit fails:** Stop and explain the problem. Do not attempt sed/awk/bash workarounds.
**IMPORTANT**: Trust the Read tool output. Copy what's after `→` into Edit immediately. DO NOT verify with sed/od/grep first - that's wasting time and the instructions already tell you to stop if Edit fails, not to pre-verify.
## Standards
Standards available at the @standards/ folder.
Generated
+33 -65
View File
@@ -2714,6 +2714,29 @@ dependencies = [
"serde",
]
[[package]]
name = "elasticsearch"
version = "9.1.0-alpha.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12bb303aa6e1d28c0c86b6fbfe484fd0fd3f512629aeed1ac4f6b85f81d9834a"
dependencies = [
"base64 0.22.1",
"bytes",
"dyn-clone",
"flate2",
"lazy_static",
"parking_lot",
"percent-encoding",
"reqwest 0.12.24",
"rustc_version",
"serde",
"serde_json",
"serde_with",
"tokio",
"url",
"void",
]
[[package]]
name = "elliptic-curve"
version = "0.13.8"
@@ -4895,9 +4918,11 @@ dependencies = [
"dotenv-build",
"dotenvy",
"either",
"elasticsearch",
"eyre",
"futures",
"futures-util",
"heck 0.5.0",
"hex",
"hmac",
"hyper-rustls 0.27.7",
@@ -4916,6 +4941,7 @@ dependencies = [
"paste",
"path-util",
"prometheus",
"quick-xml 0.38.3",
"rand 0.8.5",
"rand_chacha 0.3.1",
"redis",
@@ -4948,7 +4974,7 @@ dependencies = [
"urlencoding",
"utoipa",
"utoipa-actix-web",
"utoipa-swagger-ui",
"utoipa-scalar",
"uuid 1.18.1",
"validator",
"webp",
@@ -7925,40 +7951,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rust-embed"
version = "8.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb44e1917075637ee8c7bcb865cf8830e3a92b5b1189e44e3a0ab5a0d5be314b"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
"walkdir",
]
[[package]]
name = "rust-embed-impl"
version = "8.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "382499b49db77a7c19abd2a574f85ada7e9dbe125d5d1160fa5cad7c4cf71fc9"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn 2.0.106",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
version = "8.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21fcbee55c2458836bcdbfffb6ec9ba74bbc23ca7aa6816015a3dd2c4d8fc185"
dependencies = [
"sha2",
"walkdir",
]
[[package]]
name = "rust-ini"
version = "0.21.3"
@@ -10164,6 +10156,7 @@ dependencies = [
"either",
"encoding_rs",
"enumset",
"eyre",
"flate2",
"fs4",
"futures",
@@ -10216,6 +10209,7 @@ dependencies = [
name = "theseus_gui"
version = "1.0.0-local"
dependencies = [
"async_zip",
"chrono",
"daedalus",
"dashmap",
@@ -10233,6 +10227,7 @@ dependencies = [
"tauri-build",
"tauri-plugin-deep-link",
"tauri-plugin-dialog",
"tauri-plugin-fs",
"tauri-plugin-http",
"tauri-plugin-opener",
"tauri-plugin-os",
@@ -11172,30 +11167,17 @@ dependencies = [
]
[[package]]
name = "utoipa-swagger-ui"
version = "9.0.2"
name = "utoipa-scalar"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d047458f1b5b65237c2f6dc6db136945667f40a7668627b3490b9513a3d43a55"
checksum = "59559e1509172f6b26c1cdbc7247c4ddd1ac6560fe94b584f81ee489b141f719"
dependencies = [
"actix-web",
"base64 0.22.1",
"mime_guess",
"regex",
"rust-embed",
"serde",
"serde_json",
"url",
"utoipa",
"utoipa-swagger-ui-vendored",
"zip 3.0.0",
]
[[package]]
name = "utoipa-swagger-ui-vendored"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2eebbbfe4093922c2b6734d7c679ebfebd704a0d7e56dfcb0d05818ce28977d"
[[package]]
name = "uuid"
version = "0.8.2"
@@ -12580,20 +12562,6 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "zip"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12598812502ed0105f607f941c386f43d441e00148fce9dec3ca5ffb0bde9308"
dependencies = [
"arbitrary",
"crc32fast",
"flate2",
"indexmap 2.11.4",
"memchr",
"zopfli",
]
[[package]]
name = "zip"
version = "4.6.1"
+3 -1
View File
@@ -72,6 +72,7 @@ dotenv-build = "0.1.1"
dotenvy = "0.15.7"
dunce = "1.0.5"
either = "1.15.0"
elasticsearch = "9.1.0-alpha.1"
encoding_rs = "0.8.35"
enumset = "1.1.10"
eyre = "0.6.12"
@@ -178,6 +179,7 @@ tauri = "2.8.5"
tauri-build = "2.4.1"
tauri-plugin-deep-link = "2.4.3"
tauri-plugin-dialog = "2.4.0"
tauri-plugin-fs = "2.4.5"
tauri-plugin-http = "2.5.7"
tauri-plugin-opener = "2.5.0"
tauri-plugin-os = "2.3.1"
@@ -206,7 +208,7 @@ url = "2.5.7"
urlencoding = "2.1.3"
utoipa = { version = "5.4.0", features = ["actix_extras", "chrono", "decimal"] }
utoipa-actix-web = { version = "0.1.2" }
utoipa-swagger-ui = { version = "9.0.2", features = ["actix-web", "vendored"] }
utoipa-scalar = { version = "0.3.0", default-features = false }
uuid = "1.18.1"
validator = "0.20.0"
webp = { version = "0.3.1", default-features = false }
+7 -5
View File
@@ -22,24 +22,26 @@
"@tanstack/vue-query": "^5.90.7",
"@tauri-apps/api": "^2.5.0",
"@tauri-apps/plugin-dialog": "^2.2.1",
"@tauri-apps/plugin-http": "^2.5.0",
"@tauri-apps/plugin-fs": "^2.4.5",
"@tauri-apps/plugin-http": "~2.5.7",
"@tauri-apps/plugin-opener": "^2.2.6",
"@tauri-apps/plugin-os": "^2.2.1",
"@tauri-apps/plugin-updater": "^2.7.1",
"@tauri-apps/plugin-window-state": "^2.2.2",
"@types/three": "^0.172.0",
"intl-messageformat": "^10.7.7",
"vue-i18n": "^10.0.0",
"@vueuse/core": "^11.1.0",
"dayjs": "^1.11.10",
"floating-vue": "^5.2.2",
"fuse.js": "^6.6.2",
"intl-messageformat": "^10.7.7",
"ofetch": "^1.3.4",
"overlayscrollbars": "^2.15.1",
"pinia": "^3.0.0",
"posthog-js": "^1.158.2",
"three": "^0.172.0",
"vite-svg-loader": "^5.1.0",
"vue": "^3.5.13",
"vue-multiselect": "3.0.0",
"vue-i18n": "^10.0.0",
"vue-router": "^4.6.0",
"vue-virtual-scroller": "v2.0.0-beta.8"
},
@@ -58,7 +60,7 @@
"sass": "^1.74.1",
"tailwindcss": "^3.4.4",
"typescript": "^5.5.4",
"vite": "^6.0.0",
"vite": "^8.0.0",
"vue-component-type-helpers": "^3.1.8",
"vue-tsc": "^2.1.6"
},
+307 -155
View File
@@ -1,5 +1,12 @@
<script setup>
import { AuthFeature, PanelVersionFeature, TauriModrinthClient } from '@modrinth/api-client'
import {
AuthFeature,
NodeAuthFeature,
nodeAuthState,
PanelVersionFeature,
TauriModrinthClient,
VerboseLoggingFeature,
} from '@modrinth/api-client'
import {
ArrowBigUpDashIcon,
ChangeSkinIcon,
@@ -11,15 +18,12 @@ import {
LibraryIcon,
LogInIcon,
LogOutIcon,
MaximizeIcon,
MinimizeIcon,
NewspaperIcon,
NotepadTextIcon,
PlusIcon,
RefreshCwIcon,
RestoreIcon,
RightArrowIcon,
ServerIcon,
ServerStackIcon,
SettingsIcon,
UserIcon,
WorldIcon,
@@ -28,16 +32,19 @@ import {
import {
Admonition,
Avatar,
Button,
ButtonStyled,
commonMessages,
ContentInstallModal,
CreationFlowModal,
defineMessages,
I18nDebugPanel,
LoadingBar,
NewsArticleCard,
NotificationPanel,
OverflowMenu,
PopupNotificationPanel,
ProgressSpinner,
provideModalBehavior,
provideModrinthClient,
provideNotificationManager,
providePageContext,
@@ -46,10 +53,11 @@ import {
useVIntl,
} from '@modrinth/ui'
import { formatBytes, renderString } from '@modrinth/utils'
import { useQuery } from '@tanstack/vue-query'
import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { getVersion } from '@tauri-apps/api/app'
import { invoke } from '@tauri-apps/api/core'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { fetch as tauriFetch } from '@tauri-apps/plugin-http'
import { openUrl } from '@tauri-apps/plugin-opener'
import { type } from '@tauri-apps/plugin-os'
import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state'
@@ -58,34 +66,33 @@ import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue'
import { RouterView, useRoute, useRouter } from 'vue-router'
import ModrinthAppLogo from '@/assets/modrinth_app.svg?component'
import ModrinthLoadingIndicator from '@/components/LoadingIndicatorBar.vue'
import AccountsCard from '@/components/ui/AccountsCard.vue'
import Breadcrumbs from '@/components/ui/Breadcrumbs.vue'
import ErrorModal from '@/components/ui/ErrorModal.vue'
import FriendsList from '@/components/ui/friends/FriendsList.vue'
import AddServerToInstanceModal from '@/components/ui/install_flow/AddServerToInstanceModal.vue'
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
import InstallConfirmModal from '@/components/ui/install_flow/InstallConfirmModal.vue'
import ModInstallModal from '@/components/ui/install_flow/ModInstallModal.vue'
import InstanceCreationModal from '@/components/ui/InstanceCreationModal.vue'
import MinecraftAuthErrorModal from '@/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue'
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
import AuthGrantFlowWaitModal from '@/components/ui/modal/AuthGrantFlowWaitModal.vue'
import InstallToPlayModal from '@/components/ui/modal/InstallToPlayModal.vue'
import ModpackAlreadyInstalledModal from '@/components/ui/modal/ModpackAlreadyInstalledModal.vue'
import UpdateToPlayModal from '@/components/ui/modal/UpdateToPlayModal.vue'
import NavButton from '@/components/ui/NavButton.vue'
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 URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
import WindowControls from '@/components/ui/WindowControls.vue'
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
import { config } from '@/config'
import { hide_ads_window, init_ads_window, show_ads_window } from '@/helpers/ads.js'
import { debugAnalytics, initAnalytics, trackEvent } from '@/helpers/analytics'
import { check_reachable } from '@/helpers/auth.js'
import { get_user } from '@/helpers/cache.js'
import { get_user, get_version } from '@/helpers/cache.js'
import { command_listener, warning_listener } from '@/helpers/events.js'
import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.ts'
import { create_profile_and_install_from_file } from '@/helpers/pack'
import { list } from '@/helpers/profile.js'
import { get as getSettings, set as setSettings } from '@/helpers/settings.ts'
import { get_opening_command, initialize_state } from '@/helpers/state'
@@ -98,15 +105,18 @@ import {
isNetworkMetered,
} from '@/helpers/utils.js'
import i18n from '@/i18n.config'
import { createContentInstall, provideContentInstall } from '@/providers/content-install'
import {
provideAppUpdateDownloadProgress,
subscribeToDownloadProgress,
} from '@/providers/download-progress.ts'
import { createServerInstall, provideServerInstall } from '@/providers/server-install'
import { setupProviders } from '@/providers/setup'
import { setupAuthProvider } from '@/providers/setup/auth'
import { setupLoadingStateProvider } from '@/providers/setup/loading-state'
import { useError } from '@/store/error.js'
import { playServerProject, useInstall } from '@/store/install.js'
import { useLoading, useTheming } from '@/store/state'
import { useTheming } from '@/store/state'
import { create_profile_and_install_from_file } from './helpers/pack'
import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer'
import { get_available_capes, get_available_skins } from './helpers/skins'
import { AppNotificationManager } from './providers/app-notifications'
@@ -124,23 +134,56 @@ const { addPopupNotification } = popupNotificationManager
const tauriApiClient = new TauriModrinthClient({
userAgent: `modrinth/theseus/${getVersion()} (support@modrinth.com)`,
labrinthBaseUrl: config.labrinthBaseUrl,
archonBaseUrl: config.archonBaseUrl,
features: [
new NodeAuthFeature({
getAuth: () => nodeAuthState.getAuth?.() ?? null,
refreshAuth: async () => {
if (nodeAuthState.refreshAuth) {
await nodeAuthState.refreshAuth()
}
},
}),
new AuthFeature({
token: async () => (await getCreds()).session,
token: async () => (await getCreds())?.session,
}),
new PanelVersionFeature(),
new VerboseLoggingFeature(),
],
})
provideModrinthClient(tauriApiClient)
providePageContext({
hierarchicalSidebarAvailable: ref(true),
showAds: ref(false),
featureFlags: {
serverRamAsBytesAlwaysOn: computed(() =>
themeStore.getFeatureFlag('server_ram_as_bytes_always_on'),
),
},
openExternalUrl: (url) => openUrl(url),
})
provideModalBehavior({
noblur: computed(() => !themeStore.advancedRendering),
onShow: () => hide_ads_window(),
onHide: () => show_ads_window(),
})
const {
installationModal,
fetchExistingInstanceNames,
handleCreate,
handleBrowseModpacks,
searchModpacks,
getProjectVersions,
setModpackAlreadyInstalledModal,
handleModpackDuplicateCreateAnyway,
handleModpackDuplicateGoToInstance,
} = setupProviders(notificationManager)
const news = ref([])
const availableSurvey = ref(false)
const urlModal = ref(null)
const offline = ref(!navigator.onLine)
window.addEventListener('offline', () => {
offline.value = true
@@ -376,26 +419,153 @@ const handleClose = async () => {
}
const router = useRouter()
const route = useRoute()
const loading = setupLoadingStateProvider()
loading.setEnabled(false)
let initialLoadToken = loading.begin()
let routerToken = null
let suspenseToken = null
let suspensePending = false
const sidebarOverlayScrollbarsOptions = Object.freeze({
overflow: {
x: 'hidden',
y: 'scroll',
},
})
router.beforeEach(() => {
suspensePending = false
if (routerToken) loading.end(routerToken)
routerToken = loading.begin()
})
router.afterEach((to, from, failure) => {
trackEvent('PageView', {
path: to.path,
fromPath: from.path,
failed: failure,
})
setTimeout(() => {
if (!suspensePending && stateInitialized.value) {
if (initialLoadToken) {
loading.end(initialLoadToken)
initialLoadToken = null
}
if (routerToken) {
loading.end(routerToken)
routerToken = null
}
}
}, 100)
})
const route = useRoute()
const loading = useLoading()
loading.setEnabled(false)
function onSuspensePending() {
suspensePending = true
if (suspenseToken) loading.end(suspenseToken)
suspenseToken = loading.begin()
}
function onSuspenseResolve() {
if (suspenseToken) {
loading.end(suspenseToken)
suspenseToken = null
}
if (routerToken) {
loading.end(routerToken)
routerToken = null
}
}
const queryClient = useQueryClient()
watch(stateInitialized, (ready) => {
if (ready) {
if (initialLoadToken) {
loading.end(initialLoadToken)
initialLoadToken = null
}
if (routerToken) {
loading.end(routerToken)
routerToken = null
}
queryClient.prefetchQuery({
queryKey: ['servers'],
queryFn: async () => {
const response = await tauriApiClient.archon.servers_v0.list({ limit: 100 })
const hasMedalServers = response.servers.some((s) => s.is_medal)
if (hasMedalServers) {
const subscriptions = await tauriApiClient.labrinth.billing_internal.getSubscriptions()
for (const server of response.servers) {
if (server.is_medal) {
const sub = subscriptions.find((s) => s.metadata?.id === server.server_id)
if (sub) {
server.medal_expires = new Date(
new Date(sub.created).getTime() + 5 * 86400000,
).toISOString()
}
}
}
}
return response
},
staleTime: 30_000,
})
queryClient.prefetchQuery({
queryKey: ['billing', 'subscriptions'],
queryFn: () => tauriApiClient.labrinth.billing_internal.getSubscriptions(),
staleTime: 30_000,
})
queryClient.prefetchQuery({
queryKey: ['billing', 'payments'],
queryFn: () => tauriApiClient.labrinth.billing_internal.getPayments(),
staleTime: 30_000,
})
}
})
const error = useError()
const errorModal = ref()
const minecraftAuthErrorModal = ref()
const install = useInstall()
const contentInstall = createContentInstall({ router, handleError })
provideContentInstall(contentInstall)
const {
instances: contentInstallInstances,
compatibleLoaders: contentInstallLoaders,
gameVersions: contentInstallGameVersions,
loading: contentInstallLoading,
defaultTab: contentInstallDefaultTab,
preferredLoader: contentInstallPreferredLoader,
preferredGameVersion: contentInstallPreferredGameVersion,
releaseGameVersions: contentInstallReleaseGameVersions,
projectInfo: contentInstallProjectInfo,
handleInstallToInstance,
handleCreateAndInstall,
handleNavigate: handleContentInstallNavigate,
handleCancel: handleContentInstallCancel,
setContentInstallModal,
setModpackAlreadyInstalledModal: setContentInstallModpackAlreadyInstalledModal,
handleModpackDuplicateCreateAnyway: handleContentInstallModpackDuplicateCreateAnyway,
handleModpackDuplicateGoToInstance: handleContentInstallModpackDuplicateGoToInstance,
setIncompatibilityWarningModal: setContentIncompatibilityWarningModal,
} = contentInstall
const serverInstall = createServerInstall({ router, handleError, popupNotificationManager })
provideServerInstall(serverInstall)
const {
setInstallToPlayModal: setServerInstallToPlayModal,
setUpdateToPlayModal: setServerUpdateToPlayModal,
setAddServerToInstanceModal: setServerAddServerToInstanceModal,
playServerProject,
} = serverInstall
const modInstallModal = ref()
const modpackAlreadyInstalledModal = ref()
const contentInstallModpackAlreadyInstalledModal = ref()
const addServerToInstanceModal = ref()
const installConfirmModal = ref()
const incompatibilityWarningModal = ref()
const installToPlayModal = ref()
const updateToPlayModal = ref()
@@ -404,9 +574,31 @@ const credentials = ref()
const modrinthLoginFlowWaitModal = ref()
setupAuthProvider(credentials, async (_redirectPath) => {
await signIn()
})
async function validateSession(sessionToken) {
try {
const response = await tauriFetch(`${config.labrinthBaseUrl}/v2/user`, {
method: 'GET',
headers: { Authorization: sessionToken },
})
if (response.status === 401) return false
return true
} catch {
return true
}
}
async function fetchCredentials() {
const creds = await getCreds().catch(handleError)
if (creds && creds.user_id) {
if (creds.session && !(await validateSession(creds.session))) {
await logout().catch(handleError)
credentials.value = null
return
}
creds.user = await get_user(creds.user_id, 'bypass').catch(handleError)
}
credentials.value = creds ?? null
@@ -474,13 +666,13 @@ onMounted(() => {
error.setErrorModal(errorModal.value)
error.setMinecraftAuthErrorModal(minecraftAuthErrorModal.value)
install.setIncompatibilityWarningModal(incompatibilityWarningModal)
install.setInstallConfirmModal(installConfirmModal)
install.setModInstallModal(modInstallModal)
install.setAddServerToInstanceModal(addServerToInstanceModal)
install.setInstallToPlayModal(installToPlayModal)
install.setUpdateToPlayModal(updateToPlayModal)
install.setPopupNotificationManager(popupNotificationManager)
setContentIncompatibilityWarningModal(incompatibilityWarningModal.value)
setContentInstallModal(modInstallModal.value)
setContentInstallModpackAlreadyInstalledModal(contentInstallModpackAlreadyInstalledModal.value)
setModpackAlreadyInstalledModal(modpackAlreadyInstalledModal.value)
setServerAddServerToInstanceModal(addServerToInstanceModal.value)
setServerInstallToPlayModal(installToPlayModal.value)
setServerUpdateToPlayModal(updateToPlayModal.value)
})
const accounts = ref(null)
@@ -501,9 +693,19 @@ async function handleCommand(e) {
} else if (e.event === 'InstallServer') {
await router.push(`/project/${e.id}`)
await playServerProject(e.id).catch(handleError)
} else if (e.event === 'InstallVersion') {
const version = await get_version(e.id, 'must_revalidate').catch(handleError)
if (version) {
await contentInstall
.install(version.project_id, version.id, null, 'URLConfirmModal', undefined, undefined, {
showProjectInfo: true,
})
.catch(handleError)
}
} else {
// Other commands are URL-based (deep linking)
urlModal.value.show(e)
await contentInstall
.install(e.id, null, null, 'URLConfirmModal', undefined, undefined, { showProjectInfo: true })
.catch(handleError)
}
}
@@ -870,6 +1072,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</script>
<template>
<WindowControls />
<SplashScreen v-if="!stateFailed" ref="splashScreen" data-tauri-drag-region />
<div id="teleports"></div>
<div
@@ -898,9 +1101,16 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
<Suspense>
<AuthGrantFlowWaitModal ref="modrinthLoginFlowWaitModal" @flow-cancel="cancelLogin" />
</Suspense>
<Suspense>
<InstanceCreationModal ref="installationModal" />
</Suspense>
<CreationFlowModal
ref="installationModal"
type="instance"
show-snapshot-toggle
:fetch-existing-instance-names="fetchExistingInstanceNames"
:search-modpacks="searchModpacks"
:get-project-versions="getProjectVersions"
@create="handleCreate"
@browse-modpacks="handleBrowseModpacks"
/>
<div
class="app-grid-navbar bg-bg-raised flex flex-col p-[0.5rem] pt-0 gap-[0.5rem] w-[--left-bar-width]"
>
@@ -910,13 +1120,6 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
<NavButton v-if="themeStore.featureFlags.worlds_tab" v-tooltip.right="'Worlds'" to="/worlds">
<WorldIcon />
</NavButton>
<NavButton
v-if="themeStore.featureFlags.servers_in_app"
v-tooltip.right="'Servers'"
to="/hosting/manage"
>
<ServerIcon />
</NavButton>
<NavButton
v-tooltip.right="'Discover content'"
to="/browse/modpack"
@@ -931,6 +1134,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
<NavButton
v-tooltip.right="'Library'"
to="/library"
:is-primary="(r) => r.path === '/library' || r.path === '/library'"
:is-subpage="
() =>
route.path.startsWith('/instance') ||
@@ -940,13 +1144,21 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
>
<LibraryIcon />
</NavButton>
<NavButton
v-tooltip.right="'Modrinth Hosting'"
to="/hosting/manage"
:is-primary="(r) => r.path === '/hosting/manage' || r.path === '/hosting/manage/'"
:is-subpage="(r) => r.path.startsWith('/hosting/manage/') && r.path !== '/hosting/manage/'"
>
<ServerStackIcon />
</NavButton>
<div class="h-px w-6 mx-auto my-2 bg-surface-5"></div>
<suspense>
<QuickInstanceSwitcher />
</suspense>
<NavButton
v-tooltip.right="'Create new instance'"
:to="() => $refs.installationModal.show()"
:to="() => installationModal?.show()"
:disabled="offline"
>
<PlusIcon />
@@ -1021,9 +1233,9 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</NavButton>
</div>
<div data-tauri-drag-region class="app-grid-statusbar bg-bg-raised h-[--top-bar-height] flex">
<div data-tauri-drag-region class="flex p-3">
<ModrinthAppLogo class="h-full w-auto text-contrast pointer-events-none" />
<div data-tauri-drag-region class="flex items-center gap-1 ml-3">
<div data-tauri-drag-region class="flex min-w-0 flex-1 overflow-hidden p-3">
<ModrinthAppLogo class="h-full w-auto shrink-0 text-contrast pointer-events-none" />
<div data-tauri-drag-region class="flex shrink-0 items-center gap-1 ml-3">
<button
class="cursor-pointer p-0 m-0 text-contrast border-none outline-none bg-button-bg rounded-full flex items-center justify-center w-6 h-6 hover:brightness-75 transition-all"
@click="router.back()"
@@ -1039,7 +1251,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</div>
<Breadcrumbs class="pt-[2px]" />
</div>
<section data-tauri-drag-region class="flex ml-auto items-center">
<section data-tauri-drag-region class="flex shrink-0 ml-auto items-center">
<ButtonStyled
v-if="!forceSidebar && themeStore.toggleSidebar"
:type="sidebarToggled ? 'standard' : 'transparent'"
@@ -1058,22 +1270,6 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
<RunningAppBar />
</Suspense>
</div>
<section v-if="!nativeDecorations" class="window-controls" data-tauri-drag-region-exclude>
<Button class="titlebar-button" icon-only @click="() => getCurrentWindow().minimize()">
<MinimizeIcon />
</Button>
<Button
class="titlebar-button"
icon-only
@click="() => getCurrentWindow().toggleMaximize()"
>
<RestoreIcon v-if="isMaximized" />
<MaximizeIcon v-else />
</Button>
<Button class="titlebar-button close" icon-only @click="handleClose">
<XIcon />
</Button>
</section>
</section>
</div>
</div>
@@ -1109,14 +1305,14 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</div>
</transition>
<div
class="loading-indicator-container h-8 fixed z-50"
class="loading-indicator-container h-8 fixed z-50 pointer-events-none"
:style="{
top: 'calc(var(--top-bar-height))',
left: 'calc(var(--left-bar-width))',
width: 'calc(100% - var(--left-bar-width) - var(--right-bar-width))',
}"
>
<ModrinthLoadingIndicator />
<LoadingBar position="absolute" />
</div>
<div
v-if="themeStore.featureFlags.page_path"
@@ -1152,40 +1348,36 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</Admonition>
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Suspense @pending="loading.startLoading()" @resolve="loading.stopLoading()">
<Suspense @pending="onSuspensePending" @resolve="onSuspenseResolve">
<component :is="Component"></component>
</Suspense>
</template>
</RouterView>
</div>
<div
class="app-sidebar mt-px shrink-0 flex flex-col border-0 border-l-[1px] border-[--brand-gradient-border] border-solid overflow-auto"
class="app-sidebar mt-px shrink-0 flex flex-col border-0 border-l-[1px] border-[--brand-gradient-border] border-solid"
:class="{ 'has-plus': hasPlus }"
>
<div
class="app-sidebar-scrollable flex-grow shrink overflow-y-auto relative"
v-overlay-scrollbars="sidebarOverlayScrollbarsOptions"
class="app-sidebar-scrollable flex-grow shrink relative"
:class="{ 'pb-12': !hasPlus }"
data-overlayscrollbars-initialize
>
<div id="sidebar-teleport-target" class="sidebar-teleport-content"></div>
<div class="sidebar-default-content" :class="{ 'sidebar-enabled': sidebarVisible }">
<div
class="p-4 pr-1 border-0 border-b-[1px] border-[--brand-gradient-border] border-solid"
>
<div class="p-4 border-0 border-b-[1px] border-[--brand-gradient-border] border-solid">
<h3 class="text-base text-primary font-medium m-0">Playing as</h3>
<suspense>
<AccountsCard ref="accounts" mode="small" />
</suspense>
</div>
<div class="py-4 border-0 border-b-[1px] border-[--brand-gradient-border] border-solid">
<div class="p-4 border-0 border-b-[1px] border-[--brand-gradient-border] border-solid">
<suspense>
<FriendsList
:credentials="credentials"
:sign-in="() => signIn()"
:refresh-credentials="fetchCredentials"
/>
<FriendsList :credentials="credentials" :sign-in="() => signIn()" />
</suspense>
</div>
<div v-if="news && news.length > 0" class="p-4 pr-1 flex flex-col items-center">
<div v-if="news && news.length > 0" class="p-4 flex flex-col items-center">
<h3 class="text-base mb-4 text-primary font-medium m-0 text-left w-full">News</h3>
<div class="space-y-4 flex flex-col items-center w-full">
<NewsArticleCard
@@ -1214,87 +1406,44 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</template>
</div>
</div>
<URLConfirmModal ref="urlModal" />
<I18nDebugPanel />
<NotificationPanel has-sidebar />
<PopupNotificationPanel has-sidebar />
<NotificationPanel :has-sidebar="sidebarVisible" />
<PopupNotificationPanel :has-sidebar="sidebarVisible" />
<ErrorModal ref="errorModal" />
<MinecraftAuthErrorModal ref="minecraftAuthErrorModal" />
<ModInstallModal ref="modInstallModal" />
<ContentInstallModal
ref="modInstallModal"
:instances="contentInstallInstances"
:compatible-loaders="contentInstallLoaders"
:game-versions="contentInstallGameVersions"
:loading="contentInstallLoading"
:default-tab="contentInstallDefaultTab"
:preferred-loader="contentInstallPreferredLoader"
:preferred-game-version="contentInstallPreferredGameVersion"
:release-game-versions="contentInstallReleaseGameVersions"
:project-info="contentInstallProjectInfo"
@install="handleInstallToInstance"
@create-and-install="handleCreateAndInstall"
@navigate="handleContentInstallNavigate"
@cancel="handleContentInstallCancel"
/>
<ModpackAlreadyInstalledModal
ref="modpackAlreadyInstalledModal"
@create-anyway="handleModpackDuplicateCreateAnyway"
@go-to-instance="handleModpackDuplicateGoToInstance"
/>
<AddServerToInstanceModal ref="addServerToInstanceModal" />
<IncompatibilityWarningModal ref="incompatibilityWarningModal" />
<InstallConfirmModal ref="installConfirmModal" />
<ModpackAlreadyInstalledModal
ref="contentInstallModpackAlreadyInstalledModal"
@create-anyway="handleContentInstallModpackDuplicateCreateAnyway"
@go-to-instance="handleContentInstallModpackDuplicateGoToInstance"
/>
<InstallToPlayModal ref="installToPlayModal" />
<UpdateToPlayModal ref="updateToPlayModal" />
</template>
<style lang="scss" scoped>
.window-controls {
z-index: 20;
display: none;
flex-direction: row;
align-items: center;
.titlebar-button {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all ease-in-out 0.1s;
background-color: transparent;
color: var(--color-base);
height: 100%;
width: 3rem;
position: relative;
box-shadow: none;
&:last-child {
padding-right: 0.75rem;
width: 3.75rem;
}
svg {
width: 1.25rem;
height: 1.25rem;
}
&::before {
content: '';
border-radius: 999999px;
width: 3rem;
height: 3rem;
aspect-ratio: 1 / 1;
margin-block: auto;
position: absolute;
background-color: transparent;
scale: 0.9;
transition: all ease-in-out 0.2s;
z-index: -1;
}
&.close {
&:hover,
&:active {
color: var(--color-accent-contrast);
&::before {
background-color: var(--color-red);
}
}
}
&:hover,
&:active {
color: var(--color-contrast);
&::before {
background-color: var(--color-button-bg);
scale: 1;
}
}
}
}
.app-grid-layout,
.app-contents {
--top-bar-height: 3rem;
@@ -1319,6 +1468,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
.app-grid-statusbar {
grid-area: status;
padding-right: var(--window-controls-width, 0px);
}
[data-tauri-drag-region-exclude] {
@@ -1510,6 +1660,13 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
}
</style>
<style>
.os-theme-dark,
.os-theme-light {
--os-handle-bg: var(--color-scrollbar) !important;
--os-handle-bg-hover: var(--color-scrollbar) !important;
--os-handle-bg-active: var(--color-scrollbar) !important;
}
.mac {
.app-grid-statusbar {
padding-left: 5rem;
@@ -1521,10 +1678,6 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
height: 2.5rem !important;
}
.window-controls {
display: flex !important;
}
.info-card {
right: 22rem;
}
@@ -1534,4 +1687,3 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
}
}
</style>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
@@ -45,6 +45,14 @@
color-scheme: dark;
--view-width: calc(100% - 5rem);
--expanded-view-width: calc(100% - 13rem);
--medal-promotion-bg: #000;
--medal-promotion-bg-orange: rgba(208, 246, 255, 0.25);
--medal-promotion-text-orange: #42abff;
--medal-promotion-bg-gradient: linear-gradient(
90deg,
rgba(66, 170, 255, 0.15),
rgba(0, 0, 0, 0) 100%
);
}
body {
@@ -77,12 +85,10 @@ body {
}
a {
color: var(--color-link);
color: inherit;
text-decoration: none;
&:hover {
text-decoration: none;
}
-webkit-font-smoothing: antialiased;
will-change: filter;
}
.badge {
@@ -174,4 +180,63 @@ img {
}
}
button,
input[type='button'] {
cursor: pointer;
border: none;
outline: 2px solid transparent;
}
@import '@modrinth/assets/omorphia.scss';
input {
border-radius: var(--size-rounded-sm);
box-sizing: border-box;
border: 2px solid transparent;
// safari iOS rounds inputs by default
// set the appearance to none to prevent this
appearance: none !important;
}
pre {
font-weight: var(--font-weight-regular);
}
input,
textarea {
background: var(--color-button-bg);
color: var(--color-text);
padding: 0.5rem 1rem;
font-weight: var(--font-weight-medium);
border: none;
outline: 2px solid transparent;
box-shadow:
var(--shadow-inset-sm),
0 0 0 0 transparent;
transition: box-shadow 0.1s ease-in-out;
min-height: 36px;
&:focus,
&:focus-visible {
box-shadow:
inset 0 0 0 transparent,
0 0 0 0.25rem var(--color-brand-shadow);
color: var(--color-button-text-active);
}
&:disabled,
&[disabled='true'] {
opacity: 0.6;
pointer-events: none;
cursor: not-allowed;
}
&:focus::placeholder {
opacity: 0.8;
}
&::placeholder {
color: var(--color-button-text);
opacity: 0.6;
}
}
@@ -10,6 +10,7 @@ import {
TrashIcon,
} from '@modrinth/assets'
import {
Accordion,
DropdownSelect,
formatLoader,
injectNotificationManager,
@@ -22,7 +23,7 @@ import { computed, ref } from 'vue'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import Instance from '@/components/ui/Instance.vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import ConfirmDeleteInstanceModal from '@/components/ui/modal/ConfirmDeleteInstanceModal.vue'
import { duplicate, remove } from '@/helpers/profile.js'
const { handleError } = injectNotificationManager()
@@ -133,12 +134,33 @@ const state = useStorage(
{
group: 'Group',
sortBy: 'Name',
collapsedGroups: [],
},
localStorage,
{ mergeDefaults: true },
)
const search = ref('')
const collapsedSectionKeys = computed(() => new Set(state.value.collapsedGroups ?? []))
const getSectionKey = (sectionName) => `${state.value.group}:${sectionName}`
const isSectionCollapsed = (sectionName) => {
return collapsedSectionKeys.value.has(getSectionKey(sectionName))
}
const setSectionCollapsed = (sectionName, collapsed) => {
const sectionKey = getSectionKey(sectionName)
const collapsedSections = new Set(state.value.collapsedGroups ?? [])
if (collapsed) {
collapsedSections.add(sectionKey)
} else {
collapsedSections.delete(sectionKey)
}
state.value.collapsedGroups = [...collapsedSections]
}
const filteredResults = computed(() => {
const { group = 'Group', sortBy = 'Name' } = state.value
@@ -280,18 +302,21 @@ const filteredResults = computed(() => {
<span class="font-semibold text-secondary">{{ selected }}</span>
</DropdownSelect>
</div>
<div
<Accordion
v-for="instanceSection in Array.from(filteredResults, ([key, value]) => ({
key,
value,
}))"
:key="instanceSection.key"
:divider="instanceSection.key !== 'None'"
:open-by-default="!isSectionCollapsed(instanceSection.key)"
class="row"
@on-open="setSectionCollapsed(instanceSection.key, false)"
@on-close="setSectionCollapsed(instanceSection.key, true)"
>
<div v-if="instanceSection.key !== 'None'" class="divider">
<p>{{ instanceSection.key }}</p>
<hr aria-hidden="true" />
</div>
<template v-if="instanceSection.key !== 'None'" #title>
<span class="text-base">{{ instanceSection.key }}</span>
</template>
<section class="instances">
<Instance
v-for="instance in instanceSection.value"
@@ -301,15 +326,8 @@ const filteredResults = computed(() => {
@contextmenu.prevent.stop="(event) => handleRightClick(event, instance.path)"
/>
</section>
</div>
<ConfirmModalWrapper
ref="confirmModal"
title="Are you sure you want to delete this instance?"
description="If you proceed, all data for your instance will be removed. You will not be able to recover it."
:has-to-type="false"
proceed-label="Delete"
@proceed="deleteProfile"
/>
</Accordion>
<ConfirmDeleteInstanceModal ref="confirmModal" @delete="deleteProfile" />
<ContextMenu ref="instanceOptions" @option-clicked="handleOptionsClick">
<template #play> <PlayIcon /> Play </template>
<template #stop> <StopCircleIcon /> Stop </template>
@@ -323,73 +341,7 @@ const filteredResults = computed(() => {
</template>
<style lang="scss" scoped>
.row {
display: flex;
flex-direction: column;
align-items: flex-start;
width: 100%;
.divider {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
gap: 1rem;
margin-bottom: 1rem;
p {
margin: 0;
font-size: 1rem;
white-space: nowrap;
color: var(--color-contrast);
}
hr {
background-color: var(--color-gray);
height: 1px;
width: 100%;
border: none;
}
}
}
.header {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
gap: 1rem;
align-items: inherit;
margin: 1rem 1rem 0 !important;
padding: 1rem;
width: calc(100% - 2rem);
.iconified-input {
flex-grow: 1;
input {
min-width: 100%;
}
}
.sort-dropdown {
width: 10rem;
}
.filter-dropdown {
width: 15rem;
}
.group-dropdown {
width: 10rem;
}
.labeled_button {
display: flex;
flex-direction: row;
align-items: center;
gap: 0.5rem;
white-space: nowrap;
}
}
.instances {
@@ -1,142 +0,0 @@
<script setup>
import { computed, onBeforeUnmount, ref, watch } from 'vue'
import { useLoading } from '@/store/state.js'
const props = defineProps({
throttle: {
type: Number,
default: 0,
},
duration: {
type: Number,
default: 1000,
},
height: {
type: Number,
default: 2,
},
color: {
type: String,
default: 'var(--loading-bar-gradient)',
},
})
const indicator = useLoadingIndicator({
duration: props.duration,
throttle: props.throttle,
})
onBeforeUnmount(() => indicator.clear)
const loading = useLoading()
watch(loading, (newValue) => {
if (newValue.barEnabled) {
if (newValue.loading) {
indicator.start()
} else {
indicator.finish()
}
}
})
function useLoadingIndicator(opts) {
const progress = ref(0)
const isLoading = ref(false)
const step = computed(() => 10000 / opts.duration)
let _timer = null
let _throttle = null
function start() {
clear()
progress.value = 0
if (opts.throttle) {
_throttle = setTimeout(() => {
isLoading.value = true
_startTimer()
}, opts.throttle)
} else {
isLoading.value = true
_startTimer()
}
}
function finish() {
progress.value = 100
_hide()
}
function clear() {
clearInterval(_timer)
clearTimeout(_throttle)
_timer = null
_throttle = null
}
function _increase(num) {
progress.value = Math.min(100, progress.value + num)
}
function _hide() {
clear()
setTimeout(() => {
isLoading.value = false
setTimeout(() => {
progress.value = 0
}, 400)
}, 500)
}
function _startTimer() {
_timer = setInterval(() => {
_increase(step.value)
}, 100)
}
return { progress, isLoading, start, finish, clear }
}
</script>
<template>
<div
class="loading-indicator-bar"
:style="{
'--_width': `${indicator.progress.value}%`,
'--_height': `${indicator.isLoading.value ? props.height : 0}px`,
'--_opacity': `${indicator.isLoading.value ? 1 : 0}`,
top: `0`,
right: `0`,
left: `${props.offsetWidth}`,
pointerEvents: 'none',
width: `var(--_width)`,
height: `var(--_height)`,
borderRadius: `var(--_height)`,
// opacity: `var(--_opacity)`,
background: `${props.color}`,
backgroundSize: `${(100 / indicator.progress.value) * 100}% auto`,
transition: 'width 0.1s ease-in-out, height 0.1s ease-out',
zIndex: 6,
}"
>
<slot />
</div>
</template>
<style lang="scss" scoped>
.loading-indicator-bar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
width: var(--_width);
bottom: 0;
background-image: radial-gradient(80% 100% at 20% 0%, var(--color-brand) 0%, transparent 80%);
opacity: calc(var(--_opacity) * 0.1);
z-index: 5;
transition:
width 0.1s ease-in-out,
opacity 0.1s ease-out;
}
</style>
@@ -19,15 +19,16 @@ import { useRouter } from 'vue-router'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import Instance from '@/components/ui/Instance.vue'
import LegacyProjectCard from '@/components/ui/LegacyProjectCard.vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import ConfirmDeleteInstanceModal from '@/components/ui/modal/ConfirmDeleteInstanceModal.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_by_profile_path } from '@/helpers/process.js'
import { duplicate, kill, remove, run } from '@/helpers/profile.js'
import { showProfileInFolder } from '@/helpers/utils.js'
import { injectContentInstall } from '@/providers/content-install'
import { handleSevereError } from '@/store/error.js'
import { install as installVersion } from '@/store/install.js'
const { handleError } = injectNotificationManager()
const { install: installVersion } = injectContentInstall()
const router = useRouter()
@@ -238,14 +239,7 @@ onUnmounted(() => {
</script>
<template>
<ConfirmModalWrapper
ref="deleteConfirmModal"
title="Are you sure you want to delete this instance?"
description="If you proceed, all data for your instance will be removed. You will not be able to recover it."
:has-to-type="false"
proceed-label="Delete"
@proceed="deleteProfile"
/>
<ConfirmDeleteInstanceModal ref="deleteConfirmModal" @delete="deleteProfile" />
<div ref="rowContainer" class="flex flex-col gap-4">
<div v-for="row in actualInstances" ref="rows" :key="row.label" class="row">
<HeadingLink class="mt-1" :to="row.route">
@@ -1,64 +1,158 @@
<template>
<div data-tauri-drag-region class="flex items-center gap-1 pl-3">
<Button v-if="false" class="breadcrumbs__back transparent" icon-only @click="$router.back()">
<ChevronLeftIcon />
</Button>
<Button
v-if="false"
class="breadcrumbs__forward transparent"
icon-only
@click="$router.forward()"
<div
ref="outerRef"
data-tauri-drag-region
class="min-w-0 overflow-hidden pl-3"
:class="{ 'breadcrumb-fade-mask': isOverflowing }"
:style="isOverflowing ? { '--scroll-distance': `-${overflowAmount}px` } : undefined"
@mouseenter="onMouseEnter"
@mouseleave="onMouseLeave"
>
<div
ref="innerRef"
data-tauri-drag-region
class="flex w-fit items-center gap-1"
:class="{ 'breadcrumbs-scroll': isAnimating }"
@animationiteration="onAnimationIteration"
>
<ChevronRightIcon />
</Button>
{{ breadcrumbData.resetToNames(breadcrumbs) }}
<template v-for="breadcrumb in breadcrumbs" :key="breadcrumb.name">
<router-link
v-if="breadcrumb.link"
:to="{
path: breadcrumb.link.replace('{id}', encodeURIComponent($route.params.id)),
query: breadcrumb.query,
}"
class="text-primary"
>{{
breadcrumb.name.charAt(0) === '?'
? breadcrumbData.getName(breadcrumb.name.slice(1))
: breadcrumb.name
}}
</router-link>
<span
v-else
data-tauri-drag-region
class="text-contrast font-semibold cursor-default select-none"
>{{
breadcrumb.name.charAt(0) === '?'
? breadcrumbData.getName(breadcrumb.name.slice(1))
: breadcrumb.name
}}</span
>
<ChevronRightIcon v-if="breadcrumb.link" data-tauri-drag-region class="w-5 h-5" />
</template>
{{ breadcrumbData.resetToNames(breadcrumbs) }}
<template v-for="breadcrumb in breadcrumbs" :key="breadcrumb.name">
<router-link
v-if="breadcrumb.link"
:to="{
path: breadcrumb.link.replace('{id}', encodeURIComponent($route.params.id as string)),
query: breadcrumb.query,
}"
class="shrink-0 whitespace-nowrap text-primary"
>
{{ resolveLabel(breadcrumb.name) }}
</router-link>
<span
v-else
data-tauri-drag-region
class="shrink-0 whitespace-nowrap text-contrast font-semibold cursor-default select-none"
>
{{ resolveLabel(breadcrumb.name) }}
</span>
<ChevronRightIcon v-if="breadcrumb.link" data-tauri-drag-region class="w-5 h-5 shrink-0" />
</template>
</div>
</div>
</template>
<script setup>
import { ChevronLeftIcon, ChevronRightIcon } from '@modrinth/assets'
import { Button } from '@modrinth/ui'
import { computed } from 'vue'
<script setup lang="ts">
import { ChevronRightIcon } from '@modrinth/assets'
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useBreadcrumbs } from '@/store/breadcrumbs'
const route = useRoute()
interface Breadcrumb {
name: string
link?: string
query?: Record<string, string>
}
const route = useRoute()
const breadcrumbData = useBreadcrumbs()
const breadcrumbs = computed(() => {
const breadcrumbs = computed<Breadcrumb[]>(() => {
const additionalContext =
route.meta.useContext === true
? breadcrumbData.context
: route.meta.useRootContext === true
? breadcrumbData.rootContext
: null
return additionalContext ? [additionalContext, ...route.meta.breadcrumb] : route.meta.breadcrumb
const crumbs = (route.meta.breadcrumb ?? []) as Breadcrumb[]
return additionalContext ? [additionalContext as Breadcrumb, ...crumbs] : crumbs
})
function resolveLabel(name: string): string {
return name.charAt(0) === '?' ? breadcrumbData.getName(name.slice(1)) : name
}
// Overflow detection
const outerRef = ref<HTMLDivElement | null>(null)
const innerRef = ref<HTMLDivElement | null>(null)
const isOverflowing = ref(false)
const isAnimating = ref(false)
const overflowAmount = ref(0)
let hovered = false
let stopping = false
function checkOverflow() {
if (!outerRef.value || !innerRef.value) return
const overflow = innerRef.value.scrollWidth - outerRef.value.clientWidth
isOverflowing.value = overflow > 0
overflowAmount.value = overflow + 12
}
function onMouseEnter() {
hovered = true
stopping = false
if (isOverflowing.value) {
isAnimating.value = true
}
}
function onMouseLeave() {
hovered = false
if (isAnimating.value) {
stopping = true
}
}
function onAnimationIteration() {
if (stopping && !hovered) {
isAnimating.value = false
stopping = false
}
}
let resizeObserver: ResizeObserver | null = null
onMounted(() => {
checkOverflow()
resizeObserver = new ResizeObserver(checkOverflow)
if (outerRef.value) resizeObserver.observe(outerRef.value)
if (innerRef.value) resizeObserver.observe(innerRef.value)
})
onBeforeUnmount(() => {
resizeObserver?.disconnect()
})
watch(breadcrumbs, () => {
requestAnimationFrame(checkOverflow)
})
</script>
<style scoped>
.breadcrumb-fade-mask {
mask-image: linear-gradient(
to right,
transparent,
black 12px,
black calc(100% - 12px),
transparent
);
}
.breadcrumbs-scroll {
animation: breadcrumb-scroll 10s ease-in-out infinite;
}
@keyframes breadcrumb-scroll {
0% {
transform: translateX(0);
}
35%,
65% {
transform: translateX(var(--scroll-distance));
}
100% {
transform: translateX(0);
}
}
</style>
@@ -6,6 +6,7 @@ import {
HammerIcon,
LogInIcon,
UpdatedIcon,
WrenchIcon,
XIcon,
} from '@modrinth/assets'
import { ButtonStyled, Collapsible, injectNotificationManager } from '@modrinth/ui'
@@ -155,7 +156,7 @@ async function copyToClipboard(text) {
<template>
<ModalWrapper ref="errorModal" :header="title" :closable="closable">
<div class="modal-body">
<div class="modal-body max-w-[550px]">
<div class="markdown-body">
<template v-if="errorType === 'minecraft_auth'">
<template v-if="metadata.network">
@@ -280,7 +281,7 @@ async function copyToClipboard(text) {
{{ debugInfo }}
</template>
<template v-if="hasDebugInfo">
<hr />
<div class="w-full h-[1px] bg-surface-5 mb-3"></div>
<p>
If nothing is working and you need help, visit
<a :href="supportLink">our support page</a>
@@ -296,28 +297,47 @@ async function copyToClipboard(text) {
<ButtonStyled v-if="closable">
<button @click="errorModal.hide()"><XIcon /> Close</button>
</ButtonStyled>
<ButtonStyled v-if="hasDebugInfo">
<button :disabled="copied" @click="copyToClipboard(debugInfo)">
<template v-if="copied"> <CheckIcon class="text-green" /> Copied! </template>
<template v-else> <CopyIcon /> Copy debug info </template>
</button>
</ButtonStyled>
</div>
<template v-if="hasDebugInfo">
<div class="bg-button-bg rounded-xl mt-2 overflow-clip">
<button
class="flex items-center justify-between w-full bg-transparent border-0 px-4 py-3 cursor-pointer"
@click="errorCollapsed = !errorCollapsed"
>
<span class="text-contrast font-extrabold m-0">Debug information:</span>
<DropdownIcon
class="h-5 w-5 text-secondary transition-transform"
:class="{ 'rotate-180': !errorCollapsed }"
/>
</button>
<Collapsible :collapsed="errorCollapsed">
<pre class="m-0 px-4 py-3 bg-bg rounded-none">{{ debugInfo }}</pre>
</Collapsible>
<div class="flex flex-col gap-2">
<div class="w-full h-[1px] bg-surface-5"></div>
<div class="overflow-clip">
<button
class="flex items-center justify-between w-full bg-transparent border-0 py-4 cursor-pointer"
@click="errorCollapsed = !errorCollapsed"
>
<span class="flex items-center gap-2 text-contrast font-extrabold m-0">
<WrenchIcon class="h-4 w-4" />
Debug information
</span>
<DropdownIcon
class="h-5 w-5 text-secondary transition-transform"
:class="{ 'rotate-180': !errorCollapsed }"
/>
</button>
<Collapsible :collapsed="errorCollapsed">
<div
class="p-3 bg-surface-2 rounded-2xl text-xs grid grid-cols-[1fr_auto] max-w-full items-start"
>
<div
class="m-0 p-0 rounded-none bg-transparent text-sm font-mono break-words overflow-auto"
>
{{ debugInfo }}
</div>
<ButtonStyled circular>
<button
v-tooltip="'Copy debug info'"
:disabled="copied"
@click="copyToClipboard(debugInfo)"
>
<template v-if="copied"> <CheckIcon class="text-green" /> </template>
<template v-else> <CopyIcon /> </template>
</button>
</ButtonStyled>
</div>
</Collapsible>
</div>
</div>
</template>
</div>
@@ -1,6 +1,14 @@
<script setup>
import { PlusIcon, XIcon } from '@modrinth/assets'
import { Button, Checkbox, injectNotificationManager, StyledInput } from '@modrinth/ui'
import {
Button,
Checkbox,
commonMessages,
defineMessages,
injectNotificationManager,
StyledInput,
useVIntl,
} from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { ref } from 'vue'
@@ -9,6 +17,33 @@ import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { export_profile_mrpack, get_pack_export_candidates } from '@/helpers/profile.js'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const messages = defineMessages({
header: { id: 'app.export-modal.header', defaultMessage: 'Export modpack' },
modpackNameLabel: { id: 'app.export-modal.modpack-name-label', defaultMessage: 'Modpack Name' },
modpackNamePlaceholder: {
id: 'app.export-modal.modpack-name-placeholder',
defaultMessage: 'Modpack name',
},
versionNumberLabel: {
id: 'app.export-modal.version-number-label',
defaultMessage: 'Version number',
},
versionNumberPlaceholder: {
id: 'app.export-modal.version-number-placeholder',
defaultMessage: '1.0.0',
},
descriptionPlaceholder: {
id: 'app.export-modal.description-placeholder',
defaultMessage: 'Enter modpack description...',
},
selectFilesLabel: {
id: 'app.export-modal.select-files-label',
defaultMessage: 'Select files and folders to include in pack',
},
exportButton: { id: 'app.export-modal.export-button', defaultMessage: 'Export' },
})
const props = defineProps({
instance: {
@@ -106,36 +141,36 @@ const exportPack = async () => {
</script>
<template>
<ModalWrapper ref="exportModal" header="Export modpack">
<ModalWrapper ref="exportModal" :header="formatMessage(messages.header)">
<div class="modal-body">
<div class="labeled_input">
<p>Modpack Name</p>
<p>{{ formatMessage(messages.modpackNameLabel) }}</p>
<StyledInput
v-model="nameInput"
:icon="PackageIcon"
type="text"
placeholder="Modpack name"
:placeholder="formatMessage(messages.modpackNamePlaceholder)"
clearable
/>
</div>
<div class="labeled_input">
<p>Version number</p>
<p>{{ formatMessage(messages.versionNumberLabel) }}</p>
<StyledInput
v-model="versionInput"
:icon="VersionIcon"
type="text"
placeholder="1.0.0"
:placeholder="formatMessage(messages.versionNumberPlaceholder)"
clearable
/>
</div>
<div class="adjacent-input">
<div class="labeled_input">
<p>Description</p>
<p>{{ formatMessage(commonMessages.descriptionLabel) }}</p>
<StyledInput
v-model="exportDescription"
multiline
placeholder="Enter modpack description..."
:placeholder="formatMessage(messages.descriptionPlaceholder)"
/>
</div>
</div>
@@ -143,7 +178,7 @@ const exportPack = async () => {
<div class="table">
<div class="table-head">
<div class="table-cell row-wise">
Select files and folders to include in pack
{{ formatMessage(messages.selectFilesLabel) }}
<Button
class="sleek-primary collapsed-button"
icon-only
@@ -202,11 +237,11 @@ const exportPack = async () => {
<div class="button-row push-right">
<Button @click="exportModal.hide">
<XIcon />
Cancel
{{ formatMessage(commonMessages.cancelButton) }}
</Button>
<Button color="primary" @click="exportPack">
<PackageIcon />
Export
{{ formatMessage(messages.exportButton) }}
</Button>
</div>
</div>
@@ -1,662 +0,0 @@
<template>
<ModalWrapper ref="modal" header="Creating an instance">
<div class="modal-header">
<Chips v-model="creationType" :items="['custom', 'from file', 'import from launcher']" />
</div>
<hr class="card-divider" />
<div v-if="creationType === 'custom'" class="modal-body">
<div class="image-upload">
<Avatar :src="display_icon" size="md" :rounded="true" />
<div class="image-input">
<Button @click="upload_icon()">
<UploadIcon />
Select icon
</Button>
<Button :disabled="!display_icon" @click="reset_icon">
<XIcon />
Remove icon
</Button>
</div>
</div>
<div class="input-row">
<p class="input-label">Name</p>
<StyledInput
v-model="profile_name"
autocomplete="off"
type="text"
placeholder="Enter a name for your instance..."
:maxlength="100"
wrapper-class="w-full"
/>
</div>
<div class="input-row">
<p class="input-label">Loader</p>
<Chips v-model="loader" :items="loaders" />
</div>
<div class="input-row">
<p class="input-label">Game version</p>
<div class="flex gap-4 items-center">
<multiselect
v-model="game_version"
class="selector"
:options="game_versions"
:multiple="false"
:searchable="true"
placeholder="Select game version"
open-direction="top"
:show-labels="false"
/>
<Checkbox v-model="showSnapshots" class="shrink-0" label="Show all versions" />
</div>
</div>
<div v-if="loader !== 'vanilla'" class="input-row">
<p class="input-label">Loader version</p>
<Chips v-model="loader_version" :items="['stable', 'latest', 'other']" />
</div>
<div v-if="loader_version === 'other' && loader !== 'vanilla'">
<div v-if="game_version" class="input-row">
<p class="input-label">Select version</p>
<multiselect
v-model="specified_loader_version"
class="selector"
:options="selectable_versions"
:searchable="true"
placeholder="Select loader version"
open-direction="top"
:show-labels="false"
/>
</div>
<div v-else class="input-row">
<p class="warning">Select a game version before you select a loader version</p>
</div>
</div>
<div class="input-group push-right">
<Button @click="hide()">
<XIcon />
Cancel
</Button>
<Button color="primary" :disabled="!check_valid || creating" @click="create_instance()">
<PlusIcon v-if="!creating" />
{{ creating ? 'Creating...' : 'Create' }}
</Button>
</div>
</div>
<div v-else-if="creationType === 'from file'" class="modal-body">
<Button @click="openFile"> <FolderOpenIcon /> Import from file </Button>
<div class="info"><InfoIcon /> Or drag and drop your .mrpack file</div>
</div>
<div v-else class="modal-body">
<Chips
v-model="selectedProfileType"
:items="profileOptions"
:format-label="(profile) => profile?.name"
/>
<div class="path-selection">
<h3>{{ selectedProfileType.name }} path</h3>
<div class="path-input">
<StyledInput
v-model="selectedProfileType.path"
:icon="FolderOpenIcon"
type="text"
placeholder="Path to launcher"
clearable
@change="setPath"
/>
<Button icon-only @click="selectLauncherPath">
<FolderSearchIcon />
</Button>
<Button icon-only @click="reload">
<UpdatedIcon />
</Button>
</div>
</div>
<div class="table">
<div class="table-head table-row">
<div class="toggle-all table-cell">
<Checkbox
class="select-checkbox"
:model-value="
profiles.get(selectedProfileType.name)?.every((child) => child.selected)
"
@update:model-value="
(newValue) =>
profiles
.get(selectedProfileType.name)
?.forEach((child) => (child.selected = newValue))
"
/>
</div>
<div class="name-cell table-cell">Profile name</div>
</div>
<div
v-if="
profiles.get(selectedProfileType.name) &&
profiles.get(selectedProfileType.name).length > 0
"
class="table-content"
>
<div
v-for="(profile, index) in profiles.get(selectedProfileType.name)"
:key="index"
class="table-row"
>
<div class="checkbox-cell table-cell">
<Checkbox v-model="profile.selected" class="select-checkbox" />
</div>
<div class="name-cell table-cell">
{{ profile.name }}
</div>
</div>
</div>
<div v-else class="table-content empty">No profiles found</div>
</div>
<div class="button-row">
<Button
:disabled="
loading ||
!Array.from(profiles.values())
.flatMap((e) => e)
.some((e) => e.selected)
"
color="primary"
@click="next"
>
{{
loading
? 'Importing...'
: Array.from(profiles.values())
.flatMap((e) => e)
.some((e) => e.selected)
? `Import ${
Array.from(profiles.values())
.flatMap((e) => e)
.filter((e) => e.selected).length
} profiles`
: 'Select profiles to import'
}}
</Button>
<ProgressBar
v-if="loading"
:progress="(importedProfiles / (totalProfiles + 0.0001)) * 100"
/>
</div>
</div>
</ModalWrapper>
</template>
<script setup>
import {
FolderOpenIcon,
FolderSearchIcon,
InfoIcon,
PlusIcon,
UpdatedIcon,
UploadIcon,
XIcon,
} from '@modrinth/assets'
import {
Avatar,
Button,
Checkbox,
Chips,
injectNotificationManager,
StyledInput,
} from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { getCurrentWebview } from '@tauri-apps/api/webview'
import { open } from '@tauri-apps/plugin-dialog'
import { computed, onUnmounted, ref, shallowRef } from 'vue'
import Multiselect from 'vue-multiselect'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import ProgressBar from '@/components/ui/ProgressBar.vue'
import { trackEvent } from '@/helpers/analytics'
import {
get_default_launcher_path,
get_importable_instances,
import_instance,
} from '@/helpers/import.js'
import { get_game_versions, get_loader_versions } from '@/helpers/metadata'
import { create_profile_and_install_from_file } from '@/helpers/pack.js'
import { create } from '@/helpers/profile'
import { get_loaders } from '@/helpers/tags'
const { handleError } = injectNotificationManager()
const profile_name = ref('')
const game_version = ref('')
const loader = ref('vanilla')
const loader_version = ref('stable')
const specified_loader_version = ref('')
const icon = ref(null)
const display_icon = ref(null)
const creating = ref(false)
const showSnapshots = ref(false)
const creationType = ref('custom')
const isShowing = ref(false)
defineExpose({
show: async () => {
game_version.value = ''
specified_loader_version.value = ''
profile_name.value = ''
creating.value = false
showSnapshots.value = false
loader.value = 'vanilla'
loader_version.value = 'stable'
icon.value = null
display_icon.value = null
isShowing.value = true
modal.value.show()
unlistener.value = await getCurrentWebview().onDragDropEvent(async (event) => {
// Only if modal is showing
if (!isShowing.value) return
if (event.payload.type !== 'drop') return
if (creationType.value !== 'from file') return
hide()
const { paths } = event.payload
if (paths && paths.length > 0 && paths[0].endsWith('.mrpack')) {
await create_profile_and_install_from_file(paths[0]).catch(handleError)
trackEvent('InstanceCreate', {
source: 'CreationModalFileDrop',
})
}
})
trackEvent('InstanceCreateStart', { source: 'CreationModal' })
},
})
const unlistener = ref(null)
const hide = () => {
isShowing.value = false
modal.value.hide()
if (unlistener.value) {
unlistener.value()
unlistener.value = null
}
}
onUnmounted(() => {
if (unlistener.value) {
unlistener.value()
unlistener.value = null
}
})
const [
fabric_versions,
forge_versions,
quilt_versions,
neoforge_versions,
all_game_versions,
loaders,
] = await Promise.all([
get_loader_versions('fabric').then(shallowRef).catch(handleError),
get_loader_versions('forge').then(shallowRef).catch(handleError),
get_loader_versions('quilt').then(shallowRef).catch(handleError),
get_loader_versions('neo').then(shallowRef).catch(handleError),
get_game_versions().then(shallowRef).catch(handleError),
get_loaders()
.then((value) =>
ref(
value
.filter((item) => item.supported_project_types.includes('modpack'))
.map((item) => item.name.toLowerCase()),
),
)
.catch((err) => {
handleError(err)
return ref([])
}),
])
loaders.value.unshift('vanilla')
const game_versions = computed(() => {
return all_game_versions.value.versions
.filter((item) => {
let defaultVal = item.type === 'release' || showSnapshots.value
if (loader.value === 'fabric') {
defaultVal &= fabric_versions.value.gameVersions.some((x) => item.id === x.id)
} else if (loader.value === 'forge') {
defaultVal &= forge_versions.value.gameVersions.some((x) => item.id === x.id)
} else if (loader.value === 'quilt') {
defaultVal &= quilt_versions.value.gameVersions.some((x) => item.id === x.id)
} else if (loader.value === 'neoforge') {
defaultVal &= neoforge_versions.value.gameVersions.some((x) => item.id === x.id)
}
return defaultVal
})
.map((item) => item.id)
})
const modal = ref(null)
const check_valid = computed(() => {
return (
profile_name.value.trim() &&
game_version.value &&
game_versions.value.includes(game_version.value)
)
})
const create_instance = async () => {
creating.value = true
const loader_version_value =
loader_version.value === 'other' ? specified_loader_version.value : loader_version.value
const loaderVersion = loader.value === 'vanilla' ? null : (loader_version_value ?? 'stable')
hide()
creating.value = false
await create(
profile_name.value,
game_version.value,
loader.value,
loader.value === 'vanilla' ? null : (loader_version_value ?? 'stable'),
icon.value,
).catch(handleError)
trackEvent('InstanceCreate', {
profile_name: profile_name.value,
game_version: game_version.value,
loader: loader.value,
loader_version: loaderVersion,
has_icon: !!icon.value,
source: 'CreationModal',
})
}
const upload_icon = async () => {
const res = await open({
multiple: false,
filters: [
{
name: 'Image',
extensions: ['png', 'jpeg', 'svg', 'webp', 'gif', 'jpg'],
},
],
})
icon.value = res.path ?? res
if (!icon.value) return
display_icon.value = convertFileSrc(icon.value)
}
const reset_icon = () => {
icon.value = null
display_icon.value = null
}
const selectable_versions = computed(() => {
if (game_version.value) {
if (loader.value === 'fabric') {
return fabric_versions.value.gameVersions[0].loaders.map((item) => item.id)
} else if (loader.value === 'forge') {
return forge_versions.value.gameVersions
.find((item) => item.id === game_version.value)
.loaders.map((item) => item.id)
} else if (loader.value === 'quilt') {
return quilt_versions.value.gameVersions[0].loaders.map((item) => item.id)
} else if (loader.value === 'neoforge') {
return neoforge_versions.value.gameVersions
.find((item) => item.id === game_version.value)
.loaders.map((item) => item.id)
}
}
return []
})
const openFile = async () => {
const newProject = await open({ multiple: false })
if (!newProject) return
hide()
await create_profile_and_install_from_file(newProject.path ?? newProject).catch(handleError)
trackEvent('InstanceCreate', {
source: 'CreationModalFileOpen',
})
}
const profiles = ref(
new Map([
['MultiMC', []],
['GDLauncher', []],
['ATLauncher', []],
['Curseforge', []],
['PrismLauncher', []],
]),
)
const loading = ref(false)
const importedProfiles = ref(0)
const totalProfiles = ref(0)
const selectedProfileType = ref('MultiMC')
const profileOptions = ref([
{ name: 'MultiMC', path: '' },
{ name: 'GDLauncher', path: '' },
{ name: 'ATLauncher', path: '' },
{ name: 'Curseforge', path: '' },
{ name: 'PrismLauncher', path: '' },
])
// Attempt to get import profiles on default paths
const promises = profileOptions.value.map(async (option) => {
const path = await get_default_launcher_path(option.name).catch(handleError)
if (!path || path === '') return
// Try catch to allow failure and simply ignore default path attempt
try {
const instances = await get_importable_instances(option.name, path)
if (!instances) return
profileOptions.value.find((profile) => profile.name === option.name).path = path
profiles.value.set(
option.name,
instances.map((name) => ({ name, selected: false })),
)
} catch {
// Allow failure silently
}
})
await Promise.all(promises)
const selectLauncherPath = async () => {
selectedProfileType.value.path = await open({ multiple: false, directory: true })
if (selectedProfileType.value.path) {
await reload()
}
}
const reload = async () => {
const instances = await get_importable_instances(
selectedProfileType.value.name,
selectedProfileType.value.path,
).catch(handleError)
if (instances) {
profiles.value.set(
selectedProfileType.value.name,
instances.map((name) => ({ name, selected: false })),
)
} else {
profiles.value.set(selectedProfileType.value.name, [])
}
}
const setPath = () => {
profileOptions.value.find((profile) => profile.name === selectedProfileType.value.name).path =
selectedProfileType.value.path
}
const next = async () => {
importedProfiles.value = 0
totalProfiles.value = Array.from(profiles.value.values())
.map((profiles) => profiles.filter((profile) => profile.selected).length)
.reduce((a, b) => a + b, 0)
loading.value = true
for (const launcher of Array.from(profiles.value.entries()).map(([launcher, profiles]) => ({
launcher,
path: profileOptions.value.find((option) => option.name === launcher).path,
profiles,
}))) {
for (const profile of launcher.profiles.filter((profile) => profile.selected)) {
await import_instance(launcher.launcher, launcher.path, profile.name)
.catch(handleError)
.then(() => console.log(`Successfully Imported ${profile.name} from ${launcher.launcher}`))
profile.selected = false
importedProfiles.value++
}
}
loading.value = false
}
</script>
<style lang="scss" scoped>
.modal-body {
display: flex;
flex-direction: column;
gap: var(--gap-md);
margin-top: var(--gap-lg);
}
.input-label {
font-size: 1rem;
font-weight: bolder;
color: var(--color-contrast);
margin-bottom: 0.5rem;
}
.text-input {
width: 20rem;
}
.image-upload {
display: flex;
gap: 1rem;
}
.image-input {
display: flex;
flex-direction: column;
gap: 0.5rem;
justify-content: center;
}
.warning {
font-style: italic;
}
:deep(button.checkbox) {
border: none;
}
.selector {
max-width: 20rem;
}
.labeled-divider {
text-align: center;
}
.labeled-divider:after {
background-color: var(--color-raised-bg);
content: 'Or';
color: var(--color-base);
padding: var(--gap-sm);
position: relative;
top: -0.5rem;
}
.info {
display: flex;
flex-direction: row;
gap: 0.5rem;
align-items: center;
}
.modal-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding-bottom: 0;
}
.path-selection {
padding: var(--gap-xl);
background-color: var(--color-bg);
border-radius: var(--radius-lg);
display: flex;
flex-direction: column;
gap: var(--gap-md);
h3 {
margin: 0;
}
.path-input {
display: flex;
align-items: center;
width: 100%;
flex-direction: row;
gap: var(--gap-sm);
.iconified-input {
flex-grow: 1;
:deep(input) {
width: 100%;
flex-basis: auto;
}
}
}
}
.table {
border: 1px solid var(--color-bg);
}
.table-row {
grid-template-columns: min-content auto;
}
.table-content {
max-height: calc(5 * (18px + 2rem));
height: calc(5 * (18px + 2rem));
overflow-y: auto;
}
.select-checkbox {
button.checkbox {
border: none;
}
}
.button-row {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: var(--gap-md);
.transparent {
padding: var(--gap-sm) 0;
}
}
.empty {
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
font-weight: bolder;
color: var(--color-contrast);
}
.card-divider {
margin: var(--gap-md) var(--gap-lg) 0 var(--gap-lg);
}
</style>
@@ -2,6 +2,7 @@
import { GameIcon, LeftArrowIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled, FormattedTag } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { computed } from 'vue'
type Instance = {
game_version: string
@@ -12,18 +13,23 @@ type Instance = {
name: string
}
defineProps<{
instance: Instance
}>()
const props = withDefaults(
defineProps<{
instance: Instance
backTab?: string
}>(),
{ backTab: undefined },
)
const instanceLink = computed(() => {
const base = `/instance/${encodeURIComponent(props.instance.path)}`
return props.backTab ? `${base}/${props.backTab}` : base
})
</script>
<template>
<div class="flex justify-between items-center border-0 border-b border-solid border-divider pb-4">
<router-link
:to="`/instance/${encodeURIComponent(instance.path)}`"
tabindex="-1"
class="flex flex-col gap-4 text-primary"
>
<router-link :to="instanceLink" tabindex="-1" class="flex flex-col gap-4 text-primary">
<span class="flex items-center gap-2">
<Avatar
:src="instance.icon_path ? convertFileSrc(instance.icon_path) : undefined"
@@ -43,9 +49,7 @@ defineProps<{
</span>
</router-link>
<ButtonStyled>
<router-link :to="`/instance/${encodeURIComponent(instance.path)}`">
<LeftArrowIcon /> Back to instance
</router-link>
<router-link :to="instanceLink"> <LeftArrowIcon /> Back to instance </router-link>
</ButtonStyled>
</div>
</template>
@@ -3,6 +3,7 @@
v-if="typeof to === 'string'"
:to="to"
v-bind="$attrs"
:active-class="isSubpage ? '' : undefined"
:class="{
'router-link-active': isPrimary && isPrimary(route),
'subpage-active': isSubpage && isSubpage(route),
@@ -1,184 +0,0 @@
<template>
<nav
v-if="filteredLinks.length > 1"
ref="scrollContainer"
class="card-shadow experimental-styles-within relative flex w-fit overflow-clip rounded-full bg-bg-raised p-1 text-sm font-bold"
>
<RouterLink
v-for="(link, index) in filteredLinks"
v-show="link.shown === undefined ? true : link.shown"
:key="index"
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 ${activeIndex === index && !subpageSelected ? 'text-button-textSelected' : activeIndex === index && subpageSelected ? 'text-contrast' : 'text-primary'}`"
>
<component :is="link.icon" v-if="link.icon" class="size-5" />
<span class="text-nowrap">{{ link.label }}</span>
</RouterLink>
<div
:class="[
'pointer-events-none absolute h-[calc(100%-0.5rem)] overflow-hidden rounded-full p-1',
subpageSelected ? 'bg-button-bg' : 'bg-button-bgSelected',
{ 'navtabs-transition': transitionsEnabled },
]"
:style="{
left: sliderLeftPx,
top: sliderTopPx,
right: sliderRightPx,
bottom: sliderBottomPx,
opacity: sliderReady && activeIndex !== -1 ? 1 : 0,
}"
aria-hidden="true"
></div>
</nav>
</template>
<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import type { RouteLocationRaw } from 'vue-router'
import { RouterLink, useRoute } from 'vue-router'
const route = useRoute()
interface Tab {
label: string
href: string | RouteLocationRaw
shown?: boolean
icon?: unknown
subpages?: string[]
}
const props = defineProps<{
links: Tab[]
query?: string
}>()
const scrollContainer = ref<HTMLElement | null>(null)
const sliderLeft = ref(4)
const sliderTop = ref(4)
const sliderRight = ref(4)
const sliderBottom = ref(4)
const activeIndex = ref(-1)
const subpageSelected = ref(false)
const sliderReady = ref(false)
const transitionsEnabled = ref(false)
const sliderDelays = ref({ left: '0ms', top: '0ms', right: '0ms', bottom: '0ms' })
const filteredLinks = computed(() =>
props.links.filter((x) => (x.shown === undefined ? true : x.shown)),
)
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 leftDelay = computed(() => sliderDelays.value.left)
const rightDelay = computed(() => sliderDelays.value.right)
const topDelay = computed(() => sliderDelays.value.top)
const bottomDelay = computed(() => sliderDelays.value.bottom)
function pickLink() {
let index = -1
subpageSelected.value = false
for (let i = filteredLinks.value.length - 1; i >= 0; i--) {
const link = filteredLinks.value[i]
if (route.path === (typeof link.href === 'string' ? link.href : link.href.path)) {
index = i
break
} else if (link.subpages && link.subpages.some((subpage) => route.path.includes(subpage))) {
index = i
subpageSelected.value = true
break
}
}
activeIndex.value = index
if (activeIndex.value !== -1) {
startAnimation()
} else {
sliderLeft.value = 0
sliderRight.value = 0
}
}
function getTabElement(index: number): HTMLElement | null {
if (index === -1) return null
const container = scrollContainer.value
if (!container) return null
const tabs = container.querySelectorAll('.button-animation')
return (tabs[index] as HTMLElement) ?? null
}
function startAnimation() {
const el = getTabElement(activeIndex.value)
if (!el?.offsetParent) return
const parent = el.offsetParent as HTMLElement
const newValues = {
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) {
sliderLeft.value = newValues.left
sliderRight.value = newValues.right
sliderTop.value = newValues.top
sliderBottom.value = newValues.bottom
sliderReady.value = true
requestAnimationFrame(() => {
transitionsEnabled.value = true
})
} else {
const STAGGER_DELAY = '200ms'
sliderDelays.value = {
left: newValues.left < sliderLeft.value ? '0ms' : STAGGER_DELAY,
right: newValues.left < sliderLeft.value ? STAGGER_DELAY : '0ms',
top: newValues.top < sliderTop.value ? '0ms' : STAGGER_DELAY,
bottom: newValues.top < sliderTop.value ? STAGGER_DELAY : '0ms',
}
sliderLeft.value = newValues.left
sliderRight.value = newValues.right
sliderTop.value = newValues.top
sliderBottom.value = newValues.bottom
}
}
onMounted(() => {
window.addEventListener('resize', pickLink)
pickLink()
})
onUnmounted(() => {
window.removeEventListener('resize', pickLink)
})
watch(
filteredLinks,
async () => {
await nextTick()
pickLink()
},
{ deep: true },
)
watch(route, async () => {
await nextTick()
pickLink()
})
</script>
<style scoped>
.navtabs-transition {
/* Delay on opacity is to hide any jankiness as the page loads */
transition:
left 150ms cubic-bezier(0.4, 0, 0.2, 1) v-bind(leftDelay),
right 150ms cubic-bezier(0.4, 0, 0.2, 1) v-bind(rightDelay),
top 150ms cubic-bezier(0.4, 0, 0.2, 1) v-bind(topDelay),
bottom 150ms cubic-bezier(0.4, 0, 0.2, 1) v-bind(bottomDelay),
opacity 250ms cubic-bezier(0.5, 0, 0.2, 1) 50ms;
}
</style>
@@ -49,26 +49,22 @@ onUnmounted(() => {
</script>
<template>
<NavButton
v-for="instance in recentInstances"
:key="instance.id"
v-tooltip.right="instance.name"
:to="`/instance/${encodeURIComponent(instance.path)}`"
class="relative"
>
<Avatar
:src="instance.icon_path ? convertFileSrc(instance.icon_path) : null"
size="28px"
:tint-by="instance.path"
:class="`transition-all ${instance.install_stage !== 'installed' ? `brightness-[0.25] scale-[0.85]` : `group-hover:brightness-75`}`"
/>
<div
v-if="instance.install_stage !== 'installed'"
class="absolute inset-0 flex items-center justify-center z-10"
>
<SpinnerIcon class="animate-spin w-4 h-4" />
</div>
</NavButton>
<div v-for="instance in recentInstances" :key="instance.id" v-tooltip.right="instance.name">
<NavButton :to="`/instance/${encodeURIComponent(instance.path)}`" class="relative">
<Avatar
:src="instance.icon_path ? convertFileSrc(instance.icon_path) : null"
size="28px"
:tint-by="instance.path"
:class="`transition-all ${instance.install_stage !== 'installed' ? `brightness-[0.25] scale-[0.85]` : `group-hover:brightness-75`}`"
/>
<div
v-if="instance.install_stage !== 'installed'"
class="absolute inset-0 flex items-center justify-center z-10 pointer-events-none"
>
<SpinnerIcon class="animate-spin w-4 h-4" />
</div>
</NavButton>
</div>
<div
v-if="instances && recentInstances.length > 0"
class="h-px w-6 mx-auto my-2 bg-divider"
@@ -1,126 +0,0 @@
<template>
<ProjectCard
:title="project.title"
:link="
() => {
emit('open')
$router.push({
path: `/project/${project.project_id ?? project.id}`,
query: { i: props.instance ? props.instance.path : undefined },
})
}
"
:author="{ name: project.author, link: `https://modrinth.com/user/${project.author}` }"
:icon-url="project.icon_url"
:summary="project.description"
:tags="project.display_categories"
:all-tags="project.categories"
:downloads="project.downloads"
:followers="project.follows"
:date-updated="project.date_modified"
:banner="project.featured_gallery ?? undefined"
:color="project.color ?? undefined"
:environment="
projectType
? ['mod', 'modpack'].includes(projectType)
? {
clientSide: project.client_side,
serverSide: project.server_side,
}
: undefined
: undefined
"
layout="list"
>
<template #actions>
<ButtonStyled color="brand" type="outlined">
<button
:disabled="installed || installing"
class="shrink-0 no-wrap"
@click.stop="install()"
>
<template v-if="!installed">
<DownloadIcon v-if="modpack || instance" />
<PlusIcon v-else />
</template>
<CheckIcon v-else />
{{
installing
? 'Installing'
: installed
? 'Installed'
: modpack || instance
? 'Install'
: 'Add to an instance'
}}
</button>
</ButtonStyled>
</template>
</ProjectCard>
</template>
<script setup>
import { CheckIcon, DownloadIcon, PlusIcon } from '@modrinth/assets'
import { ButtonStyled, injectNotificationManager, ProjectCard } from '@modrinth/ui'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { install as installVersion } from '@/store/install.js'
dayjs.extend(relativeTime)
const { handleError } = injectNotificationManager()
const router = useRouter()
const props = defineProps({
backgroundImage: {
type: String,
default: null,
},
project: {
type: Object,
required: true,
},
instance: {
type: Object,
default: null,
},
featured: {
type: Boolean,
default: false,
},
installed: {
type: Boolean,
default: false,
},
projectType: {
type: String,
default: undefined,
},
})
const emit = defineEmits(['open', 'install'])
const installing = ref(false)
async function install() {
installing.value = true
await installVersion(
props.project.project_id ?? props.project.id,
null,
props.instance ? props.instance.path : null,
'SearchCard',
() => {
installing.value = false
emit('install', props.project.project_id ?? props.project.id)
},
(profile) => {
router.push(`/instance/${profile}`)
},
).catch(handleError)
}
const modpack = computed(() => props.project.project_type === 'modpack')
</script>
File diff suppressed because one or more lines are too long
@@ -1,38 +1,33 @@
<script setup>
import { Button, injectNotificationManager } from '@modrinth/ui'
import { Button, injectNotificationManager, ProjectCard } from '@modrinth/ui'
import { ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import SearchCard from '@/components/ui/SearchCard.vue'
import { get_project, get_version } from '@/helpers/cache.js'
import { get_categories } from '@/helpers/tags.js'
import { install as installVersion } from '@/store/install.js'
import { get_project_v3, get_version } from '@/helpers/cache.js'
import { injectContentInstall } from '@/providers/content-install'
const { handleError } = injectNotificationManager()
const { install: installVersion } = injectContentInstall()
const confirmModal = ref(null)
const project = ref(null)
const version = ref(null)
const categories = ref(null)
const installing = ref(false)
defineExpose({
async show(event) {
if (event.event === 'InstallVersion') {
version.value = await get_version(event.id, 'must_revalidate').catch(handleError)
project.value = await get_project(version.value.project_id, 'must_revalidate').catch(
project.value = await get_project_v3(version.value.project_id, 'must_revalidate').catch(
handleError,
)
} else {
project.value = await get_project(event.id, 'must_revalidate').catch(handleError)
project.value = await get_project_v3(event.id, 'must_revalidate').catch(handleError)
version.value = await get_version(
project.value.versions[project.value.versions.length - 1],
'must_revalidate',
).catch(handleError)
}
categories.value = (await get_categories().catch(handleError)).filter(
(cat) => project.value.categories.includes(cat.name) && cat.project_type === 'mod',
)
confirmModal.value.show()
},
})
@@ -51,13 +46,22 @@ async function install() {
</script>
<template>
<ModalWrapper ref="confirmModal" :header="`Install ${project?.title}`">
<ModalWrapper ref="confirmModal" :header="`Install ${project?.name}`">
<div class="modal-body">
<SearchCard
:project="project"
<ProjectCard
:title="project.name"
:link="() => confirmModal.hide()"
:icon-url="project.icon_url"
:summary="project.summary"
:tags="project.display_categories"
:all-tags="project.categories"
:downloads="project.downloads"
:followers="project.follows"
:date-updated="project.date_modified"
:banner="project.featured_gallery ?? undefined"
:color="project.color ?? undefined"
layout="list"
class="project-card"
:categories="categories"
@open="confirmModal.hide()"
/>
<div class="button-row">
<div class="markdown-body">
@@ -0,0 +1,98 @@
<template>
<section v-if="showControls" class="window-controls" data-tauri-drag-region-exclude>
<ButtonStyled type="transparent" circular>
<button class="titlebar-button" @click="() => getCurrentWindow().minimize()">
<MinimizeIcon />
</button>
</ButtonStyled>
<ButtonStyled type="transparent" circular>
<button class="titlebar-button" @click="() => getCurrentWindow().toggleMaximize()">
<RestoreIcon v-if="isMaximized" />
<MaximizeIcon v-else />
</button>
</ButtonStyled>
<ButtonStyled type="transparent" circular>
<button class="titlebar-button close" @click="handleClose">
<XIcon />
</button>
</ButtonStyled>
</section>
</template>
<script setup>
import { MaximizeIcon, MinimizeIcon, RestoreIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled } from '@modrinth/ui'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { get as getSettings } from '@/helpers/settings.ts'
import { getOS } from '@/helpers/utils.js'
const WINDOW_CONTROLS_WIDTH = '8rem'
const nativeDecorations = ref(true)
const isMaximized = ref(false)
const os = ref('')
const showControls = computed(() => !nativeDecorations.value && os.value !== 'MacOS')
watch(
showControls,
(visible) => {
if (typeof document === 'undefined') return
if (visible) {
document.documentElement.style.setProperty('--window-controls-width', WINDOW_CONTROLS_WIDTH)
} else {
document.documentElement.style.removeProperty('--window-controls-width')
}
},
{ immediate: true },
)
onMounted(async () => {
os.value = await getOS()
const settings = await getSettings()
nativeDecorations.value = settings.native_decorations
if (os.value !== 'MacOS') {
await getCurrentWindow().setDecorations(nativeDecorations.value)
}
isMaximized.value = await getCurrentWindow().isMaximized()
const unlisten = await getCurrentWindow().onResized(async () => {
isMaximized.value = await getCurrentWindow().isMaximized()
})
onUnmounted(() => {
unlisten()
document.documentElement.style.removeProperty('--window-controls-width')
})
})
const handleClose = async () => {
await saveWindowState(StateFlags.ALL)
await getCurrentWindow().close()
}
</script>
<style lang="scss" scoped>
.window-controls {
position: fixed;
top: 0;
right: 0;
z-index: 10001;
display: flex;
flex-direction: row;
align-items: center;
height: var(--top-bar-height, 3rem);
padding-right: 0.5rem;
gap: 0.25rem;
.titlebar-button.close:hover {
background-color: var(--color-red);
color: var(--color-accent-contrast);
}
}
</style>
@@ -288,7 +288,7 @@ const messages = defineMessages({
</div>
</div>
</ModalWrapper>
<div v-if="userCredentials && !loading" class="flex gap-1 items-center mb-3 ml-2 mr-1">
<div v-if="userCredentials && !loading" class="flex gap-1 items-center mb-3 -ml-1">
<template v-if="sortedFriends.length > 0">
<ButtonStyled circular type="transparent">
<button
@@ -309,7 +309,7 @@ const messages = defineMessages({
@keyup.esc="search = ''"
/>
</template>
<h3 v-else class="ml-2 w-full text-base text-primary font-medium m-0">
<h3 v-else class="w-full text-base text-primary font-medium m-0">
{{ formatMessage(messages.friends) }}
</h3>
<ButtonStyled v-if="incomingRequests.length > 0" circular type="transparent">
@@ -331,11 +331,11 @@ const messages = defineMessages({
</ButtonStyled>
</div>
<div class="flex flex-col gap-3">
<h3 v-if="loading" class="ml-4 mr-1 text-base text-primary font-medium m-0">
<h3 v-if="loading" class="text-base text-primary font-medium m-0">
{{ formatMessage(messages.friends) }}
</h3>
<template v-if="loading">
<div v-for="n in 5" :key="n" class="flex gap-2 items-center animate-pulse ml-4 mr-1">
<div v-for="n in 5" :key="n" class="flex gap-2 items-center animate-pulse">
<div class="min-w-9 min-h-9 bg-button-bg rounded-full"></div>
<div class="flex flex-col w-full">
<div class="h-3 bg-button-bg rounded-full w-1/2 mb-1"></div>
@@ -344,7 +344,7 @@ const messages = defineMessages({
</div>
</template>
<template v-else-if="sortedFriends.length === 0">
<div class="text-sm ml-4 mr-1">
<div class="text-sm">
<div v-if="!userCredentials">
<IntlFormatted :message-id="messages.signInToAddFriends">
<template #link="{ children }">
@@ -106,7 +106,7 @@ const messages = defineMessages({
:open-by-default="openByDefault"
:force-open="isSearching"
:button-class="
'pl-4 pr-3 flex w-full items-center bg-transparent border-0 p-0' +
'flex w-full items-center bg-transparent border-0 p-0' +
(isSearching
? ''
: ' cursor-pointer hover:brightness-[--hover-brightness] active:scale-[0.98] transition-all')
@@ -122,7 +122,7 @@ const messages = defineMessages({
<div
v-for="friend in friends"
:key="friend.username"
class="group grid items-center grid-cols-[auto_1fr_auto] gap-2 hover:bg-button-bg transition-colors rounded-full ml-4 mr-1"
class="group grid items-center grid-cols-[auto_1fr_auto] gap-2 hover:bg-button-bg transition-colors rounded-full mr-1"
@contextmenu.prevent.stop="
(event) => friendOptions?.showMenu(event, friend, createContextMenuOptions(friend))
"
@@ -37,17 +37,21 @@ defineExpose({
searchFilter.value = ''
const profilesVal = await list().catch(handleError)
for (const profile of profilesVal) {
profile.adding = false
profile.added = false
await Promise.allSettled(
profilesVal.map(async (profile) => {
profile.adding = false
profile.added = false
try {
const worlds = await get_profile_worlds(profile.path)
profile.added = worlds.some((w) => w.type === 'server' && w.address === serverAddress.value)
} catch {
// Ignore - will show as not added
}
}
try {
const worlds = await get_profile_worlds(profile.path)
profile.added = worlds.some(
(w) => w.type === 'server' && w.address === serverAddress.value,
)
} catch {
// Ignore - will show as not added
}
}),
)
profiles.value = profilesVal
modal.value.show()
@@ -17,31 +17,17 @@
<tr class="content">
<td class="data">{{ instance?.loader }} {{ instance?.game_version }}</td>
<td>
<multiselect
<Combobox
v-if="versions?.length > 1"
v-model="selectedVersion"
:options="versions"
v-model="selectedVersionId"
:options="versionOptions"
:searchable="true"
placeholder="Select version"
open-direction="top"
:show-labels="false"
:custom-label="
(version) =>
`${version?.name} (${version?.loaders
.map((name) => formatLoader(formatMessage, name))
.join(', ')} - ${version?.game_versions.join(', ')})`
"
force-direction="up"
:max-height="150"
/>
<span v-else>
<span>
{{ selectedVersion?.name }} ({{
selectedVersion?.loaders
.map((name) => formatLoader(formatMessage, name))
.join(', ')
}}
- {{ selectedVersion?.game_versions.join(', ') }})
</span>
<span>{{ selectedVersionLabel }}</span>
</span>
</td>
</tr>
@@ -59,9 +45,8 @@
<script setup>
import { DownloadIcon, XIcon } from '@modrinth/assets'
import { Button, formatLoader, injectNotificationManager, useVIntl } from '@modrinth/ui'
import { ref } from 'vue'
import Multiselect from 'vue-multiselect'
import { Button, Combobox, formatLoader, injectNotificationManager, useVIntl } from '@modrinth/ui'
import { computed, ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
@@ -79,11 +64,35 @@ const installing = ref(false)
const onInstall = ref(() => {})
const selectedVersionLabel = computed(() => {
if (!selectedVersion.value) return ''
return `${selectedVersion.value.name} (${selectedVersion.value.loaders
.map((name) => formatLoader(formatMessage, name))
.join(', ')} - ${selectedVersion.value.game_versions.join(', ')})`
})
const versionOptions = computed(() =>
(versions.value ?? []).map((version) => ({
value: version.id,
label: `${version.name} (${version.loaders
.map((name) => formatLoader(formatMessage, name))
.join(', ')} - ${version.game_versions.join(', ')})`,
})),
)
const selectedVersionId = computed({
get: () => selectedVersion.value?.id ?? null,
set: (value) => {
if (!value) return
selectedVersion.value = (versions.value ?? []).find((version) => version.id === value) ?? null
},
})
defineExpose({
show: (instanceVal, projectVal, projectVersions, selected, callback) => {
instance.value = instanceVal
versions.value = projectVersions
selectedVersion.value = selected ?? projectVersions[0]
versions.value = projectVersions ?? []
selectedVersion.value = selected ?? projectVersions?.[0] ?? null
project.value = projectVal
@@ -162,9 +171,5 @@ td:first-child {
display: flex;
flex-direction: column;
gap: 1rem;
:deep(.animated-dropdown .options) {
max-height: 13.375rem;
}
}
</style>
@@ -1,77 +0,0 @@
<script setup>
import { DownloadIcon, XIcon } from '@modrinth/assets'
import { Button, injectNotificationManager } from '@modrinth/ui'
import { ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { create_profile_and_install as pack_install } from '@/helpers/pack'
const { handleError } = injectNotificationManager()
const versionId = ref()
const project = ref()
const confirmModal = ref(null)
const installing = ref(false)
const onInstall = ref(() => {})
const onCreateInstance = ref(() => {})
defineExpose({
show: (projectVal, versionIdVal, callback, createInstanceCallback) => {
project.value = projectVal
versionId.value = versionIdVal
installing.value = false
confirmModal.value.show()
onInstall.value = callback
onCreateInstance.value = createInstanceCallback
trackEvent('PackInstallStart')
},
})
async function install() {
installing.value = true
confirmModal.value.hide()
await pack_install(
project.value.id,
versionId.value,
project.value.title,
project.value.icon_url,
onCreateInstance.value,
).catch(handleError)
trackEvent('PackInstall', {
id: project.value.id,
version_id: versionId.value,
title: project.value.title,
source: 'ConfirmModal',
})
onInstall.value(versionId.value)
installing.value = false
}
</script>
<template>
<ModalWrapper ref="confirmModal" header="Are you sure?" :on-hide="onInstall">
<div class="modal-body">
<p>You already have this modpack installed. Are you sure you want to install it again?</p>
<div class="input-group push-right">
<Button @click="() => $refs.confirmModal.hide()"><XIcon />Cancel</Button>
<Button color="primary" :disabled="installing" @click="install()"
><DownloadIcon /> {{ installing ? 'Installing' : 'Install' }}</Button
>
</div>
</div>
</ModalWrapper>
</template>
<style lang="scss" scoped>
.modal-body {
display: flex;
flex-direction: column;
gap: 1rem;
}
</style>
@@ -15,11 +15,12 @@ import { open } from '@tauri-apps/plugin-dialog'
import { computed, type Ref, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import ConfirmDeleteInstanceModal from '@/components/ui/modal/ConfirmDeleteInstanceModal.vue'
import { trackEvent } from '@/helpers/analytics'
import { duplicate, edit, edit_icon, list, remove } from '@/helpers/profile'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { GameInstance, InstanceSettingsTabProps } from '../../../helpers/types'
import type { GameInstance } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
@@ -27,21 +28,21 @@ const router = useRouter()
const deleteConfirmModal = ref()
const props = defineProps<InstanceSettingsTabProps>()
const { instance } = injectInstanceSettings()
const title = ref(props.instance.name)
const icon: Ref<string | undefined> = ref(props.instance.icon_path)
const groups = ref(props.instance.groups)
const title = ref(instance.value.name)
const icon: Ref<string | undefined> = ref(instance.value.icon_path)
const groups = ref([...instance.value.groups])
const newCategoryInput = ref('')
const installing = computed(() => props.instance.install_stage !== 'installed')
const installing = computed(() => instance.value.install_stage !== 'installed')
async function duplicateProfile() {
await duplicate(props.instance.path).catch(handleError)
await duplicate(instance.value.path).catch(handleError)
trackEvent('InstanceDuplicate', {
loader: props.instance.loader,
game_version: props.instance.game_version,
loader: instance.value.loader,
game_version: instance.value.game_version,
})
}
@@ -52,7 +53,7 @@ const availableGroups = computed(() => [
async function resetIcon() {
icon.value = undefined
await edit_icon(props.instance.path, null).catch(handleError)
await edit_icon(instance.value.path, null).catch(handleError)
trackEvent('InstanceRemoveIcon')
}
@@ -70,7 +71,7 @@ async function setIcon() {
if (!value) return
icon.value = value
await edit_icon(props.instance.path, icon.value).catch(handleError)
await edit_icon(instance.value.path, icon.value).catch(handleError)
trackEvent('InstanceSetIcon')
}
@@ -100,7 +101,8 @@ const addCategory = () => {
watch(
[title, groups, groups],
async () => {
await edit(props.instance.path, editProfileObject.value)
if (removing.value) return
await edit(instance.value.path, editProfileObject.value).catch(handleError)
},
{ deep: true },
)
@@ -108,15 +110,15 @@ watch(
const removing = ref(false)
async function removeProfile() {
removing.value = true
await remove(props.instance.path).catch(handleError)
removing.value = false
const path = instance.value.path
trackEvent('InstanceRemove', {
loader: props.instance.loader,
game_version: props.instance.game_version,
loader: instance.value.loader,
game_version: instance.value.game_version,
})
await router.push({ path: '/' })
await remove(path).catch(handleError)
}
const messages = defineMessages({
@@ -194,55 +196,50 @@ const messages = defineMessages({
</script>
<template>
<ConfirmModalWrapper
ref="deleteConfirmModal"
title="Are you sure you want to delete this instance?"
description="If you proceed, all data for your instance will be permanently erased, including your worlds. You will not be able to recover it."
:has-to-type="false"
proceed-label="Delete"
:show-ad-on-close="false"
@proceed="removeProfile"
/>
<ConfirmDeleteInstanceModal ref="deleteConfirmModal" @delete="removeProfile" />
<div class="block">
<div class="float-end ml-4 relative group">
<OverflowMenu
v-tooltip="formatMessage(messages.editIcon)"
class="bg-transparent border-none appearance-none p-0 m-0 cursor-pointer group-active:scale-95 transition-transform"
:options="[
{
id: 'select',
action: () => setIcon(),
},
{
id: 'remove',
color: 'danger',
action: () => resetIcon(),
shown: !!icon,
},
]"
>
<Avatar
:src="icon ? convertFileSrc(icon) : icon"
size="108px"
class="!border-4 group-hover:brightness-75"
:tint-by="props.instance.path"
no-shadow
/>
<div class="absolute top-0 right-0 m-2">
<div
class="p-2 m-0 text-primary flex items-center justify-center aspect-square bg-button-bg rounded-full border-button-border border-solid border-[1px] hovering-icon-shadow"
<div class="float-end ml-10 relative group w-fit">
<div class="flex flex-col gap-1">
<span class="text-lg font-semibold text-contrast">Icon</span>
<div class="group relative w-fit">
<OverflowMenu
v-tooltip="formatMessage(messages.editIcon)"
class="bg-transparent border-none appearance-none p-0 m-0 cursor-pointer group-active:scale-95 transition-transform"
:options="[
{
id: 'select',
action: () => setIcon(),
},
{
id: 'remove',
color: 'danger',
action: () => resetIcon(),
shown: !!icon,
},
]"
>
<EditIcon aria-hidden="true" class="h-4 w-4 text-primary" />
</div>
<Avatar
:src="icon ? convertFileSrc(icon) : icon"
size="108px"
class="transition-[filter] group-hover:brightness-75"
:tint-by="instance.path"
no-shadow
/>
<div
class="absolute top-0 h-full w-full flex items-center justify-center opacity-0 transition-all group-hover:opacity-100"
>
<EditIcon aria-hidden="true" class="h-10 w-10 text-primary" />
</div>
<template #select>
<UploadIcon />
{{ icon ? formatMessage(messages.replaceIcon) : formatMessage(messages.selectIcon) }}
</template>
<template #remove> <TrashIcon /> {{ formatMessage(messages.removeIcon) }} </template>
</OverflowMenu>
</div>
<template #select>
<UploadIcon />
{{ icon ? formatMessage(messages.replaceIcon) : formatMessage(messages.selectIcon) }}
</template>
<template #remove> <TrashIcon /> {{ formatMessage(messages.removeIcon) }} </template>
</OverflowMenu>
</div>
</div>
<label for="instance-name" class="m-0 mb-1 text-lg font-extrabold text-contrast block">
<label for="instance-name" class="m-0 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.name) }}
</label>
<div class="flex">
@@ -255,76 +252,82 @@ const messages = defineMessages({
/>
</div>
<template v-if="instance.install_stage == 'installed'">
<div>
<h2
id="duplicate-instance-label"
class="m-0 mt-4 mb-1 text-lg font-extrabold text-contrast block"
>
<div class="flex flex-col gap-2.5 mt-6">
<h2 id="duplicate-instance-label" class="m-0 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.duplicateInstance) }}
</h2>
<p class="m-0 mb-2">
<ButtonStyled>
<button
v-tooltip="installing ? formatMessage(messages.duplicateButtonTooltipInstalling) : null"
aria-labelledby="duplicate-instance-label"
:disabled="installing"
class="w-max !shadow-none"
@click="duplicateProfile"
>
<CopyIcon /> {{ formatMessage(messages.duplicateButton) }}
</button>
</ButtonStyled>
<p class="m-0">
{{ formatMessage(messages.duplicateInstanceDescription) }}
</p>
</div>
<ButtonStyled>
</template>
<div class="flex flex-col gap-2.5 mt-6">
<h2 class="m-0 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.libraryGroups) }}
</h2>
<div class="flex flex-col gap-1">
<Checkbox
v-for="group in availableGroups"
:key="group"
:model-value="groups.includes(group)"
:label="group"
@click="toggleGroup(group)"
/>
<div class="flex gap-2 items-center">
<StyledInput
v-model="newCategoryInput"
:placeholder="formatMessage(messages.libraryGroupsEnterName)"
class="w-full max-w-[300px]"
@submit="() => addCategory"
/>
<ButtonStyled>
<button class="w-fit !shadow-none" @click="() => addCategory()">
<PlusIcon /> {{ formatMessage(messages.libraryGroupsCreate) }}
</button>
</ButtonStyled>
</div>
</div>
<p class="m-0">
{{ formatMessage(messages.libraryGroupsDescription) }}
</p>
</div>
<div class="flex flex-col gap-2.5 mt-6">
<h2 id="delete-instance-label" class="m-0 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.deleteInstance) }}
</h2>
<ButtonStyled color="red">
<button
v-tooltip="installing ? formatMessage(messages.duplicateButtonTooltipInstalling) : null"
aria-labelledby="duplicate-instance-label"
:disabled="installing"
@click="duplicateProfile"
aria-labelledby="delete-instance-label"
:disabled="removing"
class="w-fit !shadow-none"
@click="deleteConfirmModal.show()"
>
<CopyIcon /> {{ formatMessage(messages.duplicateButton) }}
<SpinnerIcon v-if="removing" class="animate-spin" />
<TrashIcon v-else />
{{
removing
? formatMessage(messages.deletingInstanceButton)
: formatMessage(messages.deleteInstanceButton)
}}
</button>
</ButtonStyled>
</template>
<h2 class="m-0 mt-4 mb-1 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.libraryGroups) }}
</h2>
<p class="m-0 mb-2">
{{ formatMessage(messages.libraryGroupsDescription) }}
</p>
<div class="flex flex-col gap-1">
<Checkbox
v-for="group in availableGroups"
:key="group"
:model-value="groups.includes(group)"
:label="group"
@click="toggleGroup(group)"
/>
<div class="flex gap-2 items-center">
<StyledInput
v-model="newCategoryInput"
:placeholder="formatMessage(messages.libraryGroupsEnterName)"
@submit="() => addCategory"
/>
<ButtonStyled>
<button class="w-fit" @click="() => addCategory()">
<PlusIcon /> {{ formatMessage(messages.libraryGroupsCreate) }}
</button>
</ButtonStyled>
</div>
<p class="m-0">
{{ formatMessage(messages.deleteInstanceDescription) }}
</p>
</div>
<h2 id="delete-instance-label" class="m-0 mt-4 mb-1 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.deleteInstance) }}
</h2>
<p class="m-0 mb-2">
{{ formatMessage(messages.deleteInstanceDescription) }}
</p>
<ButtonStyled color="red">
<button
aria-labelledby="delete-instance-label"
:disabled="removing"
@click="deleteConfirmModal.show()"
>
<SpinnerIcon v-if="removing" class="animate-spin" />
<TrashIcon v-else />
{{
removing
? formatMessage(messages.deletingInstanceButton)
: formatMessage(messages.deleteInstanceButton)
}}
</button>
</ButtonStyled>
</div>
</template>
<style scoped lang="scss">
@@ -10,22 +10,23 @@ import { computed, ref, watch } from 'vue'
import { edit } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { AppSettings, Hooks, InstanceSettingsTabProps } from '../../../helpers/types'
import type { AppSettings, Hooks } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const { instance } = injectInstanceSettings()
const globalSettings = (await get().catch(handleError)) as AppSettings
const overrideHooks = ref(
!!props.instance.hooks.pre_launch ||
!!props.instance.hooks.wrapper ||
!!props.instance.hooks.post_exit,
!!instance.value.hooks.pre_launch ||
!!instance.value.hooks.wrapper ||
!!instance.value.hooks.post_exit,
)
const hooks = ref(props.instance.hooks ?? globalSettings.hooks)
const hooks = ref(instance.value.hooks ?? globalSettings.hooks)
const editProfileObject = computed(() => {
const editProfile: {
@@ -41,7 +42,7 @@ const editProfileObject = computed(() => {
watch(
[overrideHooks, hooks],
async () => {
await edit(props.instance.path, editProfileObject.value)
await edit(instance.value.path, editProfileObject.value)
},
{ deep: true },
)
@@ -100,57 +101,57 @@ const messages = defineMessages({
<template>
<div>
<h2 class="m-0 mb-1 text-lg font-extrabold text-contrast">
<h2 class="m-0 m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.hooks) }}
</h2>
<Checkbox v-model="overrideHooks" :label="formatMessage(messages.customHooks)" class="my-2.5" />
<p class="m-0">
{{ formatMessage(messages.hooksDescription) }}
</p>
<Checkbox v-model="overrideHooks" :label="formatMessage(messages.customHooks)" class="mt-2" />
<h2 class="mt-2 mb-1 text-lg font-extrabold text-contrast">
<h2 class="mt-6 m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.preLaunch) }}
</h2>
<p class="m-0">
{{ formatMessage(messages.preLaunchDescription) }}
</p>
<StyledInput
id="pre-launch"
v-model="hooks.pre_launch"
autocomplete="off"
:disabled="!overrideHooks"
:placeholder="formatMessage(messages.preLaunchEnter)"
wrapper-class="w-full mt-2"
wrapper-class="w-full my-2.5"
/>
<p class="m-0">
{{ formatMessage(messages.preLaunchDescription) }}
</p>
<h2 class="mt-4 mb-1 text-lg font-extrabold text-contrast">
<h2 class="mt-6 m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.wrapper) }}
</h2>
<p class="m-0">
{{ formatMessage(messages.wrapperDescription) }}
</p>
<StyledInput
id="wrapper"
v-model="hooks.wrapper"
autocomplete="off"
:disabled="!overrideHooks"
:placeholder="formatMessage(messages.wrapperEnter)"
wrapper-class="w-full mt-2"
wrapper-class="w-full my-2.5"
/>
<p class="m-0">
{{ formatMessage(messages.wrapperDescription) }}
</p>
<h2 class="mt-4 mb-1 text-lg font-extrabold text-contrast">
<h2 class="mt-6 m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.postExit) }}
</h2>
<p class="m-0">
{{ formatMessage(messages.postExitDescription) }}
</p>
<StyledInput
id="post-exit"
v-model="hooks.post_exit"
autocomplete="off"
:disabled="!overrideHooks"
:placeholder="formatMessage(messages.postExitEnter)"
wrapper-class="w-full mt-2"
wrapper-class="w-full my-2.5"
/>
<p class="m-0">
{{ formatMessage(messages.postExitDescription) }}
</p>
</div>
</template>
File diff suppressed because it is too large Load Diff
@@ -14,34 +14,35 @@ import JavaSelector from '@/components/ui/JavaSelector.vue'
import useMemorySlider from '@/composables/useMemorySlider'
import { edit, get_optimal_jre_key } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { AppSettings, InstanceSettingsTabProps } from '../../../helpers/types'
import type { AppSettings } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const { instance } = injectInstanceSettings()
const globalSettings = (await get().catch(handleError)) as unknown as AppSettings
const overrideJavaInstall = ref(!!props.instance.java_path)
const optimalJava = readonly(await get_optimal_jre_key(props.instance.path).catch(handleError))
const javaInstall = ref({ path: optimalJava.path ?? props.instance.java_path })
const overrideJavaInstall = ref(!!instance.value.java_path)
const optimalJava = readonly(await get_optimal_jre_key(instance.value.path).catch(handleError))
const javaInstall = ref({ path: optimalJava.path ?? instance.value.java_path })
const overrideJavaArgs = ref((props.instance.extra_launch_args?.length ?? 0) > 0)
const overrideJavaArgs = ref((instance.value.extra_launch_args?.length ?? 0) > 0)
const javaArgs = ref(
(props.instance.extra_launch_args ?? globalSettings.extra_launch_args).join(' '),
(instance.value.extra_launch_args ?? globalSettings.extra_launch_args).join(' '),
)
const overrideEnvVars = ref((props.instance.custom_env_vars?.length ?? 0) > 0)
const overrideEnvVars = ref((instance.value.custom_env_vars?.length ?? 0) > 0)
const envVars = ref(
(props.instance.custom_env_vars ?? globalSettings.custom_env_vars)
(instance.value.custom_env_vars ?? globalSettings.custom_env_vars)
.map((x) => x.join('='))
.join(' '),
)
const overrideMemorySettings = ref(!!props.instance.memory)
const memory = ref(props.instance.memory ?? globalSettings.memory)
const overrideMemorySettings = ref(!!instance.value.memory)
const memory = ref(instance.value.memory ?? globalSettings.memory)
const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) as unknown as {
maxMemory: number
snapPoints: number[]
@@ -79,7 +80,7 @@ watch(
memory,
],
async () => {
await edit(props.instance.path, editProfileObject.value)
await edit(instance.value.path, editProfileObject.value)
},
{ deep: true },
)
@@ -110,10 +111,10 @@ const messages = defineMessages({
<template>
<div>
<h2 id="project-name" class="m-0 mb-1 text-lg font-extrabold text-contrast block">
<h2 id="project-name" class="m-0 mb-2.5 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.javaInstallation) }}
</h2>
<Checkbox v-model="overrideJavaInstall" label="Custom Java installation" class="mb-2" />
<Checkbox v-model="overrideJavaInstall" label="Custom Java installation" class="mb-2.5" />
<template v-if="!overrideJavaInstall">
<div class="flex my-2 items-center gap-2 font-semibold">
<template v-if="javaInstall">
@@ -143,10 +144,10 @@ const messages = defineMessages({
</div>
</template>
<JavaSelector v-if="overrideJavaInstall || !javaInstall" v-model="javaInstall" />
<h2 id="project-name" class="mt-4 mb-1 text-lg font-extrabold text-contrast block">
<h2 id="project-name" class="mt-6 mb-2.5 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.javaMemory) }}
</h2>
<Checkbox v-model="overrideMemorySettings" label="Custom memory allocation" class="mb-2" />
<Checkbox v-model="overrideMemorySettings" label="Custom memory allocation" class="mb-2.5" />
<Slider
id="max-memory"
v-model="memory.maximum"
@@ -158,7 +159,7 @@ const messages = defineMessages({
:snap-range="512"
unit="MB"
/>
<h2 id="project-name" class="mt-4 mb-1 text-lg font-extrabold text-contrast block">
<h2 id="project-name" class="mt-6 mb-2.5 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.javaArguments) }}
</h2>
<Checkbox v-model="overrideJavaArgs" label="Custom java arguments" class="my-2" />
@@ -170,10 +171,10 @@ const messages = defineMessages({
placeholder="Enter java arguments..."
wrapper-class="w-full"
/>
<h2 id="project-name" class="mt-4 mb-1 text-lg font-extrabold text-contrast block">
<h2 id="project-name" class="mt-6 mb-2.5 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.javaEnvironmentVariables) }}
</h2>
<Checkbox v-model="overrideEnvVars" label="Custom environment variables" class="mb-2" />
<Checkbox v-model="overrideEnvVars" label="Custom environment variables" class="mb-2.5" />
<StyledInput
id="env-vars"
v-model="envVars"
@@ -11,24 +11,25 @@ import { computed, type Ref, ref, watch } from 'vue'
import { edit } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { AppSettings, InstanceSettingsTabProps } from '../../../helpers/types'
import type { AppSettings } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const { instance } = injectInstanceSettings()
const globalSettings = (await get().catch(handleError)) as AppSettings
const overrideWindowSettings = ref(
!!props.instance.game_resolution || !!props.instance.force_fullscreen,
!!instance.value.game_resolution || !!instance.value.force_fullscreen,
)
const resolution: Ref<[number, number]> = ref(
props.instance.game_resolution ?? (globalSettings.game_resolution.slice() as [number, number]),
instance.value.game_resolution ?? (globalSettings.game_resolution.slice() as [number, number]),
)
const fullscreenSetting: Ref<boolean> = ref(
props.instance.force_fullscreen ?? globalSettings.force_fullscreen,
instance.value.force_fullscreen ?? globalSettings.force_fullscreen,
)
const editProfileObject = computed(() => {
@@ -47,7 +48,7 @@ const editProfileObject = computed(() => {
watch(
[overrideWindowSettings, resolution, fullscreenSetting],
async () => {
await edit(props.instance.path, editProfileObject.value)
await edit(instance.value.path, editProfileObject.value)
},
{ deep: true },
)
@@ -93,14 +94,14 @@ const messages = defineMessages({
</script>
<template>
<div>
<div class="flex flex-col gap-6">
<Checkbox
v-model="overrideWindowSettings"
:label="formatMessage(messages.customWindowSettings)"
/>
<div class="mt-2 flex items-center gap-4 justify-between">
<div>
<h2 class="m-0 mb-1 text-lg font-extrabold text-contrast">
<div class="flex items-center gap-4 justify-between">
<div class="flex flex-col gap-1">
<h2 class="m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.fullscreen) }}
</h2>
<p class="m-0">
@@ -119,9 +120,9 @@ const messages = defineMessages({
/>
</div>
<div class="mt-4 flex items-center gap-4 justify-between">
<div>
<h2 class="m-0 mb-1 text-lg font-extrabold text-contrast">
<div class="flex items-center gap-4 justify-between">
<div class="flex flex-col gap-1">
<h2 class="m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.width) }}
</h2>
<p class="m-0">
@@ -138,9 +139,9 @@ const messages = defineMessages({
/>
</div>
<div class="mt-4 flex items-center gap-4 justify-between">
<div>
<h2 class="m-0 mb-1 text-lg font-extrabold text-contrast">
<div class="flex items-center gap-4 justify-between">
<div class="flex flex-col gap-1">
<h2 class="m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.height) }}
</h2>
<p class="m-0">
@@ -6,12 +6,13 @@ import {
LanguagesIcon,
ModrinthIcon,
PaintbrushIcon,
ReportIcon,
SettingsIcon,
ShieldIcon,
ToggleRightIcon,
} from '@modrinth/assets'
import {
commonMessages,
commonSettingsMessages,
defineMessage,
defineMessages,
ProgressBar,
@@ -20,9 +21,8 @@ import {
} from '@modrinth/ui'
import { getVersion } from '@tauri-apps/api/app'
import { platform as getOsPlatform, version as getOsVersion } from '@tauri-apps/plugin-os'
import { computed, ref, watch } from 'vue'
import { ref, watch } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import AppearanceSettings from '@/components/ui/settings/AppearanceSettings.vue'
import DefaultInstanceSettings from '@/components/ui/settings/DefaultInstanceSettings.vue'
import FeatureFlagSettings from '@/components/ui/settings/FeatureFlagSettings.vue'
@@ -96,25 +96,20 @@ const tabs = [
content: ResourceManagementSettings,
},
{
name: defineMessage({
id: 'app.settings.tabs.feature-flags',
defaultMessage: 'Feature flags',
}),
icon: ReportIcon,
name: commonSettingsMessages.featureFlags,
icon: ToggleRightIcon,
content: FeatureFlagSettings,
developerOnly: true,
},
]
const modal = ref()
const modal = ref<InstanceType<typeof TabbedModal> | null>(null)
function show() {
modal.value.show()
modal.value?.show()
}
const isOpen = computed(() => modal.value?.isOpen)
defineExpose({ show, isOpen })
defineExpose({ show })
const { progress, version: downloadingVersion } = injectAppUpdateDownloadProgress()
@@ -138,8 +133,8 @@ function devModeCount() {
settings.value.developer_mode = !!themeStore.devMode
devModeCounter.value = 0
if (!themeStore.devMode && tabs[modal.value.selectedTab].developerOnly) {
modal.value.setTab(0)
if (!themeStore.devMode && tabs[modal.value!.selectedTab].developerOnly) {
modal.value!.setTab(0)
}
}
}
@@ -152,49 +147,46 @@ const messages = defineMessages({
})
</script>
<template>
<ModalWrapper ref="modal">
<TabbedModal ref="modal" :tabs="tabs.filter((t) => !t.developerOnly || themeStore.devMode)">
<template #title>
<span class="flex items-center gap-2 text-lg font-extrabold text-contrast">
<SettingsIcon /> Settings
</span>
</template>
<TabbedModal :tabs="tabs.filter((t) => !t.developerOnly || themeStore.devMode)">
<template #footer>
<div class="mt-auto text-secondary text-sm">
<div class="mb-3">
<template v-if="progress > 0 && progress < 1">
<p class="m-0 mb-2">
{{ formatMessage(messages.downloading, { version: downloadingVersion }) }}
</p>
<ProgressBar :progress="progress" />
</template>
</div>
<p v-if="themeStore.devMode" class="text-brand font-semibold m-0 mb-2">
{{ formatMessage(developerModeEnabled) }}
</p>
<div class="flex items-center gap-3">
<button
class="p-0 m-0 bg-transparent border-none cursor-pointer button-animation"
:class="{
'text-brand': themeStore.devMode,
'text-secondary': !themeStore.devMode,
}"
@click="devModeCount"
>
<ModrinthIcon class="w-6 h-6" />
</button>
<div>
<p class="m-0">Modrinth App {{ version }}</p>
<p class="m-0">
<span v-if="osPlatform === 'macos'">macOS</span>
<span v-else class="capitalize">{{ osPlatform }}</span>
{{ osVersion }}
</p>
</div>
<template #footer>
<div class="mt-auto text-secondary text-sm">
<div class="mb-3">
<template v-if="progress > 0 && progress < 1">
<p class="m-0 mb-2">
{{ formatMessage(messages.downloading, { version: downloadingVersion }) }}
</p>
<ProgressBar :progress="progress" />
</template>
</div>
<p v-if="themeStore.devMode" class="text-brand font-semibold m-0 mb-2">
{{ formatMessage(developerModeEnabled) }}
</p>
<div class="flex items-center gap-3">
<button
class="p-0 m-0 bg-transparent border-none cursor-pointer button-animation"
:class="{
'text-brand': themeStore.devMode,
'text-secondary': !themeStore.devMode,
}"
@click="devModeCount"
>
<ModrinthIcon class="w-6 h-6" />
</button>
<div class="max-w-[200px]">
<p class="m-0">Modrinth App {{ version }}</p>
<p class="m-0">
<span v-if="osPlatform === 'macos'">macOS</span>
<span v-else class="capitalize">{{ osPlatform }}</span>
{{ osVersion }}
</p>
</div>
</div>
</template>
</TabbedModal>
</ModalWrapper>
</div>
</template>
</TabbedModal>
</template>
@@ -0,0 +1,78 @@
<template>
<NewModal ref="modal" :header="formatMessage(messages.header)" fade="danger" max-width="500px">
<Admonition type="critical" :header="formatMessage(messages.admonitionHeader)">
{{ formatMessage(messages.admonitionBody) }}
</Admonition>
<template #actions>
<div class="flex gap-2 justify-end">
<ButtonStyled type="outlined">
<button class="!border !border-surface-4" @click="modal?.hide()">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="red">
<button @click="confirm">
<TrashIcon />
{{ formatMessage(messages.deleteButton) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
</template>
<script setup lang="ts">
import { TrashIcon, XIcon } from '@modrinth/assets'
import {
Admonition,
ButtonStyled,
commonMessages,
defineMessages,
NewModal,
useVIntl,
} from '@modrinth/ui'
import { ref } from 'vue'
const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'app.instance.confirm-delete.header',
defaultMessage: 'Delete instance',
},
admonitionHeader: {
id: 'app.instance.confirm-delete.admonition-header',
defaultMessage: 'This action cannot be undone',
},
admonitionBody: {
id: 'app.instance.confirm-delete.admonition-body',
defaultMessage:
'All data for your instance will be permanently deleted, including your worlds, configs, and all installed content.',
},
deleteButton: {
id: 'app.instance.confirm-delete.delete-button',
defaultMessage: 'Delete instance',
},
})
const emit = defineEmits<{
(e: 'delete'): void
}>()
const modal = ref<InstanceType<typeof NewModal>>()
function show() {
modal.value?.show()
}
function confirm() {
modal.value?.hide()
emit('delete')
}
defineExpose({
show,
})
</script>
@@ -1,13 +1,9 @@
<!-- @deprecated Use ConfirmModal from @modrinth/ui directly. Ads/noblur now handled by injectModalBehavior. -->
<script setup lang="ts">
import { ConfirmModal } from '@modrinth/ui'
import { useTemplateRef } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
import { useTheming } from '@/store/theme.ts'
const themeStore = useTheming()
const props = defineProps({
defineProps({
confirmationText: {
type: String,
default: '',
@@ -38,6 +34,7 @@ const props = defineProps({
type: Boolean,
default: true,
},
/** @deprecated No longer used — ads are handled by provideModalBehavior */
showAdOnClose: {
type: Boolean,
default: true,
@@ -53,21 +50,13 @@ const modal = useTemplateRef('modal')
defineExpose({
show: () => {
hide_ads_window()
modal.value?.show()
},
hide: () => {
onModalHide()
modal.value?.hide()
},
})
function onModalHide() {
if (props.showAdOnClose) {
show_ads_window()
}
}
function proceed() {
emit('proceed')
}
@@ -82,8 +71,6 @@ function proceed() {
:description="description"
:proceed-icon="proceedIcon"
:proceed-label="proceedLabel"
:on-hide="onModalHide"
:noblur="!themeStore.advancedRendering"
:danger="danger"
:markdown="markdown"
@proceed="proceed"
@@ -73,6 +73,7 @@
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import { DownloadIcon, EyeIcon, XIcon } from '@modrinth/assets'
import type { ContentItem } from '@modrinth/ui'
import {
Admonition,
Avatar,
@@ -88,9 +89,7 @@ import { computed, ref } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads'
import { get_project, get_project_many, get_version, get_version_many } from '@/helpers/cache.js'
import { installServerProject, useInstall } from '@/store/install.js'
import type { ContentItem } from '../../../../../../packages/ui/src/components/instances/types'
import { injectServerInstall } from '@/providers/server-install'
const modal = ref<InstanceType<typeof NewModal>>()
const modpackVersionId = ref<string | null>(null)
@@ -99,7 +98,7 @@ const project = ref<Labrinth.Projects.v3.Project | null>(null)
const requiredContentProject = ref<Labrinth.Projects.v2.Project | null>(null)
const onInstallComplete = ref<() => void>(() => {})
const { formatMessage } = useVIntl()
const installStore = useInstall()
const { installServerProject, startInstallingServer, stopInstallingServer } = injectServerInstall()
const usingCustomModpack = computed(() => {
return requiredContentProject.value?.id === project.value?.id
@@ -125,14 +124,14 @@ async function fetchData(versionId: string) {
async function handleAccept() {
hide()
const serverProjectId = project.value?.id
installStore.startInstallingServer(serverProjectId)
startInstallingServer(serverProjectId)
try {
await installServerProject(serverProjectId)
onInstallComplete.value()
} catch (error) {
console.error('Failed to install server project from InstallToPlayModal:', error)
} finally {
installStore.stopInstallingServer(serverProjectId)
stopInstallingServer(serverProjectId)
}
}
@@ -16,22 +16,27 @@ import {
type TabbedModalTab,
useVIntl,
} from '@modrinth/ui'
import { useQueryClient } from '@tanstack/vue-query'
import { convertFileSrc } from '@tauri-apps/api/core'
import { computed, ref, watch } from 'vue'
import { computed, nextTick, ref, watch } from 'vue'
import GeneralSettings from '@/components/ui/instance_settings/GeneralSettings.vue'
import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
import InstallationSettings from '@/components/ui/instance_settings/InstallationSettings.vue'
import JavaSettings from '@/components/ui/instance_settings/JavaSettings.vue'
import WindowSettings from '@/components/ui/instance_settings/WindowSettings.vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { get_project_v3 } from '@/helpers/cache'
import { get_linked_modpack_info } from '@/helpers/profile'
import { provideInstanceSettings } from '@/providers/instance-settings'
import type { InstanceSettingsTabProps } from '../../../helpers/types'
import type { GameInstance } from '../../../helpers/types'
const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const props = defineProps<{
instance: GameInstance
offline?: boolean
}>()
const emit = defineEmits<{
unlinked: []
}>()
@@ -39,6 +44,15 @@ const emit = defineEmits<{
const isMinecraftServer = ref(false)
const handleUnlinked = () => emit('unlinked')
const instanceRef = computed(() => props.instance)
provideInstanceSettings({
instance: instanceRef,
offline: props.offline,
isMinecraftServer,
onUnlinked: handleUnlinked,
})
watch(
() => props.instance,
(instance) => {
@@ -56,7 +70,7 @@ watch(
{ immediate: true },
)
const tabs = computed<TabbedModalTab<InstanceSettingsTabProps>[]>(() => [
const tabs = computed<TabbedModalTab[]>(() => [
{
name: defineMessage({
id: 'instance.settings.tabs.general',
@@ -99,16 +113,31 @@ const tabs = computed<TabbedModalTab<InstanceSettingsTabProps>[]>(() => [
},
])
const modal = ref()
const queryClient = useQueryClient()
const tabbedModal = ref<InstanceType<typeof TabbedModal> | null>(null)
function show() {
modal.value.show()
function show(tabIndex?: number) {
if (props.instance.linked_data?.project_id) {
queryClient.prefetchQuery({
queryKey: ['linkedModpackInfo', props.instance.path],
queryFn: () => get_linked_modpack_info(props.instance.path, 'stale_while_revalidate'),
})
}
tabbedModal.value?.show()
if (tabIndex !== undefined) {
nextTick(() => tabbedModal.value?.setTab(tabIndex))
}
}
defineExpose({ show })
</script>
<template>
<ModalWrapper ref="modal">
<TabbedModal
ref="tabbedModal"
:tabs="tabs"
:max-width="'min(928px, calc(95vw - 10rem))'"
:width="'min(928px, calc(95vw - 10rem))'"
>
<template #title>
<span class="flex items-center gap-2 text-lg font-semibold text-primary">
<Avatar
@@ -122,18 +151,5 @@ defineExpose({ show })
}}</span>
</span>
</template>
<TabbedModal
:tabs="
tabs.map((tab) => ({
...tab,
props: {
...props,
isMinecraftServer,
onUnlinked: handleUnlinked,
},
}))
"
/>
</ModalWrapper>
</TabbedModal>
</template>
@@ -1,12 +1,8 @@
<!-- @deprecated Use NewModal from @modrinth/ui directly. Ads/noblur now handled by injectModalBehavior. -->
<script setup lang="ts">
import { NewModal as Modal } from '@modrinth/ui'
import { useTemplateRef } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
import { useTheming } from '@/store/theme.ts'
const themeStore = useTheming()
const props = defineProps({
header: {
type: String,
@@ -26,6 +22,7 @@ const props = defineProps({
return () => {}
},
},
/** @deprecated No longer used — ads are handled by provideModalBehavior */
showAdOnClose: {
type: Boolean,
default: true,
@@ -35,31 +32,21 @@ const modal = useTemplateRef('modal')
defineExpose({
show: (e: MouseEvent) => {
hide_ads_window()
modal.value?.show(e)
},
hide: () => {
onModalHide()
modal.value?.hide()
},
})
function onModalHide() {
if (props.showAdOnClose) {
show_ads_window()
}
props.onHide?.()
}
</script>
<template>
<Modal
ref="modal"
:header="header"
:noblur="!themeStore.advancedRendering"
:closable="closable"
:hide-header="hideHeader"
@hide="onModalHide"
:on-hide="() => props.onHide?.()"
>
<template #title>
<slot name="title" />
@@ -0,0 +1,102 @@
<template>
<NewModal ref="modal" :header="formatMessage(messages.header)" fade="warning" max-width="500px">
<p class="m-0 text-secondary">
<IntlFormatted :message-id="messages.body" :values="{ instanceName }">
<template #bold="{ children }">
<span class="font-medium text-contrast"><component :is="() => children" /></span>
</template>
</IntlFormatted>
</p>
<template #actions>
<div class="flex gap-2 justify-end">
<ButtonStyled type="outlined">
<button class="!border !border-surface-4" @click="handleCancel">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled>
<button @click="handleGoToInstance">
{{ formatMessage(messages.instance) }}
<RightArrowIcon />
</button>
</ButtonStyled>
<ButtonStyled color="orange">
<button @click="handleCreateAnyway">
<PlusIcon />
{{ formatMessage(messages.create) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
</template>
<script setup lang="ts">
import { PlusIcon, RightArrowIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
commonMessages,
defineMessages,
IntlFormatted,
NewModal,
useVIntl,
} from '@modrinth/ui'
import { ref } from 'vue'
const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'app.instance.modpack-already-installed.header',
defaultMessage: 'Modpack already installed',
},
body: {
id: 'app.instance.modpack-already-installed.body',
defaultMessage:
'This modpack is already installed in the <bold>{instanceName}</bold> instance. Are you sure you want to duplicate it?',
},
instance: {
id: 'app.instance.modpack-already-installed.instance',
defaultMessage: 'Instance',
},
create: {
id: 'app.instance.modpack-already-installed.create',
defaultMessage: 'Create',
},
})
const emit = defineEmits<{
(e: 'go-to-instance', instancePath: string): void
(e: 'create-anyway'): void
}>()
const modal = ref<InstanceType<typeof NewModal>>()
const instanceName = ref('')
const instancePath = ref('')
function show(name: string, path: string) {
instanceName.value = name
instancePath.value = path
modal.value?.show()
}
function handleCancel() {
modal.value?.hide()
}
function handleGoToInstance() {
modal.value?.hide()
emit('go-to-instance', instancePath.value)
}
function handleCreateAnyway() {
modal.value?.hide()
emit('create-anyway')
}
defineExpose({
show,
})
</script>
@@ -1,12 +1,8 @@
<!-- @deprecated Use ShareModal from @modrinth/ui directly. Ads/noblur now handled by injectModalBehavior. -->
<script setup lang="ts">
import { ShareModal } from '@modrinth/ui'
import { ref } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
import { useTheming } from '@/store/theme.ts'
const themeStore = useTheming()
defineProps({
header: {
type: String,
@@ -34,18 +30,12 @@ const modal = ref(null)
defineExpose({
show: (passedContent) => {
hide_ads_window()
modal.value.show(passedContent)
},
hide: () => {
onModalHide()
modal.value.hide()
},
})
function onModalHide() {
show_ads_window()
}
</script>
<template>
@@ -56,7 +46,5 @@ function onModalHide() {
:share-text="shareText"
:link="link"
:open-in-new-tab="openInNewTab"
:on-hide="onModalHide"
:noblur="!themeStore.advancedRendering"
/>
</template>
@@ -1,153 +1,39 @@
<template>
<NewModal
ref="modal"
<ContentDiffModal
ref="diffModal"
:header="formatMessage(messages.updateToPlay)"
:closable="true"
no-padding
@hide="() => show_ads_window()"
>
<div v-if="instance" class="max-w-[500px]">
<div class="flex flex-col gap-4 p-4">
<Admonition type="info" :header="formatMessage(messages.updateRequired)">
{{ formatMessage(messages.updateRequiredDescription, { name: instance.name }) }}
</Admonition>
<div v-if="diffs.length" class="flex flex-col gap-2">
<span v-if="publishedDate" class="text-contrast font-semibold">{{
formatDate(publishedDate)
}}</span>
<div class="flex gap-2">
<div v-if="removedCount" class="flex gap-1 items-center">
<MinusIcon />
{{ formatMessage(messages.removedCount, { count: removedCount }) }}
</div>
<div v-if="addedCount" class="flex gap-1 items-center">
<PlusIcon />
{{ formatMessage(messages.addedCount, { count: addedCount }) }}
</div>
<div v-if="updatedCount" class="flex gap-1 items-center">
<RefreshCwIcon />
{{ formatMessage(messages.updatedCount, { count: updatedCount }) }}
</div>
</div>
</div>
</div>
<div
v-if="diffs.length"
class="flex flex-col bg-surface-2 p-4 max-h-[272px] overflow-y-auto border-t border-b border-r-0 border-l-0 border-solid border-surface-5"
>
<div
v-for="(diff, index) in diffs"
:key="diff.project_id"
class="grid items-center min-h-10 h-10 gap-2"
:class="diff.project?.title ? 'grid-cols-[auto_1fr_1fr_1fr]' : 'grid-cols-[auto_1fr_1fr]'"
>
<div class="flex flex-col justify-between items-center">
<div class="w-[1px] h-2"></div>
<PlusIcon v-if="diff.type === 'added'" />
<MinusIcon v-else-if="diff.type === 'removed'" />
<RefreshCwIcon v-else />
<div
:class="index === diffs.length - 1 ? 'bg-transparent' : 'bg-surface-5'"
class="w-[1px] h-2 relative top-1"
></div>
</div>
<div class="flex gap-1 col-span-2">
<span class="text-sm">{{ formatMessage(diffTypeMessages[diff.type]) }}</span>
<span
v-if="diff.project"
v-tooltip="diff.project.title"
class="text-sm text-contrast font-medium truncate"
>
{{ diff.project.title }}
</span>
<span
v-else-if="diff.fileName"
v-tooltip="diff.fileName"
class="text-sm text-contrast font-medium truncate"
>
{{ decodeURIComponent(diff.fileName) }}
</span>
</div>
<span
v-if="
diff.project?.title &&
(getFilename(diff.newVersion) || getFilename(diff.currentVersion) || diff.fileName)
"
v-tooltip="
getFilename(diff.newVersion) ||
getFilename(diff.currentVersion) ||
decodeURIComponent(diff.fileName || '')
"
class="text-xs truncate text-right"
>
{{
getFilename(diff.newVersion) ||
getFilename(diff.currentVersion) ||
decodeURIComponent(diff.fileName || '')
}}
</span>
</div>
</div>
</div>
<template #actions>
<div class="flex justify-between gap-2">
<ButtonStyled color="red" type="transparent">
<button @click="handleReport">
<ReportIcon />
{{ formatMessage(commonMessages.reportButton) }}
</button>
</ButtonStyled>
<div class="flex gap-2">
<ButtonStyled>
<button @click="handleDecline">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand">
<button @click="handleUpdate">
<DownloadIcon />
{{ formatMessage(commonMessages.updateButton) }}
</button>
</ButtonStyled>
</div>
</div>
</template>
</NewModal>
:admonition-header="formatMessage(messages.updateRequired)"
:description="
instance ? formatMessage(messages.updateRequiredDescription, { name: instance.name }) : ''
"
:diffs="normalizedDiffs"
:confirm-label="formatMessage(commonMessages.updateButton)"
:confirm-icon="DownloadIcon"
:show-report-button="true"
@confirm="handleUpdate"
@cancel="handleDecline"
@report="handleReport"
/>
</template>
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import { DownloadIcon } from '@modrinth/assets'
import {
DownloadIcon,
MinusIcon,
PlusIcon,
RefreshCwIcon,
ReportIcon,
XIcon,
} from '@modrinth/assets'
import {
Admonition,
ButtonStyled,
commonMessages,
type ContentDiffItem,
ContentDiffModal,
defineMessages,
NewModal,
useFormatDateTime,
useVIntl,
} from '@modrinth/ui'
import { openUrl } from '@tauri-apps/plugin-opener'
import dayjs from 'dayjs'
import { computed, ref, watch } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads'
import { get_project_many, get_version, get_version_many } from '@/helpers/cache.js'
import { update_managed_modrinth_version } from '@/helpers/profile'
import type { GameInstance } from '@/helpers/types'
import { useInstall } from '@/store/install.js'
import { injectServerInstall } from '@/providers/server-install'
type Dependency = Labrinth.Versions.v3.Dependency
type Version = Labrinth.Versions.v2.Version
@@ -187,28 +73,26 @@ type ProjectInfo = {
}
const { formatMessage } = useVIntl()
const formatDate = useFormatDateTime({ dateStyle: 'long' })
const installStore = useInstall()
const { startInstallingServer, stopInstallingServer } = injectServerInstall()
type UpdateCompleteCallback = () => void | Promise<void>
const modal = ref<InstanceType<typeof NewModal>>()
const diffModal = ref<InstanceType<typeof ContentDiffModal>>()
const instance = ref<GameInstance | null>(null)
const onUpdateComplete = ref<UpdateCompleteCallback>(() => {})
const diffs = ref<DependencyDiff[]>([])
const modpackVersionId = ref<string | null>(null)
const modpackVersion = ref<Version | null>(null)
const removedCount = computed(() => diffs.value.filter((d) => d.type === 'removed').length)
const addedCount = computed(() => diffs.value.filter((d) => d.type === 'added').length)
const updatedCount = computed(() => diffs.value.filter((d) => d.type === 'updated').length)
const publishedDate = computed(() =>
modpackVersion.value?.date_published ? new Date(modpackVersion.value.date_published) : null,
const normalizedDiffs = computed<ContentDiffItem[]>(() =>
diffs.value.map((diff) => ({
type: diff.type,
projectName: diff.project?.title,
fileName: diff.fileName,
currentVersionName: diff.currentVersion?.version_number,
newVersionName: diff.newVersion?.version_number,
})),
)
function getFilename(version?: Version): string | undefined {
return version?.files.find((f) => f.primary)?.filename
}
async function computeDependencyDiffs(
currentDeps: Dependency[],
latestDeps: Dependency[],
@@ -305,7 +189,7 @@ async function computeDependencyDiffs(
}
})
.sort((a, b) => {
const typeOrder = { removed: 0, added: 1, updated: 2 }
const typeOrder = { added: 0, updated: 1, removed: 2 }
const typeCompare = typeOrder[a.type] - typeOrder[b.type]
if (typeCompare !== 0) return typeCompare
@@ -355,7 +239,7 @@ watch(
async function handleUpdate() {
hide()
const serverProjectId = instance.value?.linked_data?.project_id
if (serverProjectId) installStore.startInstallingServer(serverProjectId)
if (serverProjectId) startInstallingServer(serverProjectId)
try {
if (modpackVersionId.value && instance.value) {
await update_managed_modrinth_version(instance.value.path, modpackVersionId.value)
@@ -364,7 +248,7 @@ async function handleUpdate() {
} catch (error) {
console.error('Error updating instance:', error)
} finally {
if (serverProjectId) installStore.stopInstallingServer(serverProjectId)
if (serverProjectId) stopInstallingServer(serverProjectId)
}
}
@@ -389,12 +273,11 @@ function show(
instance.value = instanceVal
modpackVersionId.value = modpackVersionIdVal
onUpdateComplete.value = callback
hide_ads_window()
modal.value?.show(e)
diffModal.value?.show(e)
}
function hide() {
modal.value?.hide()
diffModal.value?.hide()
}
const messages = defineMessages({
@@ -411,33 +294,6 @@ const messages = defineMessages({
defaultMessage:
'An update is required to play {name}. Please update to the latest version to launch the game.',
},
removedCount: {
id: 'app.modal.update-to-play.removed-count',
defaultMessage: '{count} removed',
},
addedCount: {
id: 'app.modal.update-to-play.added-count',
defaultMessage: '{count} added',
},
updatedCount: {
id: 'app.modal.update-to-play.updated-count',
defaultMessage: '{count} updated',
},
})
const diffTypeMessages = defineMessages({
added: {
id: 'app.modal.update-to-play.diff-type.added',
defaultMessage: 'Added',
},
removed: {
id: 'app.modal.update-to-play.diff-type.removed',
defaultMessage: 'Removed',
},
updated: {
id: 'app.modal.update-to-play.diff-type.updated',
defaultMessage: 'Updated',
},
})
const hasUpdate = computed(() => {
@@ -21,7 +21,7 @@ watch(
)
</script>
<template>
<h2 class="m-0 text-lg font-extrabold text-contrast">Color theme</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Color theme</h2>
<p class="m-0 mt-1">Select your preferred color theme for Modrinth App.</p>
<ThemeSelector
@@ -36,9 +36,9 @@ watch(
system-theme-color="system"
/>
<div class="mt-4 flex items-center justify-between">
<div class="mt-6 flex items-center justify-between">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Advanced rendering</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Advanced rendering</h2>
<p class="m-0 mt-1">
Enables advanced rendering such as blur effects that may cause performance issues without
hardware-accelerated rendering.
@@ -57,48 +57,48 @@ watch(
/>
</div>
<div class="mt-4 flex items-center justify-between">
<div class="mt-6 flex items-center justify-between">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Hide nametag</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Hide nametag</h2>
<p class="m-0 mt-1">Disables the nametag above your player on the skins page.</p>
</div>
<Toggle id="hide-nametag-skins-page" v-model="settings.hide_nametag_skins_page" />
</div>
<div v-if="os !== 'MacOS'" class="mt-4 flex items-center justify-between gap-4">
<div v-if="os !== 'MacOS'" class="mt-6 flex items-center justify-between gap-4">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Native decorations</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Native decorations</h2>
<p class="m-0 mt-1">Use system window frame (app restart required).</p>
</div>
<Toggle id="native-decorations" v-model="settings.native_decorations" />
</div>
<div class="mt-4 flex items-center justify-between">
<div class="mt-6 flex items-center justify-between">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Minimize launcher</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Minimize launcher</h2>
<p class="m-0 mt-1">Minimize the launcher when a Minecraft process starts.</p>
</div>
<Toggle id="minimize-launcher" v-model="settings.hide_on_process_start" />
</div>
<div class="mt-4 flex items-center justify-between">
<div class="mt-6 flex items-center justify-between">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Default landing page</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Default landing page</h2>
<p class="m-0 mt-1">Change the page to which the launcher opens on.</p>
</div>
<Combobox
id="opening-page"
v-model="settings.default_page"
name="Opening page dropdown"
class="w-40"
class="max-w-40"
:options="['Home', 'Library'].map((v) => ({ value: v, label: v }))"
:display-value="settings.default_page ?? 'Select an option'"
/>
</div>
<div class="mt-4 flex items-center justify-between">
<div class="mt-6 flex items-center justify-between">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Jump back into worlds</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Jump back into worlds</h2>
<p class="m-0 mt-1">Includes recent worlds in the "Jump back in" section on the Home page.</p>
</div>
<Toggle
@@ -113,9 +113,9 @@ watch(
/>
</div>
<div class="mt-4 flex items-center justify-between">
<div class="mt-6 flex items-center justify-between">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Toggle sidebar</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Toggle sidebar</h2>
<p class="m-0 mt-1">Enables the ability to toggle the sidebar.</p>
</div>
<Toggle
@@ -52,127 +52,135 @@ watch(
<template>
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Window size</h2>
<div class="flex flex-col gap-6">
<div class="flex items-center justify-between gap-4">
<div class="flex flex-col gap-1">
<h3 class="m-0 text-lg font-semibold text-contrast">Fullscreen</h3>
<p class="m-0 leading-tight">
Overwrites the options.txt file to start in full screen when launched.
</p>
</div>
<div class="flex items-center justify-between gap-4">
<div>
<h3 class="mt-2 m-0 text-base font-extrabold text-primary">Fullscreen</h3>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">
Overwrites the options.txt file to start in full screen when launched.
</p>
<Toggle id="fullscreen" v-model="settings.force_fullscreen" />
</div>
<Toggle id="fullscreen" v-model="settings.force_fullscreen" />
</div>
<div class="flex items-center justify-between gap-4">
<div class="flex flex-col gap-1">
<h3 class="m-0 text-lg font-semibold text-contrast">Width</h3>
<p class="m-0 leading-tight">The width of the game window when launched.</p>
</div>
<div class="flex items-center justify-between gap-4">
<div>
<h3 class="mt-2 m-0 text-base font-extrabold text-primary">Width</h3>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">
The width of the game window when launched.
</p>
<StyledInput
id="width"
v-model="settings.game_resolution[0]"
:disabled="settings.force_fullscreen"
autocomplete="off"
type="number"
placeholder="Enter width..."
/>
</div>
<StyledInput
id="width"
v-model="settings.game_resolution[0]"
:disabled="settings.force_fullscreen"
autocomplete="off"
type="number"
placeholder="Enter width..."
/>
<div class="flex items-center justify-between gap-4">
<div class="flex flex-col gap-1">
<h3 class="m-0 text-lg font-semibold text-contrast">Height</h3>
<p class="m-0 leading-tight">The height of the game window when launched.</p>
</div>
<StyledInput
id="height"
v-model="settings.game_resolution[1]"
:disabled="settings.force_fullscreen"
autocomplete="off"
type="number"
placeholder="Enter height..."
/>
</div>
</div>
<div class="flex items-center justify-between gap-4">
<div>
<h3 class="mt-2 m-0 text-base font-extrabold text-primary">Height</h3>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">
The height of the game window when launched.
</p>
<hr class="my-6 bg-button-border border-none h-[1px]" />
<div class="flex flex-col gap-6">
<div class="flex flex-col gap-2.5">
<h2 class="m-0 text-lg font-semibold text-contrast">Memory allocated</h2>
<Slider
id="max-memory"
v-model="settings.memory.maximum"
:min="512"
:max="maxMemory"
:step="64"
:snap-points="snapPoints"
:snap-range="512"
unit="MB"
/>
<p class="m-0 mt-1 leading-tight">The memory allocated to each instance when it is ran.</p>
</div>
<StyledInput
id="height"
v-model="settings.game_resolution[1]"
:disabled="settings.force_fullscreen"
autocomplete="off"
type="number"
placeholder="Enter height..."
/>
<div class="flex flex-col gap-2.5">
<h2 class="m-0 text-lg font-semibold text-contrast">Java arguments</h2>
<StyledInput
id="java-args"
v-model="settings.launchArgs"
autocomplete="off"
type="text"
placeholder="Enter java arguments..."
wrapper-class="w-full"
/>
</div>
<div class="flex flex-col gap-2.5">
<h2 class="m-0 text-lg font-semibold text-contrast">Environmental variables</h2>
<StyledInput
id="env-vars"
v-model="settings.envVars"
autocomplete="off"
type="text"
placeholder="Enter environmental variables..."
wrapper-class="w-full"
/>
</div>
</div>
<hr class="mt-4 bg-button-border border-none h-[1px]" />
<hr class="my-6 bg-button-border border-none h-[1px]" />
<h2 class="mt-4 m-0 text-lg font-extrabold text-contrast">Memory allocated</h2>
<p class="m-0 mt-1 leading-tight">The memory allocated to each instance when it is ran.</p>
<Slider
id="max-memory"
v-model="settings.memory.maximum"
:min="512"
:max="maxMemory"
:step="64"
:snap-points="snapPoints"
:snap-range="512"
unit="MB"
/>
<div class="flex flex-col gap-6">
<div class="flex flex-col gap-2.5">
<h3 class="m-0 text-lg font-semibold text-contrast">Pre launch hook</h3>
<StyledInput
id="pre-launch"
v-model="settings.hooks.pre_launch"
autocomplete="off"
type="text"
placeholder="Enter pre-launch command..."
wrapper-class="w-full"
/>
<p class="m-0 leading-tight">Ran before the instance is launched.</p>
</div>
<h2 class="mt-4 mb-2 text-lg font-extrabold text-contrast">Java arguments</h2>
<StyledInput
id="java-args"
v-model="settings.launchArgs"
autocomplete="off"
type="text"
placeholder="Enter java arguments..."
wrapper-class="w-full"
/>
<div class="flex flex-col gap-2.5">
<h3 class="m-0 text-lg font-semibold text-contrast">Wrapper hook</h3>
<StyledInput
id="wrapper"
v-model="settings.hooks.wrapper"
autocomplete="off"
type="text"
placeholder="Enter wrapper command..."
wrapper-class="w-full"
/>
<p class="m-0 leading-tight">Wrapper command for launching Minecraft.</p>
</div>
<h2 class="mt-4 mb-2 text-lg font-extrabold text-contrast">Environmental variables</h2>
<StyledInput
id="env-vars"
v-model="settings.envVars"
autocomplete="off"
type="text"
placeholder="Enter environmental variables..."
wrapper-class="w-full"
/>
<hr class="mt-4 bg-button-border border-none h-[1px]" />
<h2 class="mt-4 m-0 text-lg font-extrabold text-contrast">Hooks</h2>
<h3 class="mt-2 m-0 text-base font-extrabold text-primary">Pre launch</h3>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">Ran before the instance is launched.</p>
<StyledInput
id="pre-launch"
v-model="settings.hooks.pre_launch"
autocomplete="off"
type="text"
placeholder="Enter pre-launch command..."
wrapper-class="w-full"
/>
<h3 class="mt-2 m-0 text-base font-extrabold text-primary">Wrapper</h3>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">
Wrapper command for launching Minecraft.
</p>
<StyledInput
id="wrapper"
v-model="settings.hooks.wrapper"
autocomplete="off"
type="text"
placeholder="Enter wrapper command..."
wrapper-class="w-full"
/>
<h3 class="mt-2 m-0 text-base font-extrabold text-primary">Post exit</h3>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">Ran after the game closes.</p>
<StyledInput
id="post-exit"
v-model="settings.hooks.post_exit"
autocomplete="off"
type="text"
placeholder="Enter post-exit command..."
wrapper-class="w-full"
/>
<div class="flex flex-col gap-2.5">
<h3 class="m-0 text-lg font-semibold text-contrast">Post exit hook</h3>
<StyledInput
id="post-exit"
v-model="settings.hooks.post_exit"
autocomplete="off"
type="text"
placeholder="Enter post-exit command..."
wrapper-class="w-full"
/>
<p class="m-0 leading-tight">Ran after the game closes.</p>
</div>
</div>
</div>
</template>
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { Toggle } from '@modrinth/ui'
import { ButtonStyled, Toggle } from '@modrinth/ui'
import { ref, watch } from 'vue'
import { get as getSettings, set as setSettings } from '@/helpers/settings.ts'
@@ -25,17 +25,28 @@ watch(
)
</script>
<template>
<div v-for="option in options" :key="option" class="mt-4 flex items-center justify-between">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast capitalize">
{{ option.replaceAll('_', ' ') }}
</h2>
<div class="flex flex-col gap-2.5 min-w-[600px]">
<div v-for="option in options" :key="option" class="flex items-center justify-between">
<div>
<h2 class="m-0 text-lg font-semibold text-contrast capitalize">
{{ option.replaceAll('_', ' ') }}
</h2>
</div>
<div class="flex items-center gap-2">
<ButtonStyled type="transparent">
<button
:disabled="themeStore.getFeatureFlag(option) === DEFAULT_FEATURE_FLAGS[option]"
@click="setFeatureFlag(option, DEFAULT_FEATURE_FLAGS[option])"
>
Reset to default
</button>
</ButtonStyled>
<Toggle
id="advanced-rendering"
:model-value="themeStore.getFeatureFlag(option)"
@update:model-value="() => setFeatureFlag(option, !themeStore.getFeatureFlag(option))"
/>
</div>
</div>
<Toggle
id="advanced-rendering"
:model-value="themeStore.getFeatureFlag(option)"
@update:model-value="() => setFeatureFlag(option, !themeStore.getFeatureFlag(option))"
/>
</div>
</template>
@@ -21,15 +21,21 @@ async function updateJavaVersion(version) {
}
</script>
<template>
<div v-for="(javaVersion, index) in [25, 21, 17, 8]" :key="`java-${javaVersion}`">
<h2 class="m-0 text-lg font-extrabold text-contrast" :class="{ 'mt-4': index !== 0 }">
Java {{ javaVersion }} location
</h2>
<JavaSelector
:id="'java-selector-' + javaVersion"
v-model="javaVersions[javaVersion]"
:version="javaVersion"
@update:model-value="updateJavaVersion"
/>
<div class="flex flex-col gap-6">
<div
v-for="(javaVersion, index) in [25, 21, 17, 8]"
:key="`java-${javaVersion}`"
class="flex flex-col gap-2.5"
>
<h2 class="m-0 text-lg font-semibold text-contrast" :class="{ 'mt-4': index !== 0 }">
Java {{ javaVersion }} location
</h2>
<JavaSelector
:id="'java-selector-' + javaVersion"
v-model="javaVersions[javaVersion]"
:version="javaVersion"
@update:model-value="updateJavaVersion"
/>
</div>
</div>
</template>
@@ -43,7 +43,7 @@ async function onLocaleChange(newLocale: string) {
</script>
<template>
<h2 class="m-0 text-lg font-extrabold text-contrast">Language</h2>
<h2 class="m-0 text-lg font-semibold text-contrast">Language</h2>
<Admonition type="warning" class="mt-2 mb-4">
{{ formatMessage(languageSelectorMessages.languageWarning, { platform }) }}
@@ -25,8 +25,8 @@ watch(
<template>
<div class="flex items-center justify-between gap-4">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Personalized ads</h2>
<p class="m-0 text-sm">
<h2 class="m-0 text-lg font-semibold text-contrast">Personalized ads</h2>
<p class="m-0 mt-1 text-sm">
Modrinth's ad provider, Aditude, shows ads based on your preferences. By disabling this
option, you opt out and ads will no longer be shown based on your interests.
</p>
@@ -36,8 +36,8 @@ watch(
<div class="mt-4 flex items-center justify-between gap-4">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Telemetry</h2>
<p class="m-0 text-sm">
<h2 class="m-0 text-lg font-semibold text-contrast">Telemetry</h2>
<p class="m-0 mt-1 text-sm">
Modrinth collects anonymized analytics and usage data to improve our user experience and
customize your experience. By disabling this option, you opt out and your data will no
longer be collected.
@@ -48,8 +48,8 @@ watch(
<div class="mt-4 flex items-center justify-between gap-4">
<div>
<h2 class="m-0 text-lg font-extrabold text-contrast">Discord RPC</h2>
<p class="m-0 text-sm">
<h2 class="m-0 text-lg font-semibold text-contrast">Discord RPC</h2>
<p class="m-0 mt-1 text-sm">
Manages the Discord Rich Presence integration. Disabling this will cause 'Modrinth' to no
longer show up as a game or app you are using on your Discord profile.
</p>
@@ -62,67 +62,77 @@ async function findLauncherDir() {
</script>
<template>
<h2 class="m-0 text-lg font-extrabold text-contrast">App directory</h2>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">
The directory where the launcher stores all of its files. Changes will be applied after
restarting the launcher.
</p>
<div class="flex flex-col gap-6">
<div class="flex flex-col gap-2.5">
<h2 class="m-0 text-lg font-semibold text-contrast">App directory</h2>
<StyledInput
id="appDir"
v-model="settings.custom_dir"
:icon="BoxIcon"
type="text"
wrapper-class="w-full"
>
<template #right>
<Button class="ml-1.5" @click="findLauncherDir">
<FolderSearchIcon />
</Button>
</template>
</StyledInput>
<p class="m-0 leading-tight text-secondary">
The directory where the launcher stores all of its files. Changes will be applied after
restarting the launcher.
</p>
</div>
<div class="m-1 my-2">
<StyledInput
id="appDir"
v-model="settings.custom_dir"
:icon="BoxIcon"
type="text"
wrapper-class="w-full"
>
<template #right>
<Button class="r-btn" @click="findLauncherDir">
<FolderSearchIcon />
</Button>
</template>
</StyledInput>
<div class="flex flex-col gap-2.5">
<ConfirmModalWrapper
ref="purgeCacheConfirmModal"
title="Are you sure you want to purge the cache?"
description="If you proceed, your entire cache will be purged. This may slow down the app temporarily."
:has-to-type="false"
proceed-label="Purge cache"
:show-ad-on-close="false"
@proceed="purgeCache"
/>
<h2 class="m-0 text-lg font-semibold text-contrast">App cache</h2>
<button id="purge-cache" class="btn min-w-max" @click="$refs.purgeCacheConfirmModal.show()">
<TrashIcon />
Purge cache
</button>
<p class="m-0 leading-tight text-secondary">
The Modrinth app stores a cache of data to speed up loading. This can be purged to force the
app to reload data. This may slow down the app temporarily.
</p>
</div>
<div class="flex flex-col gap-2.5">
<h2 class="m-0 text-lg font-semibold text-contrast mt-4">Maximum concurrent downloads</h2>
<Slider
id="max-downloads"
v-model="settings.max_concurrent_downloads"
:min="1"
:max="10"
:step="1"
/>
<p class="m-0 leading-tight text-secondary">
The maximum amount of files the launcher can download at the same time. Set this to a lower
value if you have a poor internet connection. (app restart required to take effect)
</p>
</div>
<div class="flex flex-col gap-2.5">
<h2 class="mt-0 m-0 text-lg font-semibold text-contrast">Maximum concurrent writes</h2>
<Slider
id="max-writes"
v-model="settings.max_concurrent_writes"
:min="1"
:max="50"
:step="1"
/>
<p class="m-0 leading-tight text-secondary">
The maximum amount of files the launcher can write to the disk at once. Set this to a lower
value if you are frequently getting I/O errors. (app restart required to take effect)
</p>
</div>
</div>
<div>
<ConfirmModalWrapper
ref="purgeCacheConfirmModal"
title="Are you sure you want to purge the cache?"
description="If you proceed, your entire cache will be purged. This may slow down the app temporarily."
:has-to-type="false"
proceed-label="Purge cache"
:show-ad-on-close="false"
@proceed="purgeCache"
/>
<h2 class="m-0 text-lg font-extrabold text-contrast">App cache</h2>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">
The Modrinth app stores a cache of data to speed up loading. This can be purged to force the
app to reload data. This may slow down the app temporarily.
</p>
</div>
<button id="purge-cache" class="btn min-w-max" @click="$refs.purgeCacheConfirmModal.show()">
<TrashIcon />
Purge cache
</button>
<h2 class="m-0 text-lg font-extrabold text-contrast mt-4">Maximum concurrent downloads</h2>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">
The maximum amount of files the launcher can download at the same time. Set this to a lower
value if you have a poor internet connection. (app restart required to take effect)
</p>
<Slider
id="max-downloads"
v-model="settings.max_concurrent_downloads"
:min="1"
:max="10"
:step="1"
/>
<h2 class="mt-4 m-0 text-lg font-extrabold text-contrast">Maximum concurrent writes</h2>
<p class="m-0 mt-1 mb-2 leading-tight text-secondary">
The maximum amount of files the launcher can write to the disk at once. Set this to a lower
value if you are frequently getting I/O errors. (app restart required to take effect)
</p>
<Slider id="max-writes" v-model="settings.max_concurrent_writes" :min="1" :max="50" :step="1" />
</template>
@@ -79,7 +79,7 @@ watch([() => props.recentInstances, () => showWorlds.value], async () => {
})
})
populateJumpBackIn()
await populateJumpBackIn()
.catch(() => {
console.error('Failed to populate jump back in')
})
@@ -189,6 +189,22 @@ const messages = defineMessages({
id: 'instance.worlds.linked_server',
defaultMessage: 'Managed by server project',
},
incompatibleVersion: {
id: 'app.world.world-item.incompatible-version',
defaultMessage: 'Incompatible version {version}',
},
playersOnline: {
id: 'app.world.world-item.players-online',
defaultMessage: '{count} online',
},
offline: {
id: 'app.world.world-item.offline',
defaultMessage: 'Offline',
},
notPlayedYet: {
id: 'app.world.world-item.not-played-yet',
defaultMessage: 'Not played yet',
},
})
</script>
<template>
@@ -243,13 +259,17 @@ const messages = defineMessages({
>
<template v-if="refreshing">
<SpinnerIcon aria-hidden="true" class="animate-spin shrink-0" />
Loading...
{{ formatMessage(commonMessages.loadingLabel) }}
</template>
<template v-else-if="serverStatus">
<template v-if="serverIncompatible">
<IssuesIcon class="shrink-0 text-orange" aria-hidden="true" />
<span class="text-orange">
Incompatible version {{ serverStatus.version?.name }}
{{
formatMessage(messages.incompatibleVersion, {
version: serverStatus.version?.name,
})
}}
</span>
</template>
<template v-else>
@@ -265,8 +285,11 @@ const messages = defineMessages({
/>
<Tooltip :disabled="!hasPlayersTooltip">
<span :class="{ 'cursor-help': hasPlayersTooltip }">
{{ formatNumber(serverStatus.players?.online) }}
online
{{
formatMessage(messages.playersOnline, {
count: formatNumber(serverStatus.players?.online ?? 0),
})
}}
</span>
<template #popper>
<div class="flex flex-col gap-1">
@@ -280,7 +303,7 @@ const messages = defineMessages({
</template>
<template v-else>
<NoSignalIcon aria-hidden="true" stroke-width="3px" class="shrink-0" />
Offline
{{ formatMessage(messages.offline) }}
</template>
</div>
</div>
@@ -299,7 +322,7 @@ const messages = defineMessages({
})
}}
</template>
<template v-else> Not played yet </template>
<template v-else> {{ formatMessage(messages.notPlayedYet) }} </template>
</div>
<template v-if="instancePath">
@@ -5,12 +5,11 @@ import {
commonMessages,
defineMessages,
injectNotificationManager,
NewModal,
useVIntl,
} from '@modrinth/ui'
import { ref } from 'vue'
import InstanceModalTitlePrefix from '@/components/ui/modal/InstanceModalTitlePrefix.vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import ServerModalBody from '@/components/ui/world/modal/ServerModalBody.vue'
import type { GameInstance } from '@/helpers/types'
import { add_server_to_profile, type ServerPackStatus, type ServerWorld } from '@/helpers/worlds.ts'
@@ -26,10 +25,10 @@ const props = defineProps<{
instance: GameInstance
}>()
const modal = ref()
const modal = ref<InstanceType<typeof NewModal>>()
const name = ref()
const address = ref()
const name = ref('')
const address = ref('')
const resourcePack = ref<ServerPackStatus>('enabled')
async function addServer(play: boolean) {
@@ -60,11 +59,11 @@ function show() {
name.value = ''
address.value = ''
resourcePack.value = 'enabled'
modal.value.show()
modal.value?.show()
}
function hide() {
modal.value.hide()
modal.value?.hide()
}
const messages = defineMessages({
@@ -85,37 +84,33 @@ const messages = defineMessages({
defineExpose({ show, hide })
</script>
<template>
<ModalWrapper ref="modal">
<template #title>
<span class="flex items-center gap-2 text-lg font-semibold text-primary">
<InstanceModalTitlePrefix :instance="instance" />
<span class="font-extrabold text-contrast">{{ formatMessage(messages.title) }}</span>
</span>
</template>
<NewModal ref="modal" :header="formatMessage(messages.title)" width="500px" max-width="500px">
<ServerModalBody
v-model:name="name"
v-model:address="address"
v-model:resource-pack="resourcePack"
/>
<div class="flex gap-2 mt-4">
<ButtonStyled color="brand">
<button :disabled="!address" @click="addServer(true)">
<PlayIcon />
{{ formatMessage(messages.addAndPlay) }}
</button>
</ButtonStyled>
<ButtonStyled>
<button :disabled="!address" @click="addServer(false)">
<PlusIcon />
{{ formatMessage(messages.addServer) }}
</button>
</ButtonStyled>
<ButtonStyled>
<button @click="hide()">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
</div>
</ModalWrapper>
<template #actions>
<div class="flex gap-2 justify-end">
<ButtonStyled type="outlined">
<button class="!border !border-surface-4" @click="hide()">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled>
<button :disabled="!address" @click="addServer(false)">
<PlusIcon />
{{ formatMessage(messages.addServer) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand">
<button :disabled="!address" @click="addServer(true)">
<PlayIcon />
{{ formatMessage(messages.addAndPlay) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
</template>
@@ -5,11 +5,11 @@ import {
commonMessages,
defineMessage,
injectNotificationManager,
NewModal,
useVIntl,
} from '@modrinth/ui'
import { computed, ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import HideFromHomeOption from '@/components/ui/world/modal/HideFromHomeOption.vue'
import ServerModalBody from '@/components/ui/world/modal/ServerModalBody.vue'
import type { GameInstance } from '@/helpers/types'
@@ -32,7 +32,7 @@ const props = defineProps<{
instance: GameInstance
}>()
const modal = ref()
const modal = ref<InstanceType<typeof NewModal>>()
const name = ref<string>('')
const address = ref<string>('')
@@ -81,11 +81,11 @@ function show(server: ServerWorld) {
index.value = server.index
displayStatus.value = server.display_status
hideFromHome.value = server.display_status === 'hidden'
modal.value.show()
modal.value?.show()
}
function hide() {
modal.value.hide()
modal.value?.hide()
}
defineExpose({ show })
@@ -96,29 +96,28 @@ const titleMessage = defineMessage({
})
</script>
<template>
<ModalWrapper ref="modal">
<template #title>
<span class="font-extrabold text-lg text-contrast">{{ formatMessage(titleMessage) }}</span>
</template>
<NewModal ref="modal" :header="formatMessage(titleMessage)" width="500px" max-width="500px">
<ServerModalBody
v-model:name="name"
v-model:address="address"
v-model:resource-pack="resourcePack"
/>
<HideFromHomeOption v-model="hideFromHome" class="mt-3" />
<div class="flex gap-2 mt-4">
<ButtonStyled color="brand">
<button :disabled="!address" @click="saveServer">
<SaveIcon />
{{ formatMessage(commonMessages.saveChangesButton) }}
</button>
</ButtonStyled>
<ButtonStyled>
<button @click="hide()">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
</div>
</ModalWrapper>
<template #actions>
<div class="flex gap-2 justify-end">
<ButtonStyled type="outlined">
<button class="!border !border-surface-4" @click="hide()">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand">
<button :disabled="!address" @click="saveServer">
<SaveIcon />
{{ formatMessage(commonMessages.saveChangesButton) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
</template>
@@ -49,34 +49,40 @@ const messages = defineMessages({
id: 'instance.server-modal.placeholder-name',
defaultMessage: 'Minecraft Server',
},
placeholderAddress: {
id: 'app.world.server-modal.placeholder-address',
defaultMessage: 'example.modrinth.gg',
},
selectAnOption: {
id: 'app.world.server-modal.select-an-option',
defaultMessage: 'Select an option',
},
})
defineExpose({ resourcePackOptions })
</script>
<template>
<div class="w-[450px]">
<h2 class="text-lg font-extrabold text-contrast mt-0 mb-1">
{{ formatMessage(messages.name) }}
</h2>
<StyledInput
v-model="name"
:placeholder="formatMessage(messages.placeholderName)"
autocomplete="off"
wrapper-class="w-full"
/>
<h2 class="text-lg font-extrabold text-contrast mt-3 mb-1">
{{ formatMessage(messages.address) }}
</h2>
<StyledInput
v-model="address"
placeholder="example.modrinth.gg"
autocomplete="off"
wrapper-class="w-full"
/>
<h2 class="text-lg font-extrabold text-contrast mt-3 mb-1">
{{ formatMessage(messages.resourcePack) }}
</h2>
<div>
<div class="space-y-4 w-full">
<label class="flex flex-col gap-2">
<span class="font-semibold text-contrast">{{ formatMessage(messages.name) }}</span>
<StyledInput
v-model="name"
:placeholder="formatMessage(messages.placeholderName)"
autocomplete="off"
wrapper-class="w-full"
/>
</label>
<label class="flex flex-col gap-2">
<span class="font-semibold text-contrast">{{ formatMessage(messages.address) }}</span>
<StyledInput
v-model="address"
:placeholder="formatMessage(messages.placeholderAddress)"
autocomplete="off"
wrapper-class="w-full"
/>
</label>
<label class="flex flex-col gap-2">
<span class="font-semibold text-contrast">{{ formatMessage(messages.resourcePack) }}</span>
<Combobox
v-model="resourcePack"
:options="
@@ -89,9 +95,9 @@ defineExpose({ resourcePackOptions })
:display-value="
resourcePack
? formatMessage(resourcePackOptionMessages[resourcePack])
: 'Select an option'
: formatMessage(messages.selectAnOption)
"
/>
</div>
</label>
</div>
</template>
@@ -0,0 +1,99 @@
import { createConsoleState } from '@modrinth/ui'
import { clear_log_buffer, get_live_log_buffer, get_logs } from '@/helpers/logs'
type ConsoleState = ReturnType<typeof createConsoleState>
interface LogEntry {
filename: string
name?: string
log_type: string
stdout?: string
age?: number
live?: boolean
}
interface InstanceConsoleEntry {
liveConsole: ConsoleState
historicalConsole: ConsoleState
historicalCache: Map<string, string>
logList: LogEntry[] | null
}
const instances = new Map<string, InstanceConsoleEntry>()
function getOrCreate(profilePathId: string): InstanceConsoleEntry {
let entry = instances.get(profilePathId)
if (entry) return entry
entry = {
liveConsole: createConsoleState(),
historicalConsole: createConsoleState(),
historicalCache: new Map(),
logList: null,
}
instances.set(profilePathId, entry)
return entry
}
async function hydrate(profilePathId: string): Promise<void> {
const entry = getOrCreate(profilePathId)
if (entry.liveConsole.output.value.length > 0) return
const buffer = await get_live_log_buffer(profilePathId)
if (buffer) {
entry.liveConsole.addLegacyLog(buffer)
}
}
async function getHistoricalLogs(profilePathId: string, instancePath: string): Promise<LogEntry[]> {
const entry = getOrCreate(profilePathId)
if (entry.logList) return entry.logList
const logs: LogEntry[] = await get_logs(instancePath, false)
entry.logList = logs
for (const log of logs) {
if (log.stdout && log.stdout !== '') {
entry.historicalCache.set(log.filename, log.stdout)
}
}
return logs
}
function getHistoricalContent(profilePathId: string, filename: string): string | undefined {
return instances.get(profilePathId)?.historicalCache.get(filename)
}
function invalidate(profilePathId: string): void {
const entry = instances.get(profilePathId)
if (!entry) return
entry.historicalCache.clear()
entry.logList = null
}
async function clearLive(profilePathId: string): Promise<void> {
const entry = getOrCreate(profilePathId)
entry.liveConsole.clear()
await clear_log_buffer(profilePathId).catch(() => {})
}
async function destroy(profilePathId: string): Promise<void> {
instances.delete(profilePathId)
await clear_log_buffer(profilePathId).catch(() => {})
}
export function useInstanceConsole(profilePathId: string) {
const entry = getOrCreate(profilePathId)
return {
liveConsole: entry.liveConsole,
historicalConsole: entry.historicalConsole,
hydrate: () => hydrate(profilePathId),
getHistoricalLogs: (instancePath: string) => getHistoricalLogs(profilePathId, instancePath),
getHistoricalContent: (filename: string) => getHistoricalContent(profilePathId, filename),
invalidate: () => invalidate(profilePathId),
clearLive: () => clearLive(profilePathId),
destroy: () => destroy(profilePathId),
}
}
+18
View File
@@ -0,0 +1,18 @@
const trimTrailingSlash = (url: string) => url.replace(/\/$/, '')
const siteUrl = trimTrailingSlash(import.meta.env.MODRINTH_URL || 'https://modrinth.com')
const labrinthBaseUrl = trimTrailingSlash(
import.meta.env.MODRINTH_API_BASE_URL || 'https://api.modrinth.com',
)
const archonBaseUrl = trimTrailingSlash(
import.meta.env.MODRINTH_ARCHON_BASE_URL || 'https://archon.modrinth.com',
)
export const config = {
siteUrl,
stripePublishableKey:
import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY ||
'pk_test_51JbFxJJygY5LJFfKV50mnXzz3YLvBVe2Gd1jn7ljWAkaBlRz3VQdxN9mXcPSrFbSqxwAb0svte9yhnsmm7qHfcWn00R611Ce7b',
labrinthBaseUrl,
archonBaseUrl,
}
@@ -0,0 +1,35 @@
import { OverlayScrollbars, type PartialOptions } from 'overlayscrollbars'
import type { ObjectDirective } from 'vue'
const defaultOverlayScrollbarsOptions = Object.freeze<PartialOptions>({
scrollbars: {
theme: 'os-theme-dark',
autoHide: 'leave',
autoHideSuspend: true,
},
})
const mergeOptions = (options: PartialOptions = {}): PartialOptions => ({
...defaultOverlayScrollbarsOptions,
...options,
scrollbars: {
...defaultOverlayScrollbarsOptions.scrollbars,
...(options.scrollbars ?? {}),
},
})
export const overlayScrollbarsDirective: ObjectDirective<HTMLElement, PartialOptions | undefined> =
{
mounted(el, binding) {
OverlayScrollbars(el, mergeOptions(binding.value))
},
updated(el, binding) {
if (binding.value === binding.oldValue) return
const instance = OverlayScrollbars(el)
instance?.options(mergeOptions(binding.value))
},
unmounted(el) {
const instance = OverlayScrollbars(el)
instance?.destroy()
},
}
+14
View File
@@ -67,3 +67,17 @@ export async function get_search_results_v3_many(ids, cacheBehaviour) {
export async function purge_cache_types(cacheTypes) {
return await invoke('plugin:cache|purge_cache_types', { cacheTypes })
}
/**
* Get versions for a project (without changelogs for fast loading).
* Uses the cache system - versions are cached for 30 minutes.
* @param {string} projectId - The project ID
* @param {string} [cacheBehaviour] - Cache behaviour ('must_revalidate', etc.)
* @returns {Promise<Array|null>} Array of version objects (without changelogs) or null
*/
export async function get_project_versions(projectId, cacheBehaviour) {
return await invoke('plugin:cache|get_project_versions', {
projectId,
cacheBehaviour,
})
}
+20
View File
@@ -97,3 +97,23 @@ export async function warning_listener(callback) {
export async function friend_listener(callback) {
return await listen('friend', (event) => callback(event.payload))
}
/// Payload for the 'log' event
/*
LogPayload {
profile_path_id: string,
type: "log4j" | "legacy",
// log4j fields (when type === "log4j"):
timestamp_millis?: number,
logger_name?: string,
level?: string,
thread_name?: string,
message?: string,
throwable?: string,
// legacy fields (when type === "legacy"):
message?: string,
}
*/
export async function log_listener(callback) {
return await listen('log', (event) => callback(event.payload))
}
+10
View File
@@ -63,3 +63,13 @@ export async function delete_logs(profilePath) {
export async function get_latest_log_cursor(profilePath, cursor) {
return await invoke('plugin:logs|logs_get_latest_log_cursor', { profilePath, cursor })
}
/// Get all buffered live log lines for a profile from the Rust ring buffer
export async function get_live_log_buffer(profilePath) {
return await invoke('plugin:logs|logs_get_live_log_buffer', { profilePath })
}
/// Clear the live log buffer for a profile on the Rust side
export async function clear_log_buffer(profilePath) {
return await invoke('plugin:logs|logs_clear_live_log_buffer', { profilePath })
}
-65
View File
@@ -1,65 +0,0 @@
/**
* All theseus API calls return serialized values (both return values and errors);
* So, for example, addDefaultInstance creates a blank Profile object, where the Rust struct is serialized,
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
import { create } from './profile'
// Installs pack from a version ID
export async function create_profile_and_install(
projectId,
versionId,
packTitle,
iconUrl,
createInstanceCallback = () => {},
) {
const location = {
type: 'fromVersionId',
project_id: projectId,
version_id: versionId,
title: packTitle,
icon_url: iconUrl,
}
const profile_creator = await invoke('plugin:pack|pack_get_profile_from_pack', { location })
const profile = await create(
profile_creator.name,
profile_creator.gameVersion,
profile_creator.modloader,
profile_creator.loaderVersion,
null,
true,
)
createInstanceCallback(profile)
return await invoke('plugin:pack|pack_install', { location, profile })
}
export async function install_to_existing_profile(projectId, versionId, title, profilePath) {
const location = {
type: 'fromVersionId',
project_id: projectId,
version_id: versionId,
title,
}
return await invoke('plugin:pack|pack_install', { location, profile: profilePath })
}
// Installs pack from a path
export async function create_profile_and_install_from_file(path) {
const location = {
type: 'fromFile',
path: path,
}
const profile_creator = await invoke('plugin:pack|pack_get_profile_from_pack', { location })
const profile = await create(
profile_creator.name,
profile_creator.gameVersion,
profile_creator.modloader,
profile_creator.loaderVersion,
null,
true,
)
return await invoke('plugin:pack|pack_install', { location, profile })
}
+90
View File
@@ -0,0 +1,90 @@
import { invoke } from '@tauri-apps/api/core'
import { create } from './profile'
import type { InstanceLoader } from './types'
interface PackProfileCreator {
name: string
gameVersion: string
modloader: InstanceLoader
loaderVersion: string | null
}
interface PackLocationVersionId {
type: 'fromVersionId'
project_id: string
version_id: string
title: string
icon_url?: string
}
interface PackLocationFile {
type: 'fromFile'
path: string
}
export async function create_profile_and_install(
projectId: string,
versionId: string,
packTitle: string,
iconUrl?: string,
createInstanceCallback: (profile: string) => void = () => {},
): Promise<void> {
const location: PackLocationVersionId = {
type: 'fromVersionId',
project_id: projectId,
version_id: versionId,
title: packTitle,
icon_url: iconUrl,
}
const profile_creator = await invoke<PackProfileCreator>(
'plugin:pack|pack_get_profile_from_pack',
{ location },
)
const profile = await create(
profile_creator.name,
profile_creator.gameVersion,
profile_creator.modloader,
profile_creator.loaderVersion,
null,
true,
)
createInstanceCallback(profile)
return await invoke('plugin:pack|pack_install', { location, profile })
}
export async function install_to_existing_profile(
projectId: string,
versionId: string,
title: string,
profilePath: string,
): Promise<void> {
const location: PackLocationVersionId = {
type: 'fromVersionId',
project_id: projectId,
version_id: versionId,
title,
}
return await invoke('plugin:pack|pack_install', { location, profile: profilePath })
}
export async function create_profile_and_install_from_file(path: string): Promise<void> {
const location: PackLocationFile = {
type: 'fromFile',
path,
}
const profile_creator = await invoke<PackProfileCreator>(
'plugin:pack|pack_get_profile_from_pack',
{ location },
)
const profile = await create(
profile_creator.name,
profile_creator.gameVersion,
profile_creator.modloader,
profile_creator.loaderVersion,
null,
true,
)
return await invoke('plugin:pack|pack_install', { location, profile })
}
-216
View File
@@ -1,216 +0,0 @@
/**
* All theseus API calls return serialized values (both return values and errors);
* So, for example, addDefaultInstance creates a blank Profile object, where the Rust struct is serialized,
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
import { install_to_existing_profile } from '@/helpers/pack.js'
/// Add instance
/*
name: String, // the name of the profile, and relative path to create
game_version: String, // the game version of the profile
modloader: ModLoader, // the modloader to use
- ModLoader is an enum, with the following variants: Vanilla, Forge, Fabric, Quilt
loader_version: String, // the modloader version to use, set to "latest", "stable", or the ID of your chosen loader
icon: Path, // the icon for the profile
- icon is a path to an image file, which will be copied into the profile directory
*/
export async function create(
name,
gameVersion,
modloader,
loaderVersion,
icon,
skipInstall,
linkedData,
) {
//Trim string name to avoid "Unable to find directory"
name = name.trim()
return await invoke('plugin:profile-create|profile_create', {
name,
gameVersion,
modloader,
loaderVersion,
icon,
skipInstall,
linkedData,
})
}
// duplicate a profile
export async function duplicate(path) {
return await invoke('plugin:profile-create|profile_duplicate', { path })
}
// Remove a profile
export async function remove(path) {
return await invoke('plugin:profile|profile_remove', { path })
}
// Get a profile by path
// Returns a Profile
export async function get(path) {
return await invoke('plugin:profile|profile_get', { path })
}
export async function get_many(paths) {
return await invoke('plugin:profile|profile_get_many', { paths })
}
// Get a profile's projects
// Returns a map of a path to profile file
export async function get_projects(path, cacheBehaviour) {
return await invoke('plugin:profile|profile_get_projects', { path, cacheBehaviour })
}
// Get a profile's full fs path
// Returns a path
export async function get_full_path(path) {
return await invoke('plugin:profile|profile_get_full_path', { path })
}
// Get's a mod's full fs path
// Returns a path
export async function get_mod_full_path(path, projectPath) {
return await invoke('plugin:profile|profile_get_mod_full_path', { path, projectPath })
}
// Get optimal java version from profile
// Returns a java version
export async function get_optimal_jre_key(path) {
return await invoke('plugin:profile|profile_get_optimal_jre_key', { path })
}
// Get a copy of the profile set
// Returns hashmap of path -> Profile
export async function list() {
return await invoke('plugin:profile|profile_list')
}
export async function check_installed(path, projectId) {
return await invoke('plugin:profile|profile_check_installed', { path, projectId })
}
// Installs/Repairs a profile
export async function install(path, force) {
return await invoke('plugin:profile|profile_install', { path, force })
}
// Updates all of a profile's projects
export async function update_all(path) {
return await invoke('plugin:profile|profile_update_all', { path })
}
// Updates a specified project
export async function update_project(path, projectPath) {
return await invoke('plugin:profile|profile_update_project', { path, projectPath })
}
// Add a project to a profile from a version
// Returns a path to the new project file
export async function add_project_from_version(path, versionId) {
return await invoke('plugin:profile|profile_add_project_from_version', { path, versionId })
}
// Add a project to a profile from a path + project_type
// Returns a path to the new project file
export async function add_project_from_path(path, projectPath, projectType) {
return await invoke('plugin:profile|profile_add_project_from_path', {
path,
projectPath,
projectType,
})
}
// Toggle disabling a project
export async function toggle_disable_project(path, projectPath) {
return await invoke('plugin:profile|profile_toggle_disable_project', { path, projectPath })
}
// Remove a project
export async function remove_project(path, projectPath) {
return await invoke('plugin:profile|profile_remove_project', { path, projectPath })
}
// Update a managed Modrinth profile to a specific version
export async function update_managed_modrinth_version(path, versionId) {
return await invoke('plugin:profile|profile_update_managed_modrinth_version', {
path,
versionId,
})
}
// Repair a managed Modrinth profile
export async function update_repair_modrinth(path) {
return await invoke('plugin:profile|profile_repair_managed_modrinth', { path })
}
// Export a profile to .mrpack
/// included_overrides is an array of paths to override folders to include (ie: 'mods', 'resource_packs')
// Version id is optional (ie: 1.1.5)
export async function export_profile_mrpack(
path,
exportLocation,
includedOverrides,
versionId,
description,
name,
) {
return await invoke('plugin:profile|profile_export_mrpack', {
path,
exportLocation,
includedOverrides,
versionId,
description,
name,
})
}
// Given a folder path, populate an array of all the subfolders
// Intended to be used for finding potential override folders
// profile
// -- mods
// -- resourcepacks
// -- file1
// => [mods, resourcepacks]
// allows selection for 'included_overrides' in export_profile_mrpack
export async function get_pack_export_candidates(profilePath) {
return await invoke('plugin:profile|profile_get_pack_export_candidates', { profilePath })
}
// Run Minecraft using a pathed profile
// Returns PID of child
export async function run(path, serverAddress = null) {
return await invoke('plugin:profile|profile_run', { path, serverAddress })
}
export async function kill(path) {
return await invoke('plugin:profile|profile_kill', { path })
}
// Edits a profile
export async function edit(path, editProfile) {
return await invoke('plugin:profile|profile_edit', { path, editProfile })
}
// Edits a profile's icon
export async function edit_icon(path, iconPath) {
return await invoke('plugin:profile|profile_edit_icon', { path, iconPath })
}
export async function finish_install(instance) {
if (instance.install_stage !== 'pack_installed') {
let linkedData = instance.linked_data
await install_to_existing_profile(
linkedData.project_id,
linkedData.version_id,
instance.name,
instance.path,
)
} else {
await install(instance.path, false)
}
}
+298
View File
@@ -0,0 +1,298 @@
/**
* All theseus API calls return serialized values (both return values and errors);
* So, for example, addDefaultInstance creates a blank Profile object, where the Rust struct is serialized,
* and deserialized into a usable JS object.
*/
import type { Labrinth } from '@modrinth/api-client'
import type { ContentItem, ContentOwner } from '@modrinth/ui'
import { invoke } from '@tauri-apps/api/core'
import { install_to_existing_profile } from '@/helpers/pack'
import type {
CacheBehaviour,
ContentFile,
ContentFileProjectType,
GameInstance,
InstanceLoader,
} from './types'
// Add instance
/*
name: String, // the name of the profile, and relative path to create
game_version: String, // the game version of the profile
modloader: ModLoader, // the modloader to use
- ModLoader is an enum, with the following variants: Vanilla, Forge, Fabric, Quilt
loader_version: String, // the modloader version to use, set to "latest", "stable", or the ID of your chosen loader
icon: Path, // the icon for the profile
- icon is a path to an image file, which will be copied into the profile directory
*/
export async function create(
name: string,
gameVersion: string,
modloader: InstanceLoader,
loaderVersion: string | null,
icon: string | null,
skipInstall: boolean,
linkedData?: { project_id: string; version_id: string; locked: boolean } | null,
): Promise<string> {
// Trim string name to avoid "Unable to find directory"
name = name.trim()
return await invoke('plugin:profile-create|profile_create', {
name,
gameVersion,
modloader,
loaderVersion,
icon,
skipInstall,
linkedData,
})
}
// duplicate a profile
export async function duplicate(path: string): Promise<string> {
return await invoke('plugin:profile-create|profile_duplicate', { path })
}
// Remove a profile
export async function remove(path: string): Promise<void> {
return await invoke('plugin:profile|profile_remove', { path })
}
// Get a profile by path
// Returns a Profile
export async function get(path: string): Promise<GameInstance | null> {
return await invoke('plugin:profile|profile_get', { path })
}
export async function get_many(paths: string[]): Promise<GameInstance[]> {
return await invoke('plugin:profile|profile_get_many', { paths })
}
// Get a profile's projects
// Returns a map of a path to profile file
export async function get_projects(
path: string,
cacheBehaviour?: CacheBehaviour,
): Promise<Record<string, ContentFile>> {
return await invoke('plugin:profile|profile_get_projects', { path, cacheBehaviour })
}
// Get just the installed project IDs for a profile (lightweight, skips update checks)
export async function get_installed_project_ids(path: string): Promise<string[]> {
return await invoke('plugin:profile|profile_get_installed_project_ids', { path })
}
// Get content items with rich metadata for a profile
// Returns content items filtered to exclude modpack files (if linked),
// sorted alphabetically by project name
export async function get_content_items(
path: string,
cacheBehaviour?: CacheBehaviour,
): Promise<ContentItem[]> {
return await invoke('plugin:profile|profile_get_content_items', { path, cacheBehaviour })
}
// Linked modpack info returned from backend
export interface LinkedModpackInfo {
project: Labrinth.Projects.v2.Project
version: Labrinth.Versions.v2.Version
owner: ContentOwner | null
has_update: boolean
update_version_id: string | null
update_version: Labrinth.Versions.v2.Version | null
}
// Get linked modpack info for a profile
// Returns project, version, and owner information for the linked modpack,
// or null if the profile is not linked to a modpack
export async function get_linked_modpack_info(
path: string,
cacheBehaviour?: CacheBehaviour,
): Promise<LinkedModpackInfo | null> {
return await invoke('plugin:profile|profile_get_linked_modpack_info', { path, cacheBehaviour })
}
// Get content items that are part of the linked modpack
// Returns the modpack's dependencies as ContentItem list
// Returns empty array if the profile is not linked to a modpack
export async function get_linked_modpack_content(
path: string,
cacheBehaviour?: CacheBehaviour,
): Promise<ContentItem[]> {
return await invoke('plugin:profile|profile_get_linked_modpack_content', { path, cacheBehaviour })
}
// Convert a list of dependencies into ContentItems with rich metadata
export async function get_dependencies_as_content_items(
dependencies: Labrinth.Versions.v3.Dependency[],
cacheBehaviour?: CacheBehaviour,
): Promise<ContentItem[]> {
return await invoke('plugin:profile|profile_get_dependencies_as_content_items', {
dependencies,
cacheBehaviour,
})
}
// Get a profile's full fs path
// Returns a path
export async function get_full_path(path: string): Promise<string> {
return await invoke('plugin:profile|profile_get_full_path', { path })
}
// Get's a mod's full fs path
// Returns a path
export async function get_mod_full_path(path: string, projectPath: string): Promise<string> {
return await invoke('plugin:profile|profile_get_mod_full_path', { path, projectPath })
}
// Get optimal java version from profile
// Returns a java version
export async function get_optimal_jre_key(path: string): Promise<string | null> {
return await invoke('plugin:profile|profile_get_optimal_jre_key', { path })
}
// Get a copy of the profile set
// Returns hashmap of path -> Profile
export async function list(): Promise<GameInstance[]> {
return await invoke('plugin:profile|profile_list')
}
export async function check_installed(path: string, projectId: string): Promise<boolean> {
return await invoke('plugin:profile|profile_check_installed', { path, projectId })
}
export async function check_installed_batch(projectId: string): Promise<Record<string, boolean>> {
return await invoke('plugin:profile|profile_check_installed_batch', { projectId })
}
// Installs/Repairs a profile
export async function install(path: string, force: boolean): Promise<void> {
return await invoke('plugin:profile|profile_install', { path, force })
}
// Updates all of a profile's projects
export async function update_all(path: string): Promise<Record<string, string>> {
return await invoke('plugin:profile|profile_update_all', { path })
}
// Updates a specified project
export async function update_project(path: string, projectPath: string): Promise<string> {
return await invoke('plugin:profile|profile_update_project', { path, projectPath })
}
// Add a project to a profile from a version
// Returns a path to the new project file
export async function add_project_from_version(path: string, versionId: string): Promise<string> {
return await invoke('plugin:profile|profile_add_project_from_version', { path, versionId })
}
// Add a project to a profile from a path + project_type
// Returns a path to the new project file
export async function add_project_from_path(
path: string,
projectPath: string,
projectType?: ContentFileProjectType,
): Promise<string> {
return await invoke('plugin:profile|profile_add_project_from_path', {
path,
projectPath,
projectType,
})
}
// Toggle disabling a project
export async function toggle_disable_project(path: string, projectPath: string): Promise<string> {
return await invoke('plugin:profile|profile_toggle_disable_project', { path, projectPath })
}
// Remove a project
export async function remove_project(path: string, projectPath: string): Promise<void> {
return await invoke('plugin:profile|profile_remove_project', { path, projectPath })
}
// Update a managed Modrinth profile to a specific version
export async function update_managed_modrinth_version(
path: string,
versionId: string,
): Promise<void> {
return await invoke('plugin:profile|profile_update_managed_modrinth_version', {
path,
versionId,
})
}
// Repair a managed Modrinth profile
export async function update_repair_modrinth(path: string): Promise<void> {
return await invoke('plugin:profile|profile_repair_managed_modrinth', { path })
}
// Export a profile to .mrpack
// included_overrides is an array of paths to override folders to include (ie: 'mods', 'resource_packs')
// Version id is optional (ie: 1.1.5)
export async function export_profile_mrpack(
path: string,
exportLocation: string,
includedOverrides: string[],
versionId?: string,
description?: string,
name?: string,
): Promise<void> {
return await invoke('plugin:profile|profile_export_mrpack', {
path,
exportLocation,
includedOverrides,
versionId,
description,
name,
})
}
// Given a folder path, populate an array of all the subfolders
// Intended to be used for finding potential override folders
// profile
// -- mods
// -- resourcepacks
// -- file1
// => [mods, resourcepacks]
// allows selection for 'included_overrides' in export_profile_mrpack
export async function get_pack_export_candidates(profilePath: string): Promise<string[]> {
return await invoke('plugin:profile|profile_get_pack_export_candidates', { profilePath })
}
// Run Minecraft using a pathed profile
// Returns PID of child
export async function run(path: string, serverAddress: string | null = null): Promise<unknown> {
return await invoke('plugin:profile|profile_run', { path, serverAddress })
}
export async function kill(path: string): Promise<void> {
return await invoke('plugin:profile|profile_kill', { path })
}
// Edits a profile
export async function edit(path: string, editProfile: Partial<GameInstance>): Promise<void> {
return await invoke('plugin:profile|profile_edit', { path, editProfile })
}
// Edits a profile's icon
export async function edit_icon(path: string, iconPath: string | null): Promise<void> {
return await invoke('plugin:profile|profile_edit_icon', { path, iconPath })
}
export async function finish_install(instance: GameInstance): Promise<void> {
if (instance.install_stage !== 'pack_installed') {
const linkedData = instance.linked_data
if (linkedData) {
await install_to_existing_profile(
linkedData.project_id,
linkedData.version_id,
instance.name,
instance.path,
)
}
} else {
await install(instance.path, false)
}
}
+6 -19
View File
@@ -1,6 +1,6 @@
import type { ModrinthId } from '@modrinth/utils'
type GameInstance = {
export type GameInstance = {
path: string
install_stage: InstallStage
@@ -46,20 +46,13 @@ type LinkedData = {
locked: boolean
}
type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
export type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
type ContentFile = {
hash: string
file_name: string
size: number
metadata?: FileMetadata
update_version_id?: string
project_type: ContentFileProjectType
}
type FileMetadata = {
project_id: string
version_id: string
metadata?: {
project_id: string
version_id: string
}
}
type ContentFileProjectType = 'mod' | 'datapack' | 'resourcepack' | 'shaderpack'
@@ -135,9 +128,3 @@ type AppSettings = {
prev_custom_dir?: string
migrated: boolean
}
export type InstanceSettingsTabProps = {
instance: GameInstance
offline?: boolean
isMinecraftServer?: boolean
}
+6
View File
@@ -30,6 +30,8 @@ export type ServerWorld = BaseWorld & {
index: number
address: string
pack_status: ServerPackStatus
project_id?: string
content_kind?: string
}
export type World = SingleplayerWorld | ServerWorld
@@ -140,12 +142,16 @@ export async function add_server_to_profile(
name: string,
address: string,
packStatus: ServerPackStatus,
projectId?: string,
contentKind?: string,
): Promise<number> {
return await invoke('plugin:worlds|add_server_to_profile', {
path,
name,
address,
packStatus,
projectId,
contentKind,
})
}
+224 -173
View File
@@ -5,6 +5,153 @@
"app.auth-servers.unreachable.header": {
"message": "تعذر الوصول إلى خوادم المصادقة"
},
"app.browse.add-server-to-instance": {
"message": "أضف الخادم للنموذج"
},
"app.browse.add-servers-to-instance": {
"message": "أضف الخوادم لنموذجك"
},
"app.browse.add-to-instance": {
"message": "أضف للنموذج"
},
"app.browse.add-to-instance-name": {
"message": "أضف للنموذج {instanceName}"
},
"app.browse.added": {
"message": "مضاف"
},
"app.browse.already-added": {
"message": "مضاف فعلا"
},
"app.browse.discover-content": {
"message": "استكشف محتوى"
},
"app.browse.discover-servers": {
"message": "استكشف خوادم"
},
"app.browse.hide-added-servers": {
"message": "إخفاء الخوادم المضافة"
},
"app.browse.hide-installed-content": {
"message": "إخفاء المحتوى المضاف"
},
"app.browse.install-content-to-instance": {
"message": "تثبيت محتوى لنموذجك"
},
"app.export-modal.description-placeholder": {
"message": "أدخل وصف التعديل..."
},
"app.export-modal.export-button": {
"message": "تصدير"
},
"app.export-modal.header": {
"message": "تصدير حزمة التعديل"
},
"app.export-modal.modpack-name-label": {
"message": "إسم حزمة التعديل"
},
"app.export-modal.modpack-name-placeholder": {
"message": "إسم حزمة التعديل"
},
"app.export-modal.select-files-label": {
"message": "حدد الملفات والمجلدات المراد تضمينها في الحزمة"
},
"app.export-modal.version-number-label": {
"message": "رقم الإصدار"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "سيتم حذف جميع البيانات الخاصة لنموذجك نهائيًا، بما في ذلك عوالمك والتكوينات وكل المحتوى المثبت."
},
"app.instance.confirm-delete.admonition-header": {
"message": "لا يمكن التراجع عن هذا الإجراء"
},
"app.instance.confirm-delete.delete-button": {
"message": "حذف النموذج"
},
"app.instance.confirm-delete.header": {
"message": "حذف النموذج"
},
"app.instance.modpack-already-installed.body": {
"message": "حُزْمَة التعديل هذه مثبته فعلًا في نموذج <bold>{instanceName}</bold>. هل انت متأكد بإرادة نسخه؟"
},
"app.instance.modpack-already-installed.create": {
"message": "إنشاء"
},
"app.instance.modpack-already-installed.header": {
"message": "حُزْمَة التعديل مثبتة بالفعل"
},
"app.instance.modpack-already-installed.instance": {
"message": "النموذج"
},
"app.instance.mods.content-type-project": {
"message": "مشروع"
},
"app.instance.mods.project-was-added": {
"message": "تمت إضافة \"{name}\""
},
"app.instance.mods.projects-were-added": {
"message": "تمت إضافة {count} مشروع"
},
"app.instance.mods.share-text": {
"message": "تحقق من المشاريع التي أستخدمها في حزمة التعديل الخاص بي!"
},
"app.instance.mods.share-title": {
"message": "مشاركة محتوى حزمة التعديل"
},
"app.instance.mods.successfully-uploaded": {
"message": "تم الرفع بنجاح"
},
"app.instance.worlds.add-server": {
"message": "أضف خادم"
},
"app.instance.worlds.browse-servers": {
"message": "تصفح الخوادم"
},
"app.instance.worlds.delete-world-description": {
"message": "سيتم حذف '{name}' **نهائيا**, و لن هناك أي طريقة لاسترداده."
},
"app.instance.worlds.delete-world-title": {
"message": "هل أنت متيقِّن من رغبتك بحذف هذا العالم نهائيا؟"
},
"app.instance.worlds.filter-modded": {
"message": "معدّل"
},
"app.instance.worlds.filter-offline": {
"message": "مفصول"
},
"app.instance.worlds.filter-online": {
"message": "يعمل"
},
"app.instance.worlds.filter-vanilla": {
"message": "الأصلي"
},
"app.instance.worlds.no-worlds-description": {
"message": "أضف خادما أو تصفح لكي تبدأ"
},
"app.instance.worlds.no-worlds-heading": {
"message": "لم تتم إضافة أي من الخوادم أو العوالم"
},
"app.instance.worlds.remove-server-description": {
"message": "ستتم إزالة '{name}' من قائمتك, إضافة لما داخل اللعبة, و لن يكون هناك أي طريقة لاسترداده."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "ستتم إزالة '{name}' ({address}) من قائمتك, إضافة لما داخل اللعبة, و لن يكون هناك أي طريقة لاسترداده."
},
"app.instance.worlds.remove-server-title": {
"message": "هل أنت متيقِّن من رغبتك في إزالة {name}؟"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "ابحث بين ال{count} عوالم..."
},
"app.instance.worlds.this-server": {
"message": "هذا الخادم"
},
"app.modal.install-to-play.content-required": {
"message": "المحتوى مطلوب"
},
"app.modal.install-to-play.header": {
"message": "نزل للعب"
},
@@ -12,43 +159,31 @@
"message": "تثبيت"
},
"app.modal.install-to-play.mod-count": {
"message": ""
"message": "{count, plural, one {# تعديل} other {# تعديلات}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "حزمة التعديل مطلوبة"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "يتطلب هذا الخادم تعديلات للعب. انقر فوق \"تثبيت\" لإعداد الملفات المطلوبة من Modrinth، ثم قم بتشغيله مباشرة إلى الخادم."
},
"app.modal.install-to-play.shared-instance": {
"message": "حُزْمَة مشاركة"
"message": "النماذج المشتركة"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "حُزْمَة خادم مشاركة"
"message": "نماذج الخادم مشتركة"
},
"app.modal.update-to-play.added-count": {
"message": "{count} مضاف"
},
"app.modal.update-to-play.diff-type.added": {
"message": "تمت الإضافة"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "تمت الإزالة"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "تم تحديث"
"app.modal.install-to-play.view-contents": {
"message": "عرض المحتويات"
},
"app.modal.update-to-play.header": {
"message": "حدث للعب"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} مزال"
},
"app.modal.update-to-play.update-required": {
"message": "يلزم التحديث"
},
"app.modal.update-to-play.update-required-description": {
"message": "هناك تحديث لازم للعب بـ {name}. الرجاء التحديث إلى آخر اصدار لتشغيل اللعبة."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} حُدِّث"
"message": "هناك تحديث مطلوب للعب بـ {name}. الرجاء التحديث إلى آخر اصدار لتشغيل اللعبة."
},
"app.settings.developer-mode-enabled": {
"message": "تم تفعيل وضع المطوّر."
@@ -62,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "خيارات النسخة الافتراضية"
},
"app.settings.tabs.feature-flags": {
"message": "أعلام الميزات"
},
"app.settings.tabs.java-installations": {
"message": "تثبيتات جافا"
},
@@ -77,6 +209,33 @@
"app.settings.tabs.resource-management": {
"message": "إدارة الموارد"
},
"app.update-popup.body": {
"message": "تطبيق Modrinth v{version} جاهز للتثبيت! أعد التحميل للتحديث الآن، أو تلقائيًا عند إغلاق تطبيق Modrinth."
},
"app.update-popup.body.download-complete": {
"message": "انتهى تنزيل تطبيق Modrinth v{version}. أعد التحميل للتحديث الآن، أو تلقائيًا عند إغلاق تطبيق Modrinth."
},
"app.update-popup.body.linux": {
"message": "تطبيق Modrinth v {version} متاح. استخدم مدير الحزم الخاص بك للتحديث للحصول على أحدث الميزات والإصلاحات!"
},
"app.update-popup.body.metered": {
"message": "تطبيق Modrinth v{version} متاح الآن! وبما أنك متصل بشبكة مقيّدة، لم نقم بتنزيله تلقائيًا."
},
"app.update-popup.changelog": {
"message": "سجل التغيير"
},
"app.update-popup.download": {
"message": "تنزيل ({size})"
},
"app.update-popup.download-complete": {
"message": "اكتمل التنزيل"
},
"app.update-popup.reload": {
"message": "إعادة تحميل"
},
"app.update-popup.title": {
"message": "تحديث متاح"
},
"app.update.complete-toast.text": {
"message": "انقر هنا لعرض سجلّ التغييرات."
},
@@ -92,6 +251,24 @@
"app.update.reload-to-update": {
"message": "أعد التحميل لتثبيت التحديث"
},
"app.world.server-modal.placeholder-address": {
"message": "مثال.مودرنث.جج"
},
"app.world.server-modal.select-an-option": {
"message": "حدد خيارا"
},
"app.world.world-item.incompatible-version": {
"message": "إصدار غير مطابق ({version})"
},
"app.world.world-item.not-played-yet": {
"message": "لم يتم اللعب به"
},
"app.world.world-item.offline": {
"message": "مفصول"
},
"app.world.world-item.players-online": {
"message": "{count} متصل حاليا"
},
"friends.action.add-friend": {
"message": "إضافة صديق"
},
@@ -191,11 +368,11 @@
"instance.edit-world.title": {
"message": "تعديل العالم"
},
"instance.filter.disabled": {
"message": "المشاريع المعطَّلة"
"instance.files.adding-files": {
"message": "إضافة ملفات ({completed}\\{total})"
},
"instance.filter.updates-available": {
"message": "توجد تحديثات متاحة"
"instance.files.save-as": {
"message": "حفظ ك..."
},
"instance.server-modal.address": {
"message": "العنوان"
@@ -234,7 +411,7 @@
"message": "نسخة النسخة"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "إنشاء."
"message": "ينشئ نسخة من هذا النموذج شاملا عوالمه, تعديلاتها النصيه, إلخ..."
},
"instance.settings.tabs.general.edit-icon": {
"message": "تعديل الأيقونة"
@@ -305,141 +482,9 @@
"instance.settings.tabs.installation": {
"message": "تثبيت"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} لـ Minecraft{game_version} مثبت بالفعل"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "فانيلا {game_version} مُثبّتة بالفعل"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "تغيير الإصدار"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "تثبيت"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "جاري التثبيت"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "جاري جلب إصدارات حزمة المودات"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "جاري تثبيت الإصدار الجديد"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "المثبت حاليًا"
},
"instance.settings.tabs.installation.debug-information": {
"message": "معلومات التصحيح:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "جاري جلب تفاصيل حزمة المودات"
},
"instance.settings.tabs.installation.game-version": {
"message": "إصدار اللعبة"
},
"instance.settings.tabs.installation.install": {
"message": "تثبيت"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "التثبيت قيد التنفيذ"
},
"instance.settings.tabs.installation.loader-version": {
"message": "إصدار {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "تعذّر جلب تفاصيل حزمة المودات المرتبطة. يرجى التحقق من اتصالك بالإنترنت."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} غير متاح لماين كرافت {version}. جرّب محمّل مودات آخر."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "هذه النسخة مرتبطة بحزمة مودات، لكن لم يتم العثور على الحزمة على مودرنث."
},
"instance.settings.tabs.installation.platform": {
"message": "منصّة"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "إعادة تثبيت حزمة المودات"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "جاري إعادة تثبيت حزمة المودات"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "إعادة التثبيت ستُعيد جميع الملفات المثبتة أو المعدلة إلى ما توفره حُزْمة المودات، مع إزالة أي مودات أو محتوى أضفته بعد التثبيت الأصلي. قد يساعد ذلك في حل السلوك غير المتوقع إذا تم تعديل النسخة، لكن إذا كانت عوالمك تعتمد على محتويات إضافية، فقد يتسبب ذلك في تعطلها."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "هل أنت متأكد أنك تريد إعادة تثبيت هذه النسخة؟"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "يعيد محتوى النسخة إلى حالته الأصلية، مع إزالة جميع المودات أو المحتوى الذي أُضيف فوق حزمة المودات الأصلية."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "إعادة تثبيت حزمة المودات"
},
"instance.settings.tabs.installation.repair.button": {
"message": "إصلاح"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "جاري الإصلاح"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "الإصلاح يعيد تثبيت مكوّنات ماين كرافت ويتحقق من التلف. قد يساعد ذلك في حل المشكلات إذا كانت لعبتك لا تعمل بسبب أخطاء متعلقة ببرنامج التشغيل، لكنه لن يحل المشكلات أو الأعطال الناتجة عن المودات المثبّتة."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "إصلاح النسخة؟"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "الإصلاح قيد التنفيذ"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "إعادة التعيين إلى الحالة الحالية"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "عرض جميع الإصدارات"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "تغيير الإصدار"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "تثبيت"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "إعادة التثبيت"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "إصلاح"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "لا يمكن {action} أثناء التثبيت"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "لا يمكن {action} أثناء عدم الاتصال بالإنترنت"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "لا يمكن {action} أثناء الإصلاح"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(إصدار غير معروف)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "إلغاء ربط النسخة"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "إذا تابعت، فلن تتمكّن من إعادة ربطها إلا بإنشاء نسخة جديدة بالكامل. لن تتلقى بعد ذلك تحديثات حزمة المودات، وستصبح نسخة عادية."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "هل أنت متأكد أنك تريد إلغاء ربط هذه النسخة؟"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "هذه النسخة مرتبطة بحزمة مودات، مما يعني أنه لا يمكن تحديث المودات أو تغيير محمّل المودات أو إصدار ماين كرافت. سيؤدي إلغاء الربط إلى فصل هذه النسخة نهائيًا عن حزمة المودات."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "إلغاء الربط من حزمة المودات"
},
"instance.settings.tabs.java": {
"message": "جافا والذاكرة"
},
@@ -500,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "عدم العرض في الصفحة الرئيسية"
},
"instance.worlds.filter.available": {
"message": "متاح"
},
"instance.worlds.game_already_open": {
"message": "النسخة مفتوحة بالفعل"
},
@@ -512,6 +554,9 @@
"instance.worlds.incompatible_server": {
"message": "الخادم غير متوافق"
},
"instance.worlds.linked_server": {
"message": "تدار بواسطة مشروع الخادم"
},
"instance.worlds.no_contact": {
"message": "تعذّر الاتصال بالخادم"
},
@@ -524,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "تشغيل النسخة"
},
"instance.worlds.type.server": {
"message": "الخادم"
},
"instance.worlds.type.singleplayer": {
"message": "لعب فردي"
},
"instance.worlds.view_instance": {
"message": "عرض النسخة"
},
@@ -547,5 +586,17 @@
},
"search.filter.locked.instance.sync": {
"message": "مزامنة مع النسخة"
},
"search.filter.locked.server": {
"message": "يقدمها الخادم"
},
"search.filter.locked.server-environment.title": {
"message": "يمكن إضافة التعديلات **المحليه** فقط إلى نموذج الخادم"
},
"search.filter.locked.server-game-version.title": {
"message": "يتم توفير نسخة اللعبة من قبل الخادم"
},
"search.filter.locked.server-loader.title": {
"message": "يتم توفير المحمّل من قبل الخادم"
}
}
+156 -174
View File
@@ -5,6 +5,147 @@
"app.auth-servers.unreachable.header": {
"message": "Připojení k autorizačním serverům se nezdařilo"
},
"app.browse.add-server-to-instance": {
"message": "Přidat server do instance"
},
"app.browse.add-servers-to-instance": {
"message": "Přidat servery do instance"
},
"app.browse.add-to-instance": {
"message": "Přidat do instance"
},
"app.browse.add-to-instance-name": {
"message": "Přidat do {instanceName}"
},
"app.browse.added": {
"message": "Přidáno"
},
"app.browse.already-added": {
"message": "Už přidáno"
},
"app.browse.discover-content": {
"message": "Prozkoumat obsah"
},
"app.browse.discover-servers": {
"message": "Prozkoumat servery"
},
"app.browse.hide-added-servers": {
"message": "Skrýt přidané servery"
},
"app.browse.hide-installed-content": {
"message": "Skrýt nainstalovaný obsah"
},
"app.browse.install-content-to-instance": {
"message": "Nainstalovat obsah do instnce"
},
"app.export-modal.description-placeholder": {
"message": "Přidej popis modpacku..."
},
"app.export-modal.export-button": {
"message": "Exportovat"
},
"app.export-modal.header": {
"message": "Exportovat modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Jméno Modpacku"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Jméno modpacku"
},
"app.export-modal.select-files-label": {
"message": "Vybrat soubory a složky co zahrnout do modpacku"
},
"app.export-modal.version-number-label": {
"message": "Číslo verze"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Všechna data z instance budou navždy smazána, včetně světů, nastavení a všeho ostatního."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Tato akce nemůže být vrácena"
},
"app.instance.confirm-delete.delete-button": {
"message": "Odstranit instanci"
},
"app.instance.confirm-delete.header": {
"message": "Odstanit instanci"
},
"app.instance.modpack-already-installed.body": {
"message": "Tento modpack je už nainstalovaný v instanci <bold>{instanceName}</bold>. Opravdu ho chceš duplikovat?"
},
"app.instance.modpack-already-installed.create": {
"message": "Vytvořit"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack už je nainstalovaný"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instance"
},
"app.instance.mods.content-type-project": {
"message": "projekt"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" bylo přidáno"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projektů bylo přidáno"
},
"app.instance.mods.share-text": {
"message": "Podívejte se na projekty co používám ve svém modpacku!"
},
"app.instance.mods.share-title": {
"message": "Sdílení obsahu modpacku"
},
"app.instance.mods.successfully-uploaded": {
"message": "Úspěšně nahráno"
},
"app.instance.worlds.add-server": {
"message": "Přidat server"
},
"app.instance.worlds.browse-servers": {
"message": "Procházet servery"
},
"app.instance.worlds.delete-world-description": {
"message": "\"{name}\" bude **navždy smazáno** a nebude způsob, jak to obnovit."
},
"app.instance.worlds.delete-world-title": {
"message": "Opravdu si jsi jistý, že chceš navždy smazat tenhle svět?"
},
"app.instance.worlds.filter-modded": {
"message": "Modováno"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Přidej nebo procházej servery"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Žádné servery nebo světy nebyly přidány"
},
"app.instance.worlds.remove-server-description": {
"message": "„{name}“ bude odstraněn z tvého seznamu, včetně hry, a nebude žádný způsob, jak ho obnovit."
},
"app.instance.worlds.remove-server-title": {
"message": "Opravdu chceš odstranit {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Hledat ve světech {count}..."
},
"app.instance.worlds.this-server": {
"message": "tento server"
},
"app.modal.install-to-play.header": {
"message": "Nainstaluj ke hraní"
},
@@ -20,36 +161,15 @@
"app.modal.install-to-play.shared-server-instance": {
"message": "Sdílená serverová instance"
},
"app.modal.update-to-play.added-count": {
"message": "{count} přidáno"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Přidáno"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Odebráno"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Aktualizováno"
},
"app.modal.update-to-play.header": {
"message": "Updatuj ke hraní"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} odstraněno"
},
"app.modal.update-to-play.update-required": {
"message": "Je vyžadována aktualizace"
},
"app.modal.update-to-play.update-required-description": {
"message": "Je nutná aktualizace ke hraní {name}. Prosím updatuj na nejnovější verzi k spuštění hry."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} aktualizováno"
},
"app.settings.developer-mode-enabled": {
"message": "Vývojářský režim povolen."
},
@@ -62,9 +182,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Výchozí možnosti instance"
},
"app.settings.tabs.feature-flags": {
"message": "Vlajky funkcí"
},
"app.settings.tabs.java-installations": {
"message": "Instalace Javy"
},
@@ -77,6 +194,9 @@
"app.settings.tabs.resource-management": {
"message": "Správa zdrojů"
},
"app.update-popup.download": {
"message": "Stáhnout ({size})"
},
"app.update.complete-toast.text": {
"message": "Kliknutím sem zobrazíte seznam změn."
},
@@ -96,7 +216,7 @@
"message": "Přidat přítele"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural, one {žádost} few {žádosti} other {žádostí}} o přátelství"
"message": "{count} přátelé {count, plural, one {request} other {requests}}"
},
"friends.add-friend.submit": {
"message": "Poslat žádost o přátelství"
@@ -191,12 +311,6 @@
"instance.edit-world.title": {
"message": "Upravit svět"
},
"instance.filter.disabled": {
"message": "Vypnuté projekty"
},
"instance.filter.updates-available": {
"message": "K dispozice jsou aktualizace"
},
"instance.server-modal.address": {
"message": "Adresa"
},
@@ -305,141 +419,9 @@
"instance.settings.tabs.installation": {
"message": "Instalace"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} pro Minecraft {game_version} již je nainstalována"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} již je nainstalována"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Změnit verzi"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Instalovat"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Instalování"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Načítání verzí modpacku"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Instalace nové verze"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Aktuálně nainstalováno"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Debugové informace:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Načítání detailů modpacku"
},
"instance.settings.tabs.installation.game-version": {
"message": "Verze hry"
},
"instance.settings.tabs.installation.install": {
"message": "Instalovat"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Probíhá instalace"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} verze"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Nelze načíst podrobnosti o modpacku. Prosím, zkontrolujte své připojení k internetu."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} není dostupný pro Minecraft {version}. Zkuste jiný mod loader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Tato instalace je připojená k modpacku, který ake nebyl najit na Modrinthu."
},
"instance.settings.tabs.installation.platform": {
"message": "Platforma"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Přeinstalovat modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Přeinstalovávání modpacku"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Přeinstalace resetuje veškerý nainstalovaný nebo upravený obsah kromě toho, co poskytuje modpack, a odstraní všechny módy nebo obsah, které jste přidali do původní instalace. To může opravit neočekávané chyby, ale pokud vaše světy závisejí na doinstalovaném obsahu, možná budou poškozeny."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Opravdu si přejete přeinstalovat tuto instalaci?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Obnoví obsah instance do původního stavu a odstraní všechny mody nebo obsah, které jste přidali nad původní modpack."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Přeinstalovat modpack"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Opravit"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Opravováno"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Oprava přeinstaluje závislosti Minecraftu a zkontroluje poškození. To může vyřešit problémy, pokud se hra nespustí kvůli chybám souvisejícím s launcherem, ale nevyřeší to problémy nebo pády související s nainstalovanými mody."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Opravit instanci?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Probíhá oprava"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Resetovat na aktuální"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Ukázat všechny verze"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "změnit verzi"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "Instalovat"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "přeinstalovat"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "opravit"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Nelze {action} při instalaci"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Nelze {action} když offline"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Nelze {action} při opravě"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(neznámá verze)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Odpojit instanci"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Pokud budete pokračovat, nebudete ji moci znovu propojit bez vytvoření zcela nové instance. Již nebudete dostávat aktualizace modpacku a stane se z něj běžná instance."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Opravdu si přejete odpojit tuto instanci?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Tato instance je připojena k modpacku, což znamená, že módy nemohou být aktualizované a nelze změnit mod loader ani verze minecraftu. Odpojení permanentně rozváže tuto instanci od modpacku."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Odpojit od modpacku"
},
"instance.settings.tabs.java": {
"message": "Java a pamět"
},
@@ -500,9 +482,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Nezobrazuje na domovské stránce"
},
"instance.worlds.filter.available": {
"message": "Dostupné"
},
"instance.worlds.game_already_open": {
"message": "Instance je již otevřená"
},
@@ -519,17 +498,11 @@
"message": "Můžeš rovnou skočit na server pouze v Minecraftu Alpha 1.0.5+"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Můžeš se rovnou připojit do světa jednoho hráče pouze v Minecraftu 1.20+"
"message": "V Minecraftu 1.20+ se rovnou přeskočit pouze do singleplayerových světů"
},
"instance.worlds.play_instance": {
"message": "Hrát instanci"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Hra pro jednoho hráče"
},
"instance.worlds.view_instance": {
"message": "Zobrazit instanci"
},
@@ -543,9 +516,18 @@
"message": "Verze hry je poskytnut instanci"
},
"search.filter.locked.instance-loader.title": {
"message": "Spouštěč je poskytnut instanci"
"message": "Spouštěč je poskytnut instancí"
},
"search.filter.locked.instance.sync": {
"message": "Synchronizováno z instancí"
},
"search.filter.locked.server-environment.title": {
"message": "Jen klientské mody mohou být přidány na server"
},
"search.filter.locked.server-game-version.title": {
"message": "Verzi hry poskytuje server"
},
"search.filter.locked.server-loader.title": {
"message": "Loader zprostředkovává server"
}
}
+135 -168
View File
@@ -5,6 +5,90 @@
"app.auth-servers.unreachable.header": {
"message": "Kan ikke nå autentificeringsservere"
},
"app.browse.add-to-instance-name": {
"message": "Tilføjet til {instanceName}"
},
"app.browse.added": {
"message": "Tilføjet"
},
"app.browse.already-added": {
"message": "Allerede tilføjet"
},
"app.browse.discover-content": {
"message": "Opdag indhold"
},
"app.browse.discover-servers": {
"message": "Opdag servere"
},
"app.browse.hide-added-servers": {
"message": "Gem tilføjet servere"
},
"app.browse.hide-installed-content": {
"message": "Gem installeret indhold"
},
"app.export-modal.description-placeholder": {
"message": "Indtast modpack beskrivelse..."
},
"app.export-modal.export-button": {
"message": "Eksporter"
},
"app.export-modal.header": {
"message": "Eksporter modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Modpack Navn"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpack navn"
},
"app.export-modal.select-files-label": {
"message": "Vælg filer og mapper til at inkludere i pakken"
},
"app.export-modal.version-number-label": {
"message": "Versionsnummer"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Al' data for din instance vil blive permanent slettet, dette inkludere dine verdener, konfigurationer, og alt installeret indhold."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Denne handling kan ikke fortrydes"
},
"app.instance.confirm-delete.delete-button": {
"message": "Slet instance"
},
"app.instance.confirm-delete.header": {
"message": "Slet instance"
},
"app.instance.modpack-already-installed.body": {
"message": "Denne modpack er allerede installeret i <bold>{instanceName}</bold> instancen. Er du sikker på du vil duplikere den?"
},
"app.instance.modpack-already-installed.create": {
"message": "Opret"
},
"app.instance.mods.content-type-project": {
"message": "projekt"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" blev tilføjet"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projekter blev tilføjet"
},
"app.instance.mods.share-text": {
"message": "Tjek ud disse projekter jeg bruger i min modpack!"
},
"app.instance.mods.share-title": {
"message": "Deler modpack indhold"
},
"app.instance.mods.successfully-uploaded": {
"message": "Uploadet"
},
"app.modal.install-to-play.content-required": {
"message": "Indhold krævet"
},
"app.modal.install-to-play.header": {
"message": "Installer for at spille"
},
@@ -14,39 +98,30 @@
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# mods}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Modpack krævet"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Denne server kræver mods for at spille. Tryk på installer for at sætte de krævet filler fra modrinth op, så lancer direkte til serveren."
},
"app.modal.update-to-play.added-count": {
"message": "{count} tilføjet"
"app.modal.install-to-play.shared-instance": {
"message": "Delt instance"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Tilføjet"
"app.modal.install-to-play.shared-server-instance": {
"message": "Delt server instance"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Fjernet"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Opdateret"
"app.modal.install-to-play.view-contents": {
"message": "Vis indhold"
},
"app.modal.update-to-play.header": {
"message": "Opdater for at spille"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} fjernet"
},
"app.modal.update-to-play.update-required": {
"message": "Opdatering krævet"
},
"app.modal.update-to-play.update-required-description": {
"message": "En opdatering er krævet for at spille {name}. Venligst opdater til den seneste version for at køre spillet."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} opdateret"
},
"app.settings.developer-mode-enabled": {
"message": "Udvikler-tilstand aktiveret."
},
@@ -59,9 +134,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Standardindstillinger for instans"
},
"app.settings.tabs.feature-flags": {
"message": "Funktionsflags"
},
"app.settings.tabs.java-installations": {
"message": "Javainstallationer"
},
@@ -74,6 +146,33 @@
"app.settings.tabs.resource-management": {
"message": "Ressourcestyring"
},
"app.update-popup.body": {
"message": "Modrinth App v{version} er klar til at blive installeret! Genindlæs for at opdatere nu, eller automatisk når du lukker Modrinth App."
},
"app.update-popup.body.download-complete": {
"message": "Modrinth App v{version} er færdig med at download. Genindlæs for at opdatere nu, eller automatisk når du lukker Modrinth App."
},
"app.update-popup.body.linux": {
"message": "Modrinth App v{version} er nu tilgængelig. Brug din pakke-manager til at opdatere for de nyeste features og fejlrettelser!"
},
"app.update-popup.body.metered": {
"message": "Modrinth App v{version} er nu tilgængelig! Siden du er på et begrænset netværk, vi downloadede den ikke automatisk."
},
"app.update-popup.changelog": {
"message": "Ændringslog"
},
"app.update-popup.download": {
"message": "Download ({size})"
},
"app.update-popup.download-complete": {
"message": "Download færdiggjort"
},
"app.update-popup.reload": {
"message": "Geninlæs"
},
"app.update-popup.title": {
"message": "Opdatering tilgængelig"
},
"app.update.complete-toast.text": {
"message": "Klik her for at vise ændringslog."
},
@@ -188,12 +287,6 @@
"instance.edit-world.title": {
"message": "Rediger verden"
},
"instance.filter.disabled": {
"message": "Deaktiverede projekter"
},
"instance.filter.updates-available": {
"message": "Tilgængelige opdateringer"
},
"instance.server-modal.address": {
"message": "Adresse"
},
@@ -302,141 +395,9 @@
"instance.settings.tabs.installation": {
"message": "Installation"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} for Minecraft {game_version} er allerede installeret"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} er allerede installeret"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Skift version"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Installer"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Installer"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Får modpack versioner"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Installere ny version"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Lige nu installeret"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Debug information:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Får modpack detaljer"
},
"instance.settings.tabs.installation.game-version": {
"message": "Spil version"
},
"instance.settings.tabs.installation.install": {
"message": "Installer"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Installation igangværende"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} version"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Kan ikke få forbundet modpack detaljer. Venligst tjek din internet forbindelse."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} er ikke mulig at bruge for Minecraft {version}. Prøv en anden mod loader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Denne instance er koblet til en modpack, men modpacken kunne ikke blive fundet på Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Platform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Geninstaller modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Geninstallere modpack"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Geninstallering vil nulstille alt installeret eller modificeret indhold givet af modpacken, fjerne alle mods eller indhold du har tilføjet ovenpå den originale installation. Dette vil måske fikse uforventet adfærd hvis ændringer er blevet lavet til den instance, men hvis din verdener nu afhænger af ektra tilføjet indhold, dette vil måske ødelægge eksisterende verdener."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Er du sikker på du vil geninstallere denne instance?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Nulstiller instanceens indhold til dens oprindelige tilstand, fjerne alle mods eller indhold du har tilføjet ovenpå den oprindelige modpack."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Geninstaller modpack"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Reparer"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Reparere"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Reparering geninstaller Minecraft afhængigheder og tjekker for korruption. Dette vil måske fikse fejl hvis dit spil ikke køre på grund af launcher relateret fejl, men vil ikke fikse fejl eller crashes relateret til installerede mods."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Reparer instance?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Reparation i gang"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Nulstil til nuværende"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Vis alle versioner"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "Ændre version"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "Installer"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "Geninstaller"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "Reparer"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Kan ikke {action} under installation"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Kan ikke {action} uden internet"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Kan ikke {action} under reparation"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(Ukendt version)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Frakoble instance"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Hvis du forsætter, du vil ikke have mulighed for at koble sammen igen uden at lave en helt ny instance. Du vil ikke længere modtage modpack opdateringer og vil blive en normal."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Er du sikker på du vil frakoble denne instance?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Denne instance er forbundet til en modpack, hvilket betyder mods kan ikke blive opdateret og du kan ikke ændre mod loaderen eller Minecraft version. Frakobling vil permanent frakoble denne instance fra modpacken."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Frakoble fra modpack"
},
"instance.settings.tabs.java": {
"message": "Java og hukommelse"
},
@@ -497,9 +458,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Vis ikke på forsiden"
},
"instance.worlds.filter.available": {
"message": "Tilgængelig"
},
"instance.worlds.game_already_open": {
"message": "Instance allerede åben"
},
@@ -509,6 +467,9 @@
"instance.worlds.incompatible_server": {
"message": "Serveren er uforenelig"
},
"instance.worlds.linked_server": {
"message": "Styret af server projektet"
},
"instance.worlds.no_contact": {
"message": "Serveren kunne ikke blive kontaktet"
},
@@ -521,12 +482,6 @@
"instance.worlds.play_instance": {
"message": "Spil instance"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Singleplayer"
},
"instance.worlds.view_instance": {
"message": "Se instance"
},
@@ -544,5 +499,17 @@
},
"search.filter.locked.instance.sync": {
"message": "Synkroniser med instance"
},
"search.filter.locked.server": {
"message": "Givet af serveren"
},
"search.filter.locked.server-environment.title": {
"message": "Kun klient-sided mods kan blive tilføjet til denne server instance"
},
"search.filter.locked.server-game-version.title": {
"message": "Spille version er givet af serveren"
},
"search.filter.locked.server-loader.title": {
"message": "Loader er givet af serveren"
}
}
+184 -196
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Authentifizierungsserver sind nicht erreichbar"
},
"app.browse.add-server-to-instance": {
"message": "Server zu Instanz hinzufügen"
},
"app.browse.add-servers-to-instance": {
"message": "Server zu deiner Instanz hinzufügen"
},
"app.browse.add-to-instance": {
"message": "Zu Instanz hinzufügen"
},
"app.browse.add-to-instance-name": {
"message": "Zu {instanceName} hinzufügen"
},
"app.browse.added": {
"message": "Hinzugefügt"
},
"app.browse.already-added": {
"message": "Bereits hinzugefügt"
},
"app.browse.discover-content": {
"message": "Inhalte entdecken"
},
"app.browse.discover-servers": {
"message": "Server entdecken"
},
"app.browse.hide-added-servers": {
"message": "Hinzugefügte Server ausblenden"
},
"app.browse.hide-installed-content": {
"message": "Installierte Inhalte ausblenden"
},
"app.browse.install-content-to-instance": {
"message": "Inhalt in Instanz installieren"
},
"app.export-modal.description-placeholder": {
"message": "Modpaketbeschreibung eingeben..."
},
"app.export-modal.export-button": {
"message": "Exportieren"
},
"app.export-modal.header": {
"message": "Modpack exportieren"
},
"app.export-modal.modpack-name-label": {
"message": "Modpaketname"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpaketname"
},
"app.export-modal.select-files-label": {
"message": "Wähle Dateien und Ordner zum hinzufügen im Paket aus"
},
"app.export-modal.version-number-label": {
"message": "Versionsnummer"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Alle Daten deiner Instanz werden permanent gelöscht, inlusive deiner Welten, Konfigurationen und allen installierten Inhalten."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Diese Aktion kann nicht rückgängig gemacht werden"
},
"app.instance.confirm-delete.delete-button": {
"message": "Instanz löschen"
},
"app.instance.confirm-delete.header": {
"message": "Instanz löschen"
},
"app.instance.modpack-already-installed.body": {
"message": "Dieses Modpack ist bereits in der Instanz <bold>{instanceName}</bold> installiert. Möchtest du es wirklich duplizieren?"
},
"app.instance.modpack-already-installed.create": {
"message": "Erstellen"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack bereits installiert"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instanz"
},
"app.instance.mods.content-type-project": {
"message": "Projekt"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" wurde hinzugefügt"
},
"app.instance.mods.projects-were-added": {
"message": "{count} Projekte wurden hinzugefügt"
},
"app.instance.mods.share-text": {
"message": "Schau dir die Projekte, welche ich in meinem Modpaket nutze an!"
},
"app.instance.mods.share-title": {
"message": "Modpaketinhalte teilen"
},
"app.instance.mods.successfully-uploaded": {
"message": "Erfolgreich hochgeladen"
},
"app.instance.worlds.add-server": {
"message": "Server hinzufügen"
},
"app.instance.worlds.browse-servers": {
"message": "Server durchsuchen"
},
"app.instance.worlds.delete-world-description": {
"message": "„{name}“ wird **endgültig gelöscht**, und es gibt keine Möglichkeit, sie wiederherzustellen."
},
"app.instance.worlds.delete-world-title": {
"message": "Möchtest du diese Welt wirklich endgültig löschen?"
},
"app.instance.worlds.filter-modded": {
"message": "Modifiziert"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Füge einen Server hinzu oder durchsuche, um loszulegen"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Keine Server oder Welten hinzugefügt"
},
"app.instance.worlds.remove-server-description": {
"message": "„{name}“ wird aus deiner Liste entfernt, auch im Spiel, und es gibt keine Möglichkeit, ihn wiederherzustellen."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "„{name}“ ({address}) wird aus deiner Liste entfernt, inklusive im Spiel, und es gibt keine Möglichkeit, ihn wiederherzustellen."
},
"app.instance.worlds.remove-server-title": {
"message": "Möchtest du {name} wirklich entfernen?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Durchsuche {count} Welten..."
},
"app.instance.worlds.this-server": {
"message": "dieser Server"
},
"app.modal.install-to-play.content-required": {
"message": "Inhalte benötigt"
},
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Inhalte ansehen"
},
"app.modal.update-to-play.added-count": {
"message": "{count} hinzuäfüägt"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Hinzugefügt"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Entfernt"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Aktualisiert"
},
"app.modal.update-to-play.header": {
"message": "Aktualisieren zum Spielen"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} entfernt"
},
"app.modal.update-to-play.update-required": {
"message": "Aktualisierung benötigt"
},
"app.modal.update-to-play.update-required-description": {
"message": "Eine aktualisierung zum spielen von {name} ist benötigt. Bitte aktualisiere auf die neuste Version um das Spiel zu starten."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} aktualisiert"
},
"app.settings.developer-mode-enabled": {
"message": "Entwicklermodus aktiviert."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Standard Instanz-Einstellungen"
},
"app.settings.tabs.feature-flags": {
"message": "Funktionsflaggen"
},
"app.settings.tabs.java-installations": {
"message": "Java Installationen"
},
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Lade neu um Aktualisierung zu installieren"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Wählen eine Option"
},
"app.world.world-item.incompatible-version": {
"message": "Inkompatible Version {version}"
},
"app.world.world-item.not-played-yet": {
"message": "Noch nicht gespielt"
},
"app.world.world-item.offline": {
"message": "Offline"
},
"app.world.world-item.players-online": {
"message": "{count} online"
},
"friends.action.add-friend": {
"message": "Freund hinzufügen"
},
@@ -150,10 +288,10 @@
"message": "Modrinth Nutzernamen eingeben..."
},
"friends.add-friend.username.title": {
"message": "Was ist der Modrinth Nutzername deines Freundes?"
"message": "Was ist der Modrinth-Nutzername deines Freundes?"
},
"friends.add-friends-to-share": {
"message": "<link>Füge Freunde hinzu</link> um zu sehen, was sie spielen!"
"message": "<link>Füge Freunde hinzu</link>, um zu sehen, was sie spielen!"
},
"friends.friend.cancel-request": {
"message": "Anfrage abbrechen"
@@ -192,7 +330,7 @@
"message": "{title} - {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>Logge dich in ein Modrinth Konto ein</link> um Freunde hinzuzufügen und zu sehen, was sie spielen!"
"message": "<link>Logge dich in ein Modrinth Konto ein</link>, um Freunde hinzuzufügen und zu sehen, was sie spielen!"
},
"instance.add-server.add-and-play": {
"message": "Ersteue u starte"
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Welt bearbeiten"
},
"instance.filter.disabled": {
"message": "Deaktivierte Projekte"
"instance.files.adding-files": {
"message": "Dateien werden hinzugefügt ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Updates verfügbar"
"instance.files.save-as": {
"message": "Speichern unter..."
},
"instance.server-modal.address": {
"message": "Adresse"
@@ -312,13 +450,13 @@
"message": "Hooks ermöglichen es erfahrenen Benutzern, bestimmte Systembefehle vor und nach dem Start des Spiels auszuführen."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "Nach dem Schliessen des Spiels"
"message": "Nach dem Schließen des Spiels"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "Wird nach dem Beenden des Spiels ausgeführt."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Ausgeführter Befehl nach dem Beenden des Spiels eingeben..."
"message": "Nach dem Beenden des Spiels auszuführenden Befehl eingeben..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Vor Start des Spiels"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Installation"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} für Minecraft {game_version} ist bereits installiert"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} ist bereits installiert"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Version ändern"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Installieren"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Wird installiert"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Sammle Modpack-Versionen"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Neue Version wird installiert"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Aktuell installiert"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Informationen zur Fehlerbehebung:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Sammle Modpack-Details"
},
"instance.settings.tabs.installation.game-version": {
"message": "Spielversion"
},
"instance.settings.tabs.installation.install": {
"message": "Installieren"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Wird installiert"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} Version"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Kann Details für verknüpftes Modpack nicht abrufen. Bitte überprüfe deine Internerverbindung."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} ist nicht verfügbar für Minecraft {version}. Versuch einen anderen Modloader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Diese Instanz ist mit einem Modpack verknüpft, aber das Modpack konnte nicht auf Modrinth gefunden werden."
},
"instance.settings.tabs.installation.platform": {
"message": "Platform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Modpack neu installieren"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Modpack wird neu installiert"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Durch die Neuinstallation werden alle installierten oder geänderten Inhalte auf die vom Modpack bereitgestellten Inhalte zurückgesetzt, wobei alle Mods oder Inhalte entfernt werden, die zusätzlich zur ursprünglichen Installation hinzugefügt wurden. Dies kann unerwartetes Verhalten beheben, wenn Änderungen an der Instanz vorgenommen wurden. Wenn deine Welten jedoch von zusätzlich installierten Inhalten abhängig sind, kann dies zu Fehlern in bestehenden Welten führen."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Bist du sicher, dass du diese Instanz neu installieren willst?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Setzt den Inhalt der Instanz auf seinen ursprünglichen Zustand zurück und entfernt all Mods oder Inhalte, welche zusätzlich zum ursprünglichen Modpack hinzugefügt wurden."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Modpack neu installieren"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Reparieren"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Wird repariert"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Das reparieren installier Minecraft-Abhängigkeiten neu und überprüft für Beschädigungen. Dies kann Probleme beheben, sofern dein Spiel aufgrund von Launcher-relevanten Problemen nicht startet, aber es kann nicht Fehler und Abstpürze in Zusammenhang mit installierten Mods beheben."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Instanz reparieren?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Wird repariert"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Auf aktuellen Wert zurücksetzen"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Alle Versionen anzeigen"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "Version ändern"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "Installieren"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "Neuinstallieren"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "Reparieren"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "{action} während der Installation nicht möglich"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "{action} nicht möglich ohne Internetverbindung"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "{action} während reparatur nicht möglich"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(unbekannte Version)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Diese Instanz ist mit einem Server verknüpft, was bedeutet, dass du die Minecraft Version nicht ändern kannst. Das trennen der Verknüpfung trennt diese Instanz permanent vom Server."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Diese Instanz ist mit einem Server verknüpft, was bedeutet, dass du Mods nicht aktualisieren, und den Modloader oder die Minecraft Version nicht ändern kannst. Das trennen der Verknüpfung trennt diese Instanz permanent vom Server."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Serververknüpfung trennen"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Verlinking der Instanz trennen"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Wenn du fortfährst, kann die Instanz nicht erneut verknüpft werden, ohne eine komplett neue Instanz zu ersztellen. Du erhälst keine Modpack-Updates mehr und es wird zu einer normalen Instanz."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Bist du sicher, dass du die Verknüpfung dieser Instanz trennen willst?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Diese Instanz ist mit einem Modpack verknüpft. Dies bedeutet, dass Mods nicht aktualisiert werden können, und dass du den Modloader oder die Minecraft Versionen nicht ändern kannst. Durch das trennen der Verknüpfung wird die Instanz permanent vom Modpack getrennt."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Verknüpfung vom Modpack trennen"
},
"instance.settings.tabs.java": {
"message": "Java und Arbeitsspeicher"
},
@@ -516,13 +513,13 @@
"message": "Vollbild"
},
"instance.settings.tabs.window.fullscreen.description": {
"message": "Startet das Spiel im Vollbildmodus (durch verwenden von options.txt)."
"message": "Startet das Spiel im Vollbildmodus (mithilfe von options.txt)."
},
"instance.settings.tabs.window.height": {
"message": "Höhe"
},
"instance.settings.tabs.window.height.description": {
"message": "Die höhe des Spielfensters beim Start."
"message": "Die Höhe des Spielfensters beim Start."
},
"instance.settings.tabs.window.height.enter": {
"message": "Höhe eingeben..."
@@ -537,7 +534,7 @@
"message": "Breite eingeben..."
},
"instance.worlds.a_minecraft_server": {
"message": "Ä Minecraft-Server"
"message": "Ein Minecraft-Server"
},
"instance.worlds.cant_connect": {
"message": "Verbindung mit Server nicht möglich"
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Nicht auf Startseite anzeigen"
},
"instance.worlds.filter.available": {
"message": "Verfügbar"
},
"instance.worlds.game_already_open": {
"message": "Instanz ist bereits geöffnet"
},
@@ -558,7 +552,7 @@
"message": "Hardcore-Modus"
},
"instance.worlds.incompatible_server": {
"message": "Server ist inkompatibel"
"message": "Server ist nicht kompatibel"
},
"instance.worlds.linked_server": {
"message": "Von Serverprojekt verwaltet"
@@ -567,48 +561,42 @@
"message": "Server konnte nicht erreicht werden"
},
"instance.worlds.no_server_quick_play": {
"message": "Du kannst nur in Minecraft Alpha 1.0.5 und neuer direkt einem Server beitreten"
"message": "Du kannst nur mit Minecraft Alpha 1.0.5 und neuer einem Server direkt beitreten"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Du kannst nur in Minecraft 1.20 und neuer einer Einzelspieler-Welt beitreten"
"message": "Du kannst nur mit Minecraft 1.20 und neuer einer Einzelspieler-Welt direkt beitreten"
},
"instance.worlds.play_instance": {
"message": "Instanz Spielen"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Einzelspieler"
},
"instance.worlds.view_instance": {
"message": "Instanz anzeigen"
},
"instance.worlds.world_in_use": {
"message": "Welt bereits in benutzung"
"message": "Welt bereits in Benutzung"
},
"search.filter.locked.instance": {
"message": "Von der Instanz bereitgestellt"
"message": "Von der Instanz vorgegeben"
},
"search.filter.locked.instance-game-version.title": {
"message": "Spielversion ist von der Instanz bereitgestellt"
"message": "Spielversion ist von der Instanz vorgegeben"
},
"search.filter.locked.instance-loader.title": {
"message": "Loader ist von der Instanz bereitgestellt"
"message": "Loader ist von der Instanz vorgegeben"
},
"search.filter.locked.instance.sync": {
"message": "Mit Instanz synchronisieren"
},
"search.filter.locked.server": {
"message": "Von Server bereitgestellt"
"message": "Vom Server bereitgestellt"
},
"search.filter.locked.server-environment.title": {
"message": "Nur Clientseitige Mods können der Serverinstanz hinzugefügt werden"
},
"search.filter.locked.server-game-version.title": {
"message": "Spielversion vom Server bereitgestellt"
"message": "Spielversion wird vom Server bereitgestellt"
},
"search.filter.locked.server-loader.title": {
"message": "Loader vom Server bereitgestellt"
"message": "Loader wird vom Server bereitgestellt"
}
}
+168 -180
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Authentifizierungsserver sind nicht erreichbar"
},
"app.browse.add-server-to-instance": {
"message": "Server zur Instanz hinzufügen"
},
"app.browse.add-servers-to-instance": {
"message": "Server zu deiner Instanz hinzufügen"
},
"app.browse.add-to-instance": {
"message": "Zur Instanz hinzufügen"
},
"app.browse.add-to-instance-name": {
"message": "Zu {instanceName} hinzufügen"
},
"app.browse.added": {
"message": "Hinzugefügt"
},
"app.browse.already-added": {
"message": "Bereits hinzugefügt"
},
"app.browse.discover-content": {
"message": "Inhalte entdecken"
},
"app.browse.discover-servers": {
"message": "Server entdecken"
},
"app.browse.hide-added-servers": {
"message": "Hinzugefügte Server ausblenden"
},
"app.browse.hide-installed-content": {
"message": "Installierte Inhalte ausblenden"
},
"app.browse.install-content-to-instance": {
"message": "Inhalt in Instanz installieren"
},
"app.export-modal.description-placeholder": {
"message": "Beschreibung des Modpacks eingeben..."
},
"app.export-modal.export-button": {
"message": "Exportieren"
},
"app.export-modal.header": {
"message": "Modpack exportieren"
},
"app.export-modal.modpack-name-label": {
"message": "Modpackname"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpackname"
},
"app.export-modal.select-files-label": {
"message": "Wähle Dateien und Ordner aus, die in das Paket sollen"
},
"app.export-modal.version-number-label": {
"message": "Versionsnummer"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Alle Daten deiner Instanz werden permanent gelöscht, einschließlich deiner Welten, Konfigurationen und allen installierten Inhalten."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Diese Aktion kann nicht rückgängig gemacht werden"
},
"app.instance.confirm-delete.delete-button": {
"message": "Instanz löschen"
},
"app.instance.confirm-delete.header": {
"message": "Instanz löschen"
},
"app.instance.modpack-already-installed.body": {
"message": "Dieses Modpack ist bereits in der Instanz <bold>{instanceName}</bold> installiert. Möchtest du es wirklich duplizieren?"
},
"app.instance.modpack-already-installed.create": {
"message": "Erstellen"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack bereits installiert"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instanz"
},
"app.instance.mods.content-type-project": {
"message": "Projekt"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" wurde hinzugefügt"
},
"app.instance.mods.projects-were-added": {
"message": "{count} Projekte wurden hinzugefügt"
},
"app.instance.mods.share-text": {
"message": "Schau dir die Projekte an, die ich in meinem Modpack verwende!"
},
"app.instance.mods.share-title": {
"message": "Modpackinhalte teilen"
},
"app.instance.mods.successfully-uploaded": {
"message": "Erfolgreich hochgeladen"
},
"app.instance.worlds.add-server": {
"message": "Server hinzufügen"
},
"app.instance.worlds.browse-servers": {
"message": "Server durchsuchen"
},
"app.instance.worlds.delete-world-description": {
"message": "„{name}“ wird **endgültig gelöscht**, und es gibt keine Möglichkeit, sie wiederherzustellen."
},
"app.instance.worlds.delete-world-title": {
"message": "Möchtest du diese Welt wirklich endgültig löschen?"
},
"app.instance.worlds.filter-modded": {
"message": "Modifiziert"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Füge einen Server hinzu oder durchsuche, um loszulegen"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Keine Server oder Welten hinzugefügt"
},
"app.instance.worlds.remove-server-description": {
"message": "„{name}“ wird aus deiner Liste entfernt, auch im Spiel, und es gibt keine Möglichkeit, ihn wiederherzustellen."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "„{name}“ ({address}) wird aus deiner Liste entfernt, inklusive im Spiel, und es gibt keine Möglichkeit, ihn wiederherzustellen."
},
"app.instance.worlds.remove-server-title": {
"message": "Möchtest du {name} wirklich entfernen?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Durchsuche {count} Welten..."
},
"app.instance.worlds.this-server": {
"message": "dieser Server"
},
"app.modal.install-to-play.content-required": {
"message": "Inhalte benötigt"
},
@@ -21,7 +165,7 @@
"message": "Benötigtes Modpack"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Dieser Server benötigt Mods zum Spielen. Klicke auf Installieren um die nötigen Dateien von Modrinth herunterzuladen und dannach direkt dem Server beizutreten."
"message": "Dieser Server benötigt Mods zum Spielen. Klicke auf Installieren um die nötigen Dateien von Modrinth herunterzuladen und danach direkt dem Server beizutreten."
},
"app.modal.install-to-play.shared-instance": {
"message": "Geteilte Instanz"
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Inhalte ansehen"
},
"app.modal.update-to-play.added-count": {
"message": "{count} hinzugefügt"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Hinzugefügt"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Entfernt"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Aktualisiert"
},
"app.modal.update-to-play.header": {
"message": "Aktualisieren zum Spielen"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} entfernt"
},
"app.modal.update-to-play.update-required": {
"message": "Aktualisierung erforderlich"
},
"app.modal.update-to-play.update-required-description": {
"message": "Zum Spielen von {name} ist eine Aktualisierung erforderlich. Bitte aktualisiere auf die neueste Version, um das Spiel zu starten."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} aktualisiert"
},
"app.settings.developer-mode-enabled": {
"message": "Entwicklermodus aktiviert."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Standard Instanz-Einstellungen"
},
"app.settings.tabs.feature-flags": {
"message": "Funktionsflags"
},
"app.settings.tabs.java-installations": {
"message": "Java-Installationen"
},
@@ -93,7 +213,7 @@
"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-popup.body.download-complete": {
"message": "Modrinth App v{version} wurde heruntergeladen. Neu laden, um jetzt zu aktualisieren, oder automatisch, wenn du die Modrinth App schließt."
"message": "Modrinth App v{version} wurde heruntergeladen. Neu laden, um jetzt zu aktualisieren, oder automatisch aktualisieren, wenn du die Modrinth App schließt."
},
"app.update-popup.body.linux": {
"message": "Modrinth App v{version} ist verfügbar. Verwende deinen Paketmanager, um die neuesten Funktionen und Fehlerbehebungen zu installieren!"
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Neu laden, um das Update zu installieren"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Wählen eine Option"
},
"app.world.world-item.incompatible-version": {
"message": "Inkompatible Version {version}"
},
"app.world.world-item.not-played-yet": {
"message": "Noch nicht gespielt"
},
"app.world.world-item.offline": {
"message": "Offline"
},
"app.world.world-item.players-online": {
"message": "{count} online"
},
"friends.action.add-friend": {
"message": "Freund hinzufügen"
},
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Welt bearbeiten"
},
"instance.filter.disabled": {
"message": "Deaktivierte Projekte"
"instance.files.adding-files": {
"message": "Dateien werden hinzugefügt ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Updates verfügbar"
"instance.files.save-as": {
"message": "Speichern unter..."
},
"instance.server-modal.address": {
"message": "Adresse"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Installation"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} für Minecraft {game_version} bereits installiert"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} ist bereits installiert"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Version ändern"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Installieren"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Wird installiert"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Modpack-Versionen werden abgerufen"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Neue Version wird installiert"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Derzeit installiert"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Informationen für die Fehlerbehebung:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Modpack-Details werden abgerufen"
},
"instance.settings.tabs.installation.game-version": {
"message": "Spielversion"
},
"instance.settings.tabs.installation.install": {
"message": "Installieren"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Installation im Gange"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} Version"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Die Details des verknüpften Modpacks können nicht abgerufen werden. Bitte überprüfe deine Internetverbindung."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} ist nicht für Minecraft {version} verfügbar. Versuche einen anderen Modloader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Diese Instanz ist mit einem Modpack verknüpft, aber das Modpack konnte auf Modrinth nicht gefunden werden."
},
"instance.settings.tabs.installation.platform": {
"message": "Plattform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Modpack neu installieren"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Modpack wird neu installiert"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Eine Neuinstallation setzt alle installierten oder geänderten Inhalte auf den Zustand zurück, der vom Modpack bereitgestellt wird, und entfernt alle Mods oder Inhalte, die du zusätzlich zur ursprünglichen Installation hinzugefügt hast.\nDies kann unerwartetes Verhalten beheben, falls Änderungen an der Instanz vorgenommen wurden. Wenn deine Welten jedoch von zusätzlich installierten Inhalten abhängen, kann dies bestehende Welten beschädigen."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Bist du dir sicher, dass du diese Instanz neu installieren willst?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Setzt den Inhalt der Instanz auf den ursprünglichen Zustand zurück und entfernt alle Mods oder Inhalte, die du zusätzlich zum ursprünglichen Modpack hinzugefügt hast."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Modpack neu installieren"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Reparieren"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Wird repariert"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Durch die Reparatur werden die Abhängigkeiten von Minecraft neu installiert und auf Beschädigungen überprüft. Dies kann Probleme beheben, wenn Minecraft aufgrund von Fehlern im Launcher nicht startet, löst jedoch keine Probleme oder Abstürze im Zusammenhang mit installierten Mods."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Instanz reparieren?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Reparatur im Gange"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Auf aktuellen Stand zurücksetzen"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Alle Versionen anzeigen"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "Version ändern"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "Installieren"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "Neuinstallieren"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "Reparieren"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "{action} während der Installation nicht möglich"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "{action} offline nicht möglich"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "{action} während der Reparation nicht möglich"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(unbekannte Version)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Diese Instanz ist mit einem Server verknüpft, was bedeutet, dass du die Minecraft-Version nicht ändern kannst. Durch das Aufheben der Verknüpfung wird diese Instanz dauerhaft vom Server getrennt."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Diese Instanz ist mit einem Server verknüpft, was bedeutet, dass Mods nicht aktualisiert werden können und du den Mod-Loader oder die Minecraft-Version nicht ändern kannst. Durch das Aufheben der Verknüpfung wird diese Instanz dauerhaft vom Server getrennt."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Vom Server trennen"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Verknüpfung der Instanz trennen"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Wenn du fortfährst, kannst du sie nicht erneut verknüpfen, ohne eine völlig neue Instanz zu erstellen. Du wirst keine Modpack-Updates mehr erhalten, und sie wird zu einer normalen Instanz."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Möchtest du die Verknüpfungen dieser Instanz wirklich trennen?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Diese Instanz ist mit einem Modpack verknüpft. Das bedeutet, dass Mods nicht aktualisiert werden können und der Mod-Loader oder die Minecraft-Version nicht geändert werden können. Durch das Aufheben der Verknüpfung wird die Instanz dauerhaft vom Modpack getrennt."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Verknüpfung vom Modpack trennen"
},
"instance.settings.tabs.java": {
"message": "Java und Arbeitsspeicher"
},
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Nicht auf der Startseite anzeigen"
},
"instance.worlds.filter.available": {
"message": "Verfügbar"
},
"instance.worlds.game_already_open": {
"message": "Instanz ist bereits geöffnet"
},
@@ -575,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "Instanz spielen"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Einzelspieler"
},
"instance.worlds.view_instance": {
"message": "Instanz anzeigen"
},
+166 -175
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Cannot reach authentication servers"
},
"app.browse.add-server-to-instance": {
"message": "Add server to instance"
},
"app.browse.add-servers-to-instance": {
"message": "Add servers to your instance"
},
"app.browse.add-to-instance": {
"message": "Add to instance"
},
"app.browse.add-to-instance-name": {
"message": "Add to {instanceName}"
},
"app.browse.added": {
"message": "Added"
},
"app.browse.already-added": {
"message": "Already added"
},
"app.browse.discover-content": {
"message": "Discover content"
},
"app.browse.discover-servers": {
"message": "Discover servers"
},
"app.browse.hide-added-servers": {
"message": "Hide added servers"
},
"app.browse.hide-installed-content": {
"message": "Hide installed content"
},
"app.browse.install-content-to-instance": {
"message": "Install content to instance"
},
"app.export-modal.description-placeholder": {
"message": "Enter modpack description..."
},
"app.export-modal.export-button": {
"message": "Export"
},
"app.export-modal.header": {
"message": "Export modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Modpack Name"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpack name"
},
"app.export-modal.select-files-label": {
"message": "Select files and folders to include in pack"
},
"app.export-modal.version-number-label": {
"message": "Version number"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "All data for your instance will be permanently deleted, including your worlds, configs, and all installed content."
},
"app.instance.confirm-delete.admonition-header": {
"message": "This action cannot be undone"
},
"app.instance.confirm-delete.delete-button": {
"message": "Delete instance"
},
"app.instance.confirm-delete.header": {
"message": "Delete instance"
},
"app.instance.modpack-already-installed.body": {
"message": "This modpack is already installed in the <bold>{instanceName}</bold> instance. Are you sure you want to duplicate it?"
},
"app.instance.modpack-already-installed.create": {
"message": "Create"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack already installed"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instance"
},
"app.instance.mods.content-type-project": {
"message": "project"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" was added"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projects were added"
},
"app.instance.mods.share-text": {
"message": "Check out the projects I'm using in my modpack!"
},
"app.instance.mods.share-title": {
"message": "Sharing modpack content"
},
"app.instance.mods.successfully-uploaded": {
"message": "Successfully uploaded"
},
"app.instance.worlds.add-server": {
"message": "Add server"
},
"app.instance.worlds.browse-servers": {
"message": "Browse servers"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' will be **permanently deleted**, and there will be no way to recover it."
},
"app.instance.worlds.delete-world-title": {
"message": "Are you sure you want to permanently delete this world?"
},
"app.instance.worlds.filter-modded": {
"message": "Modded"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Add a server or browse to get started"
},
"app.instance.worlds.no-worlds-heading": {
"message": "No servers or worlds added"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' will be removed from your list, including in-game, and there will be no way to recover it."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) will be removed from your list, including in-game, and there will be no way to recover it."
},
"app.instance.worlds.remove-server-title": {
"message": "Are you sure you want to remove {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Search {count} worlds..."
},
"app.instance.worlds.this-server": {
"message": "this server"
},
"app.modal.install-to-play.content-required": {
"message": "Content required"
},
@@ -32,33 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "View contents"
},
"app.modal.update-to-play.added-count": {
"message": "{count} added"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Added"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Removed"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Updated"
},
"app.modal.update-to-play.header": {
"message": "Update to play"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} removed"
},
"app.modal.update-to-play.update-required": {
"message": "Update required"
},
"app.modal.update-to-play.update-required-description": {
"message": "An update is required to play {name}. Please update to the latest version to launch the game."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} updated"
},
"app.settings.developer-mode-enabled": {
"message": "Developer mode enabled."
},
@@ -71,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Default instance options"
},
"app.settings.tabs.feature-flags": {
"message": "Feature flags"
},
"app.settings.tabs.java-installations": {
"message": "Java installations"
},
@@ -128,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Reload to install update"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Select an option"
},
"app.world.world-item.incompatible-version": {
"message": "Incompatible version {version}"
},
"app.world.world-item.not-played-yet": {
"message": "Not played yet"
},
"app.world.world-item.offline": {
"message": "Offline"
},
"app.world.world-item.players-online": {
"message": "{count} online"
},
"friends.action.add-friend": {
"message": "Add a friend"
},
@@ -227,11 +368,11 @@
"instance.edit-world.title": {
"message": "Edit world"
},
"instance.filter.disabled": {
"message": "Disabled projects"
"instance.files.adding-files": {
"message": "Adding files ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Updates available"
"instance.files.save-as": {
"message": "Save as..."
},
"instance.server-modal.address": {
"message": "Address"
@@ -341,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Installation"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} for Minecraft {game_version} already installed"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} already installed"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Change version"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Install"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Installing"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Fetching modpack versions"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Installing new version"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Currently installed"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Debug information:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Fetching modpack details"
},
"instance.settings.tabs.installation.game-version": {
"message": "Game version"
},
"instance.settings.tabs.installation.install": {
"message": "Install"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Installation in progress"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} version"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Cannot fetch linked modpack details. Please check your internet connection."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} is not available for Minecraft {version}. Try another mod loader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "This instance is linked to a modpack, but the modpack could not be found on Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Platform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Reinstall modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Reinstalling modpack"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Reinstalling will reset all installed or modified content to what is provided by the modpack, removing any mods or content you have added on top of the original installation. This may fix unexpected behavior if changes have been made to the instance, but if your worlds now depend on additional installed content, it may break existing worlds."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Are you sure you want to reinstall this instance?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Resets the instance's content to its original state, removing any mods or content you have added on top of the original modpack."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Reinstall modpack"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Repair"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Repairing"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Repairing reinstalls Minecraft dependencies and checks for corruption. This may resolve issues if your game is not launching due to launcher-related errors, but will not resolve issues or crashes related to installed mods."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Repair instance?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Repair in progress"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Reset to current"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Show all versions"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "change version"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "install"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "reinstall"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "repair"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Cannot {action} while installing"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Cannot {action} while offline"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Cannot {action} while repairing"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(unknown version)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "This instance is linked to a server, which means you can't change the Minecraft version. Unlinking will permanently disconnect this instance from the server."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "This instance is linked to a server, which means mods can't be updated and you can't change the mod loader or Minecraft version. Unlinking will permanently disconnect this instance from the server."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Unlink from server"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Unlink instance"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "If you proceed, you will not be able to re-link it without creating an entirely new instance. You will no longer receive modpack updates and it will become a normal instance."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Are you sure you want to unlink this instance?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "This instance is linked to a modpack, which means mods can't be updated and you can't change the mod loader or Minecraft version. Unlinking will permanently disconnect this instance from the modpack."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Unlink from modpack"
},
"instance.settings.tabs.java": {
"message": "Java and memory"
},
@@ -545,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Don't show on Home"
},
"instance.worlds.filter.available": {
"message": "Available"
},
"instance.worlds.game_already_open": {
"message": "Instance is already open"
},
@@ -572,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "Play instance"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Singleplayer"
},
"instance.worlds.view_instance": {
"message": "View instance"
},
+168 -180
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "No se puede acceder a los servidores de autenticación"
},
"app.browse.add-server-to-instance": {
"message": "Añadir servidor a instancia"
},
"app.browse.add-servers-to-instance": {
"message": "Añade servidores a tu instancia"
},
"app.browse.add-to-instance": {
"message": "Añadir a instancia"
},
"app.browse.add-to-instance-name": {
"message": "Añadir a {instanceName}"
},
"app.browse.added": {
"message": "Añadido"
},
"app.browse.already-added": {
"message": "Ya se ha añadido"
},
"app.browse.discover-content": {
"message": "Descubrir contenido"
},
"app.browse.discover-servers": {
"message": "Descubrir servidores"
},
"app.browse.hide-added-servers": {
"message": "Ocultar servidores añadidos"
},
"app.browse.hide-installed-content": {
"message": "Ocultar contenido instalado"
},
"app.browse.install-content-to-instance": {
"message": "Instalar contenido a la instancia"
},
"app.export-modal.description-placeholder": {
"message": "Introduce la descripción del modpack..."
},
"app.export-modal.export-button": {
"message": "Exportar"
},
"app.export-modal.header": {
"message": "Exportar modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Nombre del modpack"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nombre del modpack"
},
"app.export-modal.select-files-label": {
"message": "Selecciona archivos y carpetas para incluirlos en el pack"
},
"app.export-modal.version-number-label": {
"message": "Número de la versión"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Todos los datos de tu instancia se eliminarán permanentemente, incluidos tus mundos, configuraciones y todo el contenido instalado."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Esta acción no se puede deshacer"
},
"app.instance.confirm-delete.delete-button": {
"message": "Eliminar instancia"
},
"app.instance.confirm-delete.header": {
"message": "Eliminar instancia"
},
"app.instance.modpack-already-installed.body": {
"message": "El modpack ya está instalado en la instancia <bold>{instanceName}</bold>. ¿Estás seguro de querer duplicarlo?"
},
"app.instance.modpack-already-installed.create": {
"message": "Crear"
},
"app.instance.modpack-already-installed.header": {
"message": "Este modpack ya está instalado"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instancia"
},
"app.instance.mods.content-type-project": {
"message": "proyecto"
},
"app.instance.mods.project-was-added": {
"message": "Se añadió \"{name}\""
},
"app.instance.mods.projects-were-added": {
"message": "Se añadieron {count} proyectos"
},
"app.instance.mods.share-text": {
"message": "¡Mira a los proyectos que estoy usando en mi modpack!"
},
"app.instance.mods.share-title": {
"message": "Compartiendo contenido del modpack"
},
"app.instance.mods.successfully-uploaded": {
"message": "Cargado correctamente"
},
"app.instance.worlds.add-server": {
"message": "Añadir servidor"
},
"app.instance.worlds.browse-servers": {
"message": "Explorar servidores"
},
"app.instance.worlds.delete-world-description": {
"message": "\"{name}\" se **eliminará permanentemente** y no habrá forma de recuperarlo."
},
"app.instance.worlds.delete-world-title": {
"message": "¿Estás seguro de que quieres eliminar este mundo de forma permanente?"
},
"app.instance.worlds.filter-modded": {
"message": "Con mods"
},
"app.instance.worlds.filter-offline": {
"message": "Sin conexión"
},
"app.instance.worlds.filter-online": {
"message": "En línea"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Añadir un servidor o explora para comenzar"
},
"app.instance.worlds.no-worlds-heading": {
"message": "No hay servidores ni mundos añadidos"
},
"app.instance.worlds.remove-server-description": {
"message": "\"{name}\" se eliminará de tu lista, también dentro del juego, y no podrás recuperarlo."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "\"{name}\" ({address}) se eliminará de tu lista, también dentro del juego, y no podrás recuperarlo."
},
"app.instance.worlds.remove-server-title": {
"message": "¿Estás seguro de que quieres eliminar {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Buscar en {count} mundos..."
},
"app.instance.worlds.this-server": {
"message": "este servidor"
},
"app.modal.install-to-play.content-required": {
"message": "Contenido requerido"
},
@@ -21,7 +165,7 @@
"message": "Modpack requerido"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Este servidor requiere mods para poder jugar. Haz click en Instalar para configurar los archivos requeridos desde Modrinth, después se ejecutará para entrar directamente al servidor."
"message": "Este servidor requiere mods para poder jugar. Haz clic en Instalar para configurar los archivos requeridos desde Modrinth, después se ejecutará para entrar directamente al servidor."
},
"app.modal.install-to-play.shared-instance": {
"message": "Instancia compartida"
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Ver contenidos"
},
"app.modal.update-to-play.added-count": {
"message": "{count} agregados"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Se agregó"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Se eliminó"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Actualizado"
},
"app.modal.update-to-play.header": {
"message": "Actualiza para jugar"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} eliminados"
},
"app.modal.update-to-play.update-required": {
"message": "Actualización requerida"
},
"app.modal.update-to-play.update-required-description": {
"message": "Se requiere una actualización para jugar {name}. Por favor, actualiza a la versión más reciente para iniciar el juego."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} actualizados"
},
"app.settings.developer-mode-enabled": {
"message": "Modo desarrollador activado."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Opciones predeterminadas de la instancia"
},
"app.settings.tabs.feature-flags": {
"message": "Funciones experimentales"
},
"app.settings.tabs.java-installations": {
"message": "Instalaciones de Java"
},
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Recarga para instalar la actualización"
},
"app.world.server-modal.placeholder-address": {
"message": "ejemplo.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Selecciona una opción"
},
"app.world.world-item.incompatible-version": {
"message": "Versión {version} incompatible"
},
"app.world.world-item.not-played-yet": {
"message": "Aún no se ha jugado"
},
"app.world.world-item.offline": {
"message": "Desconectado"
},
"app.world.world-item.players-online": {
"message": "{count} en línea"
},
"friends.action.add-friend": {
"message": "Añadir un amigo"
},
@@ -147,7 +285,7 @@
"message": "¡Podría ser distinto a su nombre de usuario de Minecraft!"
},
"friends.add-friend.username.placeholder": {
"message": "Ingresa tu nombre de usuario de Modrinth..."
"message": "Introduce el nombre de usuario de Modrinth..."
},
"friends.add-friend.username.title": {
"message": "¿Cuál es el nombre de usuario de Modrinth de tu amigo?"
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Editar mundo"
},
"instance.filter.disabled": {
"message": "Proyectos desactivados"
"instance.files.adding-files": {
"message": "Añadiendo archivos ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Actualizaciones disponibles"
"instance.files.save-as": {
"message": "Guardar como..."
},
"instance.server-modal.address": {
"message": "Dirección IP"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Instalación"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} ya está instalado para Minecraft {game_version}"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} ya está instalada"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Cambiar versión"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Instalar"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Instalando"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Obteniendo versiones del modpack"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Instalando nueva versión"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Actualmente instalado"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Información de depuración:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Obteniendo detalles del modpack"
},
"instance.settings.tabs.installation.game-version": {
"message": "Versión del juego"
},
"instance.settings.tabs.installation.install": {
"message": "Instalar"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Instalación en progreso"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Versión de {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "No se pueden obtener los detalles del modpack vinculado. Por favor, verifica tu conexión a internet."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} no está disponible para Minecraft {version}. Prueba con otro mod loader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Esta instancia está vinculada a un modpack, pero no se pudo encontrar el modpack en Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Plataforma"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Reinstalar modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Reinstalando modpack"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "La reinstalación restablecerá todo el contenido instalado o modificado a lo que proporciona el modpack, eliminando cualquier mod o contenido que hayas agregado sobre la instalación original. Esto puede solucionar comportamientos inesperados si se han hecho cambios en la instancia, pero si tus mundos dependen de contenido adicional instalado, podría romper los mundos existentes."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "¿Estás seguro de que quieres reinstalar esta instancia?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Restablece el contenido de la instancia a su estado original, eliminando cualquier mod o contenido que hayas agregado sobre el modpack original."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Reinstalar modpack"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Reparar"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Reparando"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Reparar reinstala las dependencias de Minecraft y verifica la integridad de los archivos. Esto puede solucionar problemas si tu juego no se inicia por errores relacionados con el launcher, pero no resolverá problemas debidos a mods instalados."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "¿Reparar instancia?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Reparación en proceso..."
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Restablecer al actual"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Mostrar todas las versiones"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "cambiar versión"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "instalar"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "reinstalar"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "reparar"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "No se puede {action} mientras se está instalando"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "No se puede {action} mientras estés desconectado"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "No se puede {action} mientras se está reparando"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(versión desconocida)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Esta instancia está vinculada a un servidor, lo que significa que no puedes cambiar la versión de Minecraft. Desvincularla la desconectará permanentemente del servidor."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Esta instancia está vinculada a un servidor, lo que significa que los mods no pueden actualizarse y no puedes cambiar el mod loader ni la versión de Minecraft. Desvincularla la desconectará permanentemente del servidor."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Desvincular del servidor"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Desvincular instancia"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Si continúas, no podrás volver a vincularla sin crear una nueva instancia. Ya no recibirás actualizaciones del modpack y pasará a ser una instancia normal."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "¿Estás seguro de que quieres desvincular esta instancia?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Esta instancia está vinculada a un modpack, lo que significa que los mods no pueden actualizarse y no puedes cambiar el mod loader ni la versión de Minecraft. Desvincularla la desconectará permanentemente del modpack."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Desvincular del modpack"
},
"instance.settings.tabs.java": {
"message": "Java y memoria"
},
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "No mostrar en la página de inicio"
},
"instance.worlds.filter.available": {
"message": "Disponible"
},
"instance.worlds.game_already_open": {
"message": "La instancia ya está abierta"
},
@@ -575,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "Iniciar instancia"
},
"instance.worlds.type.server": {
"message": "Servidor"
},
"instance.worlds.type.singleplayer": {
"message": "Un jugador"
},
"instance.worlds.view_instance": {
"message": "Ver instancia"
},
+217 -169
View File
@@ -5,8 +5,152 @@
"app.auth-servers.unreachable.header": {
"message": "No se puede conectar con los servidores de autenticación"
},
"app.browse.add-server-to-instance": {
"message": "Añadir servidor a la instancia"
},
"app.browse.add-servers-to-instance": {
"message": "Añadir servidor a tu instancia"
},
"app.browse.add-to-instance": {
"message": "Añadir a la instancia"
},
"app.browse.add-to-instance-name": {
"message": "Añadir a {instanceName}"
},
"app.browse.added": {
"message": "Añadido"
},
"app.browse.already-added": {
"message": "Ya está añadido"
},
"app.browse.discover-content": {
"message": "Descubrir contenido"
},
"app.browse.discover-servers": {
"message": "Descubrir servidores"
},
"app.browse.hide-added-servers": {
"message": "Ocultar servidores añadidos"
},
"app.browse.hide-installed-content": {
"message": "Ocultar contenido instalado"
},
"app.browse.install-content-to-instance": {
"message": "Instalar contenido a una instancia"
},
"app.export-modal.description-placeholder": {
"message": "Escribe la descripción del modpack..."
},
"app.export-modal.export-button": {
"message": "Exportar"
},
"app.export-modal.header": {
"message": "Exportar modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Nombre del modpack"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nombre del modpack"
},
"app.export-modal.select-files-label": {
"message": "Seleccione archivos y carpetas para incluir en el paquete"
},
"app.export-modal.version-number-label": {
"message": "Número de versión"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Todos los datos de su instancia se eliminarán permanentemente, incluidos sus mundos, configuraciones y todo el contenido instalado."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Esta acción no se puede deshacer"
},
"app.instance.confirm-delete.delete-button": {
"message": "Eliminar instancia"
},
"app.instance.confirm-delete.header": {
"message": "Eliminar instancia"
},
"app.instance.modpack-already-installed.body": {
"message": "Este modpack ya está instalado en la instancia <bold>{instanceName}</bold>. ¿Estás seguro qué quieres duplicarlo?"
},
"app.instance.modpack-already-installed.create": {
"message": "Crear"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack ya está instalado"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instancia"
},
"app.instance.mods.content-type-project": {
"message": "proyecto"
},
"app.instance.mods.project-was-added": {
"message": "Se ha añadido \"{name}\""
},
"app.instance.mods.projects-were-added": {
"message": "Se han añadido {count} proyectos"
},
"app.instance.mods.share-text": {
"message": "¡Echa un vistazo a los proyectos que utilizo en mi modpack!"
},
"app.instance.mods.share-title": {
"message": "Compartir contenido del modpack"
},
"app.instance.mods.successfully-uploaded": {
"message": "Se ha subido correctamente"
},
"app.instance.worlds.add-server": {
"message": "Añadir servidor"
},
"app.instance.worlds.browse-servers": {
"message": "Explorar servidores"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' será **permanentemente eliminado**, y habrá forma de recuperarlo."
},
"app.instance.worlds.delete-world-title": {
"message": "¿Estás seguro de qué quieres eliminar permanentemente este mundo?"
},
"app.instance.worlds.filter-modded": {
"message": "Modeado"
},
"app.instance.worlds.filter-offline": {
"message": "Sin conexión"
},
"app.instance.worlds.filter-online": {
"message": "En línea"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Añadir un servidor o explora para comenzar"
},
"app.instance.worlds.no-worlds-heading": {
"message": "No hay servidores o mundos añadidos"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' será eliminado de tu lista, incluyendo dentro del juego, y no habrá forma de recuperarlo."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) será eliminado de tu lista, incluyendo dentro del juego, y no habrá forma de recuperarlo."
},
"app.instance.worlds.remove-server-title": {
"message": "¿Estás seguro de qué quieres eliminar {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Buscar {count} mundos..."
},
"app.instance.worlds.this-server": {
"message": "este servidor"
},
"app.modal.install-to-play.content-required": {
"message": "Contenu requis"
"message": "Contenido obligatorio"
},
"app.modal.install-to-play.header": {
"message": "Instala para jugar"
@@ -17,42 +161,30 @@
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# mods}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Modpack requerido"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Este servidor requiere ciertos mods. Pulsa Instalar para instalar los archivos requeridos de Modrinth y luego el Launcher te enviara directo al servidor."
},
"app.modal.install-to-play.shared-instance": {
"message": "Instancia compartida"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "Instancia de servidor compartida"
},
"app.modal.update-to-play.added-count": {
"message": "{count} añadidos"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Añadido"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Eliminado"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Actualizado"
"app.modal.install-to-play.view-contents": {
"message": "Ver contenido"
},
"app.modal.update-to-play.header": {
"message": "Actualiza para jugar"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} eliminados"
},
"app.modal.update-to-play.update-required": {
"message": "Actualización requerida"
},
"app.modal.update-to-play.update-required-description": {
"message": "Una actualización es requerida para jugar {name}. Por favor actualízala a la versión más reciente para ejecutar el juego."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} actualizados"
},
"app.settings.developer-mode-enabled": {
"message": "Modo desarrollador activado."
},
@@ -65,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Opciones predeterminadas de la instancia"
},
"app.settings.tabs.feature-flags": {
"message": "Funciones experimentales"
},
"app.settings.tabs.java-installations": {
"message": "Instalaciones de Java"
},
@@ -80,6 +209,33 @@
"app.settings.tabs.resource-management": {
"message": "Gestión de recursos"
},
"app.update-popup.body": {
"message": "¡La versión v{version} de Modrinth está lista para instalarse! Actualiza ahora o automáticamente al cerrar la aplicación."
},
"app.update-popup.body.download-complete": {
"message": "Modrinth App v{version} se ha descargado. Actualiza la página ahora o espera a que se actualice automáticamente al cerrar Modrinth App."
},
"app.update-popup.body.linux": {
"message": "Ya está disponible Modrinth App v{version}. ¡Utiliza tu gestor de paquetes para actualizarla y disfrutar de las últimas funciones y correcciones!"
},
"app.update-popup.body.metered": {
"message": "¡Modrinth App v{version} ya está disponible! Como estás conectado a una red con tarifa por datos, no la hemos descargado automáticamente."
},
"app.update-popup.changelog": {
"message": "Registro de cambios"
},
"app.update-popup.download": {
"message": "Descarga ({size})"
},
"app.update-popup.download-complete": {
"message": "Descarga completada"
},
"app.update-popup.reload": {
"message": "Recargar"
},
"app.update-popup.title": {
"message": "Actualización disponible"
},
"app.update.complete-toast.text": {
"message": "Haga clic aquí para ver el registro de cambios."
},
@@ -95,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Recarga para instalar la actualización"
},
"app.world.server-modal.placeholder-address": {
"message": "ejemplo.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Selecciona una opción"
},
"app.world.world-item.incompatible-version": {
"message": "Versión {version} incompatible"
},
"app.world.world-item.not-played-yet": {
"message": "No se ha jugado aún"
},
"app.world.world-item.offline": {
"message": "Desconectado"
},
"app.world.world-item.players-online": {
"message": "{count} en línea"
},
"friends.action.add-friend": {
"message": "Agrega a un amigo"
},
@@ -194,11 +368,11 @@
"instance.edit-world.title": {
"message": "Editar mundo"
},
"instance.filter.disabled": {
"message": "Desactivar proyectos"
"instance.files.adding-files": {
"message": "Añadiendo archivos ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Actualizaciones disponibles"
"instance.files.save-as": {
"message": "Guardar como..."
},
"instance.server-modal.address": {
"message": "Dirección IP"
@@ -308,141 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Instancia"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} para Minecraft {game_version} ya está instalada"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "La versión vanilla {game_version} ya está instalada"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Cambiar versión"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Instalar"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Instalando"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Buscando versiones del modpack"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Instalando versión nueva"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Instalado actualmente"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Información de debug:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Buscando detalles del modpack"
},
"instance.settings.tabs.installation.game-version": {
"message": "Versión del juego"
},
"instance.settings.tabs.installation.install": {
"message": "Instalar"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Instalación en progreso"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} versión"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "No se puede buscar los detalles del modpack enlazado. Por favor revise su conexión a internet."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} no está disponible para Minecraft {version}. Prueba con otro cargador."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "La instancia está enlazada a un modpack, pero el modpack no se ha podido encontrar en Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Plataforma"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Reinstalar modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Reinstalando modpack"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Reinstalar reiniciará todo el contenido instalado o modificado a lo que el modpack proporcione, quitando cualquier mod o contenido que hayas añadido por encima de la instalación original. Esto puede arreglar actividad inesperada, pero si los mundos dependen del contendio adicional instalado, puede romperlos. "
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "¿Estás seguro de que quieres reinstalar esta instancia?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Reinicia el contenido de la instancia a su estado original, quitando cualquier mod o contenido que hayas añadido por encima del modpack original."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Reinstalar modpack"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Reparar"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Reparando"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Reparando reinstalaciones Minecraft dependencias y buscando corrupciones. Esto podría solucionar problemas si tu juego no se está abriendo debido a errores relacionados con el launcher, pero no solucionará problemas o crashes relacionados con mods instalados."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "¿Reparar instancia?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Reparación en progreso"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Reiniciar a actual"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Mostrar todas las versiones"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "cambiar versión"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "instalar"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "reinstalar"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "reparar"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "No se puede {action} mientras se está instalando."
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "No se puede {action} sin conexión"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "No se puede {action} reparando"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(versión desconocida)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Desvincular instancia"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Si procedes, no podrás re-vincular sin crear una nueva instancia. No recibirás actualizaciones del modpack y se convertira en uno normal."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "¿Estás seguro de que quieres desvincular esta instancia?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "La instancia está vinculada a un modpack, lo que significa que los mods no pueden ser actualizados y no puedes cambiar el mod loader o la versión de Minecraft. Desvincular desconectará permanentemente esta instancia del modpack."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Desvincular del modpack"
},
"instance.settings.tabs.java": {
"message": "Java y memoria"
},
@@ -503,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "No mostrar en Inicio"
},
"instance.worlds.filter.available": {
"message": "Disponible"
},
"instance.worlds.game_already_open": {
"message": "La instancia ya está abierta"
},
@@ -515,6 +554,9 @@
"instance.worlds.incompatible_server": {
"message": "Servidor es incompatible"
},
"instance.worlds.linked_server": {
"message": "Gestionado por el proyecto del servidor"
},
"instance.worlds.no_contact": {
"message": "No se pudo contactar con el servidor"
},
@@ -527,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "Jugar instancia"
},
"instance.worlds.type.server": {
"message": "Servidor"
},
"instance.worlds.type.singleplayer": {
"message": "Un jugador"
},
"instance.worlds.view_instance": {
"message": "Ver instancia"
},
@@ -550,5 +586,17 @@
},
"search.filter.locked.instance.sync": {
"message": "Sincronizar con la instancia"
},
"search.filter.locked.server": {
"message": "Proporcionado por el servidor"
},
"search.filter.locked.server-environment.title": {
"message": "Solo se pueden añadir a la instancia del servidor modificaciones del lado del cliente"
},
"search.filter.locked.server-game-version.title": {
"message": "La versión del juego es proporcionada por el servidor"
},
"search.filter.locked.server-loader.title": {
"message": "El cargador lo proporciona el servidor"
}
}
+218 -170
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Todennuspalvelimiin ei saada yhteyttä"
},
"app.browse.add-server-to-instance": {
"message": "Lisää palvelin instanssiin"
},
"app.browse.add-servers-to-instance": {
"message": "Lisää palvelimia instanssiisi"
},
"app.browse.add-to-instance": {
"message": "Lisää instanssiin"
},
"app.browse.add-to-instance-name": {
"message": "Lisää instanssiin {instanceName}"
},
"app.browse.added": {
"message": "Lisätty"
},
"app.browse.already-added": {
"message": "On jo asennettu"
},
"app.browse.discover-content": {
"message": "Löydä sisältöä"
},
"app.browse.discover-servers": {
"message": "Löydä palvelimia"
},
"app.browse.hide-added-servers": {
"message": "Piilota lisätyt palvelimet"
},
"app.browse.hide-installed-content": {
"message": "Piilota asennettu sisältö"
},
"app.browse.install-content-to-instance": {
"message": "Lataa sisältöä instanssiin"
},
"app.export-modal.description-placeholder": {
"message": "Lisää modipaketin kuvaus..."
},
"app.export-modal.export-button": {
"message": "Vie"
},
"app.export-modal.header": {
"message": "Vie modipaketti"
},
"app.export-modal.modpack-name-label": {
"message": "Modipaketin nimi"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modipaketin nimi"
},
"app.export-modal.select-files-label": {
"message": "Valitse tiedostot ja kansiot pakettiin"
},
"app.export-modal.version-number-label": {
"message": "Versio numero"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Kaikki sinun instanssisi data poistetaan pysyvästi, sisältäen maailmasi, konfiguraatiosi ja asennetun sisällön."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Tätä toimintoa ei voi peruuttaa"
},
"app.instance.confirm-delete.delete-button": {
"message": "Poista instannsi"
},
"app.instance.confirm-delete.header": {
"message": "Poista instanssi"
},
"app.instance.modpack-already-installed.body": {
"message": "Tämä modipaketti on jo asennettu instanssiin <bold>{instanceName}</bold>. Oletko varma että haluat kopioida sen?"
},
"app.instance.modpack-already-installed.create": {
"message": "Luo"
},
"app.instance.modpack-already-installed.header": {
"message": "Modipaketti on jo asennettu"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instanssi"
},
"app.instance.mods.content-type-project": {
"message": "projekti"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" lisättiin"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projektia lisättiin"
},
"app.instance.mods.share-text": {
"message": "Tsekkaa projektit joita käytän minun modipaketissani!"
},
"app.instance.mods.successfully-uploaded": {
"message": "Onnistuneesti ladattu"
},
"app.instance.worlds.add-server": {
"message": "Lisää palvelin"
},
"app.instance.worlds.browse-servers": {
"message": "Selaa palvelimia"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' tullaan **poistamaan pysyvästi**, eikä tule olemaan mitään tapaa palauttaa sitä."
},
"app.instance.worlds.delete-world-title": {
"message": "Oletko varma että haluat pysyvästi poistaa tämän maailman?"
},
"app.instance.worlds.filter-modded": {
"message": "Modattu"
},
"app.instance.worlds.filter-offline": {
"message": "Offline-tilassa"
},
"app.instance.worlds.filter-online": {
"message": "Online-tilassa"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Lisää palvelin tai selaa aloittaaksesi"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Ei palvelimia tai maailmoja lisättynä"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' tullaan poistamaan sinun listaltasi, mukaan lukien pelin sisällä, eikä tule olemaan mitään tapaa palauttaa sitä."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) tullaan poistamaan sinun listaltasi, mukaan lukien pelin sisällä, eikä tule olemaan mitään tapaa palauttaa sitä."
},
"app.instance.worlds.remove-server-title": {
"message": "Oletko varma että haluat poistaa {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Hae {count} maailmasta..."
},
"app.instance.worlds.this-server": {
"message": "tämän palvelimen"
},
"app.modal.install-to-play.content-required": {
"message": "Sisältö vaaditaan"
},
"app.modal.install-to-play.header": {
"message": "Asenna pelataksesi"
},
@@ -14,42 +158,30 @@
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# modia}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Vaadittu modipaketti"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Tämä palvelin vaatii modeja toimiakseen. Klikkaa Asenna ladataksesi vaaditut tiedostot Modrinthista, ja käynnistä peli suoraan palvelimelle."
},
"app.modal.install-to-play.shared-instance": {
"message": "Jaettu instanssi"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "Jaettu palvelininstanssi"
},
"app.modal.update-to-play.added-count": {
"message": "{count} lisätty"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Lisätty"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Poistettu"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Päivitetty"
"app.modal.install-to-play.view-contents": {
"message": "Tarkastele sisältöä"
},
"app.modal.update-to-play.header": {
"message": "Päivitä pelataksesi"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} poistettu"
},
"app.modal.update-to-play.update-required": {
"message": "Päivitys vaaditaan"
},
"app.modal.update-to-play.update-required-description": {
"message": "Pävitys vaaditaan pelataksesi {name}. Päivitä viimeisimpään versioon pelataksesi."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} päivitetty"
},
"app.settings.developer-mode-enabled": {
"message": "Kehittäjätila käytössä."
},
@@ -62,9 +194,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Oletusinstanssin asetukset"
},
"app.settings.tabs.feature-flags": {
"message": "Ominaisuuskytkimet"
},
"app.settings.tabs.java-installations": {
"message": "Java asennukset"
},
@@ -77,6 +206,33 @@
"app.settings.tabs.resource-management": {
"message": "Resurssien hallinta"
},
"app.update-popup.body": {
"message": "Modrinth App versio {version} on valmis asennettavaksi. Voit käynnistää sovelluksen uudelleen päivittääksesi heti tai antaa päivityksen asentua automaattisesti, kun suljet Modrinth Appin."
},
"app.update-popup.body.download-complete": {
"message": "Modrinth App versio {version} on ladattu. Voit käynnistää sovelluksen uudelleen päivittääksesi heti tai antaa päivityksen asentua automaattisesti, kun suljet Modrinth Appin."
},
"app.update-popup.body.linux": {
"message": "Modrinth App versio {version} on saatavilla. Käytä paketinhallintasi ja päivitä käyttääksesi uusimpia ominaisuuksia ja korjauksia!"
},
"app.update-popup.body.metered": {
"message": "Modrinth App versio {version} on nyt saatavilla! Koska käytät käytön mukaan laskutettavaa verkkoa, emme ladannut sitä automaattisesti."
},
"app.update-popup.changelog": {
"message": "Muutosloki"
},
"app.update-popup.download": {
"message": "Lataa ({size})"
},
"app.update-popup.download-complete": {
"message": "Lataus valmis"
},
"app.update-popup.reload": {
"message": "Lataa uudelleen"
},
"app.update-popup.title": {
"message": "Päivitys saatavilla"
},
"app.update.complete-toast.text": {
"message": "Klikkaa tästä nähdäksesi muutoslokin."
},
@@ -92,6 +248,24 @@
"app.update.reload-to-update": {
"message": "Lataa uudelleen asentaaksesi päivityksen"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Valitse vaihtoehto"
},
"app.world.world-item.incompatible-version": {
"message": "Yhteensopimaton versio {version}"
},
"app.world.world-item.not-played-yet": {
"message": "Ei pelattu vielä"
},
"app.world.world-item.offline": {
"message": "Offline-tilassa"
},
"app.world.world-item.players-online": {
"message": "{count} paikalla"
},
"friends.action.add-friend": {
"message": "Lisää ystävä"
},
@@ -191,11 +365,11 @@
"instance.edit-world.title": {
"message": "Muokkaa maailmaa"
},
"instance.filter.disabled": {
"message": "Käytöstä poistetut projektit"
"instance.files.adding-files": {
"message": "Lisätään tiedostoja ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Päivityksia saatavilla"
"instance.files.save-as": {
"message": "Tallenna nimellä..."
},
"instance.server-modal.address": {
"message": "Osoite"
@@ -231,7 +405,7 @@
"message": "Ei pystytä monistamaan asennettaessa."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Monista instanssi"
"message": "Monista asennus"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Luo kopion tästä instanssista sekä kaikista sen maailmoista, asetuksista, modeista yms."
@@ -305,141 +479,9 @@
"instance.settings.tabs.installation": {
"message": "Asennus"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} Minecraft versiolle {game_version} on jo asennettu"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} on jo asennettu"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Vaihda versiota"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Asenna"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Asennetaan"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Noudetaan modipaketin versioita"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Asennetaan uutta versiota"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Asennettuna"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Virheenkorjaus informaatio:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Noudetaan modipaketin tietoja"
},
"instance.settings.tabs.installation.game-version": {
"message": "Peli versio"
},
"instance.settings.tabs.installation.install": {
"message": "Asenna"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Asennus käynnissä"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} versio"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Ei voida noutaa linkatun modipaketin tietoja. Tarkista internet yhteytesi."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} ei ole saatavilla Minecraft versiolle {version}. Kokeile toista modi lataajaa."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Tämä instanssi on linkitetty modipakettiin, mutta modipakettia ei löydetty Modrinthista."
},
"instance.settings.tabs.installation.platform": {
"message": "Alusta"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Asenna modipaketti uudelleen"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Asennetaan modipakettia uudelleen"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Uudelleen asentaminen palauttaa kaiken asennetun tai muokatun sisällön siihen muotoon missä se on modipaketissa poistaen kaikki modit ja muun sisällön mitä olet lisännyt alkuperäisen asennuksen päälle. Tämä saattaa korjata odottamatonta käytöstä mikäli instanssia on muokattu mutta jos maailmasi ovat nyt riippuvaisia lisätystä sisällöstä se saattaa rikkoa olemassa olevia maailmoja."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Haluatko varmasti asentaa tämän instanssin uudelleen?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Palauttaa instanssin sisällön alkuperäiseen muotoonsa poistaen kaikki modit tai muun sisällön mitä olet lisännyt alkuperäisen modipaketin päälle."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Asenna modipaketti uudelleen"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Korjaa"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Korjataan"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Korjaaminen uudelleen asentaa Minecraftin riippuvuuksia ja tarkistaa korruptiota varten. Tämä saattaa ratkaista ongelmia jos pelisi ei käynnisty launcheriin liittyvien virheiden takia mutta ei ratkaise ongelmia tai kaatumisia liittyen ladattuihin modeihin."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Korjaa instanssi?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Korjaus käynnissä"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Palauta nykyiseen"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Näytä kaikki versiot"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "vaihda versiota"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "asenna"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "asenna uudelleen"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "korjaa"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Et voi {action} asentaessa"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Toimintoa {action} ei voida suorittaa offline tilassa"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Et voi {action} korjatessa"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(tuntematon versio)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Poista instanssin linkitys"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Jos jatkat et voi uudelleen linkata sitä ilman että luot täysin uuden instanssin. Et vastaanota enää modipaketti päivityksiä ja siitä tulee normaali."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Oletko varma että haluat poistaa tämän instanssin linkityksen?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Tämä instanssi on linkitetty modipakettin joka tarkoittaa että modeja ei voida päivittää etkä voi vaihtaa lataaja tai Minecraft versiota. Linkityksen poistaminen katkaisee pysyvästi yhteyden instanssin ja modipaketin välillä."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Poista linkitys modipakettiin"
},
"instance.settings.tabs.java": {
"message": "Java ja muisti"
},
@@ -500,9 +542,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Älä näytä koti näkymässä"
},
"instance.worlds.filter.available": {
"message": "Saatavilla"
},
"instance.worlds.game_already_open": {
"message": "Instanssi on jo avattu"
},
@@ -512,6 +551,9 @@
"instance.worlds.incompatible_server": {
"message": "Palvelin on yhteensopimaton"
},
"instance.worlds.linked_server": {
"message": "Palvelimen projektin hallinnoima"
},
"instance.worlds.no_contact": {
"message": "Palvelimeen ei saatu yhteyttä"
},
@@ -524,12 +566,6 @@
"instance.worlds.play_instance": {
"message": "Pelaa instanssia"
},
"instance.worlds.type.server": {
"message": "Palvelin"
},
"instance.worlds.type.singleplayer": {
"message": "Yksinpeli"
},
"instance.worlds.view_instance": {
"message": "Näytä instanssi"
},
@@ -546,6 +582,18 @@
"message": "Lataajan antaa instanssi"
},
"search.filter.locked.instance.sync": {
"message": "Synkkaa instanssin kanssa"
"message": "Synkronoi instanssin kanssa"
},
"search.filter.locked.server": {
"message": "Palvelimen tarjoama"
},
"search.filter.locked.server-environment.title": {
"message": "Voit lisätä vain paikallisia modeja palvelin instanssiin"
},
"search.filter.locked.server-game-version.title": {
"message": "Peliversio on palvelimen tarjoama"
},
"search.filter.locked.server-loader.title": {
"message": "Modialusta on palvelimen tarjoama"
}
}
+131 -185
View File
@@ -5,6 +5,120 @@
"app.auth-servers.unreachable.header": {
"message": "Hindi maabot ang mga authentication server"
},
"app.browse.add-server-to-instance": {
"message": "Idagdag ang server sa instansiya"
},
"app.browse.add-servers-to-instance": {
"message": "Idagdag ang mga server sa iyong instansiya"
},
"app.browse.add-to-instance": {
"message": "Idagdag sa instansiya"
},
"app.browse.add-to-instance-name": {
"message": "Idagdag sa {instanceName}"
},
"app.browse.added": {
"message": "Dinagdag"
},
"app.browse.already-added": {
"message": "Nadagdag na"
},
"app.browse.discover-content": {
"message": "Tumuklas ng kontento"
},
"app.browse.discover-servers": {
"message": "Tumuklas ng mga server"
},
"app.browse.hide-added-servers": {
"message": "Taguin ang mga nadagdag na server"
},
"app.browse.hide-installed-content": {
"message": "Taguin ang mga na-install na kontento"
},
"app.browse.install-content-to-instance": {
"message": "I-install ang kontento sa instansiya"
},
"app.export-modal.description-placeholder": {
"message": "Ilagay ang paglalarawan ng modpack..."
},
"app.export-modal.export-button": {
"message": "Iluwas"
},
"app.export-modal.header": {
"message": "Iluwas ang modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Pangalan ng Modpack"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Pangalan ng modpack"
},
"app.export-modal.select-files-label": {
"message": "Pumili ng mga talaksan at folder na isasali sa pack"
},
"app.export-modal.version-number-label": {
"message": "Numero ng bersiyon"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Ang lahat ng data ng iyong instansiya ay tuluyang mawawala, kabilang na ang iyong mga mundo, kumpigurasyon, at lahat ng na-install na kontento."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Hindi mababawi ang aksiyong ito"
},
"app.instance.confirm-delete.delete-button": {
"message": "Tanggalin ang instansiya"
},
"app.instance.confirm-delete.header": {
"message": "Tanggalin ang instansiya"
},
"app.instance.modpack-already-installed.create": {
"message": "Ilikha"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instansiya"
},
"app.instance.mods.content-type-project": {
"message": "proyekto"
},
"app.instance.mods.project-was-added": {
"message": "Ang \"{name}\" ay nadagdag"
},
"app.instance.mods.projects-were-added": {
"message": "{count} proyekto ang nadagdag"
},
"app.instance.mods.share-title": {
"message": "Binabahagi ang kontento ng modpack"
},
"app.instance.mods.successfully-uploaded": {
"message": "Matagumpay na na-upload"
},
"app.instance.worlds.add-server": {
"message": "Magdagdag ng server"
},
"app.instance.worlds.filter-modded": {
"message": "Modded"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.remove-server-title": {
"message": "Sigurado ka bang gusto mong tanggalin ang {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Hanapin sa {count} mundo..."
},
"app.instance.worlds.this-server": {
"message": "server na ito"
},
"app.modal.install-to-play.content-required": {
"message": "Nangangailangan ng kontento"
},
@@ -32,38 +146,17 @@
"app.modal.install-to-play.view-contents": {
"message": "Tingnan ang mga kontento"
},
"app.modal.update-to-play.added-count": {
"message": "{count} nadagdag"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Dinagdag"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Tinanggal"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Na-update"
},
"app.modal.update-to-play.header": {
"message": "Mag-update upang malaro"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} tinanggal"
},
"app.modal.update-to-play.update-required": {
"message": "Kailangang mag-update"
},
"app.modal.update-to-play.update-required-description": {
"message": "Kailangang mag-update upang malaro ang {name}. Mangyaring mag-update sa pinakabagong bersiyon upang ma-launch ang laro."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} na-update"
},
"app.settings.developer-mode-enabled": {
"message": "Nakabukas ang moda ng nagdidibelop."
"message": "Binuksan ang moda ng nagdi-develop."
},
"app.settings.downloading": {
"message": "Dina-download ang v{version}"
@@ -74,9 +167,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Mga pagpipilian sa default na instansiya"
},
"app.settings.tabs.feature-flags": {
"message": "Mga hudyat ng tampok"
},
"app.settings.tabs.java-installations": {
"message": "Mga instalasyon ng Java"
},
@@ -131,6 +221,18 @@
"app.update.reload-to-update": {
"message": "Handang ma-install ang update"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Pumili ng opsiyon"
},
"app.world.world-item.incompatible-version": {
"message": "Di-magkatugmang bersiyong {version}"
},
"app.world.world-item.offline": {
"message": "Offline"
},
"friends.action.add-friend": {
"message": "Magdagdag ng kaibigan"
},
@@ -201,10 +303,10 @@
"message": "Idagdag ang server"
},
"instance.add-server.resource-pack.disabled": {
"message": "Hindi pinahihintulotan"
"message": "Tanggihan"
},
"instance.add-server.resource-pack.enabled": {
"message": "Pinahihintulotan"
"message": "Payagan"
},
"instance.add-server.resource-pack.prompt": {
"message": "Magpahintulot"
@@ -216,7 +318,7 @@
"message": "Baguhin ang server"
},
"instance.edit-world.hide-from-home": {
"message": "Huwag ipakita sa Home na pahina"
"message": "Itago sa pahina ng Tahanan"
},
"instance.edit-world.name": {
"message": "Pangalan"
@@ -230,12 +332,6 @@
"instance.edit-world.title": {
"message": "Baguhin ang mundo"
},
"instance.filter.disabled": {
"message": "Mga hindi pinapagang proyekto"
},
"instance.filter.updates-available": {
"message": "May bagong mga update"
},
"instance.server-modal.address": {
"message": "Adres"
},
@@ -344,150 +440,9 @@
"instance.settings.tabs.installation": {
"message": "Instalasyon"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "Naka-install naman ang {platform} {version} para sa Minecraft {game_version}"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Naka-install naman ang Vanilla {game_version}"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Palitan ang bersiyon"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "I-install"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Ini-install"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Nagfe-fetch ng mga bersiyon ng modpack"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Ini-install ang bagong bersiyon"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Kasalukuyang naka-install"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Impormasyon sa pagdebug:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Nagfe-fetch ng mga detalye ng modpack"
},
"instance.settings.tabs.installation.game-version": {
"message": "Bersiyon ng laro"
},
"instance.settings.tabs.installation.install": {
"message": "I-install"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Nag-i-install ngayon"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Bersiyon ng {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Hindi maka-fetch ng mga detalye ng linked modpack. Mangyaring tingnan ang iyong internet connection."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "Hindi magagamit ang {loader} sa Minecraft {version}. Sumubok ng ibang mod loader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Naka-link itong instansiya sa isang modpack, pero ang modpack na ito ay hindi makikita sa Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Plataporma"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "I-reinstall ang modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Ini-re-reinstall ang modpack"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Ang pagrere-install ay maaaring ma-reset ang lahat ng na-install at binago na kontento sa kung anong hinahandog ng modpack, tatanggalin ang mga mods at kontentong idinagdag mo sa orihinal na modpack. Maaari nitong masiayos ang mga hindi inaasahang pag-uugali kung may pagbabagong naganap sa instansiya, ngunit kung dumedepende na ang iyong mundo sa karagdagang kontento, maaari nitong masira ang mga umiiral na mundo."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Sigurado ka bang gusto mong i-reinstall ang instansiyang ito?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Mare-reset ang mga kontento ng instansiya sa orihinal niyang estado, tatanggalin ang mga mod at kontentong idinagdag mo sa orihinal na modpack."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "I-reinstall ang modpack"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Ayusin"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Inaayos"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Sa pagre-repair, mare-reinstall ang mga dependency ng Minecraft at maghahanap ng mga kurapsiyon. Maaaring maresolbe nito ang mga isyu kung hindi malu-launch ang laro dahil sa mga launcher-related error, ngunit hindi nito mareresolbe ang mga isyu at pag-crash na dulot ng mga na-install na mod."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Ayusin ang instansiya?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Inaayos ngayon"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Sa kasalukuyan i-reset"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Ipakita ang lahat ng bersiyon"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "palitan ang bersiyon"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "i-install"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "i-reinstall"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "ayusin"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Hindi makaka-{action} habang nag-i-install"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Hindi makaka-{action} habang nasa offline"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Hindi makaka-{action} habang nag-aayos"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(hindi kilalang bersiyon)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Ang instansiyang ito ay naka-link sa isang server, ibig sabihin ay hindi mo mapapalitan ang bersiyon ng Minecraft. Permanenteng madi-diskonekta ang instansiyang ito sa server kung mag-unlink."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Ang instansiyang ito ay naka-link sa isang server, ibig sabihin ang mga mod ay hindi mai-update at hindi mo mapapalitan ang mod loader at ang bersiyon ng Minecraft. Permanenteng madi-diskonekta ang instansiyang ito sa server kung mag-unlink."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "I-unlink sa server"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "I-unlink sa instansiya"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Kapag ipagpatuloy mo, hindi mo na itong mai-link muli ng hindi gagawa ng bagong instansiya. Hindi ka makakatanggap ng mga update ng modpack at magiging normal na itong."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Sigurado ka bang gusto mong i-unlik ang instansiyang ito?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Ang instansiyang ito ay naka-link sa isang modpack, ibig sabihin ang mga mod ay hindi mai-update at hindi mo mapapalitan ang mod loader at ang bersiyon ng Minecraft. Permanenteng madi-diskonekta ang instansiyang ito sa modpack kung mag-unlink."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "I-unlink sa modpack"
},
"instance.settings.tabs.java": {
"message": "Java at memorya"
},
@@ -546,10 +501,7 @@
"message": "Kopyahin ang adres"
},
"instance.worlds.dont_show_on_home": {
"message": "Huwag ipakita sa Home"
},
"instance.worlds.filter.available": {
"message": "Magagamit"
"message": "Huwag ipakita sa Tahanan"
},
"instance.worlds.game_already_open": {
"message": "Bukas naman ang instansiya"
@@ -575,12 +527,6 @@
"instance.worlds.play_instance": {
"message": "Laruin ang instansiya"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Pang-isahang laro"
},
"instance.worlds.view_instance": {
"message": "Tingnan ang instansiya"
},
+169 -181
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Impossible de contacter les serveurs d'authentification"
},
"app.browse.add-server-to-instance": {
"message": "Ajouter le serveur à l'instance"
},
"app.browse.add-servers-to-instance": {
"message": "Ajouter des serveurs à votre instance"
},
"app.browse.add-to-instance": {
"message": "Ajouter à l'instance"
},
"app.browse.add-to-instance-name": {
"message": "Ajouter à {instanceName}"
},
"app.browse.added": {
"message": "Ajouté"
},
"app.browse.already-added": {
"message": "Déjà ajouté"
},
"app.browse.discover-content": {
"message": "Découvrir du contenu"
},
"app.browse.discover-servers": {
"message": "Découvrir des serveurs"
},
"app.browse.hide-added-servers": {
"message": "Masquer les serveurs ajoutés"
},
"app.browse.hide-installed-content": {
"message": "Masquer le contenu installé"
},
"app.browse.install-content-to-instance": {
"message": "Installer du contenu à l'instance"
},
"app.export-modal.description-placeholder": {
"message": "Saisir la description du modpack..."
},
"app.export-modal.export-button": {
"message": "Exporter"
},
"app.export-modal.header": {
"message": "Exporter le modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Nom du modpack"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nom du modpack"
},
"app.export-modal.select-files-label": {
"message": "Sélectionnez des fichiers et des dossiers à inclure dans le pack"
},
"app.export-modal.version-number-label": {
"message": "Numéro de version"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Toutes les données pour votre instance seront supprimées à jamais, y compris vos mondes, vos configurations, et le contenu installé."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Cette action est irréversible"
},
"app.instance.confirm-delete.delete-button": {
"message": "Supprimer l'instance"
},
"app.instance.confirm-delete.header": {
"message": "Supprimer l'instance"
},
"app.instance.modpack-already-installed.body": {
"message": "Ce modpack est déjà installé sur l'instance <bold>{instanceName}</bold>. Êtes-vous sûr.e de vouloir le dupliquer ?"
},
"app.instance.modpack-already-installed.create": {
"message": "Créer"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack déjà installé"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instance"
},
"app.instance.mods.content-type-project": {
"message": "projet"
},
"app.instance.mods.project-was-added": {
"message": "« {name} » a été ajouté"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projets ont été ajoutés"
},
"app.instance.mods.share-text": {
"message": "Jette un coup d'œil aux projets que j'utilise dans mon modpack !"
},
"app.instance.mods.share-title": {
"message": "Partage du contenu de votre modpack"
},
"app.instance.mods.successfully-uploaded": {
"message": "Mis en ligne avec succès"
},
"app.instance.worlds.add-server": {
"message": "Ajouter le serveur"
},
"app.instance.worlds.browse-servers": {
"message": "Parcourir des serveurs"
},
"app.instance.worlds.delete-world-description": {
"message": "« {name} » sera supprimé **pour toujours**, et il sera impossible de le récupérer."
},
"app.instance.worlds.delete-world-title": {
"message": "Êtes-vous sûr.e de vouloir supprimer ce monde pour toujours ?"
},
"app.instance.worlds.filter-modded": {
"message": "Moddé"
},
"app.instance.worlds.filter-offline": {
"message": "Hors ligne"
},
"app.instance.worlds.filter-online": {
"message": "En ligne"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Ajouter un serveur ou parcourir pour commencer"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Aucun serveur ou monde ajoutés"
},
"app.instance.worlds.remove-server-description": {
"message": "« {name} » sera retiré de votre liste, y compris en jeu, et il sera impossible de le récupérer."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "« {name} » ({address}) sera retiré de votre liste, y compris en jeu, et il sera impossible de le récupérer."
},
"app.instance.worlds.remove-server-title": {
"message": "Êtes-vous sûr.e de vouloir retirer {name} ?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Rechercher {count} mondes..."
},
"app.instance.worlds.this-server": {
"message": "ce serveur"
},
"app.modal.install-to-play.content-required": {
"message": "Contenu requis"
},
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Voir le contenu"
},
"app.modal.update-to-play.added-count": {
"message": "{count} {count, plural, one {# ajouté} other {# ajoutés}}"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Ajouté"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Retiré"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Mis à jour"
},
"app.modal.update-to-play.header": {
"message": "Mettre à jour pour jouer"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} {count, plural, one {# retiré} other {# retirés}}"
},
"app.modal.update-to-play.update-required": {
"message": "Mise à jour requise"
},
"app.modal.update-to-play.update-required-description": {
"message": "Une mise à jour est requise pour jouer à {name}. Veuillez mettre à jour à la dernière version pour lancer le jeu."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} mis à jour"
},
"app.settings.developer-mode-enabled": {
"message": "Mode développeur activé."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Options dinstance par défaut"
},
"app.settings.tabs.feature-flags": {
"message": "Menu de fonctionnalité"
},
"app.settings.tabs.java-installations": {
"message": "Installations de Java"
},
@@ -90,7 +210,7 @@
"message": "Gestion des ressources"
},
"app.update-popup.body": {
"message": "Modrinth App v{version} est prête à être installée ! Rechargez pour mettre à jour maintenant, ou automatiquement quand vous fermez Modrinth App."
"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-popup.body.download-complete": {
"message": "Modrinth App v{version} a finie d'être téléchargée. Rechargez pour mettre à jour maintenant, ou automatiquement quand vous fermez Modrinth App."
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Relancez l'application pour installer la mise à jour"
},
"app.world.server-modal.placeholder-address": {
"message": "exemple.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Sélectionner une option"
},
"app.world.world-item.incompatible-version": {
"message": "Version {version} incompatible"
},
"app.world.world-item.not-played-yet": {
"message": "Pas encore joué"
},
"app.world.world-item.offline": {
"message": "Hors ligne"
},
"app.world.world-item.players-online": {
"message": "{count, plural, =0 {Personne en ligne} one {# est en ligne} other {# sont en ligne}}"
},
"friends.action.add-friend": {
"message": "Ajouter un ami"
},
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Modifier le monde"
},
"instance.filter.disabled": {
"message": "Projets désactivés"
"instance.files.adding-files": {
"message": "Ajout de fichiers ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Mises à jour disponibles"
"instance.files.save-as": {
"message": "Sauvegarder en tant que..."
},
"instance.server-modal.address": {
"message": "Adresse"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Installation"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} pour Minecraft {game_version} est déjà installé"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} est déjà installé"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Changer de version"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Installer"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Installation"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Récupération des versions de modpack"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Installation d'une nouvelle version"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Actuellement installé"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Informations de débogage :"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Récupération des détails de modpack"
},
"instance.settings.tabs.installation.game-version": {
"message": "Version du jeu"
},
"instance.settings.tabs.installation.install": {
"message": "Installer"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Installation en cours"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Version de {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Impossible de récupérer les détails du modpack lié. Veuillez vérifier votre connexion Internet."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} n'est pas disponible pour Minecraft {version}. Essayez avec un autre chargeur de mods."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Cette instance est liée à un modpack, mais le modpack n'a pas pu être trouvé sur Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Plateforme"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Réinstaller le modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Réinstallation du modpack"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "La réinstallation réinitialisera tout le contenu installé ou modifié à celui fourni par le modpack, supprimant ainsi tous les mods ou contenus ajoutés à l'installation d'origine. Cela peut corriger un comportement inattendu si des modifications ont été apportées à l'instance, mais si vos mondes dépendent désormais de contenu supplémentaire installé, cela peut endommager les mondes existants."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Êtes-vous sûr de vouloir réinstaller cette instance ?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Réinitialise le contenu de l'instance à son état d'origine, en supprimant tous les mods ou contenus que vous avez ajoutés au modpack d'origine."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Réinstaller le modpack"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Réparer"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"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 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 ?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Réparation en cours"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Restaurer à l’état actuel"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Voir toutes les versions"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "changer la version"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "installer"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "réinstaller"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "réparer"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Impossible de {action} pendant l'installation"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Impossible de {action} hors ligne"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Impossible de {action} pendant la réparation"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(version inconnue)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Cette instance est liée à un modpack, ce qui veut dire que vous ne pouvez pas changer la version de Minecraft. Délier déconnectera cette instance du serveur en permanence."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Cette instance est liée à un serveur, ce qui veut dire que les mods ne peuvent pas être mis à jour et que vous ne pouvez pas changer de mod loader ou de version de Minecraft. Délier déconnectera cette instance du serveur en permanence."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Délier du serveur"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Délier l'instance"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Si vous continuez, vous ne pourrez pas la relier de nouveau sans créer une toute nouvelle instance. Vous ne recevrez plus de mises à jour du modpack et elle deviendra une instance normale."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Êtes-vous sûr de vouloir délier cette instance ?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Cette instance est liée à un modpack, ce qui veut dire que les mods ne peuvent être mis à jour et vous ne pouvez pas changer le modloader ou la version de Minecraft. La délier va déconnecter l'instance du modpack de façon permanente."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Délier du modpack"
},
"instance.settings.tabs.java": {
"message": "Java et mémoire"
},
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Ne pas montrer dans l'Accueil"
},
"instance.worlds.filter.available": {
"message": "Disponible"
},
"instance.worlds.game_already_open": {
"message": "L'instance est déjà ouverte"
},
@@ -570,17 +564,11 @@
"message": "Vous pouvez seulement entrer directement dans les serveurs sur Minecraft Alpha 1.0.5+"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Vous pouvez seulement entrer directement dans les mondes solo sur Minecraft Alpha 1.20+"
"message": "Vous pouvez seulement entrer directement dans les mondes solo sur Minecraft 1.20+"
},
"instance.worlds.play_instance": {
"message": "Jouer à l'instance"
},
"instance.worlds.type.server": {
"message": "Serveur"
},
"instance.worlds.type.singleplayer": {
"message": "Solo"
},
"instance.worlds.view_instance": {
"message": "Voir l'instance"
},
@@ -609,6 +597,6 @@
"message": "Version du jeu est procurée par le serveur"
},
"search.filter.locked.server-loader.title": {
"message": "Loader est procuré par le serveur"
"message": "Le loader est procuré par le serveur"
}
}
+219 -168
View File
@@ -5,6 +5,153 @@
"app.auth-servers.unreachable.header": {
"message": "לא ניתן לגשת לשרתי האימות"
},
"app.browse.add-server-to-instance": {
"message": "הוסף שרת להתקנה"
},
"app.browse.add-servers-to-instance": {
"message": "הוסף שרתים להתקנה שלך"
},
"app.browse.add-to-instance": {
"message": "הוספה להתקנה"
},
"app.browse.add-to-instance-name": {
"message": "הוסף אל {instanceName}"
},
"app.browse.added": {
"message": "נוסף"
},
"app.browse.already-added": {
"message": "כבר נוסף"
},
"app.browse.discover-content": {
"message": "גלה תוכן"
},
"app.browse.discover-servers": {
"message": "גלה שרתים"
},
"app.browse.hide-added-servers": {
"message": "הסתר שרתים שנוספו"
},
"app.browse.hide-installed-content": {
"message": "הסתר תוכן מותקן"
},
"app.browse.install-content-to-instance": {
"message": "הוספת התוכן להתקנה"
},
"app.export-modal.description-placeholder": {
"message": "הזן את תיאור חבילת המודים..."
},
"app.export-modal.export-button": {
"message": "יצוא"
},
"app.export-modal.header": {
"message": "יצוא חבילת מודים"
},
"app.export-modal.modpack-name-label": {
"message": "שם חבילת המודים"
},
"app.export-modal.modpack-name-placeholder": {
"message": "שם חבילת המודים"
},
"app.export-modal.select-files-label": {
"message": "בחר קבצים ותיקיות להכללה בחבילה הזו"
},
"app.export-modal.version-number-label": {
"message": "מספר גרסה"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "כל הנתונים של ההתקנה שלך ימחקו לתמיד, זה כולל את העולמות שלך, ההגדרות וכל התוכן שהתקנת."
},
"app.instance.confirm-delete.admonition-header": {
"message": "הפעולה הזו לא ניתנת לביטול"
},
"app.instance.confirm-delete.delete-button": {
"message": "מחק התקנה"
},
"app.instance.confirm-delete.header": {
"message": "מחיקת התקנה"
},
"app.instance.modpack-already-installed.body": {
"message": "חבילת המודים הזו כבר מותקנת בתוך ההתקנה <bold>{instanceName}</bold>. האם אתה בטוח שברצונך לשכפל אותה?"
},
"app.instance.modpack-already-installed.create": {
"message": "צור"
},
"app.instance.modpack-already-installed.header": {
"message": "חבילת המודים הזאת כבר מותקנת"
},
"app.instance.modpack-already-installed.instance": {
"message": "התקנה"
},
"app.instance.mods.content-type-project": {
"message": "פרויקט"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" נוסף"
},
"app.instance.mods.projects-were-added": {
"message": "{count} פרויקטים נוספו"
},
"app.instance.mods.share-text": {
"message": "בדוק את הפרויקטים שאני משתמש בהם בחבילת המודים שלי!"
},
"app.instance.mods.share-title": {
"message": "משתף את התוכן של חבילת המודים"
},
"app.instance.mods.successfully-uploaded": {
"message": "הועלה בהצלחה"
},
"app.instance.worlds.add-server": {
"message": "הוסף שרת"
},
"app.instance.worlds.browse-servers": {
"message": "עיון בשרתים"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' יימחק לצמיתות, ולא תהיה דרך לשחזר אותו."
},
"app.instance.worlds.delete-world-title": {
"message": "האם אתה בטוח שברצונך למחוק לצמיתות את העולם הזה?"
},
"app.instance.worlds.filter-modded": {
"message": "עם מודים"
},
"app.instance.worlds.filter-offline": {
"message": "לא מקוון"
},
"app.instance.worlds.filter-online": {
"message": "מחובר"
},
"app.instance.worlds.filter-vanilla": {
"message": "ונילה"
},
"app.instance.worlds.no-worlds-description": {
"message": "הוספת שרת או עיון כדי להתחיל"
},
"app.instance.worlds.no-worlds-heading": {
"message": "אין שרתים אן עולמות שנוספו"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' יוסר מהרשימה שלך, כולל מתוך המשחק, ולא תהיה דרך לשחזר אותו."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) יוסר מהרשימה שלך, כולל מתוך המשחק, ולא תהיה דרך לשחזר אותו."
},
"app.instance.worlds.remove-server-title": {
"message": "אתה בטוח שאתה רוצה להסיר {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "חיפוש ב-{count} עולמות..."
},
"app.instance.worlds.this-server": {
"message": "השרת הזה"
},
"app.modal.install-to-play.content-required": {
"message": "תוכן נדרש"
},
"app.modal.install-to-play.header": {
"message": "צריך להתקין כדי לשחק"
},
@@ -14,42 +161,30 @@
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {מוד אחד} other {# מודים}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "חבילת מודים נדרשת"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "שרת זה דורש מודים כדי לשחק. לחץ על \"התקן\" כדי להגדיר את הקבצים הנדרשים מ-Modrinth, ולאחר מכן הפעל ישירות לשרת."
},
"app.modal.install-to-play.shared-instance": {
"message": "התקנה משותפת"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "התקנת שרת משותפת"
},
"app.modal.update-to-play.added-count": {
"message": "{count} נוספו"
},
"app.modal.update-to-play.diff-type.added": {
"message": "נוסף"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "הוסר"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "עודכן"
"app.modal.install-to-play.view-contents": {
"message": "הצג תוכן"
},
"app.modal.update-to-play.header": {
"message": "צריך לעדכן כדי לשחק"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} הוסרו"
},
"app.modal.update-to-play.update-required": {
"message": "עדכון נדרש"
},
"app.modal.update-to-play.update-required-description": {
"message": "עדכון נדרש כדי לשחק ב{name}. ניתן להתחיל את המשחק רק לאחר עדכון לגרסה החדשה."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} עודכנו"
},
"app.settings.developer-mode-enabled": {
"message": "מצב מפתח מופעל."
},
@@ -62,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "אפשרויות ברירת מחדל של התקנה"
},
"app.settings.tabs.feature-flags": {
"message": "הגדרות ניסיוניות"
},
"app.settings.tabs.java-installations": {
"message": "התקנות ג'אווה"
},
@@ -77,6 +209,33 @@
"app.settings.tabs.resource-management": {
"message": "ניהול משאבים"
},
"app.update-popup.body": {
"message": "Modrinth App v{version} מוכנה להורדה!\nיש לרענן כדי לעדכן עכשיו, או באופן אוטומטי בעת סגירת האפליקציה."
},
"app.update-popup.body.download-complete": {
"message": "Modrinth App v{version} סיימה את תהליך ההורדה. יש לרענן כדי לעדכן עכשיו, או באופן אוטומטי בעת סגירת האפליקציה."
},
"app.update-popup.body.linux": {
"message": "Modrinth App v{version} זמין. יש להשתמש במנהל חבילות שלך כדי לעדכן בשביל התכונות החדשות ותיקונים!"
},
"app.update-popup.body.metered": {
"message": "Modrinth App v{version} זמינה עכשיו! בגלל החיבור לפי שימוש, לא הורדנו אותה אוטומטית."
},
"app.update-popup.changelog": {
"message": "יומן שינויים"
},
"app.update-popup.download": {
"message": "הורדה ({size})"
},
"app.update-popup.download-complete": {
"message": "הורדה הושלמה"
},
"app.update-popup.reload": {
"message": "רענן"
},
"app.update-popup.title": {
"message": "עדכון זמין"
},
"app.update.complete-toast.text": {
"message": "לחיצה כדי לראות את יומן השינויים."
},
@@ -92,6 +251,24 @@
"app.update.reload-to-update": {
"message": "צריך לרענן כדי להתקין את העדכון"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "בחר אופציה"
},
"app.world.world-item.incompatible-version": {
"message": "גרסה לא תואמת: {version}"
},
"app.world.world-item.not-played-yet": {
"message": "עדיין לא שוחק"
},
"app.world.world-item.offline": {
"message": "לא מקוון"
},
"app.world.world-item.players-online": {
"message": "{count} מחוברים"
},
"friends.action.add-friend": {
"message": "הוספת חבר"
},
@@ -191,11 +368,11 @@
"instance.edit-world.title": {
"message": "ערוך עולם"
},
"instance.filter.disabled": {
"message": "פרויקטים מושבתים"
"instance.files.adding-files": {
"message": "הוספת קבצים ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "עדכונים זמינים"
"instance.files.save-as": {
"message": "שמור כ..."
},
"instance.server-modal.address": {
"message": "כתובת"
@@ -305,141 +482,9 @@
"instance.settings.tabs.installation": {
"message": "התקנה"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} בשביל Minecraft {game_version} כבר מותקן"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "וונילה {game_version} כבר מותקן"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "שינוי גרסה"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "התקן"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "מתקין"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "מאחזר גרסאות חבילת מודים"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "מתקין גרסה חדשה"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "מותקן כעת"
},
"instance.settings.tabs.installation.debug-information": {
"message": "מידע ניפוי שגיאות:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "מאחזר פרטי חבילת מודים"
},
"instance.settings.tabs.installation.game-version": {
"message": "גרסת משחק"
},
"instance.settings.tabs.installation.install": {
"message": "התקן"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "ההתקנה בתהליך"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} גרסה"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "לא ניתן לאחזר את פרטי חבילת המודים המקושרת. יש לבדוק את חיבור האינטרנט שלך."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} אינו זמין עבור Minecraft {version}. אנא נסה טוען מודים אחר."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "התקנה זאת מקושרת לחבילת מודים, אך חבילת המודים לא נמצאה בModrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "פלטפורמה"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "התקן מחדש את חבילת המודים"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "מתקין מחדש את חבילת המודים"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "התקנה מחדש תאפס את כל התוכן המותקן או ששונה, ותחזיר אותו למצב שסופק על ידי חבילת המודים, תוך הסרת כל מוד או תוכן שהוספתם מעבר להתקנה המקורית. פעולה זו עשויה לתקן תקלות שנגרמו משינויים בהתקנה, אך אם העולמות שלכם תלויים בתוכן נוסף שהותקן, היא עלולה לשבש אותם."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "האם אתה בטוח שברצונך להתקין מחדש instance זה?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "מאפס את התוכן שנמצא בהתקנה למצבו המקורי, תוך הסרת כל מוד או תוכן ששונה מעבר לחבילת המודים המקורית."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "התקן מחדש חבילת מודים"
},
"instance.settings.tabs.installation.repair.button": {
"message": "תיקון"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "מתקן"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "התיקון מתקין מחדש את התלויות של מיינקראפט ובודק דברים מקולקלים. פעולה זו עשויה לפתור בעיות שמונעות את הפעלת המשחק עקב שגיאות הקשורות למשגר, אך לא תפתור בעיות או קריסות הקשורות למודים המותקנים."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "לתקן את המכונה?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "תיקון בתהליך"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "אפס לגרסה הנוכחית"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "הצג את כל הגרסאות"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "שנה גרסה"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "התקן"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "התקן מחדש"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "תקן"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "לא ניתן לבצע {action} בזמן ההתקנה"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "לא ניתן לבצע {action} במצב לא מקוון"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "לא יכול {action} בזמן תיקון"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(גרסה לא ידועה)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "לבטל את הקישור של ההתקנה הזו"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "אם תמשיך, לא תוכל לקשר אותה מחדש מבלי ליצור התקנה חדשה לחלוטין. לא תקבל עוד עדכונים לחבילת המודים, והיא תהפוך להתקנה רגילה."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "האם אתה בטוח שברצונך לנתק את הקישור ל-instance הזה?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "התקנה זאת מקושרת לחבילת מודים, מה שאומר שלא ניתן לעדכן מודים ולא ניתן לשנות את טוען המודים או את גרסת המיינקראפט. הניתוק יבטל לצמיתות את הקישור של התקנה זאת לחבילת המודים."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "נתק קישור מחבילת מודים"
},
"instance.settings.tabs.java": {
"message": "ג'אווה וזיכרון"
},
@@ -500,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "אל תציג בדף הבית"
},
"instance.worlds.filter.available": {
"message": "זמין"
},
"instance.worlds.game_already_open": {
"message": "התקנה כבר פתוחה"
},
@@ -512,6 +554,9 @@
"instance.worlds.incompatible_server": {
"message": "שרת לא מתאים"
},
"instance.worlds.linked_server": {
"message": "מנוהל על ידי פרויקט שרת"
},
"instance.worlds.no_contact": {
"message": "לא ניתן ליצור קשר עם השרת"
},
@@ -524,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "שחק בהתקנה"
},
"instance.worlds.type.server": {
"message": "שרת"
},
"instance.worlds.type.singleplayer": {
"message": "שחקן יחיד"
},
"instance.worlds.view_instance": {
"message": "הצג התקנה"
},
@@ -547,5 +586,17 @@
},
"search.filter.locked.instance.sync": {
"message": "סנכרן עם התקנה"
},
"search.filter.locked.server": {
"message": "מסופק על ידי השרת"
},
"search.filter.locked.server-environment.title": {
"message": "ניתן להוסיף רק מודים בצד הלקוח לשרת"
},
"search.filter.locked.server-game-version.title": {
"message": "גרסת המשחק מסופקת על ידי השרת"
},
"search.filter.locked.server-loader.title": {
"message": "הטוען מסופק על ידי השרת"
}
}
+173 -185
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Nem lehet elérni a hitelesítési kiszolgálókat"
},
"app.browse.add-server-to-instance": {
"message": "Szerver hozzáadása a profilhoz"
},
"app.browse.add-servers-to-instance": {
"message": "Szerverek hozzáadása a profilodhoz"
},
"app.browse.add-to-instance": {
"message": "Hozzáadás a profilhoz"
},
"app.browse.add-to-instance-name": {
"message": "Hozzáadás ehhez: {instanceName}"
},
"app.browse.added": {
"message": "Hozzáadva"
},
"app.browse.already-added": {
"message": "Már hozzá van adva"
},
"app.browse.discover-content": {
"message": "Tartalom böngészése"
},
"app.browse.discover-servers": {
"message": "Szerverek böngészése"
},
"app.browse.hide-added-servers": {
"message": "Hozzáadott szerverek elrejtése"
},
"app.browse.hide-installed-content": {
"message": "A telepített tartalmak elrejtése"
},
"app.browse.install-content-to-instance": {
"message": "Tartalom letöltése a profilhoz"
},
"app.export-modal.description-placeholder": {
"message": "Írd be a modcsomag leírását..."
},
"app.export-modal.export-button": {
"message": "Exportálás"
},
"app.export-modal.header": {
"message": "Modcsomag exportálása"
},
"app.export-modal.modpack-name-label": {
"message": "A modcsomag neve"
},
"app.export-modal.modpack-name-placeholder": {
"message": "A modcsomag neve"
},
"app.export-modal.select-files-label": {
"message": "Válaszd ki a csomagba felveendő fájlokat és mappákat"
},
"app.export-modal.version-number-label": {
"message": "Verziószám"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Az profilodhoz tartozó összes adat véglegesen törlődik, beleértve a világokat, a beállításokat és az összes telepített tartalmat."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Ezt a műveletet nem lehet visszavonni"
},
"app.instance.confirm-delete.delete-button": {
"message": "Profil törlése"
},
"app.instance.confirm-delete.header": {
"message": "Profil törlése"
},
"app.instance.modpack-already-installed.body": {
"message": "Ez a modcsomag már telepítve van a(z) <bold>{instanceName}</bold> profilban. Biztosan duplikálni szeretnéd?"
},
"app.instance.modpack-already-installed.create": {
"message": "Létrehozás"
},
"app.instance.modpack-already-installed.header": {
"message": "A modcsomag már telepítve van"
},
"app.instance.modpack-already-installed.instance": {
"message": "Profil"
},
"app.instance.mods.content-type-project": {
"message": "projekt"
},
"app.instance.mods.project-was-added": {
"message": " „{name}” hozzá lett adva"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projekt került hozzáadásra"
},
"app.instance.mods.share-text": {
"message": "Nézd meg, milyen projekteket használok a modcsomagomban!"
},
"app.instance.mods.share-title": {
"message": "Modcsomag-tartalmak megosztása"
},
"app.instance.mods.successfully-uploaded": {
"message": "Sikeresen feltöltve"
},
"app.instance.worlds.add-server": {
"message": "Szerver hozzáadása"
},
"app.instance.worlds.browse-servers": {
"message": "Szerverek böngészése"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' **véglegesen törlődik**, és azt semmilyen módon nem lehet majd helyreállítani."
},
"app.instance.worlds.delete-world-title": {
"message": "Biztosan véglegesen törölni szeretnéd ezt a világot?"
},
"app.instance.worlds.filter-modded": {
"message": "Modolt"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Kezdéshez adj hozzá egy szervert, vagy böngéssz"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Nincs szerver vagy világ"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' eltávolításra kerül a listádról, beleértve a játékon belülieket is. Ezt a lépést nem tudod visszavonni."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) eltávolításra kerül a listádról, beleértve a játékon belülieket is. Ezt a lépést nem tudod visszavonni."
},
"app.instance.worlds.remove-server-title": {
"message": "Biztosan el akarod távolítani ezt: {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Keresés {count} világ között..."
},
"app.instance.worlds.this-server": {
"message": "ez a szerver"
},
"app.modal.install-to-play.content-required": {
"message": "Szükséges tartalom"
},
@@ -15,7 +159,7 @@
"message": "Telepítés"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural,one {# mod}other {# modok}}"
"message": "{count} mod"
},
"app.modal.install-to-play.required-modpack": {
"message": "Szükséges modcsomag"
@@ -30,38 +174,17 @@
"message": "Megosztott szerverprofil"
},
"app.modal.install-to-play.view-contents": {
"message": "Tartalom megjelenítése"
},
"app.modal.update-to-play.added-count": {
"message": "{count} hozzáadva"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Hozzáadva:"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Eltávolítva:"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Frissítve"
"message": "Tartalom megtekintése"
},
"app.modal.update-to-play.header": {
"message": "Frissítsd a játékhoz"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} eltávolítva"
},
"app.modal.update-to-play.update-required": {
"message": "Frissítés szükséges"
},
"app.modal.update-to-play.update-required-description": {
"message": "\nFrissítés szükséges ehhez: {name}. Kérjük, frissíts a legújabb verzióra a játék elindításához"
},
"app.modal.update-to-play.updated-count": {
"message": "{count} frissítve"
},
"app.settings.developer-mode-enabled": {
"message": "Fejlesztői mód bekapcsolva."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Alapértelmezett profil beállítások"
},
"app.settings.tabs.feature-flags": {
"message": "Funkciójelzők"
},
"app.settings.tabs.java-installations": {
"message": "Telepített Java példányok"
},
@@ -108,7 +228,7 @@
"message": "Letöltés ({size})"
},
"app.update-popup.download-complete": {
"message": "Letöltés sikeres"
"message": "Sikeres letöltés"
},
"app.update-popup.reload": {
"message": "Újratöltés"
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "A telepítéshez újraindítás szükséges"
},
"app.world.server-modal.placeholder-address": {
"message": "pelda.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Válassz egy lehetőséget"
},
"app.world.world-item.incompatible-version": {
"message": "Inkompatibilis verzió: {version}"
},
"app.world.world-item.not-played-yet": {
"message": "Még nem játszottál"
},
"app.world.world-item.offline": {
"message": "Offline"
},
"app.world.world-item.players-online": {
"message": "{count} online"
},
"friends.action.add-friend": {
"message": "Barát hozzáadása"
},
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Világ szerkesztése"
},
"instance.filter.disabled": {
"message": "Letiltott projektek"
"instance.files.adding-files": {
"message": "Fájlok hozzáadása ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Frissítések elérhetőek"
"instance.files.save-as": {
"message": "Mentés másként..."
},
"instance.server-modal.address": {
"message": "Cím"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Telepítés"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} a Minecraft {game_version} verziójához már telepítve van"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "A vanilla {game_version} már telepítve van"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Verzióváltás"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Telepítés"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Telepítés folyamatban"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Modpack verzióinak lekérése"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Új verzió telepítése"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Jelenleg telepítve"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Debug információ:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Modpack részleteinek lekérése"
},
"instance.settings.tabs.installation.game-version": {
"message": "Játék verziója"
},
"instance.settings.tabs.installation.install": {
"message": "Telepítés"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Telepítés folyamatban"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} verzió"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Nem lehetséges a csatolt modpack részleteit lekérdezni. Kérlek nézd meg az internetkapcsolatod."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} nem elérhető a Minecraft {version} verziójához. Próbálj meg egy másik modbetöltőt."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "A profilod linkelve van egy Modrinth modcsomaghoz, de a modcsomag nem található Modrinth-on."
},
"instance.settings.tabs.installation.platform": {
"message": "Platform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Modpack újratelepítése"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Modpack újratelepítése"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Az újratelepítés visszaállítja az összes telepített vagy módosított tartalmat a modcsomag által biztosított állapotra, eltávolítva az eredeti telepítéshez hozzáadott modokat vagy tartalmakat. Ez megoldhatja a váratlan hibákat, de fontos tudni hogyha használsz világokat amelyekben utólagosan hozzáadott tartalom van, azok a világok elromolhatnak."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Biztosan szeretnéd újratelepíteni ezt a profilt?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Visszaállítja a profilod tartalmát az eredeti állapotába, eltávolítva az eredeti modpackhez hozzáadott összes modot és tartalmat."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Modpack újratelepítése"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Javítás"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Javítás folyamatban"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "A javítás újratelepíti a Minecraft alapját és ellenőrzi, hogy nincs-e sérülés. Ez megoldhatja a problémákat, ha a játék nem az indítóval kapcsolatos hibák miatt nem indul el, de nem oldja meg a telepített modokkal kapcsolatos problémákat vagy összeomlásokat."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Profil javítása?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Javítás folyamatban"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Visszaállítás az aktuális állapotra"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Összes verzió mutatása"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "verzió váltás"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "telepítés"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "újratelepítés"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "javítás"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Nem lehet {action}-t végrehajtani telepítés közben"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Offline állapotban nem lehet {action}-t végrehajtani"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Nem lehet {action}-t végrehajtani javítás közben"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(ismeretlen verzió)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Ez az profil egy szerverhez van kapcsolva, ami azt jelenti, hogy nem lehet megváltoztatni a Minecraft verzióját. A kapcsolás megszüntetése véglegesen leválasztja ezt az profilt a szerverről."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Ez az profil egy szerverhez van kapcsolva, ami azt jelenti, hogy a modok nem frissíthetők, és nem lehet megváltoztatni a modbetöltőt vagy a Minecraft verziót. A kapcsolódás megszüntetése véglegesen leválasztja ezt a profilt a szerverről."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Leválasztás a szerverről"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Profil leválasztása"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Ha folytatod, akkor nem tudod újra összekapcsolni anélkül, hogy egy teljesen új profilt hoznál létre. Többé nem fogja megkapni a modcsomag frissítéseit, és normál állapotba kerül."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Biztosan le szeretnéd választani ezt a profilt?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Ez az profil egy modcsomaghoz van kapcsolva, ami azt jelenti, hogy a modok nem frissíthetőek, és nem lehet megváltoztatni a modbetöltőt vagy a Minecraft verziót. A kapcsolódás megszüntetése véglegesen leválasztja ezt a profilt a modcsomagról."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Modpack-ről való leválasztás"
},
"instance.settings.tabs.java": {
"message": "Java és memória"
},
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Ne mutasd a kezdőlapon"
},
"instance.worlds.filter.available": {
"message": "Elérhető"
},
"instance.worlds.game_already_open": {
"message": "A profil már meg van nyitva"
},
@@ -558,13 +552,13 @@
"message": "Hardcore mód"
},
"instance.worlds.incompatible_server": {
"message": "A Szerver nem kompatibilis"
"message": "A szerver nem kompatibilis"
},
"instance.worlds.linked_server": {
"message": "Szerverprojekt által kezelt"
},
"instance.worlds.no_contact": {
"message": "Nem lehet kapcsolatot létesíteni a szerverrel"
"message": "A szerverrel nem lehet kapcsolatot létesíteni"
},
"instance.worlds.no_server_quick_play": {
"message": "Csak Minecraft Alpha 1.0.5+-tól tudsz egyből szerverhez csatlakozni"
@@ -575,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "Játék a profillal"
},
"instance.worlds.type.server": {
"message": "Szerver"
},
"instance.worlds.type.singleplayer": {
"message": "Egyjátékos"
},
"instance.worlds.view_instance": {
"message": "Profil megtekintése"
},
@@ -594,13 +582,13 @@
"message": "A játékverzió a profil által van megadva"
},
"search.filter.locked.instance-loader.title": {
"message": "A modbetöltő a profil által van megadva"
"message": "A betöltő a profil által van megadva"
},
"search.filter.locked.instance.sync": {
"message": "Profil szinkronizálása"
},
"search.filter.locked.server": {
"message": "A szerver biztosítja"
"message": "A szerver által van megadva"
},
"search.filter.locked.server-environment.title": {
"message": "Csak kliensoldali modok adhatók hozzá a szerverprofilhoz"
+166 -178
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Tidak dapat terhubung ke server autentikasi"
},
"app.browse.add-server-to-instance": {
"message": "Tambah server ke instans"
},
"app.browse.add-servers-to-instance": {
"message": "Tambah server ke instans Anda"
},
"app.browse.add-to-instance": {
"message": "Tambah ke instans"
},
"app.browse.add-to-instance-name": {
"message": "Tambah ke {instanceName}"
},
"app.browse.added": {
"message": "Ditambahkan"
},
"app.browse.already-added": {
"message": "Telah ditambahkan"
},
"app.browse.discover-content": {
"message": "Temukan konten"
},
"app.browse.discover-servers": {
"message": "Temukan server"
},
"app.browse.hide-added-servers": {
"message": "Sembuyikan server tertambah"
},
"app.browse.hide-installed-content": {
"message": "Sembunyikan konten terpasang"
},
"app.browse.install-content-to-instance": {
"message": "Pasang konten ke instans"
},
"app.export-modal.description-placeholder": {
"message": "Masukkan deskripsi paket mod..."
},
"app.export-modal.export-button": {
"message": "Ekspor"
},
"app.export-modal.header": {
"message": "Ekspor paket mod"
},
"app.export-modal.modpack-name-label": {
"message": "Nama Paket Mod"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nama paket mod"
},
"app.export-modal.select-files-label": {
"message": "Pilih berkas dan folder yang ingin dimasukkan ke paket"
},
"app.export-modal.version-number-label": {
"message": "Nomor versi"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Semua data dari instans Anda akan dihapus secara permanen, termasuk dunia, konfigurasi, dan konten terpasang Anda."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Tindakan ini tidak dapat dibatalkan"
},
"app.instance.confirm-delete.delete-button": {
"message": "Hapus instans"
},
"app.instance.confirm-delete.header": {
"message": "Hapus instans"
},
"app.instance.modpack-already-installed.body": {
"message": "Paket mod ini telah terpasang di instans <bold>{instanceName}</bold>. Apakah Anda yakin ingin menggandakannya?"
},
"app.instance.modpack-already-installed.create": {
"message": "Buat"
},
"app.instance.modpack-already-installed.header": {
"message": "Paket mod telah terpasang"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instans"
},
"app.instance.mods.content-type-project": {
"message": "proyek"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" telah ditambahkan"
},
"app.instance.mods.projects-were-added": {
"message": "{count} proyek telah ditambahkan"
},
"app.instance.mods.share-text": {
"message": "Lihat proyek-proyek yang saya pakai di paket mod saya!"
},
"app.instance.mods.share-title": {
"message": "Membagi konten paket mod"
},
"app.instance.mods.successfully-uploaded": {
"message": "Berhasil diunggah"
},
"app.instance.worlds.add-server": {
"message": "Tambah server"
},
"app.instance.worlds.browse-servers": {
"message": "Telusuri server"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' akan **dihapus secara permanen**, dan Anda tidak akan dapat memulihkannya."
},
"app.instance.worlds.delete-world-title": {
"message": "Apakah Anda yakin ingin menghapus dunia ini secara permanen?"
},
"app.instance.worlds.filter-modded": {
"message": "Dimodifikasi"
},
"app.instance.worlds.filter-offline": {
"message": "Luring"
},
"app.instance.worlds.filter-online": {
"message": "Daring"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanila"
},
"app.instance.worlds.no-worlds-description": {
"message": "Tambah server atau telusuri untuk memulai"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Tidak ada server atau dunia yang ditambahkan"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' akan dihapus dari daftar Anda, termasuk di dalam permainan, dan Anda tidak akan dapat memulihkannya."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) akan dihapus dari daftar Anda, termasuk di dalam permainan, dan Anda tidak akan dapat memulihkannya."
},
"app.instance.worlds.remove-server-title": {
"message": "Apakah Anda yakin ingin menghapus {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Cari {count} dunia..."
},
"app.instance.worlds.this-server": {
"message": "server ini"
},
"app.modal.install-to-play.content-required": {
"message": "Konten diperlukan"
},
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Lihat konten"
},
"app.modal.update-to-play.added-count": {
"message": "{count} ditambahkan"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Ditambahkan"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Dihapus"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Diperbarui"
},
"app.modal.update-to-play.header": {
"message": "Perbarui untuk memainkan"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} dihapus"
},
"app.modal.update-to-play.update-required": {
"message": "Perlu diperbarui"
},
"app.modal.update-to-play.update-required-description": {
"message": "{name} perlu diperbarui sebelum dimainkan. Mohon perbarui ke versi terkini untuk meluncurkan permainan."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} diperbarui"
},
"app.settings.developer-mode-enabled": {
"message": "Mode pengembang dihidupkan."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Pilihan instans bawaan"
},
"app.settings.tabs.feature-flags": {
"message": "Bendera fitur"
},
"app.settings.tabs.java-installations": {
"message": "Pemasangan Java"
},
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Muat ulang untuk memasang pembaruan"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Pilih opsi"
},
"app.world.world-item.incompatible-version": {
"message": "Versi {version} tidak cocok"
},
"app.world.world-item.not-played-yet": {
"message": "Belum pernah dimainkan"
},
"app.world.world-item.offline": {
"message": "Luring"
},
"app.world.world-item.players-online": {
"message": "{count} orang daring"
},
"friends.action.add-friend": {
"message": "Tambah teman"
},
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Sunting dunia"
},
"instance.filter.disabled": {
"message": "Proyek takaktif"
"instance.files.adding-files": {
"message": "Menambahkan berkas ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Pembaruan tersedia"
"instance.files.save-as": {
"message": "Simpan sebagai..."
},
"instance.server-modal.address": {
"message": "Alamat"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Pemasangan"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} untuk Minecraft {game_version} sudah terpasang"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "{game_version} murni sudah terpasang"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Ubah versi"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Pasang"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Memasang"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Memperoleh versi paket mod"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Memasang versi baru"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Saat ini terpasang"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Informasi awakutu:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Memperoleh perincian paket mod"
},
"instance.settings.tabs.installation.game-version": {
"message": "Versi permainan"
},
"instance.settings.tabs.installation.install": {
"message": "Pasang"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Pemasangan sedang berjalan"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Versi {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Tidak dapat memperoleh perincian paket mod terkait. Mohon periksa sambungan internet Anda."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} tidak tersedia untuk Minecraft {version}. Mohon coba peluncur mod yang lain."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Instans ini berkaitan dengan paket mod, tetapi paket mod tersebut tidak dapat ditemukan pada Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Platform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Pasang ulang paket mod"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Memasang ulang paket mod"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Memasang ulang akan mengatur ulang semua konten yang terpasang atau termodifikasi pada apa yang telah disediakan oleh paket mod, menghapus mod atau konten apa pun yang telah Anda tambahkan di atas pemasangan awal. Hal ini dapat memperbaiki perilaku tidak terduga bila ada perubahan pada instans, tetapi bila dunia Anda sekarang bergantung pada konten terpasang tambahan, hal ini dapat merusak dunia yang ada."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Apakah Anda yakin ingin memasang ulang instans ini?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Mengatur ulang konten instans menjadi keadaan awal, menghapus mod atau konten apa pun yang telah Anda tambahkan di atas pemasangan awal."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Pasang ulang paket mod"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Perbaiki"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Memperbaiki"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Memperbaiki akan memasangkan ulang pustaka dependen dan memeriksa kerusakan. Ini dapat memecahkan masalah bila permainan Anda tidak memulai sebab kesalahan pada peluncur, tetapi tidak akan memecahkan masalah atau kemogokan yang disebabkan oleh mod terpasang."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Perbaiki instans?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Perbaikan sedang berlangsung"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Atur ulang ke saat ini"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Tampilkan semua versi"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "mengubah versi"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "memasang"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "memasang ulang"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "memperbaiki"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Tidak dapat {action} saat memasang"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Tidak dapat {action} saat luring"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Tidak dapat {action} saat memperbaiki"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(versi tidak dikenal)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Instans ini berkaitan dengan suatu server, yang berarti Anda tidak dapat mengubah versi Minecraft. Melepas kaitan akan memutuskan instans ini dari server secara permanen."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Instans ini berkaitan dengan suatu server, yang berarti mod tidak dapat diperbarui dan Anda tidak dapat mengubah versi peluncur mod atau Minecraft. Melepas kaitan akan memutuskan instans ini dari server secara permanen."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Lepas kaitan dari server"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Lepas kaitan instans"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Bila Anda melanjutkan, Anda tidak akan dapat mengaitkannya lagi tanpa membuat instans baru. Anda tidak akan mendapatkan pembaruan paket mod dan menjadi instans normal."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Apakah Anda yakin ingin melepas kaitan instans ini?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Instans ini berkaitan dengan paket mod, yang berarti mod tidak dapat diperbarui dan Anda tidak dapat mengubah versi peluncur mod atau Minecraft. Melepas kaitan akan memutuskan instans ini dari paket mod secara permanen."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Lepas kaitan dari paket mod"
},
"instance.settings.tabs.java": {
"message": "Java dan memori"
},
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Jangan tampilkan di Beranda"
},
"instance.worlds.filter.available": {
"message": "Tersedia"
},
"instance.worlds.game_already_open": {
"message": "Instans telah dibuka"
},
@@ -575,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "Mainkan instans"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Bermain sendiri"
},
"instance.worlds.view_instance": {
"message": "Lihat instans"
},
+171 -183
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Impossibile raggiungere i server di autenticazione"
},
"app.browse.add-server-to-instance": {
"message": "Aggiungi server all'istanza"
},
"app.browse.add-servers-to-instance": {
"message": "Aggiungi i server alla tua istanza"
},
"app.browse.add-to-instance": {
"message": "Aggiungi all'istanza"
},
"app.browse.add-to-instance-name": {
"message": "Aggiungi a {instanceName}"
},
"app.browse.added": {
"message": "Aggiunto"
},
"app.browse.already-added": {
"message": "Già aggiunto"
},
"app.browse.discover-content": {
"message": "Esplora i contenuti"
},
"app.browse.discover-servers": {
"message": "Esplora i server"
},
"app.browse.hide-added-servers": {
"message": "Nascondi server aggiunti"
},
"app.browse.hide-installed-content": {
"message": "Nascondi contenuti installati"
},
"app.browse.install-content-to-instance": {
"message": "Installa contenuti nell'istanza"
},
"app.export-modal.description-placeholder": {
"message": "Inserisci descrizione del pacchetto..."
},
"app.export-modal.export-button": {
"message": "Esporta"
},
"app.export-modal.header": {
"message": "Esporta pacchetto"
},
"app.export-modal.modpack-name-label": {
"message": "Nome del pacchetto"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nome del pacchetto"
},
"app.export-modal.select-files-label": {
"message": "Seleziona i file e le cartelle da includere nel pacchetto"
},
"app.export-modal.version-number-label": {
"message": "Numero di versione"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Tutti i dati della tua istanza verranno eliminati permanentemente, inclusi i tuoi mondi, configurazioni e tutti i contenuti installati."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Questa azione non può essere annullata"
},
"app.instance.confirm-delete.delete-button": {
"message": "Elimina istanza"
},
"app.instance.confirm-delete.header": {
"message": "Elimina istanza"
},
"app.instance.modpack-already-installed.body": {
"message": "Questo pacchetto di mod è già installato nell'istanza <bold>{instanceName}</bold>. Vuoi davvero duplicarlo?"
},
"app.instance.modpack-already-installed.create": {
"message": "Crea"
},
"app.instance.modpack-already-installed.header": {
"message": "Pacchetto già installato"
},
"app.instance.modpack-already-installed.instance": {
"message": "Istanza"
},
"app.instance.mods.content-type-project": {
"message": "progetto"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" è stato aggiunto"
},
"app.instance.mods.projects-were-added": {
"message": "{count} progetti aggiunti"
},
"app.instance.mods.share-text": {
"message": "Guarda le mod che uso nel mio pacchetto!"
},
"app.instance.mods.share-title": {
"message": "Condivisione del pacchetto"
},
"app.instance.mods.successfully-uploaded": {
"message": "Caricato con successo"
},
"app.instance.worlds.add-server": {
"message": "Aggiungi server"
},
"app.instance.worlds.browse-servers": {
"message": "Esplora i server"
},
"app.instance.worlds.delete-world-description": {
"message": "\"{name}\" verrà **eliminato permanentemente** e non ci sarà modo di recuperarlo."
},
"app.instance.worlds.delete-world-title": {
"message": "Vuoi davvero eliminare questo mondo per sempre?"
},
"app.instance.worlds.filter-modded": {
"message": "Moddato"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Inizia esplorando o aggiungendo un server"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Nessun server o mondo aggiunto"
},
"app.instance.worlds.remove-server-description": {
"message": "\"{name}\" sarà rimosso dalla tua lista, inclusa quella nel gioco, e non ci sarà modo di recuperarlo."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "\"{name}\" ({address}) sarà rimosso dalla tua lista, inclusa quella nel gioco, e non ci sarà modo di recuperarlo."
},
"app.instance.worlds.remove-server-title": {
"message": "Vuoi davvero rimuovere {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Cerca tra {count} mondi..."
},
"app.instance.worlds.this-server": {
"message": "questo server"
},
"app.modal.install-to-play.content-required": {
"message": "Contenuto richiesto"
},
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Mostra contenuti"
},
"app.modal.update-to-play.added-count": {
"message": "{count, plural, one {# aggiunta} other {# aggiunte}}"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Aggiunta"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Rimossa"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Aggiornata"
},
"app.modal.update-to-play.header": {
"message": "Aggiorna per continuare"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count, plural, one {# rimozione} other {# rimozioni}}"
},
"app.modal.update-to-play.update-required": {
"message": "Aggiornamento richiesto"
},
"app.modal.update-to-play.update-required-description": {
"message": "{name} richiede degli aggiornamenti. Installa l'ultima versione per poter giocare."
},
"app.modal.update-to-play.updated-count": {
"message": "{count, plural, one {# aggiornamento} other {# aggiornamenti}}"
},
"app.settings.developer-mode-enabled": {
"message": "Modalità sviluppatore attiva."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Opzioni d'istanza predefinite"
},
"app.settings.tabs.feature-flags": {
"message": "Flag di funzionalità"
},
"app.settings.tabs.java-installations": {
"message": "Installazioni Java"
},
@@ -126,11 +246,29 @@
"message": "Scarica aggiornamento"
},
"app.update.downloading-update": {
"message": "Scaricando aggiornamento ({percent}%)"
"message": "Scaricando l'aggiornamento ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Ricarica per installare l'aggiornamento"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Seleziona un'opzione"
},
"app.world.world-item.incompatible-version": {
"message": "Versione {version} incompatibile"
},
"app.world.world-item.not-played-yet": {
"message": "Mai avviato"
},
"app.world.world-item.offline": {
"message": "Offline"
},
"app.world.world-item.players-online": {
"message": "{count} online"
},
"friends.action.add-friend": {
"message": "Stringi un'amicizia"
},
@@ -180,7 +318,7 @@
"message": "Online"
},
"friends.heading.pending": {
"message": "In sospeso"
"message": "In attesa"
},
"friends.no-friends-match": {
"message": "Nessuna amicizia corrisponde a ''{query}''"
@@ -195,7 +333,7 @@
"message": "<link>Accedi a un account Modrinth</link> per stringere amicizie e sapere a cosa stanno giocando!"
},
"instance.add-server.add-and-play": {
"message": "Aggiungi e gioca"
"message": "Aggiungi e avvia"
},
"instance.add-server.add-server": {
"message": "Aggiungi server"
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Modifica mondo"
},
"instance.filter.disabled": {
"message": "Progetti disattivati"
"instance.files.adding-files": {
"message": "Aggiungendo i file ({completed}/{total})..."
},
"instance.filter.updates-available": {
"message": "Aggiornamenti disponibili"
"instance.files.save-as": {
"message": "Salva come..."
},
"instance.server-modal.address": {
"message": "Indirizzo"
@@ -321,7 +459,7 @@
"message": "Inserisci comando post-uscita..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Pre-lancio"
"message": "Pre-avvio"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "Eseguito prima dell'avvio dell'istanza."
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Installazione"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} per Minecraft {game_version} è già installato"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} è già installata"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Cambia versione"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Installa"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Installando"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Ottenendo versioni del pacchetto di mod"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Installando nuova versione"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Installazione corrente"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Informazioni per il debug:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Ottenendo dettagli del pacchetto di mod"
},
"instance.settings.tabs.installation.game-version": {
"message": "Versione del gioco"
},
"instance.settings.tabs.installation.install": {
"message": "Installa"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Installazione in corso"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Versione di {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Impossibile ottenere i dettagli del pacchetto di mod collegato. Si prega di controllare la connessione a Internet."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} non è disponibile per Minecraft {version}. Prova un altro loader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "L'istanza è collegata a un pacchetto di mod, ma non è stato possibile trovarlo su Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Piattaforma"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Reinstalla pacchetto di mod"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Reinstallando pacchetto di mod"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "La reinstallazione resetterà tutto il contenuto installato o modificato a ciò che è fornito dal pacchetto di mod, rimuovendo ogni mod o contenuto che tu abbia aggiunto all'installazione originale. Questo potrebbe risolvere comportamenti inaspettati se ci sono state modifiche all'istanza, ma se ora i tuoi mondi dipendessero da contenuto aggiuntivo installato, essi verrebbero corrotti."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Vuoi davvero reinstallare questa istanza?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Resetta il contenuto dell'istanza al suo stato originale, rimuovendo ogni mod o contenuto che tu abbia aggiunto al pacchetto di mod originale."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Reinstalla pacchetto di mod"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Ripara"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Riparando"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "La riparazione reinstalla le dipendenze di Minecraft e verifica eventuali corruzioni. Questo potrebbe risolvere problemi di avvio del gioco se dovuti a errori legati al launcher, ma non risolverà problemi o crash legati alle mod installate."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Riparare l'istanza?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Riparazione in corso"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Resetta ad attuale"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Mostra tutte le versioni"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "cambia versione"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "installa"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "reinstalla"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "ripara"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Impossibile {action} durante l'installazione"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Impossibile {action} senza connessione"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Impossibile {action} durante la riparazione"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(versione sconosciuta)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Questa istanza è collegata a un server, cioè non puoi cambiare la versione di Minecraft. Lo scollegamento disconnetterà definitivamente questa istanza dal server."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Questa istanza è collegata a un server, perciò le mod non possono essere aggiornate manualmente, e non puoi cambiare loader di mod né versione di Minecraft. Lo scollegamento disconnetterà definitivamente questa istanza dal server."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Scollega dal server"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Scollega istanza"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Procedendo non potrai più ricollegarla se non creando una nuova istanza da zero. Diventerà una normale installazione, per cui non riceverai più aggiornamenti dal pacchetto di mod."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Vuoi davvero scollegare questa istanza?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Questa istanza è collegata a un pacchetto di mod, cioè le mod non possono essere aggiornate manualmente, e non puoi cambiare loader di mod né versione di Minecraft. Lo scollegamento disconnetterà definitivamente questa istanza dal pacchetto di mod."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Scollega dal pacchetto di mod"
},
"instance.settings.tabs.java": {
"message": "Java e memoria"
},
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Non mostrare nella home"
},
"instance.worlds.filter.available": {
"message": "Disponibile"
},
"instance.worlds.game_already_open": {
"message": "Istanza già aperta"
},
@@ -573,13 +567,7 @@
"message": "È possibile avviare direttamente un mondo in giocatore singolo solo su Minecraft 1.20+"
},
"instance.worlds.play_instance": {
"message": "Gioca istanza"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Giocatore singolo"
"message": "Avvia istanza"
},
"instance.worlds.view_instance": {
"message": "Mostra istanza"
+189 -201
View File
@@ -1,10 +1,154 @@
{
"app.auth-servers.unreachable.body": {
"message": "Minecraft の認証サーバーは現在停止している可能性があります。インターネット接続を確認し、しばらくしてからもう一度お試しください。"
"message": "Minecraftの認証サーバーは現在停止している可能性があります。インターネット接続を確認し、しばらくしてからもう一度お試しください。"
},
"app.auth-servers.unreachable.header": {
"message": "認証サーバーにアクセスできません"
},
"app.browse.add-server-to-instance": {
"message": "サーバーをインスタンスに追加"
},
"app.browse.add-servers-to-instance": {
"message": "サーバーを自身のインスタンスに追加"
},
"app.browse.add-to-instance": {
"message": "インスタンスに追加"
},
"app.browse.add-to-instance-name": {
"message": "{instanceName} に追加"
},
"app.browse.added": {
"message": "追加済み"
},
"app.browse.already-added": {
"message": "すでに追加済み"
},
"app.browse.discover-content": {
"message": "コンテンツを探す"
},
"app.browse.discover-servers": {
"message": "サーバーを探す"
},
"app.browse.hide-added-servers": {
"message": "追加済みのサーバーを隠す"
},
"app.browse.hide-installed-content": {
"message": "インストール済みのコンテンツを隠す"
},
"app.browse.install-content-to-instance": {
"message": "コンテンツをインスタンスにインストールする"
},
"app.export-modal.description-placeholder": {
"message": "Modパックの説明を入力…"
},
"app.export-modal.export-button": {
"message": "書き出し"
},
"app.export-modal.header": {
"message": "Modパックを書き出す"
},
"app.export-modal.modpack-name-label": {
"message": "Modパック名"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modパック名"
},
"app.export-modal.select-files-label": {
"message": "パックに含めるファイルとフォルダーを選択"
},
"app.export-modal.version-number-label": {
"message": "バージョン番号"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "インスタンス内のすべてのデータは、ワールド、設定、インストール済みのコンテンツを含め、完全に削除されます。"
},
"app.instance.confirm-delete.admonition-header": {
"message": "この操作は取り消せません"
},
"app.instance.confirm-delete.delete-button": {
"message": "インスタンスを削除"
},
"app.instance.confirm-delete.header": {
"message": "インスタンスを削除"
},
"app.instance.modpack-already-installed.body": {
"message": "このModpackは既に <bold>{instanceName}</bold> インスタンスにインストール済みです。本当に複製しますか?"
},
"app.instance.modpack-already-installed.create": {
"message": "新規作成"
},
"app.instance.modpack-already-installed.header": {
"message": "Modパックはすでにインストール済み"
},
"app.instance.modpack-already-installed.instance": {
"message": "インスタンス"
},
"app.instance.mods.content-type-project": {
"message": "プロジェクト"
},
"app.instance.mods.project-was-added": {
"message": "「{name}」が追加されました"
},
"app.instance.mods.projects-were-added": {
"message": "{count}件のプロジェクトが追加されました"
},
"app.instance.mods.share-text": {
"message": "私のModパックで使われているプロジェクトをチェック!"
},
"app.instance.mods.share-title": {
"message": "Modパックのコンテンツを共有"
},
"app.instance.mods.successfully-uploaded": {
"message": "アップロードに成功しました"
},
"app.instance.worlds.add-server": {
"message": "サーバーを追加"
},
"app.instance.worlds.browse-servers": {
"message": "サーバーを探す"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' は **完全に削除**され、元に戻すことはできません。"
},
"app.instance.worlds.delete-world-title": {
"message": "本当にこのワールドを完全に削除しますか?"
},
"app.instance.worlds.filter-modded": {
"message": "Mod導入済み"
},
"app.instance.worlds.filter-offline": {
"message": "オフライン"
},
"app.instance.worlds.filter-online": {
"message": "オンライン"
},
"app.instance.worlds.filter-vanilla": {
"message": "バニラ"
},
"app.instance.worlds.no-worlds-description": {
"message": "サーバーを追加、またはブラウズして始める"
},
"app.instance.worlds.no-worlds-heading": {
"message": "サーバー、ワールドは追加されていません"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' はゲーム内を含むサーバーリストから削除され、元に戻すことはできません。"
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) はゲーム内を含むサーバーリストから削除され、元に戻すことはできません。"
},
"app.instance.worlds.remove-server-title": {
"message": "本当に {name} を削除しますか?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "{count} 個のワールドを検索…"
},
"app.instance.worlds.this-server": {
"message": "このサーバー"
},
"app.modal.install-to-play.content-required": {
"message": "必須コンテンツ"
},
@@ -18,7 +162,7 @@
"message": "{count, plural, other {#個のMod}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "必須Modpack"
"message": "必須Modパック"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "このサーバーをプレイするにはModが必要です。インストールをクリックしてModrinthから必要なファイルを設定し、サーバーに接続してください。"
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "コンテンツを見る"
},
"app.modal.update-to-play.added-count": {
"message": "{count}追加"
},
"app.modal.update-to-play.diff-type.added": {
"message": "追加"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "削除済み"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "更新済み"
},
"app.modal.update-to-play.header": {
"message": "更新してプレイ"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count}件削除されました"
},
"app.modal.update-to-play.update-required": {
"message": "更新が必要です"
},
"app.modal.update-to-play.update-required-description": {
"message": "{name}をプレイするには更新が必要です。ゲームを起動するには最新版に更新してください。"
},
"app.modal.update-to-play.updated-count": {
"message": "{count} 更新されました"
},
"app.settings.developer-mode-enabled": {
"message": "開発者モードがオンになっています。"
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "インスタンスの基本設定"
},
"app.settings.tabs.feature-flags": {
"message": "機能設定"
},
"app.settings.tabs.java-installations": {
"message": "Javaのインストール設定"
},
@@ -90,10 +210,10 @@
"message": "リソース管理"
},
"app.update-popup.body": {
"message": "Modrinth App v{version} のインストール準備が整いました!今すぐ更新するには再読み込みするか、Modrinth App を閉じる際に自動更新されます。"
"message": "Modrinth App v{version} のインストール準備が整いました!今すぐ更新するには再読み込みするか、Modrinth Appを閉じる際に自動更新されます。"
},
"app.update-popup.body.download-complete": {
"message": "Modrinth App v{version} のダウンロードが完了しました。今すぐ更新するには再読み込みするか、Modrinth App を閉じる際に自動更新されます。"
"message": "Modrinth App v{version} のダウンロードが完了しました。今すぐ更新するには再読み込みするか、Modrinth Appを閉じる際に自動更新されます。"
},
"app.update-popup.body.linux": {
"message": "Modrinth App v{version} が利用可能です。最新の機能と修正プログラムを入手するには、パッケージマネージャーを使用して更新してください!"
@@ -111,7 +231,7 @@
"message": "ダウンロード完了"
},
"app.update-popup.reload": {
"message": "リロード"
"message": "再読み込み"
},
"app.update-popup.title": {
"message": "アップデートが利用可能です"
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "再起動して今すぐ更新"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "オプションを選択"
},
"app.world.world-item.incompatible-version": {
"message": "互換性の無いバージョン {version}"
},
"app.world.world-item.not-played-yet": {
"message": "未プレイ"
},
"app.world.world-item.offline": {
"message": "オフライン"
},
"app.world.world-item.players-online": {
"message": "{count} 人がオンライン"
},
"friends.action.add-friend": {
"message": "フレンドを追加"
},
@@ -144,10 +282,10 @@
"message": "フレンドを追加中"
},
"friends.add-friend.username.description": {
"message": "これはMinecraftユーザーネームと違う可能性があります!"
"message": "これはMinecraftユーザー名とは異なる可能性があります!"
},
"friends.add-friend.username.placeholder": {
"message": "Modrinthユーザーネームを入力..."
"message": "Modrinthユーザー名を入力…"
},
"friends.add-friend.username.title": {
"message": "あなたのフレンドのModrinthユーザー名は何ですか?"
@@ -183,7 +321,7 @@
"message": "保留中"
},
"friends.no-friends-match": {
"message": "フレンド\"{query}\"は見つかりませんでした"
"message": "フレンド{query}は見つかりませんでした"
},
"friends.search-friends-placeholder": {
"message": "フレンドを検索…"
@@ -222,7 +360,7 @@
"message": "名前"
},
"instance.edit-world.placeholder-name": {
"message": "Mincraft ワールド"
"message": "Mincraftワールド"
},
"instance.edit-world.reset-icon": {
"message": "アイコンをリセット"
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "ワールドを編集"
},
"instance.filter.disabled": {
"message": "無効なプロジェクト"
"instance.files.adding-files": {
"message": "ファイルを追加中 ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "アップデートが可能"
"instance.files.save-as": {
"message": "名前をつけて保存…"
},
"instance.server-modal.address": {
"message": "アドレス"
@@ -258,7 +396,7 @@
"message": "インスタンスを削除"
},
"instance.settings.tabs.general.delete.description": {
"message": "デバイスからインスタンスを削除します。これらには、ワールド、設定、他、全てのインストール済みのファイルが含まれます。インスタンスを削除すると復元することはできません。"
"message": "デバイスからインスタンスを削除します。これらには、ワールド、設定などのすべてのインストール済みのファイルが含まれます。インスタンスを削除すると復元することはできません。"
},
"instance.settings.tabs.general.deleting.button": {
"message": "削除中…"
@@ -318,7 +456,7 @@
"message": "ゲームが閉じられた後に実行されます。"
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "終了後のコマンドを入力"
"message": "終了後のコマンドを入力"
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "起動前"
@@ -327,7 +465,7 @@
"message": "ゲームが起動する前に実行されます。"
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "起動前のコマンドを入力"
"message": "起動前のコマンドを入力"
},
"instance.settings.tabs.hooks.title": {
"message": "ゲーム起動フック"
@@ -336,7 +474,7 @@
"message": "ラッパー"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "Minecraftを起動のラッパーコマンド。"
"message": "Minecraftを起動するためのラッパーコマンド。"
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "ラッパーのコマンドを入力…"
@@ -344,149 +482,8 @@
"instance.settings.tabs.installation": {
"message": "インストール"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "Minecraft {game_version} の {platform} {version} はすでにインストールされています"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} はすでにインストールされています"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "バージョンを変更"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "インストール"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "インストール中"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "ModPackのバージョンを取得しています"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "新しいバージョンをインストール中"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "インストール済"
},
"instance.settings.tabs.installation.debug-information": {
"message": "デバッグ情報:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "ModPackの情報を取得しています"
},
"instance.settings.tabs.installation.game-version": {
"message": "ゲームバージョン"
},
"instance.settings.tabs.installation.install": {
"message": "インストール"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "インストール中"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} バージョン"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "リンクされたModpackの情報が取得できませんでした。インターネット接続を確認してください。"
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader}はMinecraft {version}で使用できません。別のローダーを選択してください。"
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "このインスタンスはModpackにリンクされていますが、ModrinthではModpackが見つかりません。"
},
"instance.settings.tabs.installation.platform": {
"message": "プラットフォーム"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Modpackを再インストール"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Modpackを再インストール中"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "再インストールすると、全てのコンテンツがModpackで提供される内容にリセットされ、元のコンテンツに追加されたMod等やコンテンツは全て削除されます。インスタンスに変更を加えていた場合、予期せぬ動作が修正がされる場合がありますが、ワールドが追加でインストールされたコンテンツに依存している場合、既存のワールドで動かなくなる可能性があります。"
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "本当にインスタンスを再インストールしますか?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "インスタンスの状態をもとの状態にリセットし、元のModpackに追加されたModやコンテンツ等を削除します。"
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Modpackを再インストール"
},
"instance.settings.tabs.installation.repair.button": {
"message": "修復"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "修復中"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "修復を行うと、Minecraftの依存関係が再インストールされ、破損がないかのチェックが行われます。ランチャー関連の問題の場合は、修復によって解決する可能性がありますが、インストール済みのModに関する問題は解決されません。"
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "インスタンスを修復しますか?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "修復中"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "現在の状態にリセット"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "全てのバージョンを表示"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "バージョンを変更"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "インストール"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "再インストール"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "修復"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "インストール中に{action}することはできません"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "オフラインの時に{action}することはできません"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "修復中に{action}することはできません"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(不明なバージョン)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "このインスタンスはサーバーにリンクされているので、Minecraftのバージョンを変更することはできません。リンクを解除するとこのインスタンスはサーバーから永久に切断されます。"
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "このインスタンスはサーバーにリンクされているので、Modの更新はできず、ModローダーやMinecraftのバージョンを変更することもできません。リンクを解除すると、このインスタンスはサーバーから永久に切断されます。"
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "サーバーとのリンクを解除する"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "インスタンスのリンク解除"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "この操作を行うと、新しいインスタンスを作らなければ再びリンクすることはできなくなります。通常のインスタンスになるので、modpackのバージョンアップは利用できなくなります。"
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "本当にインスタンスのリンクを解除しますか?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "このインスタンスはmodpackにリンクされているので、modやmodローダー、Minecraftのバージョンを変更することはできません。リンクを解除するとこのインスタンスとmodpackは永久に分離されます。"
},
"instance.settings.tabs.installation.unlink.title": {
"message": "modpackとのリンクを解除する"
"message": "{loader}バージョン"
},
"instance.settings.tabs.java": {
"message": "Javaとメモリ"
@@ -498,13 +495,13 @@
"message": "フック"
},
"instance.settings.tabs.java.java-arguments": {
"message": "Java コマンドライン引数"
"message": "Javaコマンドライン引数"
},
"instance.settings.tabs.java.java-installation": {
"message": "Javaのインストール"
},
"instance.settings.tabs.java.java-memory": {
"message": "メモリ割り当て"
"message": "メモリ割り当て"
},
"instance.settings.tabs.window": {
"message": "ウィンドウ"
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "ホームに表示しない"
},
"instance.worlds.filter.available": {
"message": "利用可能"
},
"instance.worlds.game_already_open": {
"message": "インスタンスは既に開いています"
},
@@ -575,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "インスタンスを起動"
},
"instance.worlds.type.server": {
"message": "サーバー"
},
"instance.worlds.type.singleplayer": {
"message": "シングルプレイ"
},
"instance.worlds.view_instance": {
"message": "インスタンスを表示する"
},
@@ -588,27 +576,27 @@
"message": "ワールドは使用中"
},
"search.filter.locked.instance": {
"message": "インスタンスより提供"
"message": "インスタンスによる条件"
},
"search.filter.locked.instance-game-version.title": {
"message": "ゲームバージョンはインスタンスより提供"
"message": "ゲームバージョンはインスタンスによる条件です"
},
"search.filter.locked.instance-loader.title": {
"message": "ローダーはインスタンスにより提供"
"message": "ローダーはインスタンスによる条件です"
},
"search.filter.locked.instance.sync": {
"message": "インスタンスと同期"
},
"search.filter.locked.server": {
"message": "サーバーにより提供されています"
"message": "サーバーによる条件"
},
"search.filter.locked.server-environment.title": {
"message": "サーバー構成にはクライアント側Modのみ追加可能"
"message": "サーバーインスタンスにはクライアント側Modのみ追加可能"
},
"search.filter.locked.server-game-version.title": {
"message": "ゲームバージョンはサーバーにより提供されています"
"message": "ゲームバージョンはサーバーによる条件です"
},
"search.filter.locked.server-loader.title": {
"message": "ローダーはサーバーにより提供されています"
"message": "ローダーはサーバーによる条件です"
}
}
+170 -182
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "인증 서버에 연결할 수 없습니다"
},
"app.browse.add-server-to-instance": {
"message": "인스턴스에 서버 추가"
},
"app.browse.add-servers-to-instance": {
"message": "인스턴스에 서버 추가"
},
"app.browse.add-to-instance": {
"message": "인스턴스에 추가"
},
"app.browse.add-to-instance-name": {
"message": "{instanceName}에 추가"
},
"app.browse.added": {
"message": "추가됨"
},
"app.browse.already-added": {
"message": "이미 추가됨"
},
"app.browse.discover-content": {
"message": "콘텐츠 탐색하기"
},
"app.browse.discover-servers": {
"message": "서버 탐색하기"
},
"app.browse.hide-added-servers": {
"message": "추가된 서버 숨기기"
},
"app.browse.hide-installed-content": {
"message": "설치된 콘텐츠 숨기기"
},
"app.browse.install-content-to-instance": {
"message": "인스턴스에 콘텐츠 설치"
},
"app.export-modal.description-placeholder": {
"message": "모드팩 설명 입력..."
},
"app.export-modal.export-button": {
"message": "내보내기"
},
"app.export-modal.header": {
"message": "모드팩 내보내기"
},
"app.export-modal.modpack-name-label": {
"message": "모드팩 이름"
},
"app.export-modal.modpack-name-placeholder": {
"message": "모드팩 이름"
},
"app.export-modal.select-files-label": {
"message": "팩에 포함할 파일과 폴더 선택"
},
"app.export-modal.version-number-label": {
"message": "버전 구분"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "인스턴스의 모든 데이터가 삭제됩니다. 세계 폴더, 설정 폴더 등 설치된 모든 컨텐츠가 포함됩니다."
},
"app.instance.confirm-delete.admonition-header": {
"message": "이 작업은 되돌릴 수 없습니다"
},
"app.instance.confirm-delete.delete-button": {
"message": "인스턴스 삭제"
},
"app.instance.confirm-delete.header": {
"message": "인스턴스 삭제"
},
"app.instance.modpack-already-installed.body": {
"message": "이 모드팩은 이미 <bold>{instanceName}</bold> 인스턴스에 설치되어 있습니다. 정말로 복제하시겠습니까?"
},
"app.instance.modpack-already-installed.create": {
"message": "생성"
},
"app.instance.modpack-already-installed.header": {
"message": "모드팩 이미 설치됨"
},
"app.instance.modpack-already-installed.instance": {
"message": "인스턴스"
},
"app.instance.mods.content-type-project": {
"message": "프로젝트"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" 추가됨"
},
"app.instance.mods.projects-were-added": {
"message": "프로젝트 {count}개 추가됨"
},
"app.instance.mods.share-text": {
"message": "제 모드팩에 사용중인 프로젝트를 확인해 보세요!"
},
"app.instance.mods.share-title": {
"message": "모드팩 콘텐츠 공유"
},
"app.instance.mods.successfully-uploaded": {
"message": "업로드 성공"
},
"app.instance.worlds.add-server": {
"message": "서버 추가"
},
"app.instance.worlds.browse-servers": {
"message": "서버 탐색하기"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}'이(가) **영구적으로 삭제**되며, 복구할 수 없습니다."
},
"app.instance.worlds.delete-world-title": {
"message": "정말로 이 세계를 영구적으로 삭제하시겠습니까?"
},
"app.instance.worlds.filter-modded": {
"message": "수정됨"
},
"app.instance.worlds.filter-offline": {
"message": "오프라인"
},
"app.instance.worlds.filter-online": {
"message": "온라인"
},
"app.instance.worlds.filter-vanilla": {
"message": "바닐라"
},
"app.instance.worlds.no-worlds-description": {
"message": "서버를 추가하거나 탐색하여 시작"
},
"app.instance.worlds.no-worlds-heading": {
"message": "추가된 서버 또는 세계 없음"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}'이(가) 게임 내를 포함한 모든 목록에서 삭제되며, 복구할 수 없습니다."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address})이(가) 게임 내를 포함한 모든 목록에서 삭제되며, 복구할 수 없습니다."
},
"app.instance.worlds.remove-server-title": {
"message": "정말로 {name}을(를) 제거하시겠습니까?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "{count}개의 세계 검색..."
},
"app.instance.worlds.this-server": {
"message": "이 서버"
},
"app.modal.install-to-play.content-required": {
"message": "콘텐츠 설치 필요"
},
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "구성 요소 보기"
},
"app.modal.update-to-play.added-count": {
"message": "{count} 추가됨"
},
"app.modal.update-to-play.diff-type.added": {
"message": "추가됨"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "삭제됨"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "업데이트됨"
},
"app.modal.update-to-play.header": {
"message": "업데이트하고 플레이"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} 삭제됨"
},
"app.modal.update-to-play.update-required": {
"message": "업데이트 필요"
},
"app.modal.update-to-play.update-required-description": {
"message": "{name}을(를) 플레이하려면 업데이트가 필요합니다. 게임을 실행하려면 최신 버전으로 업데이트해 주세요."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} 업데이트됨"
},
"app.settings.developer-mode-enabled": {
"message": "개발자 모드가 활성화되었습니다."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "기본 인스턴스 옵션"
},
"app.settings.tabs.feature-flags": {
"message": "기능 플래그"
},
"app.settings.tabs.java-installations": {
"message": "Java 설치"
},
@@ -96,7 +216,7 @@
"message": "Modrinth App v{version} 다운로드가 완료되었습니다. 새로고침하거나 Modrinth App을 종료하면 자동으로 업데이트됩니다."
},
"app.update-popup.body.linux": {
"message": "Modrinth App v{version} 버전을 사용할 수 있습니다. 최신 기능과 오류 수정을 적용하려면 패키지 관리자를 통해 업데이트하세요!"
"message": "Modrinth App v{version}을 사용할 수 있습니다. 최신 기능과 오류 수정을 적용하려면 패키지 관리자를 통해 업데이트하세요!"
},
"app.update-popup.body.metered": {
"message": "Modrinth App v{version}을 지금 사용할 수 있습니다! 데이터 통신 연결을 사용 중이므로, 자동으로 다운로드하지 않았습니다."
@@ -105,7 +225,7 @@
"message": "변경 내역"
},
"app.update-popup.download": {
"message": "({size}) 다운로드"
"message": "다운로드 ({size})"
},
"app.update-popup.download-complete": {
"message": "다운로드 완료"
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "새로고침하여 업데이트 설치"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "옵션 선택"
},
"app.world.world-item.incompatible-version": {
"message": "{version} 버전에 호환되지 않음"
},
"app.world.world-item.not-played-yet": {
"message": "플레이 안 함"
},
"app.world.world-item.offline": {
"message": "오프라인"
},
"app.world.world-item.players-online": {
"message": "{count}명 온라인"
},
"friends.action.add-friend": {
"message": "친구 추가"
},
@@ -183,7 +321,7 @@
"message": "대기 중"
},
"friends.no-friends-match": {
"message": "\"{query}\" 이름과 일치하는 친구 없음"
"message": "\"{query}\"과(와) 일치하는 친구 없음"
},
"friends.search-friends-placeholder": {
"message": "친구 검색 중..."
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "세계 편집"
},
"instance.filter.disabled": {
"message": "비활성화된 프로젝트"
"instance.files.adding-files": {
"message": "파일 추가 중 ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "업데이트 가능"
"instance.files.save-as": {
"message": "다른 이름으로 저장..."
},
"instance.server-modal.address": {
"message": "주소"
@@ -282,7 +420,7 @@
"message": "아이콘 제거"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "아이콘 체"
"message": "아이콘 체"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "아이콘 선택"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "설치"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "Minecraft {game_version} {platform} {version} 설치됨"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "바닐라 {game_version} 설치됨"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "버전 변경"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "설치"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "설치 중"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "모드팩 버전을 가져오는 중"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "새 버전을 설치하는 중"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "현재 설치됨"
},
"instance.settings.tabs.installation.debug-information": {
"message": "디버그 정보:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "모드팩 세부 정보를 가져오는 중"
},
"instance.settings.tabs.installation.game-version": {
"message": "게임 버전"
},
"instance.settings.tabs.installation.install": {
"message": "설치"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "설치 진행 중"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} 버전"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "연결된 모드팩의 세부 정보를 가져올 수 없습니다. 인터넷 연결 상태를 확인하세요."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader}(은)는 Minecraft {version}에서 사용할 수 없습니다. 다른 모드 로더를 사용하세요."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "이 인스턴스는 모드팩과 연결되어 있지만, Modrinth에서 모드팩을 찾을 수 없습니다."
},
"instance.settings.tabs.installation.platform": {
"message": "플랫폼"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "모드팩 재설치"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "모드팩 재설치 중"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "재설치하면 설치 또는 수정된 모든 콘텐츠가 모드팩에서 제공하는 콘텐츠로 초기화되며, 기존 팩에 추가한 모드나 콘텐츠는 모두 제거됩니다. 인스턴스에 변경 사항이 있는 경우 예상치 못한 동작은 해결할 수 있지만, 현재 세계가 추가로 설치된 콘텐츠에 의존하고 있다면 기존 세계가 손상될 수 있습니다."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "정말로 이 인스턴스를 다시 설치하시겠습니까?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "인스턴스를 초기 상태로 복원하고, 원본 모드팩에 추가된 모드나 콘텐츠를 모두 제거합니다."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "모드팩 재설치"
},
"instance.settings.tabs.installation.repair.button": {
"message": "복구"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "복구 중"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "복구 시 Minecraft 의존성을 재설치하고 무결성을 검사합니다. 런처 오류로 인해 게임이 실행되지 않을 경우 문제 해결에 도움이 될 수 있지만, 설치된 모드로 인한 오류나 충돌은 해결되지 않습니다."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "인스턴스를 복구하시겠습니까?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "복구 진행 중"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "현재 상태로 되돌리기"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "모든 버전 보이기"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "버전 변경"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "설치"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "재설치"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "복구"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "설치 중에는 {action} 할 수 없음"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "오프라인 상태에서는 {action} 할 수 없음"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "복구 중에는 {action} 할 수 없음"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(알 수 없는 버전)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "이 인스턴스는 서버에 연결되어 있으므로, 마인크래프트 버전을 변경할 수 없습니다. 연결을 해제하면 이 인스턴스가 서버에서 영구적으로 연결이 끊어집니다."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "이 인스턴스는 서버에 연결되어 있으므로 모드를 업데이트할 수 없으며 모드 로더나 Minecraft 버전을 변경할 수 없습니다. 연결을 해제하면 이 인스턴스가 서버에서 영구적으로 연결이 끊어집니다."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "서버 연결 해제"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "인스턴스 연결 해제"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "계속 진행하면 새 인스턴스를 만들지 않는 한 다시 연결할 수 없습니다. 또한 모드팩 업데이트를 더 이상 받을 수 없으며, 일반 인스턴스로 전환됩니다."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "정말로 이 인스턴스의 연결을 해제하시겠습니까?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "이 인스턴스는 모드팩에 연결되어 있으므로, 모드를 개별적으로 업데이트하거나 모드 로더 및 Minecraft 버전을 변경할 수 없습니다. 연결을 해제하면 이 인스턴스는 모드팩과 영구적으로 분리됩니다."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "모드팩에서 연결 해제"
},
"instance.settings.tabs.java": {
"message": "Java 및 메모리"
},
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "홈에서 숨기기"
},
"instance.worlds.filter.available": {
"message": "이용 가능"
},
"instance.worlds.game_already_open": {
"message": "이미 실행된 인스턴스"
},
@@ -575,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "인스턴스 플레이"
},
"instance.worlds.type.server": {
"message": "서버"
},
"instance.worlds.type.singleplayer": {
"message": "싱글 플레이"
},
"instance.worlds.view_instance": {
"message": "인스턴스 보기"
},
+173 -173
View File
@@ -1,10 +1,154 @@
{
"app.auth-servers.unreachable.body": {
"message": "Pelayan pengesahan Minecraft mungkin sedang tergendala sekarang. Periksa sambungan internet anda dan cuba lagi nanti."
"message": "Pelayan pengesahan Minecraft mungkin sedang tergendala sekarang. Periksa sambungan internet anda dan cuba lagi kemudian."
},
"app.auth-servers.unreachable.header": {
"message": "Tidak dapat mencapai pelayan pengesahan"
},
"app.browse.add-server-to-instance": {
"message": "Tambahkan pelayan ke dalam pemasangan"
},
"app.browse.add-servers-to-instance": {
"message": "Tambahkan pelayan ke dalam pemasangan anda"
},
"app.browse.add-to-instance": {
"message": "Tambahkan ke dalam pemasangan"
},
"app.browse.add-to-instance-name": {
"message": "Tambahkan ke {instanceName}"
},
"app.browse.added": {
"message": "Ditambah"
},
"app.browse.already-added": {
"message": "Sudah ditambah"
},
"app.browse.discover-content": {
"message": "Temui kandungan"
},
"app.browse.discover-servers": {
"message": "Temui pelayan"
},
"app.browse.hide-added-servers": {
"message": "Sembunyikan pelayan yang ditambah"
},
"app.browse.hide-installed-content": {
"message": "Sembunyikan kandungan yang dipasang"
},
"app.browse.install-content-to-instance": {
"message": "Pasang kandungan ke dalam pemasangan"
},
"app.export-modal.description-placeholder": {
"message": "Masukkan keterangan pek mod..."
},
"app.export-modal.export-button": {
"message": "Eksport"
},
"app.export-modal.header": {
"message": "Eksport pek mod"
},
"app.export-modal.modpack-name-label": {
"message": "Nama Pek Mod"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nama pek mod"
},
"app.export-modal.select-files-label": {
"message": "Pilih fail dan folder untuk disertakan dalam pek mod"
},
"app.export-modal.version-number-label": {
"message": "Nombor versi"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Semua data untuk pemasangan anda akan dipadamkan secara kekal, termasuk dunia, konfigurasi dan semua kandungan yang dipasang."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Tindakan ini tidak boleh dibatalkan"
},
"app.instance.confirm-delete.delete-button": {
"message": "Padam pemasangan"
},
"app.instance.confirm-delete.header": {
"message": "Padam pemasangan"
},
"app.instance.modpack-already-installed.body": {
"message": "Pek mod ini telah dipasang dalam pemasangan <bold>{instanceName}</bold>. Adakah anda pasti mahu menduakannya?"
},
"app.instance.modpack-already-installed.create": {
"message": "Cipta"
},
"app.instance.modpack-already-installed.header": {
"message": "Pek mod sudah dipasang"
},
"app.instance.modpack-already-installed.instance": {
"message": "Pemasangan"
},
"app.instance.mods.content-type-project": {
"message": "projek"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" telah ditambahkan"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projek telah ditambahkan"
},
"app.instance.mods.share-text": {
"message": "Lihat projek-projek yang saya gunakan dalam pek mod saya!"
},
"app.instance.mods.share-title": {
"message": "Berkongsi kandungan pek mod"
},
"app.instance.mods.successfully-uploaded": {
"message": "Berjaya dimuat naik"
},
"app.instance.worlds.add-server": {
"message": "Tambah pelayan"
},
"app.instance.worlds.browse-servers": {
"message": "Layari pelayan"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' akan **dipadamkan secara kekal**, dan tiada cara untuk memulihkannya."
},
"app.instance.worlds.delete-world-title": {
"message": "Adakah anda pasti mahu memadamkan dunia ini secara kekal?"
},
"app.instance.worlds.filter-modded": {
"message": "Diubah Suai"
},
"app.instance.worlds.filter-offline": {
"message": "Luar Talian"
},
"app.instance.worlds.filter-online": {
"message": "Dalam Talian"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanila"
},
"app.instance.worlds.no-worlds-description": {
"message": "Tambah sebuah pelayan atau layari untuk bermula"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Tiada pelayan atau dunia ditambah"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' akan dialih keluar daripada senarai anda, termasuk dalam permainan, dan tiada cara untuk memulihkannya."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) akan dialih keluar daripada senarai anda, termasuk dalam permainan, dan tiada cara untuk memulihkannya."
},
"app.instance.worlds.remove-server-title": {
"message": "Adakah anda pasti mahu mengalih keluar {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Cari {count} dunia..."
},
"app.instance.worlds.this-server": {
"message": "pelayan ini"
},
"app.modal.install-to-play.content-required": {
"message": "Kandungan yang diperlukan"
},
@@ -20,6 +164,9 @@
"app.modal.install-to-play.required-modpack": {
"message": "Pek mod yang diperlukan"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Pelayan ini memerlukan mod untuk dimainkan. Klik Pasang untuk menyediakan fail yang diperlukan daripada Modrinth, kemudian lancarkan permainan terus ke dalam pelayan."
},
"app.modal.install-to-play.shared-instance": {
"message": "Pemasangan yang dikongsi"
},
@@ -29,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Lihat kandungan"
},
"app.modal.update-to-play.added-count": {
"message": "{count} ditambah"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Ditambah"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Dialih keluar"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Dikemas kini"
},
"app.modal.update-to-play.header": {
"message": "Kemas kini untuk mainkan"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} dialih keluar"
},
"app.modal.update-to-play.update-required": {
"message": "Kemas kini diperlukan"
},
"app.modal.update-to-play.update-required-description": {
"message": "Kemas kini diperlukan untuk memainkan {name}. Sila kemas kini kepada versi terkini untuk melancarkan permainan."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} dikemas kini"
},
"app.settings.developer-mode-enabled": {
"message": "Mod pembangun didayakan."
},
@@ -71,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Tetapan lalai pemasangan"
},
"app.settings.tabs.feature-flags": {
"message": "Penetapan ciri"
},
"app.settings.tabs.java-installations": {
"message": "Pemasangan Java"
},
@@ -128,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Muat semula untuk memasang kemas kini"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Pilih pilihan anda"
},
"app.world.world-item.incompatible-version": {
"message": "Versi tidak serasi: {version}"
},
"app.world.world-item.not-played-yet": {
"message": "Belum dimainkan"
},
"app.world.world-item.offline": {
"message": "Luar Talian"
},
"app.world.world-item.players-online": {
"message": "{count} dalam talian"
},
"friends.action.add-friend": {
"message": "Tambah rakan"
},
@@ -227,11 +368,11 @@
"instance.edit-world.title": {
"message": "Sunting dunia"
},
"instance.filter.disabled": {
"message": "Projek yang dinyahdayakan"
"instance.files.adding-files": {
"message": "Sedang menambah fail ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Kemas kini tersedia"
"instance.files.save-as": {
"message": "Simpan sebagai..."
},
"instance.server-modal.address": {
"message": "Alamat"
@@ -341,144 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Pemasangan"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} untuk Minecraft {game_version} sudah pun dipasang"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "{game_version} vanila sudah pun dipasang"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Tukar versi"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Pasang"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Sedang memasang"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Sedang mengambil versi pek mod"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Sedang memasang versi baharu"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Dipasang pada masa ini"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Maklumat nyahpepijat:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Sedang mengambil maklumat pek mod"
},
"instance.settings.tabs.installation.game-version": {
"message": "Versi permainan"
},
"instance.settings.tabs.installation.install": {
"message": "Pasang"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Pemasangan sedang dijalankan"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Versi {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Tidak dapat mengambil butiran pek mod yang terpaut. Sila semak sambungan internet anda."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} tidak tersedia untuk Minecraft {version}. Cuba pemuat mod yang lain."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Pemasangan ini dipautkan kepada sebuah pek mod, tetapi pek mod tersebut tidak dapat dijumpai pada Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Platform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Pasang semula pek mod"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Sedang memasang semula pek mod"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Pemasangan semula akan menetapkan semula semua kandungan yang dipasang atau diubah suai kepada apa yang disediakan oleh pek mod, mengalih keluar sebarang mod atau kandungan yang telah anda tambahkan di atas pemasangan asal. Ini mungkin dapat membetulkan tingkah laku yang tidak dijangka jika perubahan telah dibuat pada pemasangan, tetapi jika dunia anda kini bergantung pada kandungan tambahan yang dipasang, ia mungkin akan merosakkan dunia sedia ada."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Adakah anda pasti mahu memasang semula pemasangan ini?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Menetapkan semula kandungan pemasangan kepada keadaan asalnya, mengalih keluar sebarang mod atau kandungan yang telah anda tambahkan di atas pek mod asal."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Pasang semula pek mod"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Perbaiki"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Sedang memperbaiki"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Pembaikan ini akan memasang semula kebergantungan Minecraft dan memeriksa kerosakan. Ini mungkin dapat menyelesaikan isu jika permainan anda tidak dilancarkan kerana ralat berkaitan pelancar, tetapi tidak akan menyelesaikan isu atau ranap yang berkaitan dengan mod yang dipasang."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Perbaiki pemasangan?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Pembaikan sedang dijalankan"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Tetap semula kepada semasa"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Tunjukkan semua versi"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "mengubah versi"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "memasang"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "memasang semula"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "memperbaiki"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Tidak boleh {action} semasa memasang"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Tidak boleh {action} semasa berada di luar talian"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Tidak boleh {action} semasa memperbaiki"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(versi tidak diketahui)"
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Nyahpaut daripada pelayan"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Nyahpautkan pemasangan"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Jika anda meneruskan, anda tidak akan dapat memautkannya semula tanpa membuat pemasangan yang baharu sepenuhnya. Anda tidak akan menerima kemas kini pek mod lagi dan ia akan menjadi pemasangan biasa."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Adakah anda pasti mahu menyahpautkan pemasangan ini?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Pemasangan ini dipautkan kepada pek mod, yang bermaksud mod tidak boleh dikemas kini dan anda tidak boleh menukar pemuat mod atau versi Minecraft. Menyahpaut pemasangan ini akan memutuskan sambungan pemasangan ini secara kekal daripada pek mod."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Nyahpaut daripada pek mod"
},
"instance.settings.tabs.java": {
"message": "Java dan ingatan"
},
@@ -539,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Jangan tunjukkan pada Laman Utama"
},
"instance.worlds.filter.available": {
"message": "Tersedia"
},
"instance.worlds.game_already_open": {
"message": "Pemasangan sudah pun dibuka"
},
@@ -566,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "Mainkan pemasangan"
},
"instance.worlds.type.server": {
"message": "Pelayan"
},
"instance.worlds.type.singleplayer": {
"message": "Ekapemain"
},
"instance.worlds.view_instance": {
"message": "Lihat pemasangan"
},
@@ -593,6 +590,9 @@
"search.filter.locked.server": {
"message": "Disediakan oleh pelayan"
},
"search.filter.locked.server-environment.title": {
"message": "Hanya mod bahagian pelanggan sahaja yang boleh ditambah pada pemasangan pelayan"
},
"search.filter.locked.server-game-version.title": {
"message": "Versi permainan adalah disediakan oleh pelayan"
},
+169 -181
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Authenticatieservers kunnen niet worden bereikt"
},
"app.browse.add-server-to-instance": {
"message": "Voeg server aan instantie toe"
},
"app.browse.add-servers-to-instance": {
"message": "Voeg servers aan instantie toe"
},
"app.browse.add-to-instance": {
"message": "Voeg aan instantie toe"
},
"app.browse.add-to-instance-name": {
"message": "Voeg aan {instanceName} toe"
},
"app.browse.added": {
"message": "Toegevoegd"
},
"app.browse.already-added": {
"message": "Al toegevoegd"
},
"app.browse.discover-content": {
"message": "Ontdek content"
},
"app.browse.discover-servers": {
"message": "Ontdek servers"
},
"app.browse.hide-added-servers": {
"message": "Verstop toegevoegde servers"
},
"app.browse.hide-installed-content": {
"message": "Verberg Geïnstalleerde inhoud"
},
"app.browse.install-content-to-instance": {
"message": "Installeer inhoud naar instantie"
},
"app.export-modal.description-placeholder": {
"message": "Voeg modpack beschrijving in..."
},
"app.export-modal.export-button": {
"message": "Exporteer"
},
"app.export-modal.header": {
"message": "Exporteer modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Modpack Naam"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpack naam"
},
"app.export-modal.select-files-label": {
"message": "Selecteer bestanden en mappen om toe te voegen aan pack"
},
"app.export-modal.version-number-label": {
"message": "Versie nummer"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Alle data van je instantie zal permanent verwijderd worden, inclusief al je werelden, voorkeuren, en alle geïnstalleerde content."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Deze actie kan niet ongedaan gemaakt worden"
},
"app.instance.confirm-delete.delete-button": {
"message": "Verwijder instantie"
},
"app.instance.confirm-delete.header": {
"message": "Verwijder instantie"
},
"app.instance.modpack-already-installed.body": {
"message": "Deze modpakket is al in de <bold>{instanceName}<bold> instantie geïnstalleerd. Ben je zeker dat je het geen wil dupliceren?"
},
"app.instance.modpack-already-installed.create": {
"message": "Maak"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack is al geïnstalleerd"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instantie"
},
"app.instance.mods.content-type-project": {
"message": "project"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" was toegevoegd"
},
"app.instance.mods.projects-were-added": {
"message": "{count} Projecten waren toegevoegd"
},
"app.instance.mods.share-text": {
"message": "Bekijk de projecten die ik in mijn modpack gebruik!"
},
"app.instance.mods.share-title": {
"message": "Modpack-inhoud delen"
},
"app.instance.mods.successfully-uploaded": {
"message": "Succesvol geüpload"
},
"app.instance.worlds.add-server": {
"message": "Voeg server toe"
},
"app.instance.worlds.browse-servers": {
"message": "Zoek servers"
},
"app.instance.worlds.delete-world-description": {
"message": "{name} Zal **permanent verwijderd** worden en kan niet hersteld worden."
},
"app.instance.worlds.delete-world-title": {
"message": "Weet je zeker dat je deze wereld definitief wilt verwijderen?"
},
"app.instance.worlds.filter-modded": {
"message": "Gemod"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Voeg of zoek een server om te beginnen"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Noch servers noch werelden toegevoegd"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' wordt uit je lijst verwijderd, ook in de game, en kan op geen enkele manier worden hersteld."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) wordt uit je lijst verwijderd, ook in de game, en kan op geen enkele manier worden hersteld."
},
"app.instance.worlds.remove-server-title": {
"message": "Ben je zeker dat je {name} wil verwijderen?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Zoek werelden"
},
"app.instance.worlds.this-server": {
"message": "deze server"
},
"app.modal.install-to-play.content-required": {
"message": "Content vereist"
},
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Toon content"
},
"app.modal.update-to-play.added-count": {
"message": "{count} toegevoegd"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Toegevoegd"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Verwijderd"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Geüpdatet"
},
"app.modal.update-to-play.header": {
"message": "Update om te spelen"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} verwijderd"
},
"app.modal.update-to-play.update-required": {
"message": "Update vereist"
},
"app.modal.update-to-play.update-required-description": {
"message": "Een update is vereist om {name} te spelen. Update naar de laatste versie om het spel te starten."
},
"app.modal.update-to-play.updated-count": {
"message": "{count} geüpdatet"
},
"app.settings.developer-mode-enabled": {
"message": "Ontwikkelaarsmodus ingeschakeld."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Standaardopties voor instantie"
},
"app.settings.tabs.feature-flags": {
"message": "Feature flags"
},
"app.settings.tabs.java-installations": {
"message": "Java installaties"
},
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Herlaad om de update te installeren"
},
"app.world.server-modal.placeholder-address": {
"message": "voorbeeld.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Kies een keuze"
},
"app.world.world-item.incompatible-version": {
"message": "Incompatibele versie{version}"
},
"app.world.world-item.not-played-yet": {
"message": "Nog niet gespeeld"
},
"app.world.world-item.offline": {
"message": "Offline"
},
"app.world.world-item.players-online": {
"message": "{count} online"
},
"friends.action.add-friend": {
"message": "Voeg een vriend toe"
},
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Wereld bewerken"
},
"instance.filter.disabled": {
"message": "Uitgeschakelde projecten"
"instance.files.adding-files": {
"message": "Bestanden toevoegen ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Updates beschikbaar"
"instance.files.save-as": {
"message": "Opslaan als..."
},
"instance.server-modal.address": {
"message": "Adres"
@@ -318,7 +456,7 @@
"message": "Uitgevoerd nadat het spel is afgesloten."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Voer na-afsluitcommando in..."
"message": "Voer een opdracht na het afsluiten in..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Voor het opstarten"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Installatie"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} voor Minecraft {game_version} is al geïnstalleerd"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} is al geïnstalleerd"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Verander versie"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Installeer"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Aan het installeren"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Modpack versies ophalen"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Nieuwe versie aan het installeren"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Huidig geïnstalleerd"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Fout opsporingsinformatie:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Modpack details ophalen"
},
"instance.settings.tabs.installation.game-version": {
"message": "Spel versie"
},
"instance.settings.tabs.installation.install": {
"message": "Installeer"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Bezig met installeren"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Versie {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft versie {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Kan de gekoppelde modpack details niet ophalen. Controleer je internetverbinding."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} is niet beschikbaar voor Minecraft {version}. Probeer een andere mod loader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Deze instantie is gekoppeld aan een modpack, maar de modpack kon niet worden gevonden op Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Platform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Herinstalleer modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Modpack aan het herinstalleren"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Het opnieuw installeren zal alle geïnstalleerde of gewijzigde inhoud resetten naar de inhoud die door de modpack wordt geleverd, en alle mods of inhoud die je bovenop de oorspronkelijke installatie hebt toegevoegd, verwijderen. Dit kan onverwacht gedrag oplossen als er wijzigingen zijn aangebracht in de instantie, maar als je werelden nu afhankelijk zijn van extra geïnstalleerde inhoud, kan dit bestaande werelden beschadigen."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Ben je zeker dat je deze instantie wilt herinstalleren?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Herstelt de inhoud van het exemplaar naar zijn oorspronkelijke staat. Mods en inhoud die bovenop het oorspronkelijke modpack zijn toegevoegd worden verwijderd."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Modpack opnieuw installeren"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Repareer"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Repareren"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Repareren installeert Minecraft-dependencies opnieuw en controleert op corruptie. Dit kan problemen oplossen als uw spel niet start vanwege problemen met de launcher, maar niet problemen of crashes oplossen die te maken hebben met geïnstalleerde mods."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Exemplaar repareren?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Reparatie in behandeling"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Herstel naar huidige"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Toon alle versies"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "verander versie"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "installeer"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "herinstalleer"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "repareer"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Kan niet {action} tijdens installatie"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Kan niet {action} terwijl u offline bent"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Kan niet {action} tijdens reparatie"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(Onherkende versie)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Deze instantie is gekoppeld aan een server, wat betekent dat je de Minecraft versie niet kunt wijzigen. Ontkoppelen zal deze instantie definitief van de server loskoppelen."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Deze instantie is gekoppeld aan een server, wat betekent dat mods niet kunnen worden bijgewerkt en je de modloader of Minecraft-versie niet kunt wijzigen. Ontkoppelen zal deze instantie definitief van de server loskoppelen."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Ontkoppel van server"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Ontkoppel exemplaar"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Als u doorgaat, kunt u het niet opnieuw koppelen zonder een compleet nieuwe exemplaar aan te maken. U ontvangt geen modpack updates meer en het wordt een normaal exemplaar."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Weet u zeker dat u dit exemplaar wilt ontkoppelen?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Dit exemplaar is gekoppeld aan een modpack, wat betekent dat mods niet bijgewerkt kunnen worden en de mod loader of Minecraft versie kan niet gewijzigd worden."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Ontkoppel van modpack"
},
"instance.settings.tabs.java": {
"message": "Java en geheugen"
},
@@ -525,7 +522,7 @@
"message": "De hoogte van het spelvenster wanneer opgestart."
},
"instance.settings.tabs.window.height.enter": {
"message": "Vul hoogte in..."
"message": "Voer de lengte in..."
},
"instance.settings.tabs.window.width": {
"message": "Breedte"
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Niet tonen op de startpagina"
},
"instance.worlds.filter.available": {
"message": "Beschikbaar"
},
"instance.worlds.game_already_open": {
"message": "Instantie is al open"
},
@@ -570,17 +564,11 @@
"message": "Je kan alleen direct de servers in springen in Minecraft Alpha 1.0.5+"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Je kan alleen direct je eigen werelden in springen in Minecraft 1.20+"
"message": "Je kan alleen direct je eigen werelden in springen in Minecraft 1,20+"
},
"instance.worlds.play_instance": {
"message": "Speel instantie"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Alleen spelen"
},
"instance.worlds.view_instance": {
"message": "Bekijk instantie"
},
@@ -20,36 +20,15 @@
"app.modal.install-to-play.shared-server-instance": {
"message": "Delt serverinstans"
},
"app.modal.update-to-play.added-count": {
"message": "{count} lagt til"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Lagt til"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Fjerna"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Oppdatert"
},
"app.modal.update-to-play.header": {
"message": "Oppdater for å spille"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "{count} fjerna"
},
"app.modal.update-to-play.update-required": {
"message": "Krever oppdatering"
},
"app.modal.update-to-play.update-required-description": {
"message": "Ei oppdatering er påkrevd for å spille {name}. Vær så snill å oppdater til den siste versjonen av spillet for å spille det."
},
"app.modal.update-to-play.updated-count": {
"message": "Oppdaterte {count} mods"
},
"app.settings.developer-mode-enabled": {
"message": "Utviklermodus aktivert."
},
@@ -62,9 +41,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Standard instansinstillinger"
},
"app.settings.tabs.feature-flags": {
"message": "Funksjonsflagg"
},
"app.settings.tabs.java-installations": {
"message": "Java installasjoner"
},
@@ -191,12 +167,6 @@
"instance.edit-world.title": {
"message": "Rediger verden"
},
"instance.filter.disabled": {
"message": "Deaktiverte prosjekt"
},
"instance.filter.updates-available": {
"message": "Oppdateringer tiljengelige"
},
"instance.server-modal.address": {
"message": "Adresse"
},
@@ -305,141 +275,9 @@
"instance.settings.tabs.installation": {
"message": "Installasjon"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} for Minecraft {game_version} er allerede installert"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} er allerede installert"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Endre versjon"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Installer"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Installerer"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Henter modpakkeversjoner"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Installerer ny versjon"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "For tiden installert"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Feilsøkingsinformasjon:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Henter modpakkedetaljer"
},
"instance.settings.tabs.installation.game-version": {
"message": "Spillversjon"
},
"instance.settings.tabs.installation.install": {
"message": "Installer"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Installasjon pågår"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} versjon"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Kan ikke hente detaljer for tilknyttet modpakke."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} er ikke tilgjengelig for Minecraft {version}. Prøv en annen mod laster."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Denne instansen er tilknyttet til en modpakke, men modpakken er ikke funnet på Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Platform"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Re-installer modpakke"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Re-installerer modpakke"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Reinstallering vil tilbakestille alt installert eller endret innhold til det som tilbys av modpakken, og fjerne alle mods eller innhold du har lagt til i tillegg til den opprinnelige installasjonen. Dette kan løse uventet oppførsel hvis det er gjort endringer i instansen, men hvis verdenene dine nå er avhengige av ekstra installert innhold, kan det ødelegge eksisterende verdener."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Er du sikker på at du vil reinstallere denne instansen?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Resetter innholdet til instansen til sin opprinnelige tilstand, som fjerner alle mods eller innhold som du har lagd til på toppen av originalpakken."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Reinstaller modpakke"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Reparer"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Reparerer"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Reparasjon reinstallerer Minecraft-avhengigheter og sjekker for korrupsjon. Dette kan fikse problemer hvis spillet ikke starter grunnet launcher-relaterte feil, men vil ikke løse problemer eller krasj relatert til installerte mods."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Reparer instanse?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Reparasjon pågår"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Reset til nåværende"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Vis alle versjoner"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "endre versjon"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "installer"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "reinstaller"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "reparer"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Kan ikke {action} mens en installasjon pågår"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Kan ikke {action} når man er offline"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Kan ikke {action} mens en reparasjon pågår"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(ukjent versjon)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Koble fra instanse"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Hvis du fortsetter, vil du ikke kunne koble det på nytt uten å lage en helt ny instans. Du vil ikke kunne få oppdateringer for modpakker lenger og det vil bli til en normal instans."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Er du sikker på at du vil koble fra denne instansen?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Denne instansen er koblet til en modpakke, som betyr at mods ikke kan bli oppdatert og at du ikke kan endre modloaderen eller Minecraft-versjonen. Å avlenke vil permanent koble fra instansen fra modpakken."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Koble fra modpakke"
},
"instance.settings.tabs.java": {
"message": "Java og minne"
},
@@ -500,9 +338,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Ikke vis på Hjem"
},
"instance.worlds.filter.available": {
"message": "Tilgjengelig"
},
"instance.worlds.game_already_open": {
"message": "Instansen er allerede open"
},
@@ -524,12 +359,6 @@
"instance.worlds.play_instance": {
"message": "Spill instans"
},
"instance.worlds.type.server": {
"message": "Server"
},
"instance.worlds.type.singleplayer": {
"message": "Enkeltspillermodus"
},
"instance.worlds.view_instance": {
"message": "Vis instans"
},
+166 -178
View File
@@ -5,6 +5,150 @@
"app.auth-servers.unreachable.header": {
"message": "Nie udało się połączyć się z serwerami uwierzytelniania"
},
"app.browse.add-server-to-instance": {
"message": "Dodaj serwer do instancji"
},
"app.browse.add-servers-to-instance": {
"message": "Dodaj serwery do swojej instancji"
},
"app.browse.add-to-instance": {
"message": "Dodaj do instancji"
},
"app.browse.add-to-instance-name": {
"message": "Dodaj do {instanceName}"
},
"app.browse.added": {
"message": "Dodano"
},
"app.browse.already-added": {
"message": "Już dodano"
},
"app.browse.discover-content": {
"message": "Odkrywaj zawartość"
},
"app.browse.discover-servers": {
"message": "Odkryj serwery"
},
"app.browse.hide-added-servers": {
"message": "Ukryj dodane serwery"
},
"app.browse.hide-installed-content": {
"message": "Ukryj zainstalowane zasoby"
},
"app.browse.install-content-to-instance": {
"message": "Zainstaluj zasoby do instancji"
},
"app.export-modal.description-placeholder": {
"message": "Wprowadź opis paczki modów..."
},
"app.export-modal.export-button": {
"message": "Eksportuj"
},
"app.export-modal.header": {
"message": "Eksportuj paczkę modów"
},
"app.export-modal.modpack-name-label": {
"message": "Nazwa paczki modów"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nazwa paczki modów"
},
"app.export-modal.select-files-label": {
"message": "Wybierz pliki i foldery, które mają znaleźć się w paczce"
},
"app.export-modal.version-number-label": {
"message": "Numer wersji"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Wszystkie dane z Twojej instancji zostaną trwale usunięte, w tym Twoje światy, pliki konfiguracji i wszystkie zainstalowane treści."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Tej akcji nie można odwrócić"
},
"app.instance.confirm-delete.delete-button": {
"message": "Usuń instancję"
},
"app.instance.confirm-delete.header": {
"message": "Usuń instancję"
},
"app.instance.modpack-already-installed.body": {
"message": "Ta paczka modów jest już zainstalowana w instancji <bold>{instanceName}</bold>. Czy na pewno chcesz utworzyć duplikat?"
},
"app.instance.modpack-already-installed.create": {
"message": "Utwórz"
},
"app.instance.modpack-already-installed.header": {
"message": "Paczka modów jest już zainstalowana"
},
"app.instance.modpack-already-installed.instance": {
"message": "Instalacja"
},
"app.instance.mods.content-type-project": {
"message": "projekt"
},
"app.instance.mods.project-was-added": {
"message": "Dodano \"{name}\""
},
"app.instance.mods.projects-were-added": {
"message": "Dodano {count} {count, plural, one {projekt} few {projekty} other {projektów}}"
},
"app.instance.mods.share-text": {
"message": "Sprawdź projekty, które używam w mojej paczce modów!"
},
"app.instance.mods.share-title": {
"message": "Udostępnianie zawartości paczki modów"
},
"app.instance.mods.successfully-uploaded": {
"message": "Przesyłanie powiodło się"
},
"app.instance.worlds.add-server": {
"message": "Dodaj serwer"
},
"app.instance.worlds.browse-servers": {
"message": "Szukaj serwerów"
},
"app.instance.worlds.delete-world-description": {
"message": "'{name}' zostanie **permanentnie usunięty** i nie ma możliwości go odzyskać."
},
"app.instance.worlds.delete-world-title": {
"message": "Czy na pewno chcesz trwale usunąć ten świat?"
},
"app.instance.worlds.filter-modded": {
"message": "Zmodowany"
},
"app.instance.worlds.filter-offline": {
"message": "Offline"
},
"app.instance.worlds.filter-online": {
"message": "Online"
},
"app.instance.worlds.filter-vanilla": {
"message": "Vanilla"
},
"app.instance.worlds.no-worlds-description": {
"message": "Dodaj serwer lub szukaj, aby rozpocząć"
},
"app.instance.worlds.no-worlds-heading": {
"message": "Nie dodano żadnych światów ani serwerów"
},
"app.instance.worlds.remove-server-description": {
"message": "'{name}' zostanie usunięty z twojej listy, również z gry, i nie będzie możliwości go odzyskać."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) zostanie usunięty z twojej listy, również z gry, i nie będzie możliwości go odzyskać."
},
"app.instance.worlds.remove-server-title": {
"message": "Czy jesteś pewny, że chcesz usunąć {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Szukaj wśród {count} światów..."
},
"app.instance.worlds.this-server": {
"message": "ten serwer"
},
"app.modal.install-to-play.content-required": {
"message": "Wymagane treści"
},
@@ -32,36 +176,15 @@
"app.modal.install-to-play.view-contents": {
"message": "Pokaż zawartość"
},
"app.modal.update-to-play.added-count": {
"message": "Dodano {count}"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Dodano"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Usunięto"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Zaktualizowano"
},
"app.modal.update-to-play.header": {
"message": "Zaktualizuj, by grać"
},
"app.modal.update-to-play.published-date": {
"message": "{date, date, long}"
},
"app.modal.update-to-play.removed-count": {
"message": "Usunięto {count}"
},
"app.modal.update-to-play.update-required": {
"message": "Wymagana jest aktualizacja"
},
"app.modal.update-to-play.update-required-description": {
"message": "Aktualizacja jest wymagana, aby grać w {name}. Proszę zaktualizować do najnowszej wersji, aby uruchomić grę."
},
"app.modal.update-to-play.updated-count": {
"message": "Zaktualizowano {count}"
},
"app.settings.developer-mode-enabled": {
"message": "Tryb dewelopera włączony."
},
@@ -74,9 +197,6 @@
"app.settings.tabs.default-instance-options": {
"message": "Domyślne opcje instancji"
},
"app.settings.tabs.feature-flags": {
"message": "Flagi funkcji"
},
"app.settings.tabs.java-installations": {
"message": "Instalacje Java"
},
@@ -131,6 +251,24 @@
"app.update.reload-to-update": {
"message": "Załaduj ponownie, aby zainstalować aktualizację"
},
"app.world.server-modal.placeholder-address": {
"message": "example.modrinth.gg"
},
"app.world.server-modal.select-an-option": {
"message": "Wybierz opcję"
},
"app.world.world-item.incompatible-version": {
"message": "Niekompatybilna wersja {version}"
},
"app.world.world-item.not-played-yet": {
"message": "Jeszcze nie grano"
},
"app.world.world-item.offline": {
"message": "Offline"
},
"app.world.world-item.players-online": {
"message": "{count} online"
},
"friends.action.add-friend": {
"message": "Dodaj znajomego"
},
@@ -230,11 +368,11 @@
"instance.edit-world.title": {
"message": "Edytuj świat"
},
"instance.filter.disabled": {
"message": "Wyłączone projekty"
"instance.files.adding-files": {
"message": "Dodawanie plików ({completed}/{total})"
},
"instance.filter.updates-available": {
"message": "Dostępne aktualizacje"
"instance.files.save-as": {
"message": "Zapisz jako..."
},
"instance.server-modal.address": {
"message": "Adres"
@@ -344,150 +482,9 @@
"instance.settings.tabs.installation": {
"message": "Instalacja"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} dla Minecraft {game_version} jest już zainstalowana"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} jest już zainstalowana"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Zmień wersję"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Zainstaluj"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Instalowanie"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Pobieranie wersji paczki modów"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Instalowanie nowej wersji"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Obecnie zainstalowane"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Informacje dotyczące debugowania:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Pobieranie szczegółów paczki modów"
},
"instance.settings.tabs.installation.game-version": {
"message": "Wersja gry"
},
"instance.settings.tabs.installation.install": {
"message": "Zainstaluj"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Trwa instalowanie"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Wersja {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Nie można pobrać powiązanych szczegółów paczki modów. Sprawdź swoje połączenie internetowe."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} nie jest dostępny dla Minecraft {version}. Spróbuj inny."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Ta instancja jest połączona z paczką modów, ale nie udało się znaleźć tej paczki modów na Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Platforma"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Zainstaluj paczkę modów ponownie"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Ponowne instalowanie paczki modów"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Ponowne instalowanie zresetuje całą zainstalowaną lub zmodyfikowaną zawartość do stanu podanego przez paczkę modów, usuwając jakiekolwiek mody lub zawartość, którą dodałeś(-aś) ponad oryginalną instalację. Może to naprawić nieoczekiwane zachowanie, jeśli instancja została zmieniona, ale jeśli Twoje istniejące światy polegają na dodatkowej zawartości, którą zainstalowałeś, może to je zepsuć."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Czy jesteś pewien, że chcesz ponownie zainstalować tę instancję?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Resetuje zawartość instancji do jej oryginalnego stanu, usuwając jakiekolwiek modyfikacje lub zawartość którą dodano do paczki modów."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Ponownie zainstaluj paczkę modów"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Napraw"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Naprawianie"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Naprawa ponownie instaluje zależności Minecraft i sprawdza, czy nie są one uszkodzone. Może to rozwiązać problemy, jeśli gra nie uruchomi się z powodu błędów związanych z launcherem, ale nie rozwiąże problemów związanych z zainstalowanymi modami."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Naprawić instancję?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Trwa naprawianie"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Resetuj do aktualnego"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Pokaż wszystkie wersje"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "zmień wersję"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "zainstaluj"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "zainstaluj ponownie"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "napraw"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Podczas instalowania nie można wykonać: {action}"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Nie możesz {action} podczas bycia offline"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Podczas naprawiania nie można wykonać: {action}"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(nieznana wersja)"
},
"instance.settings.tabs.installation.unlink-server-vanilla.description": {
"message": "Ta instancja jest powiązana z serwerem, co oznacza, że nie możesz zmienić wersji gry. Rozłączenie spowoduje trwałe odłączenie tej instancji od serwera."
},
"instance.settings.tabs.installation.unlink-server.description": {
"message": "Ta instancja jest powiązana z serwerem, co oznacza, że mody nie mogą być aktualizowane i nie można zmienić ani loadera, ani wersji gry. Rozłączenie spowoduje trwałe odłączenie tej instancji od serwera."
},
"instance.settings.tabs.installation.unlink-server.title": {
"message": "Rozłącz od serwera"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Rozłącz instancję"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Jeśli przejdziesz dalej, nie będziesz mógł ponownie złączyć tej instancji bez tworzenia całkowicie nowej. Nie będziesz otrzymywać aktualizacji i zostanie ona przekształcona w zwykłą instancję."
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "Czy jesteś pewien, że chcesz rozłączyć tę instancję?"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Ta instancja jest powiązana z paczką modów, co oznacza, że mody nie mogą być aktualizowane i nie można zmienić ani loadera, ani wersji gry. Rozłączenie spowoduje trwałe odłączenie tej instancji od paczki modów."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Rozłącz od paczki modów"
},
"instance.settings.tabs.java": {
"message": "Java i pamięć"
},
@@ -548,9 +545,6 @@
"instance.worlds.dont_show_on_home": {
"message": "Nie pokazuj na stronie głównej"
},
"instance.worlds.filter.available": {
"message": "Dostępny"
},
"instance.worlds.game_already_open": {
"message": "Instancja jest już otwarta"
},
@@ -575,12 +569,6 @@
"instance.worlds.play_instance": {
"message": "Zagraj"
},
"instance.worlds.type.server": {
"message": "Serwer"
},
"instance.worlds.type.singleplayer": {
"message": "Tryb jednoosobowy"
},
"instance.worlds.view_instance": {
"message": "Zobacz instancję"
},

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