Compare commits

...
Author SHA1 Message Date
coolbot100s 7d88cd3a68 Tweak phrasing on servers alert msg 2026-03-01 00:53:55 -08:00
coolbot100s 011e5d8be6 Merge branch 'coolbot/server-project-moderation' of https://github.com/modrinth/code into coolbot/server-project-moderation 2026-02-28 22:17:41 -08:00
coolbot100s ea508eabc3 don't suggest adding a bedrock IP 2026-02-28 22:17:26 -08:00
Truman GaoandGitHub 89f337997d Merge branch 'truman/linked-server-instances' into coolbot/server-project-moderation
Signed-off-by: Truman Gao <106889354+tdgao@users.noreply.github.com>
2026-02-28 22:09:44 -08:00
tdgao 2e7178a752 update some categories to default collapse 2026-02-28 22:04:25 -08:00
coolbot100s 9fa7398227 Update tags.vue warning for server projects. 2026-02-28 21:46:52 -08:00
coolbot100s dc2dc34043 fixes 2026-02-28 21:32:38 -08:00
coolbot100s 2ba47b25c6 reupload, and status messages + nag tweaks. 2026-02-28 21:31:11 -08:00
coolbot100s 509749c937 support servers' v3 exclusive links 2026-02-28 19:26:51 -08:00
coolbot100s 58dd006e44 Tags nag works with servers now 2026-02-28 19:08:57 -08:00
tdgao 25a6a7b10d fix: get server modpack content wrong link 2026-02-28 18:20:46 -08:00
tdgao 61dd6e86c5 fix: router.push doesn't add history state, use nagivateTo instead 2026-02-28 18:02:26 -08:00
tdgao 0da18cfa86 fix: router.push doesn't add history state, use nagivateTo instead 2026-02-28 17:58:30 -08:00
tdgao fa6ce37446 fix no projectV3 2026-02-28 16:52:24 -08:00
coolbot100s 381a0d210d starting tags + servers msg 2026-02-28 16:19:06 -08:00
coolbot100s 43b6a5231d Merge branch 'truman/linked-server-instances' into coolbot/server-project-moderation 2026-02-28 16:10:42 -08:00
tdgao 30a5a119f0 Merge branch 'truman/linked-server-instances' of github.com:modrinth/code into truman/linked-server-instances 2026-02-28 16:08:36 -08:00
tdgao 8262a22cce feat: add the concept of linked worlds for server instances and keep in sync with server project 2026-02-28 16:08:33 -08:00
aecsocket 667513ee18 skip license check for server projects 2026-02-28 23:57:33 +00:00
aecsocket 8372b8a792 server projects are not marked as modpacks 2026-02-28 23:57:33 +00:00
tdgao a6a53a107a fix showing modpack/loader version for server instance in installation settings 2026-02-28 15:46:27 -08:00
tdgao 7428863965 update instance online players to be client ping 2026-02-28 14:57:52 -08:00
tdgao 3db890e44f revert any handling for handling base linked modpack content for content tab 2026-02-28 14:40:12 -08:00
tdgao 785987e31d fix open in browser 2026-02-28 14:25:15 -08:00
tdgao 2ba34d1c2c Revert "update redirect middleware no longer needs projectV3"
This reverts commit 1289cb5286.
2026-02-28 14:24:51 -08:00
coolbot100s 2a379e9eae Merge branch 'truman/linked-server-instances' into coolbot/server-project-moderation 2026-02-28 14:20:29 -08:00
tdgao 41a073f02f feat: add the mf icons finally 2026-02-28 14:15:29 -08:00
tdgao 30acba861b fix: server tags labels 2026-02-28 13:40:53 -08:00
tdgao 0b547231c8 update comment 2026-02-28 13:34:07 -08:00
tdgao 1289cb5286 update redirect middleware no longer needs projectV3 2026-02-28 13:33:28 -08:00
tdgao 51f3e9e1f6 feat: add server projects to moderation queue 2026-02-28 13:28:48 -08:00
tdgao 44030706be fix: modpack content name truncate in project card 2026-02-28 10:47:57 -07:00
tdgao 4ed4560ba8 hide navtabs if theres only one tab 2026-02-28 10:25:56 -07:00
tdgao 5e015ff702 update tooltip 2026-02-28 10:18:04 -07:00
tdgao 7204735843 update language display 2026-02-28 10:17:33 -07:00
tdgao 592dfae307 fix offline server showing online 2026-02-28 10:15:36 -07:00
tdgao 8ca9406cff add active scale 2026-02-28 10:00:16 -07:00
tdgao 996ce12b6b update categories filters from one group filter card to separate filters cards 2026-02-28 09:59:59 -07:00
tdgao 2d83881bfd add sorting for user installed content to be top of list in content 2026-02-28 09:40:21 -07:00
tdgao e13356c239 hide servers tab when installing content to instance 2026-02-28 09:23:42 -07:00
coolbot100s f3e6376c11 fix, revert private use msg, adjust server & link nags 2026-02-28 05:29:50 -08:00
coolbot100s efcd26f194 Filter buttons by server project type 2026-02-27 23:16:30 -08:00
coolbot100s f9527921c5 Merge branch 'truman/linked-server-instances' into coolbot/server-project-moderation 2026-02-27 22:18:20 -08:00
tdgao da26304e7a update installation settings to handle vanilla server instance case 2026-02-27 19:53:31 -07:00
tdgao 469906a4a2 feat: implement allow editing server instances 2026-02-27 19:29:46 -07:00
tdgao d9c9053a70 implement add server to instance 2026-02-27 19:08:53 -07:00
coolbot100s 50f6225e33 Merge branch 'truman/linked-server-instances' into coolbot/server-project-moderation 2026-02-27 15:20:03 -08:00
tdgao 6322928609 add projectV3 to shouldShow callback 2026-02-27 16:13:31 -07:00
coolbot100s c07d2b08a9 Prevent undefined stage from appearing on servers. 2026-02-27 15:08:15 -08:00
tdgao fc03b07fb6 fix servers tab label in profile page 2026-02-27 15:28:38 -07:00
tdgao a6e5f9b441 feat: implement category and countries negative filters 2026-02-27 15:19:57 -07:00
tdgao 2d1ebb31b7 fix: copy ip missing hover effect 2026-02-27 14:51:31 -07:00
tdgao 10ddd67b73 feat: installation tab updates 2026-02-27 14:48:03 -07:00
tdgao 335eb534fe feat: add linked to modpack project for regular modpack instances 2026-02-27 14:40:47 -07:00
tdgao 4cda6343c2 slight change to color 2026-02-27 14:36:37 -07:00
tdgao bdfe7d4bb6 fix tags location 2026-02-27 14:26:20 -07:00
tdgao 3ada5b10b9 update search input background 2026-02-27 14:24:51 -07:00
tdgao 015fc656df conquer the type errors in Browse.vue 2026-02-27 14:06:26 -07:00
tdgao 9fdea27a83 fix: type errors 2026-02-27 13:42:07 -07:00
tdgao ef55e28157 fix: server refresh search reactivity 2026-02-27 13:33:43 -07:00
tdgao 73373f4c78 fix: use windows.history.replace instead of router.replace due to vue production bug and remove logs 2026-02-27 13:06:44 -07:00
tdgao d65375102f add logging for refreshSearch in browse.vue 2026-02-27 12:44:51 -07:00
aecsocket f276cd7881 Category and search sort fixes 2026-02-27 18:58:15 +00:00
tdgao 1fd108c6ab remove components. in search facet 2026-02-27 11:51:35 -07:00
aecsocket c49baec024 fetch latest server player count from redis instead of search doc 2026-02-27 18:44:20 +00:00
aecsocket 4a410fb6f7 don't require auth token for logging server play 2026-02-27 18:44:20 +00:00
tdgao 874ee462cb fix refresh search causing infinite rerender i.e. maximum call stack size exceeded
watch(route) → watch(() => [route.query.i, route.query.ai, route.path]) (line 102): The deep watch on the entire Vue Router route object was the most likely cause of the stack overflow. Vue Router's route object contains matched records with component definitions and other deeply nested structures. Deep-watching it triggers recursive traversal on every route change (including those from router.replace() inside refreshSearch()). Now it only watches the specific properties that updateInstanceContext() actually needs.

ref → shallowRef for serverHits and serverPings (line 189-190): The v3 search results can be deeply nested objects (minecraft_java_server.ping.data, content, etc.). Using shallowRef prevents Vue from creating deep reactive proxies on these objects, which is consistent with how results already uses shallowRef on line 295.

Re-entrance guard + try/catch on refreshSearch() (line 310): The watcher calls refreshSearch() without awaiting, so state changes during the async execution could trigger the watcher again, causing concurrent calls. The guard prevents overlapping calls, and the try/catch ensures loading.value = false is always reached (fixing the infinite loading).
2026-02-27 11:43:29 -07:00
tdgao 108c3765b4 small fix on external icon 2026-02-27 10:34:24 -07:00
tdgao 4680820ec8 fix updating modpack shouldn't launch right into game 2026-02-27 10:29:39 -07:00
tdgao 737026c077 feat: add handling for "stop" instance state for server project card and page play button 2026-02-27 10:20:09 -07:00
tdgao a84a5e4fae pnpm prepr 2026-02-27 10:01:04 -07:00
tdgao d327fa8f85 fix diffs which have unknown project/filename 2026-02-27 09:46:21 -07:00
tdgao a97be599a2 add in wiki page 2026-02-26 23:47:16 -07:00
tdgao fa1d5131b0 fix: redirect running function instead of passing function 2026-02-26 23:37:50 -07:00
tdgao d29bf1dc72 delete required content page placeholder 2026-02-26 23:34:06 -07:00
tdgao b2969bab51 fix: wrong way to determine offline status 2026-02-26 23:04:40 -07:00
tdgao ef77d8a1ae pass undefined instead of unknown for modpack content modal 2026-02-26 22:31:15 -07:00
tdgao f63e01f03f fix: profile create error app backend
Here's what was happening and the fix:

Root cause: In create.rs:107, profile_create assumed the icon_path parameter was always a local filename relative to the caches directory. It did caches_dir().join(icon) which produced a path like ...\caches\https://staging-cdn.modrinth.com/... — the colons in https:// are illegal in Windows paths (OS error 123).

The frontend's installServerProject and createVanillaInstance in install.js:290 both pass project.icon_url (a full URL) directly as the icon parameter.

Fix: Modified profile_create to detect when the icon parameter is a URL (starts with http:// or https://). When it is, it downloads the icon via fetch(), extracts the filename from the URL path, and passes the downloaded bytes and filename to set_icon() which hashes and caches it properly. The existing local-file path continues to work as before.
2026-02-26 22:19:41 -07:00
tdgao 265f3394be fix: server project showing offline 2026-02-26 22:01:18 -07:00
tdgao 3948449c60 fix search in app frontend 2026-02-26 21:55:13 -07:00
tdgao 6a488567e3 feat: deep linking to open server project page then open install to play 2026-02-26 19:24:21 -07:00
tdgao 9391dc0eab add query params for server search 2026-02-26 19:19:26 -07:00
tdgao f2c3cbc88a add grouped filters for search 2026-02-26 19:10:42 -07:00
tdgao ab1d14d570 ensure gallery banners are filtered in app backend gallery display 2026-02-26 18:45:30 -07:00
tdgao 8ba581bc62 fix error handling and helper text copy 2026-02-26 18:41:50 -07:00
tdgao ea75b769e6 upload server banner as gallery image with title == "__mc_server_banner__" and filter it from frontend gallery 2026-02-26 18:36:16 -07:00
tdgao a5f5868d8f fix: savable.ts to reset currentValues to data() after save 2026-02-26 18:23:03 -07:00
tdgao 66bcaa3f1f fix incorrect project type in projects in dashboard 2026-02-26 18:06:35 -07:00
tdgao 518e3797b6 remove console.log 2026-02-26 17:45:36 -07:00
tdgao fa3c70434c fix unsaved changes popup for tags 2026-02-26 17:45:16 -07:00
tdgao 1c24d16bb6 updates to compatibility card, add download button and display supported versions better 2026-02-26 17:42:01 -07:00
tdgao 2d25e46bc6 fix javaServerPatchaData wiping content field 2026-02-26 17:19:44 -07:00
tdgao d12c59247f fix setting project compatibility resets unsaved changes 2026-02-26 17:14:57 -07:00
tdgao 820c65fc1a move server related settings into own tab 2026-02-26 17:09:22 -07:00
tdgao 08fef0d79f make offline tag red and properly hook up online tag 2026-02-26 16:50:00 -07:00
tdgao 13f5c31a5d polish server info card styles 2026-02-26 16:35:10 -07:00
tdgao 5de8bed458 update ip address entire button to be clickable 2026-02-26 16:30:18 -07:00
tdgao c844eabe51 change modpack to modded type 2026-02-26 16:26:04 -07:00
tdgao a44b032db0 disable link for custom modpack project and show tooltip 2026-02-26 16:24:17 -07:00
tdgao a39082fda7 revert pulsing 2026-02-26 16:08:43 -07:00
tdgao c6288daa9d add online status indicator pulsing 2026-02-26 16:03:26 -07:00
tdgao 85cb988708 update online/offline tag 2026-02-26 15:57:42 -07:00
tdgao b7061b2ac8 reenable fence in app backend 2026-02-26 15:26:12 -07:00
tdgao af56fc0bb3 remove play button in website discovery for servers 2026-02-26 15:18:07 -07:00
tdgao 16f4ecf154 Merge branch 'truman/linked-server-instances' of github.com:modrinth/code into truman/linked-server-instances 2026-02-26 15:15:27 -07:00
tdgao 0d48962904 fix: update compatibility modal not closing after successful upload 2026-02-26 15:15:24 -07:00
aecsocket c63b3dacd2 also default java server content 2026-02-26 19:19:15 +00:00
tdgao b34f7e270e small fix on languages multi select 2026-02-26 11:13:27 -07:00
tdgao 1821249025 Merge branch 'truman/linked-server-instances' of github.com:modrinth/code into truman/linked-server-instances 2026-02-26 11:09:48 -07:00
tdgao 0813e1ff95 feat: show server project tags 2026-02-26 11:09:44 -07:00
aecsocket 6dc428c71f Default deserialize ProjectSerial 2026-02-26 18:03:24 +00:00
tdgao 066a4ac1e4 feat: hook up languages 2026-02-26 11:03:06 -07:00
tdgao 2718eec6c5 fix: allow java and bedrock addresses to be deleted 2026-02-26 10:28:52 -07:00
tdgao bbfac2fb25 fix game version filter facet 2026-02-26 10:23:41 -07:00
tdgao 9deb97f45d Merge branch 'truman/linked-server-instances' of github.com:modrinth/code into truman/linked-server-instances 2026-02-26 10:06:19 -07:00
tdgao e76645fc8e pnpm prepr 2026-02-26 10:06:15 -07:00
tdgao af4e6f9349 feat: implement use server search for search sorting and filter facets 2026-02-26 10:06:10 -07:00
tdgao 98243603f2 update java server ping schema 2026-02-26 09:46:11 -07:00
aecsocket fefb446ada send account UUID along with server play analytics 2026-02-26 16:00:17 +00:00
aecsocket 102a7ad7b7 move reporting server joins to backend 2026-02-26 13:36:02 +00:00
aecsocket 4e64ded09b Add game versions to server filters 2026-02-26 13:14:26 +00:00
aecsocket 4d68a7f793 Don't return missing components in project query 2026-02-26 13:01:07 +00:00
tdgao 2464646483 hook up search v3 in app backend for app frontend 2026-02-25 23:09:21 -07:00
tdgao 468b44f1fc fix: server project card tags 2026-02-25 22:29:42 -07:00
tdgao 2a95beb0aa hook up backend searchfor frontend in websiet 2026-02-25 22:15:41 -07:00
tdgao 2b7fdf0e05 fix a lot of the bugginess of navtabs when theres hidden/shown tabs between instances. match frontend nav tabs 2026-02-25 21:24:33 -07:00
tdgao 90a905be69 fix switching between server instance vs regular instance persisted invalid state 2026-02-25 21:14:43 -07:00
tdgao 72de13d38b fix nav tabs active tag 2026-02-25 21:12:35 -07:00
tdgao b65e0d1a03 copy content card item and table from content tab update branch 2026-02-25 20:54:02 -07:00
tdgao 6a97c6e2d9 fix hiding modal after saving server compatibility version 2026-02-25 20:28:07 -07:00
tdgao f15d5d18af handle locking server instance content 2026-02-25 20:25:46 -07:00
tdgao e7e7dd4057 many small fixes 2026-02-25 19:53:24 -07:00
tdgao 7a6233e1aa fix: remove required content tab from server project page 2026-02-25 19:10:02 -07:00
tdgao 1a5529c500 small fix to keep color consistent 2026-02-25 17:49:25 -07:00
tdgao a311bd2648 feat: add tags sidebar card 2026-02-25 17:46:04 -07:00
tdgao 397b3892c8 feat: add hide label for project cards 2026-02-25 17:31:01 -07:00
tdgao 1e79d771b5 update server project header and project card 2026-02-25 17:18:58 -07:00
tdgao 8be5d2521f feat: update project sidebar server info card to new design 2026-02-25 17:01:57 -07:00
tdgao dd9cacab55 add project sidebar stories 2026-02-25 15:16:14 -07:00
aecsocket dd0fa9bf33 cargo sqlx prepare 2026-02-25 19:57:00 +00:00
tdgao 7331101609 hook up server recent plays 2026-02-25 11:51:34 -07:00
tdgao 1cb52b86c3 Merge branch 'truman/linked-server-instances' of github.com:modrinth/code into truman/linked-server-instances 2026-02-25 11:41:32 -07:00
tdgao cbea77f03f fix: allow for links to be set to empty 2026-02-25 11:41:29 -07:00
aecsocket fe3153344b Fix backend impl for server player count analytics 2026-02-25 18:36:21 +00:00
tdgao ae6d1f6782 fix server projects links title 2026-02-25 11:18:45 -07:00
tdgao 4531705051 fix empty server info card 2026-02-25 11:17:57 -07:00
tdgao fcc098f919 fix server projects showing license 2026-02-25 11:16:18 -07:00
tdgao 5e1a7a8695 Merge branch 'truman/linked-server-instances' of github.com:modrinth/code into truman/linked-server-instances 2026-02-25 10:55:41 -07:00
tdgao 1c5181464a fix: server project detection to do loose null check 2026-02-25 10:55:30 -07:00
aecsocket 2a7916eda6 fixes to tracking server joins 2026-02-25 17:38:54 +00:00
aecsocket 2ceb2ef02d report server plays improved in frontend 2026-02-25 16:30:37 +00:00
aecsocket 8e504e9449 queue up server plays in batches 2026-02-25 16:25:57 +00:00
aecsocket f0d1b61293 server verified plays compiling 2026-02-25 16:16:42 +00:00
aecsocket 9e344e5555 wip: server verified plays 2026-02-25 15:10:52 +00:00
coolbot100s edb0de4ecd moderation checklist groundwork 2026-02-25 04:09:07 -08:00
coolbot100s dc79587a3c first few server related nags 2026-02-25 02:58:52 -08:00
coolbot100s e51b2206ec move add-links nag to links.ts 2026-02-25 01:26:25 -08:00
coolbot100s c347dbd256 filter certain nags out from server projects. 2026-02-25 01:25:48 -08:00
tdgao 97be76d998 add ping to project header 2026-02-24 22:30:32 -07:00
tdgao 9d3bd50522 fix play server project button when instance is launched 2026-02-24 22:28:02 -07:00
tdgao 2c362ca7ba add projectV3 to nag context for moderation package 2026-02-24 22:21:10 -07:00
tdgao e312c77159 implement ping server projects for latency in app 2026-02-24 22:13:37 -07:00
tdgao 57757dbfb1 small change: open discover to modpack 2026-02-24 21:51:31 -07:00
tdgao 1e4dfe9d68 add comment 2026-02-24 21:34:10 -07:00
tdgao 35b7bb3c3c add global installing server project state 2026-02-24 21:30:36 -07:00
tdgao 5ea8a956f1 show update success instead of launching right into the game 2026-02-24 17:46:15 -07:00
tdgao 94c64c28d4 use large play button instance 2026-02-24 17:45:52 -07:00
tdgao 216f28850c fix how install.js installs instance with modpack content title instead of server project title and dont fetch icon when installing to existing instance 2026-02-24 17:26:26 -07:00
tdgao 7a0c7e1992 show recommended & supported versions for vanilla 2026-02-24 16:52:25 -07:00
tdgao 529a455fe3 on click link for server side bar info 2026-02-24 16:43:42 -07:00
tdgao b546bfd5b8 fix undefined property 2026-02-24 16:34:08 -07:00
tdgao adddb72ba7 hide app nav tabs if only one tab 2026-02-24 16:30:36 -07:00
tdgao 62f0a58cac move servers tab to end 2026-02-24 16:29:05 -07:00
tdgao f5387353cc add diff detection for version dependencies without version_id/project_id 2026-02-24 16:21:17 -07:00
tdgao d75d7a6671 Merge branch 'truman/linked-server-instances' of github.com:modrinth/code into truman/linked-server-instances 2026-02-24 14:56:58 -07:00
tdgao 54f2c3a29f fix import 2026-02-24 14:56:42 -07:00
aecsocket a2bec70c62 remove leftover prompt 2026-02-24 18:32:58 +00:00
aecsocket 969700a01f Merge branch 'boris/server-listing-api' into truman/linked-server-instances 2026-02-24 18:24:24 +00:00
aecsocket bdb5d6deac fix search indexing not showing fields 2026-02-24 18:23:46 +00:00
aecsocket 7c3ab22956 fix serde deser flatten 2026-02-24 18:23:46 +00:00
aecsocket 8c68de0ee0 sqlx 2026-02-24 18:23:46 +00:00
aecsocket 46427f6a24 fix more defaults stuff 2026-02-24 18:23:46 +00:00
aecsocket 46bc137a9e wip: massive component query refactor 2026-02-24 18:23:46 +00:00
aecsocket e3cf5c6a0a wip: server modpack content query, components in search 2026-02-24 18:23:46 +00:00
aecsocket d005efa815 fix migration to sync with main, propagate background task errors 2026-02-24 18:23:46 +00:00
aecsocket a42fbb42c1 wip: clean up server ping, background tasks 2026-02-24 18:23:46 +00:00
aecsocket 22e31f9099 synthetic server project version for search indexing 2026-02-24 18:23:46 +00:00
aecsocket 4d64fd175b Improve server messages for app pinging 2026-02-24 18:23:46 +00:00
aecsocket 09290b452d Schema changes 2026-02-24 18:23:46 +00:00
aecsocket c3f76bfd64 clear cache on project ping, add server store link 2026-02-24 18:23:46 +00:00
aecsocket adc85f24bd fix compile error 2026-02-24 18:23:46 +00:00
aecsocket 3c527778a5 tombi fmt 2026-02-24 18:23:46 +00:00
aecsocket 3182c28027 Switch to Redis for server pings 2026-02-24 18:23:46 +00:00
aecsocket 515d1b3196 wip: resolve comments with pings 2026-02-24 18:23:46 +00:00
aecsocket 194873a5e7 fix shear 2026-02-24 18:23:46 +00:00
aecsocket 3acff84465 allow querying server ping data 2026-02-24 18:23:46 +00:00
aecsocket 1455f71f62 tombi fmt 2026-02-24 18:23:46 +00:00
aecsocket 49438d33a1 tombi fmt 2026-02-24 18:23:46 +00:00
aecsocket 6d3139f254 sqlx prepare 2026-02-24 18:23:46 +00:00
aecsocket 3a14e4fd46 mc ping server info + timeout 2026-02-24 18:23:46 +00:00
aecsocket c3a6f4d416 ping queue with tests 2026-02-24 18:23:46 +00:00
aecsocket df7ac297af wip: ping queue 2026-02-24 18:23:46 +00:00
aecsocket f3be9397c9 wip: ping minecraft servers queue 2026-02-24 18:23:46 +00:00
aecsocket 117257bcf9 clean up component edit code 2026-02-24 18:23:46 +00:00
aecsocket 6e011b043f Allow editing components 2026-02-24 18:23:46 +00:00
aecsocket 9aed50d50c docs 2026-02-24 18:23:46 +00:00
aecsocket 4fd747e6aa utoipa support for projects 2026-02-24 18:23:46 +00:00
aecsocket 7ce09d65be game version fields 2026-02-24 18:23:45 +00:00
aecsocket 7cddcee8e1 Version component creation 2026-02-24 18:23:45 +00:00
aecsocket b1c914015b Version components backend API 2026-02-24 18:23:45 +00:00
aecsocket 884907ad0c wip: version components 2026-02-24 18:23:45 +00:00
aecsocket 416598bf6d Update project component structure for servers 2026-02-24 18:23:45 +00:00
aecsocket e04a60e582 New project component metadata schema 2026-02-24 18:23:45 +00:00
aecsocket 4f24641296 No more six seven 2026-02-24 18:23:45 +00:00
aecsocket 55173e9b5a fix up rebase 2026-02-24 18:23:45 +00:00
aecsocket dbacbdafad revert accidental change 2026-02-24 18:23:45 +00:00
aecsocket 487e1e1bdd wip: project components API 2026-02-24 18:23:45 +00:00
aecsocket 7d9e58d877 wip: v67 project creation endpoint 2026-02-24 18:23:45 +00:00
aecsocket 4e5d234701 wip: server listing API 2026-02-24 18:23:45 +00:00
aecsocket 9f814ead27 update frontend to work with new versions list route 2026-02-24 18:23:45 +00:00
tdgao 764926179d use modpack content returned from project 2026-02-24 10:52:04 -07:00
tdgao 2819ade3ce rename server required content to server modpack content 2026-02-24 10:36:44 -07:00
tdgao 955fa43b2d add modpack content link to server project card 2026-02-24 10:34:35 -07:00
e362de45fb Fix library routerview race condition (#5412)
Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
2026-02-24 16:52:50 +00:00
tdgao b0b28f90b9 similarly fix routerview race condition between project page and instance page 2026-02-24 09:46:49 -07:00
tdgao 9bacb4594d fix race condition 2026-02-24 09:33:18 -07:00
tdgao 298644dd29 fix updating modpack 2026-02-23 19:51:52 -07:00
tdgao abd3862a65 fix update to play modal requests 2026-02-23 19:48:37 -07:00
tdgao bbadf272e5 small fix on upload custom modpack and add tabular num 2026-02-23 19:31:55 -07:00
tdgao 6f1a06a4d8 remove the massive buttons 2026-02-23 19:19:43 -07:00
tdgao 2694206b35 add server to profile for server projects 2026-02-23 19:09:23 -07:00
tdgao 6b6c49073a add view contents modal 2026-02-23 18:48:35 -07:00
tdgao 0ce315a1ac add dropdown button 2026-02-23 18:48:12 -07:00
tdgao 9195920fca add modpack content modal 2026-02-23 16:54:11 -07:00
tdgao f2f09b9b9c add view contents stub 2026-02-23 16:54:03 -07:00
tdgao c4ebbf0575 hide installation tab for server project instance 2026-02-23 16:31:13 -07:00
tdgao b4b42a42d9 add tooltip on recent plays and online players 2026-02-23 16:21:00 -07:00
tdgao 83714d4660 handle error for join server 2026-02-23 16:02:16 -07:00
tdgao 9182a09453 console log tags 2026-02-23 15:47:42 -07:00
tdgao b5fa03b15e install to play modal show custom mrpack name and remove shared by 2026-02-23 15:04:49 -07:00
tdgao 5b687e6449 fix instance details items 2026-02-23 14:53:34 -07:00
tdgao cd4571f6c7 fix barrel exports 2026-02-23 14:53:16 -07:00
tdgao c1c1fc1b38 fix missing icon for vanilla instance 2026-02-23 14:20:33 -07:00
tdgao 250e163bfb add auto complete "off" for address fields 2026-02-23 13:57:47 -07:00
tdgao c7b70bac10 fix uploading progress label 2026-02-23 13:51:57 -07:00
tdgao 1315052bca add comment 2026-02-23 13:29:23 -07:00
tdgao e7e5e7ecf9 dont default to CA country on create 2026-02-23 13:26:29 -07:00
tdgao f0ee8aacbc add project type field when open create project from org and dashboard 2026-02-23 13:20:52 -07:00
tdgao 038bb53757 fix vanilla server project no tags 2026-02-23 13:20:07 -07:00
tdgao 52e3123c5b fix project type redirect 2026-02-23 12:54:47 -07:00
tdgao c0a2c4d5d4 fixes to server compatibility card 2026-02-23 12:45:42 -07:00
tdgao 89bcd7fb36 disable "create project" when theres missing fields 2026-02-23 12:19:32 -07:00
tdgao f93884ab4b comment out circuit breaker 2026-02-21 18:36:38 -07:00
tdgao 22a348ca64 add option for staging environment in app build 2026-02-21 18:09:13 -07:00
tdgao c135af93a0 add server project hard coded project ids to include the one in search 2026-02-21 17:36:40 -07:00
tdgao c10be2d796 fix get version cache 2026-02-21 17:15:24 -07:00
tdgao 18343eea32 default server discovery flag to true 2026-02-21 17:12:37 -07:00
tdgao a985a43d6c add required content page placeholder in app 2026-02-21 16:45:38 -07:00
tdgao 17e1ade828 add server projects for all 3 types for testing 2026-02-21 16:22:37 -07:00
tdgao 3ff6642544 hook up play button in server card 2026-02-21 15:30:45 -07:00
tdgao 8bd204915d proper fix on nav tabs 2026-02-21 15:15:35 -07:00
tdgao 3eba32bafe fix active tab in nav 2026-02-21 13:56:08 -07:00
tdgao 2025ad5380 small fixes 2026-02-21 13:40:41 -07:00
tdgao 80ea4e1924 add required content tab project page in web and app and placeholder page for web 2026-02-21 13:25:59 -07:00
tdgao 217281e021 add required content component for server details 2026-02-21 13:12:14 -07:00
tdgao 9173505fc5 update open in app modal and hook up to play buttons 2026-02-21 12:45:01 -07:00
Truman GaoandGitHub bacc10d2f5 feat: better auth error handling (#5403)
* add log

* add log

* Revert "add log"

This reverts commit 2412a3de5f.

* add new minecraft auth error modal

* add other auth errors

* polish the styles

* update link text

* add unknown error state

* pnpm prepr

* fix link

* fix lint
2026-02-21 01:39:27 +00:00
aecsocketandGitHub 5b49af1fe8 Fix creating projects from mod install flow (#5402)
* Explicitly state if a mod is incompatible when installing

* wip: debug create instance modal

* Fix mod install createInstance
2026-02-21 00:22:06 +00:00
tdgao e808ec975c add server project card in search in app 2026-02-20 16:12:23 -07:00
tdgao 7a5d6e94ed add server tab in app 2026-02-20 15:34:53 -07:00
tdgao 7833b1687f move side bar server info queries to parent 2026-02-20 13:58:38 -07:00
tdgao 5cff50bd23 add project sidebar server info to app project page 2026-02-20 13:39:10 -07:00
tdgao c8ace75898 small fix 2026-02-20 13:00:33 -07:00
tdgao c68d5ca86d implement proper server project instance header 2026-02-20 12:58:54 -07:00
tdgao 3c4ef3c6ec add install server project util and fix install and update to play modals which use modpack content 2026-02-20 12:36:16 -07:00
tdgao b52ef5d8ed fix install to play by bypassing cache in app backend install pack 2026-02-20 10:29:16 -07:00
f052ecd702 Batch of tech review backend fixes (#5398)
* Don't enter project into tech review if no new traces

* Send tech review exited message if files are deleted

* change PATCH /issue-detail/{id} to batch update details

* Fix sorting

* store delphi jar in backend

* show jar in tech review card

* improve jar display in frontend

* Fix live/in review label for tech review cards

* sqlx prepare

* polish: decode segments + code qual fix

* fix: skip first seg

* fix: only slice if needed

* Fix tech rev card styling

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-02-20 12:54:36 +00:00
tdgao f1a97e37ff remove hard coded path 2026-02-19 21:47:51 -07:00
tdgao 266f45e37d update install to play with new content api (install not working) 2026-02-19 19:55:08 -07:00
tdgao 2b0ba51c62 update server info card to query required content project 2026-02-19 18:36:24 -07:00
tdgao 0ea4cfed09 small button style update 2026-02-19 18:16:13 -07:00
tdgao 33c9dbeac2 fix compatibility card empty state 2026-02-19 18:06:08 -07:00
tdgao 80e8a61668 style fixes in server compatibility card 2026-02-19 17:55:21 -07:00
tdgao 1b3c8cd0be fix width on floating action bar 2026-02-19 17:45:19 -07:00
tdgao 3fef34c631 remove astrisks 2026-02-19 17:39:56 -07:00
tdgao 40c74dc2cb fix stupid ah type errors 2026-02-19 17:37:01 -07:00
tdgao c3e205f006 remove num followers 2026-02-19 17:33:03 -07:00
tdgao e41665dc87 add sidebar server info card 2026-02-19 17:22:48 -07:00
tdgao b934b79089 fix server link 2026-02-19 16:45:33 -07:00
tdgao 66b6f6eca0 hook up server project discovery to backend 2026-02-19 15:39:35 -07:00
tdgao a2dccf65e2 fix server project hard coded list 2026-02-19 14:52:52 -07:00
tdgao 32008f9580 add redirect for server project type 2026-02-19 14:46:01 -07:00
tdgao 0cb3776520 fix flag svg in project page header 2026-02-19 13:21:39 -07:00
tdgao dd70e834cb remove scroll to top on patch project 2026-02-19 13:05:45 -07:00
tdgao 445c80fbdc Merge branch 'truman/linked-server-instances' into prospector/server-project-page 2026-02-19 13:02:54 -07:00
tdgao fba3c49018 fix imports 2026-02-19 12:49:55 -07:00
tdgao ffc80a4796 use dynamic component for different server vs project page header 2026-02-19 12:35:42 -07:00
tdgao 0d0fdab646 fix: dont circuit break in dev environment 2026-02-19 11:38:33 -07:00
Truman GaoandGitHub 33ff2a0759 fix: trying to get formatMessage with no current platform (#5397) 2026-02-19 17:40:53 +00:00
aecsocketandGitHub ec81bcb13c Improve environment variable handling and reading (#5389)
* wip: better env var reading

* move most env vars to env.rs

* migrate more env vars

* more migration

* more migrations

* More migration

* 🦀 dotenvy is gone (almost)

* 🦀 dotenvy is gone 🦀

* Fix mural source account env var handling

* Remove defaults from admin key vars

* dummy commit to update github pr

* fix ci
2026-02-19 17:33:41 +00:00
aecsocketandGitHub b6b4bc21f1 Cherry-pick migrations from server projects into main (#5395)
* Cherry-pick migrations from server projects into main

* Fix up project types and seed data

* fix tag test
2026-02-19 17:32:58 +00:00
9a83db2e67 fix: ensure NavTabs slider aligns correctly with dynamic tabs (#5377)
* fix(ui): ensure NavTabs slider aligns correctly with dynamic tabs

* fix: lint

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-02-19 16:57:17 +00:00
Prospector 1e190ff7c1 Merge remote-tracking branch 'origin/prospector/server-project-page' into prospector/server-project-page
# Conflicts:
#	packages/ui/src/components/project/ServerProjectHeader.vue
#	packages/ui/src/components/project/server/ServerPing.vue
2026-02-19 07:38:18 -08:00
Prospector 19f419fcbb ping to component 2026-02-19 07:37:15 -08:00
Prospector c9571315a4 beginning of server project stuff 2026-02-19 07:35:49 -08:00
Prospector 96700ed2bf remove empty div when modal closed 2026-02-19 07:33:35 -08:00
Prospector 1ad4fdbd93 simplify adplaceholder css 2026-02-19 07:33:35 -08:00
Prospector 73e1fc4709 add more project stuff to api client 2026-02-19 07:33:35 -08:00
Prospector 412f43dac7 images icon 2026-02-19 07:33:35 -08:00
Prospector 15e83bd4e3 avatar ts-ification 2026-02-19 07:33:35 -08:00
Prospector 3fe7679a9e beginning of server project stuff 2026-02-19 07:32:56 -08:00
tdgao 0dcaf6900c Merge branch 'main' into truman/linked-server-instances 2026-02-18 15:21:28 -07:00
tdgao 702e9882b6 fix upload banner 2026-02-18 14:52:09 -07:00
tdgao 6663a3c64f implement exclude own project id in select publish modpack content 2026-02-18 14:49:33 -07:00
tdgao 2ff9db4708 small fix 2026-02-18 14:44:16 -07:00
tdgao fb10ccda52 add new link urls to project page sidebar 2026-02-18 14:42:51 -07:00
tdgao cf637561fe fix v3 patch data 2026-02-18 14:08:20 -07:00
tdgao 41207cbdef remove console.log 2026-02-18 13:46:38 -07:00
tdgao 4d083c0d42 better variable names 2026-02-18 13:46:17 -07:00
tdgao 475010a50d hook up server ping to server project headerr 2026-02-18 13:44:52 -07:00
tdgao 5d48d086a5 add mc server ping to types 2026-02-18 13:04:06 -07:00
tdgao 16c9a3cfce update compatibility card for custom mrpack 2026-02-18 13:03:28 -07:00
30c48718e2 fix: single loader projects download button not showing (#5391)
* fix: single loader projects downlaod button not showing

* pnpm prepr

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
2026-02-18 19:45:28 +00:00
tdgao 0e231ca815 add language field 2026-02-18 12:31:12 -07:00
tdgao 599dc90d89 add links todo 2026-02-18 11:39:42 -07:00
Calum H.andGitHub 8328a0d61a fix: gdpr issue posthog + type improvements (#5392) 2026-02-18 18:21:21 +00:00
Truman GaoandGitHub b62bc6f3b8 fix cannot read "body" from undefined (#5387) 2026-02-18 17:43:14 +00:00
Truman GaoandGitHub 0e752ab415 feat: handling mrpack with no loaders (#5363)
* handle modpack upload with no loaders

* restrict loaders for modpack

* actually, dont allow modpack loaders to be editable

* revert loader picker changes
2026-02-18 17:43:07 +00:00
tdgao 5635896940 move manage server compatibility modal to providers folder 2026-02-18 10:10:47 -07:00
Prospector 047f72856d remove empty div when modal closed 2026-02-18 07:54:34 -08:00
Prospector 7c5f98033d simplify adplaceholder css 2026-02-18 07:53:40 -08:00
Prospector 78c94e68fa add more project stuff to api client 2026-02-18 07:51:24 -08:00
Prospector 5ade45373a images icon 2026-02-18 07:50:29 -08:00
Prospector 2e2aea2107 avatar ts-ification 2026-02-18 07:50:22 -08:00
tdgao e26df077b0 hook up play server project inside instance play button 2026-02-18 00:06:39 -07:00
tdgao b32d6fd20a refactor: make the play server project function much more readible 2026-02-18 00:01:22 -07:00
tdgao fa02aedfb4 add update vanilla version if changed 2026-02-17 23:50:38 -07:00
aecsocketandGitHub 9f558404bd Improve error logging in project delete route (#5388)
* Improve error logging in project delete route

* remove_documents more error logging

* fix ci

* try fix ci? idk man
2026-02-18 05:06:50 +00:00
tdgao 2ed3984521 small fix 2026-02-17 18:38:32 -07:00
tdgao 3e5a4e795f small fix 2026-02-17 18:29:54 -07:00
tdgao 7772c9ba59 prefill existing values for vanilla 2026-02-17 16:51:27 -07:00
tdgao 055f5525d9 use deep merge instead of shallow merge for project patch mutation 2026-02-17 16:47:32 -07:00
tdgao 1ec00e188f add empty state 2026-02-17 16:35:22 -07:00
tdgao a5ab5bb414 fix cannot read body of undefined 2026-02-17 16:20:49 -07:00
tdgao de60a29c99 use new UnsavedChanges popup in general settings 2026-02-17 16:13:33 -07:00
tdgao b347061fba small style fix 2026-02-17 16:02:17 -07:00
tdgao 436c9c5981 rename showDataLossWarning to isSwitchingCompatibilityType 2026-02-17 15:57:54 -07:00
tdgao 1820fed1cd update show dataloss warning save button 2026-02-17 15:56:51 -07:00
tdgao 3e55aaafef implement danger on switch compatibility type 2026-02-17 15:25:46 -07:00
tdgao 11b2ce1511 small style updates 2026-02-17 15:02:25 -07:00
tdgao b99a460e3e implement proper updating server compatibility 2026-02-17 15:00:50 -07:00
tdgao 1b2b5c859c update required modpack card for custom modpack 2026-02-17 14:15:13 -07:00
tdgao af9c3d1a9d small style updates 2026-02-17 14:08:03 -07:00
tdgao 437734e3bc pnpm prepr 2026-02-17 13:55:28 -07:00
Calum H.andGitHub 4be2f77bb0 feat: reimpl (#5386) 2026-02-17 18:51:30 +00:00
tdgao f664c170f8 delete content tab and create server version modal 2026-02-17 11:25:57 -07:00
tdgao 3f0f60fbea implement upload custom .mrpack 2026-02-17 11:25:36 -07:00
tdgao 406aa672d8 fix usage of --color-text-dark to use --color-text-primary 2026-02-17 11:08:14 -07:00
tdgao fdefb66af0 add compatibility card selected content and move it into its own card in settings 2026-02-17 11:03:33 -07:00
tdgao 90323da310 rename to manage server compatibility modal 2026-02-17 09:54:46 -07:00
tdgao 7f7d30e65f implement save server compatibility 2026-02-16 22:28:27 -07:00
tdgao d4eb66ee6c implement reset modal on hide 2026-02-16 21:36:33 -07:00
tdgao de3ec34aef add tooltip 2026-02-16 21:13:57 -07:00
tdgao c41ba8c3c9 implement select published modpack 2026-02-16 21:11:32 -07:00
tdgao 9ffcbd9b5b implement select compatibility type stage 2026-02-16 20:04:16 -07:00
tdgao e1971365e6 fix compatibility card styles 2026-02-16 18:33:04 -07:00
tdgao c626da819f start server compatibility modal and card 2026-02-16 18:19:09 -07:00
Prospector b3fbd884e0 changelog 2026-02-16 12:33:46 -08:00
Prospector 8c0edf669d new cpmstar ads.txt 2026-02-16 12:31:07 -08:00
tdgao fbdcd27520 pnpm i 2026-02-16 12:55:46 -07:00
tdgao 8e2833cb2a Merge branch 'main' into truman/linked-server-instances 2026-02-16 12:44:32 -07:00
f01c901445 Collection descriptions can get out of the collection's box (#5380)
* Collection descriptions can get out of the collection's box
Fixes #2281

* Update apps/frontend/src/pages/dashboard/collections.vue

Signed-off-by: Calum H. <hendersoncal117@gmail.com>

---------

Signed-off-by: Calum H. <hendersoncal117@gmail.com>
Co-authored-by: Calum H. <hendersoncal117@gmail.com>
2026-02-16 17:15:05 +00:00
Modrinth BotandGitHub 2a91fc31f1 New translations from Crowdin (main) (#5382) 2026-02-16 09:35:41 +00:00
Truman GaoandGitHub d1e4c1039f fix: project version page dependencies showing "unknown project" unless refresh (#5366)
* fix not updating stale dependencies

* remove console log

* fix wragnler json formatting

* add proper loading dependencies

* pnpm prepr

* move v-if
2026-02-14 00:31:17 +00:00
tdgao a763f6d83a refactor: make the patch data more readiable 2026-02-13 15:36:49 -07:00
tdgao cce25833ff implement setting recommended and supported versions 2026-02-13 15:14:52 -07:00
tdgao 559275bfad small style fixes 2026-02-13 10:52:20 -07:00
tdgao b20465d077 refactor: instances/index to use typescript 2026-02-13 10:38:33 -07:00
tdgao 0b4fcb4e92 fix more cannot get property of... due to null/undefined errors 2026-02-13 09:55:39 -07:00
tdgao 4d9c53dfe0 fix error when loading in app 2026-02-13 09:52:38 -07:00
tdgao 67f9decfe1 fix linked data not passed into profile create 2026-02-12 20:00:04 -07:00
Michael H. 9432d6d5e8 deploy(ui): fix storybook routes 2026-02-13 01:24:42 +01:00
Michael H. c053c00bd7 deploy(ui): remove custom domain 2026-02-13 01:22:06 +01:00
Michael H. 9d0df74475 deploy(ui): add wrangler 2026-02-13 01:19:35 +01:00
Michael H. 09e989a4c4 deploy(ui): add wrangler config 2026-02-13 01:15:06 +01:00
Calum H.andGitHub d4ef5f36c3 devex: storybook build (#5364) 2026-02-13 01:06:33 +01:00
Calum H.andGitHub a9e0655859 fixes: withdraw flow tax check fix + checklist fix (#5360)
* fix: action bar overlap on checklist

* fix: tax form uses local currency not net usd
2026-02-12 13:29:21 +00:00
aecsocketandGitHub e7eb4899a1 Fix user deletion to update more tables (#5351)
* wip: fix user delete

* add wrap_errs

* delete more rows in user deletion

* sqlx prepare
2026-02-12 11:37:40 +00:00
tdgao 0c4bd5b09b fix click to play flow for vanilla servers 2026-02-11 22:08:41 -07:00
tdgao 94bfa26dfd Merge branch 'truman/linked-server-instances' of github.com:modrinth/code into truman/linked-server-instances 2026-02-11 17:50:26 -07:00
tdgao 30a50df85a feat: implement playServerProject util 2026-02-11 17:49:46 -07:00
tdgao e01c2b1a14 get is server project in page 2026-02-11 10:52:18 -07:00
tdgao f231466532 update profile to run instance with server address 2026-02-11 10:51:33 -07:00
Prospector 9ce31b8032 lint 2026-02-11 09:05:56 -08:00
tdgao 192de9e957 implement get_project_v3 in app backend 2026-02-10 17:52:02 -07:00
tdgao dabddacccb use invalidate 2026-02-10 16:52:12 -07:00
tdgao 93d32cf2e9 fix inputs to use styledInput 2026-02-10 16:47:36 -07:00
76ba11d966 Settings ui fixes (#5352)
* Fix tabbed modal icon size

* Fix slider input being unstyled

* Refactor slider component to use ui components and tailwind

* Pnpm fix my beloved

---------

Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
2026-02-10 23:36:36 +00:00
tdgao 22a961db72 fix patch project v3 2026-02-10 15:58:30 -07:00
tdgao 8bddff40a7 Merge branch 'main' into truman/linked-server-instances 2026-02-10 15:32:53 -07:00
tdgao 6c0f2a985f add tooltip 2026-02-10 15:19:10 -07:00
tdgao c9f7cae4b6 implement new instance header 2026-02-10 14:39:15 -07:00
tdgao c801d155a9 type fix on mc version picker 2026-02-10 14:08:42 -07:00
tdgao e1fa007384 clean up code 2026-02-10 10:55:57 -07:00
tdgao b8e413050c fix data loading in 2026-02-10 10:39:57 -07:00
tdgao 15476975a2 hook up setting server addresses 2026-02-10 10:19:48 -07:00
tdgao 03ac7bcda9 hook in new transfer org 2026-02-09 22:35:28 -07:00
tdgao ec56781ebc various fixes for popup notification 2026-02-09 22:09:04 -07:00
tdgao 168750d45a fix popup notification styles 2026-02-09 22:07:57 -07:00
Prospector f22e49e4f5 v 2026-02-09 16:23:27 -08:00
Prospector 3c1bd86dcc changelog 2026-02-09 16:22:55 -08:00
Prospector 4adbd0b843 changelog 2026-02-09 16:19:10 -08:00
Truman GaoandGitHub cec35dcb60 fix: project card preload on hover (#5348) 2026-02-09 23:37:58 +00:00
Calum H.andGitHub a536d795f3 devex: dead locales cleanup + i18n inspect tool (#5313)
* chore: remove old locales + just enable all locales now

* feat: debug panel for i18n + tooltips

* feat: dedupe

* fix: debugger for app

* fix: crowdin code mismatches

* fix: lint
2026-02-09 16:00:46 +00:00
Daniel (rotgruengelb)andGitHub e3e04931cf fix: collections-grid on profile page applied margin -bottom instead of -top. (#5346) 2026-02-09 15:56:52 +00:00
Prospector 3e505e0d96 changelog 2026-02-09 07:37:11 -08:00
Calum H.andGitHub dd4b054d95 fix: replace legacy timeouts with v-bind in navtab component (#5343)
* fix: dont use timeouts for navtabs

* fix: remove nexttick
2026-02-09 15:24:39 +00:00
e80d7730ca fix: preserve allowed iframe query parameters (#5295)
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-02-09 15:17:37 +00:00
Prospector 0facf26b04 changelog 2026-02-09 07:13:34 -08:00
Calum H.andGitHub 37eac92329 refactor: migrate all input fields to StyledInput (#5306)
* feat: StyledInput component

* migrate: auth pages to styledInput

* migrate: search/filter inputs

* migrate: dashboard inputs

* migrate: app frontend

* migrate: search related inputs

* migrate: all of app-frontend

* fix: missing inputs on app-frontend

* migrate: frontend

* feat: multiline

* migrate: textareas

* fix: storybook use text-primary

* fix: lint

* fix: merge conflict

* feat: cleanup
2026-02-09 14:57:31 +00:00
Calum H.andGitHub 90438a1ad5 fix: invalidate tanstack caches on user auth (#5341)
* fix: invalidate tanstack caches on user auth

* refactor: clean up invalidate flow

* fix: lint
2026-02-09 14:43:33 +00:00
Calum H.andGitHub e962521492 feat: dynamic tax thresholds from backend (#5342)
* feat: dynamic tax thresholds from backend

* fix: lint & i18n
2026-02-09 14:42:38 +00:00
Calum H.andGitHub 45a397d52b fix: action button positioning on mobile (#5344) 2026-02-09 14:37:01 +00:00
d9d7750781 fix #5243: detect file data on multi-part uploads (#5331)
* fix modrinth/code#5243: detect file data on multi-part uploads

* fix return early not making handlingNewFiles = false

---------

Co-authored-by: Calum H. <calum@modrinth.com>
2026-02-09 12:55:39 +00:00
Modrinth BotandGitHub 1101e71fdd New translations from Crowdin (main) (#5339) 2026-02-09 10:19:58 +00:00
Prospector 34b4ae283e changelog 2026-02-08 17:19:42 -08:00
JerozgenandGitHub a8c5e036d0 Sort categories by translated name (#5307)
* Sort categories by translated name

* Use locale and numeric

* Remove @modrinth/ui import
2026-02-08 17:19:04 -08:00
ProspectorandGitHub 4eb0f0c206 Fix author name underline + fix gallery preference being broken (#5337) 2026-02-08 17:01:23 -08:00
tdgao 37f63afedb add popup notification panel, add it to storybook, and replace app popups with it 2026-02-08 17:59:21 -07:00
Truman GaoandGitHub a3bc35c303 fix:icon too bright (#5335) 2026-02-08 16:59:00 -08:00
tdgao 9e17cd4d33 pt2 2026-02-08 14:33:44 -07:00
tdgao dc676e15b6 Merge branch 'main' into truman/linked-server-instances 2026-02-08 14:33:37 -07:00
Prospector 57e012f9b7 Revert "Fix author name underline + hover icon brightness"
This reverts commit 8ab1895d8a.
2026-02-07 14:05:35 -08:00
Prospector 8ab1895d8a Fix author name underline + hover icon brightness 2026-02-07 13:51:18 -08:00
Prospector 13e5529f00 add project status to grid cards 2026-02-07 12:28:06 -08:00
Prospector 428efde36d proj card fixes 2026-02-07 12:05:59 -08:00
Prospector a978873bff changelog 2026-02-07 11:36:52 -08:00
b005c1f522 New project cards (#5298)
* New project card

* no shadow on icons

* Remove updated label

* reduce tag count to 5

* improve envs

* fix: project card bottom row not growing

* move actions in grid mode

* focus changes + new project list component

* Allow more tags in grid mode, deprioritize non-loader tags

* fix prod deploy robots.txt

* remove unused id

* App cards

* prepr

* publish date + fix router links

* fix author hover underline in firefox

* perf: preload on search item hover

* remove unused filter

* remove option for old grid view

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-02-07 11:18:59 -08:00
Prospector b6c22d6ca6 changelog 2026-02-07 10:28:59 -08:00
Calum H.andGitHub 50064c4ed6 qa: tech review 3 (#5250)
* fix: only collapse if pending -> pass/fail, not pass <-> fail

* feat: wrap in full details block

* feat: left badge

* feat: in mod queue -> in project queue

* fix: hash on malic modal

* feat: remove return to queue on indiv page

* fix: truncate in middle

* feat: bulk actions

* fix: reactivity problem

* feat: project page dropdown option

* feat: show metadata if exists

* fix: lint

* fix: qa problems

* feat: debug logging for malicious summary modal

* fix: lint

* qa: go back on bulk

* fix: reactive sets/maps -> refs

* fix: lint
2026-02-07 18:10:58 +00:00
tdgao 0982d2ceb6 better content header for small screen width 2026-02-06 17:58:12 -07:00
tdgao f81e3f36ed move content page header actions slot to be in line with title/summary if there exists a summary 2026-02-06 17:38:42 -07:00
tdgao 17145e303e add server project header 2026-02-06 17:07:40 -07:00
tdgao fd3b562092 hook up update to play 2026-02-06 16:39:34 -07:00
tdgao 8bfb007038 update copy 2026-02-06 16:39:09 -07:00
tdgao 0778e19b0e feat: update project and instance headers to match designs 2026-02-06 16:31:49 -07:00
ProspectorandGitHub 48248eafdc Fix app releases not being signed (#5317) 2026-02-06 23:19:40 +00:00
b34564a770 Fix editing project team member permissions (#5315)
* Fix editing project team member permissions

* prepare

* add success notifications

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
2026-02-06 14:56:36 -08:00
ProspectorandGitHub d713cea180 fix instance page in app (#5316) 2026-02-06 14:53:57 -08:00
tdgao 3b39d75685 stub server ping 2026-02-06 14:53:21 -07:00
tdgao 40dc007394 add country field 2026-02-06 11:41:01 -07:00
JerozgenandGitHub 695233e736 Add ICU select to report strings (#5312) 2026-02-06 18:27:55 +00:00
Calum H.andGitHub 8789d7b057 fix: 5258 (#5310)
* fix: 5258

* fix: lint
2026-02-06 18:21:41 +00:00
tdgao f819ce356f fix links page 2026-02-05 16:18:56 -07:00
tdgao 904803c0c0 fix submit when error 2026-02-05 15:38:09 -07:00
tdgao 963d35c133 fix hide on creaet 2026-02-05 15:34:28 -07:00
tdgao 1a6ed679e4 small qa fix 2026-02-05 15:26:00 -07:00
tdgao cb49902b25 fix import 2026-02-05 15:24:14 -07:00
tdgao 062a332247 qa fixes for update to play model 2026-02-05 15:24:06 -07:00
tdgao a8bb03ff1c Merge branch 'main' into truman/linked-server-instances 2026-02-05 13:37:45 -07:00
tdgao a10c242857 update copy 2026-02-05 13:36:56 -07:00
tdgao 407e196c3a hide environment moderation for server project 2026-02-05 13:36:54 -07:00
tdgao f7f31c0991 feat: update visibility section 2026-02-05 13:23:57 -07:00
tdgao 2ad5cd5442 copy updates and reorganizing settings 2026-02-05 12:47:21 -07:00
tdgao cf9ca8b9be fix submit buttons 2026-02-05 12:47:09 -07:00
tdgao d915a32f53 add combobox sublabel 2026-02-05 12:46:44 -07:00
tdgao 66953d851c filter recommended version select from support mc versions 2026-02-05 11:44:23 -07:00
tdgao a9011576af use featured gallary image as banner 2026-02-05 11:38:59 -07:00
tdgao 98eeb9fe13 add gallery routes to api client 2026-02-05 10:56:30 -07:00
tdgao 0c18af1213 fix: hover on publish button 2026-02-05 10:32:15 -07:00
tdgao c893dfcb22 add todo 2026-02-05 10:15:01 -07:00
lumiscosityandGitHub 510ea6cde4 Enable support for Filipino, Indonesian, Korean, Dutch, and Vietnamese (#5305)
All five of these have now crossed 80% translation completion!

Signed-off-by: lumiscosity <averyrudelphe@gmail.com>
2026-02-05 14:52:38 +00:00
aecsocketandGitHub b1954be2c7 Ref-count Redis pool internals, fix project creation slug/ID collision (#5302)
* Ref-count Redis pool internals, fix project creation slug/ID collision

* cargo sqlx prepare
2026-02-05 05:18:33 +00:00
Prospector 9105a68923 changelog 2026-02-04 15:54:16 -08:00
Prospector 06e2f59a94 changelog 2026-02-04 14:54:17 -08:00
ProspectorandGitHub ddb013e024 translatable category headers (#5301) 2026-02-04 14:47:35 -08:00
aecsocketandGitHub 3f5e3b1d8b Disable login captcha if backend has no captcha secret (#5288)
* Add /_internal/globals route

* Don't show login captcha if backend claims it's disabled

* try to re-add tombi

* typos

* Assume captcha enabled if globals route is unreachable

* Prepare frontend fixes
2026-02-04 18:08:14 +00:00
Prospector c958091ee6 owner selector copy 2026-02-04 07:37:36 -08:00
Prospector 37b9610d26 prepr 2026-02-04 07:34:34 -08:00
Prospector 7f45734c4d Merge remote-tracking branch 'origin/main' into truman/linked-server-instances
# Conflicts:
#	apps/app-frontend/src/components/ui/modal/InstallToPlayModal.vue
#	apps/app-frontend/src/components/ui/modal/UpdateToPlayModal.vue
#	apps/app-frontend/src/pages/instance/Index.vue
#	apps/app-frontend/src/pages/project/Index.vue
2026-02-04 07:29:37 -08:00
323090966b feat: app server projects modals + modal borders (#5256)
* feat: add modals

* NewModal add stroke

* update diff type sorting

* update icon to match figma

* fix lint ci issues

* remove formatCategory

* feature flag on buttons

* prepr

* consistent modal borders

* intl

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-02-04 07:27:25 -08:00
Calum H.andGitHub 16204d30f8 fix: withdraw flow fixes (#5296)
* fix: dev-741 currency exchanging bug

* fix: remove redundant balance available check

* fix: lint/fmt

* fix: #5245

* fix: hide max if it's less than min
2026-02-04 14:56:14 +00:00
JerozgenandGitHub 34cbc7e0c1 Use numeric: always for Italian and Russian (#5293)
* Use `numeric: always` for Italian and Russian

* Use RelativeTimeFormatNumeric type
2026-02-04 13:49:21 +00:00
tdgao d48f6243a7 small updates 2026-02-03 14:54:08 -07:00
tdgao e5d3eff085 pnpm prepr 2026-02-03 14:39:19 -07:00
tdgao 091a74cf84 add recommended version copy 2026-02-03 14:24:07 -07:00
tdgao 7aeabf60e0 fix uploaded file in custom mrpack content 2026-02-03 14:05:05 -07:00
tdgao 672a18d49f fix type error 2026-02-03 13:50:33 -07:00
tdgao 2f131d4ac7 Merge branch 'main' into truman/linked-server-instances 2026-02-03 13:41:29 -07:00
tdgao 892f8e5946 fix date 2026-02-03 13:32:10 -07:00
tdgao 3877d40b64 update create version modal to hook up to backend 2026-02-03 13:20:13 -07:00
tdgao 87aecc267d use requested_status and organization_id 2026-02-03 12:55:35 -07:00
aecsocketandGitHub 5d6593a9da Add more Prometheus metrics for memory and Tokio tasks (#5282)
* Add more Prometheus metrics for memory and Tokio tasks

* pr comments
2026-02-03 19:05:34 +00:00
Prospector ab753a82bc changelog 2026-02-03 09:11:50 -08:00
Truman GaoandGitHub 880e759336 fix: ensure legacy texture pack is checking .zip file extension (#5284) 2026-02-03 04:38:56 +00:00
tdgao 65d0803c37 update table 2026-02-02 20:23:17 -07:00
tdgao 4ce81f0e8f implement transfer to org on create project 2026-02-02 19:44:59 -07:00
tdgao d935a8f983 hook up create server project endpoint 2026-02-02 19:32:45 -07:00
tdgao 04b3488dbc remove server project feature flag and mock get project v3 route 2026-02-02 18:38:15 -07:00
Prospector 84b386141c Fix formatLoader 2026-02-02 16:57:15 -08:00
Prospector e9a4cc60ca update ads.txt 2026-02-02 16:55:44 -08:00
aecsocketandGitHub d5869c514e Use deadpool fork with tracing (#5276)
* Use deadpool fork with tracing

* Implement minimum Redis connections

* fix typos maybe

* address pr comments
2026-02-02 23:24:55 +00:00
Prospector de0a03b2e9 changelog 2026-02-02 13:17:22 -08:00
3f6c79b00d Application & pat ui improvements (#5271)
* Add categories, make localizable

* Run fix

* Run prepr

* Improve pat modal ui

* Fix pat token actions

* Make scope category localization shared

* Fix casing

* Fix casing

---------

Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-02-02 18:20:28 +00:00
ProspectorandGitHub 56c8bb1950 Remove legacy formatCategory (#5280)
* Remove legacy formatCategory

* prepr
2026-02-02 18:20:23 +00:00
François-Xavier TalbotandGitHub f81f951814 Don't persist read search client across reqs (#5277) 2026-02-02 14:09:00 +00:00
François-Xavier TalbotandGitHub 345ada27c0 Increase/make configurable search timeouts (#5261)
* Increase default operation timeout, make it configurable via SEARCH_OPERATION_TIMEOUT

* Don't update index settings when unneeded

* Add to env local
2026-02-02 13:27:29 +00:00
François-Xavier TalbotandGitHub e3395a7366 Development app builds (#5255)
* Workflow changes

* Propagate app_identifier via State

* Remove old updater stuff

* Remove patch file

* Remove unused binding

* Fix application loading

* Don't sign windows binaries by default

* Remove the damn emojis

* Figure out where windows artifacts are

* Fix windows artifacts
2026-02-02 13:10:23 +00:00
Modrinth BotandGitHub 3552c8280b New translations from Crowdin (main) (#5274) 2026-02-02 09:49:27 +00:00
ProspectorandGitHub 11f00be606 Clean up formatters from prev PR (#5254) 2026-02-02 09:38:36 +00:00
aecsocketandGitHub a207daef0d Update charges rows on user deletion (#5269) 2026-02-01 19:14:38 +00:00
aecsocketandGitHub ddd395ed4f Fix FX conversion for Tremendous methods (#5268) 2026-02-01 19:05:32 +00:00
Prospector 04a7ae55e7 prepr 2026-01-30 15:18:38 -08:00
Prospector 5a33d462f6 changelog 2026-01-30 13:05:32 -08:00
ProspectorandGitHub cefa7b90ed Add noindex to pages that should be private (#5257)
* Add noindex to pages that should be private

* fix unused
2026-01-30 13:04:19 -08:00
tdgao acccddffc3 delete duplicate keys 2026-01-30 12:55:31 -07:00
tdgao 7e6470e361 pnpm prepr 2026-01-30 10:47:49 -07:00
tdgao 43ab52a902 Merge branch 'main' into truman/linked-server-instances 2026-01-30 10:45:56 -07:00
NotchArrowandGitHub 0875a8a0bc Fixed Payout Source Code Link (#5251) 2026-01-30 16:51:20 +00:00
Calum H.andGitHub 5624e86c2b fix: stale cache handling (#5253)
* fix: allow stale cache

* fix: cache amnt

* fix: other one asw
2026-01-30 16:41:03 +00:00
Prospector c622a9281f changelog 2026-01-30 07:51:57 -08:00
Prospector 937d385241 Revert "remove imgur from proxy whitelist (#5239)"
This reverts commit deaa57fa15.
2026-01-30 07:50:38 -08:00
Calum H.andGitHub 3ec9bcf7e7 fix: caching problems frontend for version upload (#5252) 2026-01-30 14:50:57 +00:00
tdgao 68a09b1c9c implement locking required version and hiding supported versions when using mrpack 2026-01-29 23:01:48 -07:00
tdgao 3eea154520 fix: combobox disabled state 2026-01-29 22:48:32 -07:00
tdgao dd7b8fdb46 add todos 2026-01-29 22:40:38 -07:00
tdgao bba62c6b98 feat: implement required and supported versions 2026-01-29 22:38:29 -07:00
tdgao 6fb15eb4c5 feat: implement update to play modal 2026-01-29 15:34:17 -07:00
tdgao 93e292d5a6 start update to play moadl 2026-01-29 11:00:50 -07:00
tdgao 6c2ab769c4 small copy updates to install to play modal 2026-01-29 11:00:41 -07:00
tdgao 2092ba85ed fix hide modal on install to play 2026-01-29 09:57:06 -07:00
Prospector 3dd5314062 Add loading state to envs 2026-01-28 17:52:32 -08:00
Prospector d77823c5f4 Fix reference to props on members page 2026-01-28 17:19:51 -08:00
Prospector 41b48bd353 changelog 2026-01-28 16:42:42 -08:00
6225ece6be Add Tangled to common source links (#5236)
* Add Tangled to common source links

* prepr

---------

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

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

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

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

* fix: tooltips + colors

* feat: fix orgs

* feat: add ContentModpackCard

* fix: extract types

* feat: selection v-model

* add show icon in selected for combobox with stories

* feat: add project combobox

* clean up project combobox

* feat: start install to play modal

* fix: events

* feat: figma alignments

* feat: migrate toggle to tailwind

* fix: row borders

* feat: disabled state

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

* fix: lint

* feat: virtualization + smaller contentcard items

* feat: fix gap + border issues on last elm

* fix: use TeleportOverflowMenu

* fix: hasUpdate type

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

* fix: storybook

* feat: start on updater modal

* feat: finish content updater modal

* feat: i18n pass

* remove install to play modal from ui package

* pnpm prepr

* feat: reusable table component

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

* feat: add table overflow menu story example

* feat: add surface-1.5 and use in table

* chore: export table in index

* fix: allow more loose typing on columns

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

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

* fix: lint

* feat: add no padding story for new modal

---------

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

* fix: locale problems

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

* Migrate more things

* fix import

* more import fixes

* export tag-messages

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

* deduplicate common strings, part 2

* typo and general import mess fixes

* detail common string

* fix lint

* fix lint TWO

* adress review concerns + lint

* app lint too

* actually leave privateLabel untouched

* lint fix THREE

* fix: broken msg

* fix: lint

---------

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

* feat: useSavable improvements

* feat: migrate where possible to useSavable

* fix: gitignore

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

* (compiles) standardize pg types used

* more standardization

* general log message improvements

* wip: improve sqlx-tracing architecture

* unify sqlx::Executor type

* wip: try fix sqlx tracing

* wip: sqlx-tracing compiles

* so close

* it compiles

* fix ci
2026-01-28 13:38:57 +00:00
tdgao a0858efbcd Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-27 21:03:55 -07:00
tdgao a8c4e2dfb1 feat: update table component to derive key from column instead of data 2026-01-27 21:02:33 -07:00
tdgao 1d7c8a0bdd update above table buttons 2026-01-27 20:37:29 -07:00
tdgao e67f25166c update active tag 2026-01-27 20:24:23 -07:00
Prospector 7cb7e881fa Revert "changelog"
This reverts commit 638bb55649.
2026-01-27 16:31:20 -08:00
Prospector 2cf82349a5 Revert "feat: badge for tax 2025 bug (#5230)"
This reverts commit 6d1b0eef15.
2026-01-27 16:31:15 -08:00
Prospector 638bb55649 changelog 2026-01-27 14:09:10 -08:00
Calum H.andGitHub 6d1b0eef15 feat: badge for tax 2025 bug (#5230) 2026-01-27 19:03:54 +00:00
03658b6a62 feat: show update available notif for modrinth app in linux (#5181)
* feat: show update available notif for modrinth app in linux

* remove changelog button

* update copy

* pnpm prepr

* add restart app changelog

* pnpm prepr

* use env var to check for updates are disabled

* update copy

* pnpm prepr

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-27 14:20:11 +00:00
tdgao 02a9f4c722 fix: allow more loose typing on columns 2026-01-26 16:10:04 -07:00
tdgao 11769df7b7 add mocked server proj versions table 2026-01-26 16:09:03 -07:00
François-Xavier TalbotandGitHub f998a8dca5 Allow node transfer field to recv more than 1 node (#5220) 2026-01-26 22:49:21 +00:00
tdgao 021b85928d Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-26 15:10:40 -07:00
tdgao 9783cbf52b chore: export table in index 2026-01-26 15:10:31 -07:00
tdgao 51398a1323 Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-26 14:55:54 -07:00
tdgao 8392ae3513 feat: add surface-1.5 and use in table 2026-01-26 14:48:06 -07:00
tdgao ccee5e0ca7 Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-26 14:13:40 -07:00
tdgao b1972afb16 feat: add table overflow menu story example 2026-01-26 14:11:57 -07:00
tdgao 292b3f8e8c feat: add column width prop for table and fix stories 2026-01-26 13:59:45 -07:00
tdgao e63787c5dd feat: reusable table component 2026-01-26 13:49:23 -07:00
tdgao 5232929c5a fixes from merge with main 2026-01-26 12:32:03 -07:00
tdgao bfaed9a9a5 update get project route 2026-01-26 12:16:49 -07:00
tdgao f281a804ea add api routes for server projects 2026-01-26 12:14:42 -07:00
tdgao 50f738101e pnpm prepr 2026-01-26 10:50:22 -07:00
tdgao 71074d8499 pnpm prepr 2026-01-26 10:47:15 -07:00
tdgao 138b5e9971 Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-26 10:44:29 -07:00
tdgao e165180a8d remove install to play modal from ui package 2026-01-26 10:37:07 -07:00
Calum H.andGitHub 61e69ac0d7 Merge branch 'main' into worlds-and-shared-instances-components
Signed-off-by: Calum H. <contact@cal.engineer>
2026-01-26 08:33:10 +00:00
Calum H. (IMB11) 0c12fbed2f feat: i18n pass 2026-01-26 08:30:14 +00:00
Calum H. (IMB11) 1e70473574 feat: finish content updater modal 2026-01-26 08:21:10 +00:00
Modrinth BotandGitHub 0d6bee3a5b New translations from Crowdin (main) (#5217) 2026-01-26 07:47:29 +00:00
Prospector 7ce334aeb2 changelog 2026-01-25 13:22:14 -08:00
ProspectorandGitHub fe3a1b2058 Fix versions not loading in settings page (#5214)
* Fix versions not loading in settings page

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

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

* feat: add https for futureproofing asw

---------

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

* fix: gallery settings
2026-01-25 12:27:45 -08:00
Calum H. (IMB11) 16f46a464e feat: start on updater modal 2026-01-24 22:08:24 +00:00
Calum H. (IMB11) 1712ed2fd2 fix: storybook 2026-01-24 18:21:59 +00:00
François-Xavier TalbotandGitHub 2d7e87a4cb Local cache lock (#5193) 2026-01-24 00:35:46 +01:00
Prospector fa421b4b83 changelog 2026-01-23 12:59:29 -08:00
François-Xavier TalbotandGitHub 79217e78b4 Theseus circuit breaker (#5196)
* Impl request fence

* Reduce max FETCH_ATTEMPTS

* Tweak fail threshold & window

* Check block status every retry iteration

* Fix fmt

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

* feat: lazy load non-core data

* feat: ssr timing debugging

* feat: go back to all parallel

* feat: migrate to DI + set up mutators

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

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

* feat: gallery.vue start

* fix: remove left behind console log

* fix: type issues + gallery

* fix: versionsummary modal + version page direct join

* fix: projectRaw guard

* fix: currentMember val fix

* fix: actualProjectType

* fix: vers summary link same page

* fix: lint

---------

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

* format what we've got so far

* lint and fix locale setting

* the rest of the owl, almost

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

* finishing touches

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

* whoops, that's literal

* get back in the span, you

* fix typo + lint

* and now it works

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

* Batched search indexing that actually works

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

* Improve Redis tracing

* improve messages

* make lpush and brpop use traced cmds
2026-01-22 17:46:37 +01:00
Calum H. (IMB11) af35e92218 fix: fallback to svg if src is invalid on avatar component 2026-01-22 13:37:48 +00:00
Calum H. (IMB11) 4877eaee5d fix: hasUpdate type 2026-01-22 13:16:51 +00:00
Calum H. (IMB11) 067b3466ee fix: use TeleportOverflowMenu 2026-01-22 13:13:00 +00:00
Calum H. (IMB11) d4af422214 feat: fix gap + border issues on last elm 2026-01-22 12:17:36 +00:00
Calum H. (IMB11) bd5fbb3d09 feat: virtualization + smaller contentcard items 2026-01-22 12:07:13 +00:00
Calum H. (IMB11) 6f84acb01b fix: lint 2026-01-22 11:38:10 +00:00
Calum H. (IMB11) ff5ed4045d feat: virtual list impl for card table based on window scroll 2026-01-22 11:35:31 +00:00
Calum H. (IMB11) 144bde8976 feat: disabled state 2026-01-22 11:18:28 +00:00
Calum H. (IMB11) 1850de7b8d fix: row borders 2026-01-22 11:01:19 +00:00
Calum H. (IMB11) e0c871c0e4 feat: migrate toggle to tailwind 2026-01-22 10:54:31 +00:00
Calum H. (IMB11) f46a4fb4c6 feat: figma alignments 2026-01-22 10:29:59 +00:00
Prospector adf365d99d changelog 2026-01-21 14:50:48 -08:00
ProspectorandGitHub f3f48c3c6f Fix .some error (#5180) 2026-01-21 14:48:47 -08:00
aecsocketandGitHub e072f2237b Improve Labrinth Sentry integration (#5174)
* Improve Sentry integration

* remove debug routes

* fix ci

* sentry tracing stuff

* Add spans to Sentry logging

* Fix CI

* Redis op instrumentation

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

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

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

* fix string reference

* fixed formatting

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: aecsocket <aecsocket@tutanota.com>
2026-01-21 01:15:33 +00:00
tdgao db3f745562 implement install function and move install to play modal into app-frontend 2026-01-20 17:38:36 -07:00
ProspectorandGitHub b36801c5ed Reduce some more sentry errors (#5173)
* short-circuit user menu options if no user

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

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

* prepr
2026-01-20 13:51:12 -08:00
tdgao 35b962178e Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-20 14:29:49 -07:00
tdgao 2e900879da Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-20 14:29:22 -07:00
ProspectorandGitHub 8f5185de1c Error on state fail in prod and log endpoint errors (#5167)
* Error on state fail in prod and log endpoint errors

* brint back eslint suppress

* lint
2026-01-20 21:16:25 +00:00
tdgao 7135ef4cf4 implement open in app modal 2026-01-20 14:13:26 -07:00
ProspectorandGitHub 9f6db31785 update Modrinth Hosting issue template + misc comments (#5166) 2026-01-20 12:40:11 -08:00
a869086ce9 polish(frontend): technical review QA (#5097)
* feat: filtering + sorting alignment

* polish: malicious summary modal changes

* feat: better filter row using floating panel

* fix: re-enable request

* fix: lint

* polish: jump back to files tab qol

* feat: scroll to top of next card when done

* fix: show lock icon on preview msg

* feat: download no _blank

* feat: show also marked in notif

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

* feat: proper page titles

* fix: text-contrast typo

* fix: lint

* feat: QA changes

* feat: individual report page + more qa

* fix: back btn

* fix: broken import

* feat: quick reply msgs

* fix: in other queue filter

* fix: caching threads wrongly

* fix: flag filter

* feat: toggle enabled by default

* fix: dont make btns opacity 50

---------

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

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

* Search management routes

* Probably fluke

* Use utoipa routes

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

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

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

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

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

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

* Fix

---------

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

* adjust app cache logic

* more cache logic

* cleanup

* add v2 redirect

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

* fix: yeet
2026-01-19 13:57:49 -08:00
Michael H. 11fe90a69b deploy: nerf cpu time to 5s 2026-01-19 22:27:38 +01:00
Michael H. 1108086854 Revert "Remove dev check in payload/pojo debugger (#5152)"
This reverts commit 3f3e6f5199.
2026-01-19 22:27:15 +01:00
Michael H. 5aea892a39 deploy: raise cpu limit to 10s 2026-01-19 22:12:31 +01:00
tdgao 51d84ca80c feat: start install to play modal 2026-01-19 14:00:58 -07:00
tdgao 1591fcc795 fix: update file dropzone size 2026-01-19 12:22:12 -07:00
tdgao e4536b5f66 Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-19 12:01:01 -07:00
tdgao b5a5a6a10c clean up project combobox 2026-01-19 12:00:05 -07:00
tdgao 1501b11f7b feat: add project combobox 2026-01-19 11:46:09 -07:00
Calum H.andGitHub 3f3e6f5199 Remove dev check in payload/pojo debugger (#5152)
* Remove dev dcheck in payload/pojo debugger

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

* feat: better payload debugger

---------

Signed-off-by: Calum H. <contact@cal.engineer>
2026-01-19 10:28:25 -08:00
tdgao 63a90f7051 use new showIconInSelected prop 2026-01-19 11:26:46 -07:00
tdgao ea2431b2dd Merge branch 'worlds-and-shared-instances-components' into truman/linked-server-instances 2026-01-19 11:08:13 -07:00
tdgao 973208730e add show icon in selected for combobox with stories 2026-01-19 11:06:58 -07:00
tdgao 2dc3dad296 fix: update header 2026-01-19 10:59:12 -07:00
Calum H. (IMB11) 4a26d17951 feat: selection v-model 2026-01-19 15:39:04 +00:00
Calum H. (IMB11) 74cc23054d fix: extract types 2026-01-19 09:42:34 +00:00
Calum H. (IMB11) b54276fb10 feat: add ContentModpackCard 2026-01-19 09:32:31 +00:00
Modrinth BotandGitHub 2efcd383bb New translations from Crowdin (main) (#5154) 2026-01-19 07:35:48 +00:00
Prospector faec9c2965 changelog 2026-01-18 11:28:51 -08:00
Calum H.andGitHub a0e8c7f924 feat: more o11y for i18n pojo (#5148) 2026-01-18 11:18:07 -08:00
Emma AlexiaandGitHub 6efdfdf17e chore: 100k Modrinth projects 🎉 (#5150)
Signed-off-by: Emma Alexia <emma@modrinth.com>
2026-01-18 19:10:47 +00:00
Truman GaoandGitHub aec268c6e9 fix: duplicate changelogs not grouping (#5146)
* fix: changelogs not grouping

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

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

* prioritise fabric over nf

* pnpm prepr

---------

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

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

* fix: lint

* move to plugin

---------

Signed-off-by: Calum H. <contact@cal.engineer>
2026-01-16 11:56:46 -08:00
tdgao 765e3fba0e update links page 2026-01-16 11:40:54 -07:00
tdgao 6e84c922fa feat: implement create server project version and server general settings page 2026-01-16 11:26:35 -07:00
Calum H.andGitHub 82e4eb7b40 feat: light mode fixes for navtab + files tab (#5134) 2026-01-16 18:23:43 +00:00
Calum H.andGitHub bd5f0364c2 Merge branch 'main' into worlds-and-shared-instances-components 2026-01-16 10:11:32 +00:00
Calum H. (IMB11) 847d752dae feat: fix orgs 2026-01-16 10:06:56 +00:00
Calum H. (IMB11) 548c1f3be4 fix: tooltips + colors 2026-01-16 09:57:56 +00:00
Calum H. (IMB11) 6328d4d92a feat: base content card component 2026-01-16 09:47:13 +00:00
Calum H.andGitHub c9bfc4e9b6 fix: analytics.js using old i18n impl (#5132)
* fix i18n

* fix: lint
2026-01-16 09:07:40 +00:00
Calum H.andGitHub 1ea96df00e fix: broken infinite query on files.vue (#5133) 2026-01-16 09:03:56 +00:00
tdgao 93805bc7b9 feat: update nav links for servers 2026-01-15 23:37:45 -07:00
tdgao 6753e95922 fix spacing 2026-01-15 21:06:18 -07:00
tdgao 2dcc031a52 add server project related fields 2026-01-15 21:01:47 -07:00
Calum H.andGitHub 75c5316dc3 fix: PAT range error guard (#5098) 2026-01-16 03:30:00 +00:00
tdgao 8536ca52ea feat: create project modal to use typescript 2026-01-15 20:10:29 -07:00
tdgao b5c69958ee fix: url text input wrapper before 2026-01-15 20:07:01 -07:00
4ee7623837 build: deploy on both environments (#5129)
* build: deploy on both environments

* build: missing whitespace

* build: add path filter

* build: add sentry env

* build: inherit secrets

* remove if check

* Revert "remove if check"

This reverts commit b2ffe1d611.

* remove if check 2

* Fix Wrangler env

* Fix Wrangler env but for real this time

* Alternative method of getting URLs

* Check for environment instead

* Fix comment

* Clickable commit

* Set PREVIEW build var

* Fix commit shown in comment

* Fix linting errors

* )

* add preview banner

* prepr

* prepr again

* ..

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-16 01:40:10 +00:00
ProspectorandGitHub f65479ee15 ignore robots.txt (#5130) 2026-01-15 17:15:24 -08:00
a903e46be9 feat: remove nuxt i18n for in house i18n for web (#5131)
* feat: remove nuxt i18n for in house

* cleanup: remove old nuxt/i18n patch

* prepr

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-15 23:49:38 +00:00
tdgao 6e4abf6e26 feat: add create server project in dropdown 2026-01-15 16:35:46 -07:00
Prospector 4497131206 changelog 2026-01-15 15:15:32 -08:00
Truman GaoandGitHub 4871abfb3a fix: worker exceeding resources bug caused by large changelogs (#5121)
* fetch changelog only where actually used

* use query parameter properly

* remove todos

* pnpm prepr
2026-01-15 22:58:06 +00:00
b0ed808745 Fix Discover URL filter parsing, improve search sidebar (#5104)
* fix category parsing on discover

* Make categories (loader, platform, etc) colored in discover, also add i18n

* fix formatting

* add localized strings

---------

Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-15 15:01:09 -08:00
ProspectorandGitHub 169224560b Include changelog query docs (#5128)
* Include changelog query docs

* example -> default
2026-01-15 14:50:15 -08:00
Prospector 106edc3a51 app 0.10.26 changelog 2026-01-15 14:43:26 -08:00
Truman GaoandGitHub ede405c650 fix: open path util freezing app (#5111)
* fix open path util crashing app

* use spawn blocking instead

* fmt
2026-01-15 20:43:52 +00:00
François-Xavier TalbotandGitHub 1dd1629884 Server transfer admin UI (#5116)
* Initial frontend

* doc for opus (TO REMOVE)

* Make better

* Clarified language

* Remove agent docs

* No scss

* Fmt

* Remove i18n

* Fmt

* Add transferred node tagging
2026-01-15 20:43:37 +00:00
Calum H.andGitHub 0070c9877b fix: re-enable async context (#5126) 2026-01-15 21:41:01 +01:00
Calum H.andGitHub eb208eed8b fix: try nodejs_compat_v2 (#5125) 2026-01-15 14:16:47 +01:00
aecsocketandGitHub c37bf75853 Implement replied/unreplied filter for tech review (#5006)
* Implement replied/unreplied filter for tech review

* project status filter

* wip: issue type filter

* correct filter field

* wip: break up tech review query

* Improve tech review query

* Get tech review working more properly

* Add get single project reports endpoint
2026-01-15 11:54:20 +00:00
Calum H.andGitHub 7838008396 feat: test fix 2 (#5123) 2026-01-15 02:44:26 +01:00
Calum H.andGitHub 454c708fd6 fix: error "27" (#5122)
* fix: error 27

* fix: sentry only in prod

* fix: sentry env

* Revert "fix: error 27"

This reverts commit 66ee482a05.

* feat: attempt to fix error 27
2026-01-15 01:38:23 +01:00
François-Xavier TalbotandGitHub 3ffa78aa07 Allow many Meilisearch write addrs (#5102)
* Write to many Meilisearch write addrs

* Keep client results ordered

* Attach Read Meilisearch client to actix data

* Load balanced meilisearch Compose profile

* Nginx config (round_robin)

* Fix nginx

* Meilisearch + nginx in same net

* Fix env vars example

* Fix env example again

* Fix env again

* Use try_collect with FuturesOrdered

* maybe fix remove_documents

* Clippy
2026-01-15 01:38:09 +01:00
Michael H. 7dba9cbe54 deploy: match sentry sample rate with wrangler observability 2026-01-14 19:00:08 +01:00
716c4e9a21 deploy: add sentry to frontend server (#5118)
* deploy: add sentry to frontend server

* build: add sentry auth token to env

* fix: use sentry CLI for sourcemap upload instead

* feat: comment deploy

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-01-14 17:46:55 +00:00
aecsocketandGitHub f85a2d3ec1 Make changelog in version response optional (#5115)
* Make changelog on version routes optional

* fix clippy

* fix ci
2026-01-14 10:55:20 +00:00
d055dc68dc Payout flows in backend - fix Tremendous forex cards (#5001)
* wip: payouts flow api

* working

* Finish up flow migration

* vibe-coded frontend changes

* fix typos and vue

* fix: types

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-01-14 10:53:35 +00:00
Emma AlexiaandGitHub 50a87ba933 Fix user deletion (again) (again) (notifications_deliveries) (#5112)
Doesn't seem to work fully with notification IDs, not sure why.
2026-01-13 22:25:00 +00:00
Truman GaoandGitHub 6030cb560c fix: auto close version modal after create (#5108)
* fix: auto closing version modal

* hide on next tick
2026-01-13 20:50:33 +00:00
Prospector c498230ebf changelog 2026-01-12 16:28:40 -08:00
4bbc5905e4 fix: dont remount components for project page every time route changes (#5105)
* fix: dont remount components for project page every time route changes

* remove ts from macro

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-13 00:13:21 +00:00
Truman GaoandGitHub 40f5db64d8 fix: versions v2 fixes (#5106)
* update dependencies step to show when cannot detect suggested dependencies

* rollback environment to previous copy

* implement disable close when uploading in modal

* pnpm prepr
2026-01-13 00:12:10 +00:00
Calum H.andGitHub 8d72a42be5 fix: checklist fixes (#5103)
* fix: page switching only when stage actually changes

* feat: preload improvements

* fix: dont skip own locks
2026-01-12 13:30:36 -08:00
61c8cd75cd feat: manage project versions v2 (#5049)
* update add files copy and go to next step on just one file

* rename and reorder stages

* add metadata stage and update details stage

* implement files inside metadata stage

* use regular prettier instead of prettier eslint

* remove changelog stage config

* save button on details stage

* update edit buttons in versions table

* add collapse environment selector

* implement dependencies list in metadata step

* move dependencies into provider

* add suggested dependencies to metadata stage

* pnpm prepr

* fix unused var

* Revert "add collapse environment selector"

This reverts commit f90fabc7a5.

* hide resource pack loader only when its the only loader

* fix no dependencies for modpack

* add breadcrumbs with hide breadcrumb option

* wider stages

* add proper horizonal scroll breadcrumbs

* fix titles

* handle save version in version page

* remove box shadow

* add notification provider to storybook

* add drop area for versions to drop file right into page

* fix mobile versions table buttons overflowing

* pnpm prepr

* fix drop file opening modal in wrong stage

* implement invalid file for dropping files

* allow horizontal scroll on breadcrumbs

* update infer.js as best as possible

* add create version button uploading version state

* add extractVersionFromFilename for resource pack and datapack

* allow jars for datapack project

* detect multiple loaders when possible

* iris means compatible with optifine too

* infer environment on loader change as well

* add tooltip

* prevent navigate forward when cannot go to next step

* larger breadcrumb click targets

* hide loaders and mc versions stage until files added

* fix max width in header

* fix add files from metadata step jumping steps

* define width in NewModal instead

* disable remove dependency in metadata stage

* switch metadata and details buttons positions

* fix remove button spacing

* do not allow duplicate suggested dependencies

* fix version detection for fabric minecraft version semvar

* better verion number detection based on filename

* show resource pack loader but uneditable

* remove vanilla shader detection

* refactor: break up large infer.js into ts and modules

* remove duplicated types

* add fill missing from file name step

* pnpm prepr

* fix neoforge loader parse failing and not adding neoforge loader

* add missing pack formats

* handle new pack format

* pnpm prepr

* add another regex where it is version in anywhere in filename

* only show resource pack or data pack options for filetype on datapack project

* add redundant zip folder check

* reject RP and DP if has redundant folder

* fix hide stage in breadcrumb

* add snapshot group key in case no release version. brings out 26.1 snapshots

* pnpm prepr

* open in group if has something selected

* fix resource pack loader uneditable if accidentally selected on different project type

* add new environment tags

* add unknown and not applicable environment tags

* pnpm prepr

* use shared constant on labels

* use ref for timeout

* remove console logs

* remove box shadow only for cm-content

* feat: xhr upload + fix wrangler prettierignore

* fix: upload content type fix

* fix dependencies version width

* fix already added dependencies logic

* add changelog minheight

* set progress percentage on button

* add legacy fabric detection logic

* lint

* small update on create version button label

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-12 19:41:14 +00:00
Calum H.andGitHub b46f6d0141 feat: moderation locking (#5070)
* feat: base locking impl

* feat: lock logic in place in rev endpoint + fetch rev

* feat: frontend impl and finalize

* feat: auto skip if using the moderation queue page

* fix: qa issues

* fix: async state + locking fix

* fix: lint

* fix: fmt

* fix: qa issue

* fix: qa + redirect bug

* fix: lint

* feat: delete all locks endpoint for admins

* fix: dedupe

* fix: fmt

* fix: project redirect move to middleware

* fix: lint
2026-01-12 17:08:30 +00:00
915d8c68bf Fix theme store race condition (#4885)
Co-authored-by: Calum H. <contact@cal.engineer>
2026-01-12 12:15:34 +00:00
ProspectorandGitHub 21045142cd Disallow all in robots.txt unless prod (#5078) 2026-01-12 11:54:21 +00:00
Modrinth BotandGitHub f171752109 New translations from Crowdin (main) (#5095) 2026-01-12 10:26:48 +00:00
Calum H.andGitHub 82f00f961e feat: switch to api-client to prevent rate limit errors on game-versions (#5089)
* feat: switch to api-client to prevent rate limit errors on game-versions

* feat: sentry temp

* Revert "feat: sentry temp"

This reverts commit aaa21a3f80.
2026-01-11 19:55:07 +00:00
Calum H.andGitHub b55b7fdc1c feat: enable async context + patch i18n to be more resilient (#5084)
* feat: enable async context

* feat: improve handling of $i18n defining (patch)
2026-01-10 17:43:21 +00:00
Michael H.andGitHub 0b60060f65 fix: vite dev server cf workers compatibility (#5080) 2026-01-10 14:11:00 +00:00
Calum H.andGitHub b0f1266a8b feat: normalize paths + add share for crash reports (#5071) 2026-01-09 17:02:42 +00:00
Prospector 863ff2e228 fix date 2026-01-08 14:27:58 -08:00
Prospector 579aa5967f app changelog 2026-01-08 14:26:56 -08:00
François-Xavier TalbotandGitHub 3bf5a6ebec Allow projects in tech review to still show up in moderation queue (#5068)
* Don't prevent projects from appearing in moderation queue if there are pending delphi reports

* Update query cache
2026-01-08 20:47:32 +01:00
François-Xavier TalbotandGitHub ff222aa168 PG/RedisPool configuration/o11y improvements (#5032)
* Don't retain Redis connections while doing database queries

* Optional REDIS_WAIT_TIMEOUT_MS

* Attach more data to CacheTimeout errrors

* Fix locks_released

* Fmt

* Set default REDIS_WAIT_TIMEOUT_MS to 15s

* Fix lint

* Close Redis connections idle for > 5 minutes

* Exponential backoff on cache spin lock
2026-01-08 20:47:13 +01:00
Michael H. ea17534f77 deploy(frontend): reduce sampling rate 2026-01-08 20:07:58 +01:00
Michael H. b91d581928 deploy(frontend): add production route 2026-01-08 19:55:52 +01:00
Michael H. 4f6cb7f26c deploy(frontend): don't wrap quotes around value 2026-01-08 18:37:49 +01:00
Michael H. c1da3e7e95 deploy(frontend): actions is stupid 2026-01-08 18:35:18 +01:00
Michael H. 040c568fdb deploy(frontend): debug variables 2026-01-08 18:31:54 +01:00
Michael H. 7a78565c97 deploy(frontend): merge variable injection & build step 2026-01-08 18:14:04 +01:00
62e56eb27e Worker migration (#5072)
* Worker migration

* Deploy on pnpm changes

* Specify package manager

* Manually bump Wrangler to 4.54

* Get rid of useless Wranglers worker

* I take it back

* Set account ID

* Fix preview alias

* feat: use workers api key

* feat: try fix

* fix: missing imports

* fix: again

* fix: only run push workflow on main or prod

* feat: remove store id?

* Populate secret store IDs

* Use correct key name

* Fix setting PREVIEW variable

* Inject variables from wrangler into shell

* Inject variables from wrangler into shell

* Add git- prefix to preview-alias

* No need to use environments now

* fix: remove test as it's covered by staging deploy

---------

Co-authored-by: Michael H. <michael@iptables.sh>
2026-01-08 16:25:45 +00:00
ProspectorandGitHub 8175120c4c Add fallback for checkbox aria-labels if description is not provided (#5066) 2026-01-08 15:47:32 +00:00
François-Xavier TalbotandGitHub 6221fe5e08 Fix build with updater feature (#5067) 2026-01-08 02:38:02 +00:00
François-Xavier TalbotandGitHub 4a8f882063 Fix underflow in QuickPlay compat check (#5065) 2026-01-08 02:14:05 +00:00
François-Xavier TalbotandGitHub 17db55a0bc Include OS in theseus User-Agent (#5046) 2026-01-08 02:11:18 +00:00
François-Xavier TalbotandGitHub a1d9268d00 Fix daedalus (#5064)
* Support default-user-jvm arguments type

* Use this branch's container

* Allow no rules in Ruled argument variant

* Run main
2026-01-08 01:43:47 +00:00
François-Xavier TalbotandGitHub 14d227a1a3 Revert "Use backup physical_id for progress updates matching" (#5060)
* Revert "Use backup physical_id for progress updates matching"

This reverts commit de2f6275b9.

* Fix page crash on backups page reload
2026-01-07 22:28:57 +00:00
François-Xavier TalbotandGitHub 3fd6ce1b6d Use fill v3 API for fetching paper build versions (#5063) 2026-01-07 22:27:46 +00:00
François-Xavier TalbotandGitHub 7eb1b38cc7 Support updated servers backup route schema, remove backup locking (#5053)
* Use backup physical_id for progress updates matching

* Remove locking

* Fmt
2026-01-06 01:03:46 +00:00
Prospector 2e9730ea1f changelog 2026-01-05 16:58:15 -08:00
a6cd4dfc0f feat: improve error handling for withdraw modal (#5054)
* feat: improve error handling for withdraw modal

* fix: add headers to error info

* prepr

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-06 00:46:34 +00:00
Modrinth BotandGitHub 0cf28c6392 New translations from Crowdin (main) (#5048) 2026-01-06 00:44:05 +00:00
Calum H.andGitHub 7c2327ce16 fix: broken analytics pages (#5052) 2026-01-06 00:42:13 +00:00
099011a177 feat: modrinth hosting - files tab refactor (#4912)
* feat: api-client module for content v0

* feat: delete unused components + modules + setting

* feat: xhr uploading

* feat: fs module -> api-client

* feat: migrate files.vue to use tanstack

* fix: mem leak + other issues

* fix: build

* feat: switch to monaco

* fix: go back to using ace, but improve preloading + theme

* fix: styling + dead attrs

* feat: match figma

* fix: padding

* feat: files-new for ui page structure

* feat: finalize files.vue

* fix: lint

* fix: qa

* fix: dep

* fix: lint

* fix: lockfile merge

* feat: icons on navtab

* fix: surface alternating on table

* fix: hover surface color

---------

Signed-off-by: Calum H. <contact@cal.engineer>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-06 00:35:51 +00:00
Calum H.andGitHub 61d4a34f0f devex: skip services + env + db steps in CI if not needed (#4965) 2026-01-06 00:23:22 +00:00
ProspectorandGitHub 5b890dcd8a This fixes it and i don't know why because it still redirects O_O (#5051) 2026-01-05 14:16:00 -08:00
Prospector c2bd88377b changelog 2026-01-05 12:27:14 -08:00
Truman GaoandGitHub efcc0d87b5 fix server upgrade button open modal (#5043) 2026-01-04 21:25:40 +00:00
ProspectorandGitHub f3033956cf Clean up licensing ambiguities (#4979) 2026-01-03 15:16:17 -08:00
ProspectorandGitHub e26291943c fix hydration error in moderation queue (#5038)
* fix hydration error in moderation queue

* disabled moderation button when no projects

* fix circular prop type issue

* Make moderation checklist clientonly
2026-01-03 12:49:32 -08:00
Truman GaoandGitHub 3fc18feacf fix: markdown editor scroll issues with max-height (#5031)
* add markdown editor stories to show scrolling bug

* add story

* update story content

* fix markdown editor scroll

* fix space

* lint
2026-01-03 03:33:20 +00:00
Truman GaoandGitHub 09a0b34df3 link with slug if exists (#5029) 2026-01-02 22:14:53 +00:00
Prospector 937be840c4 changelog 2026-01-01 17:20:58 -08:00
fef6df1321 fix: throw error on fail so it doesnt cache (#5023)
* fix: throw error on fail so it doesnt cache

* lint

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-02 00:39:13 +00:00
daf804947c devex: storybook for UI Package (#4984)
* add storybook

* clean up stories

* small fix

* add stories for all components

* add vintl

* default to dark mode

* fix  teleport

* add theme addon

* add new modal story

* delete broken stories

* move all stories to central stories folder

* fix paths

* add pnpm run storybook

* remove chromatic

* add add-stories.md

* fix types

* fix unncessary args field

* cover more addordion states

* pt2

* remove old vintl

* fix: missing style + ctx

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-01-02 00:32:58 +00:00
Truman GaoandGitHub 477d77cdc1 fix: balance displaying NaN (#5024)
* convert string to num

* another potentional string addition

* remove return statement

* fix formatting
2026-01-02 00:27:53 +00:00
Calum H.andGitHub 9bb012a439 fix: direct page visit breaking when labrinth goes down (#5022) 2026-01-01 21:21:39 +01:00
Calum H.andGitHub d1650bb3c4 fix: fouc (#5012)
* fix: fouc

* feat: lazy load locales

* switch test to use build
2026-01-01 14:08:05 +00:00
ProspectorandGitHub 2ce22c18bf Simplify default layout template by moving banners to components (#5010) 2026-01-01 02:28:10 +00:00
Truman GaoandGitHub b48443c65b fix: not checking file extension in loader detection (#5013) 2026-01-01 02:27:28 +00:00
b7e7e5e603 Change input mode for sign-in form (#5000)
* Change input mode and types and modes for sign-in form

-Added the inputmode of "email" to tell mobile browsers to change to the email keyboard for username/email input

-Added the inputmode of "numeric" to tell mobile browsers to change to the numeric keyboard for 2fa input (https://www.w3schools.com/TAgs/att_inputmode.asp)

-Changed two-factor code input type to "numeric" to provide a greater hint to autofill that this is where they should fill in 2fa codes

Signed-off-by: MIfoodie <94649676+MIfoodie@users.noreply.github.com>

* Clean up whitespace in sign-in.vue that I accidently added :)

Removed extra whitespace before the Google authentication link.

Signed-off-by: MIfoodie <94649676+MIfoodie@users.noreply.github.com>

* Change input type from 'number' to 'text'

Signed-off-by: MIfoodie <94649676+MIfoodie@users.noreply.github.com>

---------

Signed-off-by: MIfoodie <94649676+MIfoodie@users.noreply.github.com>
Co-authored-by: Calum H. <contact@cal.engineer>
2025-12-31 17:54:19 +00:00
Prospector fca5b7b544 unparsable 2025-12-31 10:27:07 -08:00
Prospector 3a40ee8713 changelog 2025-12-31 10:17:55 -08:00
Calum H.andGitHub 9e4317a262 fix: use ast not regex (#5007)
* fix: use ast not regex

* packages/ui incl
2025-12-31 17:48:27 +00:00
Truman GaoandGitHub 7fb6401613 fix: server ping spam (#4983)
* add a throttle on populate jump back in list

* Revert "add a throttle on populate jump back in list"

This reverts commit b3e7f51b34.

* only allow populate jump back in list to run 3x on linux

* add temp debug logs

* Revert "add temp debug logs"

This reverts commit 8c5ec42fa3.

* only allow 3x refresh limit for worlds list as well
2025-12-31 11:04:14 +00:00
Truman GaoandGitHub d332032e53 fix large projects list query with fetch segmented (#5004) 2025-12-31 11:03:40 +00:00
Calum H.andGitHub 560f21c0fe fix: various fixes (#4998)
* feat: check imports using ast

* fix: lint

* fix: loadericon

* fix: lint

* feat: remove usd warning

* fix: error.vue

* fix: lint
2025-12-30 21:47:11 +00:00
Calum H.andGitHub 2f99628d94 fix: downgrade to rolldown-vite 7.2.11 (#4999) 2025-12-30 20:53:36 +00:00
aecsocketandGitHub ad3edf541b Replace MaxMind with CloudFlare headers (#4934)
* Replace MaxMind with CloudFlare headers

* Remove MaxMind env vars

* Fix test harness
2025-12-30 16:49:49 +00:00
Calum H.andGitHub b07a1659b4 chore: update to nuxt 3.20 (#4992)
* feat: nuxt 3.14 → 3.15.4

* feat: nuxt 3.15.4 → 3.16.2 (vite 6)

* feat: bump nuxt-i18n

* feat: nuxt 3.20

* fix: lint

* feat: use rolldown-vite

* fix: shut the fuck up

* fix: silence for app as well

* fix: vue-router mismatch

---------

Signed-off-by: Calum H. <contact@cal.engineer>
2025-12-30 15:06:52 +00:00
Calum H.andGitHub 1a16d61511 fix: rev page broken (#4994)
* fix: i18n

* fix: lint
2025-12-30 00:40:56 +01:00
Prospector 366a0a6366 changelog 2025-12-29 14:33:57 -08:00
91b08e7380 Versions environments updates (#4949)
* add environment to version page metadata card

* remove environment migration warnings

* show settings/environments in nav only for staff

* use v2 versions route due to regressions

* add modpack incorrect loaders migration

* remove modpack migration step

* remove unused var

* run pnpm intl:extract

* componentize environment migration page

* rename environment selector

* rename environment selector pt2

* add migration modal to admonition

* hide environments in settings and show message

* show environment in project versions table

* pnpm fix

* pnpm fix on ui package

* intl:extract

* fix: .value

* lower case file

* add icon to environment tags and use i18n

* Update apps/frontend/src/pages/[type]/[id].vue

Co-authored-by: Calum H. <contact@cal.engineer>
Signed-off-by: Truman Gao <106889354+tdgao@users.noreply.github.com>

* open migration modal from warning icon in project dashboard

* fix settings side nav icon

* use useRoute composable

* pnpm fix

* intl:extract

* fix import

* fix import again

* run pnpm prepr

* fix designMessage import

* fix environment fetch

* fix environment fetch properly without key conflict

* fix environment refetching

* fix not using current versions in table to check different environments

* fix download tooltip

---------

Signed-off-by: Truman Gao <106889354+tdgao@users.noreply.github.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2025-12-29 21:58:17 +00:00
François-Xavier TalbotandGitHub 9924faab84 Fix tech rev rejection query (#4963) 2025-12-29 21:06:47 +00:00
Calum H.andGitHub 9f356beec3 feat: bank acct owner (#4993) 2025-12-29 20:44:18 +00:00
Calum H.andGitHub afe5f773e0 devex: i18n coverage (#4991)
* devex: i18n coverage

* feat: chalk usage

* feat: exclude legal
2025-12-29 20:41:40 +00:00
Calum H.andGitHub 3e246f12de fix: scopes i18n + authorization page temp warning (#4989) 2025-12-29 19:49:54 +00:00
Calum H.andGitHub 042451bad6 feat: i18n switcher in app-frontend (#4990)
* feat: app i18n stuff

* feat: locale switching on load

* feat: db migration

* feat: polish + fade indicator impl onto TabbedModal

* fix: prepr checks

* fix: remove staging lock for language switching

* fix: lint
2025-12-29 19:41:39 +00:00
30106d5f82 Provide more specific payout method names on frontend (#4977)
* Provide more specific payout method names on frontend

Been getting a lot of confused tickets recently of people withdrawing to PayPal but then not recognizing what "Tremendous" means. This should clarify things.

* feat: improve icons + names for withdrawals

* Update apps/frontend/src/components/ui/dashboard/RevenueTransaction.vue

Co-authored-by: Emma Alexia <emma@modrinth.com>
Signed-off-by: Calum H. <hendersoncal117@gmail.com>

* fix: icons

* fix: object cover

* feat: icons for crypto + bank

* fix: remove empty null

* fix: qa

---------

Signed-off-by: Calum H. <hendersoncal117@gmail.com>
Co-authored-by: Calum H. <contact@cal.engineer>
2025-12-29 13:08:33 +00:00
Modrinth BotandGitHub e0d159c010 New translations from Crowdin (main) (#4910) 2025-12-29 12:59:14 +00:00
ProspectorandGitHub 061c52c274 Updated DMCA agent info (#4981) 2025-12-28 00:17:55 +00:00
1bbb01bd42 devex: migrate to vue-i18n (#4966)
* sample languages refactor

* feat: consistency + dedupe impl of i18n

* fix: broken imports

* fix: intl formatted component

* fix: use relative imports

* fix: imports

* fix: comment out incomplete locales + fix imports

* feat: cleanup

* fix: ui imports

* fix: lint

* fix: admonition import

* make footer a component, fix language reactivity

* make copyright notice untranslatable

---------

Co-authored-by: Calum H. <contact@cal.engineer>
2025-12-27 21:37:37 +00:00
Calum H.andGitHub 3cabc3b967 fix: make icons + blog generators not break with eslint (presort) (#4980) 2025-12-27 20:50:08 +00:00
Calum H.andGitHub 7de4e55bad feat: fix report msgs not showing (#4974) 2025-12-27 00:24:08 +00:00
Calum H.andGitHub 1f21d66140 devex: add icon cmd (#4958)
* feat: icons add cmd

* fix: dep

* Update packages/assets/build/add-icons.ts

Signed-off-by: Calum H. <hendersoncal117@gmail.com>

* fix: lint

---------

Signed-off-by: Calum H. <hendersoncal117@gmail.com>
Signed-off-by: Calum H. <contact@cal.engineer>
2025-12-24 22:30:46 +00:00
Calum H.andGitHub 3adee66899 devex: prepr:web and app with proper caching (#4957)
* devex: prepr:web and app with proper caching

* fix: add tooling config to turbo global deps

* fix: exclude turbo + node modules for tooling-config

* feat: prepr:frontend

* fix: ci issue
2025-12-24 21:39:59 +00:00
Truman GaoandGitHub 67a6cd24cc devex: use tailwind preset for website, app, and ui package (#4964)
* use tailwind preset for website, app, and ui package

* fix preset import
2025-12-24 21:24:05 +00:00
Michael H. a952318c77 Revert "feat: downtime banner (#4955)"
This reverts commit 336832ec40.
2025-12-23 16:55:47 +01:00
Calum H.andGitHub 336832ec40 feat: downtime banner (#4955) 2025-12-23 16:40:42 +01:00
543bd5acf7 Coolbot/moderation updates for versions changes (#4942)
* update reports message to the correct support bubble color

* update checklist to direct to new settings pages and use v3 env info

* fix: project v2 + v3 in moderation checklist funcs

* Split environment stage if project uses mixed environments.

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2025-12-22 23:37:44 +00:00
Calum H.andGitHub 6a0bf5858e fix: panel breaking with advancedDebugInfo (#4952) 2025-12-22 22:45:13 +00:00
Prospector 11a75e7657 changelog 2025-12-22 14:15:25 -08:00
Calum H.andGitHub 88635d8da8 fix: auto-icon utility import (#4950) 2025-12-22 22:03:44 +00:00
Prospector 934936eba8 changelog 2025-12-22 12:48:17 -08:00
Truman GaoandGitHub 53ec2c5306 Handle project type on per version basis for multi-type projects (#4945)
* infer project type by draft version loader

* fix detecting modpack project type when editing

* fix no loaders check

* pnpm run fix
2025-12-21 22:13:41 +01:00
aecsocketandGitHub cace1a54cd Fix tech review query routes (#4946) 2025-12-21 09:23:21 +00:00
803c17de31 Fix modpack exports in the app being broken due to new file types (#4944)
* Fix modpack exports in the app being broken due to new file types

* pnpm fix to fix CI

---------

Co-authored-by: aecsocket <aecsocket@tutanota.com>
2025-12-21 08:49:53 +00:00
Calum H.andGitHub 537eadef0c fix: issues with files tab + tech rev cards (#4941) 2025-12-20 22:58:14 +01:00
39f2b0ecb6 Technical review queue (#4775)
* chore: fix typo in status message

* feat(labrinth): overhaul malware scanner report storage and routes

* chore: address some review comments

* feat: add Delphi to Docker Compose `with-delphi` profile

* chore: fix unused import Clippy lint

* feat(labrinth/delphi): use PAT token authorization with project read scopes

* chore: expose file IDs in version queries

* fix: accept null decompiled source payloads from Delphi

* tweak(labrinth): expose base62 file IDs more consistently for Delphi

* feat(labrinth/delphi): support new Delphi report severity field

* chore(labrinth): run `cargo sqlx prepare` to fix Docker build errors

* tweak: add route for fetching Delphi issue type schema, abstract Labrinth away from issue types

* chore: run `cargo sqlx prepare`

* chore: fix typo on frontend generated state file message

* feat: update to use new Delphi issue schema

* wip: tech review endpoints

* wip: add ToSchema for dependent types

* wip: report issues return

* wip

* wip: returning more data

* wip

* Fix up db query

* Delphi configuration to talk to Labrinth

* Get Delphi working with Labrinth

* Add Delphi dummy fixture

* Better Delphi logging

* Improve utoipa for tech review routes

* Add more sorting options for tech review queue

* Oops join

* New routes for fetching issues and reports

* Fix which kind of ID is returned in tech review endpoints

* Deduplicate tech review report rows

* Reduce info sent for projects

* Fetch more thread info

* Address PR comments

* fix ci

* fix postgres version mismatch

* fix version creation

* Implement routes

* fix up tech review

* Allow adding a moderation comment to Delphi rejections

* fix up rebase

* exclude rejected projects from tech review

* add status change msg to tech review thread

* cargo sqlx prepare

* also ignore withheld projects

* More filtering on issue search

* wip: report routes

* Fix up for build

* cargo sqlx prepare

* fix thread message privacy

* New tech review search route

* submit route

* details have statuses now

* add default to drid status

* dedup issue details

* fix sqlx query on empty files

* fixes

* Dedupe issue detail statuses and message on entering tech rev

* Fix qa issues

* Fix qa issues

* fix review comments

* typos

* fix ci

* feat: tech review frontend (#4781)

* chore: fix typo in status message

* feat(labrinth): overhaul malware scanner report storage and routes

* chore: address some review comments

* feat: add Delphi to Docker Compose `with-delphi` profile

* chore: fix unused import Clippy lint

* feat(labrinth/delphi): use PAT token authorization with project read scopes

* chore: expose file IDs in version queries

* fix: accept null decompiled source payloads from Delphi

* tweak(labrinth): expose base62 file IDs more consistently for Delphi

* feat(labrinth/delphi): support new Delphi report severity field

* chore(labrinth): run `cargo sqlx prepare` to fix Docker build errors

* tweak: add route for fetching Delphi issue type schema, abstract Labrinth away from issue types

* chore: run `cargo sqlx prepare`

* chore: fix typo on frontend generated state file message

* feat: update to use new Delphi issue schema

* wip: tech review endpoints

* wip: add ToSchema for dependent types

* wip: report issues return

* wip

* wip: returning more data

* wip

* Fix up db query

* Delphi configuration to talk to Labrinth

* Get Delphi working with Labrinth

* Add Delphi dummy fixture

* Better Delphi logging

* Improve utoipa for tech review routes

* Add more sorting options for tech review queue

* Oops join

* New routes for fetching issues and reports

* Fix which kind of ID is returned in tech review endpoints

* Deduplicate tech review report rows

* Reduce info sent for projects

* Fetch more thread info

* Address PR comments

* fix ci

* fix ci

* fix postgres version mismatch

* fix version creation

* Implement routes

* feat: batch scan alert

* feat: layout

* feat: introduce surface variables

* fix: theme selector

* feat: rough draft of tech review card

* feat: tab switcher

* feat: batch scan btn

* feat: api-client module for tech review

* draft: impl

* feat: auto icons

* fix: layout issues

* feat: fixes to code blocks + flag labels

* feat: temp remove mock data

* fix: search sort types

* fix: intl & lint

* chore: re-enable mock data

* fix: flag badges + auto open first issue in file tab

* feat: update for new routes

* fix: more qa issues

* feat: lazy load sources

* fix: re-enable auth middleware

* feat: impl threads

* fix: lint & severity

* feat: download btn + switch to using NavTabs with new local mode option

* feat: re-add toplevel btns

* feat: reports page consistency

* fix: consistency on project queue

* fix: icons + sizing

* fix: colors and gaps

* fix: impl endpoints

* feat: load all flags on file tab

* feat: thread generics changes

* feat: more qa

* feat: fix collapse

* fix: qa

* feat: msg modal

* fix: ISO import

* feat: qa fixes

* fix: empty state basic

* fix: collapsible region

* fix: collapse thread by default

* feat: rough draft of new process/flow

* fix labrinth build

* fix thread message privacy

* New tech review search route

* feat: qa fixes

* feat: QA changes

* fix: verdict on detail not whole issue

* fix: lint + intl

* fix: lint

* fix: thread message for tech rev verdict

* feat: use anim frames

* fix: exports + typecheck

* polish: qa changes

* feat: qa

* feat: qa polish

* feat: fix malic modal

* fix: lint

* fix: qa + lint

* fix: pagination

* fix: lint

* fix: qa

* intl extract

* fix ci

---------

Signed-off-by: Calum H. <contact@cal.engineer>
Co-authored-by: Alejandro González <me@alegon.dev>
Co-authored-by: aecsocket <aecsocket@tutanota.com>

---------

Signed-off-by: Calum H. <contact@cal.engineer>
Co-authored-by: Alejandro González <me@alegon.dev>
Co-authored-by: Calum H. <contact@cal.engineer>
2025-12-20 11:43:04 +00:00
Truman GaoandGitHub 1e9e13aebb Proper handling of modpack loaders (#4940)
* fix handling modpack loader

* fix order

* increase timeout

* fix search erroring on non alphanumeric input for searching project id
2025-12-19 23:24:40 +00:00
Prospector 67835b04a8 changelog 2025-12-19 13:40:32 -08:00
Truman GaoandGitHub 3f93041ca2 Improve editing project versions (#4933)
* add edit versions dropdown menu

* implement improved edit version with individual edit stages

* make changelog bigger

* update button styles

* remove hover button when hover on row

* bring editing versions back to project settings

* bring back gallery edit and upload in project page

* fix progress value

* fix admonition import

* fix v3 upload for modpacks

* fix modpack loader display for editing version and better open edit/create modal handling

* fix currentMember prop

* fix modpack loader displaying incorrectly

* fix max length

* fix version url after making an edit to version and fix delete

* small max height fix

* hide edit dependencies for modpack

* pnpm run fix

* fix import

* add tooltip

* update icons

* update copy and create version button style
2025-12-19 21:24:14 +00:00
Julian VennenandGitHub 0663b8adb0 Add missing file type enum values to openapi spec (#4936) 2025-12-19 21:11:47 +00:00
Truman GaoandGitHub 1f48f5b5af Fix project dependencies search (#4932)
* add search on all project types except mod packs

* add search by ID

* fix placeholder

* rename to dependency select
2025-12-19 20:27:17 +00:00
Truman GaoandGitHub 0268600044 Provide default when modpack doesn't specify loader (#4930)
* fix no modpack loader, default to minecraft loader

* use v2 create then modify with v3 for environment
2025-12-19 00:54:00 +01:00
François-Xavier TalbotandGitHub 8fb38ba0f2 Remove tag="type" on PaymentRequestMetadata (#4931)
This would conflict with the flattened kind: PaymentRequestMetadataKind
enum, which itself is internally tagged with "type", leading to two
"type" fields being serialized, confusing the deserializer.

Deserialization would fail, be silenced in the stripe webhook and lead
to the incorrect region being assigned to a server.
2025-12-19 00:52:43 +01:00
Prospector 85c65e697d changelog 2025-12-18 13:37:51 -08:00
Truman GaoandGitHub 563997e060 Project versions hot fixes (#4928)
* Fix everyone seeing managing gallery/version has moved alert

* fix loader picker disappear
2025-12-18 13:35:57 -08:00
Calum H.andGitHub 2d5568ecec polish: qa changes for non-usd cards (#4926)
* polish: qa changes for non-usd cards

* fix: always show worth

* fix: padding
2025-12-18 21:29:32 +00:00
Prospector a64c4201bb changelog 2025-12-18 12:41:08 -08:00
ProspectorandGitHub 51d5ed771c Add new versions blog post (#4925) 2025-12-18 12:39:18 -08:00
Prospector 539132a527 changelog 2025-12-18 12:24:35 -08:00
9958600121 feat: managing project versions (#4811)
* start modal, working show modal

* add stages and implement MultiModalStage component

* add project versions context and add file button

* implement add files stage

* export interfaces

* move MultiStageModal to /base

* small update to file input

* add version types to api-client

* wrap version namespace under v3

* implement add details stage fields and loaders component

* start create MC versions stage

* implement changelog stage and bring width into a per stage concern

* implement loader picker with grouping

* improve grouping and sorting for loader picker

* use chips component

* small updaets

* fix loader icon color

* componentize mc version picker

* initial version of shift click to select range

* use newModal for markdown editor

* start add dependencies stage with search

* implement showing mod options in search

* componentize modselect and add version/dependency relation select

* hide version and dependency relation when no project selected

* fix project facet search

* implement api-client versions requests

* fix search api request facet type to be string

* fix new modal outer container scroll

* implement add dependency stage

* fix parse error

* add placeholders

* fix types

* update dependency row styles

* small change

* fix the types on manage versions to be correct with labrinth request bodies

* fix create version file parts

* use draft version ref in flow and implement proper file handlling

* use draft version ref for mc versions select

* implement reactive modal state and conditionally disabled next buttons

* ensure all data is using draftVersion ref

* remove shift click to select range since it sucks

* fix up add dependencies stage state/types

* small fixes

* implement adding dependencies connected to api calls and make adding dependencies work

* add final create version button config

* start create version backend call and bring versions table to project settings

* set add files stage width

* remove version file upload in project page

* small fix

* fix create version api call

* implement error handling

* implement mc versions search

* implement showing all mc versions

* small fix

* implement prefill data

* add success notification

* add cancel button

* add new dropzone file input

* run pnpm run fix

* add tailwind preset in ui package

* polish file version row

* fix modal widths

* hide added versions when no versions added

* implement add loaders stage

* implement small chips and small fixes

* implement grouping for all releases

* implement new all releases grouping

* implement better shift click for version select

* small fixes

* fix search input style

* delete versions provider and start project type inferring

* implement getting project type

* add versions empty state, add folder up icon and pnpm run fix

* implement create version in project versions table

* update side nav

* implement dynamic create version flow depending on project type and detected data

* add id to stages and fix calling setStage not working

* move added loaded out of loader picker

* remove selected and detected MC versions

* add loading message to dependency search and fix dependency type always being "required"

* fix components in ref

* fix width on dropdown

* implement toggle all mc versions based on state of last in range

* fix mc version text colour

* do proper clean up

* update loaders to use tag item

* update UI to use TagItem and better match styles

* handle detected data when setting primary file

* add progress bar

* hide progress bar for non-progress stage

* add loading state on submit

* properly cache dependencies projects/versions

* pnpm run fix

* add dragover show purple border on dropzone file input

* better handle added dependencies

* move versions in side nav

* implement adding file type

* fix api body format for file type

* implement working edit existing version
- working add/remove file
- working edit version details

* a step towards proper versions refresh

* add gallery to project settings

* actually figured out refresh versions

* move checklist into settings page

* remove editing version from version page and add button to versions table in project settings

* remove edit and delete buttons from gallery in project page

* add empty state messages for project page

* add default scroll bar styles

* implement support for new file types

* remove edit from dropdown in project page versions table

* redirect to settings page

* move changelog to row with actions

* fix overflow on added dependencies

* fix redirect

* update scroll styles

* implement add environment stage (create and modify version not persisting environment to backend)

* small style fixes

* small spacing fix

* small style fixes

* add a flag for loading dependency projects

* address PR comments

* fix modrinth ui imports

* use magic keys instead of window.addeventlistener

* add spacing in bottom of settings page

* useDebounceFn from vue

* fix inconsistent stroke

* persist scroll through

* fix remove button

* fix api fields

* fix version file dropdown: hide primary option in edit mode and fix setting initial value

* fix links in nags

* implement skipped field for skipping steps instead of mutating stages array's elements

* implement suggested dependencies components

* implement suggested dependencies api call

* refactor cached get project and get version calls

* always hide environments

* update links

* set scroll in 10ms

* update links

* fix links pt2

* fix shadow

* fix progress bar

* dont include mc versions in suggested versions finder

* fix text overflow styles

* use tooltip

* fix change version name api

* implement set environment api call

* delete unused vue pages

* implement detected environment, edit environment step, and fix showing loaders in details for no loader projects

* small fix

* no loaders project wrong check

* fix not having 'minecraft' loader for resource pack

* implement updating existing files file type

* move add minecraft loader outside try catch

* add datapack to have environment

* fix being able to select duplicate MC versions

* remove datapack project from environment

* fix version fetch

* fix having detected environment not properly skipping step

* only add detected data when primary file changes

* fix unknown environemtn

* implement gallery and versions have moved admonition

* update project page for creator view

* small copy update

* merge fixes

* pnpm run fix

* fix checkmark squished

* fix version type can be deselected

* refactor: DI context + better typed MultistageModal

* fix type import

* Misc QA fixes

* fix allowed file types with no project type

* implement new add files stage

* fix versiosn header with new pagination

* hide buttons when no files for add file stage

* use prettier formatter

* allow signature file types

* add detecting primary file

* fix progress bar in firefox

* fix environment not correctly being hidden/shown

* remove environment missing nag

* temp bring back environment page

* remove delete version action from project page

* replace "continue" next button label with actual next step

* fix types

* pnpm run fix

* move supplementary files alert up and update border radius style on dropzone

* copy updates

* small update on version num placeholder

* update placeholder

* make timeout on upload routes 2 minutes

* fix lint issues

* run pnpm intl:extract

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2025-12-18 19:56:15 +00:00
aecsocketandGitHub 9ad01723a2 Fix optional file type upload validation (#4924) 2025-12-18 19:18:05 +00:00
Prospector 8448bacae7 Update changelog 2025-12-18 11:16:36 -08:00
Prospector c21e98a2a8 Update changelog 2025-12-18 11:15:06 -08:00
ProspectorandGitHub 5bbc3872f3 Revert "Use alt CDN URL when request header is passed (#4921)" (#4923)
This reverts commit 609e3896eb.
2025-12-18 18:40:27 +00:00
aecsocketandGitHub 8d894541e8 Add affiliate code revenue analytics (#4883)
* Add affiliate code revenue analytics

* clean up some error handling

* Add conversions to affiliate code analytics

* Only include affiliate subscriptions which have an associated successful charge

* wip: affiliate code clicks

* affiliate code click ingest route

* Add affiliate code clicks to analytics

* add new cols
2025-12-18 18:02:49 +00:00
dc16a65b62 Improve support for non-USD Tremendous gift cards (#4887)
* Improve support for non-USD Tremendous gift cards

* add forex info to tremendous payout methods

* fix: partially fix DEV-535

* feat: wip

* eur/usd to usd/eur

* feat: better denom picking

* feat: qa changes

* fix: intl

---------

Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2025-12-18 18:02:29 +00:00
Calum H.andGitHub 514c6f6e34 fix: muralpay iso mismatch (#4871)
* fix: deduplicate and use full code

* fix: subdivisions match muralpay
2025-12-18 02:08:47 +00:00
aecsocketandGitHub 609e3896eb Use alt CDN URL when request header is passed (#4921)
* Use alt CDN URL when request header is passed

* Modify version routes to use alt CDN
2025-12-17 18:12:29 +00:00
Prospector fd08dff1e7 Update changelog 2025-12-16 12:59:17 -08:00
Prospector 6425ab8c57 Add Java 25 setting 2025-12-16 12:47:05 -08:00
aecsocketandGitHub e123e51c66 Fix how processor arguments are generated in app (#4919) 2025-12-16 20:03:37 +00:00
ProspectorandGitHub 21fad12a21 Fix collection pages requiring auth (#4915) 2025-12-16 14:14:52 +00:00
Calum H.andGitHub 924a77eb3f fix: temporarily disable vintl for all langs apart from en-US (#4911)
* fix: temporarily disable vintl apart from en_us

* fix: lint
2025-12-15 19:04:19 +00:00
aecsocketandGitHub 7aaf99a0c8 Split logging utils into its own crate (#4852)
* Split logging utils into its own crate

* fix review comments

* remove anyhow from root

* make meilisearch less verbose
2025-12-12 02:09:57 +00:00
Prospector 91accd5578 Update app changelog + fix accordion issue 2025-12-11 16:19:51 -08:00
Prospector 147f19f11e lint 2025-12-11 16:09:20 -08:00
Prospector 73ff6df73c update changelog 2025-12-11 16:08:35 -08:00
ProspectorandGitHub 0de780b7c9 Make game versions update every 10 minutes via server-side route (#4892) 2025-12-11 16:05:31 -08:00
ProspectorandGitHub f49f889536 Fix news row width (#4894)
* fix news row width

* lint
2025-12-11 16:05:19 -08:00
ProspectorandGitHub b3f598aa1d Fix server content search (#4891)
* fix server content search

* wtf
2025-12-11 16:04:54 -08:00
Prospector cd1b5dcd3d update changelog 2025-12-11 16:00:12 -08:00
ProspectorandGitHub 79b7d269b0 Throttle search to not spam requests (#4893)
* Throttle search to not spam requests

* lint
2025-12-11 21:03:10 +00:00
ProspectorandGitHub 40ac726930 Exclude node_modules from tailwind pattern to improve build time (#4890) 2025-12-11 19:04:28 +00:00
aecsocketandGitHub ddcc14d99f Add details to Mural API errors (#4886) 2025-12-11 12:49:59 +00:00
Prospector 3dd2de5f18 changelog 2025-12-09 18:18:26 -08:00
ProspectorandGitHub 0a8f489234 NormalPage component w/ Collections refactor (#4873)
* Refactor search page, migrate to /discover/

* Add NormalPage component for common layouts, refactor Collections page as an example, misc ui pkg cleanup

* intl:extract

* lint

* lint

* remove old components

* Refactor search page, migrate to /discover/

* Add NormalPage component for common layouts, refactor Collections page as an example, misc ui pkg cleanup

* intl:extract

* lint

* lint

* remove old components
2025-12-09 22:44:10 +00:00
ProspectorandGitHub 1d64b2e22a Refactor search page, migrate to /discover/ (#4862) 2025-12-09 14:25:45 -08:00
Calum H.andGitHub 251e89fe5a fix: notice btns not matching colour of notice + gap issue (#4823)
* feat: improve notices

* fix: bottom gap for notices

* fix: lint

* fix: lint
2025-12-09 09:14:59 +00:00
Calum H.andGitHub 4fbbc2b1cf feat: use utc during balance bar calcs (#4875) 2025-12-09 08:44:04 +00:00
Calum H.andGitHub d5b7ac3542 fix: setting states not persisting (#4872)
Closes: 4867
2025-12-08 23:29:52 +00:00
ProspectorandGitHub fec395a4cf Revert "New translations from Crowdin (main) (#4815)" (#4878)
This reverts commit 16c0dadc4a.
2025-12-08 15:29:05 -08:00
Modrinth BotandGitHub 16c0dadc4a New translations from Crowdin (main) (#4815) 2025-12-08 21:53:44 +00:00
Calum H.andGitHub 779092c0b7 feat: user details modal for moderators (#4764)
* feat: user details modal for moderators

* fix: casing
2025-12-08 21:50:38 +00:00
aecsocketandGitHub 9aa06fbc26 Fix Mural payout status syncing (#4853)
* Fix Mural payout status syncing

* Make Mural payout code more resilient

* prepare sqlx

* fix test
2025-12-08 20:34:41 +00:00
Calum H.andGitHub cfd2977c21 feat: stable key for mods list (#4876) 2025-12-08 18:50:55 +00:00
Prospector 27fc0796a4 changelog 2025-12-08 10:24:47 -08:00
Calum H.andGitHub b1438bd460 fix: blocking await for jump back in (#4870)
* fix: loading state for jump back in

* fix: lint
2025-12-08 18:03:08 +00:00
Calum H.andGitHub 267e0cb636 fix: license url not being removed when saving (#4874)
Closes: #4848
2025-12-08 17:55:29 +00:00
coolbotandGitHub d471ef6763 Update support contact bubble color in utils.ts (#4868)
Signed-off-by: coolbot <76798835+coolbot100s@users.noreply.github.com>
2025-12-08 06:51:11 +00:00
cea5cfa4ab Add new optional file types (#4854)
* Add new optional file types

* Fix build

* Add signature file type

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2025-12-06 23:45:10 +00:00
Prospector 56356e8260 changelog 2025-12-05 11:56:19 -08:00
41e4086973 feat: qa improvements for backups page (#4857)
* feat: fix backup action disabling logic

* feat: allow actions when backup is being created

* feat: qa fixes

* feat: backups empty state

* fix: lint

* intl:extract

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2025-12-05 01:48:34 +00:00
Calum H.andGitHub 0f1f27d450 feat: dev-541 (#4858) 2025-12-05 01:34:05 +00:00
Calum H.andGitHub a558064f9d fix: add x-panel-version header (#4855) 2025-12-04 15:15:03 +01:00
Prospector c421249767 changelog 2025-12-03 18:32:43 -08:00
8eff939039 feat: ws client & new backups frontend (#4813)
* feat: ws client

* feat: v1 backups endpoints

* feat: migrate backups page to api-client and new DI ctx

* feat: switch to ws client via api-client

* fix: disgust

* fix: stats

* fix: console

* feat: v0 backups api

* feat: migrate backups.vue to page system w/ components to ui pkgs

* feat: polish backups frontend

* feat: pending refactor for ws handling of backups

* fix: vue shit

* fix: cancel logic fix

* fix: qa issues

* fix: alignment issues for backups page

* fix: bar positioning

* feat: finish QA

* fix: icons

* fix: lint & i18n

* fix: clear comment

* lint

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2025-12-03 18:32:03 -08:00
Prospector e3444a3456 changelog 2025-12-03 14:39:02 -08:00
ProspectorandGitHub 16a6f7b352 Modrinth Hosting rebrand (#4846)
* Modrinth Hosting rebranding

* fix capitalization issue

* fix issues
2025-12-03 22:15:36 +00:00
aecsocketandGitHub 79c2633011 Fix slug/project ID collisions (#4844)
* wip: tool to create project with id

* fix

* fix id/slug collision for orgs
2025-12-03 00:30:18 +00:00
aecsocketandGitHub 783aaa6553 Add revenue split to affiliate codes v2 (#4672)
* wip: affiliate payouts again

* Implement affiliate payout queue

* Deactivate subscription affiliations on cancellation

* Remove a test that never compiled in the first place

* Update sqlx cache

* address some PR comments

* more comments

* wip: handle refund charges

* cargo sqlx prepare

* Address PR comments

* cargo sqlx prepare
2025-12-02 00:01:24 +00:00
Prospector 60e0953616 stringify errors 2025-11-28 12:11:39 -08:00
Prospector f7c86f9fc9 update changelog 2025-11-28 11:39:32 -08:00
aecsocketandGitHub fe684ab903 Change auth servers reachable check URL (#4830) 2025-11-27 19:38:26 +00:00
Calum H.andGitHub 8592761493 fix: stale modpack permissions data on re-review (#4822) 2025-11-27 17:15:10 +00:00
aecsocketandGitHub dfe087df20 Enforce 2dp on payout withdrawals (#4829)
* fix mural withdraw amount

* Enforce 2dp on all payout logic
2025-11-27 10:03:34 +00:00
aecsocketandGitHub be3208c5a1 Fix Docker Compose to match staging/prod environments (#4828) 2025-11-26 23:54:03 +00:00
Calum H.andGitHub b56f39ce07 fix: edit server icon issues (#4821) 2025-11-26 23:29:29 +00:00
aecsocketandGitHub 0178fddc38 Install mod update dependencies automatically (#4800)
* Redownload version dependencies when updating a mod

* Fix update all button as well
2025-11-24 13:35:14 +00:00
aecsocketandGitHub 31417a2aa1 more logging on sync payouts task (#4814) 2025-11-23 21:48:15 +01:00
f333a75221 fix empty state for projects in "All" tab (#4801)
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2025-11-23 02:38:13 +00:00
aecsocketandGitHub bcf14a4c51 Fix downloading libraries for Forge 1.7.2 (#4808)
* wip: fix Forge 1.7.2 downloads

* Bump recursion limit
2025-11-21 22:45:34 +00:00
aecsocketandGitHub 130c2863ab Fix exposing Docker Compose ports to broadcast addr (#4805) 2025-11-21 11:13:11 +00:00
Prospector e59664426b changelog 2025-11-19 15:17:01 -08:00
aecsocketandGitHub 2f0ef07944 Add logging and change limit of Mural payouts task (#4798) 2025-11-19 12:38:30 +00:00
Truman GaoandGitHub 9af19d01e5 Fix modrinth+ firing ad requests on load (#4792) 2025-11-18 18:05:24 +00:00
François-Xavier TalbotandGitHub e837d9fa30 Add route to reprocess a refund charge's tax record (#4791) 2025-11-18 11:36:55 +00:00
1668 changed files with 150976 additions and 69121 deletions
@@ -1,6 +1,6 @@
name: 👥 Bug with Modrinth Servers
description: For issues with a Modrinth Servers product.
labels: [servers]
name: 👥 Bug with Modrinth Hosting
description: For issues with a Modrinth Hosting product.
labels: [hosting]
type: 'bug'
body:
- type: checkboxes
+1 -1
View File
@@ -19,7 +19,7 @@ body:
options:
- Modrinth App
- Modrinth.com website
- Modrinth Servers
- Modrinth Hosting
- Modrinth API for developers
- type: textarea
attributes:
@@ -2,7 +2,7 @@
applyTo: '**/*.vue'
---
You are given a Nuxt/Vue single-file component (.vue). Your task is to convert every hard-coded natural-language string in the <template> into our localization system using @vintl/vintl-nuxt (which wraps FormatJS).
You are given a Nuxt/Vue single-file component (.vue). Your task is to convert every hard-coded natural-language string in the <template> into our localization system using vue-i18n with utilities from `@modrinth/ui`.
Please follow these rules precisely:
@@ -13,40 +13,53 @@ Please follow these rules precisely:
2. Create message definitions
- In the <script setup> block, import `defineMessage` or `defineMessages` from `@vintl/vintl`.
- In the <script setup> block, import `defineMessage` or `defineMessages` from `@modrinth/ui`.
- For each extracted string, define a message with a unique `id` (use a descriptive prefix based on the component path, e.g. `auth.welcome.long-title`) and a `defaultMessage` equal to the original English string.
Example:
const messages = defineMessages({
welcomeTitle: { id: 'auth.welcome.title', defaultMessage: 'Welcome' },
welcomeDescription: { id: 'auth.welcome.description', defaultMessage: 'Youre now part of the community…' },
welcomeDescription: { id: 'auth.welcome.description', defaultMessage: 'You're now part of the community…' },
})
3. Handle variables and ICU formats
- Replace dynamic parts with ICU placeholders: "Hello, ${user.name}!" → `{name}` and defaultMessage: 'Hello, {name}!'
- For numbers/dates/times, use ICU/FormatJS options (e.g., currency): `{price, number, ::currency/USD}`
- For numbers/dates/times, use ICU options (e.g., currency): `{price, number, ::currency/USD}`
- For plurals/selects, use ICU: `'{count, plural, one {# message} other {# messages}}'`
4. Rich-text messages (links/markup)
- In `defaultMessage`, wrap link/markup ranges with tags, e.g.:
"By creating an account, you agree to our <terms-link>Terms</terms-link> and <privacy-link>Privacy Policy</privacy-link>."
- Render rich-text messages with `<IntlFormatted>` from `@vintl/vintl/components` and map tags via `values`:
<IntlFormatted
:message="messages.tosLabel"
:values="{
'terms-link': (chunks) => <NuxtLink to='/terms'>{chunks}</NuxtLink>,
'privacy-link': (chunks) => <NuxtLink to='/privacy'>{chunks}</NuxtLink>,
}"
/>
- For simple emphasis: `'Welcome to <strong>Modrinth</strong>!'` and map `'strong': (c) => <strong>{c}</strong>`
- Render rich-text messages with `<IntlFormatted>` from `@modrinth/ui` using named slots:
<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:
<template #strong="{ children }">
<strong><component :is="() => children" /></strong>
</template>
- For more complex child handling, use `normalizeChildren` from `@modrinth/ui`:
<template #bold="{ children }">
<strong><component :is="() => normalizeChildren(children)" /></strong>
</template>
5. Formatting in templates
- Import and use `useVIntl()`; prefer `formatMessage` for simple strings:
- Import and use `useVIntl()` from `@modrinth/ui`; prefer `formatMessage` for simple strings:
`const { formatMessage } = useVIntl()`
`<button>{{ formatMessage(messages.welcomeTitle) }}</button>`
- Vue methods like `$formatMessage`, `$formatNumber`, `$formatDate` are also available if needed.
- Pass variables as a second argument:
`{{ formatMessage(messages.greeting, { name: user.name }) }}`
6. Naming conventions and id stability
@@ -58,7 +71,8 @@ Please follow these rules precisely:
8. Update imports and remove literals
- Ensure imports for `defineMessage`/`defineMessages`, `useVIntl`, and `<IntlFormatted>` are present. Replace all hard-coded strings with `formatMessage(...)` or `<IntlFormatted>` and remove the literals.
- Ensure imports from `@modrinth/ui` are present: `defineMessage`/`defineMessages`, `useVIntl`, `IntlFormatted`, and optionally `normalizeChildren`.
- Replace all hard-coded strings with `formatMessage(...)` or `<IntlFormatted>` and remove the literals.
9. Preserve functionality
+3
View File
@@ -0,0 +1,3 @@
# Copying
Modrinth's Github workflows are licensed under the MIT License, which is provided in the file [LICENSE](./LICENSE).
+7
View File
@@ -0,0 +1,7 @@
Copyright 2025 Rinth, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+11 -9
View File
@@ -13,13 +13,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: crate-ci/typos@master
- uses: crate-ci/typos@v1.43.1
# broken: <https://github.com/SchemaStore/schemastore/issues/5108>
# tombi:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: tombi-toml/setup-tombi@v1
# - run: tombi lint
# - run: tombi fmt --check
# see <https://github.com/influxdata/datafusion-udf-wasm/pull/275>
tombi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: taiki-e/install-action@v2
with:
tool: tombi
- run: tombi lint
- run: tombi fmt --check
+143
View File
@@ -0,0 +1,143 @@
name: Deploy frontend
on:
push:
branches:
- main
- prod
paths:
- 'apps/frontend/**/*'
- 'packages/ui/**/*'
- 'packages/utils/**/*'
- 'packages/assets/**/*'
- '**/wrangler.jsonc'
- '**/pnpm-*.yaml'
- '.github/workflows/frontend-deploy.yml'
workflow_dispatch:
workflow_call:
inputs:
environment:
required: true
type: string
description: 'The environment to deploy to (staging-preview or production-preview)'
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure environment
id: meta
run: |
echo "cmd=deploy" >> $GITHUB_OUTPUT
ENV_INPUT="${{ inputs.environment }}"
REF="${{ github.ref }}"
SHA_SHORT="${GITHUB_SHA::8}"
if [ "$ENV_INPUT" = "staging-preview" ]; then
echo "env=staging" >> $GITHUB_OUTPUT
echo "url=https://git-$SHA_SHORT-frontend-staging.modrinth.workers.dev" >> $GITHUB_OUTPUT
echo "cmd=versions upload --preview-alias git-$SHA_SHORT --var PREVIEW:true" >> $GITHUB_OUTPUT
elif [ "$ENV_INPUT" = "production-preview" ]; then
echo "env=production" >> $GITHUB_OUTPUT
echo "url=https://git-$SHA_SHORT-frontend.modrinth.workers.dev" >> $GITHUB_OUTPUT
echo "cmd=versions upload --preview-alias git-$SHA_SHORT --var PREVIEW:true" >> $GITHUB_OUTPUT
elif [ "$REF" = "refs/heads/main" ]; then
echo "env=staging" >> $GITHUB_OUTPUT
echo "url=https://staging.modrinth.com" >> $GITHUB_OUTPUT
else
# Production env (no preview)
echo "env=production" >> $GITHUB_OUTPUT
echo "url=https://modrinth.com" >> $GITHUB_OUTPUT
fi
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: pnpm
- name: Inject build variables
working-directory: ./apps/frontend
run: |
if [ "${{ steps.meta.outputs.env }}" == "staging" ]; then
echo "Injecting staging variables from wrangler.jsonc..."
jq -r '.env.staging.vars | to_entries[] | "\(.key)=\(.value)"' wrangler.jsonc >> $GITHUB_ENV
else
echo "Injecting production variables from wrangler.jsonc..."
jq -r '.vars | to_entries[] | "\(.key)=\(.value)"' wrangler.jsonc >> $GITHUB_ENV
fi
- name: Install dependencies
working-directory: ./apps/frontend
run: pnpm install
- name: Build frontend
working-directory: ./apps/frontend
run: pnpm build
env:
CF_PAGES_BRANCH: ${{ github.ref_name }}
CF_PAGES_COMMIT_SHA: ${{ github.sha }}
CF_PAGES_URL: ${{ steps.meta.outputs.url }}
BUILD_ENV: ${{ steps.meta.outputs.env }}
PREVIEW: ${{ inputs.environment != '' && 'true' || 'false' }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Create Sentry release and upload sourcemaps
uses: getsentry/action-release@v3
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: modrinth
SENTRY_PROJECT: knossos-server
with:
environment: ${{ steps.meta.outputs.env }}
sourcemaps: ./apps/frontend/.output/server
url_prefix: '~/'
- name: Deploy Cloudflare Worker
id: wrangler
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
environment: ${{ steps.meta.outputs.env != 'production' && steps.meta.outputs.env || '' }}
workingDirectory: ./apps/frontend
packageManager: pnpm
wranglerVersion: '4.54.0'
command: ${{ steps.meta.outputs.cmd }}
- name: Purge cache
if: github.ref == 'refs/heads/prod'
run: |
curl -X POST \
-H "Authorization: Bearer ${{ secrets.CF_API_TOKEN }}" \
-H "Content-Type: application/json" \
--data '{"hosts": ["modrinth.com", "www.modrinth.com", "staging.modrinth.com"]}' \
https://api.cloudflare.com/client/v4/zones/e39df17b9c4ef44cbce2646346ee6d33/purge_cache
- name: Write deployment URL to file
if: ${{ inputs.environment != '' }}
run: |
echo "${{ steps.meta.outputs.url }}" > deployment-url-${{ inputs.environment }}.txt
- name: Upload deployment URL
if: ${{ inputs.environment != '' }}
uses: actions/upload-artifact@v6
with:
name: deployment-url-${{ inputs.environment }}
path: deployment-url-${{ inputs.environment }}.txt
-30
View File
@@ -1,30 +0,0 @@
name: Clear pages cache
on:
push:
branches:
- prod
jobs:
wait:
if: github.repository_owner == 'modrinth'
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: Cloudflare Pages deployment
uses: WalshyDev/cf-pages-await@v1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: '9ddae624c98677d68d93df6e524a6061'
project: 'frontend'
commitHash: ${{ steps.push-changes.outputs.commit-hash }}
- name: Purge cache
if: github.ref == 'refs/heads/prod'
run: |
curl -X POST \
-H "Authorization: Bearer ${{ secrets.CF_API_TOKEN }}" \
-H "Content-Type: application/json" \
--data '{"hosts": ["modrinth.com", "www.modrinth.com"]}' \
https://api.cloudflare.com/client/v4/zones/e39df17b9c4ef44cbce2646346ee6d33/purge_cache
+72
View File
@@ -0,0 +1,72 @@
name: Deploy frontend preview
on:
pull_request:
paths:
- 'apps/frontend/**/*'
- 'packages/ui/**/*'
- 'packages/utils/**/*'
- 'packages/assets/**/*'
- '**/wrangler.jsonc'
- '**/pnpm-*.yaml'
- '.github/workflows/frontend-preview.yml'
jobs:
deploy:
if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository
uses: ./.github/workflows/frontend-deploy.yml
secrets: inherit
strategy:
matrix:
environment: [staging-preview, production-preview]
with:
environment: ${{ matrix.environment }}
comment:
if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
needs: deploy
steps:
- name: Download deployment URLs
uses: actions/download-artifact@v7
with:
pattern: deployment-url-*
merge-multiple: true
- name: Read deployment URLs
id: urls
run: |
STAGING_PREVIEW_URL=$(cat deployment-url-staging-preview.txt)
PRODUCTION_PREVIEW_URL=$(cat deployment-url-production-preview.txt)
echo "Production preview URL: $PRODUCTION_PREVIEW_URL"
echo "Staging preview URL: $STAGING_PREVIEW_URL"
echo "staging-preview-url=$STAGING_PREVIEW_URL" >> $GITHUB_OUTPUT
echo "production-preview-url=$PRODUCTION_PREVIEW_URL" >> $GITHUB_OUTPUT
- name: Find comment
if: github.event_name == 'pull_request'
uses: peter-evans/find-comment@v3
id: fc
with:
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:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.fc.outputs.comment-id }}
body: |
## Frontend previews
Last deployed commit is [${{ github.sha }}](${{ github.event.pull_request.head.repo.html_url }}/commit/${{ github.sha }})
| Environment | URL |
|-------------|-----|
| staging | ${{ steps.urls.outputs.staging-preview-url }} |
| production | ${{ steps.urls.outputs.production-preview-url }} |
edit-mode: replace
+50 -19
View File
@@ -19,7 +19,15 @@ on:
sign-windows-binaries:
description: Sign Windows binaries
type: boolean
default: true
default: false
required: false
environment:
description: Environment
type: choice
options:
- prod
- staging
default: prod
required: false
jobs:
@@ -40,33 +48,48 @@ jobs:
runs-on: ${{ matrix.platform }}
steps:
- name: 📥 Check out code
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 🧰 Setup Rust toolchain
- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
rustflags: ''
target: ${{ startsWith(matrix.platform, 'macos') && 'x86_64-apple-darwin' || '' }}
- name: 🧰 Install pnpm
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: 🧰 Setup Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: pnpm
- name: 🧰 Install Linux build dependencies
- name: Generate tauri-dev.conf.json
shell: bash
run: |
GIT_HASH=$(git rev-parse --short HEAD)
cat > apps/app/tauri-dev.conf.json <<EOF
{
"productName": "Modrinth App (dev-${GIT_HASH})",
"mainBinaryName": "Modrinth App (dev-${GIT_HASH})",
"identifier": "ModrinthApp-dev-${GIT_HASH}",
"bundle": {
"fileAssociations": []
}
}
EOF
- name: Install Linux build dependencies
if: startsWith(matrix.platform, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -yq libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev
- name: 🧰 Setup Dasel
- name: Setup Dasel
uses: jaxxstorm/action-install-gh-release@v2.1.0
with:
repo: TomWright/dasel
@@ -75,24 +98,26 @@ jobs:
rename-to: ${{ startsWith(matrix.platform, 'windows') && 'dasel.exe' || 'dasel' }}
chmod: 0755
- name: ⚙️ Set application version and environment
- name: Set application version and environment
shell: bash
run: |
APP_VERSION="$(git describe --tags --always | sed -E 's/-([0-9]+)-(g[0-9a-fA-F]+)$/-canary+\1.\2/')"
BUILD_ENVIRONMENT="${{ inputs.environment || 'prod' }}"
echo "Setting application version to $APP_VERSION"
echo "Using environment $BUILD_ENVIRONMENT"
dasel put -f apps/app/Cargo.toml -t string -v "${APP_VERSION#v}" 'package.version'
dasel put -f packages/app-lib/Cargo.toml -t string -v "${APP_VERSION#v}" 'package.version'
dasel put -f apps/app-frontend/package.json -t string -v "${APP_VERSION#v}" 'version'
cp packages/app-lib/.env.prod packages/app-lib/.env
cp "packages/app-lib/.env.${BUILD_ENVIRONMENT}" packages/app-lib/.env
- name: 💨 Setup Turbo cache
- name: Setup Turbo cache
uses: rharkor/caching-for-turbo@v1.8
- name: 🧰 Install dependencies
- name: Install dependencies
run: pnpm install
- name: ✍️ Set up Windows code signing
- name: Set up Windows code signing
if: startsWith(matrix.platform, 'windows')
shell: bash
run: |
@@ -102,8 +127,8 @@ jobs:
dasel delete -f apps/app/tauri-release.conf.json 'bundle.windows.signCommand'
fi
- name: 🔨 Build macOS app
run: pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json
- name: Build macOS app
run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-dev.conf.json' }}
if: startsWith(matrix.platform, 'macos')
env:
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
@@ -116,19 +141,19 @@ jobs:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
- name: 🔨 Build Linux app
run: pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json
- name: Build Linux app
run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json' }}
if: startsWith(matrix.platform, 'ubuntu')
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
- name: 🔨 Build Windows app
- name: Build Windows app
run: |
[System.Convert]::FromBase64String("$env:DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_BASE64") | Set-Content -Path signer-client-cert.p12 -AsByteStream
$env:DIGICERT_ONE_SIGNER_CREDENTIALS = "$env:DIGICERT_ONE_SIGNER_API_KEY|$PWD\signer-client-cert.p12|$env:DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD"
$env:JAVA_HOME = "$env:JAVA_HOME_17_X64"
pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles 'nsis,updater'
${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles "nsis,updater"' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json --verbose --bundles "nsis,updater"' }}
Remove-Item -Path signer-client-cert.p12 -ErrorAction SilentlyContinue
if: startsWith(matrix.platform, 'windows')
env:
@@ -138,7 +163,7 @@ jobs:
DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_BASE64: ${{ secrets.DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_BASE64 }}
DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD: ${{ secrets.DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD }}
- name: 📤 Upload app bundles
- name: Upload app bundles
uses: actions/upload-artifact@v4
with:
name: App bundle (${{ matrix.artifact-target-name }})
@@ -146,7 +171,13 @@ jobs:
target/release/bundle/appimage/Modrinth App_*.AppImage*
target/release/bundle/deb/Modrinth App_*.deb*
target/release/bundle/rpm/Modrinth App-*.rpm*
target/release/bundle/appimage/Modrinth App (dev-*)_*.AppImage*
target/release/bundle/deb/Modrinth App (dev-*)_*.deb*
target/release/bundle/rpm/Modrinth App (dev-*)-*.rpm*
target/universal-apple-darwin/release/bundle/macos/Modrinth App.app.tar.gz*
target/universal-apple-darwin/release/bundle/macos/Modrinth App (dev-*)*.app.tar.gz
target/universal-apple-darwin/release/bundle/dmg/Modrinth App (dev-*)*.dmg
target/universal-apple-darwin/release/bundle/dmg/Modrinth App_*.dmg*
target/release/bundle/nsis/Modrinth App_*-setup.exe*
target/release/bundle/nsis/Modrinth App (dev-*)_*-setup.exe*
target/release/bundle/nsis/Modrinth App_*-setup.nsis.zip*
+19 -5
View File
@@ -70,23 +70,37 @@ jobs:
- name: 🧰 Install dependencies
run: pnpm install
- name: ⚙️ Set app environment
working-directory: packages/app-lib
run: cp .env.staging .env
# check if labrinth tests will actually run (cache miss)
- name: 🔍 Check if labrinth tests need to run
id: check-labrinth
run: |
LABRINTH_TEST_STATUS=$(pnpm turbo run test --filter=@modrinth/labrinth --dry-run=json | jq -r '.tasks[] | select(.task == "test") | .cache.status')
echo "Labrinth test cache status: $LABRINTH_TEST_STATUS"
if [ "$LABRINTH_TEST_STATUS" = "HIT" ]; then
echo "needs_services=false" >> $GITHUB_OUTPUT
else
echo "needs_services=true" >> $GITHUB_OUTPUT
fi
- name: ⚙️ Start services
if: steps.check-labrinth.outputs.needs_services == 'true'
run: docker compose up --wait
- name: ⚙️ Setup labrinth environment and database
if: steps.check-labrinth.outputs.needs_services == 'true'
working-directory: apps/labrinth
run: |
cp .env.local .env
sqlx database setup
- name: ⚙️ Set app environment
working-directory: packages/app-lib
run: cp .env.staging .env
- name: 🔍 Lint and test
run: pnpm run ci
- name: 🔍 Verify intl:extract has been run
run: |
pnpm intl:extract
pnpm turbo run intl:extract --force
git diff --exit-code --color */*/src/locales/en-US/index.json
+9
View File
@@ -65,6 +65,15 @@ app-playground-data/*
.astro
.claude
.letta
# labrinth demo fixtures
apps/labrinth/fixtures/demo
*storybook.log
storybook-static
.wrangler/
# frontend robots.txt
apps/frontend/src/public/robots.txt
+5
View File
@@ -12,6 +12,11 @@
<sourceFolder url="file://$MODULE_DIR$/packages/app-lib/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/packages/ariadne/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/packages/path-util/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/packages/modrinth-log/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/packages/modrinth-maxmind/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/packages/modrinth-maxmind/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/packages/modrinth-util/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/packages/muralpay/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
+1 -1
View File
@@ -13,7 +13,7 @@
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[vue]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
+3 -3
View File
@@ -16,13 +16,13 @@ Both have access to our dependency injection framework, examples as seen in `pac
### Website (apps/frontend)
Before a pull request can be opened for the website, `pnpm web:fix` and `pnpm web:intl:extract` must be run, otherwise CI will fail.
Before a pull request can be opened for the website, run `pnpm prepr:frontend:web` from the root folder, otherwise CI will fail.
To run a development version of the frontend, you must first copy over the relevant `.env` template file (prod, staging or local, usually prod) within the `apps/frontend` folder into `apps/frontend/.env`. Then you can run the frontend by running `pnpm web:dev` in the root folder.
### App Frontend (apps/app-frontend)
Before a pull request can be opened for the website, you must CD into the `app-frontend` folder; `pnpm fix` and `pnpm intl:extract` must be run, otherwise CI will fail.
Before a pull request can be opened for the app frontend, run `pnpm prepr:frontend:app` from the root folder, otherwise CI will fail.
To run a development version of the app frontend, you must first copy over the relevant `.env` template file (prod, staging or local, usually prod) within `packages/app-lib` into `packages/app-lib/.env`. Then you must run the app itself by running `pnpm app:dev` in the root folder.
@@ -56,7 +56,7 @@ Use `docker exec labrinth-clickhouse clickhouse-client` to access the Clickhouse
### Postgres
Use `docker exec labrinth-postgres psql -U postgres` to access the PostgreSQL instance.
Use `docker exec labrinth-postgres psql -U labrinth -d labrinth -c "SELECT 1"` to access the PostgreSQL instance, replacing the `SELECT 1` with your query.
# Guidelines
+5 -1
View File
@@ -8,10 +8,14 @@ For detailed information, consult each package's COPYING.md, LICENSE.txt, or LIC
The use of Modrinth branding elements, including but not limited to the wrench-in-labyrinth logo, the landing image, and any variations thereof, is strictly prohibited without explicit written permission from Rinth, Inc. This includes trademarks, logos, or other branding elements.
> All rights reserved. © 2020-2024 Rinth, Inc.
> All rights reserved. © 2020-2025 Rinth, Inc.
This includes, but may not be limited to, the following files:
- .idea/icon.svg
- .github/api_cover.png
- .github/app_cover.png
- .github/monorepo_cover.png
- .github/web_cover.png
If you fork this repository, you must remove all Modrinth branding assets from your fork.
Generated
+674 -36
View File
@@ -521,6 +521,22 @@ dependencies = [
"zbus",
]
[[package]]
name = "astral-tokio-tar"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec179a06c1769b1e42e1e2cbe74c7dcdb3d6383c838454d063eaac5bbb7ebbe5"
dependencies = [
"filetime",
"futures-core",
"libc",
"portable-atomic",
"rustc-hash",
"tokio",
"tokio-stream",
"xattr",
]
[[package]]
name = "async-broadcast"
version = "0.7.2"
@@ -624,6 +640,19 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "async-minecraft-ping"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "668b459c14dd8d9ef21e296af3f2a3651ff7dc3536e092fb0b09e528daaa6d89"
dependencies = [
"async-trait",
"serde",
"serde_json",
"thiserror 1.0.69",
"tokio",
]
[[package]]
name = "async-process"
version = "2.5.0"
@@ -671,6 +700,28 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "async-stream"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
dependencies = [
"async-stream-impl",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-stream-impl"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "async-stripe"
version = "0.41.0"
@@ -892,6 +943,49 @@ dependencies = [
"thiserror 2.0.17",
]
[[package]]
name = "axum"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
dependencies = [
"axum-core",
"bytes",
"futures-util",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"serde_core",
"sync_wrapper",
"tower",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum-core"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
dependencies = [
"bytes",
"futures-core",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"mime",
"pin-project-lite",
"sync_wrapper",
"tower-layer",
"tower-service",
]
[[package]]
name = "backtrace"
version = "0.3.76"
@@ -1066,6 +1160,83 @@ dependencies = [
"piper",
]
[[package]]
name = "bollard"
version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87a52479c9237eb04047ddb94788c41ca0d26eaff8b697ecfbb4c32f7fdc3b1b"
dependencies = [
"async-stream",
"base64 0.22.1",
"bitflags 2.9.4",
"bollard-buildkit-proto",
"bollard-stubs",
"bytes",
"chrono",
"futures-core",
"futures-util",
"hex",
"home",
"http 1.3.1",
"http-body-util",
"hyper 1.7.0",
"hyper-named-pipe",
"hyper-rustls 0.27.7",
"hyper-util",
"hyperlocal",
"log",
"num",
"pin-project-lite",
"rand 0.9.2",
"rustls 0.23.32",
"rustls-native-certs 0.8.1",
"rustls-pemfile 2.2.0",
"rustls-pki-types",
"serde",
"serde_derive",
"serde_json",
"serde_repr",
"serde_urlencoded",
"thiserror 2.0.17",
"tokio",
"tokio-stream",
"tokio-util",
"tonic 0.14.2",
"tower-service",
"url",
"winapi",
]
[[package]]
name = "bollard-buildkit-proto"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85a885520bf6249ab931a764ffdb87b0ceef48e6e7d807cfdb21b751e086e1ad"
dependencies = [
"prost 0.14.3",
"prost-types",
"tonic 0.14.2",
"tonic-prost",
"ureq",
]
[[package]]
name = "bollard-stubs"
version = "1.49.1-rc.28.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5731fe885755e92beff1950774068e0cae67ea6ec7587381536fca84f1779623"
dependencies = [
"base64 0.22.1",
"bollard-buildkit-proto",
"bytes",
"chrono",
"prost 0.14.3",
"serde",
"serde_json",
"serde_repr",
"serde_with",
]
[[package]]
name = "borsh"
version = "1.5.7"
@@ -2009,6 +2180,16 @@ dependencies = [
"darling_macro 0.21.3",
]
[[package]]
name = "darling"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
dependencies = [
"darling_core 0.23.0",
"darling_macro 0.23.0",
]
[[package]]
name = "darling_core"
version = "0.20.11"
@@ -2037,6 +2218,19 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "darling_core"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.106",
]
[[package]]
name = "darling_macro"
version = "0.20.11"
@@ -2059,6 +2253,17 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "darling_macro"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
dependencies = [
"darling_core 0.23.0",
"quote",
"syn 2.0.106",
]
[[package]]
name = "dashmap"
version = "6.1.0"
@@ -2089,30 +2294,28 @@ checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376"
[[package]]
name = "deadpool"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b"
source = "git+https://github.com/modrinth/deadpool?rev=db5fb00b036ecc8fe5f18853c559b745ffe47bde#db5fb00b036ecc8fe5f18853c559b745ffe47bde"
dependencies = [
"deadpool-runtime",
"lazy_static",
"num_cpus",
"tokio",
"tracing",
]
[[package]]
name = "deadpool-redis"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0965b977f1244bc3783bb27cd79cfcff335a8341da18f79232d00504b18eb1a"
version = "0.22.1"
source = "git+https://github.com/modrinth/deadpool?rev=db5fb00b036ecc8fe5f18853c559b745ffe47bde#db5fb00b036ecc8fe5f18853c559b745ffe47bde"
dependencies = [
"deadpool",
"redis",
"tracing",
]
[[package]]
name = "deadpool-runtime"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b"
version = "0.1.5"
source = "git+https://github.com/modrinth/deadpool?rev=db5fb00b036ecc8fe5f18853c559b745ffe47bde#db5fb00b036ecc8fe5f18853c559b745ffe47bde"
dependencies = [
"tokio",
]
@@ -2378,6 +2581,17 @@ dependencies = [
"const-random",
]
[[package]]
name = "docker_credential"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d89dfcba45b4afad7450a99b39e751590463e45c04728cf555d36bb66940de8"
dependencies = [
"base64 0.21.7",
"serde",
"serde_json",
]
[[package]]
name = "document-features"
version = "0.2.11"
@@ -2679,6 +2893,17 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "etcetera"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6"
dependencies = [
"cfg-if",
"home",
"windows-sys 0.59.0",
]
[[package]]
name = "event-listener"
version = "2.5.3"
@@ -3801,6 +4026,21 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-named-pipe"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278"
dependencies = [
"hex",
"hyper 1.7.0",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
"winapi",
]
[[package]]
name = "hyper-rustls"
version = "0.24.2"
@@ -3835,6 +4075,19 @@ dependencies = [
"webpki-roots 1.0.3",
]
[[package]]
name = "hyper-timeout"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
dependencies = [
"hyper 1.7.0",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]]
name = "hyper-tls"
version = "0.6.0"
@@ -3877,6 +4130,21 @@ dependencies = [
"windows-registry",
]
[[package]]
name = "hyperlocal"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7"
dependencies = [
"hex",
"http-body-util",
"hyper 1.7.0",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]]
name = "iana-time-zone"
version = "0.1.64"
@@ -4509,6 +4777,7 @@ dependencies = [
"arc-swap",
"argon2",
"ariadne",
"async-minecraft-ping",
"async-stripe",
"async-trait",
"base64 0.22.1",
@@ -4523,6 +4792,7 @@ dependencies = [
"const_format",
"dashmap",
"deadpool-redis",
"derive_more 2.0.1",
"dotenv-build",
"dotenvy",
"either",
@@ -4541,7 +4811,6 @@ dependencies = [
"labrinth",
"lettre",
"meilisearch-sdk",
"modrinth-maxmind",
"modrinth-util",
"muralpay",
"murmur2",
@@ -4559,7 +4828,6 @@ dependencies = [
"rustls 0.23.32",
"rusty-money",
"sentry",
"sentry-actix",
"serde",
"serde_json",
"serde_with",
@@ -4567,6 +4835,7 @@ dependencies = [
"sha2",
"spdx",
"sqlx",
"sqlx-tracing",
"strum",
"thiserror 2.0.17",
"tikv-jemalloc-ctl",
@@ -4590,6 +4859,16 @@ dependencies = [
"zxcvbn",
]
[[package]]
name = "labrinth-derive"
version = "0.0.0"
dependencies = [
"darling 0.23.0",
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "language-tags"
version = "0.3.2"
@@ -4889,6 +5168,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "matchit"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "maxminddb"
version = "0.26.0"
@@ -5056,6 +5341,18 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "modrinth-log"
version = "0.0.0"
dependencies = [
"dotenvy",
"eyre",
"sentry",
"tracing",
"tracing-ecs",
"tracing-subscriber",
]
[[package]]
name = "modrinth-maxmind"
version = "0.0.0"
@@ -5082,10 +5379,11 @@ dependencies = [
"derive_more 2.0.1",
"dotenvy",
"eyre",
"modrinth-log",
"rust_decimal",
"serde",
"tracing",
"tracing-ecs",
"tracing-subscriber",
"serde_json",
"utoipa",
]
[[package]]
@@ -5144,11 +5442,7 @@ dependencies = [
"arc-swap",
"bytes",
"chrono",
"clap",
"color-eyre",
"derive_more 2.0.1",
"dotenvy",
"eyre",
"reqwest",
"rust_decimal",
"rust_iso3166",
@@ -5157,8 +5451,6 @@ dependencies = [
"serde_json",
"serde_with",
"strum",
"tokio",
"tracing-subscriber",
"utoipa",
"uuid 1.18.1",
]
@@ -5867,6 +6159,124 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "opentelemetry"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf416e4cb72756655126f7dd7bb0af49c674f4c1b9903e80c009e0c37e552e6"
dependencies = [
"futures-core",
"futures-sink",
"js-sys",
"pin-project-lite",
"thiserror 2.0.17",
"tracing",
]
[[package]]
name = "opentelemetry-appender-tracing"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e68f63eca5fad47e570e00e893094fc17be959c80c79a7d6ec1abdd5ae6ffc16"
dependencies = [
"opentelemetry",
"tracing",
"tracing-core",
"tracing-log",
"tracing-opentelemetry",
"tracing-subscriber",
]
[[package]]
name = "opentelemetry-http"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f6639e842a97dbea8886e3439710ae463120091e2e064518ba8e716e6ac36d"
dependencies = [
"async-trait",
"bytes",
"http 1.3.1",
"opentelemetry",
"reqwest",
]
[[package]]
name = "opentelemetry-otlp"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b"
dependencies = [
"http 1.3.1",
"opentelemetry",
"opentelemetry-http",
"opentelemetry-proto",
"opentelemetry_sdk",
"prost 0.13.5",
"reqwest",
"thiserror 2.0.17",
"tokio",
"tonic 0.13.1",
"tracing",
]
[[package]]
name = "opentelemetry-proto"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e046fd7660710fe5a05e8748e70d9058dc15c94ba914e7c4faa7c728f0e8ddc"
dependencies = [
"opentelemetry",
"opentelemetry_sdk",
"prost 0.13.5",
"tonic 0.13.1",
]
[[package]]
name = "opentelemetry-semantic-conventions"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83d059a296a47436748557a353c5e6c5705b9470ef6c95cfc52c21a8814ddac2"
[[package]]
name = "opentelemetry-testing"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562407eb254fea88076c8a410a733a8ee2075fd9c7fbde3da2a03d29e2cef104"
dependencies = [
"anyhow",
"opentelemetry",
"opentelemetry-appender-tracing",
"opentelemetry-otlp",
"opentelemetry-semantic-conventions",
"opentelemetry_sdk",
"serde",
"serde_json",
"serial_test",
"tempfile",
"testcontainers",
"tokio",
"tracing-opentelemetry",
"tracing-subscriber",
]
[[package]]
name = "opentelemetry_sdk"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11f644aa9e5e31d11896e024305d7e3c98a88884d9f8919dbf37a9991bc47a4b"
dependencies = [
"futures-channel",
"futures-executor",
"futures-util",
"opentelemetry",
"percent-encoding",
"rand 0.9.2",
"serde_json",
"thiserror 2.0.17",
"tokio",
"tokio-stream",
]
[[package]]
name = "option-ext"
version = "0.2.0"
@@ -5991,6 +6401,31 @@ dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "parse-display"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a"
dependencies = [
"parse-display-derive",
"regex",
"regex-syntax",
]
[[package]]
name = "parse-display-derive"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281"
dependencies = [
"proc-macro2",
"quote",
"regex",
"regex-syntax",
"structmeta",
"syn 2.0.106",
]
[[package]]
name = "parse-size"
version = "1.1.0"
@@ -6378,7 +6813,7 @@ dependencies = [
"inferno",
"num",
"paste",
"prost",
"prost 0.13.5",
]
[[package]]
@@ -6584,7 +7019,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
dependencies = [
"bytes",
"prost-derive",
"prost-derive 0.13.5",
]
[[package]]
name = "prost"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
dependencies = [
"bytes",
"prost-derive 0.14.3",
]
[[package]]
@@ -6600,6 +7045,28 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "prost-derive"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
dependencies = [
"anyhow",
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "prost-types"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7"
dependencies = [
"prost 0.14.3",
]
[[package]]
name = "protobuf"
version = "3.7.2"
@@ -7627,6 +8094,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scc"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc"
dependencies = [
"sdd",
]
[[package]]
name = "schannel"
version = "0.1.28"
@@ -7718,6 +8194,12 @@ dependencies = [
"untrusted",
]
[[package]]
name = "sdd"
version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
[[package]]
name = "seahash"
version = "4.1.0"
@@ -7841,19 +8323,6 @@ dependencies = [
"ureq",
]
[[package]]
name = "sentry-actix"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc694e6ffc8d5d7fdb2a33923b0358f6ad41c0b428ced034b349b9e2b08260bc"
dependencies = [
"actix-http",
"actix-web",
"bytes",
"futures-util",
"sentry-core",
]
[[package]]
name = "sentry-backtrace"
version = "0.45.0"
@@ -8177,6 +8646,32 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "serial_test"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555"
dependencies = [
"futures-executor",
"futures-util",
"log",
"once_cell",
"parking_lot",
"scc",
"serial_test_derive",
]
[[package]]
name = "serial_test_derive"
version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "serialize-to-javascript"
version = "0.1.2"
@@ -8583,7 +9078,7 @@ dependencies = [
"chrono",
"crc",
"dotenvy",
"etcetera",
"etcetera 0.8.0",
"futures-channel",
"futures-core",
"futures-util",
@@ -8636,6 +9131,20 @@ dependencies = [
"uuid 1.18.1",
]
[[package]]
name = "sqlx-tracing"
version = "0.2.0"
dependencies = [
"derive_more 2.0.1",
"futures",
"opentelemetry",
"opentelemetry-testing",
"sqlx",
"testcontainers",
"tokio",
"tracing",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -9412,6 +9921,35 @@ dependencies = [
"winapi",
]
[[package]]
name = "testcontainers"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f3ac71069f20ecfa60c396316c283fbf35e6833a53dff551a31b5458da05edc"
dependencies = [
"astral-tokio-tar",
"async-trait",
"bollard",
"bytes",
"docker_credential",
"either",
"etcetera 0.10.0",
"futures",
"log",
"memchr",
"parse-display",
"pin-project-lite",
"serde",
"serde_json",
"serde_with",
"thiserror 2.0.17",
"tokio",
"tokio-stream",
"tokio-util",
"ulid",
"url",
]
[[package]]
name = "theseus"
version = "1.0.0-local"
@@ -9449,6 +9987,7 @@ dependencies = [
"notify",
"notify-debouncer-mini",
"p256",
"parking_lot",
"paste",
"path-util",
"phf 0.13.1",
@@ -9877,6 +10416,72 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
[[package]]
name = "tonic"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9"
dependencies = [
"async-trait",
"base64 0.22.1",
"bytes",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"hyper 1.7.0",
"hyper-timeout",
"hyper-util",
"percent-encoding",
"pin-project",
"prost 0.13.5",
"tokio",
"tokio-stream",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tonic"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203"
dependencies = [
"async-trait",
"axum",
"base64 0.22.1",
"bytes",
"h2 0.4.12",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"hyper 1.7.0",
"hyper-timeout",
"hyper-util",
"percent-encoding",
"pin-project",
"socket2 0.6.1",
"sync_wrapper",
"tokio",
"tokio-stream",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tonic-prost"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67"
dependencies = [
"bytes",
"prost 0.14.3",
"tonic 0.14.2",
]
[[package]]
name = "totp-rs"
version = "5.7.0"
@@ -9899,11 +10504,15 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [
"futures-core",
"futures-util",
"indexmap 2.11.4",
"pin-project-lite",
"slab",
"sync_wrapper",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
@@ -10019,6 +10628,24 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-opentelemetry"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddcf5959f39507d0d04d6413119c04f33b623f4f951ebcbdddddfad2d0623a9c"
dependencies = [
"js-sys",
"once_cell",
"opentelemetry",
"opentelemetry_sdk",
"smallvec",
"tracing",
"tracing-core",
"tracing-log",
"tracing-subscriber",
"web-time",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.20"
@@ -10114,6 +10741,16 @@ dependencies = [
"winapi",
]
[[package]]
name = "ulid"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe"
dependencies = [
"rand 0.9.2",
"web-time",
]
[[package]]
name = "uname"
version = "0.1.1"
@@ -10343,6 +10980,7 @@ dependencies = [
"quote",
"regex",
"syn 2.0.106",
"url",
"uuid 1.18.1",
]
+13 -4
View File
@@ -8,6 +8,8 @@ members = [
"packages/app-lib",
"packages/ariadne",
"packages/daedalus",
"packages/labrinth-derive",
"packages/modrinth-log",
"packages/modrinth-maxmind",
"packages/modrinth-util",
"packages/path-util",
@@ -31,6 +33,7 @@ arc-swap = "1.7.1"
argon2 = { version = "0.5.3", features = ["std"] }
ariadne = { path = "packages/ariadne" }
async-compression = { version = "0.4.32", default-features = false }
async-minecraft-ping = { version = "0.8.0" }
async-recursion = "1.1.1"
async-stripe = { version = "0.41.0", default-features = false, features = [
"runtime-tokio-hyper-rustls",
@@ -57,9 +60,10 @@ color-eyre = "0.6.5"
color-thief = "0.2.2"
const_format = "0.2.34"
daedalus = { path = "packages/daedalus" }
darling = { version = "0.23" }
dashmap = "6.1.0"
data-url = "0.3.2"
deadpool-redis = "0.22.0"
deadpool-redis = { git = "https://github.com/modrinth/deadpool", rev = "db5fb00b036ecc8fe5f18853c559b745ffe47bde", version = "0.22.1" }
derive_more = "2.0.1"
directories = "6.0.0"
dirs = "6.0.0"
@@ -107,7 +111,7 @@ lettre = { version = "0.11.19", default-features = false, features = [
] }
maxminddb = "0.26.0"
meilisearch-sdk = { version = "0.30.0", default-features = false }
modrinth-maxmind = { path = "packages/modrinth-maxmind" }
modrinth-log = { path = "packages/modrinth-log" }
modrinth-util = { path = "packages/modrinth-util" }
muralpay = { path = "packages/muralpay" }
murmur2 = "0.1.0"
@@ -115,13 +119,16 @@ native-dialog = "0.9.2"
notify = { version = "8.2.0", default-features = false }
notify-debouncer-mini = { version = "0.7.0", default-features = false }
p256 = "0.13.2"
parking_lot = "0.12.5"
paste = "1.0.15"
path-util = { path = "packages/path-util" }
phf = { version = "0.13.1", features = ["macros"] }
png = "0.18.0"
proc-macro2 = { version = "1.0" }
prometheus = "0.14.0"
quartz_nbt = "0.2.9"
quick-xml = "0.38.3"
quote = { version = "1.0" }
rand = "=0.8.5" # Locked on 0.8 until argon2 and p256 update to 0.9
rand_chacha = "=0.3.1" # Locked on 0.3 until we can update rand to 0.9
redis = "0.32.7"
@@ -149,7 +156,6 @@ sentry = { version = "0.45.0", default-features = false, features = [
"reqwest",
"rustls",
] }
sentry-actix = "0.45.0"
serde = "1.0.228"
serde_bytes = "0.11.19"
serde_cbor = "0.11.2"
@@ -163,7 +169,9 @@ sha2 = "0.10.9"
shlex = "1.3.0"
spdx = "0.12.0"
sqlx = { version = "0.8.6", default-features = false }
sqlx-tracing = { path = "packages/sqlx-tracing" }
strum = "0.27.2"
syn = { version = "2.0" }
sysinfo = { version = "0.37.2", default-features = false }
tar = "0.4.44"
tauri = "2.8.5"
@@ -238,7 +246,7 @@ manual_assert = "warn"
manual_instant_elapsed = "warn"
manual_is_variant_and = "warn"
manual_let_else = "warn"
map_unwrap_or = "warn"
map_unwrap_or = "allow"
match_bool = "warn"
needless_collect = "warn"
negative_feature_names = "warn"
@@ -268,4 +276,5 @@ codegen-units = 1 # Compile crates one after another so the compiler can optimi
# Specific profile for labrinth production builds
[profile.release-labrinth]
inherits = "release"
strip = false # Keep debug symbols for Sentry
panic = "unwind" # Don't exit the whole app on panic in production
+4
View File
@@ -17,3 +17,7 @@ extend-exclude = [
tou = "tou"
# Google Ad Manager
gam = "gam"
# short for "constants"
consts = "consts"
# short for "Copy"
Cpy = "Cpy"
+2 -6
View File
@@ -1,13 +1,9 @@
# Copying
The source code of the theseus repository is licensed under the GNU General Public License, Version 3 only, which is provided in the file [LICENSE](./LICENSE). However, some files listed below are licensed under a different license.
The source code of Modrinth App's frontend is licensed under the GNU General Public License, Version 3 only, which is provided in the file [LICENSE](./LICENSE). However, some files listed below are licensed under a different license.
## Modrinth logo
The use of Modrinth branding elements, including but not limited to the wrench-in-labyrinth logo, the landing image, and any variations thereof, is strictly prohibited without explicit written permission from Rinth, Inc. This includes trademarks, logos, or other branding elements.
> All rights reserved. © 2020-2023 Rinth, Inc.
This includes, but may not be limited to, the following files:
- theseus_gui/src-tauri/icons/\*
> All rights reserved. © 2020-2025 Rinth, Inc.
+7 -5
View File
@@ -28,18 +28,19 @@
"@tauri-apps/plugin-updater": "^2.7.1",
"@tauri-apps/plugin-window-state": "^2.2.2",
"@types/three": "^0.172.0",
"@vintl/vintl": "^4.4.1",
"intl-messageformat": "^10.7.7",
"vue-i18n": "^10.0.0",
"@vueuse/core": "^11.1.0",
"dayjs": "^1.11.10",
"floating-vue": "^5.2.2",
"ofetch": "^1.3.4",
"pinia": "^2.1.7",
"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-router": "4.3.0",
"vue-router": "^4.6.0",
"vue-virtual-scroller": "v2.0.0-beta.8"
},
"devDependencies": {
@@ -48,7 +49,7 @@
"@modrinth/tooling-config": "workspace:*",
"@nuxt/eslint-config": "^0.5.6",
"@taijased/vue-render-tracker": "^1.0.7",
"@vitejs/plugin-vue": "^5.0.4",
"@vitejs/plugin-vue": "^6.0.3",
"autoprefixer": "^10.4.19",
"eslint": "^9.9.1",
"eslint-plugin-turbo": "^2.5.4",
@@ -57,7 +58,8 @@
"sass": "^1.74.1",
"tailwindcss": "^3.4.4",
"typescript": "^5.5.4",
"vite": "^5.4.6",
"vite": "^6.0.0",
"vue-component-type-helpers": "^3.1.8",
"vue-tsc": "^2.1.6"
},
"packageManager": "pnpm@9.4.0",
+199 -93
View File
@@ -1,5 +1,5 @@
<script setup>
import { AuthFeature, TauriModrinthClient } from '@modrinth/api-client'
import { AuthFeature, PanelVersionFeature, TauriModrinthClient } from '@modrinth/api-client'
import {
ArrowBigUpDashIcon,
ChangeSkinIcon,
@@ -31,15 +31,21 @@ import {
Button,
ButtonStyled,
commonMessages,
defineMessages,
I18nDebugPanel,
NewsArticleCard,
NotificationPanel,
OverflowMenu,
PopupNotificationPanel,
ProgressSpinner,
provideModrinthClient,
provideNotificationManager,
providePageContext,
providePopupNotificationManager,
useDebugLogger,
useVIntl,
} from '@modrinth/ui'
import { renderString } from '@modrinth/utils'
import { formatBytes, renderString } from '@modrinth/utils'
import { useQuery } from '@tanstack/vue-query'
import { getVersion } from '@tauri-apps/api/app'
import { invoke } from '@tauri-apps/api/core'
@@ -47,7 +53,6 @@ import { getCurrentWindow } from '@tauri-apps/api/window'
import { openUrl } from '@tauri-apps/plugin-opener'
import { type } from '@tauri-apps/plugin-os'
import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { $fetch } from 'ofetch'
import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue'
import { RouterView, useRoute, useRouter } from 'vue-router'
@@ -58,22 +63,25 @@ 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 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 UpdateToast from '@/components/ui/UpdateToast.vue'
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
import { hide_ads_window, init_ads_window, show_ads_window } from '@/helpers/ads.js'
import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics'
import { debugAnalytics, initAnalytics, trackEvent } from '@/helpers/analytics'
import { check_reachable } from '@/helpers/auth.js'
import { get_user } from '@/helpers/cache.js'
import { command_listener, warning_listener } from '@/helpers/events.js'
@@ -90,18 +98,20 @@ import {
isDev,
isNetworkMetered,
} from '@/helpers/utils.js'
import i18n from '@/i18n.config'
import {
provideAppUpdateDownloadProgress,
subscribeToDownloadProgress,
} from '@/providers/download-progress.ts'
import { useError } from '@/store/error.js'
import { useInstall } from '@/store/install.js'
import { playServerProject, useInstall } from '@/store/install.js'
import { useLoading, 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'
import { AppPopupNotificationManager } from './providers/app-popup-notifications'
const themeStore = useTheming()
@@ -109,16 +119,24 @@ const notificationManager = new AppNotificationManager()
provideNotificationManager(notificationManager)
const { handleError, addNotification } = notificationManager
const popupNotificationManager = new AppPopupNotificationManager()
providePopupNotificationManager(popupNotificationManager)
const { addPopupNotification } = popupNotificationManager
const tauriApiClient = new TauriModrinthClient({
userAgent: `modrinth/theseus/${getVersion()} (support@modrinth.com)`,
features: [
new AuthFeature({
token: async () => (await getCreds()).session,
}),
new PanelVersionFeature(),
],
})
provideModrinthClient(tauriApiClient)
providePageContext({
hierarchicalSidebarAvailable: ref(true),
showAds: ref(false),
})
const news = ref([])
const availableSurvey = ref(false)
@@ -136,6 +154,7 @@ const showOnboarding = ref(false)
const nativeDecorations = ref(false)
const os = ref('')
const isDevEnvironment = ref(false)
const stateInitialized = ref(false)
@@ -214,10 +233,10 @@ const messages = defineMessages({
})
async function setupApp() {
stateInitialized.value = true
const {
native_decorations,
theme,
locale,
telemetry,
collapsed_navigation,
advanced_rendering,
@@ -229,12 +248,18 @@ async function setupApp() {
pending_update_toast_for_version,
} = await getSettings()
// Initialize locale from saved settings
if (locale) {
i18n.global.locale.value = locale
}
if (default_page === 'Library') {
await router.push('/library')
}
os.value = await getOS()
const dev = await isDev()
isDevEnvironment.value = dev
const version = await getVersion()
showOnboarding.value = !onboarded
@@ -247,6 +272,7 @@ async function setupApp() {
themeStore.toggleSidebar = toggle_sidebar
themeStore.devMode = developer_mode
themeStore.featureFlags = feature_flags
stateInitialized.value = true
isMaximized.value = await getCurrentWindow().isMaximized()
@@ -254,12 +280,11 @@ async function setupApp() {
isMaximized.value = await getCurrentWindow().isMaximized()
})
initAnalytics()
if (!telemetry) {
optOutAnalytics()
if (telemetry) {
initAnalytics()
if (dev) debugAnalytics()
trackEvent('Launched', { version, dev, onboarded })
}
if (dev) debugAnalytics()
trackEvent('Launched', { version, dev, onboarded })
if (!dev) document.addEventListener('contextmenu', (event) => event.preventDefault())
@@ -372,11 +397,15 @@ loading.setEnabled(false)
const error = useError()
const errorModal = ref()
const minecraftAuthErrorModal = ref()
const install = useInstall()
const modInstallModal = ref()
const addServerToInstanceModal = ref()
const installConfirmModal = ref()
const incompatibilityWarningModal = ref()
const installToPlayModal = ref()
const updateToPlayModal = ref()
const credentials = ref()
@@ -387,7 +416,7 @@ async function fetchCredentials() {
if (creds && creds.user_id) {
creds.user = await get_user(creds.user_id).catch(handleError)
}
credentials.value = creds
credentials.value = creds ?? null
}
async function signIn() {
@@ -434,28 +463,31 @@ const forceSidebar = computed(
() => route.path.startsWith('/browse') || route.path.startsWith('/project'),
)
const sidebarVisible = computed(() => sidebarToggled.value || forceSidebar.value)
const showAd = computed(() => !(!sidebarVisible.value || hasPlus.value))
watch(
showAd,
() => {
if (!showAd.value) {
hide_ads_window(true)
} else {
init_ads_window(true)
}
},
{ immediate: true },
const showAd = computed(
() => sidebarVisible.value && !hasPlus.value && credentials.value !== undefined,
)
watch(showAd, () => {
if (!showAd.value) {
hide_ads_window(true)
} else {
init_ads_window(true)
}
})
onMounted(() => {
invoke('show_window')
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)
})
const accounts = ref(null)
@@ -473,6 +505,9 @@ async function handleCommand(e) {
source: 'CreationModalFileDrop',
})
}
} else if (e.event === 'InstallServer') {
await router.push(`/project/${e.id}`)
await playServerProject(e.id).catch(handleError)
} else {
// Other commands are URL-based (deep linking)
urlModal.value.show(e)
@@ -491,24 +526,72 @@ const downloadPercent = computed(() => Math.trunc(appUpdateDownload.progress.val
const metered = ref(true)
const finishedDownloading = ref(false)
const restarting = ref(false)
const updateToastDismissed = ref(false)
const availableUpdate = ref(null)
const updateSize = ref(null)
const updatesEnabled = ref(true)
const updatePopupMessages = defineMessages({
updateAvailable: {
id: 'app.update-popup.title',
defaultMessage: 'Update available',
},
downloadComplete: {
id: 'app.update-popup.download-complete',
defaultMessage: 'Download complete',
},
body: {
id: 'app.update-popup.body',
defaultMessage:
'Modrinth App v{version} is ready to install! Reload to update now, or automatically when you close Modrinth App.',
},
meteredBody: {
id: 'app.update-popup.body.metered',
defaultMessage: `Modrinth App v{version} is available now! Since you're on a metered network, we didn't automatically download it.`,
},
downloadedBody: {
id: 'app.update-popup.body.download-complete',
defaultMessage: `Modrinth App v{version} has finished downloading. Reload to update now, or automatically when you close Modrinth App.`,
},
linuxBody: {
id: 'app.update-popup.body.linux',
defaultMessage:
'Modrinth App v{version} is available. Use your package manager to update for the latest features and fixes!',
},
reload: {
id: 'app.update-popup.reload',
defaultMessage: 'Reload',
},
download: {
id: 'app.update-popup.download',
defaultMessage: 'Download ({size})',
},
changelog: {
id: 'app.update-popup.changelog',
defaultMessage: 'Changelog',
},
})
async function checkUpdates() {
if (!(await areUpdatesEnabled())) {
console.log('Skipping update check as updates are disabled in this build or environment')
updatesEnabled.value = false
if (os.value === 'Linux' && !isDevEnvironment.value) {
checkLinuxUpdates()
setInterval(checkLinuxUpdates, 5 * 60 * 1000)
}
return
}
async function performCheck() {
const update = await invoke('plugin:updater|check')
const isExistingUpdate = update.version === availableUpdate.value?.version
if (!update) {
console.log('No update available')
return
}
const isExistingUpdate = update.version === availableUpdate.value?.version
if (isExistingUpdate) {
console.log('Update is already known')
return
@@ -516,7 +599,6 @@ async function checkUpdates() {
appUpdateDownload.progress.value = 0
finishedDownloading.value = false
updateToastDismissed.value = false
console.log(`Update ${update.version} is available.`)
@@ -526,6 +608,28 @@ async function checkUpdates() {
downloadUpdate(update)
} else {
console.log(`Metered connection detected, not auto-downloading update.`)
getUpdateSize(update.rid).then((size) => {
updateSize.value = size
addPopupNotification({
title: formatMessage(updatePopupMessages.updateAvailable),
text: formatMessage(updatePopupMessages.meteredBody, { version: update.version }),
type: 'info',
autoCloseMs: null,
buttons: [
{
label: formatMessage(updatePopupMessages.download, {
size: formatBytes(updateSize.value ?? 0),
}),
action: () => downloadAvailableUpdate(),
color: 'brand',
},
{
label: formatMessage(updatePopupMessages.changelog),
action: () => openUrl('https://modrinth.com/news/changelog?filter=app'),
},
],
})
})
}
getUpdateSize(update.rid).then((size) => (updateSize.value = size))
@@ -542,8 +646,26 @@ async function checkUpdates() {
)
}
async function showUpdateToast() {
updateToastDismissed.value = false
async function checkLinuxUpdates() {
try {
const [response, currentVersion] = await Promise.all([
fetch('https://launcher-files.modrinth.com/updates.json'),
getVersion(),
])
const updates = await response.json()
const latestVersion = updates?.version
if (latestVersion && latestVersion !== currentVersion) {
addPopupNotification({
title: formatMessage(updatePopupMessages.updateAvailable),
text: formatMessage(updatePopupMessages.linuxBody, { version: latestVersion }),
type: 'info',
autoCloseMs: null,
})
}
} catch (e) {
console.error('Failed to check for updates:', e)
}
}
async function downloadAvailableUpdate() {
@@ -569,6 +691,26 @@ async function downloadUpdate(versionToDownload) {
unlistenUpdateDownload = null
})
console.log('Finished downloading!')
addPopupNotification({
title: formatMessage(updatePopupMessages.downloadComplete),
text: formatMessage(updatePopupMessages.downloadedBody, {
version: versionToDownload.version,
}),
type: 'success',
autoCloseMs: null,
buttons: [
{
label: formatMessage(updatePopupMessages.reload),
action: () => installUpdate(),
color: 'brand',
},
{
label: formatMessage(updatePopupMessages.changelog),
action: () => openUrl('https://modrinth.com/news/changelog?filter=app'),
},
],
})
})
unlistenUpdateDownload = await subscribeToDownloadProgress(
appUpdateDownload,
@@ -742,24 +884,6 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
class="app-grid-layout experimental-styles-within relative"
:class="{ 'disable-advanced-rendering': !themeStore.advancedRendering }"
>
<Suspense>
<Transition name="toast">
<UpdateToast
v-if="
!!availableUpdate &&
!updateToastDismissed &&
!restarting &&
(finishedDownloading || metered)
"
:version="availableUpdate.version"
:size="updateSize"
:metered="metered"
@close="updateToastDismissed = true"
@restart="installUpdate"
@download="downloadAvailableUpdate"
/>
</Transition>
</Suspense>
<Transition name="fade">
<div
v-if="restarting"
@@ -796,7 +920,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
<NavButton
v-if="themeStore.featureFlags.servers_in_app"
v-tooltip.right="'Servers'"
to="/servers/manage"
to="/hosting/manage"
>
<ServerIcon />
</NavButton>
@@ -836,14 +960,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</NavButton>
<div class="flex flex-grow"></div>
<Transition name="nav-button-animated">
<div
v-if="
availableUpdate &&
updateToastDismissed &&
!restarting &&
(finishedDownloading || metered)
"
>
<div v-if="availableUpdate && !restarting && (finishedDownloading || metered)">
<NavButton
v-tooltip.right="
formatMessage(
@@ -857,13 +974,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
},
)
"
:to="
finishedDownloading
? installUpdate
: downloadProgress > 0 && downloadProgress < 1
? showUpdateToast
: downloadAvailableUpdate
"
:to="finishedDownloading ? installUpdate : downloadAvailableUpdate"
>
<ProgressSpinner
v-if="downloadProgress > 0 && downloadProgress < 1"
@@ -898,13 +1009,25 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
]"
placement="right-end"
>
<Avatar :src="credentials.user.avatar_url" alt="" size="32px" circle />
<Avatar
v-if="credentials.user?.avatar_url"
:src="credentials.user.avatar_url"
alt=""
size="32px"
circle
/>
<template #view-profile>
<UserIcon />
<span class="inline-flex items-center gap-1">
Signed in as
<span class="inline-flex items-center gap-1 text-contrast font-semibold">
<Avatar :src="credentials.user.avatar_url" alt="" size="20px" circle />
<Avatar
v-if="credentials.user?.avatar_url"
:src="credentials.user.avatar_url"
alt=""
size="20px"
circle
/>
{{ credentials.user.username }}
</span>
</span>
@@ -985,7 +1108,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
<transition name="popup-survey">
<div
v-if="availableSurvey"
class="w-[400px] z-20 fixed -bottom-12 pb-16 right-[--right-bar-width] mr-4 rounded-t-2xl card-shadow bg-bg-raised border-divider border-[1px] border-solid border-b-0 p-4"
class="w-[400px] z-20 fixed -bottom-12 pb-16 right-[--right-bar-width] mr-4 rounded-t-2xl card-shadow bg-bg-raised border-surface-5 border-[1px] border-solid border-b-0 p-4"
>
<h2 class="text-lg font-extrabold mt-0 mb-2">Hey there Modrinth user!</h2>
<p class="m-0 leading-tight">
@@ -1111,11 +1234,17 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</div>
</div>
<URLConfirmModal ref="urlModal" />
<I18nDebugPanel />
<NotificationPanel has-sidebar />
<PopupNotificationPanel has-sidebar />
<ErrorModal ref="errorModal" />
<MinecraftAuthErrorModal ref="minecraftAuthErrorModal" />
<ModInstallModal ref="modInstallModal" />
<AddServerToInstanceModal ref="addServerToInstanceModal" />
<IncompatibilityWarningModal ref="incompatibilityWarningModal" />
<InstallConfirmModal ref="installConfirmModal" />
<InstallToPlayModal ref="installToPlayModal" />
<UpdateToPlayModal ref="updateToPlayModal" />
</template>
<style lang="scss" scoped>
@@ -1344,38 +1473,15 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
transform: translateY(10rem) scale(0.8) scaleY(1.6);
}
.toast-enter-active {
transition: opacity 0.25s linear;
}
.toast-enter-from,
.toast-leave-to {
opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
.toast-enter-active,
.nav-button-animated-enter-active {
transition: all 0.5s cubic-bezier(0.15, 1.4, 0.64, 0.96);
}
.toast-leave-active,
.nav-button-animated-leave-active {
transition: all 0.25s ease;
}
.toast-enter-from {
scale: 0.5;
translate: 0 -10rem;
opacity: 0;
}
.toast-leave-to {
scale: 0.96;
translate: 20rem 0;
opacity: 0;
}
.nav-button-animated-enter-active {
position: relative;
}
@@ -1439,7 +1545,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
}
.info-card {
right: 8rem;
right: 22rem;
}
.profile-card {
@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:serif="http://www.serif.com/" version="1.1" viewBox="0 0 1793 199">
<g>
<g id="Layer_1">
<g id="green" fill="var(--color-brand)">
<path d="M1184.1,166.6c-8,0-15.6-1-22.9-3.1s-13.1-4.6-17.4-7.6l8.5-16.9c4.3,2.7,9.4,5,15.3,6.8,5.9,1.8,11.9,2.7,17.8,2.7s12.1-.9,15.2-2.8c3.1-1.9,4.7-4.5,4.7-7.7s-1.1-4.6-3.2-6c-2.1-1.4-4.9-2.4-8.4-3.1-3.4-.7-7.3-1.4-11.5-2-4.2-.6-8.4-1.4-12.6-2.4-4.2-1-8-2.5-11.5-4.5-3.4-2-6.2-4.6-8.4-7.9-2.1-3.3-3.2-7.7-3.2-13.2s1.7-11.3,5.2-15.8c3.4-4.5,8.3-7.9,14.5-10.3,6.2-2.4,13.6-3.7,22.2-3.7s12.9.7,19.4,2.1c6.5,1.4,11.9,3.4,16.2,6.1l-8.5,16.9c-4.5-2.7-9.1-4.6-13.6-5.6-4.6-1-9.1-1.5-13.6-1.5-6.8,0-11.8,1-15,3-3.3,2-4.9,4.6-4.9,7.7s1.1,5,3.2,6.4c2.1,1.4,4.9,2.6,8.4,3.4,3.4.8,7.3,1.5,11.5,2,4.2.5,8.4,1.3,12.6,2.4,4.2,1.1,8,2.5,11.5,4.4,3.5,1.8,6.3,4.4,8.5,7.7,2.1,3.3,3.2,7.7,3.2,13s-1.8,11.1-5.3,15.5c-3.5,4.4-8.5,7.8-14.9,10.2-6.4,2.4-14.1,3.7-23,3.7Z"/>
<path d="M1291.1,166.6c-10.6,0-19.8-2.1-27.7-6.3-7.9-4.2-14-10-18.3-17.4-4.3-7.4-6.5-15.7-6.5-25.1s2.1-17.9,6.3-25.2c4.2-7.3,10-13,17.5-17.2,7.4-4.2,15.9-6.2,25.4-6.2s17.5,2,24.8,6.1c7.2,4,12.9,9.7,17.1,17.1,4.2,7.4,6.2,16,6.2,26s0,2,0,3.2c0,1.2-.2,2.3-.3,3.4h-79.3v-14.8h67.5l-8.7,4.6c.1-5.5-1-10.3-3.4-14.4-2.4-4.2-5.6-7.4-9.7-9.8-4.1-2.4-8.8-3.6-14.2-3.6s-10.2,1.2-14.3,3.6c-4.1,2.4-7.3,5.7-9.6,9.9-2.3,4.2-3.5,9.2-3.5,14.9v3.6c0,5.7,1.3,10.7,3.9,15.1,2.6,4.4,6.3,7.8,11,10.2,4.7,2.4,10.2,3.6,16.4,3.6s10.2-.8,14.4-2.5c4.3-1.7,8.1-4.3,11.4-7.8l11.9,13.7c-4.3,5-9.6,8.8-16.1,11.5-6.5,2.7-13.9,4-22.2,4Z"/>
<path d="M1357.2,165.3v-95.1h21.2v26.2l-2.5-7.7c2.8-6.4,7.3-11.3,13.4-14.6,6.1-3.3,13.7-5,22.9-5v21.2c-1-.2-1.8-.4-2.7-.4-.8,0-1.7,0-2.5,0-8.4,0-15.1,2.5-20.1,7.4-5,4.9-7.5,12.3-7.5,22v46.1h-22.3Z"/>
<path d="M1460,165.3l-40.8-95.1h23.2l35.1,83.9h-11.4l36.3-83.9h21.4l-40.8,95.1h-23Z"/>
<path d="M1579.6,166.6c-10.6,0-19.8-2.1-27.7-6.3-7.9-4.2-14-10-18.3-17.4-4.3-7.4-6.5-15.7-6.5-25.1s2.1-17.9,6.3-25.2c4.2-7.3,10-13,17.5-17.2,7.4-4.2,15.9-6.2,25.4-6.2s17.5,2,24.8,6.1c7.2,4,12.9,9.7,17.1,17.1,4.2,7.4,6.2,16,6.2,26s0,2,0,3.2c0,1.2-.2,2.3-.3,3.4h-79.3v-14.8h67.5l-8.7,4.6c.1-5.5-1-10.3-3.4-14.4-2.4-4.2-5.6-7.4-9.7-9.8-4.1-2.4-8.8-3.6-14.2-3.6s-10.2,1.2-14.3,3.6c-4.1,2.4-7.3,5.7-9.6,9.9-2.3,4.2-3.5,9.2-3.5,14.9v3.6c0,5.7,1.3,10.7,3.9,15.1,2.6,4.4,6.3,7.8,11,10.2,4.7,2.4,10.2,3.6,16.4,3.6s10.2-.8,14.4-2.5c4.3-1.7,8.1-4.3,11.4-7.8l11.9,13.7c-4.3,5-9.6,8.8-16.1,11.5-6.5,2.7-13.9,4-22.2,4Z"/>
<path d="M1645.7,165.3v-95.1h21.2v26.2l-2.5-7.7c2.8-6.4,7.3-11.3,13.4-14.6,6.1-3.3,13.7-5,22.9-5v21.2c-1-.2-1.8-.4-2.7-.4-.8,0-1.7,0-2.5,0-8.4,0-15.1,2.5-20.1,7.4-5,4.9-7.5,12.3-7.5,22v46.1h-22.3Z"/>
<path d="M1749.9,166.6c-8,0-15.6-1-22.9-3.1s-13.1-4.6-17.4-7.6l8.5-16.9c4.3,2.7,9.4,5,15.3,6.8,5.9,1.8,11.9,2.7,17.8,2.7s12.1-.9,15.2-2.8c3.1-1.9,4.7-4.5,4.7-7.7s-1.1-4.6-3.2-6c-2.1-1.4-4.9-2.4-8.4-3.1-3.4-.7-7.3-1.4-11.5-2-4.2-.6-8.4-1.4-12.6-2.4-4.2-1-8-2.5-11.5-4.5-3.4-2-6.2-4.6-8.4-7.9-2.1-3.3-3.2-7.7-3.2-13.2s1.7-11.3,5.2-15.8c3.4-4.5,8.3-7.9,14.5-10.3,6.2-2.4,13.6-3.7,22.2-3.7s12.9.7,19.4,2.1c6.5,1.4,11.9,3.4,16.2,6.1l-8.5,16.9c-4.5-2.7-9.1-4.6-13.6-5.6-4.6-1-9.1-1.5-13.6-1.5-6.8,0-11.8,1-15,3-3.3,2-4.9,4.6-4.9,7.7s1.1,5,3.2,6.4c2.1,1.4,4.9,2.6,8.4,3.4,3.4.8,7.3,1.5,11.5,2,4.2.5,8.4,1.3,12.6,2.4,4.2,1.1,8,2.5,11.5,4.4,3.5,1.8,6.3,4.4,8.5,7.7,2.1,3.3,3.2,7.7,3.2,13s-1.8,11.1-5.3,15.5c-3.5,4.4-8.5,7.8-14.9,10.2-6.4,2.4-14.1,3.7-23,3.7Z"/>
<g>
<path d="M9.8,143l63.4-38.1-5.8-15.3,18.1-18.6,22.9-4.9,6.6,8.2-10.6,10.7-9.2,2.9-6.6,6.8,3.2,9,6.5,6.9,9.2-2.5,6.6-7.2,14.3-4.5,4.3,9.6-14.8,18.1-24.8,7.8-11.1-12.4-63.6,38.2c-3-3.9-6.5-9.4-8.8-14.7ZM192.8,65.4l-50.4,13.6c2.8,7.4,3.7,11.7,4.5,16.5l50.3-13.6c-.8-5.4-2.2-10.8-4.4-16.5Z" fill-rule="evenodd"/>
<path d="M17.3,106.5c3.6,42.1,38.9,75.2,82,75.2s60.7-18.9,74-46.3l16.4,5.7c-15.8,34.1-50.3,57.9-90.4,57.9S3.6,158.2,0,106.5h17.3ZM.3,89.4C5.3,39.2,47.8,0,99.3,0s99.5,44.6,99.5,99.5-1.1,17.4-3.3,25.5l-16.3-5.7c1.6-6.5,2.4-13.1,2.4-19.8,0-45.4-36.9-82.3-82.3-82.3S22.6,48.7,17.6,89.4H.3Z" fill-rule="evenodd"/>
<path d="M99,51.6c-26.4,0-47.9,21.5-47.9,48s21.5,48,48,48,2.7,0,4-.2l4.8,16.8c-2.9.4-5.8.6-8.8.6-36,0-65.2-29.2-65.2-65.2S63.1,34.4,99,34.4s1.8,0,2.7,0l-2.7,17.1ZM118.6,37.4c26.4,8.3,45.6,33,45.6,62.2s-16.4,50.2-39.8,60l-4.8-16.7c16.2-7.7,27.4-24.2,27.4-43.3s-13-38.1-31.1-44.9l2.7-17.2Z" fill-rule="evenodd"/>
</g>
</g>
<g id="black" fill="currentColor">
<path d="M354.8,69.2c12,0,21.7,3.4,28.6,10.4,7,7.2,10.6,17.5,10.6,31.5v54.8h-22.4v-51.9c0-8.4-1.8-14.7-5.5-19-3.8-4.1-8.9-6.3-15.9-6.3s-13.6,2.5-18.1,7.3c-4.5,5-6.8,12.2-6.8,21.3v48.5h-22.4v-51.9c0-8.4-1.8-14.7-5.5-19-3.8-4.1-8.9-6.3-15.9-6.3s-13.6,2.5-18.1,7.3c-4.5,4.8-6.8,12-6.8,21.3v48.5h-22.4v-95.6h21.3v12.2c3.6-4.3,8.1-7.5,13.4-9.8,5.4-2.3,11.3-3.4,17.9-3.4s13.6,1.3,19.2,3.9c5.5,2.9,9.8,6.8,13.1,12,3.9-5,8.9-8.9,15.2-11.8,6.3-2.7,13.1-4.1,20.6-4.1ZM466,167.2c-9.7,0-18.4-2.1-26.1-6.3-7.6-4-13.8-10.1-18.1-17.5-4.5-7.3-6.6-15.7-6.6-25.2s2.1-17.9,6.6-25.2c4.3-7.4,10.6-13.4,18.1-17.4,7.7-4.1,16.5-6.3,26.1-6.3s18.6,2.1,26.3,6.3c7.7,4.1,13.8,10,18.3,17.4,4.3,7.3,6.4,15.7,6.4,25.2s-2.1,17.9-6.4,25.2c-4.5,7.5-10.6,13.4-18.3,17.5-7.7,4.1-16.5,6.3-26.3,6.3h0ZM466,148c8.2,0,15-2.7,20.4-8.2,5.4-5.5,8.1-12.7,8.1-21.7s-2.7-16.1-8.1-21.7c-5.4-5.5-12.2-8.2-20.4-8.2s-15,2.7-20.2,8.2c-5.4,5.5-8.1,12.7-8.1,21.7s2.7,16.1,8.1,21.7c5.2,5.5,12,8.2,20.2,8.2ZM631.5,33.1v132.8h-21.5v-12.3c-3.7,4.4-8.3,7.9-13.6,10.2-5.5,2.3-11.5,3.4-18.1,3.4s-17.4-2-24.7-6.1c-7.3-4.1-13.2-9.8-17.4-17.4-4.1-7.3-6.3-15.9-6.3-25.6s2.1-18.3,6.3-25.6c4.1-7.3,10-13.1,17.4-17.2,7.3-4.1,15.6-6.1,24.7-6.1s12.2,1.1,17.4,3.2c5.2,2.1,9.8,5.4,13.4,9.7v-49h22.4ZM581.1,148c5.4,0,10.2-1.3,14.5-3.8,4.3-2.3,7.7-5.9,10.2-10.4,2.5-4.5,3.8-9.8,3.8-15.7s-1.3-11.3-3.8-15.7c-2.5-4.5-5.9-8.1-10.2-10.6-4.3-2.3-9.1-3.6-14.5-3.6s-10.2,1.3-14.5,3.6c-4.3,2.5-7.7,6.1-10.2,10.6-2.5,4.5-3.8,9.8-3.8,15.7s1.3,11.3,3.8,15.7c2.5,4.5,5.9,8.1,10.2,10.4,4.3,2.5,9.1,3.8,14.5,3.8ZM681.6,84.3c6.4-10,17.7-15,34-15v21.3c-1.7-.3-3.4-.5-5.2-.5-8.8,0-15.6,2.5-20.4,7.5-4.8,5.2-7.3,12.5-7.3,22v46.4h-22.4v-95.6h21.3v14h0ZM734.1,70.3h22.4v95.6h-22.4v-95.6ZM745.4,54.6c-4.1,0-7.5-1.3-10.2-3.9-2.7-2.4-4.2-5.9-4.1-9.5,0-3.8,1.4-7,4.1-9.7,2.7-2.5,6.1-3.8,10.2-3.8s7.5,1.3,10.2,3.6c2.7,2.5,4.1,5.5,4.1,9.3s-1.3,7.2-3.9,9.8c-2.7,2.7-6.3,4.1-10.4,4.1ZM839.5,69.2c12,0,21.7,3.6,29,10.6,7.3,7,10.9,17.5,10.9,31.3v54.8h-22.4v-51.9c0-8.4-2-14.7-5.9-19-3.9-4.1-9.5-6.3-16.8-6.3s-14.7,2.5-19.5,7.3c-4.8,5-7.2,12.2-7.2,21.5v48.3h-22.4v-95.6h21.3v12.3c3.8-4.5,8.4-7.7,14-10,5.5-2.3,12-3.4,19-3.4ZM964.8,160.7c-2.8,2.2-6,3.9-9.5,4.8-3.9,1.1-7.9,1.6-12,1.6-10.6,0-18.6-2.7-24.3-8.2-5.7-5.5-8.6-13.4-8.6-24v-46h-15.7v-17.9h15.7v-21.8h22.4v21.8h25.6v17.9h-25.6v45.5c0,4.7,1.1,8.2,3.4,10.6,2.3,2.5,5.5,3.8,9.8,3.8s9.1-1.3,12.5-3.9l6.3,15.9ZM1036.9,69.2c12,0,21.7,3.6,29,10.6,7.3,7,10.9,17.5,10.9,31.3v54.8h-22.4v-51.9c0-8.4-2-14.7-5.9-19-3.9-4.1-9.5-6.3-16.8-6.3s-14.7,2.5-19.5,7.3c-4.8,5-7.2,12.2-7.2,21.5v48.3h-22.4V33.1h22.4v48.3c3.8-3.9,8.2-7,13.8-9.1,5.4-2,11.5-3,18.1-3Z"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.0 KiB

@@ -2,6 +2,8 @@
@tailwind components;
@tailwind utilities;
@import '@modrinth/ui/src/styles/tailwind-utilities.css';
@font-face {
font-family: 'bundled-minecraft-font-mrapp';
font-style: normal;
@@ -83,10 +85,6 @@ a {
}
}
input {
border: none !important;
}
.badge {
display: flex;
border-radius: var(--radius-md);
@@ -8,10 +8,14 @@ import {
SearchIcon,
StopCircleIcon,
TrashIcon,
XIcon,
} from '@modrinth/assets'
import { Button, DropdownSelect, injectNotificationManager } from '@modrinth/ui'
import { formatCategoryHeader } from '@modrinth/utils'
import {
DropdownSelect,
formatLoader,
injectNotificationManager,
StyledInput,
useVIntl,
} from '@modrinth/ui'
import { useStorage } from '@vueuse/core'
import dayjs from 'dayjs'
import { computed, ref } from 'vue'
@@ -23,6 +27,8 @@ import { duplicate, remove } from '@/helpers/profile.js'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const props = defineProps({
instances: {
type: Array,
@@ -175,7 +181,7 @@ const filteredResults = computed(() => {
if (group === 'Loader') {
instances.forEach((instance) => {
const loader = formatCategoryHeader(instance.loader)
const loader = formatLoader(formatMessage, instance.loader)
if (!instanceMap.has(loader)) {
instanceMap.set(loader, [])
}
@@ -243,13 +249,14 @@ const filteredResults = computed(() => {
</script>
<template>
<div class="flex gap-2">
<div class="iconified-input flex-1">
<SearchIcon />
<input v-model="search" type="text" placeholder="Search" />
<Button class="r-btn" @click="() => (search = '')">
<XIcon />
</Button>
</div>
<StyledInput
v-model="search"
:icon="SearchIcon"
type="text"
placeholder="Search"
clearable
wrapper-class="flex-1"
/>
<DropdownSelect
v-slot="{ selected }"
v-model="state.sortBy"
@@ -18,8 +18,8 @@ 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 ProjectCard from '@/components/ui/ProjectCard.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_by_profile_path } from '@/helpers/process.js'
import { duplicate, kill, remove, run } from '@/helpers/profile.js'
@@ -270,7 +270,7 @@ onUnmounted(() => {
/>
</section>
<section v-else ref="modsRow" class="projects">
<ProjectCard
<LegacyProjectCard
v-for="project in row.instances.slice(0, maxProjectsPerRow)"
:key="project?.project_id"
ref="instanceComponents"
@@ -33,6 +33,7 @@ const metadata = ref({})
defineExpose({
async show(errorVal, context, canClose = true, source = null) {
console.log(errorVal, context, canClose, source)
closable.value = canClose
if (errorVal.message && errorVal.message.includes('Minecraft authentication error:')) {
@@ -1,6 +1,6 @@
<script setup>
import { PlusIcon, XIcon } from '@modrinth/assets'
import { Button, Checkbox, injectNotificationManager } from '@modrinth/ui'
import { Button, Checkbox, injectNotificationManager, StyledInput } from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { ref } from 'vue'
@@ -110,31 +110,33 @@ const exportPack = async () => {
<div class="modal-body">
<div class="labeled_input">
<p>Modpack Name</p>
<div class="iconified-input">
<PackageIcon />
<input v-model="nameInput" type="text" placeholder="Modpack name" class="input" />
<Button class="r-btn" @click="nameInput = ''">
<XIcon />
</Button>
</div>
<StyledInput
v-model="nameInput"
:icon="PackageIcon"
type="text"
placeholder="Modpack name"
clearable
/>
</div>
<div class="labeled_input">
<p>Version number</p>
<div class="iconified-input">
<VersionIcon />
<input v-model="versionInput" type="text" placeholder="1.0.0" class="input" />
<Button class="r-btn" @click="versionInput = ''">
<XIcon />
</Button>
</div>
<StyledInput
v-model="versionInput"
:icon="VersionIcon"
type="text"
placeholder="1.0.0"
clearable
/>
</div>
<div class="adjacent-input">
<div class="labeled_input">
<p>Description</p>
<div class="textarea-wrapper">
<textarea v-model="exportDescription" placeholder="Enter modpack description..." />
</div>
<StyledInput
v-model="exportDescription"
multiline
placeholder="Enter modpack description..."
/>
</div>
</div>
@@ -289,17 +291,4 @@ const exportPack = async () => {
align-items: center;
gap: 1rem;
}
.textarea-wrapper {
// margin-top: 1rem;
height: 12rem;
textarea {
max-height: 12rem;
}
.preview {
overflow-y: auto;
}
}
</style>
@@ -20,12 +20,13 @@
</div>
<div class="input-row">
<p class="input-label">Name</p>
<input
<StyledInput
v-model="profile_name"
autocomplete="off"
class="text-input"
type="text"
maxlength="100"
placeholder="Enter a name for your instance..."
:maxlength="100"
wrapper-class="w-full"
/>
</div>
<div class="input-row">
@@ -93,18 +94,14 @@
<div class="path-selection">
<h3>{{ selectedProfileType.name }} path</h3>
<div class="path-input">
<div class="iconified-input">
<FolderOpenIcon />
<input
v-model="selectedProfileType.path"
type="text"
placeholder="Path to launcher"
@change="setPath"
/>
<Button class="r-btn" @click="() => (selectedProfileType.path = '')">
<XIcon />
</Button>
</div>
<StyledInput
v-model="selectedProfileType.path"
:icon="FolderOpenIcon"
type="text"
placeholder="Path to launcher"
clearable
@change="setPath"
/>
<Button icon-only @click="selectLauncherPath">
<FolderSearchIcon />
</Button>
@@ -197,7 +194,14 @@ import {
UploadIcon,
XIcon,
} from '@modrinth/assets'
import { Avatar, Button, Checkbox, Chips, injectNotificationManager } from '@modrinth/ui'
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'
@@ -341,7 +345,7 @@ 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'
const loaderVersion = loader.value === 'vanilla' ? null : (loader_version_value ?? 'stable')
hide()
creating.value = false
@@ -350,7 +354,7 @@ const create_instance = async () => {
profile_name.value,
game_version.value,
loader.value,
loader.value === 'vanilla' ? null : loader_version_value ?? 'stable',
loader.value === 'vanilla' ? null : (loader_version_value ?? 'stable'),
icon.value,
).catch(handleError)
@@ -1,7 +1,6 @@
<script setup lang="ts">
import { GameIcon, LeftArrowIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled } from '@modrinth/ui'
import { formatCategory } from '@modrinth/utils'
import { Avatar, ButtonStyled, FormattedTag } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
type Instance = {
@@ -37,7 +36,8 @@ defineProps<{
</span>
<span class="text-secondary flex items-center gap-2 font-semibold">
<GameIcon class="h-5 w-5 text-secondary" />
{{ formatCategory(instance.loader) }} {{ instance.game_version }}
<FormattedTag :tag="instance.loader" enforce-type="loader" />
{{ instance.game_version }}
</span>
</span>
</span>
@@ -1,18 +1,17 @@
<template>
<JavaDetectionModal ref="detectJavaModal" @submit="(val) => emit('update:modelValue', val)" />
<div class="toggle-setting" :class="{ compact }">
<input
<StyledInput
autocomplete="off"
:disabled="props.disabled"
:value="props.modelValue ? props.modelValue.path : ''"
type="text"
class="installation-input"
:model-value="props.modelValue ? props.modelValue.path : ''"
:placeholder="placeholder ?? '/path/to/java'"
@input="
wrapper-class="installation-input"
@update:model-value="
(val) => {
emit('update:modelValue', {
...props.modelValue,
path: val.target.value,
path: val,
})
}
"
@@ -60,7 +59,7 @@ import {
SearchIcon,
XIcon,
} from '@modrinth/assets'
import { Button, injectNotificationManager } from '@modrinth/ui'
import { Button, injectNotificationManager, StyledInput } from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { ref } from 'vue'
@@ -1,7 +1,7 @@
<script setup>
import { DownloadIcon, HeartIcon, TagIcon } from '@modrinth/assets'
import { Avatar, TagItem } from '@modrinth/ui'
import { formatCategory, formatNumber } from '@modrinth/utils'
import { Avatar, FormattedTag, TagItem } from '@modrinth/ui'
import { formatNumber } from '@modrinth/utils'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { computed } from 'vue'
@@ -63,7 +63,7 @@ const toTransparent = computed(() => {
<div
class="w-full aspect-[2/1] bg-cover bg-center bg-no-repeat"
:style="{
'background-color': project.featured_gallery ?? project.gallery[0] ? null : toColor,
'background-color': (project.featured_gallery ?? project.gallery[0]) ? null : toColor,
'background-image': `url(${
project.featured_gallery ??
project.gallery[0] ??
@@ -107,7 +107,7 @@ const toTransparent = computed(() => {
<div class="flex items-center gap-1 pr-2">
<TagIcon />
<TagItem>
{{ formatCategory(featuredCategory) }}
<FormattedTag :tag="featuredCategory" />
</TagItem>
</div>
</div>
+63 -39
View File
@@ -1,5 +1,7 @@
<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
@@ -14,13 +16,17 @@
<span class="text-nowrap">{{ link.label }}</span>
</RouterLink>
<div
:class="`navtabs-transition pointer-events-none absolute h-[calc(100%-0.5rem)] overflow-hidden rounded-full p-1 ${subpageSelected ? 'bg-button-bg' : 'bg-button-bgSelected'}`"
: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: sliderLeft === 4 && sliderLeft === sliderRight ? 0 : activeIndex === -1 ? 0 : 1,
opacity: sliderReady && activeIndex !== -1 ? 1 : 0,
}"
aria-hidden="true"
></div>
@@ -28,7 +34,7 @@
</template>
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import type { RouteLocationRaw } from 'vue-router'
import { RouterLink, useRoute } from 'vue-router'
@@ -47,13 +53,16 @@ const props = defineProps<{
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 oldIndex = 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)),
@@ -63,13 +72,18 @@ 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)) {
if (route.path === (typeof link.href === 'string' ? link.href : (link.href as any).path)) {
index = i
break
} else if (link.subpages && link.subpages.some((subpage) => route.path.includes(subpage))) {
@@ -83,57 +97,54 @@ function pickLink() {
if (activeIndex.value !== -1) {
startAnimation()
} else {
oldIndex.value = -1
sliderLeft.value = 0
sliderRight.value = 0
}
}
const tabLinkElements = ref()
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 = tabLinkElements.value[activeIndex.value].$el
if (!el || !el.offsetParent) return
const el = getTabElement(activeIndex.value)
if (!el?.offsetParent) return
const parent = el.offsetParent as HTMLElement
const newValues = {
left: el.offsetLeft,
top: el.offsetTop,
right: el.offsetParent.offsetWidth - el.offsetLeft - el.offsetWidth,
bottom: el.offsetParent.offsetHeight - el.offsetTop - el.offsetHeight,
right: parent.offsetWidth - el.offsetLeft - el.offsetWidth,
bottom: parent.offsetHeight - el.offsetTop - el.offsetHeight,
}
if (sliderLeft.value === 4 && sliderRight.value === 4) {
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 delay = 200
if (newValues.left < sliderLeft.value) {
sliderLeft.value = newValues.left
setTimeout(() => {
sliderRight.value = newValues.right
}, delay)
} else {
sliderRight.value = newValues.right
setTimeout(() => {
sliderLeft.value = newValues.left
}, delay)
}
if (newValues.top < sliderTop.value) {
sliderTop.value = newValues.top
setTimeout(() => {
sliderBottom.value = newValues.bottom
}, delay)
} else {
sliderBottom.value = newValues.bottom
setTimeout(() => {
sliderTop.value = newValues.top
}, delay)
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
}
}
@@ -146,7 +157,17 @@ onUnmounted(() => {
window.removeEventListener('resize', pickLink)
})
watch(route, () => {
watch(
filteredLinks,
async () => {
await nextTick()
pickLink()
},
{ deep: true },
)
watch(route, async () => {
await nextTick()
pickLink()
})
</script>
@@ -154,7 +175,10 @@ watch(route, () => {
.navtabs-transition {
/* Delay on opacity is to hide any jankiness as the page loads */
transition:
all 150ms cubic-bezier(0.4, 0, 0.2, 1) 0s,
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>
@@ -34,18 +34,18 @@ function updateAdPosition() {
<template>
<div ref="adsWrapper" class="ad-parent relative flex w-full justify-center cursor-pointer bg-bg">
<a
href="https://modrinth.gg/medal?from=app-placeholder"
href="https://modrinth.host/medal?from=app-placeholder"
target="_blank"
class="flex max-h-[250px] min-h-[250px] min-w-[300px] max-w-[300px] flex-col gap-4 rounded-[inherit]"
>
<img
src="https://cdn-raw.modrinth.com/medal-modrinth-servers-light-new.webp"
alt="Host your next server with Modrinth Servers"
src="https://cdn-raw.modrinth.com/modrinth-hosting-medal-light.webp"
alt="Host your next server with Modrinth Hosting"
class="hidden light-image rounded-[inherit]"
/>
<img
src="https://cdn-raw.modrinth.com/medal-modrinth-servers-dark-new.webp"
alt="Host your next server with Modrinth Servers"
src="https://cdn-raw.modrinth.com/modrinth-hosting-medal-dark.webp"
alt="Host your next server with Modrinth Hosting"
class="dark-image rounded-[inherit]"
/>
</a>
@@ -69,7 +69,10 @@ onUnmounted(() => {
<SpinnerIcon class="animate-spin w-4 h-4" />
</div>
</NavButton>
<div v-if="recentInstances.length > 0" class="h-px w-6 mx-auto my-2 bg-divider"></div>
<div
v-if="instances && recentInstances.length > 0"
class="h-px w-6 mx-auto my-2 bg-divider"
></div>
</template>
<style scoped lang="scss"></style>
@@ -52,10 +52,12 @@
<h3 class="info-title">
{{ loadingBar.title }}
</h3>
<ProgressBar :progress="Math.floor((100 * loadingBar.current) / loadingBar.total)" />
<div class="row">
{{ Math.floor((100 * loadingBar.current) / loadingBar.total) }}%
{{ loadingBar.message }}
<div class="flex flex-col gap-2 w-full">
<ProgressBar :progress="Math.floor((100 * loadingBar.current) / loadingBar.total)" />
<div class="row">
{{ Math.floor((100 * loadingBar.current) / loadingBar.total) }}%
{{ loadingBar.message }}
</div>
</div>
</div>
</Card>
@@ -102,7 +104,12 @@ import {
TerminalSquareIcon,
UnplugIcon,
} from '@modrinth/assets'
import { Button, ButtonStyled, Card, injectNotificationManager } from '@modrinth/ui'
import {
Button,
ButtonStyled,
Card,
injectNotificationManager,
} from '@modrinth/ui'
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
@@ -176,7 +183,7 @@ const goToTerminal = (path) => {
const currentLoadingBars = ref([])
const refreshInfo = async () => {
const currentLoadingBarCount = currentLoadingBars.value.length
const previousBars = [...currentLoadingBars.value]
currentLoadingBars.value = Object.values(await progress_bars_list().catch(handleError))
.map((x) => {
if (x.bar_type.type === 'java_download') {
@@ -205,7 +212,7 @@ const refreshInfo = async () => {
if (currentLoadingBars.value.length === 0) {
showCard.value = false
} else if (currentLoadingBarCount < currentLoadingBars.value.length) {
} else if (previousBars.length < currentLoadingBars.value.length) {
showCard.value = true
}
}
@@ -346,7 +353,7 @@ onBeforeUnmount(() => {
.info-card {
position: absolute;
top: 3.5rem;
right: 0.5rem;
right: 100%;
z-index: 9;
width: 20rem;
background-color: var(--color-raised-bg);
@@ -420,7 +427,7 @@ onBeforeUnmount(() => {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
gap: 0.75rem;
margin: 0;
padding: 0;
}
@@ -1,7 +1,7 @@
<template>
<div
class="card-shadow p-4 bg-bg-raised rounded-xl flex gap-3 group cursor-pointer hover:brightness-90 transition-all"
@click="
<ProjectCard
:title="project.title"
:link="
() => {
emit('open')
$router.push({
@@ -10,116 +10,58 @@
})
}
"
: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"
>
<div class="icon w-[96px] h-[96px] relative">
<Avatar :src="project.icon_url" size="96px" class="search-icon origin-top transition-all" />
</div>
<div class="flex flex-col gap-2 overflow-hidden">
<div class="gap-2 overflow-hidden no-wrap text-ellipsis">
<span class="text-lg font-extrabold text-contrast m-0 leading-none">
{{ project.title }}
</span>
<span v-if="project.author" class="text-secondary"> by {{ project.author }}</span>
</div>
<div class="m-0 line-clamp-2">
{{ project.description }}
</div>
<div v-if="categories.length > 0" class="mt-auto flex items-center gap-1 no-wrap">
<TagsIcon class="h-4 w-4 shrink-0" />
<div
v-if="project.project_type === 'mod' || project.project_type === 'modpack'"
class="text-sm font-semibold text-secondary flex gap-1 px-[0.375rem] py-0.5 bg-button-bg rounded-full"
<template #actions>
<ButtonStyled color="brand" type="outlined">
<button
:disabled="installed || installing"
class="shrink-0 no-wrap"
@click.stop="install()"
>
<template v-if="project.client_side === 'optional' && project.server_side === 'optional'">
Client or server
<template v-if="!installed">
<DownloadIcon v-if="modpack || instance" />
<PlusIcon v-else />
</template>
<template
v-else-if="
(project.client_side === 'optional' || project.client_side === 'required') &&
(project.server_side === 'optional' || project.server_side === 'unsupported')
"
>
Client
</template>
<template
v-else-if="
(project.server_side === 'optional' || project.server_side === 'required') &&
(project.client_side === 'optional' || project.client_side === 'unsupported')
"
>
Server
</template>
<template
v-else-if="
project.client_side === 'unsupported' && project.server_side === 'unsupported'
"
>
Unsupported
</template>
<template
v-else-if="project.client_side === 'required' && project.server_side === 'required'"
>
Client and server
</template>
</div>
<div
v-for="tag in categories"
:key="tag"
class="text-sm font-semibold text-secondary flex gap-1 px-[0.375rem] py-0.5 bg-button-bg rounded-full"
>
{{ formatCategory(tag.name) }}
</div>
</div>
</div>
<div class="flex flex-col gap-2 items-end shrink-0 ml-auto">
<div class="flex items-center gap-2">
<DownloadIcon class="shrink-0" />
<span>
{{ formatNumber(project.downloads) }}
<span class="text-secondary">downloads</span>
</span>
</div>
<div class="flex items-center gap-2">
<HeartIcon class="shrink-0" />
<span>
{{ formatNumber(project.follows ?? project.followers) }}
<span class="text-secondary">followers</span>
</span>
</div>
<div class="mt-auto relative">
<div class="absolute bottom-0 right-0 w-fit">
<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>
</div>
</div>
</div>
</div>
<CheckIcon v-else />
{{
installing
? 'Installing'
: installed
? 'Installed'
: modpack || instance
? 'Install'
: 'Add to an instance'
}}
</button>
</ButtonStyled>
</template>
</ProjectCard>
</template>
<script setup>
import { CheckIcon, DownloadIcon, HeartIcon, PlusIcon, TagsIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled, injectNotificationManager } from '@modrinth/ui'
import { formatCategory, formatNumber } from '@modrinth/utils'
import { 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'
@@ -141,10 +83,6 @@ const props = defineProps({
type: Object,
required: true,
},
categories: {
type: Array,
required: true,
},
instance: {
type: Object,
default: null,
@@ -157,6 +95,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
projectType: {
type: String,
default: undefined,
},
})
const emit = defineEmits(['open', 'install'])
@@ -191,7 +191,8 @@ const handleClose = async () => {
position: absolute;
height: 100vh;
width: 100vw;
background: linear-gradient(180deg, rgba(66, 131, 92, 0.275) 0%, rgba(17, 35, 43, 0.5) 97.29%),
background:
linear-gradient(180deg, rgba(66, 131, 92, 0.275) 0%, rgba(17, 35, 43, 0.5) 97.29%),
linear-gradient(0deg, rgba(22, 24, 28, 0.64), rgba(22, 24, 28, 0.64));
z-index: 9997;
}
@@ -1,131 +0,0 @@
<script setup lang="ts">
import { DownloadIcon, ExternalIcon, RefreshCwIcon, SpinnerIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, commonMessages, ProgressBar } from '@modrinth/ui'
import { formatBytes } from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { ref } from 'vue'
import { injectAppUpdateDownloadProgress } from '@/providers/download-progress.ts'
const { formatMessage } = useVIntl()
const emit = defineEmits<{
(e: 'close' | 'restart' | 'download'): void
}>()
defineProps<{
version: string
size: number | null
metered: boolean
}>()
const downloading = ref(false)
const { progress } = injectAppUpdateDownloadProgress()
function download() {
emit('download')
downloading.value = true
}
const messages = defineMessages({
title: {
id: 'app.update-toast.title',
defaultMessage: 'Update available',
},
body: {
id: 'app.update-toast.body',
defaultMessage:
'Modrinth App v{version} is ready to install! Reload to update now, or automatically when you close Modrinth App.',
},
reload: {
id: 'app.update-toast.reload',
defaultMessage: 'Reload',
},
download: {
id: 'app.update-toast.download',
defaultMessage: 'Download ({size})',
},
downloading: {
id: 'app.update-toast.downloading',
defaultMessage: 'Downloading...',
},
changelog: {
id: 'app.update-toast.changelog',
defaultMessage: 'Changelog',
},
meteredBody: {
id: 'app.update-toast.body.metered',
defaultMessage: `Modrinth App v{version} is available now! Since you're on a metered network, we didn't automatically download it.`,
},
downloadCompleteTitle: {
id: 'app.update-toast.title.download-complete',
defaultMessage: 'Download complete',
},
downloadedBody: {
id: 'app.update-toast.body.download-complete',
defaultMessage: `Modrinth App v{version} has finished downloading. Reload to update now, or automatically when you close Modrinth App.`,
},
})
</script>
<template>
<div
class="grid grid-cols-[min-content] fixed card-shadow rounded-2xl top-[--top-bar-height] mt-6 right-6 p-4 z-10 bg-bg-raised border-divider border-solid border-[2px]"
:class="{
'download-complete': progress === 1,
}"
>
<div class="flex min-w-[25rem] gap-4">
<h2 class="whitespace-nowrap text-base text-contrast font-semibold m-0 grow">
{{
formatMessage(metered && progress === 1 ? messages.downloadCompleteTitle : messages.title)
}}
</h2>
<ButtonStyled size="small" circular>
<button v-tooltip="formatMessage(commonMessages.closeButton)" @click="emit('close')">
<XIcon />
</button>
</ButtonStyled>
</div>
<p class="text-sm mt-2 mb-0">
{{
formatMessage(
metered
? progress === 1
? messages.downloadedBody
: messages.meteredBody
: messages.body,
{ version },
)
}}
</p>
<p
v-if="metered && progress < 1"
class="text-sm text-secondary mt-2 mb-0 flex items-center gap-1"
>
<template v-if="progress > 0">
<ProgressBar :progress="progress" class="max-w-[unset]" />
</template>
</p>
<div class="flex gap-2 mt-4">
<ButtonStyled color="brand">
<button v-if="metered && progress < 1" :disabled="downloading" @click="download">
<SpinnerIcon v-if="downloading" class="animate-spin" />
<DownloadIcon v-else />
{{
formatMessage(downloading ? messages.downloading : messages.download, {
size: formatBytes(size ?? 0),
})
}}
</button>
<button v-else @click="emit('restart')">
<RefreshCwIcon /> {{ formatMessage(messages.reload) }}
</button>
</ButtonStyled>
<ButtonStyled>
<a href="https://modrinth.com/news/changelog?filter=app">
{{ formatMessage(messages.changelog) }} <ExternalIcon />
</a>
</ButtonStyled>
</div>
</div>
</template>
@@ -3,12 +3,13 @@ import { MailIcon, SendIcon, UserIcon, UserPlusIcon, XIcon } from '@modrinth/ass
import {
Avatar,
ButtonStyled,
commonMessages,
defineMessages,
injectNotificationManager,
IntlFormatted,
StyledInput,
useRelativeTime,
useVIntl,
} from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import { computed, onUnmounted, ref, watch } from 'vue'
import FriendsSection from '@/components/ui/friends/FriendsSection.vue'
@@ -270,15 +271,14 @@ const messages = defineMessages({
{{ formatMessage(messages.usernameDescription) }}
</p>
<div class="flex items-center gap-2 mt-4">
<div class="iconified-input flex-1">
<UserIcon aria-hidden="true" />
<input
v-model="username"
type="text"
:placeholder="formatMessage(messages.usernamePlaceholder)"
@keyup.enter="addFriendFromModal"
/>
</div>
<StyledInput
v-model="username"
:icon="UserIcon"
type="text"
:placeholder="formatMessage(messages.usernamePlaceholder)"
wrapper-class="flex-1"
@keyup.enter="addFriendFromModal"
/>
<ButtonStyled color="brand">
<button :disabled="username.length === 0" @click="addFriendFromModal">
<SendIcon />
@@ -299,23 +299,15 @@ const messages = defineMessages({
<UserPlusIcon />
</button>
</ButtonStyled>
<div class="iconified-input flex-1">
<input
v-model="search"
type="text"
class="friends-search-bar flex w-full"
:placeholder="formatMessage(messages.searchFriends)"
@keyup.esc="search = ''"
/>
<button
v-if="search"
v-tooltip="formatMessage(commonMessages.clearButton)"
class="r-btn flex items-center justify-center bg-transparent button-animation p-2 cursor-pointer appearance-none border-none"
@click="search = ''"
>
<XIcon />
</button>
</div>
<StyledInput
v-model="search"
type="text"
:placeholder="formatMessage(messages.searchFriends)"
clearable
variant="outlined"
wrapper-class="flex-1"
@keyup.esc="search = ''"
/>
</template>
<h3 v-else class="ml-2 w-full text-base text-primary font-medium m-0">
{{ formatMessage(messages.friends) }}
@@ -412,16 +404,3 @@ const messages = defineMessages({
</template>
</div>
</template>
<style scoped>
.friends-search-bar {
background: none;
border: 2px solid var(--color-button-bg) !important;
padding: 8px;
border-radius: 12px;
height: 36px;
}
.friends-search-bar::placeholder {
@apply text-sm font-normal;
}
</style>
@@ -1,8 +1,14 @@
<script setup lang="ts">
import { MoreVerticalIcon, TrashIcon, UserIcon, XIcon } from '@modrinth/assets'
import { Accordion, Avatar, ButtonStyled, OverflowMenu } from '@modrinth/ui'
import {
Accordion,
Avatar,
ButtonStyled,
defineMessages,
OverflowMenu,
useVIntl,
} from '@modrinth/ui'
import { openUrl } from '@tauri-apps/plugin-opener'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { useTemplateRef } from 'vue'
import ContextMenu from '@/components/ui/ContextMenu.vue'
@@ -0,0 +1,136 @@
<script setup>
import {
CheckIcon,
PlusIcon,
SearchIcon,
} from '@modrinth/assets'
import { Admonition, Avatar, ButtonStyled, injectNotificationManager, StyledInput } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { computed, ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { list } from '@/helpers/profile'
import { add_server_to_profile, get_profile_worlds } from '@/helpers/worlds.ts'
const { handleError } = injectNotificationManager()
const modal = ref()
const searchFilter = ref('')
const profiles = ref([])
const serverName = ref('')
const serverAddress = ref('')
const shownProfiles = computed(() =>
profiles.value.filter((profile) => {
return profile.name.toLowerCase().includes(searchFilter.value.toLowerCase())
}),
)
defineExpose({
show: async (name, address) => {
serverName.value = name
serverAddress.value = address
searchFilter.value = ''
const profilesVal = await list().catch(handleError)
for (const profile of profilesVal) {
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
}
}
profiles.value = profilesVal
modal.value.show()
trackEvent('AddServerToInstanceStart', { source: 'AddServerToInstanceModal' })
},
})
async function addServer(profile) {
profile.adding = true
try {
await add_server_to_profile(
profile.path,
serverName.value,
serverAddress.value,
'prompt',
)
profile.added = true
trackEvent('AddServerToInstance', {
server_name: serverName.value,
instance_name: profile.name,
source: 'AddServerToInstanceModal',
})
} catch (err) {
handleError(err)
}
profile.adding = false
}
</script>
<template>
<ModalWrapper ref="modal" header="Add server to instance">
<div class="flex flex-col gap-4 min-w-[350px]">
<Admonition type="warning" body="This server may not be compatible with all instances." />
<StyledInput
v-model="searchFilter"
:icon="SearchIcon"
type="search"
placeholder="Search for an instance"
autocomplete="off"
/>
<div class="max-h-[21rem] overflow-y-auto">
<div
v-for="profile in shownProfiles"
:key="profile.path"
class="flex w-full items-center justify-between gap-2 bg-bg-raised text-icon shadow-none"
>
<router-link
class="btn btn-transparent p-2 text-left"
:to="`/instance/${encodeURIComponent(profile.path)}`"
@click="modal.hide()"
>
<Avatar
:src="profile.icon_path ? convertFileSrc(profile.icon_path) : null"
class="mr-2 [--size:2rem]"
/>
{{ profile.name }}
</router-link>
<ButtonStyled>
<button
:disabled="profile.added || profile.adding"
@click="addServer(profile)"
>
<PlusIcon v-if="!profile.added && !profile.adding" />
<CheckIcon v-else-if="profile.added" />
{{
profile.adding
? 'Adding...'
: profile.added
? 'Added'
: 'Add'
}}
</button>
</ButtonStyled>
</div>
</div>
<div class="input-group push-right">
<ButtonStyled>
<button @click="modal.hide()">Cancel</button>
</ButtonStyled>
</div>
</div>
</ModalWrapper>
</template>
@@ -28,7 +28,7 @@
:custom-label="
(version) =>
`${version?.name} (${version?.loaders
.map((name) => formatCategory(name))
.map((name) => formatLoader(formatMessage, name))
.join(', ')} - ${version?.game_versions.join(', ')})`
"
:max-height="150"
@@ -36,7 +36,9 @@
<span v-else>
<span>
{{ selectedVersion?.name }} ({{
selectedVersion?.loaders.map((name) => formatCategory(name)).join(', ')
selectedVersion?.loaders
.map((name) => formatLoader(formatMessage, name))
.join(', ')
}}
- {{ selectedVersion?.game_versions.join(', ') }})
</span>
@@ -57,8 +59,7 @@
<script setup>
import { DownloadIcon, XIcon } from '@modrinth/assets'
import { Button, injectNotificationManager } from '@modrinth/ui'
import { formatCategory } from '@modrinth/utils'
import { Button, formatLoader, injectNotificationManager, useVIntl } from '@modrinth/ui'
import { ref } from 'vue'
import Multiselect from 'vue-multiselect'
@@ -67,6 +68,7 @@ import { trackEvent } from '@/helpers/analytics'
import { add_project_from_version as installMod } from '@/helpers/profile'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const instance = ref(null)
const project = ref(null)
@@ -4,10 +4,11 @@ import {
DownloadIcon,
PlusIcon,
RightArrowIcon,
SearchIcon,
UploadIcon,
XIcon,
} from '@modrinth/assets'
import { Avatar, Button, Card, injectNotificationManager } from '@modrinth/ui'
import { Avatar, Button, Card, injectNotificationManager, StyledInput } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { open } from '@tauri-apps/plugin-dialog'
import { computed, ref } from 'vue'
@@ -15,6 +16,7 @@ import { useRouter } from 'vue-router'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_project_v3_many } from '@/helpers/cache.js'
import {
add_project_from_version as installMod,
check_installed,
@@ -48,19 +50,14 @@ const creatingInstance = ref(false)
const profiles = ref([])
const shownProfiles = computed(() =>
profiles.value
.filter((profile) => {
return profile.name.toLowerCase().includes(searchFilter.value.toLowerCase())
})
.filter((profile) => {
const version = {
game_versions: versions.value.flatMap((v) => v.game_versions),
loaders: versions.value.flatMap((v) => v.loaders),
}
return isVersionCompatible(version, project.value, profile)
}),
profiles.value.filter((profile) => {
return profile.name.toLowerCase().includes(searchFilter.value.toLowerCase())
}),
)
const isProfileCompatible = (profile) =>
versions.value?.some((version) => isVersionCompatible(version, project.value, profile))
const onInstall = ref(() => {})
defineExpose({
@@ -85,6 +82,22 @@ defineExpose({
handleError,
)
}
const linkedProjectIds = profilesVal
.filter((p) => p.linked_data?.project_id)
.map((p) => p.linked_data.project_id)
if (linkedProjectIds.length > 0) {
const linkedProjects = await get_project_v3_many(linkedProjectIds, 'stale_while_revalidate_skip_offline').catch(
() => [],
)
const serverProjectIds = new Set(
linkedProjects.filter((p) => p?.minecraft_server != null).map((p) => p.id),
)
for (const profile of profilesVal) {
profile.isServerInstance = serverProjectIds.has(profile.linked_data?.project_id)
}
}
profiles.value = profilesVal
installModal.value.show()
@@ -159,20 +172,21 @@ const reset_icon = () => {
const createInstance = async () => {
creatingInstance.value = true
const loader =
versions.value[0].loaders[0] !== 'forge' &&
versions.value[0].loaders[0] !== 'fabric' &&
versions.value[0].loaders[0] !== 'quilt'
? 'vanilla'
: versions.value[0].loaders[0]
const gameVersions = versions.value[0].game_versions
const gameVersion = gameVersions[0]
const id = await create(
name.value,
versions.value[0].game_versions[0],
loader,
'latest',
icon.value,
).catch(handleError)
const loaders = versions.value[0].loaders
const loader = loaders.includes('fabric')
? 'fabric'
: loaders.includes('neoforge')
? 'neoforge'
: loaders.includes('forge')
? 'forge'
: loaders.includes('quilt')
? 'quilt'
: 'vanilla'
const id = await create(name.value, gameVersion, loader, 'latest', icon.value).catch(handleError)
await installMod(id, versions.value[0].id).catch(handleError)
@@ -210,12 +224,12 @@ const createInstance = async () => {
<template>
<ModalWrapper ref="installModal" header="Install project to instance" :on-hide="onInstall">
<div class="modal-body">
<input
<StyledInput
v-model="searchFilter"
autocomplete="off"
type="text"
class="search"
:icon="SearchIcon"
type="search"
placeholder="Search for an instance"
autocomplete="off"
/>
<div class="profiles" :class="{ 'hide-creation': !showCreation }">
<div v-for="profile in shownProfiles" :key="profile.name" class="option">
@@ -238,17 +252,23 @@ const createInstance = async () => {
"
>
<Button
:disabled="profile.installedMod || profile.installing"
:disabled="
!isProfileCompatible(profile) || profile.installedMod || profile.installing
"
@click="install(profile)"
>
<DownloadIcon v-if="!profile.installedMod && !profile.installing" />
<DownloadIcon
v-if="isProfileCompatible(profile) && !profile.installedMod && !profile.installing"
/>
<CheckIcon v-else-if="profile.installedMod" />
{{
profile.installing
? 'Installing...'
: profile.installedMod
? 'Installed'
: 'Install'
: !isProfileCompatible(profile)
? 'Incompatible'
: 'Install'
}}
</Button>
</div>
@@ -270,7 +290,7 @@ const createInstance = async () => {
</div>
</div>
<div class="creation-settings">
<input
<StyledInput
v-model="name"
autocomplete="off"
type="text"
@@ -4,12 +4,14 @@ import {
Avatar,
ButtonStyled,
Checkbox,
defineMessages,
injectNotificationManager,
OverflowMenu,
StyledInput,
useVIntl,
} from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { open } from '@tauri-apps/plugin-dialog'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { computed, type Ref, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
@@ -244,13 +246,12 @@ const messages = defineMessages({
{{ formatMessage(messages.name) }}
</label>
<div class="flex">
<input
<StyledInput
id="instance-name"
v-model="title"
autocomplete="off"
maxlength="80"
class="flex-grow"
type="text"
:maxlength="80"
wrapper-class="flex-grow"
/>
</div>
<template v-if="instance.install_stage == 'installed'">
@@ -291,9 +292,8 @@ const messages = defineMessages({
@click="toggleGroup(group)"
/>
<div class="flex gap-2 items-center">
<input
<StyledInput
v-model="newCategoryInput"
type="text"
:placeholder="formatMessage(messages.libraryGroupsEnterName)"
@submit="() => addCategory"
/>
@@ -1,6 +1,11 @@
<script setup lang="ts">
import { Checkbox, injectNotificationManager } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import {
Checkbox,
defineMessages,
injectNotificationManager,
StyledInput,
useVIntl,
} from '@modrinth/ui'
import { computed, ref, watch } from 'vue'
import { edit } from '@/helpers/profile'
@@ -109,14 +114,13 @@ const messages = defineMessages({
<p class="m-0">
{{ formatMessage(messages.preLaunchDescription) }}
</p>
<input
<StyledInput
id="pre-launch"
v-model="hooks.pre_launch"
autocomplete="off"
:disabled="!overrideHooks"
type="text"
:placeholder="formatMessage(messages.preLaunchEnter)"
class="w-full mt-2"
wrapper-class="w-full mt-2"
/>
<h2 class="mt-4 mb-1 text-lg font-extrabold text-contrast">
@@ -125,14 +129,13 @@ const messages = defineMessages({
<p class="m-0">
{{ formatMessage(messages.wrapperDescription) }}
</p>
<input
<StyledInput
id="wrapper"
v-model="hooks.wrapper"
autocomplete="off"
:disabled="!overrideHooks"
type="text"
:placeholder="formatMessage(messages.wrapperEnter)"
class="w-full mt-2"
wrapper-class="w-full mt-2"
/>
<h2 class="mt-4 mb-1 text-lg font-extrabold text-contrast">
@@ -141,14 +144,13 @@ const messages = defineMessages({
<p class="m-0">
{{ formatMessage(messages.postExitDescription) }}
</p>
<input
<StyledInput
id="post-exit"
v-model="hooks.post_exit"
autocomplete="off"
:disabled="!overrideHooks"
type="text"
:placeholder="formatMessage(messages.postExitEnter)"
class="w-full mt-2"
wrapper-class="w-full mt-2"
/>
</div>
</template>
@@ -1,6 +1,7 @@
<script setup lang="ts">
import {
DownloadIcon,
getLoaderIcon,
HammerIcon,
IssuesIcon,
SpinnerIcon,
@@ -16,23 +17,19 @@ import {
Checkbox,
Chips,
Combobox,
defineMessages,
formatLoader,
injectNotificationManager,
useVIntl,
} from '@modrinth/ui'
import {
formatCategory,
type GameVersionTag,
type PlatformTag,
type Project,
type Version,
} from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import type { GameVersionTag, PlatformTag, Project, Version } from '@modrinth/utils'
import dayjs from 'dayjs'
import { computed, type ComputedRef, type Ref, ref, shallowRef, watch } from 'vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import ModpackVersionModal from '@/components/ui/ModpackVersionModal.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_project, get_version_many } from '@/helpers/cache'
import { get_project, get_version, get_version_many } from '@/helpers/cache'
import { get_loader_versions } from '@/helpers/metadata'
import { edit, install, update_repair_modrinth } from '@/helpers/profile'
import { get_game_versions, get_loaders } from '@/helpers/tags'
@@ -113,6 +110,12 @@ if (props.instance.linked_data && props.instance.linked_data.project_id && !prop
versions.find(
(version: Version) => version.id === props.instance.linked_data?.version_id,
) ?? null
if (!modpackVersion.value) {
get_version(props.instance.linked_data?.version_id, 'bypass')
.then((version: Version) => (modpackVersion.value = version ?? null))
.catch(handleError)
}
})
.catch(handleError)
.finally(() => {
@@ -128,9 +131,7 @@ if (props.instance.linked_data && props.instance.linked_data.project_id && !prop
fetching.value = false
}
const currentLoaderIcon = computed(
() => loaders?.value.find((x) => x.name === props.instance.loader)?.icon,
)
const currentLoaderIcon = computed(() => getLoaderIcon(props.instance.loader))
const gameVersionsForLoader = computed(() => {
return all_game_versions?.value.filter((item) => {
@@ -429,6 +430,18 @@ const messages = defineMessages({
id: 'instance.settings.tabs.installation.unlink.description',
defaultMessage: `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.`,
},
unlinkServerTitle: {
id: 'instance.settings.tabs.installation.unlink-server.title',
defaultMessage: 'Unlink from server',
},
unlinkServerDescription: {
id: 'instance.settings.tabs.installation.unlink-server.description',
defaultMessage: `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.`,
},
unlinkServerVanillaDescription: {
id: 'instance.settings.tabs.installation.unlink-server-vanilla.description',
defaultMessage: `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.`,
},
unlinkInstanceButton: {
id: 'instance.settings.tabs.installation.unlink.button',
defaultMessage: 'Unlink instance',
@@ -549,7 +562,7 @@ const messages = defineMessages({
v-else
class="w-10 h-10 flex items-center justify-center rounded-full bg-button-bg border-solid border-[1px] border-button-border p-2 [&_svg]:h-full [&_svg]:w-full"
>
<div v-if="!!currentLoaderIcon" class="contents" v-html="currentLoaderIcon" />
<component :is="currentLoaderIcon" v-if="currentLoaderIcon" />
<WrenchIcon v-else />
</div>
<div class="flex flex-col gap-2 justify-center">
@@ -562,17 +575,27 @@ const messages = defineMessages({
})
}}
</span>
<span class="text-sm text-secondary leading-none">
<span class="text-sm text-secondary leading-none capitalize">
{{
modpackProject
? modpackVersion
? modpackVersion?.version_number
: 'Unknown version'
: formatCategory(instance.loader)
: props.isMinecraftServer
? ''
: 'Unknown version'
: formatLoader(formatMessage, instance.loader)
}}
<template v-if="instance.loader !== 'vanilla' && !modpackProject">
{{ instance.loader_version || formatMessage(messages.unknownVersion) }}
</template>
<template
v-else-if="
instance.loader && instance.loader !== 'vanilla' && props.isMinecraftServer
"
>
{{ instance.loader }}
{{ instance.loader_version }}
</template>
</span>
</div>
</div>
@@ -604,7 +627,10 @@ const messages = defineMessages({
}}
</button>
</ButtonStyled>
<ButtonStyled v-if="modpackProject" hover-color-fill="background">
<ButtonStyled
v-if="modpackProject && !props.isMinecraftServer"
hover-color-fill="background"
>
<button
v-tooltip="
changingVersion
@@ -676,7 +702,11 @@ const messages = defineMessages({
</div>
<template v-if="loader !== 'vanilla'">
<h2 class="m-0 mt-4 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.loaderVersion, { loader: formatCategory(loader) }) }}
{{
formatMessage(messages.loaderVersion, {
loader: formatLoader(formatMessage, loader),
})
}}
</h2>
<Combobox
v-if="selectableLoaderVersions"
@@ -708,7 +738,7 @@ const messages = defineMessages({
? messages.alreadyInstalledVanilla
: messages.alreadyInstalledModded,
{
platform: formatCategory(loader),
platform: formatLoader(formatMessage, loader),
version: instance.loader_version,
game_version: gameVersion,
},
@@ -755,17 +785,29 @@ const messages = defineMessages({
<template v-else>
<template v-if="instance.linked_data && instance.linked_data.locked">
<h2 class="mt-4 mb-1 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.unlinkInstanceTitle) }}
{{
formatMessage(
props.isMinecraftServer ? messages.unlinkServerTitle : messages.unlinkInstanceTitle,
)
}}
</h2>
<p class="m-0">
{{ formatMessage(messages.unlinkInstanceDescription) }}
{{
formatMessage(
props.isMinecraftServer
? instance.loader === 'vanilla'
? messages.unlinkServerVanillaDescription
: messages.unlinkServerDescription
: messages.unlinkInstanceDescription,
)
}}
</p>
<ButtonStyled>
<button class="mt-2" @click="modalConfirmUnpair.show()">
<UnlinkIcon /> {{ formatMessage(messages.unlinkInstanceButton) }}
</button>
</ButtonStyled>
<template v-if="modpackProject">
<template v-if="modpackProject && !props.isMinecraftServer">
<div>
<h2 class="m-0 mb-1 text-lg font-extrabold text-contrast block mt-4">
{{ formatMessage(messages.reinstallModpackTitle) }}
@@ -1,7 +1,13 @@
<script setup lang="ts">
import { CheckCircleIcon, XCircleIcon } from '@modrinth/assets'
import { Checkbox, injectNotificationManager, Slider } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import {
Checkbox,
defineMessages,
injectNotificationManager,
Slider,
StyledInput,
useVIntl,
} from '@modrinth/ui'
import { computed, readonly, ref, watch } from 'vue'
import JavaSelector from '@/components/ui/JavaSelector.vue'
@@ -9,7 +15,7 @@ import useMemorySlider from '@/composables/useMemorySlider'
import { edit, get_optimal_jre_key } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import type { AppSettings, InstanceSettingsTabProps, MemorySettings } from '../../../helpers/types'
import type { AppSettings, InstanceSettingsTabProps } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
@@ -22,12 +28,12 @@ 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 overrideJavaArgs = ref(props.instance.extra_launch_args?.length !== undefined)
const overrideJavaArgs = ref((props.instance.extra_launch_args?.length ?? 0) > 0)
const javaArgs = ref(
(props.instance.extra_launch_args ?? globalSettings.extra_launch_args).join(' '),
)
const overrideEnvVars = ref(props.instance.custom_env_vars?.length !== undefined)
const overrideEnvVars = ref((props.instance.custom_env_vars?.length ?? 0) > 0)
const envVars = ref(
(props.instance.custom_env_vars ?? globalSettings.custom_env_vars)
.map((x) => x.join('='))
@@ -42,36 +48,23 @@ const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) a
}
const editProfileObject = computed(() => {
const editProfile: {
java_path?: string
extra_launch_args?: string[]
custom_env_vars?: string[][]
memory?: MemorySettings
} = {}
if (overrideJavaInstall.value) {
if (javaInstall.value.path !== '') {
editProfile.java_path = javaInstall.value.path.replace('java.exe', 'javaw.exe')
}
return {
java_path:
overrideJavaInstall.value && javaInstall.value.path !== ''
? javaInstall.value.path.replace('java.exe', 'javaw.exe')
: null,
extra_launch_args: overrideJavaArgs.value
? javaArgs.value.trim().split(/\s+/).filter(Boolean)
: null,
custom_env_vars: overrideEnvVars.value
? envVars.value
.trim()
.split(/\s+/)
.filter(Boolean)
.map((x) => x.split('=').filter(Boolean))
: null,
memory: overrideMemorySettings.value ? memory.value : null,
}
if (overrideJavaArgs.value) {
editProfile.extra_launch_args = javaArgs.value.trim().split(/\s+/).filter(Boolean)
}
if (overrideEnvVars.value) {
editProfile.custom_env_vars = envVars.value
.trim()
.split(/\s+/)
.filter(Boolean)
.map((x) => x.split('=').filter(Boolean))
}
if (overrideMemorySettings.value) {
editProfile.memory = memory.value
}
return editProfile
})
watch(
@@ -169,27 +162,25 @@ const messages = defineMessages({
{{ formatMessage(messages.javaArguments) }}
</h2>
<Checkbox v-model="overrideJavaArgs" label="Custom java arguments" class="my-2" />
<input
<StyledInput
id="java-args"
v-model="javaArgs"
autocomplete="off"
:disabled="!overrideJavaArgs"
type="text"
class="w-full"
placeholder="Enter java arguments..."
wrapper-class="w-full"
/>
<h2 id="project-name" class="mt-4 mb-1 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.javaEnvironmentVariables) }}
</h2>
<Checkbox v-model="overrideEnvVars" label="Custom environment variables" class="mb-2" />
<input
<StyledInput
id="env-vars"
v-model="envVars"
autocomplete="off"
:disabled="!overrideEnvVars"
type="text"
class="w-full"
placeholder="Enter environmental variables..."
wrapper-class="w-full"
/>
</div>
</template>
@@ -1,6 +1,12 @@
<script setup lang="ts">
import { Checkbox, injectNotificationManager, Toggle } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import {
Checkbox,
defineMessages,
injectNotificationManager,
StyledInput,
Toggle,
useVIntl,
} from '@modrinth/ui'
import { computed, type Ref, ref, watch } from 'vue'
import { edit } from '@/helpers/profile'
@@ -26,20 +32,16 @@ const fullscreenSetting: Ref<boolean> = ref(
)
const editProfileObject = computed(() => {
const editProfile: {
force_fullscreen?: boolean
game_resolution?: [number, number]
} = {}
if (overrideWindowSettings.value) {
editProfile.force_fullscreen = fullscreenSetting.value
if (!fullscreenSetting.value) {
editProfile.game_resolution = resolution.value
if (!overrideWindowSettings.value) {
return {
force_fullscreen: null,
game_resolution: null,
}
}
return editProfile
return {
force_fullscreen: fullscreenSetting.value,
game_resolution: fullscreenSetting.value ? null : resolution.value,
}
})
watch(
@@ -95,14 +97,6 @@ const messages = defineMessages({
<Checkbox
v-model="overrideWindowSettings"
:label="formatMessage(messages.customWindowSettings)"
@update:model-value="
(value) => {
if (!value) {
resolution = globalSettings.game_resolution
fullscreenSetting = globalSettings.force_fullscreen
}
}
"
/>
<div class="mt-2 flex items-center gap-4 justify-between">
<div>
@@ -134,7 +128,7 @@ const messages = defineMessages({
{{ formatMessage(messages.widthDescription) }}
</p>
</div>
<input
<StyledInput
id="width"
v-model="resolution[0]"
autocomplete="off"
@@ -153,7 +147,7 @@ const messages = defineMessages({
{{ formatMessage(messages.heightDescription) }}
</p>
</div>
<input
<StyledInput
id="height"
v-model="resolution[1]"
autocomplete="off"
@@ -0,0 +1,184 @@
<script setup lang="ts">
import {
CheckIcon,
CopyIcon,
DropdownIcon,
LogInIcon,
MessagesSquareIcon,
WrenchIcon,
} from '@modrinth/assets'
import { Admonition, ButtonStyled, Collapsible, NewModal } from '@modrinth/ui'
import { computed, ref } from 'vue'
import { login as login_flow, set_default_user } from '@/helpers/auth.js'
import { handleSevereError } from '@/store/error.js'
import { type MinecraftAuthError, minecraftAuthErrors } from './minecraft-auth-errors'
const modal = ref<InstanceType<typeof NewModal>>()
const rawError = ref<string>('')
const matchedError = ref<MinecraftAuthError | null>(null)
const debugCollapsed = ref(true)
const copied = ref(false)
const loadingSignIn = ref(false)
function show(errorVal: { message?: string }) {
rawError.value = errorVal?.message ?? String(errorVal)
matchedError.value = minecraftAuthErrors.find((e) => rawError.value.includes(e.errorCode)) ?? null
debugCollapsed.value = true
modal.value?.show()
}
function hide() {
modal.value?.hide()
}
defineExpose({
show,
hide,
})
async function signInAgain() {
try {
loadingSignIn.value = true
const loggedIn = await login_flow()
if (loggedIn) {
await set_default_user(loggedIn.profile.id)
}
loadingSignIn.value = false
modal.value?.hide()
} catch (err) {
loadingSignIn.value = false
handleSevereError(err)
}
}
const debugInfo = computed(() => rawError.value || 'No error message.')
async function copyToClipboard(text: string) {
await navigator.clipboard.writeText(text)
copied.value = true
setTimeout(() => {
copied.value = false
}, 3000)
}
</script>
<template>
<NewModal ref="modal" header="Sign in Failed" :max-width="'548px'">
<div class="flex flex-col gap-6">
<Admonition
type="warning"
body=" We couldn't sign you into your Microsoft account. This may be due to account restrictions or
regional limitations."
>
</Admonition>
<!-- Matched error details -->
<div class="bg-surface-2 rounded-2xl p-4 px-5 flex flex-col gap-3">
<template v-if="matchedError">
<div class="flex flex-col gap-1.5">
<h3 class="text-base font-bold m-0">What we think happened</h3>
<p class="text-sm text-secondary m-0">
{{ matchedError.whatHappened }}
</p>
</div>
<div class="flex flex-col gap-1.5">
<h3 class="text-base font-bold m-0">How to fix it</h3>
<ol class="list-none flex flex-col gap-2 m-0 pl-0">
<li
v-for="(step, index) in matchedError.stepsToFix"
:key="index"
class="flex items-baseline gap-2"
>
<span
class="inline-flex items-center justify-center shrink-0 w-5 h-5 rounded-full bg-surface-4 border border-solid border-surface-5 text-xs font-medium"
>
{{ index + 1 }}
</span>
<!-- eslint-disable-next-line vue/no-v-html -->
<span
class="text-sm [&_a]:text-info [&_a]:font-medium [&_a]:underline"
v-html="step"
/>
</li>
</ol>
</div>
</template>
<template v-else>
<div class="flex flex-col gap-1.5">
<h3 class="text-base font-bold m-0">Unknown error</h3>
<p class="text-sm text-secondary m-0">
We dont recognize this error and cant recommend specific steps to resolve it.
</p>
<p class="text-sm text-secondary m-0">
Try visiting
<a
class="text-info font-medium underline hover:underline"
href="https://www.minecraft.net/en-us/login"
>Minecraft Login</a
>
and signing in, as it may prompt you with the necessary steps. You can also contact
support and we can look into it further.
</p>
</div>
</template>
</div>
<!-- Action buttons -->
<div class="flex items-center gap-2">
<ButtonStyled>
<a href="https://support.modrinth.com" class="!w-full" @click="modal?.hide()">
<MessagesSquareIcon /> Contact support
</a>
</ButtonStyled>
<ButtonStyled color="brand">
<button :disabled="loadingSignIn" class="!w-full" @click="signInAgain">
<LogInIcon /> Sign in again
</button>
</ButtonStyled>
</div>
<div class="flex flex-col gap-2">
<div class="w-full h-[1px] bg-surface-5"></div>
<!-- Debug info -->
<div class="overflow-clip">
<button
class="flex items-center justify-between w-full bg-transparent border-0 py-4 cursor-pointer"
@click="debugCollapsed = !debugCollapsed"
>
<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': !debugCollapsed }"
/>
</button>
<Collapsible :collapsed="debugCollapsed">
<div class="p-3 bg-surface-2 rounded-2xl text-xs flex items-start">
<div class="m-0 p-0 rounded-none bg-transparent text-sm font-mono">
{{ 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>
</div>
</NewModal>
</template>
@@ -0,0 +1,90 @@
export interface MinecraftAuthError {
errorCode: string
whatHappened: string
stepsToFix: string[]
}
export const minecraftAuthErrors: MinecraftAuthError[] = [
{
errorCode: '2148916222',
whatHappened:
'Your Minecraft/Xbox Live account requires age verification to comply with UK regulations. You must complete this before signing in.',
stepsToFix: [
'Go to the <a href="https://www.minecraft.net/en-us/login">Minecraft Login</a> page and sign in',
'Follow the instructions to verify your age',
'Once verified, try signing in again',
'For additional help, visit <a href="https://support.xbox.com/en-GB/help/family-online-safety/online-safety/UK-age-verification">UK age verification on Xbox</a>',
],
},
{
errorCode: '2148916233',
whatHappened: "This account doesn't have an Xbox profile set up or doesn't own Minecraft.",
stepsToFix: [
'Make sure Minecraft is purchased on this account',
'Visit <a href="https://www.minecraft.net/en-us/login">Minecraft Login</a> and sign in',
'Complete Xbox profile setup if prompted',
'Once finished, try signing in again',
],
},
{
errorCode: '2148916235',
whatHappened: "Xbox Live isn't available in your region, so sign-in is blocked.",
stepsToFix: [
'Xbox services must be supported in your country before you can sign in',
'Check <a href="https://www.xbox.com/en-US/regions">Xbox Availability</a> for supported regions',
],
},
{
errorCode: '2148916236',
whatHappened: 'This account requires adult verification under South Korean regulations.',
stepsToFix: [
'Visit <a href="https://www.xbox.com">Xbox</a> and sign in',
'Complete the identity verification process',
'Once finished, try signing in again',
],
},
{
errorCode: '2148916237',
whatHappened: 'This account requires adult verification under South Korean regulations.',
stepsToFix: [
'Visit <a href="https://www.xbox.com">Xbox</a> and sign in',
'Complete the identity verification process',
'Once finished, try signing in again',
],
},
{
errorCode: '2148916238',
whatHappened: 'This account is underage and not linked to a Microsoft family group.',
stepsToFix: [
'Review the <a href="https://help.minecraft.net/hc/en-us/articles/4408968616077">Family Setup Guide</a>',
'Join or create a family group as instructed',
'Once finished, try signing in again',
],
},
{
errorCode: '2148916227',
whatHappened: 'This account was suspended for violating Xbox Community Standards.',
stepsToFix: [
'Visit <a href="https://support.xbox.com">Xbox Support</a> and review the enforcement details',
'Submit an appeal if one is available',
],
},
{
errorCode: '2148916229',
whatHappened: "This account is restricted and doesn't have permission to play online.",
stepsToFix: [
'Have a guardian sign in to <a href="https://account.microsoft.com/family/">Microsoft Family</a>',
'Update online play permissions',
'Once finished, try signing in again',
],
},
{
errorCode: '2148916234',
whatHappened: "This account hasn't accepted Xbox's Terms of Service.",
stepsToFix: [
'Visit <a href="https://www.xbox.com">Xbox</a> and sign in',
'Accept the Terms if prompted',
'Once finished, try signing in again',
],
},
]
@@ -3,16 +3,23 @@ import {
CoffeeIcon,
GameIcon,
GaugeIcon,
LanguagesIcon,
ModrinthIcon,
PaintbrushIcon,
ReportIcon,
SettingsIcon,
ShieldIcon,
} from '@modrinth/assets'
import { ProgressBar, TabbedModal } from '@modrinth/ui'
import {
commonMessages,
defineMessage,
defineMessages,
ProgressBar,
TabbedModal,
useVIntl,
} from '@modrinth/ui'
import { getVersion } from '@tauri-apps/api/app'
import { platform as getOsPlatform, version as getOsVersion } from '@tauri-apps/plugin-os'
import { defineMessage, defineMessages, useVIntl } from '@vintl/vintl'
import { computed, ref, watch } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
@@ -20,6 +27,7 @@ import AppearanceSettings from '@/components/ui/settings/AppearanceSettings.vue'
import DefaultInstanceSettings from '@/components/ui/settings/DefaultInstanceSettings.vue'
import FeatureFlagSettings from '@/components/ui/settings/FeatureFlagSettings.vue'
import JavaSettings from '@/components/ui/settings/JavaSettings.vue'
import LanguageSettings from '@/components/ui/settings/LanguageSettings.vue'
import PrivacySettings from '@/components/ui/settings/PrivacySettings.vue'
import ResourceManagementSettings from '@/components/ui/settings/ResourceManagementSettings.vue'
import { get, set } from '@/helpers/settings.ts'
@@ -46,6 +54,15 @@ const tabs = [
icon: PaintbrushIcon,
content: AppearanceSettings,
},
{
name: defineMessage({
id: 'app.settings.tabs.language',
defaultMessage: 'Language',
}),
icon: LanguagesIcon,
content: LanguageSettings,
badge: commonMessages.beta,
},
{
name: defineMessage({
id: 'app.settings.tabs.privacy',
@@ -0,0 +1,305 @@
<template>
<NewModal ref="modal" :header="formatMessage(messages.installToPlay)" :closable="true">
<div v-if="requiredContentProject" class="flex flex-col gap-6 max-w-[500px]">
<Admonition type="info" :header="formatMessage(messages.contentRequired)">
{{ formatMessage(messages.serverRequiresMods) }}
</Admonition>
<div class="flex flex-col gap-1">
<div class="flex justify-between items-center">
<span class="font-semibold text-contrast">{{
formatMessage(messages.requiredModpack)
}}</span>
<ButtonStyled type="transparent">
<button @click="openViewContents">
<EyeIcon />
{{ formatMessage(messages.viewContents) }}
</button>
</ButtonStyled>
</div>
<div class="flex items-center gap-3 rounded-xl bg-surface-2 p-3">
<Avatar
:src="requiredContentProject.icon_url"
:alt="requiredContentProject.title"
size="48px"
/>
<div class="flex flex-col gap-0.5">
<span class="font-semibold text-contrast">
<template v-if="usingCustomModpack">
{{ modpackVersion.name }}
</template>
<template v-else>
{{ requiredContentProject.title }}
</template>
</span>
<span class="text-sm text-secondary">
{{ loaderDisplay }} {{ requiredContentProject.game_versions?.[0] }}
<template v-if="modCount">
· {{ formatMessage(messages.modCount, { count: modCount }) }}
</template>
</span>
</div>
</div>
</div>
</div>
<template #actions>
<div class="flex justify-end gap-2">
<ButtonStyled>
<button @click="handleDecline">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand">
<button @click="handleAccept">
<DownloadIcon />
{{ formatMessage(messages.installButton) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
<ModpackContentModal
ref="modpackContentModal"
:modpack-name="project?.title ?? ''"
:modpack-icon-url="project?.icon_url ?? undefined"
/>
</template>
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import { DownloadIcon, EyeIcon, XIcon } from '@modrinth/assets'
import {
Admonition,
Avatar,
ButtonStyled,
commonMessages,
defineMessages,
formatLoader,
ModpackContentModal,
NewModal,
useVIntl,
} from '@modrinth/ui'
import { computed, ref } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads'
import {
get_organization,
get_project,
get_project_many,
get_team,
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'
const modal = ref<InstanceType<typeof NewModal>>()
const modpackVersionId = ref<string | null>(null)
const modpackVersion = ref<any>(null)
const project = ref<any>(null)
const requiredContentProject = ref<any>(null)
const organization = ref<any>(null)
const teamMembers = ref<any[]>([])
const onInstallComplete = ref<() => void>(() => {})
const { formatMessage } = useVIntl()
const installStore = useInstall()
const usingCustomModpack = computed(() => {
return requiredContentProject.value?.id === project.value?.id
})
const sharedBy = computed(() => {
if (organization.value) {
return {
name: organization.value.name,
icon_url: organization.value.icon_url,
}
}
if (teamMembers.value?.length) {
const owner = teamMembers.value.find((member: { is_owner: boolean }) => member.is_owner)
if (owner) {
return {
name: owner.user.username,
icon_url: owner.user.avatar_url,
}
}
}
return null
})
const loaderDisplay = computed(() => {
const loader = requiredContentProject.value?.loaders?.[0]
if (!loader) return ''
return formatLoader(formatMessage, loader)
})
const modCount = computed(() => modpackVersion.value?.dependencies?.length)
async function fetchData(versionId: string) {
// cache is making version null for some reason so bypassing for now
modpackVersion.value = await get_version(versionId, 'bypass')
if (modpackVersion.value?.project_id) {
requiredContentProject.value = await get_project(modpackVersion.value.project_id, 'bypass')
}
if (project.value?.organization) {
organization.value = await get_organization(project.value.organization, 'bypass')
} else if (project.value?.team_id) {
teamMembers.value = await get_team(project.value.team_id, 'bypass')
}
}
async function handleAccept() {
hide()
const serverProjectId = project.value.id
installStore.startInstallingServer(serverProjectId)
try {
await installServerProject(serverProjectId)
onInstallComplete.value()
} catch (error) {
console.error('Failed to install server project from InstallToPlayModal:', error)
} finally {
installStore.stopInstallingServer(serverProjectId)
}
}
function handleDecline() {
hide()
}
const modpackContentModal = ref<InstanceType<typeof ModpackContentModal>>()
async function openViewContents() {
modpackContentModal.value?.showLoading()
try {
// Ensure version data is available — the useQuery may not have resolved yet
const versionId = modpackVersionId.value
const version =
modpackVersion.value ?? (versionId ? await get_version(versionId, 'must_revalidate') : null)
const deps = version?.dependencies ?? []
const projectIds = deps
.map((d: { project_id?: string }) => d.project_id)
.filter((id: string | undefined): id is string => !!id)
const versionIds = deps
.map((d: { version_id?: string }) => d.version_id)
.filter((id: string | undefined): id is string => !!id)
const projects: Labrinth.Projects.v2.Project[] =
projectIds.length > 0 ? await get_project_many(projectIds, 'must_revalidate') : []
const versions: Labrinth.Versions.v2.Version[] =
versionIds.length > 0 ? await get_version_many(versionIds, 'must_revalidate') : []
const projectMap = new Map(projects.map((p: any) => [p.id, p]))
const contentItems: ContentItem[] = deps.map((dep: any): ContentItem => {
const depProject = dep.project_id ? projectMap.get(dep.project_id) : null
const depVersion = dep.version_id ? versions.find((v: any) => v.id === dep.version_id) : null
return {
file_name: dep.file_name ?? depProject?.title ?? 'Unknown',
project_type: depProject?.project_type ?? 'mod',
has_update: false,
update_version_id: null,
project: {
id: depProject?.id ?? dep.project_id ?? dep.file_name ?? 'unknown',
slug: depProject?.slug ?? dep.project_id ?? 'unknown',
title: depProject?.title ?? dep.file_name ?? 'Unknown',
icon_url: depProject?.icon_url ?? null,
},
...(depVersion
? {
version: {
id: depVersion.id,
file_name: depVersion.files?.[0]?.filename ?? dep.file_name,
version_number: depVersion.version_number ?? undefined,
date_published: depVersion.date_published ?? undefined,
},
}
: {}),
}
})
modpackContentModal.value?.show(contentItems)
} catch (err) {
console.error('Failed to load modpack contents:', err)
modpackContentModal.value?.show([])
}
}
async function show(
projectVal: Labrinth.Projects.v3.Project,
modpackVersionIdVal: string | null = null,
callback: () => void = () => {},
e?: MouseEvent,
) {
project.value = projectVal
modpackVersionId.value = modpackVersionIdVal
modpackVersion.value = null
requiredContentProject.value = null
organization.value = null
teamMembers.value = []
onInstallComplete.value = callback
if (modpackVersionIdVal) await fetchData(modpackVersionIdVal)
hide_ads_window()
modal.value?.show(e)
}
function hide() {
modal.value?.hide()
show_ads_window()
}
const messages = defineMessages({
installToPlay: {
id: 'app.modal.install-to-play.header',
defaultMessage: 'Install to play',
},
sharedServerInstance: {
id: 'app.modal.install-to-play.shared-server-instance',
defaultMessage: 'Shared server instance',
},
contentRequired: {
id: 'app.modal.install-to-play.content-required',
defaultMessage: 'Content required',
},
serverRequiresMods: {
id: 'app.modal.install-to-play.server-requires-mods',
defaultMessage:
'This server requires mods to play. Click Install to set up the required files from Modrinth, then launch directly into the server.',
},
requiredModpack: {
id: 'app.modal.install-to-play.required-modpack',
defaultMessage: 'Required modpack',
},
sharedInstance: {
id: 'app.modal.install-to-play.shared-instance',
defaultMessage: 'Shared instance',
},
modCount: {
id: 'app.modal.install-to-play.mod-count',
defaultMessage: '{count, plural, one {# mod} other {# mods}}',
},
installButton: {
id: 'app.modal.install-to-play.install-button',
defaultMessage: 'Install',
},
viewContents: {
id: 'app.modal.install-to-play.view-contents',
defaultMessage: 'View contents',
},
})
defineExpose({ show, hide })
</script>
@@ -7,10 +7,16 @@ import {
MonitorIcon,
WrenchIcon,
} from '@modrinth/assets'
import { Avatar, TabbedModal, type TabbedModalTab } from '@modrinth/ui'
import {
Avatar,
commonMessages,
defineMessage,
TabbedModal,
type TabbedModalTab,
useVIntl,
} from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { defineMessage, useVIntl } from '@vintl/vintl'
import { ref } from 'vue'
import { computed, ref, watch } from 'vue'
import GeneralSettings from '@/components/ui/instance_settings/GeneralSettings.vue'
import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
@@ -18,6 +24,7 @@ import InstallationSettings from '@/components/ui/instance_settings/Installation
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 type { InstanceSettingsTabProps } from '../../../helpers/types'
@@ -25,7 +32,26 @@ const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const tabs: TabbedModalTab<InstanceSettingsTabProps>[] = [
const isMinecraftServer = ref(false)
watch(
() => props.instance,
(instance) => {
isMinecraftServer.value = false
if (instance.linked_data?.project_id) {
get_project_v3(instance.linked_data.project_id, 'must_revalidate')
.then((project: any) => {
if (project?.minecraft_server != null) {
isMinecraftServer.value = true
}
})
.catch(() => {})
}
},
{ immediate: true },
)
const tabs = computed<TabbedModalTab<InstanceSettingsTabProps>[]>(() => [
{
name: defineMessage({
id: 'instance.settings.tabs.general',
@@ -66,7 +92,7 @@ const tabs: TabbedModalTab<InstanceSettingsTabProps>[] = [
icon: CodeIcon,
content: HooksSettings,
},
]
])
const modal = ref()
@@ -75,11 +101,6 @@ function show() {
}
defineExpose({ show })
const titleMessage = defineMessage({
id: 'instance.settings.title',
defaultMessage: 'Settings',
})
</script>
<template>
<ModalWrapper ref="modal">
@@ -91,10 +112,16 @@ const titleMessage = defineMessage({
:tint-by="props.instance.path"
/>
{{ instance.name }} <ChevronRightIcon />
<span class="font-extrabold text-contrast">{{ formatMessage(titleMessage) }}</span>
<span class="font-extrabold text-contrast">{{
formatMessage(commonMessages.settingsLabel)
}}</span>
</span>
</template>
<TabbedModal :tabs="tabs.map((tab) => ({ ...tab, props }))" />
<TabbedModal
:tabs="
tabs.map((tab) => ({ ...tab, props: { ...props, isMinecraftServer: isMinecraftServer } }))
"
/>
</ModalWrapper>
</template>
@@ -0,0 +1,447 @@
<template>
<NewModal
ref="modal"
: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">{{
formatMessage(messages.publishedDate, { date: 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>
</template>
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import {
DownloadIcon,
MinusIcon,
PlusIcon,
RefreshCwIcon,
ReportIcon,
XIcon,
} from '@modrinth/assets'
import {
Admonition,
ButtonStyled,
commonMessages,
defineMessages,
NewModal,
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'
type Dependency = Labrinth.Versions.v3.Dependency
type Version = Labrinth.Versions.v2.Version
interface BaseDiff {
project_id: string
project?: {
title: string
icon_url?: string
slug: string
}
currentVersionId?: string
newVersionId?: string
currentVersion?: Version
newVersion?: Version
fileName?: string
}
interface AddedDiff extends BaseDiff {
type: 'added'
newVersionId: string
}
interface RemovedDiff extends BaseDiff {
type: 'removed'
}
interface UpdatedDiff extends BaseDiff {
type: 'updated'
currentVersionId: string
newVersionId: string
}
type DependencyDiff = AddedDiff | RemovedDiff | UpdatedDiff
type ProjectInfo = {
id: string
title: string
icon_url?: string
slug: string
}
const { formatMessage } = useVIntl()
const installStore = useInstall()
const modal = ref<InstanceType<typeof NewModal>>()
const instance = ref<GameInstance | null>(null)
const onUpdateComplete = ref<() => void>(() => {})
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,
)
function getFilename(version?: Version): string | undefined {
return version?.files.find((f) => f.primary)?.filename
}
async function computeDependencyDiffs(
currentDeps: Dependency[],
latestDeps: Dependency[],
): Promise<DependencyDiff[]> {
console.log('Computing dependency diffs', { currentDeps, latestDeps })
// Separate deps with project_id from file_name-only deps
const currentWithProject = currentDeps.filter((d) => d.project_id)
const latestWithProject = latestDeps.filter((d) => d.project_id)
const currentFileOnly = currentDeps.filter((d) => !d.project_id && d.file_name)
const latestFileOnly = latestDeps.filter((d) => !d.project_id && d.file_name)
const currentByProject = new Map<string, Dependency>(
currentWithProject.map((d) => [d.project_id!, d]),
)
const latestByProject = new Map<string, Dependency>(
latestWithProject.map((d) => [d.project_id!, d]),
)
const currentFilenames = new Set(currentFileOnly.map((d) => d.file_name!))
const latestFilenames = new Set(latestFileOnly.map((d) => d.file_name!))
const diffs: DependencyDiff[] = []
// Find added and updated dependencies (by project_id)
latestByProject.forEach((latestDep, projectId) => {
const currentDep = currentByProject.get(projectId)
if (!currentDep && latestDep.version_id) {
diffs.push({ type: 'added', project_id: projectId, newVersionId: latestDep.version_id })
} else if (
currentDep?.version_id &&
latestDep?.version_id &&
currentDep?.version_id !== latestDep.version_id
) {
diffs.push({
type: 'updated',
project_id: projectId,
currentVersionId: currentDep.version_id,
newVersionId: latestDep.version_id,
})
}
})
// Find removed dependencies (by project_id)
currentByProject.forEach((currentDep, projectId) => {
if (!latestByProject.has(projectId)) {
diffs.push({
type: 'removed',
project_id: projectId,
currentVersionId: currentDep.version_id,
})
}
})
// Find added/removed file_name-only dependencies
// ideally in future, this should use the hash of the file instead of filename, but since version dependencies don't include file hashes, we'll use filename as a best effort approach
for (const fileName of latestFilenames) {
if (!currentFilenames.has(fileName)) {
diffs.push({ type: 'added', project_id: '', newVersionId: '' as string, fileName })
}
}
for (const fileName of currentFilenames) {
if (!latestFilenames.has(fileName)) {
diffs.push({ type: 'removed', project_id: '', fileName })
}
}
// Fetch projects and versions of diffs
const allProjectIds = [...new Set(diffs.map((d) => d.project_id).filter(Boolean))]
const allVersionIds = [
...new Set(
[...diffs.map((d) => d.newVersionId), ...diffs.map((d) => d.currentVersionId)].filter(
Boolean,
),
),
] as string[]
const [projects, versions] = await Promise.all([
get_project_many(allProjectIds, 'bypass'),
get_version_many(allVersionIds, 'bypass'),
])
const projectMap = new Map<string, ProjectInfo>(projects.map((p: ProjectInfo) => [p.id, p]))
const versionMap = new Map<string, Version>(versions.map((v: Version) => [v.id, v]))
const mappedDiffs = diffs
.map((diff) => {
const project = projectMap.get(diff.project_id)
return {
...diff,
project: project
? { title: project.title, icon_url: project.icon_url, slug: project.slug }
: undefined,
currentVersion: diff.currentVersionId ? versionMap.get(diff.currentVersionId) : undefined,
newVersion: diff.newVersionId ? versionMap.get(diff.newVersionId) : undefined,
}
})
.sort((a, b) => {
const typeOrder = { removed: 0, added: 1, updated: 2 }
const typeCompare = typeOrder[a.type] - typeOrder[b.type]
if (typeCompare !== 0) return typeCompare
const aDate = a.newVersion?.date_published || a.currentVersion?.date_published || ''
const bDate = b.newVersion?.date_published || b.currentVersion?.date_published || ''
return dayjs(bDate).valueOf() - dayjs(aDate).valueOf()
}).filter((d) => d.project || d.fileName) // filter out any diffs that couldn't be matched to a project or file
return mappedDiffs
}
async function checkUpdateAvailable(inst: GameInstance): Promise<DependencyDiff[] | null> {
if (!inst.linked_data) return null
try {
// For server projects, linked_data.project_id is the server project but
// linked_data.version_id references a content modpack version from a different project.
// Detect this by comparing the version's project_id with linked_data.project_id.
modpackVersion.value = await get_version(modpackVersionId.value, 'bypass')
const instanceModpackVersion = await get_version(inst.linked_data.version_id, 'bypass')
// Compute dependency diffs between current and latest version
if (instanceModpackVersion && modpackVersion.value) {
return await computeDependencyDiffs(
modpackVersion.value.dependencies || [],
instanceModpackVersion.dependencies || [],
)
}
} catch (error) {
console.error('Error checking for updates:', error)
return null
}
return null
}
watch(
() => instance.value,
async (newInstance) => {
if (!newInstance) return
const result = await checkUpdateAvailable(newInstance)
diffs.value = result || []
},
{ immediate: true, deep: true },
)
async function handleUpdate() {
hide()
const serverProjectId = instance.value?.linked_data?.project_id
if (serverProjectId) installStore.startInstallingServer(serverProjectId)
try {
if (modpackVersionId.value && instance.value) {
await update_managed_modrinth_version(instance.value.path, modpackVersionId.value)
onUpdateComplete.value()
}
} catch (error) {
console.error('Error updating instance:', error)
} finally {
if (serverProjectId) installStore.stopInstallingServer(serverProjectId)
}
}
function handleReport() {
if (instance.value?.linked_data?.project_id) {
openUrl(
`https://modrinth.com/report?item=project&itemID=${instance.value.linked_data.project_id}`,
)
}
}
function handleDecline() {
hide()
}
function show(
instanceVal: GameInstance,
modpackVersionIdVal: string | null = null,
callback: () => void = () => {},
e?: MouseEvent,
) {
instance.value = instanceVal
modpackVersionId.value = modpackVersionIdVal
onUpdateComplete.value = callback
hide_ads_window()
modal.value?.show(e)
}
function hide() {
modal.value?.hide()
}
const messages = defineMessages({
updateToPlay: {
id: 'app.modal.update-to-play.header',
defaultMessage: 'Update to play',
},
updateRequired: {
id: 'app.modal.update-to-play.update-required',
defaultMessage: 'Update required',
},
updateRequiredDescription: {
id: 'app.modal.update-to-play.update-required-description',
defaultMessage:
'An update is required to play {name}. Please update to the latest version to launch the game.',
},
publishedDate: {
id: 'app.modal.update-to-play.published-date',
defaultMessage: '{date, date, long}',
},
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(() => {
if (!instance.value?.linked_data) return false
return (
modpackVersionId.value != null &&
modpackVersionId.value !== instance.value.linked_data.version_id
)
})
defineExpose({ show, hide, hasUpdate })
</script>
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { injectNotificationManager, Slider, Toggle } from '@modrinth/ui'
import { injectNotificationManager, Slider, StyledInput, Toggle } from '@modrinth/ui'
import { ref, watch } from 'vue'
import useMemorySlider from '@/composables/useMemorySlider'
@@ -73,7 +73,7 @@ watch(
</p>
</div>
<input
<StyledInput
id="width"
v-model="settings.game_resolution[0]"
:disabled="settings.force_fullscreen"
@@ -91,13 +91,12 @@ watch(
</p>
</div>
<input
<StyledInput
id="height"
v-model="settings.game_resolution[1]"
:disabled="settings.force_fullscreen"
autocomplete="off"
type="number"
class="input"
placeholder="Enter height..."
/>
</div>
@@ -118,23 +117,23 @@ watch(
/>
<h2 class="mt-4 mb-2 text-lg font-extrabold text-contrast">Java arguments</h2>
<input
<StyledInput
id="java-args"
v-model="settings.launchArgs"
autocomplete="off"
type="text"
placeholder="Enter java arguments..."
class="w-full"
wrapper-class="w-full"
/>
<h2 class="mt-4 mb-2 text-lg font-extrabold text-contrast">Environmental variables</h2>
<input
<StyledInput
id="env-vars"
v-model="settings.envVars"
autocomplete="off"
type="text"
placeholder="Enter environmental variables..."
class="w-full"
wrapper-class="w-full"
/>
<hr class="mt-4 bg-button-border border-none h-[1px]" />
@@ -143,37 +142,37 @@ watch(
<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>
<input
<StyledInput
id="pre-launch"
v-model="settings.hooks.pre_launch"
autocomplete="off"
type="text"
placeholder="Enter pre-launch command..."
class="w-full"
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>
<input
<StyledInput
id="wrapper"
v-model="settings.hooks.wrapper"
autocomplete="off"
type="text"
placeholder="Enter wrapper command..."
class="w-full"
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>
<input
<StyledInput
id="post-exit"
v-model="settings.hooks.post_exit"
autocomplete="off"
type="text"
placeholder="Enter post-exit command..."
class="w-full"
wrapper-class="w-full"
/>
</div>
</template>
@@ -21,7 +21,7 @@ async function updateJavaVersion(version) {
}
</script>
<template>
<div v-for="(javaVersion, index) in [21, 17, 8]" :key="`java-${javaVersion}`">
<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>
@@ -0,0 +1,71 @@
<script setup lang="ts">
import {
Admonition,
AutoLink,
IntlFormatted,
LanguageSelector,
languageSelectorMessages,
LOCALES,
useVIntl,
} from '@modrinth/ui'
import { ref, watch } from 'vue'
import { get, set } from '@/helpers/settings.ts'
import i18n from '@/i18n.config'
const { formatMessage } = useVIntl()
const platform = formatMessage(languageSelectorMessages.platformApp)
const settings = ref(await get())
watch(
settings,
async () => {
await set(settings.value)
},
{ deep: true },
)
const $isChanging = ref(false)
async function onLocaleChange(newLocale: string) {
if (settings.value.locale === newLocale) return
$isChanging.value = true
try {
i18n.global.locale.value = newLocale
settings.value.locale = newLocale
} finally {
$isChanging.value = false
}
}
</script>
<template>
<h2 class="m-0 text-lg font-extrabold text-contrast">Language</h2>
<Admonition type="warning" class="mt-2 mb-4">
{{ formatMessage(languageSelectorMessages.languageWarning, { platform }) }}
</Admonition>
<p class="m-0 mb-4">
<IntlFormatted
:message-id="languageSelectorMessages.languagesDescription"
:values="{ platform }"
>
<template #~crowdin-link="{ children }">
<AutoLink to="https://translate.modrinth.com">
<component :is="() => children" />
</AutoLink>
</template>
</IntlFormatted>
</p>
<LanguageSelector
:current-locale="settings.locale"
:locales="LOCALES"
:on-locale-change="onLocaleChange"
:is-changing="$isChanging"
/>
</template>
@@ -1,6 +1,6 @@
<script setup>
import { BoxIcon, FolderSearchIcon, TrashIcon } from '@modrinth/assets'
import { Button, injectNotificationManager, Slider } from '@modrinth/ui'
import { Button, injectNotificationManager, Slider, StyledInput } from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { ref, watch } from 'vue'
@@ -65,13 +65,19 @@ async function findLauncherDir() {
</p>
<div class="m-1 my-2">
<div class="iconified-input w-full">
<BoxIcon />
<input id="appDir" v-model="settings.custom_dir" type="text" class="input" />
<Button class="r-btn" @click="findLauncherDir">
<FolderSearchIcon />
</Button>
</div>
<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>
<div>
@@ -15,10 +15,10 @@ import {
OverflowMenu,
SmartClickable,
useRelativeTime,
useVIntl,
} from '@modrinth/ui'
import { capitalizeString } from '@modrinth/utils'
import { convertFileSrc } from '@tauri-apps/api/core'
import { useVIntl } from '@vintl/vintl'
import type { Dayjs } from 'dayjs'
import dayjs from 'dayjs'
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
@@ -1,6 +1,8 @@
<script setup lang="ts">
import { LoaderCircleIcon } from '@modrinth/assets'
import type { GameVersion } from '@modrinth/ui'
import { GAME_MODES, HeadingLink, injectNotificationManager } from '@modrinth/ui'
import { platform } from '@tauri-apps/plugin-os'
import type { Dayjs } from 'dayjs'
import dayjs from 'dayjs'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
@@ -39,6 +41,7 @@ const props = defineProps<{
const theme = useTheming()
const jumpBackInItems = ref<JumpBackInItem[]>([])
const loading = ref(true)
const serverData = ref<Record<string, ServerData>>({})
const protocolVersions = ref<Record<string, ProtocolVersion | null>>({})
const gameVersions = ref<GameVersion[]>(await get_game_versions().catch(() => []))
@@ -46,6 +49,11 @@ const gameVersions = ref<GameVersion[]>(await get_game_versions().catch(() => []
const MIN_JUMP_BACK_IN = 3
const MAX_JUMP_BACK_IN = 6
const TWO_WEEKS_AGO = dayjs().subtract(14, 'day')
const MAX_LINUX_POPULATES = 3
// Track populate calls on Linux to prevent server ping spam
const isLinux = platform() === 'linux'
const linuxPopulateCount = ref(0)
type BaseJumpBackInItem = {
last_played: Dayjs
@@ -71,11 +79,19 @@ watch([() => props.recentInstances, () => showWorlds.value], async () => {
})
})
await populateJumpBackIn().catch(() => {
console.error('Failed to populate jump back in')
})
populateJumpBackIn()
.catch(() => {
console.error('Failed to populate jump back in')
})
.finally(() => {
loading.value = false
})
async function populateJumpBackIn() {
// On Linux, limit automatic populates to prevent server ping spam
if (isLinux && linuxPopulateCount.value >= MAX_LINUX_POPULATES) return
if (isLinux) linuxPopulateCount.value++
console.info('Repopulating jump back in...')
const worldItems: WorldJumpBackInItem[] = []
@@ -224,6 +240,7 @@ const checkProcesses = async () => {
onMounted(() => {
checkProcesses()
linuxPopulateCount.value = 0
})
onUnmounted(() => {
@@ -233,7 +250,15 @@ onUnmounted(() => {
</script>
<template>
<div v-if="jumpBackInItems.length > 0" class="flex flex-col gap-2">
<div v-if="loading" class="flex flex-col gap-2">
<span class="flex mt-1 mb-3 leading-none items-center gap-1 text-primary text-lg font-bold">
Jump back in
</span>
<div class="text-center py-4">
<LoaderCircleIcon class="mx-auto size-8 animate-spin text-contrast" />
</div>
</div>
<div v-else-if="jumpBackInItems.length > 0" class="flex flex-col gap-2">
<HeadingLink v-if="theme.getFeatureFlag('worlds_tab')" to="/worlds" class="mt-1">
Jump back in
</HeadingLink>
@@ -17,18 +17,19 @@ import {
UserIcon,
XIcon,
} from '@modrinth/assets'
import type { MessageDescriptor } from '@modrinth/ui'
import {
Avatar,
ButtonStyled,
commonMessages,
defineMessages,
OverflowMenu,
SmartClickable,
useRelativeTime,
useVIntl,
} from '@modrinth/ui'
import { formatNumber, getPingLevel } from '@modrinth/utils'
import { convertFileSrc } from '@tauri-apps/api/core'
import type { MessageDescriptor } from '@vintl/vintl'
import { defineMessages, useVIntl } from '@vintl/vintl'
import dayjs from 'dayjs'
import { Tooltip } from 'floating-vue'
import type { Component } from 'vue'
@@ -43,7 +44,7 @@ import type {
SingleplayerWorld,
World,
} from '@/helpers/worlds.ts'
import { getWorldIdentifier, set_world_display_status } from '@/helpers/worlds.ts'
import { getWorldIdentifier, isLinkedWorld, set_world_display_status } from '@/helpers/worlds.ts'
const { formatMessage } = useVIntl()
const formatRelativeTime = useRelativeTime()
@@ -116,6 +117,7 @@ const serverIncompatible = computed(
)
const locked = computed(() => props.world.type === 'singleplayer' && props.world.locked)
const linked = computed(() => isLinkedWorld(props.world))
const messages = defineMessages({
hardcore: {
@@ -170,6 +172,10 @@ const messages = defineMessages({
id: 'instance.worlds.dont_show_on_home',
defaultMessage: `Don't show on Home`,
},
linkedServer: {
id: 'instance.worlds.linked_server',
defaultMessage: 'Managed by server project',
},
})
</script>
<template>
@@ -188,7 +194,9 @@ const messages = defineMessages({
>
<Avatar
:src="
world.type === 'server' && serverStatus ? serverStatus.favicon ?? world.icon : world.icon
world.type === 'server' && serverStatus
? (serverStatus.favicon ?? world.icon)
: world.icon
"
size="48px"
/>
@@ -393,8 +401,12 @@ const messages = defineMessages({
id: 'edit',
action: () => emit('edit'),
shown: !instancePath,
disabled: locked,
tooltip: locked ? formatMessage(messages.worldInUse) : undefined,
disabled: locked || linked,
tooltip: locked
? formatMessage(messages.worldInUse)
: linked
? formatMessage(messages.linkedServer)
: undefined,
},
{
id: 'open-folder',
@@ -429,8 +441,12 @@ const messages = defineMessages({
hoverFilled: true,
action: () => emit('delete'),
shown: !instancePath,
disabled: locked,
tooltip: locked ? formatMessage(messages.worldInUse) : undefined,
disabled: locked || linked,
tooltip: locked
? formatMessage(messages.worldInUse)
: linked
? formatMessage(messages.linkedServer)
: undefined,
},
]"
>
@@ -1,7 +1,12 @@
<script setup lang="ts">
import { PlayIcon, PlusIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, commonMessages, injectNotificationManager } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import {
ButtonStyled,
commonMessages,
defineMessages,
injectNotificationManager,
useVIntl,
} from '@modrinth/ui'
import { ref } from 'vue'
import InstanceModalTitlePrefix from '@/components/ui/modal/InstanceModalTitlePrefix.vue'
@@ -1,7 +1,12 @@
<script setup lang="ts">
import { SaveIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, commonMessages, injectNotificationManager } from '@modrinth/ui'
import { defineMessage, useVIntl } from '@vintl/vintl'
import {
ButtonStyled,
commonMessages,
defineMessage,
injectNotificationManager,
useVIntl,
} from '@modrinth/ui'
import { computed, ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
@@ -1,7 +1,14 @@
<script setup lang="ts">
import { ChevronRightIcon, SaveIcon, UndoIcon, XIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled, commonMessages, injectNotificationManager } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import {
Avatar,
ButtonStyled,
commonMessages,
defineMessages,
injectNotificationManager,
StyledInput,
useVIntl,
} from '@modrinth/ui'
import { computed, ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
@@ -97,12 +104,11 @@ const messages = defineMessages({
<h2 class="text-lg font-extrabold text-contrast mt-0 mb-1">
{{ formatMessage(messages.name) }}
</h2>
<input
<StyledInput
v-model="name"
type="text"
:placeholder="formatMessage(messages.placeholderName)"
class="w-full"
autocomplete="off"
wrapper-class="w-full"
/>
<HideFromHomeOption v-model="hideFromHome" class="mt-3" />
</div>
@@ -1,6 +1,5 @@
<script setup lang="ts">
import { Checkbox } from '@modrinth/ui'
import { defineMessage, useVIntl } from '@vintl/vintl'
import { Checkbox, defineMessage, useVIntl } from '@modrinth/ui'
import { computed } from 'vue'
const { formatMessage } = useVIntl()
@@ -1,6 +1,11 @@
<script setup lang="ts">
import { Combobox } from '@modrinth/ui'
import { defineMessages, type MessageDescriptor, useVIntl } from '@vintl/vintl'
import {
Combobox,
defineMessages,
type MessageDescriptor,
StyledInput,
useVIntl,
} from '@modrinth/ui'
import type { ServerPackStatus } from '@/helpers/worlds.ts'
@@ -53,22 +58,20 @@ defineExpose({ resourcePackOptions })
<h2 class="text-lg font-extrabold text-contrast mt-0 mb-1">
{{ formatMessage(messages.name) }}
</h2>
<input
<StyledInput
v-model="name"
type="text"
:placeholder="formatMessage(messages.placeholderName)"
class="w-full"
autocomplete="off"
wrapper-class="w-full"
/>
<h2 class="text-lg font-extrabold text-contrast mt-3 mb-1">
{{ formatMessage(messages.address) }}
</h2>
<input
<StyledInput
v-model="address"
type="text"
placeholder="example.modrinth.gg"
class="w-full"
autocomplete="off"
wrapper-class="w-full"
/>
<h2 class="text-lg font-extrabold text-contrast mt-3 mb-1">
{{ formatMessage(messages.resourcePack) }}
@@ -1,24 +0,0 @@
import { posthog } from 'posthog-js'
export const initAnalytics = () => {
posthog.init('phc_9Iqi6lFs9sr5BSqh9RRNRSJ0mATS9PSgirDiX3iOYJ', {
persistence: 'localStorage',
api_host: 'https://posthog.modrinth.com',
})
}
export const debugAnalytics = () => {
posthog.debug()
}
export const optOutAnalytics = () => {
posthog.opt_out_capturing()
}
export const optInAnalytics = () => {
posthog.opt_in_capturing()
}
export const trackEvent = (eventName, properties) => {
posthog.capture(eventName, properties)
}
@@ -0,0 +1,80 @@
import { posthog } from 'posthog-js'
interface InstanceProperties {
loader: string
game_version: string
}
interface ProjectProperties extends InstanceProperties {
id: string
project_type: string
}
type AnalyticsEventMap = {
Launched: { version: string; dev: boolean; onboarded: boolean }
PageView: { path: string; fromPath: string; failed: unknown }
InstanceCreate: { source: string }
InstanceCreateStart: { source: string }
InstancePlay: InstanceProperties & { source: string }
InstanceStop: Partial<InstanceProperties> & { source?: string }
InstanceDuplicate: InstanceProperties
InstanceRepair: InstanceProperties
InstanceSetIcon: Record<string, never>
InstanceRemoveIcon: Record<string, never>
InstanceUpdateAll: InstanceProperties & { count: number; selected: boolean }
InstanceProjectUpdate: InstanceProperties & { id: string; name: string; project_type: string }
InstanceProjectDisable: InstanceProperties & {
id: string
name: string
project_type: string
disabled: boolean
}
InstanceProjectRemove: InstanceProperties & { id: string; name: string; project_type: string }
ProjectInstall: ProjectProperties & { version_id: string; title: string; source: string }
ProjectInstallStart: { source: string }
PackInstall: { id: string; version_id: string; title: string; source: string }
PackInstallStart: Record<string, never>
AccountLogIn: { source?: string }
AccountLogOut: Record<string, never>
JavaTest: { path: string; success: boolean }
JavaManualSelect: { version: string }
JavaAutoDetect: { path: string; version: string }
}
export type AnalyticsEvent = keyof AnalyticsEventMap
let initialized = false
export const initAnalytics = () => {
if (initialized) return
posthog.init('phc_9Iqi6lFs9sr5BSqh9RRNRSJ0mATS9PSgirDiX3iOYJ', {
persistence: 'localStorage',
api_host: 'https://posthog.modrinth.com',
})
initialized = true
}
export const debugAnalytics = () => {
if (!initialized) return
posthog.debug()
}
export const optOutAnalytics = () => {
if (!initialized) return
posthog.opt_out_capturing()
}
export const optInAnalytics = () => {
initAnalytics()
posthog.opt_in_capturing()
}
type OptionalArgs<T> = Record<string, never> extends T ? [properties?: T] : [properties: T]
export const trackEvent = <E extends AnalyticsEvent>(
eventName: E,
...args: OptionalArgs<AnalyticsEventMap[E]>
) => {
if (!initialized) return
posthog.capture(eventName, args[0])
}
+16
View File
@@ -8,6 +8,14 @@ export async function get_project_many(ids, cacheBehaviour) {
return await invoke('plugin:cache|get_project_many', { ids, cacheBehaviour })
}
export async function get_project_v3(id, cacheBehaviour) {
return await invoke('plugin:cache|get_project_v3', { id, cacheBehaviour })
}
export async function get_project_v3_many(ids, cacheBehaviour) {
return await invoke('plugin:cache|get_project_v3_many', { ids, cacheBehaviour })
}
export async function get_version(id, cacheBehaviour) {
return await invoke('plugin:cache|get_version', { id, cacheBehaviour })
}
@@ -48,6 +56,14 @@ export async function get_search_results_many(ids, cacheBehaviour) {
return await invoke('plugin:cache|get_search_results_many', { ids, cacheBehaviour })
}
export async function get_search_results_v3(id, cacheBehaviour) {
return await invoke('plugin:cache|get_search_results_v3', { id, cacheBehaviour })
}
export async function get_search_results_v3_many(ids, cacheBehaviour) {
return await invoke('plugin:cache|get_search_results_v3_many', { ids, cacheBehaviour })
}
export async function purge_cache_types(cacheTypes) {
return await invoke('plugin:cache|purge_cache_types', { cacheTypes })
}
+4 -3
View File
@@ -18,7 +18,7 @@ import { install_to_existing_profile } from '@/helpers/pack.js'
- 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) {
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', {
@@ -28,6 +28,7 @@ export async function create(name, gameVersion, modloader, loaderVersion, icon,
loaderVersion,
icon,
skipInstall,
linkedData,
})
}
@@ -174,8 +175,8 @@ export async function get_pack_export_candidates(profilePath) {
// Run Minecraft using a pathed profile
// Returns PID of child
export async function run(path) {
return await invoke('plugin:profile|profile_run', { path })
export async function run(path, serverAddress = null) {
return await invoke('plugin:profile|profile_run', { path, serverAddress })
}
export async function kill(path) {
@@ -36,6 +36,7 @@ export type AppSettings = {
max_concurrent_writes: number
theme: ColorTheme
locale: string
default_page: 'home' | 'library'
collapsed_navigation: boolean
hide_nametag_skins_page: boolean
+1
View File
@@ -139,4 +139,5 @@ type AppSettings = {
export type InstanceSettingsTabProps = {
instance: GameInstance
offline?: boolean
isMinecraftServer?: boolean
}
+13 -1
View File
@@ -30,6 +30,7 @@ export type ServerWorld = BaseWorld & {
index: number
address: string
pack_status: ServerPackStatus
linked_project_id?: string
}
export type World = SingleplayerWorld | ServerWorld
@@ -140,8 +141,15 @@ export async function add_server_to_profile(
name: string,
address: string,
packStatus: ServerPackStatus,
linkedProjectId?: string,
): Promise<number> {
return await invoke('plugin:worlds|add_server_to_profile', { path, name, address, packStatus })
return await invoke('plugin:worlds|add_server_to_profile', {
path,
name,
address,
packStatus,
linkedProjectId,
})
}
export async function edit_server_in_profile(
@@ -212,6 +220,10 @@ export function isServerWorld(world: World): world is ServerWorld {
return world.type === 'server'
}
export function isLinkedWorld(world: World): boolean {
return world.type === 'server' && !!world.linked_project_id
}
export async function refreshServerData(
serverData: ServerData,
protocolVersion: ProtocolVersion | null,
+18
View File
@@ -0,0 +1,18 @@
import { buildLocaleMessages, createMessageCompiler, type CrowdinMessages } from '@modrinth/ui'
import { createI18n } from 'vue-i18n'
const localeModules = import.meta.glob<{ default: CrowdinMessages }>('./locales/*/index.json', {
eager: true,
})
const i18n = createI18n({
legacy: false,
locale: 'en-US',
fallbackLocale: 'en-US',
messageCompiler: createMessageCompiler(),
missingWarn: false,
fallbackWarn: false,
messages: buildLocaleMessages(localeModules),
})
export default i18n
@@ -1,305 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "Ontwikkelaarmodus geaktiveer."
},
"app.settings.downloading": {
"message": "Aflaai v{version}"
},
"app.settings.tabs.appearance": {
"message": "Voorkoms"
},
"app.settings.tabs.default-instance-options": {
"message": "Verstek instansie opsies"
},
"app.settings.tabs.feature-flags": {
"message": "Kenmerk vlae"
},
"app.settings.tabs.java-installations": {
"message": "Java installasies"
},
"app.settings.tabs.privacy": {
"message": "Privaatheid"
},
"app.settings.tabs.resource-management": {
"message": "Hulpbronbestuur"
},
"app.update-toast.body": {
"message": "Modrinth App v{version} is gereed om te installeer! Herlaai nou werk, of outomaties wanneer jy naby Modrinth App."
},
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version} klaar afgelaai. Herlaai nou werk, of outomaties wanneer jy naby Modrinth App."
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} is nou beskikbaar! Aangesien jy op'n gemeterde netwerk, ons het nie outomaties laai dit."
},
"app.update-toast.changelog": {
"message": "Alle veranderinge"
},
"app.update-toast.download": {
"message": "Laai ({size})"
},
"app.update-toast.downloading": {
"message": "Aflaai..."
},
"app.update-toast.reload": {
"message": "Herlaai"
},
"app.update-toast.title": {
"message": "Die opdatering is beskikbaar"
},
"app.update-toast.title.download-complete": {
"message": "Aflaai voltooi"
},
"app.update.complete-toast.text": {
"message": "Klik hier om die veranderinge te sien."
},
"app.update.complete-toast.title": {
"message": "Weergawe {version} is suksesvol geïnstalleer!"
},
"app.update.download-update": {
"message": "Laai die opdatering af"
},
"app.update.downloading-update": {
"message": "Laai tans opdatering af ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Herlaai om opdatering te installeer"
},
"instance.add-server.add-and-play": {
"message": "voeg by en speel"
},
"instance.add-server.add-server": {
"message": "bediener byvoeg"
},
"instance.add-server.resource-pack.disabled": {
"message": "Gestrem"
},
"instance.add-server.resource-pack.enabled": {
"message": "aangeskakel"
},
"instance.add-server.resource-pack.prompt": {
"message": "spoed"
},
"instance.add-server.title": {
"message": "voeg 'n bediener by"
},
"instance.edit-server.title": {
"message": "wysig bediener"
},
"instance.edit-world.hide-from-home": {
"message": "versteek van die tuisblad"
},
"instance.edit-world.name": {
"message": "Naam"
},
"instance.edit-world.placeholder-name": {
"message": "Minecraft Wêreld"
},
"instance.edit-world.reset-icon": {
"message": "herstel ikoon"
},
"instance.edit-world.title": {
"message": "wêreld wysig"
},
"instance.filter.disabled": {
"message": "gestremde projekte"
},
"instance.filter.updates-available": {
"message": "opdaterings beskikbaar"
},
"instance.server-modal.address": {
"message": "adres"
},
"instance.server-modal.name": {
"message": "Naam"
},
"instance.server-modal.placeholder-name": {
"message": "Minecraft-bediener"
},
"instance.server-modal.resource-pack": {
"message": "Hulpbronpakket"
},
"instance.settings.tabs.general": {
"message": "Algemeen"
},
"instance.settings.tabs.general.delete": {
"message": "verwyder instansie"
},
"instance.settings.tabs.general.delete.button": {
"message": "verwyder instansie"
},
"instance.settings.tabs.general.delete.description": {
"message": "Vee 'n instansie permanent van jou toestel uit, insluitend jou wêrelde, konfigurasies en alle geïnstalleerde inhoud. Wees versigtig, want sodra jy 'n instansie verwyder het, is daar geen manier om dit te herstel nie."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Vee tans uit …"
},
"instance.settings.tabs.general.duplicate-button": {
"message": "Duplikaat"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "Kan nie dupliseer tydens installasie nie."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Duplikaat instansie"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Skep 'n kopie van hierdie instansie, insluitend wêrelde, konfigurasies, mods, ens."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Wwysig ikoon"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Verwyder ikoon"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "Vervang ikoon"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "Kies ikoon"
},
"instance.settings.tabs.general.library-groups": {
"message": "Biblioteekgroepe"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "Skep nuwe groep"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "Biblioteekgroepe laat jou toe om jou instansies in verskillende afdelings in jou biblioteek te organiseer."
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "Voer groepnaam in"
},
"instance.settings.tabs.general.name": {
"message": "Naam"
},
"instance.settings.tabs.hooks": {
"message": "Lanseerhake"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Pasgemaakte lanseerhake"
},
"instance.settings.tabs.hooks.description": {
"message": "Hooks laat gevorderde gebruikers toe om sekere stelselopdragte uit te voer voor en na die bekendstelling van die spel."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "Na-uitgang"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "Het gehardloop nadat die wedstryd geëindig het."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Voer die na-uitgang-opdrag in..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Voorbekendstelling"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "Het gehardloop voordat die instansie geloods is."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Voer pre-lanceringsopdrag in..."
},
"instance.settings.tabs.hooks.wrapper": {
"message": "Verpakking"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "Verpakking opdrag vir die bekendstelling Van Minecraft."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "Voer die Verpakking-opdrag in..."
},
"instance.settings.tabs.installation": {
"message": "Installation"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} vir Minecraft {game_version} reeds geïnstalleer"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Vanilla {game_version} reeds geïnstalleer"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Verander weergawe"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Installeer"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Installasie"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Haal modpack weergawes"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Installeer nuwe weergawe"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Huidiglik geïnstalleer"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Ontfoutinligting:"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "Haal modpack besonderhede"
},
"instance.settings.tabs.installation.game-version": {
"message": "Spel weergawe"
},
"instance.settings.tabs.installation.install": {
"message": "Installeer"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Installasie aan die gang"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} weergawe"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Kan nie gekoppelde modpack-besonderhede haal nie. Kontroleer asseblief u internetverbinding."
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "{loader} is nie beskikbaar Vir Minecraft {version} nie. Probeer'n ander mod loader."
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "Hierdie geval is gekoppel aan'n modpack, maar die modpack kon nie gevind word op Modrinth."
},
"instance.settings.tabs.installation.platform": {
"message": "Basis"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Herinstalleer modpack"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Herinstalleer modpack weer"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Herinstalleer sal alle geïnstalleerde of gewysigde inhoud terugstel na wat deur die modpack verskaf word, en enige mods of inhoud wat jy bo-op die oorspronklike installasie bygevoeg het, verwyder. Dit kan onverwagte gedrag regstel as veranderinge aan die instansie aangebring is, maar as jou wêrelde nou afhanklik is van addisionele geïnstalleerde inhoud, kan dit bestaande wêrelde breek."
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Wil u definitief hierdie instansie herinstalleer?"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Stel die inhoud van die instansie terug na sy oorspronklike toestand, en verwyder enige mods of inhoud wat u bo-op die oorspronklike modpack bygevoeg het."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Herinstalleer modpack"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Herstel"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Herstel"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Herstel herinstalleer Minecraft afhanklikhede en tjeks vir korrupsie. Dit kan probleme oplos as u speletjie nie begin nie weens foute wat verband hou met die lanseerder, maar dit sal nie probleme of ineenstortings wat verband hou met geïnstalleerde mods oplos nie."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Herstel geval?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Herstelwerk aan die gang"
}
}
@@ -1,419 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "وضع المطوّر مُفعَّل."
},
"app.settings.tabs.appearance": {
"message": "المظهر"
},
"app.settings.tabs.default-instance-options": {
"message": "خيارات النسخة الافتراضية"
},
"app.settings.tabs.feature-flags": {
"message": "إعدادات المميزات"
},
"app.settings.tabs.java-installations": {
"message": "تثبيتات جافا"
},
"app.settings.tabs.privacy": {
"message": "الخصوصية"
},
"app.settings.tabs.resource-management": {
"message": "إدارة الموارد"
},
"instance.add-server.add-and-play": {
"message": "إضافة واللعب"
},
"instance.add-server.add-server": {
"message": "إضافة الخادم"
},
"instance.add-server.resource-pack.disabled": {
"message": "معطَّل"
},
"instance.add-server.resource-pack.enabled": {
"message": "مفعَّل"
},
"instance.add-server.resource-pack.prompt": {
"message": "موجه الأوامر"
},
"instance.add-server.title": {
"message": "إضافة خادم"
},
"instance.edit-server.title": {
"message": "تعديل خادم"
},
"instance.edit-world.hide-from-home": {
"message": "إخفاء من الصفحة الرئيسية"
},
"instance.edit-world.name": {
"message": "الاسم"
},
"instance.edit-world.placeholder-name": {
"message": "عالم ماينكرافت"
},
"instance.edit-world.reset-icon": {
"message": "إعادة تعيين الأيقونة"
},
"instance.edit-world.title": {
"message": "تعديل العالم"
},
"instance.filter.disabled": {
"message": "المشاريع المعطَّلة"
},
"instance.filter.updates-available": {
"message": "توجد تحديثات متاحة"
},
"instance.server-modal.address": {
"message": "العنوان"
},
"instance.server-modal.name": {
"message": "الاسم"
},
"instance.server-modal.placeholder-name": {
"message": "خادم ماين كرافت"
},
"instance.server-modal.resource-pack": {
"message": "حزمة الموارد"
},
"instance.settings.tabs.general": {
"message": "عام"
},
"instance.settings.tabs.general.delete": {
"message": "حذف النسخة"
},
"instance.settings.tabs.general.delete.button": {
"message": "حذف النسخة"
},
"instance.settings.tabs.general.delete.description": {
"message": "يحذف النسخة نهائيًا من جهازك، بما في ذلك عوالمك، إعداداتك، وجميع المحتويات المثبّتة. كن حذرًا، فبمجرد حذف النسخة لن تكون هناك أي طريقة لاستعادتها."
},
"instance.settings.tabs.general.deleting.button": {
"message": "جاري الحذف..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "نسخ"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "لا يمكن النسخ أثناء التثبيت."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "نسخة النسخة"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "إنشاء."
},
"instance.settings.tabs.general.edit-icon": {
"message": "تعديل الأيقونة"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "أزل الأيقونة"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "استبدل الأيقونة"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "اختر الأيقونة"
},
"instance.settings.tabs.general.library-groups": {
"message": "مجموعات المكتبة"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "إنشاء مجموعة جديدة"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "مجموعات المكتبة تساعدك على ترتيب حالاتك على أقسام مختلفة في مكتبتك."
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "إدخال اسم المجموعة"
},
"instance.settings.tabs.general.name": {
"message": "الاسم"
},
"instance.settings.tabs.hooks": {
"message": "إجراءات تشغيل إضافية"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "إجراءات تشغيل إضافية مخصصة"
},
"instance.settings.tabs.hooks.description": {
"message": "إجراءات التشغيل المضافة تسمح للمستخدمين المتقدمين بإنشاء أوامر نظامية محددة قبل و عند تشغيل اللعبة."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "ما بعد الخروج"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "يتم تشغيله بعد إغلاق اللعبة."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "أدخل أمر ما بعد الخروج..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "ما قبل الإطلاق"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "يتم تشغيله قبل بَدْء تشغيل النسخة."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "أدخل أمر ما قبل الإطلاق..."
},
"instance.settings.tabs.hooks.title": {
"message": "خطافات تشغيل اللعبة"
},
"instance.settings.tabs.hooks.wrapper": {
"message": "مُغلِّف"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "أمر غلاف لتشغيل ماين كرافت."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "أدخل أمر الغلاف..."
},
"instance.settings.tabs.installation": {
"message": "تثبيت"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} لماين كرافت {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": "ماين كرافت {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": "جافا والذاكرة"
},
"instance.settings.tabs.java.environment-variables": {
"message": "المتغيرات البيئية"
},
"instance.settings.tabs.java.hooks": {
"message": "الخطافات"
},
"instance.settings.tabs.java.java-arguments": {
"message": "وسائط جافا"
},
"instance.settings.tabs.java.java-installation": {
"message": "تثبيت جافا"
},
"instance.settings.tabs.java.java-memory": {
"message": "الذاكرة المخصَّصة"
},
"instance.settings.tabs.window": {
"message": "النافذة"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "إعدادات نافذة مخصّصة"
},
"instance.settings.tabs.window.fullscreen": {
"message": "ملء الشاشة"
},
"instance.settings.tabs.window.fullscreen.description": {
"message": "جعل اللعبة تبدأ في وضع ملء الشاشة عند التشغيل (باستخدام options.txt)."
},
"instance.settings.tabs.window.height": {
"message": "الارتفاع"
},
"instance.settings.tabs.window.height.description": {
"message": "ارتفاع نافذة اللعبة عند التشغيل."
},
"instance.settings.tabs.window.height.enter": {
"message": "أدخل الارتفاع..."
},
"instance.settings.tabs.window.width": {
"message": "العرض"
},
"instance.settings.tabs.window.width.description": {
"message": "عرض نافذة اللعبة عند التشغيل."
},
"instance.settings.tabs.window.width.enter": {
"message": "أدخل العرض..."
},
"instance.settings.title": {
"message": "الإعدادات"
},
"instance.worlds.a_minecraft_server": {
"message": "خادم ماين كرافت"
},
"instance.worlds.cant_connect": {
"message": "لا يمكن الاتصال بالخادم"
},
"instance.worlds.copy_address": {
"message": "نسخ العنوان"
},
"instance.worlds.dont_show_on_home": {
"message": "عدم العرض في الصفحة الرئيسية"
},
"instance.worlds.filter.available": {
"message": "متاح"
},
"instance.worlds.game_already_open": {
"message": "النسخة مفتوحة بالفعل"
},
"instance.worlds.hardcore": {
"message": "وضع الهاردكور"
},
"instance.worlds.incompatible_server": {
"message": "الخادم غير متوافق"
},
"instance.worlds.no_contact": {
"message": "تعذّر الاتصال بالخادم"
},
"instance.worlds.no_server_quick_play": {
"message": "يمكنك الدخول مباشرة إلى الخوادم فقط على ماين كرافت Alpha 1.0.5+"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "يمكنك الدخول مباشرة إلى عوالم اللعب الفردي فقط على ماين كرافت ‎1.20+‎"
},
"instance.worlds.play_instance": {
"message": "تشغيل النسخة"
},
"instance.worlds.type.server": {
"message": "الخادم"
},
"instance.worlds.type.singleplayer": {
"message": "لعب فردي"
},
"instance.worlds.view_instance": {
"message": "عرض النسخة"
},
"instance.worlds.world_in_use": {
"message": "العالم قيد الاستخدام"
},
"search.filter.locked.instance": {
"message": "مقدَّم من النسخة"
},
"search.filter.locked.instance-game-version.title": {
"message": "إصدار اللعبة مقدَّم من النسخة"
},
"search.filter.locked.instance-loader.title": {
"message": "المحمّل مقدَّم من النسخة"
},
"search.filter.locked.instance.sync": {
"message": "مزامنة مع النسخة"
}
}
+38 -8
View File
@@ -1,4 +1,34 @@
{
"app.auth-servers.unreachable.body": {
"message": "قد تكون خوادم مصادقة ماينكرافت معطلة حاليًا. تحقق من اتصالك بالإنترنت وحاول مرة أخرى لاحقًا."
},
"app.auth-servers.unreachable.header": {
"message": "تعذر الوصول إلى خوادم المصادقة"
},
"app.modal.install-to-play.header": {
"message": "نزل للعب"
},
"app.modal.install-to-play.install-button": {
"message": "تثبيت"
},
"app.modal.install-to-play.mod-count": {
"message": ""
},
"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.update-required": {
"message": "يلزم التحديث"
},
"app.settings.developer-mode-enabled": {
"message": "تم تفعيل وضع المطوّر."
},
@@ -17,6 +47,9 @@
"app.settings.tabs.java-installations": {
"message": "تثبيتات جافا"
},
"app.settings.tabs.language": {
"message": "اللغة"
},
"app.settings.tabs.privacy": {
"message": "الخصوصية"
},
@@ -78,7 +111,7 @@
"message": "جار إضافة صديق"
},
"friends.add-friend.username.description": {
"message": "قد يختلف عن اسم المستخدم الخاص بهم في Minecraft!"
"message": "قد يختلف عن اسم المستخدم الخاص بهم في ماينكرافت!"
},
"friends.add-friend.username.placeholder": {
"message": "أدخل اسم مستخدم Modrinth..."
@@ -132,7 +165,7 @@
"message": "إضافة واللعب"
},
"instance.add-server.add-server": {
"message": "إضافة الخادم"
"message": "إضافة خادم"
},
"instance.add-server.resource-pack.disabled": {
"message": "معطَّل"
@@ -177,7 +210,7 @@
"message": "الاسم"
},
"instance.server-modal.placeholder-name": {
"message": "خادم ماين كرافت"
"message": "خادم ماينكرافت"
},
"instance.server-modal.resource-pack": {
"message": "حزمة الموارد"
@@ -270,7 +303,7 @@
"message": "مُغلِّف"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "أمر غلاف لتشغيل ماين كرافت."
"message": "أمر غلاف لتشغيل ماينكرافت."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "أدخل أمر الغلاف..."
@@ -279,7 +312,7 @@
"message": "تثبيت"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} لماين كرافت {game_version} مثبت بالفعل"
"message": "{platform} {version} لماينكرافت {game_version} مثبت بالفعل"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "فانيلا {game_version} مُثبّتة بالفعل"
@@ -461,9 +494,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "أدخل العرض..."
},
"instance.settings.title": {
"message": "الإعدادات"
},
"instance.worlds.a_minecraft_server": {
"message": "خادم ماين كرافت"
},
@@ -1,8 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": ""
},
"app.settings.downloading": {
"message": ""
}
}
@@ -1 +0,0 @@
{}
@@ -1,131 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "Режим за разработчици активиран."
},
"app.settings.tabs.appearance": {
"message": "Външен вид"
},
"app.settings.tabs.default-instance-options": {
"message": "Опции по подразбиране"
},
"app.settings.tabs.java-installations": {
"message": "Java инсталации"
},
"app.settings.tabs.privacy": {
"message": "Поверителност"
},
"app.settings.tabs.resource-management": {
"message": "Контрол на ресурси"
},
"instance.add-server.add-and-play": {
"message": "Добави и играй"
},
"instance.add-server.add-server": {
"message": "Добави сървър"
},
"instance.add-server.resource-pack.disabled": {
"message": "Деактивирано"
},
"instance.add-server.resource-pack.enabled": {
"message": "Активирано"
},
"instance.add-server.title": {
"message": "Добавяне на сървър"
},
"instance.edit-server.title": {
"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.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}. Моля пробвайте друг mod loader."
},
"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.title": {
"message": "Сигурни ли сте, че искате да преинсталирате това?"
},
"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.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.window": {
"message": "Прозорец"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "Различни настройки на прозорец"
},
"instance.settings.tabs.window.fullscreen": {
"message": "Пълен екран"
}
}
@@ -1 +0,0 @@
{}
@@ -1,179 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "Mode de desenvolupament activat."
},
"app.settings.tabs.appearance": {
"message": "Aparença"
},
"app.settings.tabs.default-instance-options": {
"message": "Opcions d'instància per defecte"
},
"app.settings.tabs.java-installations": {
"message": "Instal·lacions de Java"
},
"app.settings.tabs.privacy": {
"message": "Privacitat"
},
"instance.add-server.add-and-play": {
"message": "Afegir i jugar"
},
"instance.add-server.add-server": {
"message": "Afegir servidor"
},
"instance.add-server.resource-pack.disabled": {
"message": "Desactivat"
},
"instance.add-server.resource-pack.enabled": {
"message": "Activat"
},
"instance.add-server.resource-pack.prompt": {
"message": "Preguntar"
},
"instance.add-server.title": {
"message": "Afegir un servidor"
},
"instance.edit-server.title": {
"message": "Editar servidor"
},
"instance.edit-world.hide-from-home": {
"message": "Amagar de l'inici"
},
"instance.edit-world.name": {
"message": "Nom"
},
"instance.edit-world.placeholder-name": {
"message": "Món de Minecraft"
},
"instance.edit-world.reset-icon": {
"message": "Reinicia l'icona"
},
"instance.edit-world.title": {
"message": "Edita el món"
},
"instance.filter.disabled": {
"message": "Projectes desactivats"
},
"instance.filter.updates-available": {
"message": "Actualitzacions disponibles"
},
"instance.server-modal.address": {
"message": "Adreça web"
},
"instance.server-modal.name": {
"message": "Nom"
},
"instance.server-modal.placeholder-name": {
"message": "Servidor de Minecraft"
},
"instance.server-modal.resource-pack": {
"message": "Paquet de recursos"
},
"instance.settings.tabs.general": {
"message": "General"
},
"instance.settings.tabs.general.delete": {
"message": "Suprimeix la instància"
},
"instance.settings.tabs.general.delete.button": {
"message": "Suprimir instància"
},
"instance.settings.tabs.general.delete.description": {
"message": "Suprimeix permanentment una instància del dispositiu, inclosos els vostres mons, configuracions i tot el contingut instal·lat. Aneu amb compte, ja que un cop suprimiu una instància no hi ha manera de recuperar-la."
},
"instance.settings.tabs.general.deleting.button": {
"message": "S'està suprimint..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "Duplicar"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "No es pot duplicar durant la instal·lació."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Duplica la instància"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Crea una còpia d'aquesta instància, incloent-hi mons, configuracions, mods, etc."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Edita la icona"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Treu icona"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "Substitueix icona"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "Selecciona icona"
},
"instance.settings.tabs.general.library-groups": {
"message": "Grup de llibreries"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "Crear nou grup"
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "Introdueix nom del grup"
},
"instance.settings.tabs.general.name": {
"message": "Nom"
},
"instance.settings.tabs.installation": {
"message": "Instal·lació"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Canviar versió"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Instal·lar"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Instal·lant"
},
"instance.settings.tabs.installation.game-version": {
"message": "Versió del joc"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.platform": {
"message": "Plataforma"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Reparar"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "canviar versió"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "reparar"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(versió desconeguda)"
},
"instance.settings.tabs.java": {
"message": "Java i memòria"
},
"instance.settings.tabs.window.fullscreen": {
"message": "Pantalla completa"
},
"instance.settings.tabs.window.height": {
"message": "Altura"
},
"instance.settings.tabs.window.width": {
"message": "Amplada"
},
"instance.settings.title": {
"message": "Configuració"
},
"instance.worlds.filter.available": {
"message": "Disponible"
},
"instance.worlds.play_instance": {
"message": "Jugar instància"
},
"instance.worlds.type.server": {
"message": "Servidor"
}
}
@@ -1,473 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "Gipaandar ang paagi sa tigpalambo."
},
"app.settings.downloading": {
"message": "Gakarganug sa v{version}"
},
"app.settings.tabs.appearance": {
"message": "Panagway"
},
"app.settings.tabs.default-instance-options": {
"message": "Mga kapilian sa sukaranan nga pananglitan"
},
"app.settings.tabs.feature-flags": {
"message": "Bandera sa mga panagway"
},
"app.settings.tabs.java-installations": {
"message": "Mga pagtaod sa Java"
},
"app.settings.tabs.privacy": {
"message": "Pribasiya"
},
"app.settings.tabs.resource-management": {
"message": "Pagdumala sa kahinguhaan"
},
"app.update-toast.body": {
"message": "Andam na mataud ang Modrinth App v{version}! Pagkarga kausab aron mapasibo, o kinaugalingon pagtak-op sa Modrinth App."
},
"app.update-toast.body.download-complete": {
"message": "Nahuman ang pagkarganug sa Modrinth App v{version}. Pagkarga kausab aron mapasibo, o kinaugalingon pagtak-op sa Modrinth App."
},
"app.update-toast.body.metered": {
"message": "Magamit na karon ang Modrinth App! Wala namo karganugi daan kay inihap man ang imong pum-ot."
},
"app.update-toast.changelog": {
"message": "Talaan sa Kausaban"
},
"app.update-toast.download": {
"message": "Karganugi ({size})"
},
"app.update-toast.downloading": {
"message": "Gakarganug..."
},
"app.update-toast.reload": {
"message": "Kargaha pag-usab"
},
"app.update-toast.title": {
"message": "Naay bag-o nga pagpasibo"
},
"app.update-toast.title.download-complete": {
"message": "Nahuman ang pagkarganug"
},
"app.update.complete-toast.text": {
"message": "Panuplok diri aron malantaw ang talaan sa kausaban."
},
"app.update.complete-toast.title": {
"message": "Malampusong nataud ang bersiyon nga {version}!"
},
"app.update.download-update": {
"message": "Karganugi ang kausaban"
},
"app.update.downloading-update": {
"message": "Gakarganug sa pagpasibo ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Andam mataud ang pagpasibo"
},
"friends.action.add-friend": {
"message": "Pagdugang og higala"
},
"friends.action.view-friend-requests": {
"message": "{count} ka hangyo sa pakighigala"
},
"friends.add-friend.submit": {
"message": "Pagpadala og hangyo sa pakighigala"
},
"friends.add-friend.title": {
"message": "Pagdugang og higala"
},
"friends.add-friend.username.description": {
"message": "Mahimong galahi sa ngalan nila sa Minecraft!"
},
"friends.add-friend.username.placeholder": {
"message": "Ibutang ang ngalan sa tiggamit sa Modrinth..."
},
"friends.add-friend.username.title": {
"message": "Unsa man ang ngalan sa imong higala sa Modrinth?"
},
"friends.add-friends-to-share": {
"message": "<link>Pagdugang og mga higala</link> aron makit-an ang ilang ginadula!"
},
"friends.friend.cancel-request": {
"message": "Bawia ang hangyo"
},
"friends.friend.remove-friend": {
"message": "Tangtangi ang higala"
},
"friends.friend.request-sent": {
"message": "Gipadala na ang hangyo sa pakighigala"
},
"friends.friend.view-profile": {
"message": "Tan-awa ang propayl"
},
"friends.heading": {
"message": "Mga higala"
},
"friends.heading.active": {
"message": "Malihokon"
},
"friends.heading.offline": {
"message": "Sira"
},
"friends.heading.online": {
"message": "Buka"
},
"friends.heading.pending": {
"message": "Gahulat"
},
"friends.no-friends-match": {
"message": "Walay higala nga motukma sa \"{query}\""
},
"friends.search-friends-placeholder": {
"message": "Mangita sa mga higala..."
},
"friends.section.heading": {
"message": "{title} - {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>Pag-sign-in sa Modrinth account</link> aron makadugang og mga higala ug mahibal-an ang ginadula nila!"
},
"instance.add-server.add-and-play": {
"message": "Idugang ug dulaa"
},
"instance.add-server.add-server": {
"message": "Idugang ang magsisilbi"
},
"instance.add-server.resource-pack.disabled": {
"message": "Dili motugot"
},
"instance.add-server.resource-pack.enabled": {
"message": "Gitugotan"
},
"instance.add-server.resource-pack.prompt": {
"message": "Magpatugot"
},
"instance.add-server.title": {
"message": "Pagdugang og magsisilbi"
},
"instance.edit-server.title": {
"message": "Usba ang magsisilbi"
},
"instance.edit-world.hide-from-home": {
"message": "Ayaw ipakita sa Puluy-anang panid"
},
"instance.edit-world.name": {
"message": "Ngalan"
},
"instance.edit-world.placeholder-name": {
"message": "Minecraft nga Kalibutan"
},
"instance.edit-world.reset-icon": {
"message": "Pag-usab sa amoy"
},
"instance.edit-world.title": {
"message": "Usba ang kalibutan"
},
"instance.filter.disabled": {
"message": "Di-paganhong mga proyekto"
},
"instance.filter.updates-available": {
"message": "Naay bag-ong mga kausaban"
},
"instance.server-modal.address": {
"message": "Padad-anan"
},
"instance.server-modal.name": {
"message": "Ngalan"
},
"instance.server-modal.placeholder-name": {
"message": "Minecraft nga Magsisilbi"
},
"instance.server-modal.resource-pack": {
"message": "Putos sa kahinguhaan"
},
"instance.settings.tabs.general": {
"message": "Tinanan"
},
"instance.settings.tabs.general.delete": {
"message": "Panas-i kining pananglitan"
},
"instance.settings.tabs.general.delete.button": {
"message": "Panas-i kining pananglitan"
},
"instance.settings.tabs.general.delete.description": {
"message": "Malungtarong mopanas ang pananglitan sa imong himan, apil na ang imong mga kalibutan, paghan-ay, ug tanang gitaod nga sulod. Pag-amping, dili na mabawi kung gipanas na nimo ang pananglitan."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Gapanas..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "Paghulad"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "Dili makahulad samtang nga gataud."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Paghulad sa pananglitan"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Buhatan og awat kining pananglitan, apil na ang imong mga kalibutan, paghan-ay, kausaban, ug uban pa."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Usba ang amoy"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Tangtangi ang amoy"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "Pulihan ang amoy"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "Pamili og amoy"
},
"instance.settings.tabs.general.library-groups": {
"message": "Mga pundok sa librarya"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "Pagbuhat og bag-o nga pundok"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "Gitugotan sa mga pundok sa librarya nga imong mahan-ay ang imong mga pananglitan sa nagkalain-lain nga bahin sa imong librarya."
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "Ibutang ang ngalan sa pundok"
},
"instance.settings.tabs.general.name": {
"message": "Ngalan"
},
"instance.settings.tabs.hooks": {
"message": "Mga kaw-it sa paglansad"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Mga pinatuyo nga kaw-it sa paglansad"
},
"instance.settings.tabs.hooks.description": {
"message": "Gitugotan sa mga kaw-it ang mga eksperto nga mga tiggamit nga makapadagan og mga sistema nga sugo ayha ug paghuman malansad ang dula."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "Human-matak-op"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "Ipadagan paghuman matak-op ang dula."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Ibutang ang human-matak-op nga sugo..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Ayha-malansad"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "Ipadagan ayha malansad ang pananglitan."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Ibutang ang ayha-malansad nga sugo..."
},
"instance.settings.tabs.hooks.title": {
"message": "Mga kaw-it sa paglansad sa dula"
},
"instance.settings.tabs.hooks.wrapper": {
"message": "Pamutos"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "Pamutos nga sugo sa paglansad sa Minecraft."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "Ibutang ang pamutos nga sugo..."
},
"instance.settings.tabs.installation": {
"message": "Pagtaud"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "Nataud naman ang {platform} {version} alang sa Minecraft {game_version}"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "Nataud naman ang Banilya nga {game_version}"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Pulihan og bersiyon"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Itaud"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Gataud"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Gapangita og mga bersiyon sa mga putos sa kausaban"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Gataud sa bag-o nga bersiyon"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Pagkakarong taud"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Kasayoran sa pagputli:"
},
"instance.settings.tabs.installation.game-version": {
"message": "Bersiyon sa dula"
},
"instance.settings.tabs.installation.install": {
"message": "Itaud"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Nagtaud karon"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Bersiyon sa {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "Dili magamit ang {loader} sa Minecraft {version}. Sulayi ang ubang tigkarga sa kausaban."
},
"instance.settings.tabs.installation.platform": {
"message": "Pantawan"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Itaud pag-usab ang putos sa kausaban"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Nagtaud pag-usab sa putos sa kusaban"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Mahimo nga mobalik sa sinugdan ang tanang gitaod o giusab nga sulod sa unsay ihatag sa putos sa kausaban, tangtangon ang mga kausaban o sulod nga imong gidugang apil na ang lintunganay nga putos sa kausaban. Mahimo nga maayo ang mga tuhaw nga batasan kon naay pagbag-o sa pananglitan, apan kon gasalig na ang imong kalibutan sa dinugang nga sulod, mahimo nga madaut ani ang daan nga mga kalibutan."
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "Ibalik ang mga sulod sa pananglitan sa unang kahimtang, tangtangon ang mga kausaban o sulod nga imong gidugang apil na ang lintunganay nga putos sa kausaban."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Itaud pag-usab ang putos sa kausaban"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Ayohon"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Gaayo"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Sa pag-ayo, mataud pagbalik ang mga sinaligan sa Minecraft ug mangita og mga kadunot. Mahimo nga masulbad niini ang mga isyu kun dili malunsad ang dula tungod sa mga kasaypan matud sa tiglansad, apan dili ni masulbad ang mga isyu o pagdusmog matud sa mga gitaud nga kausaban."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Ayohon ang pananglitan?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Nag-ayo karon"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Sa kasamtang pag-usab "
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Ipakita ang tanang bersiyon"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "pulihan og bersiyon"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "itaud"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "itaud pag-usab"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "ayohon"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Dili maka-{action} samtang nga gataud"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Dili maka-{action} samtang binugto"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Dili maka-{action} samtang nag-ayo"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(diinilang bersiyon)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Pagbugto sa pananglitan"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Kun imong ipadayon, dili na nimo makatay pagbalik nga wala mohimo og bag-o nga pananglitan. Dili na ka makadawat og pagpasibo sa putos sa kausaban ug mahimo kining naandan nga."
},
"instance.settings.tabs.installation.unlink.description": {
"message": "Nakakatay kining pananglitan sa usa ka putos sa kausaban, pasabot ani nga dili mapasibo ang mga kausaban og dili nimo mausab ang tigkarga sa kausaban o ang bersiyon sa Minecraft. Kanunay nga mabugto kining pananglitan og putos sa kausabon kun tangtangon ang katay."
},
"instance.settings.tabs.installation.unlink.title": {
"message": "Pagbugto sa putos sa kausaban"
},
"instance.settings.tabs.java": {
"message": "Java at memorya"
},
"instance.settings.tabs.java.hooks": {
"message": "Mga kaw-it"
},
"instance.settings.tabs.java.java-arguments": {
"message": "Mga lantugi sa java"
},
"instance.settings.tabs.java.java-installation": {
"message": "Pagtaud sa Java"
},
"instance.settings.tabs.java.java-memory": {
"message": "Memoryang gigahin"
},
"instance.settings.tabs.window": {
"message": "Tamboanan"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "Mga himutangan sa pinatuyo nga tamboanan"
},
"instance.settings.tabs.window.fullscreen": {
"message": "Punong-tabil"
},
"instance.settings.tabs.window.height": {
"message": "Gitas-on"
},
"instance.settings.tabs.window.height.enter": {
"message": "Ibutang ang gitas-on..."
},
"instance.settings.tabs.window.width": {
"message": "Gilapdon"
},
"instance.settings.tabs.window.width.enter": {
"message": "Ibutang ang gilapdon..."
},
"instance.settings.title": {
"message": "Mga Himutangan"
},
"instance.worlds.a_minecraft_server": {
"message": "Usa ka Minecraft nga Magsisilbi"
},
"instance.worlds.copy_address": {
"message": "Awata ang padad-anan"
},
"instance.worlds.dont_show_on_home": {
"message": "Ayaw pakit-a sa Puloy-anan"
},
"instance.worlds.filter.available": {
"message": "Magamit"
},
"instance.worlds.hardcore": {
"message": "Mahanasnon nga paagi"
},
"instance.worlds.play_instance": {
"message": "Dulai ang pananglitan"
},
"instance.worlds.type.server": {
"message": "Magsisilbi"
},
"instance.worlds.type.singleplayer": {
"message": "Inusara nga dula"
},
"instance.worlds.view_instance": {
"message": "Tan-awa ang pananglitan"
},
"instance.worlds.world_in_use": {
"message": "Gigamit ang kalibotan"
},
"search.filter.locked.instance.sync": {
"message": "Pagdungan sa pananglitan"
}
}
+166 -40
View File
@@ -1,4 +1,61 @@
{
"app.auth-servers.unreachable.body": {
"message": "Autořizační servery Minecraftu aktuálně nejsou k dispozici. Zkontrolujte si své připojení k internetu a zkuste to znovu později."
},
"app.auth-servers.unreachable.header": {
"message": "Připojení k autorizačním serverům se nezdařilo"
},
"app.modal.install-to-play.header": {
"message": "Nainstaluj ke hraní"
},
"app.modal.install-to-play.install-button": {
"message": "Instalovat"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural,one {#mód} other {#módy}}"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Tento server k hraní vyžaduje módy. Klikni na instalovat pro získání potřebných módů z Modrinth."
},
"app.modal.install-to-play.shared-by-today": {
"message": "{name} dnes s vámi sdílel tuto instanci."
},
"app.modal.install-to-play.shared-instance": {
"message": "Sdílená instance"
},
"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."
},
@@ -17,6 +74,9 @@
"app.settings.tabs.java-installations": {
"message": "Instalace Javy"
},
"app.settings.tabs.language": {
"message": "Jazyk"
},
"app.settings.tabs.privacy": {
"message": "Soukromí"
},
@@ -24,19 +84,25 @@
"message": "Správa zdrojů"
},
"app.update-toast.body": {
"message": "Modrinth App v{version} je připravena k instalaci! Znovu načtěte aktualizaci nyní nebo automaticky po zavření aplikace Modrinth."
"message": "Aplikace Modrinth v{version} je připravena k instalaci! Nainstalujte aktualizaci nyní nebo automaticky po zavření aplikace Modrinth."
},
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version} byla dokončena ke stažení. Znovu načtěte aktualizaci nyní nebo automaticky po zavření aplikace Modrinth."
"message": "Stahování aplikace Modrinth v{version} bylo dokončeno. Nainstalujte aktualizaci nyní nebo automaticky po zavření aplikace Modrinth."
},
"app.update-toast.body.linux": {
"message": "Modrinth App v{version} je k dispozici. Aktualizujte pomocí svého správce balíčků, abyste získali nejnovější funkce a opravy!"
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} je nyní k dispozici! Protože jste v síti s měřením, nebyla stažena automaticky."
"message": "Aplikace Modrinth v{version} je nyní k dispozici! Protože jste v měřené síti, nebyla stažena automaticky."
},
"app.update-toast.changelog": {
"message": "Seznam změn"
},
"app.update-toast.download": {
"message": "Stáhnout ({size})"
"message": "Stahování ({size})"
},
"app.update-toast.download-page": {
"message": "Stáhnout"
},
"app.update-toast.downloading": {
"message": "Stahování..."
@@ -45,10 +111,10 @@
"message": "Načíst znovu"
},
"app.update-toast.title": {
"message": "K dispozici je aktualizace"
"message": "Aktualizace je k dispozici"
},
"app.update-toast.title.download-complete": {
"message": "Stahování dokončeno"
"message": "Stahování bylo dokončeno"
},
"app.update.complete-toast.text": {
"message": "Kliknutím sem zobrazíte seznam změn."
@@ -63,7 +129,70 @@
"message": "Stahování aktualizace ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Znovu načíst pro nainstalování aktualizace"
"message": "Restartovat aplikaci pro nainstalování aktualizace"
},
"friends.action.add-friend": {
"message": "Přidat přítele"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural, one {žádost} few {žádosti} other {žádostí}} o přátelství"
},
"friends.add-friend.submit": {
"message": "Poslat žádost o přátelství"
},
"friends.add-friend.title": {
"message": "Přidávání kamaráda"
},
"friends.add-friend.username.description": {
"message": "Může být jiné než jejich Minecraft jméno!"
},
"friends.add-friend.username.placeholder": {
"message": "Zadejte uživatelské jméno Modrinth..."
},
"friends.add-friend.username.title": {
"message": "Jak se váš kamarád jmenuje na Modrinthu?"
},
"friends.add-friends-to-share": {
"message": "<link>Přidejte si přátelé</link> a podívejte se, co hrají!"
},
"friends.friend.cancel-request": {
"message": "Zrušit žádost"
},
"friends.friend.remove-friend": {
"message": "Odebrat přítele"
},
"friends.friend.request-sent": {
"message": "Žádost o přátelství odeslána"
},
"friends.friend.view-profile": {
"message": "Zobrazit profil"
},
"friends.heading": {
"message": "Kamarádi"
},
"friends.heading.active": {
"message": "Aktivní"
},
"friends.heading.offline": {
"message": "Offline"
},
"friends.heading.online": {
"message": "Online"
},
"friends.heading.pending": {
"message": "Čeká na vyřízení"
},
"friends.no-friends-match": {
"message": "Žádní přátelé neodpovídají '{query}''"
},
"friends.search-friends-placeholder": {
"message": "Hledat přátele..."
},
"friends.section.heading": {
"message": "{title} - {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>Přihlašte se ke svému Modrinth účtu</link>, abyste jsi přidali přátele a uviděli co hrají!"
},
"instance.add-server.add-and-play": {
"message": "Přidat a hrát"
@@ -78,7 +207,7 @@
"message": "Zapnuto"
},
"instance.add-server.resource-pack.prompt": {
"message": "Na dotaz"
"message": "Ptát se"
},
"instance.add-server.title": {
"message": "Přidat server"
@@ -87,7 +216,7 @@
"message": "Upravit server"
},
"instance.edit-world.hide-from-home": {
"message": "Schovat z domovské stránky"
"message": "Skrýt z domovské obrazovky"
},
"instance.edit-world.name": {
"message": "Název"
@@ -96,16 +225,16 @@
"message": "Minecraft svět"
},
"instance.edit-world.reset-icon": {
"message": "Reset ikony"
"message": "Resetovat ikonu"
},
"instance.edit-world.title": {
"message": "Upravit svět"
},
"instance.filter.disabled": {
"message": "Vypnout projekty"
"message": "Vypnuté projekty"
},
"instance.filter.updates-available": {
"message": "Aktualizace jsou dostupné"
"message": "K dispozice jsou aktualizace"
},
"instance.server-modal.address": {
"message": "Adresa"
@@ -117,19 +246,19 @@
"message": "Minecraft Server"
},
"instance.server-modal.resource-pack": {
"message": "Balíček textur"
"message": "Balíčky textur"
},
"instance.settings.tabs.general": {
"message": "Obecné"
},
"instance.settings.tabs.general.delete": {
"message": "Smazat instanci"
"message": "Odstranit instalaci"
},
"instance.settings.tabs.general.delete.button": {
"message": "Smazat instanci"
"message": "Odstranit instalaci"
},
"instance.settings.tabs.general.delete.description": {
"message": "Trvale smaže instanci z vašeho zařízení, včetně vašich světů, konfigurací a veškerého nainstalovaného obsahu. Buďte opatrní, protože jakmile instanci smažete, ne možné ji obnovit."
"message": "Trvale smaže instalaci z vašeho zařízení, včetně vašich světů, konfigurací a veškerého nainstalovaného obsahu. Buďte opatrní, protože jakmile instalaci smažete, nebude možné ji obnovit."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Mazání..."
@@ -141,34 +270,34 @@
"message": "Nelze duplikovat při instalaci."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Duplikovat instanci"
"message": "Duplikovat instalaci"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Vytvoří kopii této instance, včetně světů, konfigurací, modů atd."
"message": "Vytvoří kopii této instalace, včetně světů, konfigurací, modů atd."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Upravit ikonu"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Icona odstranit"
"message": "Odstranit ikonu"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "Ikona replikace"
"message": "Změnit ikonu"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "Výber ikona"
"message": "Vybrat ikonu"
},
"instance.settings.tabs.general.library-groups": {
"message": "Skupina knihoven"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "Vytvoří novou skupinu"
"message": "Vytvořit novou skupinu"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "Skupiny knihoven vám umožňují uspořádat instance do různých sekcí v knihovně."
"message": "Skupiny knihoven vám umožňují uspořádat instalace do různých sekcí."
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "Zadej název skupiny"
"message": "Zadejte název skupiny"
},
"instance.settings.tabs.general.name": {
"message": "Název"
@@ -195,7 +324,7 @@
"message": "Před spuštěním"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "Spouštějí se před spuštěním instance."
"message": "Spouštějí se před spuštěním instalace."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Zadejte příkaz k provedení před spuštěním..."
@@ -216,28 +345,28 @@
"message": "Instalace"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} pro Minecraft {game_version} již nainstalována"
"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ž nainstalována"
"message": "Vanilla {game_version} již je nainstalována"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Změnit instalaci"
"message": "Změnit verzi"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Instalovat"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Instalace"
"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ých verzí"
"message": "Instalace nové verze"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Aktuální instalace"
"message": "Aktuálně nainstalováno"
},
"instance.settings.tabs.installation.debug-information": {
"message": "Debugové informace:"
@@ -252,7 +381,7 @@
"message": "Instalovat"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Probíhající instalace"
"message": "Probíhá instalace"
},
"instance.settings.tabs.installation.loader-version": {
"message": "{loader} verze"
@@ -261,13 +390,13 @@
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Nelze načíst podrobnosti o modpacku. Zkontrolujte připojení k internetu."
"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, ale modpack nebyl najit na Modrinthu."
"message": "Tato instalace je připojená k modpacku, který ake nebyl najit na Modrinthu."
},
"instance.settings.tabs.installation.platform": {
"message": "Platforma"
@@ -279,7 +408,7 @@
"message": "Přeinstalovávání modpacku"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Přeinstalace resetuje veškerý nainstalovaný nebo upravený obsah na to, co poskytuje modpack, a odstraní všechny mody nebo obsah, které jste přidali do původní instalaci. To může opravit neočekávané chyby, ale pokud vaše světy závisejí na nově instalovaném obsahu, možná budou poškozeny."
"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?"
@@ -312,7 +441,7 @@
"message": "Ukázat všechny verze"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "Změnit verzi"
"message": "změnit verzi"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "Instalovat"
@@ -398,9 +527,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Zadejte šířku..."
},
"instance.settings.title": {
"message": "Nastavení"
},
"instance.worlds.a_minecraft_server": {
"message": "Minecraft Server"
},
@@ -432,7 +558,7 @@
"message": "Můžeš rovnou skočit na server pouze v Minecraftu Alpha 1.0.5+"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Můžeš rovnou skočit do světa jednoho hráče pouze v Minecraftu 1.20+"
"message": "Můžeš se rovnou připojit do světa jednoho hráče pouze v Minecraftu 1.20+"
},
"instance.worlds.play_instance": {
"message": "Hrát instanci"
+59 -8
View File
@@ -1,4 +1,49 @@
{
"app.auth-servers.unreachable.body": {
"message": "Minecraft authentication servere kan måske være nede lige nu. Tjek din internet forbindelse og prøv igen senere."
},
"app.auth-servers.unreachable.header": {
"message": "Kan ikke nå autentificeringsservere"
},
"app.modal.install-to-play.header": {
"message": "Installer for at spille"
},
"app.modal.install-to-play.install-button": {
"message": "Installer"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# mods}}"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Denne server kræver mods for at spille. Klik installer for at sætte op filerne som er krævet fra Modrinth."
},
"app.modal.update-to-play.added-count": {
"message": "{count} tilføjet"
},
"app.modal.update-to-play.diff-type.added": {
"message": "Tilføjet"
},
"app.modal.update-to-play.diff-type.removed": {
"message": "Fjernet"
},
"app.modal.update-to-play.diff-type.updated": {
"message": "Opdateret"
},
"app.modal.update-to-play.header": {
"message": "Opdater for at spille"
},
"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."
},
@@ -17,6 +62,9 @@
"app.settings.tabs.java-installations": {
"message": "Javainstallationer"
},
"app.settings.tabs.language": {
"message": "Sprog"
},
"app.settings.tabs.privacy": {
"message": "Privatliv"
},
@@ -29,6 +77,9 @@
"app.update-toast.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-toast.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-toast.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."
},
@@ -38,6 +89,9 @@
"app.update-toast.download": {
"message": "Download ({size})"
},
"app.update-toast.download-page": {
"message": "Download"
},
"app.update-toast.downloading": {
"message": "Downloader..."
},
@@ -252,7 +306,7 @@
"message": "Kørte efter spillet lukkes."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Indskriv post-exit kommando..."
"message": "Indtast post-exit kommando..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Pre-launch"
@@ -261,7 +315,7 @@
"message": "Kørt før en instance bliver kørt."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Indskriv pre-launch kommando..."
"message": "Indtast pre-launch kommando..."
},
"instance.settings.tabs.hooks.title": {
"message": "Spille lunch hooks"
@@ -273,7 +327,7 @@
"message": "Wrapper kommando for at køre Minecraft."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "Indskriv wrapper kommando..."
"message": "Indtast wrapper kommando..."
},
"instance.settings.tabs.installation": {
"message": "Installation"
@@ -450,7 +504,7 @@
"message": "Højden af spillevinduet når kørt."
},
"instance.settings.tabs.window.height.enter": {
"message": "Indskriv højde..."
"message": "Indtast højde..."
},
"instance.settings.tabs.window.width": {
"message": "Bredde"
@@ -459,10 +513,7 @@
"message": "Bredden på spille vinduet når kørt."
},
"instance.settings.tabs.window.width.enter": {
"message": "Indskriv bredde..."
},
"instance.settings.title": {
"message": "Indstillinger"
"message": "Indtast bredde..."
},
"instance.worlds.a_minecraft_server": {
"message": "En Minecraft server"
+66 -3
View File
@@ -1,4 +1,61 @@
{
"app.auth-servers.unreachable.body": {
"message": "Die Authentifizierungsserver von Minecraft sind eventuell momentan nicht erreichbar. Überprüfe deine Internetverbindung und versuche es später erneut."
},
"app.auth-servers.unreachable.header": {
"message": "Authentifizierungsserver sind nicht erreichbar"
},
"app.modal.install-to-play.header": {
"message": "Installieren zum Spielen"
},
"app.modal.install-to-play.install-button": {
"message": "Installieren"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# Mod} other {# Mods}}"
},
"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 einzurichten."
},
"app.modal.install-to-play.shared-by-today": {
"message": "{name} hat diese Instanz heute mit dir geteilt."
},
"app.modal.install-to-play.shared-instance": {
"message": "Geteilte Instanz"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "Geteilte Server Instanz"
},
"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 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."
},
@@ -17,6 +74,9 @@
"app.settings.tabs.java-installations": {
"message": "Java Installationen"
},
"app.settings.tabs.language": {
"message": "Sprache"
},
"app.settings.tabs.privacy": {
"message": "Datenschutz"
},
@@ -29,6 +89,9 @@
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version} wurde heruntergeladen. Lade die App neu, oder schliesse sie, um zu aktualisieren."
},
"app.update-toast.body.linux": {
"message": "Modrinth App v{version} ist verfügbar. Benutze deinen Paketmanager zum aktualisieren um die neusten Features und Bugfixes zu erhalten!"
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} ist jetzt verfügbar! Da du in einem begrenzten Netzwerk bist, haben wir es nicht automatisch heruntergeladen."
},
@@ -38,6 +101,9 @@
"app.update-toast.download": {
"message": "Herunterladen ({size})"
},
"app.update-toast.download-page": {
"message": "Herunterladen"
},
"app.update-toast.downloading": {
"message": "Lade herunter..."
},
@@ -461,9 +527,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Breite eingeben..."
},
"instance.settings.title": {
"message": "Einstellungen"
},
"instance.worlds.a_minecraft_server": {
"message": "Ä Minecraft-Server"
},
+77 -14
View File
@@ -1,4 +1,61 @@
{
"app.auth-servers.unreachable.body": {
"message": "Die Authentifizierungsserver von Minecraft sind eventuell momentan nicht erreichbar. Überprüfe deine Internetverbindung und versuche es später erneut."
},
"app.auth-servers.unreachable.header": {
"message": "Authentifizierungsserver sind nicht erreichbar"
},
"app.modal.install-to-play.header": {
"message": "Installieren zum Spielen"
},
"app.modal.install-to-play.install-button": {
"message": "Installieren"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# Mod} other {# Mods}}"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Dieser Server benötigt Mods zum Spielen. Klick auf „Installieren“ um die erforderlichen Dateien von Modrinth zu installieren."
},
"app.modal.install-to-play.shared-by-today": {
"message": "{name} hat diese Instanz heute mit dir geteilt."
},
"app.modal.install-to-play.shared-instance": {
"message": "Geteilte Instanz"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "Geteilte Serverinstanz"
},
"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."
},
@@ -12,11 +69,14 @@
"message": "Standard Instanz-Einstellungen"
},
"app.settings.tabs.feature-flags": {
"message": "Funktionsflaggen"
"message": "Funktionsflags"
},
"app.settings.tabs.java-installations": {
"message": "Java-Installationen"
},
"app.settings.tabs.language": {
"message": "Sprache"
},
"app.settings.tabs.privacy": {
"message": "Datenschutz"
},
@@ -29,6 +89,9 @@
"app.update-toast.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."
},
"app.update-toast.body.linux": {
"message": "Modrinth App v{version} ist verfügbar. Verwende deinen Paketmanager, um die neuesten Funktionen und Fehlerbehebungen zu installieren!"
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} ist jetzt verfügbar! Da du ein getaktetes Netzwerk nutzt, haben wir den Download nicht automatisch gestartet."
},
@@ -38,6 +101,9 @@
"app.update-toast.download": {
"message": "Herunterladen ({size})"
},
"app.update-toast.download-page": {
"message": "Herunterladen"
},
"app.update-toast.downloading": {
"message": "Wird Heruntergeladen..."
},
@@ -63,7 +129,7 @@
"message": "Update wird heruntergeladen ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Neu laden um Update zu installieren"
"message": "Neu laden, um das Update zu installieren"
},
"friends.action.add-friend": {
"message": "Freund hinzufügen"
@@ -72,7 +138,7 @@
"message": "{count} {count, plural, one {Freundesanfrage} other {Freundesanfragen}}"
},
"friends.add-friend.submit": {
"message": "Freundesanfrage senden"
"message": "Freundschaftsanfrage senden"
},
"friends.add-friend.title": {
"message": "Einen Freund hinzufügen"
@@ -96,7 +162,7 @@
"message": "Freund entfernen"
},
"friends.friend.request-sent": {
"message": "Freundesanfrage gesendet"
"message": "Freundschaftsanfrage gesendet"
},
"friends.friend.view-profile": {
"message": "Profil anzeigen"
@@ -150,7 +216,7 @@
"message": "Server bearbeiten"
},
"instance.edit-world.hide-from-home": {
"message": "Von Startseite verbergen"
"message": "Von der Startseite verbergen"
},
"instance.edit-world.name": {
"message": "Name"
@@ -192,7 +258,7 @@
"message": "Instanz löschen"
},
"instance.settings.tabs.general.delete.description": {
"message": "Löscht eine Instanz dauerhaft von deinem Gerät, einschließlich deiner Welten, Einstellungen und aller installierten Inhalte. Sei vorsichtig, da eine gelöschte Instanz nicht wiederhergestellt werden kann."
"message": "Löscht eine Instanz dauerhaft von deinem Gerät, einschließlich deiner Welten, Einstellungen und aller installierten Inhalte. Sei vorsichtig, eine gelöschte Instanz ist nicht wiederherstellbar."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Wird gelöscht..."
@@ -201,13 +267,13 @@
"message": "Kopieren"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "Kann während der Installation nicht kopiert werden."
"message": "Kann während der Installation nicht dupliziert werden."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Instanz duplizieren"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Erstellt eine Kopie dieser Instanz, inklusive aller Welten, Einstellungen, Modifikationen, usw."
"message": "Erstellt eine Kopie dieser Instanz, inklusive aller Welten, Einstellungen, Mods, usw."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Icon bearbeiten"
@@ -237,10 +303,10 @@
"message": "Name"
},
"instance.settings.tabs.hooks": {
"message": "Start Hooks"
"message": "Startargumente"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Benutzerdefinierte Start Hooks"
"message": "Benutzerdefinierte Startargumente"
},
"instance.settings.tabs.hooks.description": {
"message": "Hooks ermöglichen es fortgeschrittenen Benutzern, bestimmte Systembefehle vor und nach dem Spielstart auszuführen."
@@ -261,7 +327,7 @@
"message": "Wird vor dem Starten der Instanz ausgeführt."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Vor Spielstart auszuführender Befehl eingeben..."
"message": "Vor Spielstart auszuführenden Befehl eingeben..."
},
"instance.settings.tabs.hooks.title": {
"message": "Start-Hooks"
@@ -461,9 +527,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Breite eingeben..."
},
"instance.settings.title": {
"message": "Einstellungen"
},
"instance.worlds.a_minecraft_server": {
"message": "Ein Minecraft-Server"
},
@@ -1,155 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "Λειτουργία προγραμματιστή ενεργό."
},
"app.settings.tabs.appearance": {
"message": "Εμφάνιση"
},
"app.settings.tabs.default-instance-options": {
"message": "Προεπιλεγμένες επιλογές στιγμιότυπου"
},
"app.settings.tabs.feature-flags": {
"message": "Σημαίες χαρακτηριστικών"
},
"app.settings.tabs.java-installations": {
"message": "Εγκαταστάσεις Java"
},
"app.settings.tabs.privacy": {
"message": "Απόρρητο"
},
"app.settings.tabs.resource-management": {
"message": "Διαχείριση πόρων"
},
"instance.add-server.add-and-play": {
"message": "Προσθήκη και παίξε"
},
"instance.add-server.add-server": {
"message": "Προσθήκη διακομιστή"
},
"instance.add-server.resource-pack.disabled": {
"message": "Ανενεργό"
},
"instance.add-server.resource-pack.enabled": {
"message": "Ενεργό"
},
"instance.add-server.resource-pack.prompt": {
"message": "Ειδοποίηση"
},
"instance.add-server.title": {
"message": "Προσθήκη διακομιστή"
},
"instance.edit-server.title": {
"message": "Επεξεργασία διακομιστή"
},
"instance.edit-world.hide-from-home": {
"message": "Απόκρυψη από την Αρχική σελίδα"
},
"instance.edit-world.name": {
"message": "Όνομα"
},
"instance.edit-world.placeholder-name": {
"message": "Minecraft Κόσμος"
},
"instance.edit-world.reset-icon": {
"message": "Επαναφορά εικονιδίου"
},
"instance.edit-world.title": {
"message": "Επεξεργασία κόσμου"
},
"instance.filter.disabled": {
"message": "Ανενεργά έργα"
},
"instance.filter.updates-available": {
"message": "Διαθέσιμη ενημέρωση"
},
"instance.server-modal.address": {
"message": "Διεύθυνση"
},
"instance.server-modal.name": {
"message": "Όνομα"
},
"instance.server-modal.placeholder-name": {
"message": "Minecraft Διακομιστής"
},
"instance.server-modal.resource-pack": {
"message": "Πακέτο πόρων"
},
"instance.settings.tabs.general": {
"message": "Γενικά"
},
"instance.settings.tabs.general.delete": {
"message": "Διαγραφή στιγμιότυπου"
},
"instance.settings.tabs.general.delete.button": {
"message": "Διαγραφή στιγμιότυπου"
},
"instance.settings.tabs.general.delete.description": {
"message": "Διαγράφει οριστικά ένα στιγμιότυπο από τη συσκευή σας, συμπεριλαμβανομένων των κόσμων, των ρυθμίσεων και όλου του εγκατεστημένου περιεχομένου. Να είστε προσεκτικοί, καθώς μόλις διαγράψετε μια παρουσία, δεν υπάρχει τρόπος να την ανακτήσετε."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Διαγραφή..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "Διπλότυπο"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "Δεν είναι δυνατή η δημιουργία αντιγράφων κατά την εγκατάσταση."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Διπλότυπο στιγμιότυπο"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Δημιουργεί ένα αντίγραφο αυτού του στιγμιότυπου, συμπεριλαμβάνοντας κόσμους, ρυθμίσεις, mods, κτλ."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Επεξεργασία εικονιδίου"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Αφαίρεση εικονιδίου"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "Αντικατάσταση εικονιδίου"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "Επιλογή εικονιδίου"
},
"instance.settings.tabs.general.library-groups": {
"message": "Ομάδες βιβλιοθηκών"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "Δημιουργία νέας ομάδας"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "Οι ομάδες βιβλιοθήκης σάς επιτρέπουν να οργανώσετε τα στιγμιότυπα σας σε διαφορετικές ενότητες στη βιβλιοθήκη σας."
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "Εισάγετε το όνομα της ομάδας"
},
"instance.settings.tabs.general.name": {
"message": "Όνομα"
},
"instance.settings.tabs.hooks": {
"message": "Άγκιστρα εκκίνησης"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Προσαρμοσμένα άγκιστρα εκκίνησης"
},
"instance.settings.tabs.hooks.description": {
"message": "Τα άγκιστρα επιτρέπουν στους προχωρημένους χρήστες να εκτελούν ορισμένες εντολές συστήματος πριν και μετά την εκκίνηση του παιχνιδιού."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "Μετά την έξοδο"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "Εκτελέστηκε αφού έκλεισε το παιχνίδι."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Εισαγάγετε την εντολή μετά την έξοδο..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Πριν την εκκίνηση"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "Εκτελέστηκε πριν από την εκκίνηση του στιγμιότυπου."
}
}
@@ -1,71 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "In ye captain's boots."
},
"app.settings.tabs.appearance": {
"message": "How ye be looking"
},
"app.settings.tabs.privacy": {
"message": "Keepin' ye gold under lock and key"
},
"instance.add-server.add-server": {
"message": "Plundered"
},
"instance.add-server.resource-pack.disabled": {
"message": "Unable"
},
"instance.add-server.resource-pack.enabled": {
"message": "Able"
},
"instance.add-server.resource-pack.prompt": {
"message": "Can"
},
"instance.add-server.title": {
"message": "Plundered"
},
"instance.edit-server.title": {
"message": "Change yer island"
},
"instance.edit-world.name": {
"message": "What'n yer world be called"
},
"instance.server-modal.address": {
"message": "Whar ye' reside"
},
"instance.server-modal.resource-pack": {
"message": "Picture pack"
},
"instance.settings.tabs.general.delete": {
"message": "Mutiny instance"
},
"instance.settings.tabs.general.delete.button": {
"message": "Mutiny instance"
},
"instance.settings.tabs.general.delete.description": {
"message": "Forces yer intstance to be walk'n the plank an' to see Davy Jones' locker, never to be seen nor heard from ever again. Ya hear?"
},
"instance.settings.tabs.general.deleting.button": {
"message": "Shoving..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "Ship o' Theseus your instance"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Replaces all o' the planks on yer instance wit' new ones - be it even the same anymore?"
},
"instance.settings.tabs.general.edit-icon": {
"message": "Change yer picture"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Scrub ye deck of old paint"
},
"instance.settings.tabs.installation.game-version": {
"message": "Ye model of sloop"
},
"instance.worlds.type.server": {
"message": "Island"
},
"instance.worlds.type.singleplayer": {
"message": "Lonely Voyage"
}
}
@@ -1,419 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "˙pǝlqɐuǝ ǝpoɯ ɹǝdolǝʌǝᗡ"
},
"app.settings.tabs.appearance": {
"message": "ǝɔuɐɹɐǝddⱯ"
},
"app.settings.tabs.default-instance-options": {
"message": "suoᴉʇdo ǝɔuɐʇsuᴉ ʇlnɐɟǝᗡ"
},
"app.settings.tabs.feature-flags": {
"message": "sɓɐlɟ ǝɹnʇɐǝℲ"
},
"app.settings.tabs.java-installations": {
"message": "suoᴉʇɐllɐʇsuᴉ ɐʌɐſ"
},
"app.settings.tabs.privacy": {
"message": "ʎɔɐʌᴉɹԀ"
},
"app.settings.tabs.resource-management": {
"message": "ʇuǝɯǝɓɐuɐɯ ǝɔɹnosǝᴚ"
},
"instance.add-server.add-and-play": {
"message": "ʎɐld puɐ ppⱯ"
},
"instance.add-server.add-server": {
"message": "ɹǝʌɹǝs ppⱯ"
},
"instance.add-server.resource-pack.disabled": {
"message": "pǝlqɐsᴉᗡ"
},
"instance.add-server.resource-pack.enabled": {
"message": "pǝlqɐuƎ"
},
"instance.add-server.resource-pack.prompt": {
"message": "ʇdɯoɹԀ"
},
"instance.add-server.title": {
"message": "ɹǝʌɹǝs ɐ ppⱯ"
},
"instance.edit-server.title": {
"message": "ɹǝʌɹǝs ʇᴉpƎ"
},
"instance.edit-world.hide-from-home": {
"message": "ǝɓɐd ǝɯoH ǝɥʇ ɯoɹɟ ǝpᴉH"
},
"instance.edit-world.name": {
"message": "ǝɯɐN"
},
"instance.edit-world.placeholder-name": {
"message": "plɹoM ʇɟɐɹɔǝuᴉW"
},
"instance.edit-world.reset-icon": {
"message": "uoɔᴉ ʇǝsǝᴚ"
},
"instance.edit-world.title": {
"message": "plɹoʍ ʇᴉpƎ"
},
"instance.filter.disabled": {
"message": "sʇɔǝſoɹd pǝlqɐsᴉᗡ"
},
"instance.filter.updates-available": {
"message": "ǝlqɐlᴉɐʌɐ sǝʇɐpd∩"
},
"instance.server-modal.address": {
"message": "ssǝɹppⱯ"
},
"instance.server-modal.name": {
"message": "ǝɯɐN"
},
"instance.server-modal.placeholder-name": {
"message": "ɹǝʌɹǝS ʇɟɐɹɔǝuᴉW"
},
"instance.server-modal.resource-pack": {
"message": "ʞɔɐd ǝɔɹnosǝᴚ"
},
"instance.settings.tabs.general": {
"message": "lɐɹǝuǝ⅁"
},
"instance.settings.tabs.general.delete": {
"message": "ǝɔuɐʇsuᴉ ǝʇǝlǝᗡ"
},
"instance.settings.tabs.general.delete.button": {
"message": "ǝɔuɐʇsuᴉ ǝʇǝlǝᗡ"
},
"instance.settings.tabs.general.delete.description": {
"message": "˙ʇᴉ ɹǝʌoɔǝɹ oʇ ʎɐʍ ou sᴉ ǝɹǝɥʇ ǝɔuɐʇsuᴉ ɐ ǝʇǝlǝp noʎ ǝɔuo sɐ ˋlnɟǝɹɐɔ ǝᗺ ˙ʇuǝʇuoɔ pǝllɐʇsuᴉ llɐ puɐ ˋsɓᴉɟuoɔ ˋsplɹoʍ ɹnoʎ ɓuᴉpnlɔuᴉ ˋǝɔᴉʌǝp ɹnoʎ ɯoɹɟ ǝɔuɐʇsuᴉ uɐ sǝʇǝlǝp ʎlʇuǝuɐɯɹǝԀ"
},
"instance.settings.tabs.general.deleting.button": {
"message": "˙˙˙ɓuᴉʇǝlǝᗡ"
},
"instance.settings.tabs.general.duplicate-button": {
"message": "ǝʇɐɔᴉldnᗡ"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "˙ɓuᴉllɐʇsuᴉ ǝlᴉɥʍ ǝʇɐɔᴉldnp ʇouuɐƆ"
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "ǝɔuɐʇsuᴉ ǝʇɐɔᴉldnᗡ"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "˙ɔʇǝ ˋspoɯ ˋsɓᴉɟuoɔ ˋsplɹoʍ ɓuᴉpnlɔuᴉ ˋǝɔuɐʇsuᴉ sᴉɥʇ ɟo ʎdoɔ ɐ sǝʇɐǝɹƆ"
},
"instance.settings.tabs.general.edit-icon": {
"message": "uoɔᴉ ʇᴉpƎ"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "uoɔᴉ ǝʌoɯǝᴚ"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "uoɔᴉ ǝɔɐldǝᴚ"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "uoɔᴉ ʇɔǝlǝS"
},
"instance.settings.tabs.general.library-groups": {
"message": "Sǝlǝɔʇ ᴉɔon"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "dnoɹɓ ʍǝu ǝʇɐǝɹƆ"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "˙ʎɹɐɹqᴉl ɹnoʎ uᴉ suoᴉʇɔǝs ʇuǝɹǝɟɟᴉp oʇuᴉ sǝɔuɐʇsuᴉ ɹnoʎ ǝzᴉuɐɓɹo oʇ noʎ ʍollɐ sdnoɹɓ ʎɹɐɹqᴉꞀ"
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "ǝɯɐu dnoɹɓ ɹǝʇuƎ"
},
"instance.settings.tabs.general.name": {
"message": "ǝɯɐN"
},
"instance.settings.tabs.hooks": {
"message": "sʞooɥ ɥɔunɐꞀ"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "sʞooɥ ɥɔunɐl ɯoʇsnƆ"
},
"instance.settings.tabs.hooks.description": {
"message": "˙ǝɯɐɓ ǝɥʇ ɓuᴉɥɔunɐl ɹǝʇɟɐ puɐ ǝɹoɟǝq spuɐɯɯoɔ ɯǝʇsʎs uᴉɐʇɹǝɔ unɹ oʇ sɹǝsn pǝɔuɐʌpɐ ʍollɐ sʞooH"
},
"instance.settings.tabs.hooks.post-exit": {
"message": "ʇᴉxǝ-ʇsoԀ"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "˙sǝsolɔ ǝɯɐɓ ǝɥʇ ɹǝʇɟɐ uɐᴚ"
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "˙˙˙puɐɯɯoɔ ʇᴉxǝ-ʇsod ɹǝʇuƎ"
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "ɥɔunɐl-ǝɹԀ"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "˙pǝɥɔunɐl sᴉ ǝɔuɐʇsuᴉ ǝɥʇ ǝɹoɟǝq uɐᴚ"
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "˙˙˙puɐɯɯoɔ ɥɔunɐl-ǝɹd ɹǝʇuƎ"
},
"instance.settings.tabs.hooks.title": {
"message": "sʞooɥ ɥɔunɐl ǝɯɐ⅁"
},
"instance.settings.tabs.hooks.wrapper": {
"message": "ɹǝddɐɹM"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "˙ʇɟɐɹɔǝuᴉW ɓuᴉɥɔunɐl ɹoɟ puɐɯɯoɔ ɹǝddɐɹM"
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "˙˙˙puɐɯɯoɔ ɹǝddɐɹʍ ɹǝʇuƎ"
},
"instance.settings.tabs.installation": {
"message": "uoᴉʇɐllɐʇsuI"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "pǝllɐʇsuᴉ ʎpɐǝɹlɐ {game_version} ʇɟɐɹɔǝuᴉW ɹoɟ {version} {platform}"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "pǝllɐʇsuᴉ ʎpɐǝɹlɐ {game_version} ɐllᴉuɐΛ"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "uoᴉsɹǝʌ ǝɓuɐɥƆ"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "llɐʇsuI"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "ɓuᴉllɐʇsuI"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "suoᴉsɹǝʌ ʞɔɐdpoɯ ɓuᴉɥɔʇǝℲ"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "uoᴉsɹǝʌ ʍǝu ɓuᴉllɐʇsuI"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "pǝllɐʇsuᴉ ʎlʇuǝɹɹnƆ"
},
"instance.settings.tabs.installation.debug-information": {
"message": ":uoᴉʇɐɯɹoɟuᴉ ɓnqǝᗡ"
},
"instance.settings.tabs.installation.fetching-modpack-details": {
"message": "slᴉɐʇǝp ʞɔɐdpoɯ ɓuᴉɥɔʇǝℲ"
},
"instance.settings.tabs.installation.game-version": {
"message": "uoᴉsɹǝʌ ǝɯɐ⅁"
},
"instance.settings.tabs.installation.install": {
"message": "llɐʇsuI"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "ssǝɹɓoɹd uᴉ uoᴉʇɐllɐʇsuI"
},
"instance.settings.tabs.installation.loader-version": {
"message": "uoᴉsɹǝʌ {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "{version} ʇɟɐɹɔǝuᴉW"
},
"instance.settings.tabs.installation.no-connection": {
"message": "˙uoᴉʇɔǝuuoɔ ʇǝuɹǝʇuᴉ ɹnoʎ ʞɔǝɥɔ ǝsɐǝlԀ ˙slᴉɐʇǝp ʞɔɐdpoɯ pǝʞuᴉl ɥɔʇǝɟ ʇouuɐƆ"
},
"instance.settings.tabs.installation.no-loader-versions": {
"message": "˙ɹǝpɐol poɯ ɹǝɥʇouɐ ʎɹ⟘ ˙{version} ʇɟɐɹɔǝuᴉW ɹoɟ ǝlqɐlᴉɐʌɐ ʇou sᴉ {loader}"
},
"instance.settings.tabs.installation.no-modpack-found": {
"message": "˙ɥʇuᴉɹpoW uo punoɟ ǝq ʇou plnoɔ ʞɔɐdpoɯ ǝɥʇ ʇnq ˋʞɔɐdpoɯ ɐ oʇ pǝʞuᴉl sᴉ ǝɔuɐʇsuᴉ sᴉɥ⟘"
},
"instance.settings.tabs.installation.platform": {
"message": "ɯɹoɟʇɐlԀ"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "ʞɔɐdpoɯ llɐʇsuᴉǝᴚ"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "ʞɔɐdpoɯ ɓuᴉllɐʇsuᴉǝᴚ"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "˙splɹoʍ ɓuᴉʇsᴉxǝ ʞɐǝɹq ʎɐɯ ʇᴉ ˋʇuǝʇuoɔ pǝllɐʇsuᴉ lɐuoᴉʇᴉppɐ uo puǝdǝp ʍou splɹoʍ ɹnoʎ ɟᴉ ʇnq ˋǝɔuɐʇsuᴉ ǝɥʇ oʇ ǝpɐɯ uǝǝq ǝʌɐɥ sǝɓuɐɥɔ ɟᴉ ɹoᴉʌɐɥǝq pǝʇɔǝdxǝun xᴉɟ ʎɐɯ sᴉɥ⟘ ˙uoᴉʇɐllɐʇsuᴉ lɐuᴉɓᴉɹo ǝɥʇ ɟo doʇ uo pǝppɐ ǝʌɐɥ noʎ ʇuǝʇuoɔ ɹo spoɯ ʎuɐ ɓuᴉʌoɯǝɹ ˋʞɔɐdpoɯ ǝɥʇ ʎq pǝpᴉʌoɹd sᴉ ʇɐɥʍ oʇ ʇuǝʇuoɔ pǝᴉɟᴉpoɯ ɹo pǝllɐʇsuᴉ llɐ ʇǝsǝɹ llᴉʍ ɓuᴉllɐʇsuᴉǝᴚ"
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "¿ǝɔuɐʇsuᴉ sᴉɥʇ llɐʇsuᴉǝɹ oʇ ʇuɐʍ noʎ ǝɹns noʎ ǝɹⱯ"
},
"instance.settings.tabs.installation.reinstall.description": {
"message": "˙ʞɔɐdpoɯ lɐuᴉɓᴉɹo ǝɥʇ ɟo doʇ uo pǝppɐ ǝʌɐɥ noʎ ʇuǝʇuoɔ ɹo spoɯ ʎuɐ ɓuᴉʌoɯǝɹ ˋǝʇɐʇs lɐuᴉɓᴉɹo sʇᴉ oʇ ʇuǝʇuoɔ s,ǝɔuɐʇsuᴉ ǝɥʇ sʇǝsǝᴚ"
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "ʞɔɐdpoɯ llɐʇsuᴉǝᴚ"
},
"instance.settings.tabs.installation.repair.button": {
"message": "ɹᴉɐdǝᴚ"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "ɓuᴉɹᴉɐdǝᴚ"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "˙spoɯ pǝllɐʇsuᴉ oʇ pǝʇɐlǝɹ sǝɥsɐɹɔ ɹo sǝnssᴉ ǝʌlosǝɹ ʇou llᴉʍ ʇnq ˋsɹoɹɹǝ pǝʇɐlǝɹ-ɹǝɥɔunɐl oʇ ǝnp ɓuᴉɥɔunɐl ʇou sᴉ ǝɯɐɓ ɹnoʎ ɟᴉ sǝnssᴉ ǝʌlosǝɹ ʎɐɯ sᴉɥ⟘ ˙uoᴉʇdnɹɹoɔ ɹoɟ sʞɔǝɥɔ puɐ sǝᴉɔuǝpuǝdǝp ʇɟɐɹɔǝuᴉW sllɐʇsuᴉǝɹ ɓuᴉɹᴉɐdǝᴚ"
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "¿ǝɔuɐʇsuᴉ ɹᴉɐdǝᴚ"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "ssǝɹɓoɹd uᴉ ɹᴉɐdǝᴚ"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "ʇuǝɹɹnɔ oʇ ʇǝsǝᴚ"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "suoᴉsɹǝʌ llɐ ʍoɥS"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "uoᴉsɹǝʌ ǝɓuɐɥɔ"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "llɐʇsuᴉ"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "llɐʇsuᴉǝɹ"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "ɹᴉɐdǝɹ"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "ɓuᴉllɐʇsuᴉ ǝlᴉɥʍ {action} ʇouuɐƆ"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "ǝuᴉlɟɟo ǝlᴉɥʍ {action} ʇouuɐƆ"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "ɓuᴉɹᴉɐdǝɹ ǝlᴉɥʍ {action} ʇouuɐƆ"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(uoᴉsɹǝʌ uʍouʞun)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "ǝɔuɐʇsuᴉ ʞuᴉlu∩"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "˙lɐɯɹou ɐ ǝɯoɔǝq llᴉʍ ʇᴉ puɐ sǝʇɐpdn ʞɔɐdpoɯ ǝʌᴉǝɔǝɹ ɹǝɓuol ou llᴉʍ no⅄ ˙ǝɔuɐʇsuᴉ ʍǝu ʎlǝɹᴉʇuǝ uɐ ɓuᴉʇɐǝɹɔ ʇnoɥʇᴉʍ ʇᴉ ʞuᴉl-ǝɹ oʇ ǝlqɐ ǝq ʇou llᴉʍ noʎ ˋpǝǝɔoɹd noʎ ɟI"
},
"instance.settings.tabs.installation.unlink.confirm.title": {
"message": "¿ǝɔuɐʇsuᴉ sᴉɥʇ ʞuᴉlun oʇ ʇuɐʍ noʎ ǝɹns noʎ ǝɹⱯ"
},
"instance.settings.tabs.installation.unlink.description": {
"message": "˙ʞɔɐdpoɯ ǝɥʇ ɯoɹɟ ǝɔuɐʇsuᴉ sᴉɥʇ ʇɔǝuuoɔsᴉp ʎlʇuǝuɐɯɹǝd llᴉʍ ɓuᴉʞuᴉlu∩ ˙uoᴉsɹǝʌ ʇɟɐɹɔǝuᴉW ɹo ɹǝpɐol poɯ ǝɥʇ ǝɓuɐɥɔ ʇ,uɐɔ noʎ puɐ pǝʇɐpdn ǝq ʇ,uɐɔ spoɯ suɐǝɯ ɥɔᴉɥʍ ˋʞɔɐdpoɯ ɐ oʇ pǝʞuᴉl sᴉ ǝɔuɐʇsuᴉ sᴉɥ⟘"
},
"instance.settings.tabs.installation.unlink.title": {
"message": "ʞɔɐdpoɯ ɯoɹɟ ʞuᴉlu∩"
},
"instance.settings.tabs.java": {
"message": "ʎɹoɯǝɯ puɐ ɐʌɐſ"
},
"instance.settings.tabs.java.environment-variables": {
"message": "sǝlqɐᴉɹɐʌ ʇuǝɯuoɹᴉʌuƎ"
},
"instance.settings.tabs.java.hooks": {
"message": "sʞooH"
},
"instance.settings.tabs.java.java-arguments": {
"message": "sʇuǝɯnɓɹɐ ɐʌɐſ"
},
"instance.settings.tabs.java.java-installation": {
"message": "uoᴉʇɐllɐʇsuᴉ ɐʌɐſ"
},
"instance.settings.tabs.java.java-memory": {
"message": "pǝʇɐɔollɐ ʎɹoɯǝW"
},
"instance.settings.tabs.window": {
"message": "ʍopuᴉM"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "sɓuᴉʇʇǝs ʍopuᴉʍ ɯoʇsnƆ"
},
"instance.settings.tabs.window.fullscreen": {
"message": "uǝǝɹɔsllnℲ"
},
"instance.settings.tabs.window.fullscreen.description": {
"message": "˙(ʇxʇ˙suoᴉʇdo ɓuᴉsn) pǝɥɔunɐl uǝɥʍ uǝǝɹɔs llnɟ uᴉ ʇɹɐʇs ǝɯɐɓ ǝɥʇ ǝʞɐW"
},
"instance.settings.tabs.window.height": {
"message": "ʇɥɓᴉǝH"
},
"instance.settings.tabs.window.height.description": {
"message": "˙pǝɥɔunɐl uǝɥʍ ʍopuᴉʍ ǝɯɐɓ ǝɥʇ ɟo ʇɥɓᴉǝɥ ǝɥ⟘"
},
"instance.settings.tabs.window.height.enter": {
"message": "˙˙˙ʇɥɓᴉǝɥ ɹǝʇuƎ"
},
"instance.settings.tabs.window.width": {
"message": "ɥʇpᴉM"
},
"instance.settings.tabs.window.width.description": {
"message": "˙pǝɥɔunɐl uǝɥʍ ʍopuᴉʍ ǝɯɐɓ ǝɥʇ ɟo ɥʇpᴉʍ ǝɥ⟘"
},
"instance.settings.tabs.window.width.enter": {
"message": "˙˙˙ɥʇpᴉʍ ɹǝʇuƎ"
},
"instance.settings.title": {
"message": "sɓuᴉʇʇǝS"
},
"instance.worlds.a_minecraft_server": {
"message": "ɹǝʌɹǝS ʇɟɐɹɔǝuᴉW Ɐ"
},
"instance.worlds.cant_connect": {
"message": "ɹǝʌɹǝs oʇ ʇɔǝuuoɔ ʇ,uɐƆ"
},
"instance.worlds.copy_address": {
"message": "ssǝɹppɐ ʎdoƆ"
},
"instance.worlds.dont_show_on_home": {
"message": "ǝɯoH uo ʍoɥs ʇ,uoᗡ"
},
"instance.worlds.filter.available": {
"message": "ǝlqɐlᴉɐʌⱯ"
},
"instance.worlds.game_already_open": {
"message": "uǝdo ʎpɐǝɹlɐ sᴉ ǝɔuɐʇsuI"
},
"instance.worlds.hardcore": {
"message": "ǝpoɯ ǝɹoɔpɹɐH"
},
"instance.worlds.incompatible_server": {
"message": "ǝlqᴉʇɐdɯoɔuᴉ sᴉ ɹǝʌɹǝS"
},
"instance.worlds.no_contact": {
"message": "pǝʇɔɐʇuoɔ ǝq ʇ,uplnoɔ ɹǝʌɹǝS"
},
"instance.worlds.no_server_quick_play": {
"message": "+૨˙0˙⇂ ɐɥdlⱯ ʇɟɐɹɔǝuᴉW uo sɹǝʌɹǝs oʇuᴉ ʇɥɓᴉɐɹʇs dɯnſ ʎluo uɐɔ no⅄"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "+0ᘕ˙⇂ ʇɟɐɹɔǝuᴉW uo splɹoʍ ɹǝʎɐldǝlɓuᴉs oʇuᴉ ʇɥɓᴉɐɹʇs dɯnſ ʎluo uɐɔ no⅄"
},
"instance.worlds.play_instance": {
"message": "ǝɔuɐʇsuᴉ ʎɐlԀ"
},
"instance.worlds.type.server": {
"message": "ɹǝʌɹǝS"
},
"instance.worlds.type.singleplayer": {
"message": "ɹǝʎɐldǝlɓuᴉS"
},
"instance.worlds.view_instance": {
"message": "ǝɔuɐʇsuᴉ ʍǝᴉΛ"
},
"instance.worlds.world_in_use": {
"message": "ǝsn uᴉ sᴉ plɹoM"
},
"search.filter.locked.instance": {
"message": "ǝɔuɐʇsuᴉ ǝɥʇ ʎq pǝpᴉʌoɹԀ"
},
"search.filter.locked.instance-game-version.title": {
"message": "ǝɔuɐʇsuᴉ ǝɥʇ ʎq pǝpᴉʌoɹd sᴉ uoᴉsɹǝʌ ǝɯɐ⅁"
},
"search.filter.locked.instance-loader.title": {
"message": "ǝɔuɐʇsuᴉ ǝɥʇ ʎq pǝpᴉʌoɹd sᴉ ɹǝpɐoꞀ"
},
"search.filter.locked.instance.sync": {
"message": "ǝɔuɐʇsuᴉ ɥʇᴉʍ ɔuʎS"
}
}
+78 -15
View File
@@ -5,6 +5,63 @@
"app.auth-servers.unreachable.header": {
"message": "Cannot reach authentication servers"
},
"app.modal.install-to-play.content-required": {
"message": "Content required"
},
"app.modal.install-to-play.header": {
"message": "Install to play"
},
"app.modal.install-to-play.install-button": {
"message": "Install"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# mods}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Required modpack"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "This server requires mods to play. Click Install to set up the required files from Modrinth, then launch directly into the server."
},
"app.modal.install-to-play.shared-instance": {
"message": "Shared instance"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "Shared server instance"
},
"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.published-date": {
"message": "{date, date, long}"
},
"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."
},
@@ -23,39 +80,42 @@
"app.settings.tabs.java-installations": {
"message": "Java installations"
},
"app.settings.tabs.language": {
"message": "Language"
},
"app.settings.tabs.privacy": {
"message": "Privacy"
},
"app.settings.tabs.resource-management": {
"message": "Resource management"
},
"app.update-toast.body": {
"app.update-popup.body": {
"message": "Modrinth App v{version} is ready to install! Reload to update now, or automatically when you close Modrinth App."
},
"app.update-toast.body.download-complete": {
"app.update-popup.body.download-complete": {
"message": "Modrinth App v{version} has finished downloading. Reload to update now, or automatically when you close Modrinth App."
},
"app.update-toast.body.metered": {
"app.update-popup.body.linux": {
"message": "Modrinth App v{version} is available. Use your package manager to update for the latest features and fixes!"
},
"app.update-popup.body.metered": {
"message": "Modrinth App v{version} is available now! Since you're on a metered network, we didn't automatically download it."
},
"app.update-toast.changelog": {
"app.update-popup.changelog": {
"message": "Changelog"
},
"app.update-toast.download": {
"app.update-popup.download": {
"message": "Download ({size})"
},
"app.update-toast.downloading": {
"message": "Downloading..."
"app.update-popup.download-complete": {
"message": "Download complete"
},
"app.update-toast.reload": {
"app.update-popup.reload": {
"message": "Reload"
},
"app.update-toast.title": {
"app.update-popup.title": {
"message": "Update available"
},
"app.update-toast.title.download-complete": {
"message": "Download complete"
},
"app.update.complete-toast.text": {
"message": "Click here to view the changelog."
},
@@ -404,6 +464,12 @@
"instance.settings.tabs.installation.unknown-version": {
"message": "(unknown version)"
},
"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"
},
@@ -467,9 +533,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Enter width..."
},
"instance.settings.title": {
"message": "Settings"
},
"instance.worlds.a_minecraft_server": {
"message": "A Minecraft Server"
},
@@ -1,341 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "Programista modo ebligita."
},
"app.settings.tabs.appearance": {
"message": "Aspekto"
},
"app.settings.tabs.default-instance-options": {
"message": "Defaŭltaj agordoj de aperoj"
},
"app.settings.tabs.feature-flags": {
"message": "Trajtoflagoj"
},
"app.settings.tabs.java-installations": {
"message": "Instaloj de Java"
},
"app.settings.tabs.privacy": {
"message": "Privateco"
},
"instance.add-server.add-and-play": {
"message": "Aldoni kaj ludi"
},
"instance.add-server.add-server": {
"message": "Aldoni servilon"
},
"instance.add-server.resource-pack.disabled": {
"message": "Neebligita"
},
"instance.add-server.resource-pack.enabled": {
"message": "Ebligita"
},
"instance.add-server.resource-pack.prompt": {
"message": "Petu"
},
"instance.add-server.title": {
"message": "Aldoni servilon"
},
"instance.edit-server.title": {
"message": "Redakti servilon"
},
"instance.edit-world.hide-from-home": {
"message": "Kaŝi el la Hejma paĝo"
},
"instance.edit-world.name": {
"message": "Nomo"
},
"instance.edit-world.placeholder-name": {
"message": "Mondo de Minecraft"
},
"instance.edit-world.reset-icon": {
"message": "Restarigi simbolon"
},
"instance.edit-world.title": {
"message": "Redakti mondon"
},
"instance.filter.disabled": {
"message": "Neebligitaj projektoj"
},
"instance.filter.updates-available": {
"message": "Ĝisdatigoj disponeblas"
},
"instance.server-modal.address": {
"message": "Adreso"
},
"instance.server-modal.name": {
"message": "Nomo"
},
"instance.server-modal.placeholder-name": {
"message": "Servilo de Minecraft"
},
"instance.server-modal.resource-pack": {
"message": "Rimedo-pako"
},
"instance.settings.tabs.general": {
"message": "Ĝeneralo"
},
"instance.settings.tabs.general.delete": {
"message": "Forigo de apero"
},
"instance.settings.tabs.general.delete.button": {
"message": "Forigi aperon"
},
"instance.settings.tabs.general.delete.description": {
"message": "Porĉiame forigas aperon de via aparato, inkluzivo de mondoj, kaj ĉiu instaligita enhavon. Estu zorgema ĉar kiam oni forigus aperon, ĝi ne estus restaŭrebla."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Forigado..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "Duobligi"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "Ne povas duobligi dum instalado."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Duobligo de apero"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Kopias la aperon, inkluzivo de mondoj, agordoj, modifoj, ktp."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Redakti simbolon"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Forigi simbolon"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "Ŝanĝi simbolon"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "Elekti simbolon"
},
"instance.settings.tabs.general.library-groups": {
"message": "Grupoj de la biblioteko"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "Krei novan grupon"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "Grupoj de la biblioteko ebligas vin organizi la aperojn en fakojn en la biblioteko."
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "Entajpu nomon de grupo"
},
"instance.settings.tabs.general.name": {
"message": "Nomo"
},
"instance.settings.tabs.hooks": {
"message": "Lanĉaj hokoj"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Propraj lanĉaj hokoj"
},
"instance.settings.tabs.hooks.post-exit": {
"message": "Post fermo"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "Plenumata post kiam ludo fermas."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Entajpu komandon de post fermo..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Antaŭ malfermo"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "Plenumata antaŭ kiam ludo malfermas."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Entajpu komandon de antaŭ malfermo..."
},
"instance.settings.tabs.hooks.title": {
"message": "Hokoj de luda lanĉo"
},
"instance.settings.tabs.installation": {
"message": "Instalo"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Ŝanĝi version"
},
"instance.settings.tabs.installation.change-version.button.install": {
"message": "Instali"
},
"instance.settings.tabs.installation.change-version.button.installing": {
"message": "Instalado"
},
"instance.settings.tabs.installation.change-version.cannot-while-fetching": {
"message": "Elŝutado de modifo-pakaĵaj versioj"
},
"instance.settings.tabs.installation.change-version.in-progress": {
"message": "Instalado de nova versio"
},
"instance.settings.tabs.installation.currently-installed": {
"message": "Nune instalata"
},
"instance.settings.tabs.installation.game-version": {
"message": "Luda versio"
},
"instance.settings.tabs.installation.install": {
"message": "Instali"
},
"instance.settings.tabs.installation.install.in-progress": {
"message": "Instalado okazas"
},
"instance.settings.tabs.installation.loader-version": {
"message": "Versio de {loader}"
},
"instance.settings.tabs.installation.minecraft-version": {
"message": "Minecraft {version}"
},
"instance.settings.tabs.installation.no-connection": {
"message": "Ne povas elŝuti detalojn de ligita modifo-pakaĵo. Bonvolu kontroli la konekton de interreto."
},
"instance.settings.tabs.installation.platform": {
"message": "Platformo"
},
"instance.settings.tabs.installation.reinstall.button": {
"message": "Reinstali modifo-pakaĵon"
},
"instance.settings.tabs.installation.reinstall.button.reinstalling": {
"message": "Reinstalado de modifo-pakaĵo"
},
"instance.settings.tabs.installation.reinstall.confirm.title": {
"message": "Ĉu vi certas, ke vi volas reinstali la aperon?"
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "Reinstalo de modifo-pakaĵo"
},
"instance.settings.tabs.installation.repair.button": {
"message": "Ripari"
},
"instance.settings.tabs.installation.repair.button.repairing": {
"message": "Riparado"
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Ĉu riparu aperon?"
},
"instance.settings.tabs.installation.repair.in-progress": {
"message": "Riparo okazas"
},
"instance.settings.tabs.installation.reset-selections": {
"message": "Restarigi al nuna"
},
"instance.settings.tabs.installation.show-all-versions": {
"message": "Montri ĉiun version"
},
"instance.settings.tabs.installation.tooltip.action.change-version": {
"message": "ŝanĝi version"
},
"instance.settings.tabs.installation.tooltip.action.install": {
"message": "instali"
},
"instance.settings.tabs.installation.tooltip.action.reinstall": {
"message": "reinstali"
},
"instance.settings.tabs.installation.tooltip.action.repair": {
"message": "ripari"
},
"instance.settings.tabs.installation.tooltip.cannot-while-installing": {
"message": "Ne povas {action} dum instalado"
},
"instance.settings.tabs.installation.tooltip.cannot-while-offline": {
"message": "Ne povas {action} kiam neenreta"
},
"instance.settings.tabs.installation.tooltip.cannot-while-repairing": {
"message": "Ne povas {action} dum riparado"
},
"instance.settings.tabs.installation.unknown-version": {
"message": "(nekonata versio)"
},
"instance.settings.tabs.installation.unlink.button": {
"message": "Malligi aperon"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Se vi daŭrus, vi ne povus re-ligi ĝin sen kreado de nova aperon. Vi ne daŭre ricevos ĝisdatigojn de modifo-pakaĵoj kaj ĝi normaliĝos."
},
"instance.settings.tabs.java": {
"message": "Java kaj memoro"
},
"instance.settings.tabs.java.hooks": {
"message": "Hokoj"
},
"instance.settings.tabs.java.java-arguments": {
"message": "Argumentoj de Java"
},
"instance.settings.tabs.java.java-installation": {
"message": "Instalo de Java"
},
"instance.settings.tabs.java.java-memory": {
"message": "Asigno de memoro"
},
"instance.settings.tabs.window": {
"message": "Fenestro"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "Propraj agordoj de fenestro"
},
"instance.settings.tabs.window.fullscreen": {
"message": "Tutekrano"
},
"instance.settings.tabs.window.fullscreen.description": {
"message": "Ludo lanĉiĝos tutekrane (uzante na options.txt)."
},
"instance.settings.tabs.window.height": {
"message": "Alto"
},
"instance.settings.tabs.window.height.description": {
"message": "Alto de la luda fenestro kiam lanĉata."
},
"instance.settings.tabs.window.height.enter": {
"message": "Entajpu alton..."
},
"instance.settings.tabs.window.width": {
"message": "Larĝo"
},
"instance.settings.tabs.window.width.description": {
"message": "Larĝo de la luda fenestro kiam lanĉata."
},
"instance.settings.tabs.window.width.enter": {
"message": "Entajpu larĝon..."
},
"instance.settings.title": {
"message": "Agordoj"
},
"instance.worlds.a_minecraft_server": {
"message": "Servilo de Minecraft"
},
"instance.worlds.cant_connect": {
"message": "Ne povas konektiĝi kun servilo"
},
"instance.worlds.copy_address": {
"message": "Kopii adreson"
},
"instance.worlds.dont_show_on_home": {
"message": "Ne montri en Hejmo"
},
"instance.worlds.filter.available": {
"message": "Disponeblaj"
},
"instance.worlds.game_already_open": {
"message": "Apero jam estas malferma"
},
"instance.worlds.play_instance": {
"message": "Ludi en apero"
},
"instance.worlds.type.server": {
"message": "Servilo"
},
"instance.worlds.type.singleplayer": {
"message": "Unu ludanto"
},
"instance.worlds.view_instance": {
"message": "Vidi aperon"
},
"instance.worlds.world_in_use": {
"message": "Mondo nune uzata"
},
"search.filter.locked.instance.sync": {
"message": "Sinkroni kun apero"
}
}
+93 -30
View File
@@ -1,4 +1,61 @@
{
"app.auth-servers.unreachable.body": {
"message": "Los servidores de autenticación de Minecraft pueden no estar funcionando en este momento. Verifica tu conexión a internet e inténtalo de nuevo más tarde."
},
"app.auth-servers.unreachable.header": {
"message": "No se puede acceder a los servidores de autenticación"
},
"app.modal.install-to-play.header": {
"message": "Instala para jugar"
},
"app.modal.install-to-play.install-button": {
"message": "Instalar"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# mods}}"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Este servidor requiere mods para jugar. Haz clic en instalar para configurar los archivos necesarios desde Modrinth."
},
"app.modal.install-to-play.shared-by-today": {
"message": "{name} compartió esta instancia contigo hoy."
},
"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} 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."
},
@@ -17,6 +74,9 @@
"app.settings.tabs.java-installations": {
"message": "Instalaciones de Java"
},
"app.settings.tabs.language": {
"message": "Idioma"
},
"app.settings.tabs.privacy": {
"message": "Privacidad"
},
@@ -24,13 +84,16 @@
"message": "Gestión de recursos"
},
"app.update-toast.body": {
"message": La aplicación Modrinth v{version} está lista para instalarse! Actualiza ahora o automáticamente al cerrar la aplicación Modrinth."
"message": "¡Modrinth App v{version} lista para instalar! Actualiza ahora o automáticamente al cerrar la aplicación."
},
"app.update-toast.body.download-complete": {
"message": "La descarga de la aplicación Modrinth v{version} ha finalizado. Actualice ahora o automáticamente al cerrar la aplicación Modrinth."
"message": "La descarga de la Modrinth App v{version} ha finalizado. Actualiza ahora o automáticamente al cerrar la aplicación Modrinth."
},
"app.update-toast.body.linux": {
"message": "La aplicación Modrinth v{version} ya está disponible. ¡Utiliza tu gestor de paquetes para actualizarla y disfrutar de las últimas funciones y correcciones!"
},
"app.update-toast.body.metered": {
"message": La aplicación Modrinth v{version} ya está disponible! Como estás conectado a una red con límite de datos, no la hemos descargado automáticamente."
"message": "¡Modrinth App v{version} ya está disponible! Como estás en una red con límite de datos, no se descargó automáticamente."
},
"app.update-toast.changelog": {
"message": "Registro de cambios"
@@ -38,6 +101,9 @@
"app.update-toast.download": {
"message": "Descargar ({size})"
},
"app.update-toast.download-page": {
"message": "Descargar"
},
"app.update-toast.downloading": {
"message": "Descargando..."
},
@@ -51,7 +117,7 @@
"message": "Descarga completada"
},
"app.update.complete-toast.text": {
"message": "Haga clic aquí para ver el registro de cambios."
"message": "Haz clic aquí para ver el registro de cambios."
},
"app.update.complete-toast.title": {
"message": "¡La versión {version} se ha instalado correctamente!"
@@ -78,10 +144,10 @@
"message": "Añadiendo un amigo"
},
"friends.add-friend.username.description": {
"message": "¡Podría ser distinto a su nombre de Minecraft!"
"message": "¡Podría ser distinto a su nombre de usuario de Minecraft!"
},
"friends.add-friend.username.placeholder": {
"message": "Escribe el nombre de usuario de Modrinth..."
"message": "Ingresa tu nombre de usuario de Modrinth..."
},
"friends.add-friend.username.title": {
"message": "¿Cuál es el nombre de usuario de Modrinth de tu amigo?"
@@ -159,7 +225,7 @@
"message": "Mundo de Minecraft"
},
"instance.edit-world.reset-icon": {
"message": "Resetear ícono"
"message": "Restablecer ícono"
},
"instance.edit-world.title": {
"message": "Editar mundo"
@@ -180,7 +246,7 @@
"message": "Servidor de Minecraft"
},
"instance.server-modal.resource-pack": {
"message": "Resource pack"
"message": "Paquete de recursos"
},
"instance.settings.tabs.general": {
"message": "General"
@@ -192,7 +258,7 @@
"message": "Eliminar instancia"
},
"instance.settings.tabs.general.delete.description": {
"message": "Elimina permanentemente una instancia de tu dispositivo, incluyendo tus mundos, configuraciones y todo el contenido instalado. Ten cuidado, ya que una vez que elimines una instancia no hay forma de recuperarla."
"message": "Elimina permanentemente una instancia de tu dispositivo, incluidos tus mundos, configuraciones y todo el contenido instalado. Ten cuidado, una vez eliminada, no hay forma de recuperarla."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Eliminando..."
@@ -213,7 +279,7 @@
"message": "Editar ícono"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "Remover ícono"
"message": "Eliminar ícono"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "Reemplazar ícono"
@@ -231,16 +297,16 @@
"message": "Los grupos de la librería te ayudan a organizar tus instancias en diferentes secciones en tu librería."
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "Escribe el nombre del grupo"
"message": "Ingresa el nombre del grupo"
},
"instance.settings.tabs.general.name": {
"message": "Nombre"
},
"instance.settings.tabs.hooks": {
"message": "Lanzar hooks"
"message": "Hooks de inicio"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Hooks personalizados"
"message": "Hooks de inicio personalizados"
},
"instance.settings.tabs.hooks.description": {
"message": "Los hooks permiten que usuarios avanzados ejecuten comandos del sistema antes y despues de lanzar el juego."
@@ -249,7 +315,7 @@
"message": "Post-cierre"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "Ejecutados luego de que el juego se cierra."
"message": "Ejecutados después de que el juego se cierre."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Introduce el comando post-cierre..."
@@ -261,19 +327,19 @@
"message": "Ejecutados antes de que la instancia inicie."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "Introducir comando pre-inicio..."
"message": "Introduce el comando pre-inicio..."
},
"instance.settings.tabs.hooks.title": {
"message": "Hooks de inicio de juego"
"message": "Hooks de inicio del juego"
},
"instance.settings.tabs.hooks.wrapper": {
"message": "Wrapper"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "Comando de capa para lanzar Minecraft."
"message": "Comando Wrapper para iniciar Minecraft."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "Introduce el comando capa..."
"message": "Introduce el comando Wrapper..."
},
"instance.settings.tabs.installation": {
"message": "Instalación"
@@ -282,7 +348,7 @@
"message": "{platform} {version} ya está instalado para Minecraft {game_version}"
},
"instance.settings.tabs.installation.change-version.already-installed.vanilla": {
"message": "{game_version} vanilla ya está instalado"
"message": "Vanilla {game_version} ya está instalada"
},
"instance.settings.tabs.installation.change-version.button": {
"message": "Cambiar versión"
@@ -327,7 +393,7 @@
"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 esta disponible para Minecraft {version}. Prueba con otro mod loader."
"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."
@@ -342,13 +408,13 @@
"message": "Reinstalando modpack"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Reinstalar restablecerá todo el contenido instalado o modificado a lo que proporciona el modpack, eliminando cualquier mod o contenido que hayas agregado encima de 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 afectar los mundos existentes."
"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 encima del modpack original."
"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"
@@ -360,7 +426,7 @@
"message": "Reparando"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "Reparar reinstala las dependencias de Minecraft y verifica si hay archivos dañados. Esto puede solucionar problemas si tu juego no se inicia por errores relacionados con el launcher, pero no resolverá problemas causados por mods instalados."
"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?"
@@ -402,13 +468,13 @@
"message": "Desvincular instancia"
},
"instance.settings.tabs.installation.unlink.confirm.description": {
"message": "Si continúas, no podrás volver a vincularla sin crear una instancia completamente nueva. Ya no recibirás actualizaciones del modpack y se convertirá en una instancia normal."
"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 se pueden actualizar y no puedes cambiar el mod loader ni la versión de Minecraft. Desvincularla desconectará permanentemente esta instancia del modpack."
"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"
@@ -435,13 +501,13 @@
"message": "Ventana"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "Opciones personalizadas de ventana"
"message": "Configuración de ventana personalizada"
},
"instance.settings.tabs.window.fullscreen": {
"message": "Pantalla completa"
},
"instance.settings.tabs.window.fullscreen.description": {
"message": "Inicia el juego en pantalla completa al ejecutarlo (usando options.txt)."
"message": "Inicia el juego en pantalla completa al iniciarlo (usando options.txt)."
},
"instance.settings.tabs.window.height": {
"message": "Altura"
@@ -461,9 +527,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Ingresa el ancho..."
},
"instance.settings.title": {
"message": "Configuración"
},
"instance.worlds.a_minecraft_server": {
"message": "Un servidor de Minecraft"
},
+70 -7
View File
@@ -1,4 +1,61 @@
{
"app.auth-servers.unreachable.body": {
"message": "Los servidores de autenticación de Minecraft pueden no estar funcionando en este momento. Verifica tu conexión a internet e inténtalo de nuevo más tarde."
},
"app.auth-servers.unreachable.header": {
"message": "No se puede conectar con los servidores de autenticación"
},
"app.modal.install-to-play.header": {
"message": "Instala para jugar"
},
"app.modal.install-to-play.install-button": {
"message": "Instalar"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# mods}}"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Este servidor requiere mods para jugar. Haz clic en instalar para configurar los archivos necesarios de Modrinth."
},
"app.modal.install-to-play.shared-by-today": {
"message": "{name} ha compartido contigo hoy esta instancia."
},
"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.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."
},
@@ -17,6 +74,9 @@
"app.settings.tabs.java-installations": {
"message": "Instalaciones de Java"
},
"app.settings.tabs.language": {
"message": "Idioma"
},
"app.settings.tabs.privacy": {
"message": "Privacidad"
},
@@ -29,8 +89,11 @@
"app.update-toast.body.download-complete": {
"message": "La descarga de la versión v{version} de Modrinth ha finalizado. Actualice ahora o automáticamente al cerrar la aplicación."
},
"app.update-toast.body.linux": {
"message": "Modrinth App v{version} está disponible. ¡Usa tu gestor de paquetes para actualizar a la última versión con nuevas funciones y correcciones!"
},
"app.update-toast.body.metered": {
"message": "¡La versión v{version} de Modrinth ya está disponible! Como estás conectado a una red con límite de datos, no la hemos descargado automáticamente."
"message": "¡La versión v{version} de Modrinth App ya está disponible! Como estás conectado a una red con límite de datos, no la hemos descargado automáticamente."
},
"app.update-toast.changelog": {
"message": "Registro de cambios"
@@ -38,6 +101,9 @@
"app.update-toast.download": {
"message": "Descarga ({size})"
},
"app.update-toast.download-page": {
"message": "Descargar"
},
"app.update-toast.downloading": {
"message": "Descargando..."
},
@@ -87,7 +153,7 @@
"message": "¿Cuál es el apodo de tu amigo en Modrinth?"
},
"friends.add-friends-to-share": {
"message": "<link>Añade amigos</link> para ver a qué están jugando."
"message": "<link>Añade amigos</link> para ver a qué están jugando!"
},
"friends.friend.cancel-request": {
"message": "Cancelar petición"
@@ -126,7 +192,7 @@
"message": "{title}: {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>Inicia sesión en una cuenta Modrinth</link> para añadir amigos y ver a qué están jugando."
"message": "<link>Inicia sesión en una cuenta Modrinth</link> para añadir amigos y ver a qué están jugando!"
},
"instance.add-server.add-and-play": {
"message": "Añadir y jugar"
@@ -270,7 +336,7 @@
"message": "Wrapper"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": ".."
"message": "comando Wrapper para lanzar Minecraft."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "Introducir comando para el wrapper..."
@@ -461,9 +527,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Introduzca el ancho..."
},
"instance.settings.title": {
"message": "Ajustes"
},
"instance.worlds.a_minecraft_server": {
"message": "Un Servidor de Minecraft"
},
@@ -1,107 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "Arendajarežiim sisse lülitatud."
},
"app.settings.tabs.appearance": {
"message": "Välimus"
},
"app.settings.tabs.default-instance-options": {
"message": "Vaikimisi instantsi valikud"
},
"app.settings.tabs.feature-flags": {
"message": "Funktsioonimärgid"
},
"app.settings.tabs.java-installations": {
"message": "Java installatsioonid"
},
"app.settings.tabs.privacy": {
"message": "Privaatsus"
},
"app.settings.tabs.resource-management": {
"message": "Ressursside haldus"
},
"instance.add-server.add-and-play": {
"message": "Lisa ja mängi"
},
"instance.add-server.add-server": {
"message": "Lisa server"
},
"instance.add-server.resource-pack.disabled": {
"message": "Väljas"
},
"instance.add-server.resource-pack.enabled": {
"message": "Sees"
},
"instance.add-server.resource-pack.prompt": {
"message": "Küsi"
},
"instance.add-server.title": {
"message": "Lisa server"
},
"instance.edit-server.title": {
"message": "Muuda server"
},
"instance.edit-world.hide-from-home": {
"message": "Peida koduleheküljelt"
},
"instance.edit-world.name": {
"message": "Nimi"
},
"instance.edit-world.placeholder-name": {
"message": "Minecrafti maailm"
},
"instance.edit-world.reset-icon": {
"message": "Lähtesta ikoon"
},
"instance.edit-world.title": {
"message": "Muuda maailm"
},
"instance.filter.disabled": {
"message": "Suletud projektid"
},
"instance.filter.updates-available": {
"message": "Uuendused on saadaval"
},
"instance.server-modal.address": {
"message": "Aadress"
},
"instance.server-modal.name": {
"message": "Nimi"
},
"instance.server-modal.placeholder-name": {
"message": "Minecrafti server"
},
"instance.server-modal.resource-pack": {
"message": "Ressursipakk"
},
"instance.settings.tabs.general": {
"message": "Üldised"
},
"instance.settings.tabs.general.delete": {
"message": "Kustuta instants"
},
"instance.settings.tabs.general.delete.button": {
"message": "Kustuta instants"
},
"instance.settings.tabs.general.delete.description": {
"message": "Kustutab instantsi seadmest alatiselt, sealhulgas maailmad, konfiguratsioonid ja kogu paigaldatud sisu. Ole ettevaatlik, kuna instantsi kustutamisel ei ole seda enam võimalik taastada."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Kustutab..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "Dubleeri"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "Pole võimalik dubleerida paigaldamisel."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "Dubleeri instants"
},
"instance.settings.tabs.general.name": {
"message": "Nimi"
},
"instance.settings.title": {
"message": "Sätted"
}
}
@@ -1,419 +0,0 @@
{
"app.settings.developer-mode-enabled": {
"message": "حالت برنامه‌نویس روشن شد."
},
"app.settings.tabs.appearance": {
"message": "ظاهر"
},
"app.settings.tabs.default-instance-options": {
"message": "گزینه‌های پیش‌فرض اینستنس (نسخهٔ جدا)"
},
"app.settings.tabs.feature-flags": {
"message": "سوییچ قابلیت‌ها"
},
"app.settings.tabs.java-installations": {
"message": "جاواهای نصب‌شده"
},
"app.settings.tabs.privacy": {
"message": "حریم خصوصی"
},
"app.settings.tabs.resource-management": {
"message": "مدیریت منابع"
},
"instance.add-server.add-and-play": {
"message": "اضافه کردن و پلی دادن"
},
"instance.add-server.add-server": {
"message": "اضافه کردن سرور"
},
"instance.add-server.resource-pack.disabled": {
"message": "غیرفعال"
},
"instance.add-server.resource-pack.enabled": {
"message": "فعال"
},
"instance.add-server.resource-pack.prompt": {
"message": "درخواست از سرور"
},
"instance.add-server.title": {
"message": "اضافه کردن سرور"
},
"instance.edit-server.title": {
"message": "ویرایش سرور"
},
"instance.edit-world.hide-from-home": {
"message": "مخفی کردن از صفحه ی اصلی"
},
"instance.edit-world.name": {
"message": "نام"
},
"instance.edit-world.placeholder-name": {
"message": "جهان ماینکرفت"
},
"instance.edit-world.reset-icon": {
"message": "ریست کردن آیکن"
},
"instance.edit-world.title": {
"message": "ویرایش جهان"
},
"instance.filter.disabled": {
"message": "پروزه های غیر فعال"
},
"instance.filter.updates-available": {
"message": "آپدیت موجوده"
},
"instance.server-modal.address": {
"message": "آدرس"
},
"instance.server-modal.name": {
"message": "نام"
},
"instance.server-modal.placeholder-name": {
"message": "سرور ماینکرفت"
},
"instance.server-modal.resource-pack": {
"message": "رسورس پک"
},
"instance.settings.tabs.general": {
"message": "تنظیمات کلی"
},
"instance.settings.tabs.general.delete": {
"message": "حذف اینستنس (نسخهٔ جدا)"
},
"instance.settings.tabs.general.delete.button": {
"message": "حذف اینستنس (نسخهٔ جدا)"
},
"instance.settings.tabs.general.delete.description": {
"message": "این کار یه اینستنس (نسخهٔ جدا) رو به‌طور کامل از دستگاهت پاک می‌کنه، شامل دنیاها، تنظیمات و همه محتوای نصب‌شده. مراقب باش، چون بعد از حذف، هیچ راهی برای بازیابی‌ش نیست."
},
"instance.settings.tabs.general.deleting.button": {
"message": "در حال حذف..."
},
"instance.settings.tabs.general.duplicate-button": {
"message": "دوپلیکیت"
},
"instance.settings.tabs.general.duplicate-button.tooltip.installing": {
"message": "نمیشه هنگام نصب دوپلیکیت کرد."
},
"instance.settings.tabs.general.duplicate-instance": {
"message": "دوپلیکیت کردن اینستنس (نسخهٔ جدا)"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "یه کپی از این اینستنس (نسخهٔ جدا) می‌سازه، شامل دنیاها، تنظیمات، مودها و بقیه چیزا."
},
"instance.settings.tabs.general.edit-icon": {
"message": "ویرایش آیکن"
},
"instance.settings.tabs.general.edit-icon.remove": {
"message": "حذف آیکن"
},
"instance.settings.tabs.general.edit-icon.replace": {
"message": "جایگزین آیکن"
},
"instance.settings.tabs.general.edit-icon.select": {
"message": "انتخاب آیکن"
},
"instance.settings.tabs.general.library-groups": {
"message": "گروه های کتابخانه"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "ساخت گروه کتابخانه ی جدید"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "گروه‌های کتابخانه به شما امکان می‌دهند اینستنس‌های خود را در بخش‌های مختلف کتابخانه مرتب کنید."
},
"instance.settings.tabs.general.library-groups.enter-name": {
"message": "نام گروه رو بنویس"
},
"instance.settings.tabs.general.name": {
"message": "نام"
},
"instance.settings.tabs.hooks": {
"message": "اجرای پیشرفته"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "شخصی سازی اجرا"
},
"instance.settings.tabs.hooks.description": {
"message": "اجرای پیشرفته به کاربران حرفه‌ای اجازه می‌ده قبل و بعد از اجرای بازی، بعضی کامند های سیستمی رو اجرا کنن."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "پس از خروج"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "پس از بسته شدن بازی اجرا شد."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "کامند بعد خروج رو بنویس..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "قبل از اجرا"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "قبل از اجرا شدن بازی ران میشه."
},
"instance.settings.tabs.hooks.pre-launch.enter": {
"message": "کامند قبل اجرا رو بنویس..."
},
"instance.settings.tabs.hooks.title": {
"message": "شخصی سازی اجرای بازی"
},
"instance.settings.tabs.hooks.wrapper": {
"message": "دستور میانجی"
},
"instance.settings.tabs.hooks.wrapper.description": {
"message": "دستور میانجی برای اجرای ماینکرفت."
},
"instance.settings.tabs.hooks.wrapper.enter": {
"message": "کامند میانجی را وارد کنید..."
},
"instance.settings.tabs.installation": {
"message": "نسخه‌های نصب‌شده"
},
"instance.settings.tabs.installation.change-version.already-installed.modded": {
"message": "{platform} {version} برای ماینکرفت {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": "ماینکرفت {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": "این اینستنس (نسخهٔ جدا) به یه مودپک لینک شده، ولی مودپک تو 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": "ترمیم کردن، وابستگی‌های ماینکرفت رو دوباره نصب می‌کنه و سالم بودنشون رو بررسی می‌کنه. این ممکنه مشکلاتی که باعث اجرا نشدن بازی رو حل کنه، ولی مشکلات یا کرش‌های مربوط به مودهای نصب‌شده رو درست نمی‌کنه."
},
"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": "جاوا و مقدار رم"
},
"instance.settings.tabs.java.environment-variables": {
"message": "متغیرهای محیطی"
},
"instance.settings.tabs.java.hooks": {
"message": "اجرای پیشرفته"
},
"instance.settings.tabs.java.java-arguments": {
"message": "پارامتر های جاوا"
},
"instance.settings.tabs.java.java-installation": {
"message": "جاوا های نصب شده"
},
"instance.settings.tabs.java.java-memory": {
"message": "رم گرفته شده"
},
"instance.settings.tabs.window": {
"message": "پنجره"
},
"instance.settings.tabs.window.custom-window-settings": {
"message": "شخصی سازی پنجره"
},
"instance.settings.tabs.window.fullscreen": {
"message": "تمام صفحه"
},
"instance.settings.tabs.window.fullscreen.description": {
"message": "بازی وقتی اجرا می‌شه به‌صورت تمام‌صفحه باز بشه (با استفاده از options.txt)."
},
"instance.settings.tabs.window.height": {
"message": "ارتفاع"
},
"instance.settings.tabs.window.height.description": {
"message": "ارتفاع پنجره‌ی بازی وقتی اجرا می‌شه."
},
"instance.settings.tabs.window.height.enter": {
"message": "ارتفاع رو وارد کن..."
},
"instance.settings.tabs.window.width": {
"message": "عرض"
},
"instance.settings.tabs.window.width.description": {
"message": "عرض پنجره ی بازی هنگام اجرا شدن."
},
"instance.settings.tabs.window.width.enter": {
"message": "عرض رو وارد کن..."
},
"instance.settings.title": {
"message": "تنظیمات"
},
"instance.worlds.a_minecraft_server": {
"message": "سرور ماینکرفت"
},
"instance.worlds.cant_connect": {
"message": "نمیشه به سرور متصل شد"
},
"instance.worlds.copy_address": {
"message": "کپی کردن آدرس"
},
"instance.worlds.dont_show_on_home": {
"message": "نشون ندادن روی صفحه ی اصلی"
},
"instance.worlds.filter.available": {
"message": "در درسترس"
},
"instance.worlds.game_already_open": {
"message": "این اینستنس (نسخهٔ جدا) در حال اجراست"
},
"instance.worlds.hardcore": {
"message": "حالت هاردکور"
},
"instance.worlds.incompatible_server": {
"message": "سرور ناسازگاره"
},
"instance.worlds.no_contact": {
"message": "سرور در دسترس نیست"
},
"instance.worlds.no_server_quick_play": {
"message": "می‌تونی فقط از نسخه‌ی ماینکرفت آلفای 1.0.5 به بعد مستقیم وارد سرورها بشی"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "می‌تونی فقط از نسخه‌ی ماینکرفت 1.20 به بعد مستقیم وارد جهان ماینکرفت بشی"
},
"instance.worlds.play_instance": {
"message": "اجرای اینستنس (نسخهٔ جدا)"
},
"instance.worlds.type.server": {
"message": "سرور"
},
"instance.worlds.type.singleplayer": {
"message": "سینگل پلیر"
},
"instance.worlds.view_instance": {
"message": "دیدن اینستنس (نسخهٔ جدا)"
},
"instance.worlds.world_in_use": {
"message": "جهان در حال استفادست"
},
"search.filter.locked.instance": {
"message": "ارائه‌شده توسط اینستنس (نسخهٔ جدا)"
},
"search.filter.locked.instance-game-version.title": {
"message": "ورژن بازی توسط اینستنس (نسخهٔ جدا) ارائه شده"
},
"search.filter.locked.instance-loader.title": {
"message": "لودر توسط اینستنس (نسخهٔ جدا) ارائه شده"
},
"search.filter.locked.instance.sync": {
"message": "سینک کردن با اینستنس"
}
}
+121 -4
View File
@@ -1,7 +1,16 @@
{
"app.auth-servers.unreachable.body": {
"message": "Minecraftin todennuspalvelimet eivät ehkä ole tällä hetkellä tavoitettavissa. Tarkista internetyhteytesi ja yritä myöhemmin uudelleen."
},
"app.auth-servers.unreachable.header": {
"message": "Todennuspalvelimiin ei saada yhteyttä"
},
"app.settings.developer-mode-enabled": {
"message": "Kehittäjätila käytössä."
},
"app.settings.downloading": {
"message": "Ladataan v{version}"
},
"app.settings.tabs.appearance": {
"message": "Ulkonäkö"
},
@@ -14,12 +23,123 @@
"app.settings.tabs.java-installations": {
"message": "Java asennukset"
},
"app.settings.tabs.language": {
"message": "Kieli"
},
"app.settings.tabs.privacy": {
"message": "Yksityisyys"
},
"app.settings.tabs.resource-management": {
"message": "Resurssien hallinta"
},
"app.update-toast.body": {
"message": "Modrinth-sovellus v{version} on valmis asennettavaksi! Lataa sovellus uudelleen päivittääksesi sen nyt tai automaattisesti, kun suljet Modrinth-sovelluksen."
},
"app.update-toast.body.download-complete": {
"message": "Modrinth-sovellus v{version} on ladattu. Lataa sovellus uudelleen päivittääksesi sen nyt tai automaattisesti, kun suljet Modrinth-sovelluksen."
},
"app.update-toast.body.metered": {
"message": "Modrinth-sovellus v{version} on nyt saatavilla! Koska käytät käyttömaksullista verkkoa, emme ladanneet sitä automaattisesti."
},
"app.update-toast.changelog": {
"message": "Muutosloki"
},
"app.update-toast.download": {
"message": "Lataa ({size})"
},
"app.update-toast.download-page": {
"message": "Lataa"
},
"app.update-toast.downloading": {
"message": "Ladataan..."
},
"app.update-toast.reload": {
"message": "Uudelleen lataa"
},
"app.update-toast.title": {
"message": "Päivitys saatavilla"
},
"app.update-toast.title.download-complete": {
"message": "Lataus valmis"
},
"app.update.complete-toast.text": {
"message": "Klikkaa tästä nähdäksesi muutoslokin."
},
"app.update.complete-toast.title": {
"message": "Versio {version} asennettiin onnistuneesti!"
},
"app.update.download-update": {
"message": "Lataa päivitys"
},
"app.update.downloading-update": {
"message": "Ladataan päivitystä ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Lataa uudelleen asentaaksesi päivityksen"
},
"friends.action.add-friend": {
"message": "Lisää ystävä"
},
"friends.action.view-friend-requests": {
"message": "{count} ystävä{count, plural, one {pyyntö} other {pyyntöä}}"
},
"friends.add-friend.submit": {
"message": "Lähetä kaveripyyntö"
},
"friends.add-friend.title": {
"message": "Lisätään kaveria"
},
"friends.add-friend.username.description": {
"message": "Se ei voi olla eri kuin heidän Minecraft-käyttäjänimi!"
},
"friends.add-friend.username.placeholder": {
"message": "Syötä Modrinth-käyttäjätunnus..."
},
"friends.add-friend.username.title": {
"message": "Mikä on ystäväsi Modrinth-käyttäjänimi?"
},
"friends.add-friends-to-share": {
"message": "<link>Lisää kavereita</link> nähdäksesi mitä he pelaavat!"
},
"friends.friend.cancel-request": {
"message": "Peruuta pyyntö"
},
"friends.friend.remove-friend": {
"message": "Poista ystävä"
},
"friends.friend.request-sent": {
"message": "Ystäväpyyntö lähetetty"
},
"friends.friend.view-profile": {
"message": "Näytä profiili"
},
"friends.heading": {
"message": "Ystävät"
},
"friends.heading.active": {
"message": "Aktiiviset"
},
"friends.heading.offline": {
"message": "Offline-tilassa"
},
"friends.heading.online": {
"message": "Online-tilassa"
},
"friends.heading.pending": {
"message": "Odotetaan"
},
"friends.no-friends-match": {
"message": "Ei ystäviä, jotka vastaavat ''{query}''"
},
"friends.search-friends-placeholder": {
"message": "Hae ystäviä..."
},
"friends.section.heading": {
"message": "{title} - {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>Kirjaudu Modrinth-tilille</link> lisätäksesi ystäviä ja nähdäksesi mitä he pelaavat!"
},
"instance.add-server.add-and-play": {
"message": "Lisää ja pelaa"
},
@@ -30,7 +150,7 @@
"message": "Poistettu käytöstä"
},
"instance.add-server.resource-pack.enabled": {
"message": "Päällä"
"message": "Käytössä"
},
"instance.add-server.resource-pack.prompt": {
"message": "Kehote"
@@ -353,9 +473,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Syötä leveys..."
},
"instance.settings.title": {
"message": "Asetukset"
},
"instance.worlds.a_minecraft_server": {
"message": "Minecraft palvelin"
},
+136 -19
View File
@@ -1,4 +1,61 @@
{
"app.auth-servers.unreachable.body": {
"message": "Maaaring hindi maaabot ang mga authentication server ng Minecraft sa ngayon. Tingnan mo ang iyong internet connection at muling subukan mamaya."
},
"app.auth-servers.unreachable.header": {
"message": "Hindi maabot ang mga authentication server"
},
"app.modal.install-to-play.header": {
"message": "Mag-install upang malaro"
},
"app.modal.install-to-play.install-button": {
"message": "I-install"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# na mod}}"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Ang server na ito ay nangangailangan ng mga mod upang malaro. Pindutin ang install upang mahanda ang mga kinakailangang file galing sa Modrinth."
},
"app.modal.install-to-play.shared-by-today": {
"message": "Ibinahagi ngayong araw ni {name} ang instansiyang ito sa iyo."
},
"app.modal.install-to-play.shared-instance": {
"message": "Binahaging instansiya"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "Binahaging instansiyang pang-server"
},
"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."
},
@@ -12,22 +69,28 @@
"message": "Mga pagpipilian sa default na instansiya"
},
"app.settings.tabs.feature-flags": {
"message": "Mga feature flag"
"message": "Mga hudyat ng tampok"
},
"app.settings.tabs.java-installations": {
"message": "Mga instalasyon ng Java"
},
"app.settings.tabs.language": {
"message": "Wika"
},
"app.settings.tabs.privacy": {
"message": "Pribasiya"
},
"app.settings.tabs.resource-management": {
"message": "Pamamahala ng resource"
"message": "Pamamahala ng paglalaan"
},
"app.update-toast.body": {
"message": "Ang Modrinth App v{version} ay handa nang ma-install. Mag-reload upang ma-update ngayon, o awtomatiko pagsara ng Modrinth App."
"message": "Ang Modrinth App v{version} ay handa nang ma-install. Mag-reload upang ma-update ngayon, o awtomatiko sa pagsara ng Modrinth App."
},
"app.update-toast.body.download-complete": {
"message": "Tapos nang ma-download ang Modrinth App v{version}. Mag-reload upang ma-update ngayon, o awtomatiko pagsara ng Modrinth App."
"message": "Tapos nang ma-download ang Modrinth App v{version}. Mag-reload upang ma-update ngayon, o awtomatiko sa pagsara ng Modrinth App."
},
"app.update-toast.body.linux": {
"message": "Magagamit na ngayon ang Modrinth App v{version}. Gamitin ang iyong package manager upang i-update sa pinabagong tampok at pag-aayos!"
},
"app.update-toast.body.metered": {
"message": "Magagamit na ngayon ang Modrinth App v{version}! Hindi namin dinanload kaagad dahil naka-metro ang inyong network."
@@ -38,6 +101,9 @@
"app.update-toast.download": {
"message": "I-download ({size})"
},
"app.update-toast.download-page": {
"message": "I-download"
},
"app.update-toast.downloading": {
"message": "Nagda-download..."
},
@@ -51,7 +117,7 @@
"message": "Nakumpleto ang pagdownload"
},
"app.update.complete-toast.text": {
"message": "Magpindot rito upang matingnan ang changelog."
"message": "Dito pumindot upang matingnan ang changelog."
},
"app.update.complete-toast.title": {
"message": "Tagumpay na na-install ang bersiyong {version}!"
@@ -126,7 +192,7 @@
"message": "{title} - {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>Mag-sign-in sa Modrinth account</link> upang maidagdag ang mga kaibigan at malaman ang kanilang nilalaro!"
"message": "<link>Mag-sign in sa Modrinth account</link> upang maidagdag ang mga kaibigan at malaman ang kanilang nilalaro!"
},
"instance.add-server.add-and-play": {
"message": "Idagdag at laruin"
@@ -186,13 +252,13 @@
"message": "General"
},
"instance.settings.tabs.general.delete": {
"message": "I-delete ang instansiya"
"message": "Tanggalin ang instansiya"
},
"instance.settings.tabs.general.delete.button": {
"message": "I-delete ang instansiya"
"message": "Tanggalin ang instansiya"
},
"instance.settings.tabs.general.delete.description": {
"message": "Permanenteng matatanggal ang instansiya sa iyong device, kasali na ang iyong mga mundo, konpigurasyon, at lahat ng nakainstall na kontento. Mag-ingat, kapag magtanggal ka ng instansiya ay hindi na ito mababawi."
"message": "Habambuhay na matatanggal ang instansiya sa iyong device, kasama ang iyong mga mundo, kompigurasyon, at lahat ng naka-install na kontento. Mag-ingat, kapag nagtanggal ka ng instansiya ay hindi na ito mababawi."
},
"instance.settings.tabs.general.deleting.button": {
"message": "Nagde-delete..."
@@ -207,7 +273,7 @@
"message": "I-duplicate ang instansiya"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Gagawan ng kopya ng instansiyang ito, kasali na ang mga mundo, konpigurasyon, mods, at iba pa."
"message": "Lilikhaan ng kopya ang instansiyang ito, kasama ang mga mundo, kumpigurasyon, mod, at iba pa."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Baguhin ang ikono"
@@ -225,7 +291,7 @@
"message": "Mga grupo ng librerya"
},
"instance.settings.tabs.general.library-groups.create": {
"message": "Gumawa ng bagong grupo"
"message": "Lumikha ng bagong grupo"
},
"instance.settings.tabs.general.library-groups.description": {
"message": "Binibigyan ng mga grupo ng librerya na iyong maayos ang iyong mga instansiya sa iba't-ibang pangkat in iyong librerya."
@@ -243,7 +309,7 @@
"message": "Mga custom na launch hook"
},
"instance.settings.tabs.hooks.description": {
"message": "Binibigyan-daan ng mga hook ang mga ekspertong user na makapagtakbo ng mga system command bago at pagkatapos ma-launch ang laro."
"message": "Binibigyan-daan ng mga hook ang mga ekspertong tagagamit na makapagtakbo ng mga system command bago at pagkatapos ma-launch ang laro."
},
"instance.settings.tabs.hooks.post-exit": {
"message": "Post-exist"
@@ -305,6 +371,9 @@
"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"
},
@@ -320,9 +389,15 @@
"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"
},
@@ -333,10 +408,13 @@
"message": "Ini-re-reinstall ang modpack"
},
"instance.settings.tabs.installation.reinstall.confirm.description": {
"message": "Ang pagrere-install ay maaaring mare-reset ang lahat ng na-install o binago na kontento sa kung anong ibibigay ng modpack, tatanggalin ang mga mods o kontentong idinagdag mo lalo na ang mga 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."
"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": "I-reset ang mga kontento ng instansiya sa orihinal niyang estado, tatanggalin ang mga mods o kontentong idinagdag mo lalo na ang mga orihinal na modpack."
"message": "Mare-reset ang mga kontento ng instansiya sa orihinal niyang estado, tatanggalin ang mga mods at kontentong idinagdag mo sa orihinal na modpack."
},
"instance.settings.tabs.installation.reinstall.title": {
"message": "I-reinstall ang modpack"
@@ -348,7 +426,7 @@
"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 o pag-crash na dulot nga mga na-install na mod."
"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?"
@@ -392,8 +470,11 @@
"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 o ang bersiyon ng Minecraft."
"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"
@@ -401,6 +482,9 @@
"instance.settings.tabs.java": {
"message": "Java at memorya"
},
"instance.settings.tabs.java.environment-variables": {
"message": "Environment variables"
},
"instance.settings.tabs.java.hooks": {
"message": "Mga hook"
},
@@ -422,24 +506,33 @@
"instance.settings.tabs.window.fullscreen": {
"message": "Fullscreen"
},
"instance.settings.tabs.window.fullscreen.description": {
"message": "Gagawing magsisimulang naka-fullscreen ang laro pag-launch (gamit ang options.txt)."
},
"instance.settings.tabs.window.height": {
"message": "Taas"
},
"instance.settings.tabs.window.height.description": {
"message": "Ang taas ng game window kung na-launch."
},
"instance.settings.tabs.window.height.enter": {
"message": "Ilagay ang taas..."
},
"instance.settings.tabs.window.width": {
"message": "Lapad"
},
"instance.settings.tabs.window.width.description": {
"message": "Ang lapad ng game window kung na-launch."
},
"instance.settings.tabs.window.width.enter": {
"message": "Ilagay ang lapad..."
},
"instance.settings.title": {
"message": "Mga Setting"
},
"instance.worlds.a_minecraft_server": {
"message": "Isang Minecraft Server"
},
"instance.worlds.cant_connect": {
"message": "Hndi makakonekta sa server"
},
"instance.worlds.copy_address": {
"message": "Kopyahin ang adres"
},
@@ -449,9 +542,24 @@
"instance.worlds.filter.available": {
"message": "Magagamit"
},
"instance.worlds.game_already_open": {
"message": "Bukas naman ang instansiya"
},
"instance.worlds.hardcore": {
"message": "Modong eksperto"
},
"instance.worlds.incompatible_server": {
"message": "Hindi magkatugma sa server"
},
"instance.worlds.no_contact": {
"message": "Hindi makontak ang server"
},
"instance.worlds.no_server_quick_play": {
"message": "Deretso kang makakalukso lamang sa mga server na nasa Minecraft Alpha 1.0.5+"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Deretso kang makakalukso lamang sa mga pang-isahang larong mundo na nasa Minecraft 1.20+"
},
"instance.worlds.play_instance": {
"message": "Laruin ang instansiya"
},
@@ -467,6 +575,15 @@
"instance.worlds.world_in_use": {
"message": "Ginagamit ang mundo"
},
"search.filter.locked.instance": {
"message": "Sagot na ng instansiya"
},
"search.filter.locked.instance-game-version.title": {
"message": "Sagot na ng instansiya ang bersiyon ng laro"
},
"search.filter.locked.instance-loader.title": {
"message": "Sagot na ng instansiya ang loader ng laro"
},
"search.filter.locked.instance.sync": {
"message": "Maki-sync sa instansiya"
}
+79 -16
View File
@@ -1,4 +1,61 @@
{
"app.auth-servers.unreachable.body": {
"message": "Les serveurs d'authentification de Minecraft sont peut-être actuellement hors ligne. Vérifiez votre connexion Internet et essayez à nouveau dans quelques instants."
},
"app.auth-servers.unreachable.header": {
"message": "Impossible de contacter les serveurs d'authentification"
},
"app.modal.install-to-play.header": {
"message": "Installer pour jouer"
},
"app.modal.install-to-play.install-button": {
"message": "Installer"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} other {# mods}}"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "Ce serveur nécessite des mods pour pouvoir y jouer. Cliquez sur installer pour mettre les fichiers de Modrinth en place."
},
"app.modal.install-to-play.shared-by-today": {
"message": "{name} a partagé cette instance avec vous aujourd'hui."
},
"app.modal.install-to-play.shared-instance": {
"message": "Instance partagée"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "Instance serveur partagée"
},
"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é."
},
@@ -17,6 +74,9 @@
"app.settings.tabs.java-installations": {
"message": "Installations de Java"
},
"app.settings.tabs.language": {
"message": "Langue"
},
"app.settings.tabs.privacy": {
"message": "Confidentialité"
},
@@ -24,25 +84,31 @@
"message": "Gestion des ressources"
},
"app.update-toast.body": {
"message": "L'application Modrinth v{version} est prêtes à être installé ! Relancez l'application pour faire la mise à jour maintenant ou la mise à jour se fera automatiquement lorsque vous fermerez l'application Modrinth."
"message": "Modrinth App v{version} est prête à être installée ! Relancez l'application pour faire la mise à jour maintenant, ou automatiquement à la fermeture de Modrinth App."
},
"app.update-toast.body.download-complete": {
"message": "L'application Modrinth v{version} a finis d'être téléchargé ! Relancez l'application pour faire la mise à jour maintenant ou la mise à jour se fera automatiquement lorsque vous fermerez l'application Modrinth."
"message": "Le téléchargement de Modrinth App v{version} est terminé ! Relancez l'application pour mettre à jour maintenant, ou automatiquement à la fermeture de Modrinth App."
},
"app.update-toast.body.linux": {
"message": "Modrith App v{version} est disponible. Utilisez votre gestionnaire de paquets pour obtenir les derniers changements et corrections de bugs !"
},
"app.update-toast.body.metered": {
"message": "L'application Modrinth v{version} est disponible dès maintenant ! Lorsque vous êtes sur un réseau limité ou en donnée mobile, nous ne téléchargerons pas les mises à jour automatiquement."
"message": "Modrinth App v{version} est disponible dès maintenant ! Lorsque vous êtes sur un réseau limité ou en données mobiles, nous ne téléchargerons pas les mises à jour automatiquement."
},
"app.update-toast.changelog": {
"message": "Notes de changement"
"message": "Journal des modifications"
},
"app.update-toast.download": {
"message": "Télécharger ({size})"
},
"app.update-toast.download-page": {
"message": "Télécharger"
},
"app.update-toast.downloading": {
"message": "Téléchargement..."
},
"app.update-toast.reload": {
"message": "Rechargement"
"message": "Recharger"
},
"app.update-toast.title": {
"message": "Mise à jour disponible"
@@ -69,7 +135,7 @@
"message": "Ajouter un ami"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural,one {demande}other {demandes}} d'ami"
"message": "{count} {count, plural, one {demande} other {demandes}} d'ami"
},
"friends.add-friend.submit": {
"message": "Envoyer une demande d'ami"
@@ -78,7 +144,7 @@
"message": "Ajouter un ami"
},
"friends.add-friend.username.description": {
"message": "Ça peut être différent de son pseudo Minecraft !"
"message": "Peut être différent de leur pseudo Minecraft !"
},
"friends.add-friend.username.placeholder": {
"message": "Entrez un pseudo Modrinth..."
@@ -87,7 +153,7 @@
"message": "Quel est le pseudo Modrinth de votre ami ?"
},
"friends.add-friends-to-share": {
"message": "<link>Ajouter des amis</link> pour voir à quoi ils jouent !"
"message": "<link>Ajoutez des amis</link> pour voir à quoi ils jouent !"
},
"friends.friend.cancel-request": {
"message": "Annuler la demande"
@@ -117,7 +183,7 @@
"message": "En attente"
},
"friends.no-friends-match": {
"message": "Aucuns amis ne correspondent à \"{query}\""
"message": "Aucuns amis ne correspondent à « {query} »"
},
"friends.search-friends-placeholder": {
"message": "Chercher des amis..."
@@ -240,7 +306,7 @@
"message": "Crochets de lancement"
},
"instance.settings.tabs.hooks.custom-hooks": {
"message": "Crochets de lancement custom"
"message": "Crochets de lancement personnalisés"
},
"instance.settings.tabs.hooks.description": {
"message": "Les crochets permettent aux usagers avancés d'exécuter certaines commandes systèmes avant et après le lancement du jeu."
@@ -249,7 +315,7 @@
"message": "Post-fermeture"
},
"instance.settings.tabs.hooks.post-exit.description": {
"message": "Exécuté après fermeture."
"message": "Exécuté après la fermeture du jeu."
},
"instance.settings.tabs.hooks.post-exit.enter": {
"message": "Entrer commande de post-fermeture..."
@@ -360,7 +426,7 @@
"message": "Réparation"
},
"instance.settings.tabs.installation.repair.confirm.description": {
"message": "La réparation réinstalle les dépendances de Minecraft et vérifie la corruption. Cela peut résoudre les problèmes de lancement du jeu en raison d'erreurs liées au lanceur, mais ne résoudra pas les problèmes ou plantages liés aux mods installés."
"message": "La réparation réinstalle les dépendances de Minecraft et vérifie la corruption. Cela peut résoudre les problèmes de lancement du jeu en raison d'erreurs liées au launcher, mais ne résoudra pas les problèmes ou plantages liés aux mods installés."
},
"instance.settings.tabs.installation.repair.confirm.title": {
"message": "Réparer l'instance ?"
@@ -461,9 +527,6 @@
"instance.settings.tabs.window.width.enter": {
"message": "Entrer la largeur..."
},
"instance.settings.title": {
"message": "Paramètres"
},
"instance.worlds.a_minecraft_server": {
"message": "Un Serveur Minecraft"
},
@@ -477,7 +540,7 @@
"message": "Ne pas montrer dans l'Accueil"
},
"instance.worlds.filter.available": {
"message": "Libre"
"message": "Disponible"
},
"instance.worlds.game_already_open": {
"message": "L'instance est déjà ouverte"

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