diff --git a/.agents/skills/api-module/SKILL.md b/.agents/skills/api-module/SKILL.md
new file mode 100644
index 0000000000..32cc16756b
--- /dev/null
+++ b/.agents/skills/api-module/SKILL.md
@@ -0,0 +1,23 @@
+---
+name: api-module
+description: Add an API endpoint module to packages/api-client from an OpenAPI schema. Use for new backend endpoints, API client modules, or tasks that provide an OpenAPI schema.
+---
+
+# Add an API Module
+
+Read the applicable `AGENTS.md` files before you edit code.
+
+Read [the API module standard](../../../standards/frontend/ADDING_API_MODULES.md) in full.
+
+1. Identify the OpenAPI schema from the request. If more than one schema is possible, ask the user to select one.
+2. Read the schema. Identify each endpoint, HTTP method, request type, response type, and path parameter.
+3. Get the service and version from the URL prefix. For example, map `/v3/projects` to `labrinth/v3/`.
+4. Define the API types in `types.ts`. Make each type match the schema exactly.
+5. Do not change, rename, or remove API fields.
+6. Make a module class that extends `AbstractModule`. Implement each endpoint with `this.client.request()` or `this.client.upload()`.
+7. Use the request-option pattern from the standard. Do not call `$fetch`, `fetch`, or another HTTP client directly.
+8. Add the module to `MODULE_REGISTRY` so the client can instantiate it.
+9. Export new service types from the applicable barrel `index.ts`.
+10. Check the module paths, registry key, public type exports, and endpoint types.
+
+Run only the checks that the user or the applicable `AGENTS.md` permits.
diff --git a/.agents/skills/api-module/agents/openai.yaml b/.agents/skills/api-module/agents/openai.yaml
new file mode 100644
index 0000000000..c8dd768afe
--- /dev/null
+++ b/.agents/skills/api-module/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Add API Module"
+ short_description: "Add typed API client modules from OpenAPI"
+ default_prompt: "Use $api-module to add an API client module from this OpenAPI schema."
diff --git a/.agents/skills/cross-platform-pages/SKILL.md b/.agents/skills/cross-platform-pages/SKILL.md
new file mode 100644
index 0000000000..2399604821
--- /dev/null
+++ b/.agents/skills/cross-platform-pages/SKILL.md
@@ -0,0 +1,38 @@
+---
+name: cross-platform-pages
+description: Convert a page to the shared Modrinth page system for the website and desktop app. Use for shared layouts, wrapped layouts, or platform dependency-injection contracts.
+---
+
+# Convert a Cross-Platform Page
+
+Read the applicable `AGENTS.md` files before you edit code.
+
+Read these standards in full:
+
+- [Cross-platform pages](../../../standards/frontend/CROSS_PLATFORM_PAGES.md)
+- [Dependency injection](../../../standards/frontend/DEPENDENCY_INJECTION.md)
+
+1. Identify the target page from the request.
+2. Read the page and its route shell. Identify data sources, mutations, navigation, and platform APIs.
+3. Use a wrapped layout when both platforms use the same API source and page logic.
+4. Use a shared layout when platform data or operations have different implementations.
+
+For a shared layout:
+
+1. Define a provider contract for all platform operations.
+2. Put common UI and state logic in the shared layout.
+3. Put reusable search, filter, and selection logic in local composables.
+4. Implement the contract in `apps/frontend/` and `apps/app-frontend/`.
+5. Use optional contract fields only for capabilities that are not available on both platforms.
+
+For a wrapped layout:
+
+1. Move the page to `packages/ui/src/layouts/wrapped/` and preserve its route structure.
+2. Replace platform-only imports with common utilities or provider calls.
+3. Make each frontend route shell render the wrapped component.
+4. Match primary query options in both route shells when the layout uses `ReadyTransition` and `useReadyState`.
+5. Prefetch these queries with `ensureQueryData`, as the standard specifies.
+
+Check that both route shells resolve their imports. Check that all required provider fields have implementations.
+
+Run only the checks that the user or the applicable `AGENTS.md` permits.
diff --git a/.agents/skills/cross-platform-pages/agents/openai.yaml b/.agents/skills/cross-platform-pages/agents/openai.yaml
new file mode 100644
index 0000000000..ad15d4df68
--- /dev/null
+++ b/.agents/skills/cross-platform-pages/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Convert Cross-Platform Page"
+ short_description: "Share pages across the web and desktop app"
+ default_prompt: "Use $cross-platform-pages to convert this page for the website and desktop app."
diff --git a/.agents/skills/figma-mcp/SKILL.md b/.agents/skills/figma-mcp/SKILL.md
new file mode 100644
index 0000000000..b6d99eecca
--- /dev/null
+++ b/.agents/skills/figma-mcp/SKILL.md
@@ -0,0 +1,21 @@
+---
+name: figma-mcp
+description: Convert a Figma design into a Modrinth Vue page or component. Use when a request provides a Figma URL or asks to implement a Figma layout.
+---
+
+# Implement a Figma Design
+
+Read the applicable `AGENTS.md` files before you edit code.
+
+Read `packages/ui/AGENTS.md` in full.
+
+1. Load the available Figma design-to-code instructions and follow the MCP tool guidance.
+2. Call `get_design_context` first with `clientLanguages: "typescript,html,css"` and `clientFrameworks: "vue"`.
+3. Treat the result as reference code and adapt it to the Modrinth codebase.
+4. Map Figma color variables to the applicable `surface-*` and `text-*` tokens. Do not use aliased Figma names directly.
+5. Reuse applicable components from `packages/ui/src/components/` before creating new ones. Also refer to `standards/frontend/COMPONENT_STRUCTURE.md`
+6. Read `packages/assets/styles/variables.scss` when Figma does not supply a required token.
+7. Use exact spacing values from the design.
+8. Implement the result as a Vue SFC with Tailwind classes and the existing component library.
+
+Run only the checks that the user or the applicable `AGENTS.md` permits.
diff --git a/.agents/skills/figma-mcp/agents/openai.yaml b/.agents/skills/figma-mcp/agents/openai.yaml
new file mode 100644
index 0000000000..1a7c61d304
--- /dev/null
+++ b/.agents/skills/figma-mcp/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Implement Figma Design"
+ short_description: "Build Modrinth Vue UI from Figma designs"
+ default_prompt: "Use $figma-mcp to implement this Figma design as a Modrinth Vue component."
diff --git a/.agents/skills/i18n-pass/SKILL.md b/.agents/skills/i18n-pass/SKILL.md
new file mode 100644
index 0000000000..05f69de695
--- /dev/null
+++ b/.agents/skills/i18n-pass/SKILL.md
@@ -0,0 +1,32 @@
+---
+name: i18n-pass
+description: Convert hard-coded English text in changed Vue components to the @modrinth/ui localization system. Use for an i18n pass, untranslated-string review, pull request, or component migration.
+---
+
+# Do an Internationalization Pass
+
+Read the applicable `AGENTS.md` files before you edit code.
+
+Read [the internationalization standard](../../../standards/frontend/INTERNATIONALIZATION.md) in full.
+
+1. Identify the scope from the request.
+2. For a pull request, use `gh pr diff ` to identify changed files.
+3. For a file path, inspect that file.
+4. When the request gives no scope, inspect the current uncommitted diff.
+5. Limit the pass to changed `.vue` files.
+6. Find user-visible text in templates and scripts.
+
+Check inner text, `alt`, `placeholder`, `aria-label`, buttons, tooltips, notifications, dropdown labels, and error messages.
+
+Do not change dynamic expressions, HTML tag names, CSS classes, internal identifiers, or log messages.
+
+1. Define stable message IDs with `defineMessage` or `defineMessages`.
+2. Replace simple text with `formatMessage()` calls.
+3. Use `` for text that contains links or markup.
+4. Use ICU selections and plurals when grammar depends on a value.
+5. Add a space before `}}` when an ICU placeholder ends at the Vue delimiter.
+6. Do not change component logic, layout, or reactivity.
+7. Do not edit localization JSON files. The user maintains those files.
+8. Check the changed templates again for hard-coded English text.
+
+Run only the checks that the user or the applicable `AGENTS.md` permits.
diff --git a/.agents/skills/i18n-pass/agents/openai.yaml b/.agents/skills/i18n-pass/agents/openai.yaml
new file mode 100644
index 0000000000..347ef98b2d
--- /dev/null
+++ b/.agents/skills/i18n-pass/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Run Internationalization Pass"
+ short_description: "Localize user-visible text in Vue files"
+ default_prompt: "Use $i18n-pass to localize the user-visible text in these changed Vue files."
diff --git a/.agents/skills/review-changelog/SKILL.md b/.agents/skills/review-changelog/SKILL.md
new file mode 100644
index 0000000000..5ab041c1c9
--- /dev/null
+++ b/.agents/skills/review-changelog/SKILL.md
@@ -0,0 +1,40 @@
+---
+name: review-changelog
+description: Review the latest packages/blog/changelog.ts entry against the Modrinth changelog standard. Use before a pull request or when asked to review or lint a changelog entry.
+---
+
+# Review a Changelog Entry
+
+Read [the changelog standard](../../../standards/maintaining/CHANGELOG.md) in full before the review.
+
+1. Open `packages/blog/changelog.ts`.
+2. Find the first entry in the `VERSIONS` array.
+3. If the request names `web`, `hosting`, or `app`, review the latest entry for that product.
+4. Otherwise, review the latest entry and all adjacent entries with the same date.
+
+Check the entry structure:
+
+- `date` contains a valid ISO 8601 timestamp.
+- `product` is `web`, `hosting`, or `app`.
+- An `app` entry has a `version` value.
+- A `web` or `hosting` entry does not have a `version` value.
+- Standard headings are `## Added`, `## Changed`, `## Fixed`, and `## Security`.
+- A featured release can use a linked heading.
+- Flag the legacy `## Improvements` heading.
+
+Check each bullet:
+
+- The voice and tense agree with the section.
+- The first verb agrees with the section.
+- The bullet describes user-visible behavior, not implementation.
+- The bullet identifies the applicable page, tab, modal, or feature.
+- The bullet contains one sentence, uses sentence case, and ends with a period.
+- Product and UI names use the public labels.
+- The bullet does not contain filler, vague intensifiers, apologies, or internal references.
+- The bullet is not a duplicate detail of a larger listed change.
+
+Group findings by entry. For each finding, show the original bullet and a proposed replacement.
+
+If the entry has no findings, state this result. Do not edit the changelog unless the user asks you to apply fixes.
+
+When the user asks for fixes, preserve tab indentation and template-literal formatting.
diff --git a/.agents/skills/review-changelog/agents/openai.yaml b/.agents/skills/review-changelog/agents/openai.yaml
new file mode 100644
index 0000000000..421afc3587
--- /dev/null
+++ b/.agents/skills/review-changelog/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Review Changelog"
+ short_description: "Review changelog entries for style problems"
+ default_prompt: "Use $review-changelog to review the latest changelog entry."
diff --git a/.agents/skills/tanstack-query/SKILL.md b/.agents/skills/tanstack-query/SKILL.md
new file mode 100644
index 0000000000..71c3ecc71b
--- /dev/null
+++ b/.agents/skills/tanstack-query/SKILL.md
@@ -0,0 +1,39 @@
+---
+name: tanstack-query
+description: Convert Vue server-state code to TanStack Query. Use for useQuery, useMutation, cache invalidation, optimistic updates, or replacement of useAsyncData and manual ref patterns.
+---
+
+# Convert Data Code to TanStack Query
+
+Read the applicable `AGENTS.md` files before you edit code.
+
+Read [the TanStack Query standard](../../../standards/frontend/FETCHING_DATA.md) in full.
+
+1. Identify the target file from the request.
+2. Find `useAsyncData`, `useFetch`, manual API refs, and fetch calls in `onMounted`.
+3. Identify mutations that use manual loading, error, or result refs.
+
+For queries:
+
+1. Replace manual fetch logic with `useQuery`.
+2. Get `api-client` with `injectModrinthClient()`.
+3. Use a hierarchical query key with the resource, qualifier, and parameters.
+4. Use a computed query key for reactive parameters.
+5. Use a computed `enabled` option when the query depends on other data.
+6. Use a shared query-option factory when multiple components use the query.
+
+For mutations:
+
+1. Replace manual mutation state with `useMutation`.
+2. Invalidate or update related query data after success.
+3. Use an optimistic update only when the UI needs an immediate response.
+4. Cancel the applicable query and save its prior data before an optimistic update.
+5. Restore the prior data after an error. Invalidate the query after settlement.
+
+Remove manual loading and error refs that TanStack Query replaces. Remove obsolete `onMounted` fetch calls.
+
+Keep Nuxt SSR behavior. Match route-shell prefetch options when `ReadyTransition` and `useReadyState` depend on the query.
+
+Check query keys, invalidation prefixes, reactive values, and rollback data.
+
+Run only the checks that the user or the applicable `AGENTS.md` permits.
diff --git a/.agents/skills/tanstack-query/agents/openai.yaml b/.agents/skills/tanstack-query/agents/openai.yaml
new file mode 100644
index 0000000000..2db5ece878
--- /dev/null
+++ b/.agents/skills/tanstack-query/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Migrate to TanStack Query"
+ short_description: "Migrate Vue server state to TanStack Query"
+ default_prompt: "Use $tanstack-query to migrate this Vue component to TanStack Query."
diff --git a/.claude/skills/api-module/SKILL.md b/.claude/skills/api-module/SKILL.md
deleted file mode 100644
index 37b4ac7788..0000000000
--- a/.claude/skills/api-module/SKILL.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-name: api-module
-description: Add a new API endpoint module to packages/api-client from an OpenAPI schema. Use when adding new backend endpoints, creating API client modules, or when an openapi.yml is provided.
-argument-hint:
----
-
-Refer to the standard: @standards/frontend/ADDING_API_MODULES.md
-
-## Steps
-
-1. **Read the OpenAPI schema** at `$ARGUMENTS` — identify the endpoints, request/response shapes, and path parameters.
-2. **Read the standard above** for naming conventions, type rules, and the module registration pattern.
-3. **Determine the service and version** — the URL path prefix tells you which service directory and version namespace to use (e.g. `/v3/projects` → `labrinth/v3/`).
-4. **Define types in `types.ts`** — types must match the API response 1:1. Use the OpenAPI schema as the source of truth. Do not reshape or rename fields.
-5. **Create the module class** — extend `BaseModule`, implement each endpoint as a method. Use the correct HTTP verb and request options pattern from the standard.
-6. **Register in `MODULE_REGISTRY`** — add the module entry so it's auto-instantiated on the client.
-7. **Export types** from the service's barrel `index.ts`.
-8. **Verify** — check that the module compiles and the types are accessible from `@modrinth/api-client`.
diff --git a/.claude/skills/cross-platform-pages/SKILL.md b/.claude/skills/cross-platform-pages/SKILL.md
deleted file mode 100644
index 6558eed3c3..0000000000
--- a/.claude/skills/cross-platform-pages/SKILL.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-name: cross-platform-pages
-description: Convert a page to the cross-platform page system so it works in both the website and the desktop app. Use when moving a page into packages/ui/src/layouts/, creating shared or wrapped layouts, or setting up DI contracts for platform abstraction.
-argument-hint:
----
-
-Refer to the standards: @standards/frontend/CROSS_PLATFORM_PAGES.md and @standards/frontend/DEPENDENCY_INJECTION.md
-
-## Steps
-
-1. **Read the target page** at `$ARGUMENTS` and understand its data sources, mutations, and navigation.
-2. **Read the standards above** to understand the shared vs wrapped distinction and the DI pattern.
-3. **Decide the category:**
- - **Wrapped** (`layouts/wrapped/`) — if the page uses the same API source on both platforms (e.g. web requests, not Tauri plugins). Just move the page component into `packages/ui` and import it from both frontends.
- - **Shared** (`layouts/shared/`) — if the page has different data-fetching logic per platform (e.g. website uses `api-client`, app uses Tauri `invoke`). Requires a DI contract.
-4. **For shared layouts:**
- - Define a DI contract interface in `providers/` capturing all platform-specific operations.
- - Create the layout component that injects the context and handles all UI logic.
- - Extract reusable stateful logic (search, filtering, selection) into `composables/`.
- - Implement the contract separately in each frontend (`apps/frontend/`, `apps/app-frontend/`).
-5. **For wrapped pages:**
- - Move the page component into `packages/ui/src/layouts/wrapped/` matching the route structure.
- - Replace any platform-specific imports with shared utilities.
- - Import and render the wrapped page from both frontends as a simple component.
- - If the layout uses TanStack Query for initial route paint with `ReadyTransition` / `useReadyState`, each platform route shell must call `ensureQueryData` for those queries with matching keys and fetchers — see **Platform route shells: prefetch with `ensureQueryData`** in `standards/frontend/CROSS_PLATFORM_PAGES.md`.
-6. **Verify** the page renders correctly by checking for missing imports and that all DI contracts are satisfied.
diff --git a/.claude/skills/figma-mcp/SKILL.md b/.claude/skills/figma-mcp/SKILL.md
deleted file mode 100644
index defabf8d2e..0000000000
--- a/.claude/skills/figma-mcp/SKILL.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-name: figma-mcp
-description: Use the Figma MCP server to translate a Figma design into a Vue page or component layout. Use when the user provides a Figma URL, asks to implement a design, or wants to draft a page layout from Figma.
-argument-hint:
----
-
-Refer to the standard: @standards/frontend/FIGMA_MCP_USAGE.md
-Also read @packages/ui/CLAUDE.md for color token mapping and component conventions.
-
-## Steps
-
-1. **Parse the Figma URL** from `$ARGUMENTS` — extract the `fileKey` and `nodeId`. Convert `-` to `:` in the node ID.
-2. **Read the standards above** for the available tools, adaptation rules, and color usage.
-3. **Call `get_design_context`** with the extracted `nodeId` and `fileKey`, using `clientLanguages: "typescript,html,css"` and `clientFrameworks: "vue"`. This is always the first tool to call.
-5. **Adapt the output to the Modrinth codebase:**
- - Map Figma color variables to `surface-*` / `text-*` tokens — never use Figma's aliased names directly.
- - Check `packages/ui/src/components/` for existing components that match elements in the design (buttons, cards, modals, inputs, etc.).
- - Check `packages/assets/styles/variables.scss` for tokens not exposed in Figma.
- - Match spacing values exactly from the design.
-6. **Use `get_screenshot`** if you need a closer visual reference of specific nodes.
-7. **Use `get_variable_defs`** to verify which design tokens are applied to ambiguous elements.
-8. **Build the component** as a Vue SFC using Tailwind classes and the project's existing component library.
diff --git a/.claude/skills/i18n-pass/SKILL.md b/.claude/skills/i18n-pass/SKILL.md
deleted file mode 100644
index 7edd69996c..0000000000
--- a/.claude/skills/i18n-pass/SKILL.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-name: i18n-pass
-description: Perform an i18n localization pass on changed files or a pull request, converting hard-coded English strings to the @modrinth/ui i18n system. Use when internationalizing a set of changes, reviewing a PR for untranslated strings, or converting a specific component.
-argument-hint: [file-path-or-pr-number]
----
-
-Refer to the standard: @standards/frontend/INTERNATIONALIZATION.md
-
-## Steps
-
-1. **Identify the scope of changes:**
- - If `$ARGUMENTS` is a PR number, run `gh pr diff $ARGUMENTS` to get the changed files.
- - If `$ARGUMENTS` is a file path, use that directly.
- - If no argument, check `git diff` for uncommitted changes.
-2. **Read the standard above** for the message definition pattern, ICU format rules, and `IntlFormatted` usage.
-3. **Filter to Vue SFCs** — only `.vue` files need i18n passes. Skip non-component files.
-4. **For each file, scan for hard-coded strings:**
- - ``: inner text, `alt`, `placeholder`, `aria-label`, button labels, tooltip text.
- - `
diff --git a/apps/app-frontend/src/components/ui/ErrorModal.vue b/apps/app-frontend/src/components/ui/ErrorModal.vue
index 385c503f11..475c1f3f76 100644
--- a/apps/app-frontend/src/components/ui/ErrorModal.vue
+++ b/apps/app-frontend/src/components/ui/ErrorModal.vue
@@ -9,7 +9,13 @@ import {
WrenchIcon,
XIcon,
} from '@modrinth/assets'
-import { ButtonStyled, Collapsible, injectNotificationManager } from '@modrinth/ui'
+import {
+ Button,
+ ButtonLink,
+ Collapsible,
+ IconButton,
+ injectNotificationManager,
+} from '@modrinth/ui'
import { computed, ref } from 'vue'
import { ChatIcon } from '@/assets/icons'
@@ -273,12 +279,10 @@ async function copyToClipboard(text) {
@@ -307,16 +311,15 @@ async function copyToClipboard(text) {
>
{{ debugInfo }}
-
-
-
-
-
-
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/ExportModal.vue b/apps/app-frontend/src/components/ui/ExportModal.vue
index e97f833f5c..d0cdd1410b 100644
--- a/apps/app-frontend/src/components/ui/ExportModal.vue
+++ b/apps/app-frontend/src/components/ui/ExportModal.vue
@@ -1,27 +1,25 @@
@@ -278,26 +228,24 @@ function isExportCandidateDisabled(path) {
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
-
- {{ formatMessage(messages.exportButton) }}
-
-
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+ {{ formatMessage(messages.exportButton) }}
+
diff --git a/apps/app-frontend/src/components/ui/HostingUpdateRequired.vue b/apps/app-frontend/src/components/ui/HostingUpdateRequired.vue
new file mode 100644
index 0000000000..6ad1c50d22
--- /dev/null
+++ b/apps/app-frontend/src/components/ui/HostingUpdateRequired.vue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatMessage(messages.description) }}
+
+
+
+
+
+ {{ formatMessage(messages.downloadingUpdate) }}
+
+ {{ downloadPercent }}%
+
+
+
+ {{ formatMessage(messages.reloadToUpdate) }}
+
+ {{ formatMessage(messages.downloadToUpdate) }}
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/Instance.vue b/apps/app-frontend/src/components/ui/Instance.vue
index 6845a00f2b..7540fb5865 100644
--- a/apps/app-frontend/src/components/ui/Instance.vue
+++ b/apps/app-frontend/src/components/ui/Instance.vue
@@ -7,14 +7,14 @@ import {
StopCircleIcon,
TimerIcon,
} from '@modrinth/assets'
-import { Avatar, ButtonStyled, injectNotificationManager, useRelativeTime } from '@modrinth/ui'
+import { Avatar, IconButton, injectNotificationManager, useRelativeTime } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import dayjs from 'dayjs'
-import { computed, onMounted, onUnmounted, ref } from 'vue'
+import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
+import { useAppEvent } from '@/composables/use-app-event'
import { trackEvent } from '@/helpers/analytics'
-import { process_listener } from '@/helpers/events'
import { install_existing_instance, install_pack_to_existing_instance } from '@/helpers/install'
import { kill, run } from '@/helpers/instance'
import { get_by_instance_id } from '@/helpers/process'
@@ -136,7 +136,7 @@ defineExpose({
const currentEvent = ref(null)
-const unlisten = await process_listener((e) => {
+useAppEvent('process', (e) => {
if (e.instance_id === props.instance.id) {
currentEvent.value = e.event
if (e.event === 'finished') {
@@ -148,7 +148,6 @@ const unlisten = await process_listener((e) => {
onMounted(() => {
checkProcess()
})
-onUnmounted(() => unlisten())
@@ -168,30 +167,37 @@ onUnmounted(() => unlisten())
{{ instance.name }}
-
- stop(e, 'InstanceCard')">
-
-
-
-
-
-
-
-
-
stop(e, 'InstanceCard')"
>
- play(e, 'InstanceCard')"
- @mousehover="checkProcess"
- >
-
-
-
-
+
+
+
+
+
+
play(e, 'InstanceCard')"
+ @mouseenter="checkProcess"
+ >
+
+
+
@@ -219,47 +225,51 @@ onUnmounted(() => unlisten())
:class="`transition-all ${modLoading || installing ? `brightness-[0.25] scale-[0.85]` : `group-hover:brightness-75`}`"
/>
-
- stop(e, 'InstanceCard')"
- @mousehover="checkProcess"
- >
-
-
-
+
stop(e, 'InstanceCard')"
+ @mouseenter="checkProcess"
+ >
+
+
-
repair(e)"
>
- repair(e)"
- >
-
-
-
-
- play(e, 'InstanceCard')"
- @mousehover="checkProcess"
- >
-
-
-
+
+
+
play(e, 'InstanceCard')"
+ @mouseenter="checkProcess"
+ >
+
+
diff --git a/apps/app-frontend/src/components/ui/InstanceIndicator.vue b/apps/app-frontend/src/components/ui/InstanceIndicator.vue
index 2787635117..cb077c4bfb 100644
--- a/apps/app-frontend/src/components/ui/InstanceIndicator.vue
+++ b/apps/app-frontend/src/components/ui/InstanceIndicator.vue
@@ -1,6 +1,6 @@
diff --git a/apps/app-frontend/src/components/ui/SurveyPopup.vue b/apps/app-frontend/src/components/ui/SurveyPopup.vue
index cd6fe819e4..7c2f4069b3 100644
--- a/apps/app-frontend/src/components/ui/SurveyPopup.vue
+++ b/apps/app-frontend/src/components/ui/SurveyPopup.vue
@@ -1,14 +1,16 @@
diff --git a/apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-shared-instance-update-available.vue b/apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-shared-instance-update-available.vue
deleted file mode 100644
index ffb96f4329..0000000000
--- a/apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-shared-instance-update-available.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- {{ formatMessage(messages.sharedInstanceUpdateAvailableBody, { name: instanceName }) }}
-
-
-
-
- {{ formatMessage(messages.sharedInstanceReviewUpdateButton) }}
-
-
-
-
-
-
-
diff --git a/apps/app-frontend/src/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue b/apps/app-frontend/src/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue
index 40267f14f5..9f29f9a945 100644
--- a/apps/app-frontend/src/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue
+++ b/apps/app-frontend/src/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue
@@ -7,10 +7,9 @@ import {
MessagesSquareIcon,
WrenchIcon,
} from '@modrinth/assets'
-import { Admonition, ButtonStyled, Collapsible, NewModal } from '@modrinth/ui'
+import { Admonition, Button, ButtonLink, Collapsible, IconButton, NewModal } from '@modrinth/ui'
import { computed, ref } from 'vue'
-import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
import { login as login_flow, set_default_user } from '@/helpers/auth.js'
import { handleSevereError } from '@/store/error.js'
@@ -29,19 +28,13 @@ function show(errorVal: { message?: string }) {
matchedError.value = findMinecraftAuthError(rawError.value)
debugCollapsed.value = true
- hide_ads_window()
modal.value?.show()
}
function hide() {
- onModalHide()
modal.value?.hide()
}
-function onModalHide() {
- show_ads_window()
-}
-
defineExpose({
show,
hide,
@@ -74,7 +67,7 @@ async function copyToClipboard(text: string) {
-
+
@@ -176,16 +171,15 @@ async function copyToClipboard(text: string) {
>
{{ debugInfo }}
-
-
-
-
-
-
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/minecraft-required-modal/MinecraftRequiredModal.vue b/apps/app-frontend/src/components/ui/minecraft-required-modal/MinecraftRequiredModal.vue
index c82c174a45..c22b268e2a 100644
--- a/apps/app-frontend/src/components/ui/minecraft-required-modal/MinecraftRequiredModal.vue
+++ b/apps/app-frontend/src/components/ui/minecraft-required-modal/MinecraftRequiredModal.vue
@@ -20,39 +20,28 @@
-
-
-
-
- {{ formatMessage(messages.getSupport) }}
-
-
-
-
-
-
-
-
-
-
-
- {{ formatMessage(messages.signIn) }}
-
-
+
+
+
+ {{ formatMessage(messages.getSupport) }}
+
+
+
+
+
+
+
+
+
+ {{ formatMessage(messages.signIn) }}
+
{{ formatMessage(messages.dontHaveAccount) }}
@@ -69,7 +58,7 @@
@@ -185,54 +181,53 @@ onUnmounted(() => {
-
-
-
- {{ formatMessage(commonMessages.stopButton) }}
-
-
-
-
-
-
- {{ formatMessage(commonMessages.playButton) }}
-
-
-
-
-
-
-
- View instance
-
-
-
- {{ formatMessage(commonMessages.openFolderButton) }}
-
-
-
+
+
+ {{ formatMessage(commonMessages.stopButton) }}
+
+
+
+
+ {{ formatMessage(commonMessages.playButton) }}
+
+
+
+
+
+ View instance
+
+
+
+ {{ formatMessage(commonMessages.openFolderButton) }}
+
+
diff --git a/apps/app-frontend/src/components/ui/world/RecentWorldsList.vue b/apps/app-frontend/src/components/ui/world/RecentWorldsList.vue
index dc0438f914..c8104d73f0 100644
--- a/apps/app-frontend/src/components/ui/world/RecentWorldsList.vue
+++ b/apps/app-frontend/src/components/ui/world/RecentWorldsList.vue
@@ -5,12 +5,12 @@ import { GAME_MODES, 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'
+import { computed, onMounted, ref, watch } from 'vue'
import InstanceItem from '@/components/ui/world/InstanceItem.vue'
import WorldItem from '@/components/ui/world/WorldItem.vue'
+import { useAppEvent } from '@/composables/use-app-event'
import { trackEvent } from '@/helpers/analytics'
-import { instance_listener, process_listener } from '@/helpers/events'
import { kill, run } from '@/helpers/instance'
import { get_all } from '@/helpers/process'
import { get_game_versions } from '@/helpers/tags'
@@ -215,11 +215,11 @@ async function stopInstance(path: string) {
const currentInstance = ref()
const currentWorld = ref()
-const unlistenProcesses = await process_listener(async () => {
+useAppEvent('process', async () => {
await checkProcesses()
})
-const unlistenInstances = await instance_listener(async () => {
+useAppEvent('instance', async () => {
await populateJumpBackIn().catch(() => {
console.error('Failed to populate jump back in')
})
@@ -251,11 +251,6 @@ onMounted(() => {
checkProcesses()
linuxPopulateCount.value = 0
})
-
-onUnmounted(() => {
- unlistenProcesses()
- unlistenInstances()
-})
diff --git a/apps/app-frontend/src/components/ui/world/WorldItem.vue b/apps/app-frontend/src/components/ui/world/WorldItem.vue
index 5e509c57a2..7d53d27b5d 100644
--- a/apps/app-frontend/src/components/ui/world/WorldItem.vue
+++ b/apps/app-frontend/src/components/ui/world/WorldItem.vue
@@ -21,13 +21,13 @@ import {
import type { MessageDescriptor } from '@modrinth/ui'
import {
Avatar,
- ButtonStyled,
+ Button,
commonMessages,
defineMessages,
injectNotificationManager,
- OverflowMenu,
SmartClickable,
TagItem,
+ TeleportOverflowMenu,
useFormatDateTime,
useFormatNumber,
useRelativeTime,
@@ -412,177 +412,184 @@ const messages = defineMessages({
-
-
-
- {{ formatMessage(commonMessages.stopButton) }}
-
-
-
-
-
-
- {{ formatMessage(commonMessages.playButton) }}
-
-
-
-
+ {{ formatMessage(commonMessages.stopButton) }}
+
+
+
+
+ {{ formatMessage(commonMessages.playButton) }}
+
+
-
-
-
- {{ formatMessage(messages.playInstance) }}
-
-
-
- {{ formatMessage(messages.viewInstance) }}
-
-
-
- {{ formatMessage(commonMessages.editButton) }}
-
-
-
- {{ formatMessage(commonMessages.openFolderButton) }}
-
-
-
- {{ formatMessage(messages.copyAddress) }}
-
-
-
- {{ formatMessage(commonMessages.refreshButton) }}
-
-
-
- {{ formatMessage(messages.createShortcut) }}
-
-
-
- {{ formatMessage(messages.dontShowOnHome) }}
-
-
-
- {{
- formatMessage(
- world.type === 'server'
- ? commonMessages.removeButton
- : commonMessages.deleteLabel,
- )
- }}
-
-
-
+ },
+ {
+ id: 'create-shortcut',
+ label: formatMessage(messages.createShortcut),
+ shown: !!shortcutInstanceId && !quarantined,
+ action: () => createShortcut(),
+ },
+ {
+ type: 'divider',
+ shown: !instanceId,
+ },
+ {
+ id: 'delete',
+ label: formatMessage(
+ world.type === 'server' ? commonMessages.removeButton : commonMessages.deleteLabel,
+ ),
+ tone: 'red',
+ action: () => emit('delete'),
+ shown: !instanceId,
+ disabled: locked || managed,
+ tooltip: locked
+ ? formatMessage(messages.worldInUse)
+ : managed
+ ? formatMessage(messages.linkedServer)
+ : undefined,
+ },
+ ]"
+ >
+
+
+
+ {{ formatMessage(messages.playInstance) }}
+
+
+
+ {{ formatMessage(messages.viewInstance) }}
+
+
+
+ {{ formatMessage(commonMessages.editButton) }}
+
+
+
+ {{ formatMessage(commonMessages.openFolderButton) }}
+
+
+
+ {{ formatMessage(messages.copyAddress) }}
+
+
+
+ {{ formatMessage(commonMessages.refreshButton) }}
+
+
+
+ {{ formatMessage(messages.createShortcut) }}
+
+
+
+ {{ formatMessage(messages.dontShowOnHome) }}
+
+
+
+ {{
+ formatMessage(
+ world.type === 'server' ? commonMessages.removeButton : commonMessages.deleteLabel,
+ )
+ }}
+
+
diff --git a/apps/app-frontend/src/components/ui/world/modal/AddServerModal.vue b/apps/app-frontend/src/components/ui/world/modal/AddServerModal.vue
index c1679ae0b5..335b0b85eb 100644
--- a/apps/app-frontend/src/components/ui/world/modal/AddServerModal.vue
+++ b/apps/app-frontend/src/components/ui/world/modal/AddServerModal.vue
@@ -1,7 +1,7 @@
diff --git a/apps/app-frontend/src/pages/Skins.vue b/apps/app-frontend/src/pages/Skins.vue
index 6c89f34712..14394ca444 100644
--- a/apps/app-frontend/src/pages/Skins.vue
+++ b/apps/app-frontend/src/pages/Skins.vue
@@ -10,7 +10,7 @@ import {
SpinnerIcon,
} from '@modrinth/assets'
import {
- ButtonStyled,
+ Button,
commonMessages,
ConfirmModal,
defineMessages,
@@ -1038,6 +1038,7 @@ async function checkUserChanges() {
try {
const defaultId = await get_default_user()
if (defaultId !== currentUserId.value) {
+ await accountsCard.value?.refreshValues()
await loadCurrentUser()
await loadCapes()
await loadSkins()
@@ -1111,13 +1112,15 @@ await loadSkins()
class="skin-preview-actions flex w-full items-center justify-center gap-1.5"
:class="selectedSkinHasEarsFeatures ? 'flex-nowrap' : 'flex-wrap'"
>
-
{{ formatMessage(commonMessages.resetButton) }}
-
-
+
{{ formatMessage(messages.applyButton) }}
-
+
- selectedSkin && editSkinModal?.show(e, selectedSkin)"
>
{{ formatMessage(messages.editSkinButton) }}
-
+
Ears
-
-
- {{
- formatMessage(
- earsFeaturesEnabled
- ? messages.toggleEarsFeaturesOff
- : messages.toggleEarsFeaturesOn,
- )
- }}
-
-
+
+ {{
+ formatMessage(
+ earsFeaturesEnabled
+ ? messages.toggleEarsFeaturesOff
+ : messages.toggleEarsFeaturesOn,
+ )
+ }}
+
{{ formatMessage(messages.signInDescription) }}
-
-
-
-
- {{ formatMessage(messages.signInButton) }}
-
-
+
+
+
+ {{ formatMessage(messages.signInButton) }}
+
diff --git a/apps/app-frontend/src/pages/User.vue b/apps/app-frontend/src/pages/User.vue
index ea2b5cf23d..daf79890c2 100644
--- a/apps/app-frontend/src/pages/User.vue
+++ b/apps/app-frontend/src/pages/User.vue
@@ -1,5 +1,5 @@
-
+
+ >
+
+
+
+
+
+ {{
+ formatMessage(
+ isProjectInstalling(project.id)
+ ? commonMessages.installingLabel
+ : project.project_type === 'modpack'
+ ? commonMessages.installButton
+ : messages.installToInstance,
+ )
+ }}
+
+
+
diff --git a/apps/app-frontend/src/components/ui/instance/instance-admonitions/index.vue b/apps/app-frontend/src/pages/instance/components/admonitions/index.vue
similarity index 72%
rename from apps/app-frontend/src/components/ui/instance/instance-admonitions/index.vue
rename to apps/app-frontend/src/pages/instance/components/admonitions/index.vue
index e16171bc5b..f294d38df1 100644
--- a/apps/app-frontend/src/components/ui/instance/instance-admonitions/index.vue
+++ b/apps/app-frontend/src/pages/instance/components/admonitions/index.vue
@@ -6,11 +6,6 @@
:instance="instance"
@published="emit('published')"
/>
-
()
const emit = defineEmits<{
published: []
delete: []
- 'review-update': [event: MouseEvent]
}>()
const sharedInstanceWrongAccount = computed(() => props.sharedInstanceWrongAccount ?? false)
@@ -76,15 +68,6 @@ const showSharedInstancePublishAdmonition = computed(
props.instance.shared_instance?.role === 'owner' &&
props.instance.shared_instance.status === 'stale',
)
-const showSharedInstanceUpdateAdmonition = computed(
- () =>
- !sharedInstanceWrongAccount.value &&
- !displayedSharedInstanceUnavailableReason.value &&
- props.instance.install_stage === 'installed' &&
- props.sharedInstanceRole === 'member' &&
- props.sharedInstanceUpdateAvailable === true,
-)
-
const stackItems = computed(() => {
const items: InstanceAdmonitionItem[] = []
@@ -120,15 +103,6 @@ const stackItems = computed(() => {
})
}
- if (showSharedInstanceUpdateAdmonition.value) {
- items.push({
- id: 'shared-instance-update-available',
- type: 'info',
- dismissible: false,
- kind: 'shared-instance-update-available',
- })
- }
-
return items
})
diff --git a/apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-messages.ts b/apps/app-frontend/src/pages/instance/components/admonitions/messages.ts
similarity index 83%
rename from apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-messages.ts
rename to apps/app-frontend/src/pages/instance/components/admonitions/messages.ts
index 011a57acaf..5191ae9b26 100644
--- a/apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-messages.ts
+++ b/apps/app-frontend/src/pages/instance/components/admonitions/messages.ts
@@ -21,19 +21,6 @@ export const instanceAdmonitionsMessages = defineMessages({
id: 'app.instance.admonitions.shared-instance.reviewing-button',
defaultMessage: 'Reviewing...',
},
- sharedInstanceUpdateAvailableHeader: {
- id: 'app.instance.admonitions.shared-instance.update-available-header',
- defaultMessage: 'An update is available',
- },
- sharedInstanceUpdateAvailableBody: {
- id: 'app.instance.admonitions.shared-instance.update-available-body',
- defaultMessage:
- 'An update is required to play {name}. Please update to latest version to launch the game.',
- },
- sharedInstanceReviewUpdateButton: {
- id: 'app.instance.admonitions.shared-instance.review-update-button',
- defaultMessage: 'Review update',
- },
sharedInstanceReviewHeader: {
id: 'app.instance.admonitions.shared-instance.review-header',
defaultMessage: 'Review changes',
diff --git a/apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-shared-instance-stale.vue b/apps/app-frontend/src/pages/instance/components/admonitions/shared-instance-stale.vue
similarity index 63%
rename from apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-shared-instance-stale.vue
rename to apps/app-frontend/src/pages/instance/components/admonitions/shared-instance-stale.vue
index e437bfe1cf..63d053a91e 100644
--- a/apps/app-frontend/src/components/ui/instance/instance-admonitions/instance-admonitions-shared-instance-stale.vue
+++ b/apps/app-frontend/src/pages/instance/components/admonitions/shared-instance-stale.vue
@@ -6,23 +6,27 @@
>
{{ formatMessage(messages.sharedInstanceChangesBody) }}
-
-
-
-
- {{
- isPublishing
- ? formatMessage(messages.sharedInstancePublishingButton)
- : isReviewingPublish
- ? formatMessage(messages.sharedInstanceReviewingButton)
- : formatMessage(messages.sharedInstancePublishButton)
- }}
-
-
+
+
+
+ {{
+ isPublishing
+ ? formatMessage(messages.sharedInstancePublishingButton)
+ : isReviewingPublish
+ ? formatMessage(messages.sharedInstanceReviewingButton)
+ : formatMessage(messages.sharedInstancePublishButton)
+ }}
+
@@ -36,13 +40,13 @@
diff --git a/apps/app-frontend/src/components/ui/shared-instances/ConfirmRevokeSharedInstanceInviteModal.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/confirm-revoke-shared-instance-invite-modal.vue
similarity index 83%
rename from apps/app-frontend/src/components/ui/shared-instances/ConfirmRevokeSharedInstanceInviteModal.vue
rename to apps/app-frontend/src/pages/instance/components/settings-modal/confirm-revoke-shared-instance-invite-modal.vue
index e373ce7b93..89fd9f6cd8 100644
--- a/apps/app-frontend/src/components/ui/shared-instances/ConfirmRevokeSharedInstanceInviteModal.vue
+++ b/apps/app-frontend/src/pages/instance/components/settings-modal/confirm-revoke-shared-instance-invite-modal.vue
@@ -10,18 +10,14 @@
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
-
- {{ formatMessage(messages.revokeButton) }}
-
-
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+ {{ formatMessage(messages.revokeButton) }}
+
@@ -31,7 +27,7 @@
import { XIcon } from '@modrinth/assets'
import {
Admonition,
- ButtonStyled,
+ Button,
commonMessages,
defineMessages,
IntlFormatted,
diff --git a/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/general-settings.vue
similarity index 88%
rename from apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue
rename to apps/app-frontend/src/pages/instance/components/settings-modal/general-settings.vue
index 8568ebefa6..e3f9d8f64b 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue
+++ b/apps/app-frontend/src/pages/instance/components/settings-modal/general-settings.vue
@@ -2,13 +2,13 @@
import { CopyIcon, EditIcon, PlusIcon, SpinnerIcon, TrashIcon, UploadIcon } from '@modrinth/assets'
import {
Avatar,
- ButtonStyled,
+ Button,
Checkbox,
Chips,
defineMessages,
injectNotificationManager,
- OverflowMenu,
StyledInput,
+ TeleportOverflowMenu,
useVIntl,
} from '@modrinth/ui'
import { useQueryClient } from '@tanstack/vue-query'
@@ -21,9 +21,9 @@ import ConfirmDeleteInstanceModal from '@/components/ui/modal/ConfirmDeleteInsta
import { trackEvent } from '@/helpers/analytics'
import { install_duplicate_instance } from '@/helpers/install'
import { edit, edit_icon, list, remove } from '@/helpers/instance'
-import { injectInstanceSettings } from '@/providers/instance-settings'
-import type { GameInstance } from '../../../helpers/types'
+import type { GameInstance } from '../../../../helpers/types'
+import { injectInstanceSettings } from './instance-settings-context'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
@@ -298,17 +298,24 @@ const messages = defineMessages({
Icon
-
{{ formatMessage(messages.duplicateInstance) }}
-
-
- {{ formatMessage(messages.duplicateButton) }}
-
-
+
+ {{ formatMessage(messages.duplicateButton) }}
+
{{ formatMessage(messages.duplicateInstanceDescription) }}
@@ -388,11 +393,9 @@ const messages = defineMessages({
class="w-full max-w-[300px]"
@submit="() => addCategory"
/>
-
- addCategory()">
- {{ formatMessage(messages.libraryGroupsCreate) }}
-
-
+ addCategory()">
+ {{ formatMessage(messages.libraryGroupsCreate) }}
+
@@ -421,22 +424,22 @@ const messages = defineMessages({
{{ formatMessage(messages.deleteInstance) }}
-
-
-
-
- {{
- removing
- ? formatMessage(messages.deletingInstanceButton)
- : formatMessage(messages.deleteInstanceButton)
- }}
-
-
+
+
+
+ {{
+ removing
+ ? formatMessage(messages.deletingInstanceButton)
+ : formatMessage(messages.deleteInstanceButton)
+ }}
+
{{ formatMessage(messages.deleteInstanceDescription) }}
diff --git a/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/hooks-settings.vue
similarity index 68%
rename from apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue
rename to apps/app-frontend/src/pages/instance/components/settings-modal/hooks-settings.vue
index bfd016d940..a40a173b8e 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue
+++ b/apps/app-frontend/src/pages/instance/components/settings-modal/hooks-settings.vue
@@ -10,9 +10,9 @@ import { computed, ref, watch } from 'vue'
import { edit } from '@/helpers/instance'
import { get } from '@/helpers/settings.ts'
-import { injectInstanceSettings } from '@/providers/instance-settings'
-import type { AppSettings, Hooks } from '../../../helpers/types'
+import type { AppSettings, Hooks } from '../../../../helpers/types'
+import { injectInstanceSettings } from './instance-settings-context'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
@@ -56,6 +56,35 @@ const messages = defineMessages({
defaultMessage:
'Hooks allow advanced users to run certain system commands before and after launching the game.',
},
+ hookVariablesDescription: {
+ id: 'instance.settings.tabs.hooks.variables.description',
+ defaultMessage:
+ 'Hooks run in the working directory of the instance, with the following variables:',
+ },
+ instanceNameDescription: {
+ id: 'instance.settings.tabs.hooks.variables.inst-name.description',
+ defaultMessage: '$INST_NAME: The name of the instance',
+ },
+ instanceIdDescription: {
+ id: 'instance.settings.tabs.hooks.variables.inst-id.description',
+ defaultMessage: "$INST_ID: The name of the instance's folder",
+ },
+ instanceDirDescription: {
+ id: 'instance.settings.tabs.hooks.variables.inst-dir.description',
+ defaultMessage: "$INST_DIR: The absolute path to the instance's folder",
+ },
+ instanceMcDirDescription: {
+ id: 'instance.settings.tabs.hooks.variables.inst-mc-dir.description',
+ defaultMessage: '$INST_MC_DIR: An alias for $INST_DIR',
+ },
+ instanceJavaDescription: {
+ id: 'instance.settings.tabs.hooks.variables.inst-java.description',
+ defaultMessage: '$INST_JAVA: The absolute path to the java binary',
+ },
+ instanceJavaArgsDescription: {
+ id: 'instance.settings.tabs.hooks.variables.inst-java-args.description',
+ defaultMessage: '$INST_JAVA_ARGS: The JVM Arguments provided to the game',
+ },
customHooks: {
id: 'instance.settings.tabs.hooks.custom-hooks',
defaultMessage: 'Custom launch hooks',
@@ -153,5 +182,17 @@ const messages = defineMessages({
{{ formatMessage(messages.postExitDescription) }}
+
+
+ {{ formatMessage(messages.hookVariablesDescription) }}
+
+
+ {{ formatMessage(messages.instanceNameDescription) }}
+ {{ formatMessage(messages.instanceIdDescription) }}
+ {{ formatMessage(messages.instanceDirDescription) }}
+ {{ formatMessage(messages.instanceMcDirDescription) }}
+ {{ formatMessage(messages.instanceJavaDescription) }}
+ {{ formatMessage(messages.instanceJavaArgsDescription) }}
+
diff --git a/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/index.vue
similarity index 89%
rename from apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue
rename to apps/app-frontend/src/pages/instance/components/settings-modal/index.vue
index 800cac656b..c979e793c5 100644
--- a/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue
+++ b/apps/app-frontend/src/pages/instance/components/settings-modal/index.vue
@@ -22,19 +22,19 @@ import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { convertFileSrc } from '@tauri-apps/api/core'
import { computed, nextTick, ref, watch } from 'vue'
-import GeneralSettings from '@/components/ui/instance_settings/GeneralSettings.vue'
-import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
-import InstallationSettings from '@/components/ui/instance_settings/InstallationSettings.vue'
-import JavaSettings from '@/components/ui/instance_settings/JavaSettings.vue'
-import SharingSettings from '@/components/ui/instance_settings/SharingSettings.vue'
-import WindowSettings from '@/components/ui/instance_settings/WindowSettings.vue'
import { get_project_v3 } from '@/helpers/cache'
import { get_linked_modpack_info } from '@/helpers/instance'
import { get_loader_versions } from '@/helpers/metadata'
import { get_game_versions, get_loaders } from '@/helpers/tags'
-import { provideInstanceSettings } from '@/providers/instance-settings'
+import type { GameInstance } from '@/helpers/types'
-import type { GameInstance } from '../../../helpers/types'
+import GeneralSettings from './general-settings.vue'
+import HooksSettings from './hooks-settings.vue'
+import InstallationSettings from './installation-settings.vue'
+import { provideInstanceSettings } from './instance-settings-context.ts'
+import JavaSettings from './java-settings.vue'
+import SharingSettings from './sharing-settings.vue'
+import WindowSettings from './window-settings.vue'
const { formatMessage } = useVIntl()
const queryClient = useQueryClient()
diff --git a/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/installation-settings.vue
similarity index 96%
rename from apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue
rename to apps/app-frontend/src/pages/instance/components/settings-modal/installation-settings.vue
index fe210e165f..f2a6e9206e 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue
+++ b/apps/app-frontend/src/pages/instance/components/settings-modal/installation-settings.vue
@@ -15,7 +15,6 @@ import type { GameVersionTag, PlatformTag } from '@modrinth/utils'
import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { computed, ref } from 'vue'
-import SharedInstanceInstallationSettingsControls from '@/components/ui/shared-instances/SharedInstanceInstallationSettingsControls.vue'
import { useManagedContentPolicy } from '@/composables/instances/use-managed-content-policy'
import { trackEvent } from '@/helpers/analytics'
import { get_project_versions, get_version } from '@/helpers/cache'
@@ -33,13 +32,17 @@ import {
} from '@/helpers/instance'
import { get_loader_versions } from '@/helpers/metadata'
import { get_game_versions, get_loaders } from '@/helpers/tags'
+import { injectAppEvents } from '@/providers/app-events'
import { provideInstanceBackup } from '@/providers/instance-backup'
-import { injectInstanceSettings } from '@/providers/instance-settings'
import { useTheming } from '@/store/state'
-import type { Manifest } from '../../../helpers/types'
+import type { Manifest } from '../../../../helpers/types'
+import { instanceKeys } from '../../query-options.ts'
+import { injectInstanceSettings } from './instance-settings-context.ts'
+import SharedInstanceInstallationSettingsControls from './shared-instance-installation-settings-controls.vue'
const { handleError } = injectNotificationManager()
+const appEvents = injectAppEvents()
const filePicker = injectFilePicker()
const { formatMessage } = useVIntl()
const queryClient = useQueryClient()
@@ -148,7 +151,9 @@ async function unlinkSharedInstance() {
unlinkingSharedInstance.value = true
try {
await unlink_shared_instance(instance.value.id)
- await queryClient.invalidateQueries({ queryKey: ['sharedInstanceUsers', instance.value.id] })
+ await queryClient.invalidateQueries({
+ queryKey: instanceKeys.sharedMembers(instance.value.id),
+ })
await queryClient.invalidateQueries({ queryKey: ['linkedModpackInfo', instance.value.id] })
onUnlinked()
} catch (error) {
@@ -195,7 +200,7 @@ async function installLocalModpackFromPicker() {
}).catch(handleError)
if (!job) return false
- const completed = await wait_for_install_job(job.job_id).catch(handleError)
+ const completed = await wait_for_install_job(appEvents, job.job_id).catch(handleError)
return !!completed
}
@@ -229,6 +234,7 @@ provideInstallationSettings({
() =>
isModrinthLinkedModpack.value ||
isImportedModpack.value ||
+ instance.value.link?.type === 'server_project' ||
isSharedInstanceManagedModpack.value,
),
isBusy: installationSettingsBusy,
diff --git a/apps/app-frontend/src/providers/instance-settings.ts b/apps/app-frontend/src/pages/instance/components/settings-modal/instance-settings-context.ts
similarity index 100%
rename from apps/app-frontend/src/providers/instance-settings.ts
rename to apps/app-frontend/src/pages/instance/components/settings-modal/instance-settings-context.ts
diff --git a/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue
similarity index 82%
rename from apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue
rename to apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue
index 71e4449937..97a9ab101a 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue
+++ b/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue
@@ -9,7 +9,7 @@ import {
XCircleIcon,
} from '@modrinth/assets'
import {
- ButtonStyled,
+ Button,
Checkbox,
defineMessages,
injectNotificationManager,
@@ -25,9 +25,9 @@ import useJavaTest from '@/composables/useJavaTest'
import useMemorySlider from '@/composables/useMemorySlider'
import { edit, get_optimal_jre_key } from '@/helpers/instance'
import { get } from '@/helpers/settings.ts'
-import { injectInstanceSettings } from '@/providers/instance-settings'
-import type { AppSettings } from '../../../helpers/types'
+import type { AppSettings } from '../../../../helpers/types'
+import { injectInstanceSettings } from './instance-settings-context'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
@@ -224,45 +224,60 @@ const messages = defineMessages({
wrapper-class="flex-1 min-w-0"
@update:model-value="(val) => (javaPath = String(val))"
/>
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
- Detect
-
-
-
-
-
- Browse
-
-
+
+
+ Detect
+
+
+
+ Browse
+
diff --git a/apps/app-frontend/src/components/ui/shared-instances/SharedInstanceInstallationSettingsControls.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/shared-instance-installation-settings-controls.vue
similarity index 78%
rename from apps/app-frontend/src/components/ui/shared-instances/SharedInstanceInstallationSettingsControls.vue
rename to apps/app-frontend/src/pages/instance/components/settings-modal/shared-instance-installation-settings-controls.vue
index d72f17090e..62c55c1c79 100644
--- a/apps/app-frontend/src/components/ui/shared-instances/SharedInstanceInstallationSettingsControls.vue
+++ b/apps/app-frontend/src/pages/instance/components/settings-modal/shared-instance-installation-settings-controls.vue
@@ -2,13 +2,11 @@
{{ formatMessage(messages.title) }}
-
-
-
-
- {{ formatMessage(unpublishing ? messages.unpublishingButton : messages.unpublishButton) }}
-
-
+
+
+
+ {{ formatMessage(unpublishing ? messages.unpublishingButton : messages.unpublishButton) }}
+
{{ formatMessage(messages.unpublishDescription) }}
@@ -17,13 +15,11 @@
formatMessage(messages.linkedTitle)
}}
-
-
-
-
- {{ formatMessage(unlinking ? messages.unlinkingButton : messages.unlinkButton) }}
-
-
+
+
+
+ {{ formatMessage(unlinking ? messages.unlinkingButton : messages.unlinkButton) }}
+
{{ formatMessage(messages.unlinkDescription) }}
@@ -39,15 +35,11 @@
}}
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
- {{ formatMessage(messages.unpublishButton) }}
-
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+ {{ formatMessage(messages.unpublishButton) }}
+
@@ -70,15 +62,16 @@
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
- {{ formatMessage(messages.unlinkButton) }}
-
+ {{ formatMessage(commonMessages.cancelButton) }}
+ {{ formatMessage(messages.unlinkButton) }}
+
@@ -88,7 +81,7 @@
import { SpinnerIcon, UnlinkIcon, XIcon } from '@modrinth/assets'
import {
Admonition,
- ButtonStyled,
+ Button,
commonMessages,
defineMessages,
InlineBackupCreator,
diff --git a/apps/app-frontend/src/components/ui/instance_settings/SharingSettings.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/sharing-settings.vue
similarity index 84%
rename from apps/app-frontend/src/components/ui/instance_settings/SharingSettings.vue
rename to apps/app-frontend/src/pages/instance/components/settings-modal/sharing-settings.vue
index c34a6e0b62..e4f7527170 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/SharingSettings.vue
+++ b/apps/app-frontend/src/pages/instance/components/settings-modal/sharing-settings.vue
@@ -40,29 +40,28 @@
-
-
+
-
-
-
-
+ class="animate-spin"
+ aria-hidden="true"
+ />
+
+
@@ -81,8 +80,8 @@
diff --git a/apps/app-frontend/src/pages/instance/Files.vue b/apps/app-frontend/src/pages/instance/files/index.vue
similarity index 80%
rename from apps/app-frontend/src/pages/instance/Files.vue
rename to apps/app-frontend/src/pages/instance/files/index.vue
index 79020b38ac..c54a58f3cb 100644
--- a/apps/app-frontend/src/pages/instance/Files.vue
+++ b/apps/app-frontend/src/pages/instance/files/index.vue
@@ -10,6 +10,7 @@ import {
useDebugLogger,
useVIntl,
} from '@modrinth/ui'
+import { useQuery } from '@tanstack/vue-query'
import { invoke } from '@tauri-apps/api/core'
import {
mkdir,
@@ -22,21 +23,17 @@ import {
writeFile as writeFileBytes,
writeTextFile,
} from '@tauri-apps/plugin-fs'
-import { onUnmounted, ref, watch } from 'vue'
+import { computed, ref, watch } from 'vue'
-import { instance_listener } from '@/helpers/events'
+import { useAppEvent } from '@/composables/use-app-event'
import { get_full_path } from '@/helpers/instance'
-import type { GameInstance } from '@/helpers/types'
import { highlightInFolder } from '@/helpers/utils'
-const props = defineProps<{
- instance: GameInstance
- options: unknown
- offline: boolean
- playing: boolean
- installed: boolean
- isServerInstance: boolean
-}>()
+import { injectInstancePage } from '../instance-context'
+import { instanceKeys } from '../query-options'
+
+const instancePage = injectInstancePage()
+const instanceId = instancePage.instanceId
const { formatMessage } = useVIntl()
const { addNotification } = injectNotificationManager()
@@ -53,7 +50,15 @@ const messages = defineMessages({
},
})
-const instanceRoot = ref('')
+const instanceRootQuery = useQuery(
+ computed(() => ({
+ queryKey: instanceKeys.rootPath(instancePage.instanceId.value),
+ queryFn: () => get_full_path(instancePage.instanceId.value),
+ enabled: !!instancePage.instanceId.value,
+ staleTime: Infinity,
+ })),
+)
+const instanceRoot = computed(() => instanceRootQuery.data.value ?? '')
const items = ref([])
/** True until the first directory read for the current instance path finishes (initial load only). */
const firstPaintPending = ref(true)
@@ -62,12 +67,7 @@ const error = ref(null)
const currentPath = ref('')
const editingFile = ref(null)
-debug('setup: start, instance.id =', props.instance.id)
-
-instanceRoot.value = await get_full_path(props.instance.id)
-debug('setup: instanceRoot =', instanceRoot.value)
-await refresh()
-debug('setup: refresh complete, items =', items.value.length, 'error =', error.value)
+debug('setup: start, instance.id =', instanceId.value)
function resolvePath(relativePath: string): string {
return relativePath ? `${instanceRoot.value}/${relativePath}` : instanceRoot.value
@@ -113,21 +113,39 @@ async function listDirectory(dirPath: string): Promise {
return results.filter((item): item is FileItem => item !== null)
}
+const directoryQuery = useQuery(
+ computed(() => ({
+ queryKey: instanceKeys.files(instancePage.instanceId.value, currentPath.value),
+ queryFn: () => listDirectory(currentPath.value),
+ enabled: !!instanceRoot.value,
+ staleTime: 30_000,
+ })),
+)
+
+watch(
+ directoryQuery.data,
+ (data) => {
+ if (!data) return
+ items.value = data
+ firstPaintPending.value = false
+ },
+ { immediate: true },
+)
+watch(directoryQuery.isFetching, (fetching) => {
+ loading.value = fetching
+})
+watch(directoryQuery.error, (queryError) => {
+ error.value = queryError
+ if (queryError) items.value = []
+})
+
+await instanceRootQuery.suspense()
+await directoryQuery.refetch()
+firstPaintPending.value = false
+
async function refresh() {
debug('refresh: called, currentPath =', currentPath.value, 'instanceRoot =', instanceRoot.value)
- loading.value = true
- error.value = null
- try {
- items.value = await listDirectory(currentPath.value)
- debug('refresh: success, items =', items.value.length)
- } catch (e) {
- debug('refresh: error =', e)
- error.value = e instanceof Error ? e : new Error(String(e))
- items.value = []
- } finally {
- loading.value = false
- firstPaintPending.value = false
- }
+ await directoryQuery.refetch()
}
function navigateTo(path: string) {
@@ -221,7 +239,7 @@ async function handleWriteFile(path: string, content: string) {
async function handleDownloadFile(path: string, _fileName: string) {
await invoke('plugin:files|file_save_as', {
- instanceId: props.instance.id,
+ instanceId: instanceId.value,
filePath: path,
})
}
@@ -275,7 +293,7 @@ async function handleUploadFiles(files: File[]) {
async function handleExtractFile(path: string, override: boolean, dry: boolean) {
try {
return await invoke('plugin:files|file_extract_zip', {
- instanceId: props.instance.id,
+ instanceId: instanceId.value,
filePath: path,
overrideConflicts: override,
dryRun: dry,
@@ -289,32 +307,21 @@ async function handleExtractFile(path: string, override: boolean, dry: boolean)
}
}
-debug('setup: registering instance_listener')
-const unlistenInstances = await instance_listener(
- async (event: { event: string; instance_id: string }) => {
- debug('instance_listener: event =', event.event, 'path =', event.instance_id)
- if (event.instance_id === props.instance.id && event.event === 'synced') {
- debug('instance_listener: synced event matched, calling refresh')
- await refresh()
- }
- },
-)
-debug('setup: instance_listener registered')
-
-onUnmounted(() => {
- unlistenInstances()
+useAppEvent('instance', async (event) => {
+ debug('app event: instance =', event.event, 'path =', event.instance_id)
+ if (event.instance_id === instanceId.value && event.event === 'synced') {
+ debug('app event: synced instance matched, calling refresh')
+ await refresh()
+ }
})
-watch(
- () => props.instance.id,
- async () => {
- debug('watch instance.id: changed to', props.instance.id)
- firstPaintPending.value = true
- instanceRoot.value = await get_full_path(props.instance.id)
- currentPath.value = ''
- await refresh()
- },
-)
+watch(instanceId, async () => {
+ debug('watch instance.id: changed to', instanceId.value)
+ firstPaintPending.value = true
+ currentPath.value = ''
+ await instanceRootQuery.refetch()
+ await refresh()
+})
provideFileManager({
items,
diff --git a/apps/app-frontend/src/pages/instance/index.js b/apps/app-frontend/src/pages/instance/index.js
deleted file mode 100644
index 0e6a0e7ec2..0000000000
--- a/apps/app-frontend/src/pages/instance/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import Files from './Files.vue'
-import Index from './Index.vue'
-import Logs from './Logs.vue'
-import Mods from './Mods.vue'
-import Overview from './Overview.vue'
-import Share from './share/index.vue'
-import Worlds from './Worlds.vue'
-
-export { Files, Index, Logs, Mods, Overview, Share, Worlds }
diff --git a/apps/app-frontend/src/pages/instance/index.ts b/apps/app-frontend/src/pages/instance/index.ts
new file mode 100644
index 0000000000..a4cfdec8da
--- /dev/null
+++ b/apps/app-frontend/src/pages/instance/index.ts
@@ -0,0 +1,8 @@
+import Content from './content/index.vue'
+import Files from './files/index.vue'
+import Index from './layout.vue'
+import Logs from './logs/index.vue'
+import Share from './share/index.vue'
+import Worlds from './worlds/index.vue'
+
+export { Content, Files, Index, Logs, Share, Worlds }
diff --git a/apps/app-frontend/src/pages/instance/instance-context.ts b/apps/app-frontend/src/pages/instance/instance-context.ts
new file mode 100644
index 0000000000..397922e372
--- /dev/null
+++ b/apps/app-frontend/src/pages/instance/instance-context.ts
@@ -0,0 +1,29 @@
+import type { Labrinth } from '@modrinth/api-client'
+import { createContext } from '@modrinth/ui'
+import type { ComputedRef, Ref } from 'vue'
+
+import type { GameInstance } from '@/helpers/types'
+
+export interface InstancePageContext {
+ readonly instanceId: ComputedRef
+ readonly instance: ComputedRef
+ readonly linkedProject: ComputedRef
+ readonly isServerInstance: ComputedRef
+ readonly sharedInstanceUpdateAvailable: ComputedRef
+ readonly offline: Readonly[>
+ readonly playing: ComputedRef]
+ readonly loading: Readonly[>
+ readonly stopping: Readonly][>
+ refreshInstance: () => Promise]
+ refreshPlayState: () => Promise
+ play: (source: string) => Promise
+ stop: (source: string) => Promise
+ playServer: () => Promise
+ openSettings: (tab?: number) => void
+ browseContent: (projectType?: string) => Promise
+ browseServers: () => Promise
+ reviewSharedInstanceUpdate: (event?: MouseEvent) => void
+}
+
+export const [injectInstancePage, provideInstancePage] =
+ createContext('InstancePage')
diff --git a/apps/app-frontend/src/pages/instance/Index.vue b/apps/app-frontend/src/pages/instance/layout.vue
similarity index 55%
rename from apps/app-frontend/src/pages/instance/Index.vue
rename to apps/app-frontend/src/pages/instance/layout.vue
index 6cc08714f1..ac60605015 100644
--- a/apps/app-frontend/src/pages/instance/Index.vue
+++ b/apps/app-frontend/src/pages/instance/layout.vue
@@ -11,7 +11,7 @@
ref="settingsModal"
:instance="instance"
:offline="offline"
- @unlinked="fetchInstance"
+ @unlinked="refreshInstance"
/>
repairInstance()"
@stop="() => stopInstance('InstancePage')"
@play="() => startInstance('InstancePage')"
@@ -64,33 +61,19 @@
:shared-instance-expected-user-id="sharedInstanceExpectedUserId"
:shared-instance-role="instance.shared_instance?.role"
:shared-instance-signed-out="sharedInstanceSignedOut"
- :shared-instance-update-available="showSharedInstanceUpdateAdmonition"
- @published="fetchInstance"
+ @published="refreshInstance"
@delete="requestInstanceDeletion"
- @review-update="reviewSharedInstanceUpdate"
/>
-
+
- stopInstance('InstanceSubpage')"
- >
+
@@ -102,45 +85,24 @@
Edit
Copy path
Open folder
- Copy link
- Open in Modrinth
- Copy names
- Copy slugs
- Copy links
- Toggle selected
- Disable selected
- Enable selected
- Show/Hide unselected
- Update {{ selected.length > 0 ? 'selected' : 'all' }}
- Select Updatable
-
-
diff --git a/apps/app-frontend/src/pages/instance/Logs.vue b/apps/app-frontend/src/pages/instance/logs/index.vue
similarity index 68%
rename from apps/app-frontend/src/pages/instance/Logs.vue
rename to apps/app-frontend/src/pages/instance/logs/index.vue
index 6a08117dd7..2aacfe0d7b 100644
--- a/apps/app-frontend/src/pages/instance/Logs.vue
+++ b/apps/app-frontend/src/pages/instance/logs/index.vue
@@ -11,51 +11,20 @@ import {
injectNotificationManager,
provideConsoleManager,
} from '@modrinth/ui'
-import { computed, onUnmounted, ref, shallowRef, triggerRef, watch, watchEffect } from 'vue'
-import { useRoute } from 'vue-router'
+import { useQuery } from '@tanstack/vue-query'
+import { computed, ref, shallowRef, triggerRef, watch, watchEffect } from 'vue'
+import { useAppEvent } from '@/composables/use-app-event'
import { useInstanceConsole } from '@/composables/useInstanceConsole'
-import { log_listener, process_listener } from '@/helpers/events.js'
import { delete_logs_by_filename, get_output_by_filename } from '@/helpers/logs.js'
+import { injectInstancePage } from '../instance-context'
+import { instanceKeys } from '../query-options'
+
const client = injectModrinthClient()
const { handleError } = injectNotificationManager()
-const route = useRoute()
-
-const props = defineProps({
- instance: {
- type: Object,
- default() {
- return {}
- },
- },
- options: {
- type: Object,
- default() {
- return {}
- },
- },
- offline: {
- type: Boolean,
- default() {
- return false
- },
- },
- playing: {
- type: Boolean,
- default() {
- return false
- },
- },
- installed: {
- type: Boolean,
- default() {
- return false
- },
- },
-})
-
-const instanceId = computed(() => route.params.id)
+const instancePage = injectInstancePage()
+const instanceId = instancePage.instanceId
const {
liveConsole,
historicalConsole,
@@ -66,7 +35,17 @@ const {
clearLive,
} = useInstanceConsole(instanceId.value)
-await hydrate()
+const consoleHydrationQuery = useQuery({
+ queryKey: computed(() => instanceKeys.console(instanceId.value)),
+ queryFn: async () => {
+ await hydrate()
+ return true
+ },
+ staleTime: 0,
+ refetchOnMount: 'always',
+})
+
+await consoleHydrationQuery.suspense()
function buildLogList(rawLogs) {
return [
@@ -88,18 +67,29 @@ function buildLogList(rawLogs) {
}
const logs = ref(buildLogList([]))
-
-void getHistoricalLogs()
- .then((allLogs) => {
- logs.value = buildLogList(allLogs)
- })
- .catch(handleError)
+const historicalLogsQuery = useQuery({
+ queryKey: computed(() => instanceKeys.logs(instanceId.value)),
+ queryFn: getHistoricalLogs,
+ staleTime: 0,
+})
+watch(
+ historicalLogsQuery.data,
+ (allLogs) => {
+ if (allLogs) logs.value = buildLogList(allLogs)
+ },
+ { immediate: true },
+)
+watch(historicalLogsQuery.error, (error) => {
+ if (error) handleError(error)
+})
const selectedLogIndex = ref(0)
const isLive = computed(() => selectedLogIndex.value === 0)
const filteredLogs = computed(() =>
- props.playing ? logs.value.filter((l) => l.live || l.name !== 'latest.log') : logs.value,
+ instancePage.playing.value
+ ? logs.value.filter((l) => l.live || l.name !== 'latest.log')
+ : logs.value,
)
const logSources = computed(() =>
@@ -140,16 +130,16 @@ const selectedLog = computed(() => filteredLogs.value[selectedLogIndex.value])
const deleteDisabled = computed(() => {
const log = selectedLog.value
if (!log || log.live) return true
- return log.filename === 'latest.log' && props.playing
+ return log.filename === 'latest.log' && instancePage.playing.value
})
async function deleteSelectedLog() {
const log = selectedLog.value
if (!log || log.live) return
- await delete_logs_by_filename(props.instance.id, log.log_type, log.filename)
+ await delete_logs_by_filename(instanceId.value, log.log_type, log.filename)
invalidate()
- const freshLogs = await getHistoricalLogs()
- logs.value = buildLogList(freshLogs)
+ const { data } = await historicalLogsQuery.refetch()
+ if (data) logs.value = buildLogList(data)
selectedLogIndex.value = 0
}
@@ -166,7 +156,7 @@ provideConsoleManager({
onDelete: deleteSelectedLog,
deleteDisabled,
deleteDisabledTooltip: 'Cannot delete latest.log while the instance is running',
- shareDisabled: computed(() => props.offline),
+ shareDisabled: instancePage.offline,
emptyStateType: 'instance',
crashAnalysis,
onDismissCrash: () => {
@@ -186,7 +176,7 @@ watch(selectedLogIndex, async (newIndex) => {
return
}
- const output = await get_output_by_filename(props.instance.id, log.log_type, log.filename).catch(
+ const output = await get_output_by_filename(instanceId.value, log.log_type, log.filename).catch(
handleError,
)
if (output) {
@@ -197,11 +187,11 @@ watch(selectedLogIndex, async (newIndex) => {
selectedLogIndex.value = 0
-if (!props.playing) {
+if (!instancePage.playing.value) {
void analyseForCrash()
}
-const unlistenLog = await log_listener((payload) => {
+useAppEvent('log', (payload) => {
if (payload.instance_id !== instanceId.value) return
if (payload.type === 'log4j') {
@@ -211,23 +201,19 @@ const unlistenLog = await log_listener((payload) => {
}
})
-const unlistenProcesses = await process_listener(async (e) => {
+useAppEvent('process', async (e) => {
if (e.instance_id !== instanceId.value) return
if (e.event === 'launched') {
liveConsole.clear()
invalidate()
+ void historicalLogsQuery.refetch()
selectedLogIndex.value = 0
}
if (e.event === 'finished') {
invalidate()
- const freshLogs = await getHistoricalLogs()
- logs.value = buildLogList(freshLogs)
+ const { data } = await historicalLogsQuery.refetch()
+ if (data) logs.value = buildLogList(data)
void analyseForCrash()
}
})
-
-onUnmounted(() => {
- unlistenLog()
- unlistenProcesses()
-})
diff --git a/apps/app-frontend/src/pages/instance/query-options.ts b/apps/app-frontend/src/pages/instance/query-options.ts
new file mode 100644
index 0000000000..6848ccb7ac
--- /dev/null
+++ b/apps/app-frontend/src/pages/instance/query-options.ts
@@ -0,0 +1,81 @@
+import { queryOptions } from '@tanstack/vue-query'
+
+import { get_project_v3 } from '@/helpers/cache.js'
+import { get as getInstance } from '@/helpers/instance'
+import { loadInstanceContentData } from '@/helpers/instance-content'
+import { get_by_instance_id } from '@/helpers/process'
+import { refreshWorlds } from '@/helpers/worlds'
+
+export const instanceKeys = {
+ all: ['instances'] as const,
+ detail: (instanceId: string) => [...instanceKeys.all, 'summary', instanceId] as const,
+ processes: (instanceId: string) => [...instanceKeys.all, 'processes', instanceId] as const,
+ content: (instanceId: string) => [...instanceKeys.all, 'content', instanceId] as const,
+ contentUpdateCheck: (instanceId: string) =>
+ [...instanceKeys.all, 'content-update-check', instanceId] as const,
+ rootPath: (instanceId: string) => [...instanceKeys.detail(instanceId), 'root-path'] as const,
+ files: (instanceId: string, path: string) =>
+ [...instanceKeys.detail(instanceId), 'files', path] as const,
+ console: (instanceId: string) => [...instanceKeys.detail(instanceId), 'console'] as const,
+ logs: (instanceId: string) => [...instanceKeys.detail(instanceId), 'logs'] as const,
+ installedProjectIds: (instanceId: string, source: 'content' | 'worlds') =>
+ [...instanceKeys.detail(instanceId), 'installed-project-ids', source] as const,
+ linkedContent: (instanceId: string) => ['linkedModpackContent', instanceId] as const,
+ worlds: (instanceId: string) => ['worlds', instanceId] as const,
+ linkedProject: (projectId: string) => ['project', 'v3', projectId] as const,
+ sharedEligibility: (userId: string | null | undefined) =>
+ ['shared-instance-eligibility', userId] as const,
+ sharedUpdatePreview: (instanceId: string, userId: string | null | undefined) =>
+ [...instanceKeys.detail(instanceId), 'shared-update-preview', userId] as const,
+ sharedMembers: (instanceId: string) => ['sharedInstanceUsers', instanceId] as const,
+}
+
+export function instanceDetailQueryOptions(instanceId: string) {
+ return queryOptions({
+ queryKey: instanceKeys.detail(instanceId),
+ queryFn: async () => {
+ const instance = await getInstance(instanceId)
+ if (!instance) throw new Error(`Instance ${instanceId} is not managed`)
+ return instance
+ },
+ staleTime: 30_000,
+ })
+}
+
+export function instanceProcessesQueryOptions(instanceId: string) {
+ return queryOptions({
+ queryKey: instanceKeys.processes(instanceId),
+ queryFn: async () => {
+ const processes = await get_by_instance_id(instanceId)
+ return Array.isArray(processes) ? processes : []
+ },
+ staleTime: 0,
+ })
+}
+
+export function instanceLinkedProjectQueryOptions(projectId: string) {
+ return queryOptions({
+ queryKey: instanceKeys.linkedProject(projectId),
+ queryFn: () => get_project_v3(projectId, 'must_revalidate'),
+ staleTime: 30_000,
+ })
+}
+
+export function instanceContentQueryOptions(
+ instanceId: string,
+ onError?: (error: Error) => unknown,
+) {
+ return queryOptions({
+ queryKey: instanceKeys.content(instanceId),
+ queryFn: () => loadInstanceContentData(instanceId, undefined, onError),
+ staleTime: 30_000,
+ })
+}
+
+export function instanceWorldsQueryOptions(instanceId: string) {
+ return queryOptions({
+ queryKey: instanceKeys.worlds(instanceId),
+ queryFn: () => refreshWorlds(instanceId),
+ staleTime: 0,
+ })
+}
diff --git a/apps/app-frontend/src/pages/instance/share/index.vue b/apps/app-frontend/src/pages/instance/share/index.vue
index b6addbe3bf..d88eed0d3c 100644
--- a/apps/app-frontend/src/pages/instance/share/index.vue
+++ b/apps/app-frontend/src/pages/instance/share/index.vue
@@ -55,20 +55,7 @@
-
+
-
- {{ formatMessage(lockedActionButton) }}
-
+
+ {{ formatMessage(lockedActionButton) }}
+
@@ -123,21 +108,21 @@
:description="formatMessage(messages.noFriendsInvitedDescription)"
>
-
- {{
- formatMessage(messages.inviteFriendsButton)
- }}
-
+ {{
+ formatMessage(messages.inviteFriendsButton)
+ }}
+
@@ -147,7 +132,7 @@
import { LogInIcon, SpinnerIcon, UserPlusIcon } from '@modrinth/assets'
import {
Avatar,
- ButtonStyled,
+ Button,
ConfirmUnlinkModal,
defineMessages,
injectAuth,
@@ -156,8 +141,8 @@ import {
type InvitePlayersUser,
useVIntl,
} from '@modrinth/ui'
-import { useQuery, useQueryClient } from '@tanstack/vue-query'
-import { computed, ref, toRef, watch } from 'vue'
+import { useQueryClient } from '@tanstack/vue-query'
+import { computed, ref, watch } from 'vue'
import ModrinthAccountRequiredModal from '@/components/ui/modal/ModrinthAccountRequiredModal.vue'
import SharedInstancePublishModal from '@/components/ui/shared-instances/SharedInstancePublishModal.vue'
@@ -166,16 +151,16 @@ import {
isSharedInstancesApiError,
isSharedInstanceUnavailableError,
} from '@/helpers/install'
-import { can_current_user_use_shared_instances, edit } from '@/helpers/instance'
+import { edit } from '@/helpers/instance'
import type { ModrinthAuthFlow } from '@/helpers/mr_auth.ts'
import {
sharedInstanceErrorMessages,
useSharedInstanceErrors,
} from '@/helpers/shared-instance-errors'
-import type { GameInstance } from '@/helpers/types'
-import { provideInstanceBackup } from '@/providers/instance-backup'
-import { injectSharedInstanceState } from '../use-shared-instance-state'
+import { injectInstancePage } from '../instance-context'
+import { injectSharedInstance } from '../shared-instance-context'
+import { provideSharedInstanceManagement } from './shared-instance-management-context'
import SharedInstanceMembersTable from './shared-instance-members-table.vue'
import SharedInstanceRemoveMemberModal from './shared-instance-remove-member-modal.vue'
import SharedInstanceShareEmptyState from './shared-instance-share-empty-state.vue'
@@ -184,10 +169,7 @@ import { useSharedInstanceInviteCandidates } from './use-shared-instance-invite-
import { useSharedInstanceInviteLink } from './use-shared-instance-invite-link'
import { useSharedInstanceMembers } from './use-shared-instance-members'
-const props = defineProps<{
- instance: GameInstance
- offline?: boolean
-}>()
+const instancePage = injectInstancePage()
const auth = injectAuth()
const queryClient = useQueryClient()
const { formatMessage } = useVIntl()
@@ -196,8 +178,9 @@ const {
notifySharedInstanceError,
notifySharedInstanceUnavailable,
} = useSharedInstanceErrors()
-const sharedInstanceState = injectSharedInstanceState()
-const instance = toRef(props, 'instance')
+const sharedInstanceState = injectSharedInstance()
+const instance = computed(() => instancePage.instance.value!)
+const offline = instancePage.offline
const actionsLocked = sharedInstanceState.shareActionsLocked
const sharedInstanceActionsLocked = actionsLocked
const currentUserId = computed(() => auth.user.value?.id ?? null)
@@ -224,16 +207,7 @@ function notifyOperationError(error: unknown) {
}
}
-const eligibilityQuery = useQuery({
- queryKey: computed(() => ['shared-instance-eligibility', currentUserId.value]),
- queryFn: can_current_user_use_shared_instances,
- enabled: () => isSignedIn.value && !!currentUserId.value,
- retry: false,
- staleTime: Infinity,
- refetchOnMount: 'always',
- refetchOnWindowFocus: false,
- refetchOnReconnect: false,
-})
+const eligibilityQuery = sharedInstanceState.eligibilityQuery
const members = useSharedInstanceMembers({
instance,
@@ -257,7 +231,7 @@ const {
actionsLocked,
})
const inviteLink = useSharedInstanceInviteLink(
- computed(() => props.instance.id),
+ computed(() => instance.value.id),
remainingUserSlots,
notifyOperationError,
)
@@ -286,7 +260,7 @@ const unableToConnect = computed(
const membersTableLoading = computed(
() =>
members.rows.value.length === 0 &&
- !!props.instance.shared_instance &&
+ !!instance.value.shared_instance &&
(members.query.data.value === undefined || members.query.isFetching.value) &&
!sharedInstanceUnavailable.value &&
!sharedInstanceActionsLocked.value,
@@ -294,7 +268,7 @@ const membersTableLoading = computed(
const showMembersTable = computed(
() =>
members.rows.value.length > 0 ||
- (!!props.instance.shared_instance &&
+ (!!instance.value.shared_instance &&
members.query.data.value !== undefined &&
!members.query.isFetching.value &&
!sharedInstanceUnavailable.value &&
@@ -302,13 +276,13 @@ const showMembersTable = computed(
)
const requiresUnlink = computed(
() =>
- props.instance.link?.type === 'imported_modpack' &&
- !props.instance.shared_instance &&
+ instance.value.link?.type === 'imported_modpack' &&
+ !instance.value.shared_instance &&
!importedModpackUnlinked.value,
)
const importedModpackBackupTip = computed(() =>
- props.instance.link?.type === 'imported_modpack'
- ? (props.instance.link.name ?? props.instance.link.filename ?? undefined)
+ instance.value.link?.type === 'imported_modpack'
+ ? (instance.value.link.name ?? instance.value.link.filename ?? undefined)
: undefined,
)
@@ -395,9 +369,9 @@ async function showInvitePlayers(event?: MouseEvent) {
}
async function unlinkImportedModpack() {
try {
- await edit(props.instance.id, { link: null as unknown as undefined })
+ await edit(instance.value.id, { link: null as unknown as undefined })
importedModpackUnlinked.value = true
- await queryClient.invalidateQueries({ queryKey: ['linkedModpackInfo', props.instance.id] })
+ await queryClient.invalidateQueries({ queryKey: ['linkedModpackInfo', instance.value.id] })
if (await inviteLink.ensure()) invitePlayersModal.value?.show()
} catch (error) {
notifyOperationError(error)
@@ -419,7 +393,7 @@ function userProfileLink(username: string) {
return !username || username.includes('@') ? undefined : `/user/${encodeURIComponent(username)}`
}
async function requestAuth(flow: ModrinthAuthFlow) {
- await auth.requestSignIn(`/instance/${encodeURIComponent(props.instance.id)}/share`, flow, {
+ await auth.requestSignIn(`/instance/${encodeURIComponent(instance.value.id)}/share`, flow, {
showModal: false,
})
return !!auth.session_token.value
@@ -428,6 +402,23 @@ function signInToShare(event?: MouseEvent) {
void accountRequiredModal.value?.show(event)
}
+provideSharedInstanceManagement({
+ rows: members.rows,
+ actionsLocked: sharedInstanceActionsLocked,
+ inviteDisabled: computed(() => !hasRemainingUserSlots.value),
+ invitePending: inviteLink.pending,
+ pushUpdateDisabled: computed(
+ () =>
+ instance.value.install_stage !== 'installed' ||
+ publishState.value !== 'idle' ||
+ offline.value,
+ ),
+ pushUpdatePending: computed(() => publishState.value !== 'idle'),
+ invite: (event) => void showInvitePlayers(event),
+ remove: showRemoveMemberModal,
+ pushUpdate: reviewUpdate,
+})
+
watch(
[eligibilityQuery.error, members.query.error],
(errors) => {
@@ -443,7 +434,7 @@ watch([eligibilityQuery.data, members.query.data], ([eligibility, memberRows]) =
}
})
watch(
- () => props.instance.id,
+ () => instance.value.id,
() => {
importedModpackUnlinked.value = false
},
@@ -455,6 +446,4 @@ watch(
},
{ immediate: true, flush: 'post' },
)
-
-provideInstanceBackup(() => props.instance)
diff --git a/apps/app-frontend/src/pages/instance/share/shared-instance-management-context.ts b/apps/app-frontend/src/pages/instance/share/shared-instance-management-context.ts
new file mode 100644
index 0000000000..615d66e16e
--- /dev/null
+++ b/apps/app-frontend/src/pages/instance/share/shared-instance-management-context.ts
@@ -0,0 +1,19 @@
+import { createContext } from '@modrinth/ui'
+import type { ComputedRef, Ref } from 'vue'
+
+import type { ShareRow } from './shared-instance-share-types'
+
+export interface SharedInstanceManagementContext {
+ readonly rows: ComputedRef
+ readonly actionsLocked: Ref
+ readonly inviteDisabled: ComputedRef
+ readonly invitePending: Ref
+ readonly pushUpdateDisabled: ComputedRef
+ readonly pushUpdatePending: ComputedRef
+ invite: (event: MouseEvent) => void
+ remove: (row: ShareRow) => void
+ pushUpdate: (event: MouseEvent) => void
+}
+
+export const [injectSharedInstanceManagement, provideSharedInstanceManagement] =
+ createContext('InstanceSharePage')
diff --git a/apps/app-frontend/src/pages/instance/share/shared-instance-members-table.vue b/apps/app-frontend/src/pages/instance/share/shared-instance-members-table.vue
index 85cc02c8c2..fb35a9457a 100644
--- a/apps/app-frontend/src/pages/instance/share/shared-instance-members-table.vue
+++ b/apps/app-frontend/src/pages/instance/share/shared-instance-members-table.vue
@@ -11,28 +11,29 @@
clearable
/>
-
-
-
-
- {{ formatMessage(messages.pushUpdate) }}
-
-
-
-
-
-
- Invite friends
-
-
+
+
+
+ {{ formatMessage(messages.pushUpdate) }}
+
+
+
+
+ Invite friends
+
@@ -120,15 +121,15 @@
-
-
+
+
@@ -145,10 +146,10 @@ import {
UserPlusIcon,
XIcon,
} from '@modrinth/assets'
+import { Button, IconButton } from '@modrinth/ui'
import {
AutoLink,
Avatar,
- ButtonStyled,
defineMessages,
type SortDirection,
StyledInput,
@@ -161,6 +162,7 @@ import {
} from '@modrinth/ui'
import { computed, ref, watch } from 'vue'
+import { injectSharedInstanceManagement } from './shared-instance-management-context'
import {
type MethodFilter,
methodLabels,
@@ -169,19 +171,15 @@ import {
type ShareTableColumn,
} from './shared-instance-share-types'
-const props = defineProps<{
- rows: ShareRow[]
- actionsLocked?: boolean
- inviteDisabled?: boolean
- invitePending?: boolean
- pushUpdateDisabled?: boolean
- pushUpdatePending?: boolean
-}>()
-const emit = defineEmits<{
- invite: [event: MouseEvent]
- remove: [row: ShareRow]
- 'push-update': [event: MouseEvent]
-}>()
+const management = injectSharedInstanceManagement()
+const {
+ rows,
+ actionsLocked,
+ inviteDisabled,
+ invitePending,
+ pushUpdateDisabled,
+ pushUpdatePending,
+} = management
const search = ref('')
const methodFilter = ref
('all')
const sortColumn = ref('joined')
@@ -194,7 +192,7 @@ const methodFilterOptions: Array<{ id: ShareMethod; label: string }> = [
{ id: 'direct', label: methodLabels.direct },
{ id: 'link', label: methodLabels.link },
]
-const hasMultipleMethods = computed(() => new Set(props.rows.map((row) => row.method)).size > 1)
+const hasMultipleMethods = computed(() => new Set(rows.value.map((row) => row.method)).size > 1)
const columns = computed[]>(() => {
const result: TableColumn[] = [
{
@@ -230,7 +228,7 @@ const columns = computed[]>(() => {
cellClass: 'whitespace-nowrap !px-2',
},
]
- if (!props.actionsLocked)
+ if (!actionsLocked.value)
result.push({
key: 'actions',
label: 'Actions',
@@ -243,7 +241,7 @@ const columns = computed[]>(() => {
})
const filteredRows = computed(() => {
const query = search.value.trim().toLowerCase()
- return props.rows.filter((row) => {
+ return rows.value.filter((row) => {
if (methodFilter.value !== 'all' && row.method !== methodFilter.value) return false
if (!query) return true
return [
@@ -285,7 +283,7 @@ function filterClass(active: boolean) {
return [
'cursor-pointer rounded-full border border-solid px-3 py-1.5 text-base font-semibold leading-5 transition-all duration-100 active:scale-[0.97]',
active
- ? 'border-green bg-brand-highlight text-brand'
+ ? 'border-brand bg-brand-highlight text-brand'
: 'border-surface-5 bg-surface-4 text-primary hover:bg-surface-5',
]
}
diff --git a/apps/app-frontend/src/pages/instance/share/shared-instance-remove-member-modal.vue b/apps/app-frontend/src/pages/instance/share/shared-instance-remove-member-modal.vue
index 1f7983dcdd..96d67be712 100644
--- a/apps/app-frontend/src/pages/instance/share/shared-instance-remove-member-modal.vue
+++ b/apps/app-frontend/src/pages/instance/share/shared-instance-remove-member-modal.vue
@@ -32,16 +32,12 @@
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
- {{ formatMessage(messages.removeButton) }}
-
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+ {{ formatMessage(messages.removeButton) }}
+
@@ -52,7 +48,7 @@ import { UserXIcon, XIcon } from '@modrinth/assets'
import {
Admonition,
Avatar,
- ButtonStyled,
+ Button,
commonMessages,
defineMessages,
NewModal,
diff --git a/apps/app-frontend/src/pages/instance/share/use-shared-instance-members.ts b/apps/app-frontend/src/pages/instance/share/use-shared-instance-members.ts
index 801f9a3552..cd0c43304c 100644
--- a/apps/app-frontend/src/pages/instance/share/use-shared-instance-members.ts
+++ b/apps/app-frontend/src/pages/instance/share/use-shared-instance-members.ts
@@ -12,13 +12,14 @@ import {
} from '@/helpers/instance'
import type { GameInstance } from '@/helpers/types'
+import { instanceKeys } from '../query-options'
import {
normalizeInviteKey,
SHARED_INSTANCE_USER_LIMIT,
type ShareRow,
} from './shared-instance-share-types'
-type MembersQueryKey = readonly ['sharedInstanceUsers', string]
+type MembersQueryKey = ReturnType
type OptimisticChange = {
queryKey: MembersQueryKey
@@ -48,7 +49,7 @@ export function useSharedInstanceMembers(options: {
onError: (error: unknown) => void
}) {
const queryClient = useQueryClient()
- const queryKey = computed(() => ['sharedInstanceUsers', options.instance.value.id] as const)
+ const queryKey = computed(() => instanceKeys.sharedMembers(options.instance.value.id))
const invitingUserIds = new Set()
const removingUserIds = new Set()
const exclusiveMutationPending = ref(false)
diff --git a/apps/app-frontend/src/pages/instance/shared-instance-context.ts b/apps/app-frontend/src/pages/instance/shared-instance-context.ts
new file mode 100644
index 0000000000..57c424d5ca
--- /dev/null
+++ b/apps/app-frontend/src/pages/instance/shared-instance-context.ts
@@ -0,0 +1,184 @@
+import { createContext, injectAuth } from '@modrinth/ui'
+import { useQuery, useQueryClient } from '@tanstack/vue-query'
+import { computed, type Ref, ref, watch } from 'vue'
+
+import { useUserQuery } from '@/composables/users/use-user-query'
+import {
+ getSharedInstanceUnavailableReason,
+ install_get_shared_instance_update_preview,
+ isSharedInstanceUnavailableError,
+ type SharedInstanceUnavailableReason,
+} from '@/helpers/install'
+import { can_current_user_use_shared_instances } from '@/helpers/instance'
+import type { GameInstance } from '@/helpers/types'
+
+import { instanceKeys } from './query-options'
+
+export type SharedInstanceManager =
+ | {
+ type: 'user'
+ name: string
+ avatarUrl?: string
+ tintBy: string
+ }
+ | {
+ type: 'server'
+ name: string
+ avatarUrl?: string
+ tintBy: string
+ }
+
+export function createSharedInstanceContext(
+ instance: Ref,
+ offline: Ref,
+ notifyError: (error: unknown) => void,
+) {
+ const auth = injectAuth()
+ const queryClient = useQueryClient()
+ const forcedUnavailableReason = ref(null)
+
+ const expectedUserId = computed(() => instance.value?.shared_instance?.linked_user_id ?? null)
+ const wrongAccount = computed(() => {
+ if (auth.isReady && !auth.isReady.value) return false
+ if (!expectedUserId.value) return false
+ return auth.user.value?.id !== expectedUserId.value
+ })
+ const actionsLocked = computed(() => wrongAccount.value)
+ const signedOut = computed(() => !auth.session_token.value)
+ const managerUserId = computed(() => {
+ const attachment = instance.value?.shared_instance
+ if (!attachment) return null
+ if (attachment.role === 'owner') {
+ return actionsLocked.value ? (attachment.linked_user_id ?? null) : null
+ }
+ return attachment.manager_id ?? null
+ })
+ const managerUserQuery = useUserQuery(managerUserId)
+ const manager = computed(() => {
+ const attachment = instance.value?.shared_instance
+ if (!attachment) return null
+
+ if (attachment.server_manager_name) {
+ return {
+ type: 'server',
+ name: attachment.server_manager_name,
+ avatarUrl: attachment.server_manager_icon_url ?? undefined,
+ tintBy: attachment.server_manager_name,
+ }
+ }
+
+ const user = managerUserQuery.data.value
+ if (!user) return null
+ return {
+ type: 'user',
+ name: user.username,
+ avatarUrl: user.avatar_url ?? undefined,
+ tintBy: user.id,
+ }
+ })
+ const unavailableManager = computed(() => manager.value?.name ?? null)
+
+ const eligibilityQuery = useQuery({
+ queryKey: computed(() => instanceKeys.sharedEligibility(auth.user.value?.id)),
+ queryFn: can_current_user_use_shared_instances,
+ enabled: () => !!auth.session_token.value && !!auth.user.value?.id,
+ retry: false,
+ staleTime: Infinity,
+ refetchOnWindowFocus: false,
+ refetchOnReconnect: false,
+ })
+ const currentUserCanUseSharedInstances = computed(
+ () => !auth.session_token.value || eligibilityQuery.data.value !== false,
+ )
+
+ const updatePreviewQuery = useQuery({
+ queryKey: computed(() =>
+ instanceKeys.sharedUpdatePreview(instance.value?.id ?? '', auth.user.value?.id),
+ ),
+ queryFn: () => install_get_shared_instance_update_preview(instance.value!.id),
+ enabled: computed(
+ () =>
+ !!instance.value?.id &&
+ instance.value.install_stage === 'installed' &&
+ !!instance.value.shared_instance &&
+ !actionsLocked.value &&
+ !offline.value &&
+ (auth.isReady?.value ?? true) &&
+ !!auth.session_token.value &&
+ !!auth.user.value?.id,
+ ),
+ retry: false,
+ staleTime: 30_000,
+ refetchOnWindowFocus: false,
+ })
+
+ watch(updatePreviewQuery.data, (preview) => {
+ if (preview !== undefined) forcedUnavailableReason.value = null
+ })
+ watch(updatePreviewQuery.error, (error) => {
+ if (!error) return
+ if (isSharedInstanceUnavailableError(error)) {
+ forcedUnavailableReason.value = getSharedInstanceUnavailableReason(error)
+ } else {
+ notifyError(error)
+ }
+ })
+
+ const unavailableReason = computed(() => forcedUnavailableReason.value)
+ const shareActionsLocked = computed(() => actionsLocked.value || unavailableReason.value !== null)
+ const updatePreview = computed(() =>
+ unavailableReason.value ? null : (updatePreviewQuery.data.value ?? null),
+ )
+ const lastUpdateCheckAt = computed(() => updatePreviewQuery.dataUpdatedAt.value || undefined)
+
+ watch(
+ () => instance.value?.id,
+ () => {
+ forcedUnavailableReason.value = null
+ },
+ )
+
+ async function refreshAvailability() {
+ forcedUnavailableReason.value = null
+ if (!instance.value?.id) return
+ await queryClient.invalidateQueries({
+ queryKey: instanceKeys.sharedUpdatePreview(instance.value.id, auth.user.value?.id),
+ })
+ }
+
+ async function refreshUpdatePreview() {
+ forcedUnavailableReason.value = null
+ if (!instance.value?.id || !auth.user.value?.id) return null
+ const result = await updatePreviewQuery.refetch({ throwOnError: true })
+ return result.data ?? null
+ }
+
+ function setUnavailable(reason: SharedInstanceUnavailableReason | null) {
+ forcedUnavailableReason.value = reason
+ }
+
+ return {
+ actionsLocked,
+ shareActionsLocked,
+ unavailableReason,
+ unavailableManager,
+ manager,
+ updatePreview,
+ lastUpdateCheckAt,
+ expectedUserId,
+ wrongAccount,
+ signedOut,
+ eligibilityQuery,
+ currentUserCanUseSharedInstances,
+ refreshAvailability,
+ refreshUpdatePreview,
+ setUnavailable,
+ }
+}
+
+export type SharedInstanceContext = ReturnType
+
+export const [injectSharedInstance, provideSharedInstance] = createContext(
+ 'InstancePage',
+ 'sharedInstance',
+)
diff --git a/apps/app-frontend/src/pages/instance/use-shared-instance-state.ts b/apps/app-frontend/src/pages/instance/use-shared-instance-state.ts
deleted file mode 100644
index 408bd3c2cc..0000000000
--- a/apps/app-frontend/src/pages/instance/use-shared-instance-state.ts
+++ /dev/null
@@ -1,228 +0,0 @@
-import { injectAuth } from '@modrinth/ui'
-import { computed, inject, type InjectionKey, provide, type Ref, ref, watch } from 'vue'
-
-import { useUserQuery } from '@/composables/users/use-user-query'
-import {
- getSharedInstanceUnavailableReason,
- install_get_shared_instance_update_preview,
- isSharedInstanceUnavailableError,
- type SharedInstanceUnavailableReason,
-} from '@/helpers/install'
-import type { GameInstance } from '@/helpers/types'
-
-export type SharedInstanceManager =
- | {
- type: 'user'
- name: string
- avatarUrl?: string
- tintBy: string
- }
- | {
- type: 'server'
- name: string
- avatarUrl?: string
- tintBy: string
- }
-
-export function useSharedInstanceState(
- instance: Ref,
- offline: Ref,
- notifyError: (error: unknown) => void,
-) {
- const auth = injectAuth()
- const updatePreview =
- ref>>(null)
- const updatePreviewLoaded = ref(false)
- const unavailableReason = ref(null)
- const availabilityCheckKey = ref(null)
- const availabilityRefresh = ref(0)
- let availabilityRequestId = 0
- let availabilityRequest: {
- key: string
- promise: Promise<{
- preview: Awaited>
- error: unknown | null
- }>
- } | null = null
-
- const expectedUserId = computed(() => instance.value?.shared_instance?.linked_user_id ?? null)
- const wrongAccount = computed(() => {
- if (auth.isReady && !auth.isReady.value) return false
- if (!expectedUserId.value) return false
- return auth.user.value?.id !== expectedUserId.value
- })
- const actionsLocked = computed(() => wrongAccount.value)
- const shareActionsLocked = computed(() => actionsLocked.value || unavailableReason.value !== null)
- const signedOut = computed(() => !auth.session_token.value)
- const managerUserId = computed(() => {
- const attachment = instance.value?.shared_instance
- if (!attachment) return null
- if (attachment.role === 'owner') {
- return actionsLocked.value ? (attachment.linked_user_id ?? null) : null
- }
- return attachment.manager_id ?? null
- })
- const managerUserQuery = useUserQuery(managerUserId)
- const manager = computed(() => {
- const attachment = instance.value?.shared_instance
- if (!attachment) return null
-
- if (attachment.server_manager_name) {
- return {
- type: 'server',
- name: attachment.server_manager_name,
- avatarUrl: attachment.server_manager_icon_url ?? undefined,
- tintBy: attachment.server_manager_name,
- }
- }
-
- const user = managerUserQuery.data.value
- if (!user) return null
- return {
- type: 'user',
- name: user.username,
- avatarUrl: user.avatar_url ?? undefined,
- tintBy: user.id,
- }
- })
- const unavailableManager = computed(() => manager.value?.name ?? null)
-
- function reset() {
- availabilityRequestId++
- availabilityRequest = null
- availabilityCheckKey.value = null
- updatePreview.value = null
- updatePreviewLoaded.value = false
- unavailableReason.value = null
- }
-
- function refreshAvailability() {
- availabilityCheckKey.value = null
- updatePreviewLoaded.value = false
- availabilityRefresh.value++
- }
-
- function setUnavailable(reason: SharedInstanceUnavailableReason | null) {
- availabilityRequestId++
- availabilityRequest = null
- availabilityCheckKey.value = null
- updatePreview.value = null
- updatePreviewLoaded.value = false
- unavailableReason.value = reason
- }
-
- async function checkAvailability(instanceId: string, key: string, throwError = false) {
- const requestId = ++availabilityRequestId
- let request = availabilityRequest
- if (!request || request.key !== key) {
- const promise = install_get_shared_instance_update_preview(instanceId).then(
- (preview) => ({ preview, error: null }),
- (error: unknown) => ({ preview: null, error }),
- )
- request = { key, promise }
- availabilityRequest = request
- void promise.finally(() => {
- if (availabilityRequest?.promise === promise) availabilityRequest = null
- })
- }
-
- const result = await request.promise
- if (!isCurrentRequest(requestId, instanceId, key)) return null
-
- if (result.error !== null) {
- updatePreviewLoaded.value = false
- if (isSharedInstanceUnavailableError(result.error)) {
- updatePreview.value = null
- unavailableReason.value = getSharedInstanceUnavailableReason(result.error)
- } else if (!throwError) {
- notifyError(result.error)
- }
-
- if (throwError) throw result.error
- return null
- }
-
- updatePreview.value = result.preview
- updatePreviewLoaded.value = true
- unavailableReason.value = null
- return result.preview
- }
-
- async function refreshUpdatePreview() {
- const instanceId = instance.value?.id
- const userId = auth.user.value?.id
- if (!instanceId || !userId) return null
-
- const key = `${instanceId}:${userId}`
- availabilityCheckKey.value = key
- return await checkAvailability(instanceId, key, true)
- }
-
- function isCurrentRequest(requestId: number, instanceId: string, key: string) {
- return (
- requestId === availabilityRequestId &&
- instance.value?.id === instanceId &&
- availabilityCheckKey.value === key
- )
- }
-
- watch(
- () => ({
- refresh: availabilityRefresh.value,
- instanceId: instance.value?.id,
- role: instance.value?.shared_instance?.role,
- locked: actionsLocked.value,
- offline: offline.value,
- signedIn: !!auth.session_token.value,
- userId: auth.user.value?.id ?? null,
- authReady: auth.isReady?.value ?? true,
- }),
- async ({ instanceId, role, locked, offline, signedIn, userId, authReady }) => {
- if (!instanceId || !role || locked || offline || !authReady || !signedIn || !userId) {
- availabilityRequestId++
- availabilityRequest = null
- availabilityCheckKey.value = null
- updatePreview.value = null
- updatePreviewLoaded.value = false
- if (instanceId && role) unavailableReason.value = null
- return
- }
-
- const key = `${instanceId}:${userId}`
- if (availabilityCheckKey.value === key) return
- availabilityCheckKey.value = key
- await checkAvailability(instanceId, key)
- },
- { immediate: true },
- )
-
- return {
- actionsLocked,
- shareActionsLocked,
- unavailableReason,
- unavailableManager,
- manager,
- updatePreview,
- expectedUserId,
- wrongAccount,
- signedOut,
- reset,
- refreshAvailability,
- refreshUpdatePreview,
- setUnavailable,
- }
-}
-
-export type SharedInstanceState = ReturnType
-
-const sharedInstanceStateKey: InjectionKey = Symbol('shared-instance-state')
-
-export function provideSharedInstanceState(state: SharedInstanceState) {
- provide(sharedInstanceStateKey, state)
-}
-
-export function injectSharedInstanceState() {
- const state = inject(sharedInstanceStateKey)
- if (!state) throw new Error('Shared instance state has not been provided.')
- return state
-}
diff --git a/apps/app-frontend/src/pages/instance/Worlds.vue b/apps/app-frontend/src/pages/instance/worlds/index.vue
similarity index 86%
rename from apps/app-frontend/src/pages/instance/Worlds.vue
rename to apps/app-frontend/src/pages/instance/worlds/index.vue
index 4a5bd6192d..3539b608ca 100644
--- a/apps/app-frontend/src/pages/instance/Worlds.vue
+++ b/apps/app-frontend/src/pages/instance/worlds/index.vue
@@ -35,23 +35,14 @@
"
/>
-
-
-
- {{ formatMessage(messages.addServer) }}
-
-
-
-
-
- {{ formatMessage(messages.browseServers) }}
-
-
+
+
+ {{ formatMessage(messages.addServer) }}
+
+
+
+ {{ formatMessage(messages.browseServers) }}
+
@@ -72,16 +63,17 @@
{{ option.label }}
-
-
-
- {{
- formatMessage(
- refreshingAll ? messages.refreshingButton : commonMessages.refreshButton,
- )
- }}
-
-
+
+
+ {{
+ formatMessage(refreshingAll ? messages.refreshingButton : commonMessages.refreshButton)
+ }}
+
joinWorld(world)"
- @stop="() => emit('stop')"
+ @stop="() => instancePage.stop('InstanceWorlds')"
@refresh="() => refreshServer((world as ServerWorld).address)"
@edit="
() =>
@@ -127,31 +119,22 @@
:description="formatMessage(messages.noWorldsDescription)"
>
-
-
-
- {{ formatMessage(messages.addServer) }}
-
-
-
-
-
- {{ formatMessage(messages.browseServers) }}
-
-
+
+
+ {{ formatMessage(messages.addServer) }}
+
+
+
+ {{ formatMessage(messages.browseServers) }}
+
diff --git a/apps/app-frontend/src/pages/library/Index.vue b/apps/app-frontend/src/pages/library/Index.vue
index a8510edcd4..87a15405de 100644
--- a/apps/app-frontend/src/pages/library/Index.vue
+++ b/apps/app-frontend/src/pages/library/Index.vue
@@ -1,11 +1,11 @@
@@ -53,12 +50,10 @@ onUnmounted(() => {
{ label: 'Saved', href: `/library/saved`, shown: false },
]"
/>
-
-
-
- New instance
-
-
+
+
+ New instance
+
@@ -68,12 +63,10 @@ onUnmounted(() => {
No instances found
-
-
-
- Create new instance
-
-
+
+
+ Create new instance
+
diff --git a/apps/app-frontend/src/pages/project/Gallery.vue b/apps/app-frontend/src/pages/project/Gallery.vue
index 05a771f927..454d20cfb4 100644
--- a/apps/app-frontend/src/pages/project/Gallery.vue
+++ b/apps/app-frontend/src/pages/project/Gallery.vue
@@ -39,40 +39,40 @@
@@ -90,10 +90,10 @@ import {
RightArrowIcon,
XIcon,
} from '@modrinth/assets'
-import { ButtonStyled, Card, useFormatDateTime } from '@modrinth/ui'
+import { ButtonLink, Card, IconButton, useFormatDateTime } from '@modrinth/ui'
import { computed, onMounted, onUnmounted, ref } from 'vue'
-import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
+import { release_ads_window_hold, take_ads_window_hold } from '@/helpers/ads.js'
import { trackEvent } from '@/helpers/analytics'
const MC_SERVER_BANNER_NAME = '__mc_server_banner__'
@@ -118,10 +118,14 @@ const filteredGallery = computed(
const expandedGalleryItem = ref(null)
const expandedGalleryIndex = ref(0)
const zoomedIn = ref(false)
+let adsWindowHold = false
const hideImage = () => {
expandedGalleryItem.value = null
- show_ads_window()
+ if (adsWindowHold) {
+ adsWindowHold = false
+ release_ads_window_hold()
+ }
}
const nextImage = () => {
@@ -149,7 +153,10 @@ const previousImage = () => {
}
const expandImage = (item, index) => {
- hide_ads_window()
+ if (!adsWindowHold) {
+ adsWindowHold = true
+ take_ads_window_hold()
+ }
expandedGalleryItem.value = item
expandedGalleryIndex.value = index
zoomedIn.value = false
@@ -181,6 +188,10 @@ onMounted(() => {
onUnmounted(() => {
document.removeEventListener('keydown', keyListener)
+ if (adsWindowHold) {
+ adsWindowHold = false
+ release_ads_window_hold()
+ }
})
diff --git a/apps/app-frontend/src/pages/project/Index.vue b/apps/app-frontend/src/pages/project/Index.vue
index 2d3ee48c3a..92b3610164 100644
--- a/apps/app-frontend/src/pages/project/Index.vue
+++ b/apps/app-frontend/src/pages/project/Index.vue
@@ -70,87 +70,104 @@
>
-
-
-
- {{ formatMessage(commonMessages.stopButton) }}
-
-
-
-
-
- {{
- serverInstallLoading
- ? formatMessage(commonMessages.installingLabel)
- : formatMessage(commonMessages.playButton)
- }}
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ {{ formatMessage(commonMessages.stopButton) }}
+
+
+
+ {{
+ serverInstallLoading
+ ? formatMessage(commonMessages.installingLabel)
+ : formatMessage(commonMessages.playButton)
+ }}
+
+
+
+
+
+
+
-
-
-
- {{ formatMessage(commonMessages.installedLabel) }}
-
-
-
-
-
- {{ formatMessage(messages.switchVersion) }}
-
-
-
-
-
- {{
- installButtonInstalled
- ? formatMessage(commonMessages.installedLabel)
- : installButtonValidating
- ? formatMessage(commonMessages.validatingLabel)
- : installButtonLoading
- ? formatMessage(commonMessages.installingLabel)
- : serverProjectSelected
- ? formatMessage(commonMessages.selectedLabel)
- : formatMessage(commonMessages.installButton)
- }}
-
-
-
-
-
-
-
+
+
+ {{ formatMessage(commonMessages.installedLabel) }}
+
+
+
+ {{ formatMessage(messages.switchVersion) }}
+
+
+
+ {{
+ installButtonInstalled
+ ? formatMessage(commonMessages.installedLabel)
+ : installButtonValidating
+ ? formatMessage(commonMessages.validatingLabel)
+ : installButtonLoading
+ ? formatMessage(commonMessages.installingLabel)
+ : serverProjectSelected
+ ? formatMessage(commonMessages.selectedLabel)
+ : formatMessage(commonMessages.installButton)
+ }}
+
+
+
+
@@ -241,11 +258,12 @@ import {
} from '@modrinth/assets'
import {
BrowseInstallHeader,
- ButtonStyled,
+ Button,
commonMessages,
CreationFlowModal,
defineMessages,
getTargetInstallPreferences,
+ IconButton,
injectNotificationManager,
NavTabs,
ProjectBackgroundGradient,
@@ -266,7 +284,7 @@ import { convertFileSrc } from '@tauri-apps/api/core'
import { openUrl } from '@tauri-apps/plugin-opener'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
-import { computed, onUnmounted, ref, shallowRef, watch } from 'vue'
+import { computed, ref, shallowRef, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { SwapIcon } from '@/assets/icons/index.js'
@@ -276,6 +294,7 @@ import {
fetchCachedServerStatus,
getFreshCachedServerStatus,
} from '@/composables/instances/use-server-status-query'
+import { useAppEvent } from '@/composables/use-app-event'
import {
get_organization,
get_project,
@@ -284,7 +303,6 @@ import {
get_version,
get_version_many,
} from '@/helpers/cache.js'
-import { process_listener } from '@/helpers/events'
import {
get as getInstance,
get_projects as getInstanceProjects,
@@ -571,13 +589,13 @@ const serverProjectHeaderMoreActions = computed(() => [
action: openProjectInBrowser,
},
{
- divider: true,
+ type: 'divider',
},
{
id: 'report',
label: formatMessage(commonMessages.reportButton),
icon: ReportIcon,
- color: 'red',
+ tone: 'red',
action: reportProject,
},
])
@@ -605,13 +623,13 @@ const projectHeaderMoreActions = computed(() => [
action: openProjectInBrowser,
},
{
- divider: true,
+ type: 'divider',
},
{
id: 'report',
label: formatMessage(commonMessages.reportButton),
icon: ReportIcon,
- color: 'red',
+ tone: 'red',
action: reportProject,
},
])
@@ -796,8 +814,7 @@ function fetchDeferredServerData(project) {
await fetchProjectData()
-let unlistenProcesses
-process_listener((e) => {
+useAppEvent('process', (e) => {
if (
e.event === 'finished' &&
serverInstancePath.value &&
@@ -805,12 +822,6 @@ process_listener((e) => {
) {
serverPlaying.value = false
}
-}).then((unlisten) => {
- unlistenProcesses = unlisten
-})
-
-onUnmounted(() => {
- unlistenProcesses?.()
})
watch(
diff --git a/apps/app-frontend/src/pages/project/Version.vue b/apps/app-frontend/src/pages/project/Version.vue
index 85a368440b..83390cabb4 100644
--- a/apps/app-frontend/src/pages/project/Version.vue
+++ b/apps/app-frontend/src/pages/project/Version.vue
@@ -14,63 +14,68 @@
:members="members"
:dependency-link-creator="createDependencyLink"
>
-
-
- version && install(version.id)"
- >
-
-
-
- {{
- installing
- ? formatMessage(messages.installing)
- : installed && installedVersion === version.id
- ? formatMessage(commonMessages.installedLabel)
- : installed
- ? formatMessage(commonMessages.switchToVersionButton)
- : formatMessage(commonMessages.installButton)
- }}
-
-
-
-
-
-
-
- {{ formatMessage(commonMessages.openInBrowserButton) }}
-
-
- {{ formatMessage(commonMessages.reportButton) }}
-
-
-
+
+ version && install(version.id)"
+ >
+
+
+
+ {{
+ installing
+ ? formatMessage(messages.installing)
+ : installed && installedVersion === version.id
+ ? formatMessage(commonMessages.installedLabel)
+ : installed
+ ? formatMessage(commonMessages.switchToVersionButton)
+ : formatMessage(commonMessages.installButton)
+ }}
+
+
+
+
+
+ {{ formatMessage(commonMessages.openInBrowserButton) }}
+
+
+ {{ formatMessage(commonMessages.reportButton) }}
+
+
-
-
-
- {{ formatMessage(messages.downloadInBrowser) }}
-
-
+
+
+ {{ formatMessage(messages.downloadInBrowser) }}
+
@@ -87,12 +92,12 @@ import {
ReportIcon,
VersionIcon,
} from '@modrinth/assets'
+import { Button, ButtonLink, TeleportOverflowMenu } from '@modrinth/ui'
import {
- ButtonStyled,
commonMessages,
defineMessages,
type DependencyContext,
- OverflowMenu,
+ useFormatBytes,
useVIntl,
VersionPage,
} from '@modrinth/ui'
@@ -104,6 +109,7 @@ import { get_project_many, get_version_many } from '@/helpers/cache.js'
import { useBreadcrumb } from '@/providers/breadcrumbs'
const { formatMessage } = useVIntl()
+const formatBytes = useFormatBytes()
const messages = defineMessages({
allVersions: {
diff --git a/apps/app-frontend/src/pages/project/Versions.vue b/apps/app-frontend/src/pages/project/Versions.vue
index 7d7438cf12..d723a634b8 100644
--- a/apps/app-frontend/src/pages/project/Versions.vue
+++ b/apps/app-frontend/src/pages/project/Versions.vue
@@ -9,76 +9,53 @@
:version-link="(version) => buildProjectHref(`/project/${project.id}/version/${version.id}`)"
>
- install(version.id)"
>
- install(version.id)"
- >
-
-
-
-
-
-
-
-
-
-
- Add to another instance
-
-
- {{ formatMessage(commonMessages.openInBrowserButton) }}
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/assets/styles/components.scss b/apps/frontend/src/assets/styles/components.scss
index 4458f7c307..ad5da17d1e 100644
--- a/apps/frontend/src/assets/styles/components.scss
+++ b/apps/frontend/src/assets/styles/components.scss
@@ -93,7 +93,7 @@
}
}
- :where(button, .button, .iconified-button) {
+ :where(button:not([data-button])) {
width: fit-content;
}
@@ -118,7 +118,6 @@
gap: var(--spacing-card-sm);
margin-bottom: calc(var(--spacing-card-sm) + var(--spacing-card-md));
- .iconified-button,
.input-group {
flex-shrink: 0;
}
@@ -250,185 +249,6 @@
}
}
-.button-base {
- @extend .button-animation;
- font-weight: 500;
- outline: 2px solid transparent;
-
- &:focus-visible:not(&:disabled),
- &:hover:not(&:disabled) {
- cursor: pointer;
- filter: brightness(0.85);
- }
-
- &:active:not(&:disabled) {
- filter: brightness(0.8);
- }
-
- &:disabled,
- &[disabled='true'] {
- cursor: not-allowed;
- filter: grayscale(50%);
- opacity: 0.5;
- box-shadow: none;
- }
-}
-
-:not(tr).button-transparent {
- @extend .button-base;
- background-color: transparent;
- border-radius: var(--size-rounded-sm);
-
- &:focus-visible:not(&:disabled),
- &:hover:not(&:disabled),
- &:active:not(&:disabled) {
- background-color: var(--color-raised-bg);
- }
-
- &.brand-button {
- color: var(--color-brand);
- }
-
- &.danger-button {
- color: var(--color-red);
- }
-}
-
-tr.button-transparent {
- @extend .button-animation;
- background-color: transparent;
- border-radius: var(--size-rounded-sm);
-
- &:focus-visible:not(&:disabled) > *,
- &:hover:not(&:disabled) > * {
- cursor: pointer;
- filter: brightness(0.85);
- background-color: var(--color-raised-bg);
- }
-
- &:active:not(&:disabled) > * {
- filter: brightness(0.8);
- background-color: var(--color-raised-bg);
- }
-
- &:disabled > *,
- &[disabled='true'] > * {
- cursor: not-allowed;
- filter: grayscale(50%);
- opacity: 0.5;
- box-shadow: none;
- }
-}
-
-.button-color-base {
- box-sizing: border-box;
- --text-color: var(--color-button-text);
- --background-color: var(--color-button-bg);
-
- color: var(--text-color);
- background-color: var(--background-color);
- box-shadow:
- var(--shadow-inset-sm),
- 0 0 0 0 transparent;
- border-radius: var(--size-rounded-sm);
-}
-
-.iconified-button {
- @extend .button-base;
- @extend .button-color-base;
-
- display: flex;
- padding: var(--spacing-card-sm) var(--spacing-card-bg);
- margin: 0;
- font-size: var(--font-size-nm);
- align-items: center;
- cursor: pointer;
- width: fit-content;
- height: fit-content;
- transition:
- opacity 0.5s ease-in-out,
- filter 0.2s ease-in-out,
- scale 0.05s ease-in-out,
- outline 0.2s ease-in-out;
-
- text-decoration: none;
-
- svg {
- width: 1.1rem;
- height: 1.1rem;
- margin-right: 0.5rem;
- }
-
- &.icon-only {
- padding: 0 0.5rem;
-
- svg {
- margin-right: 0;
- }
- }
-
- &.transparent {
- background: none;
- box-shadow: none;
- }
-}
-
-.square-button {
- @extend .button-base;
-
- --text-color: var(--color-button-text);
- --background-color: var(--color-button-bg);
-
- display: flex;
- align-items: center;
- justify-content: center;
- height: 2.25rem;
- width: 2.25rem;
- border-radius: var(--size-rounded-sm);
- color: var(--text-color);
- background-color: var(--background-color);
- box-shadow:
- var(--shadow-inset-sm),
- 0 0 0 0 transparent;
-
- svg {
- min-width: 1.25rem;
- max-width: 1.25rem;
- min-height: 1.25rem;
- max-height: 1.25rem;
- }
-
- flex-shrink: 0;
-}
-
-.raised-button {
- --background-color: var(--color-raised-bg);
- box-shadow: var(--shadow-inset-sm), var(--shadow-raised);
-}
-
-.danger-button {
- --background-color: var(--color-red);
- --text-color: var(--color-brand-inverted);
-}
-
-.moderation-button {
- --background-color: var(--color-orange);
- --text-color: var(--color-brand-inverted);
-}
-
-.brand-button {
- --background-color: var(--color-brand);
- --text-color: var(--color-brand-inverted);
-}
-
-.button-group {
- display: flex;
- grid-gap: var(--spacing-card-sm);
- flex-wrap: wrap;
- margin-top: var(--spacing-card-md);
- justify-content: right;
-}
-
.error {
display: flex;
flex-direction: column;
@@ -501,7 +321,6 @@ textarea.known-error {
}
@media (prefers-reduced-motion) {
- .button-animation,
button {
transform: none !important;
}
diff --git a/apps/frontend/src/assets/styles/global.scss b/apps/frontend/src/assets/styles/global.scss
index 8ad63c2da1..42e3059ce7 100644
--- a/apps/frontend/src/assets/styles/global.scss
+++ b/apps/frontend/src/assets/styles/global.scss
@@ -40,6 +40,8 @@ html {
interpolate-size: allow-keywords;
scrollbar-gutter: stable;
+
+ --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
}
.light-mode {
@@ -475,18 +477,6 @@ input {
outline: 2px solid transparent !important;
}
-.button-animation {
- transition:
- opacity 0.5s ease-in-out,
- filter 0.2s ease-in-out,
- transform 0.05s ease-in-out,
- outline-width 0.2s ease-in-out;
-}
-
-.button-transparent {
- box-shadow: none;
-}
-
.qc-cmp2-close-tooltip {
background-color: transparent;
color: hsl(145, 78%, 28%);
diff --git a/apps/frontend/src/assets/styles/layout.scss b/apps/frontend/src/assets/styles/layout.scss
index 83debb8ff8..d633ed8df9 100644
--- a/apps/frontend/src/assets/styles/layout.scss
+++ b/apps/frontend/src/assets/styles/layout.scss
@@ -111,6 +111,18 @@
max-width: 100%;
}
}
+
+ &.align-x {
+ margin: 0 auto;
+ }
+
+ &.align-l {
+ margin: 0 0 0 auto;
+ }
+
+ &.align-r {
+ margin: 0 auto 0 0;
+ }
}
.normal-page__sidebar {
@@ -140,6 +152,18 @@
'sidebar'
/ 100%;
+ &.align-x {
+ margin: 0 auto;
+ }
+
+ &.align-l {
+ margin: 0 0 0 auto;
+ }
+
+ &.align-r {
+ margin: 0 auto 0 0;
+ }
+
@media screen and (min-width: 1024px) {
&.sidebar {
grid-template:
diff --git a/apps/frontend/src/components/analytics-dashboard/analytics-chart/analytics-chart-header/AnalyticsChartRenderLimitModal.vue b/apps/frontend/src/components/analytics-dashboard/analytics-chart/analytics-chart-header/AnalyticsChartRenderLimitModal.vue
index 9da495ce24..06147218c1 100644
--- a/apps/frontend/src/components/analytics-dashboard/analytics-chart/analytics-chart-header/AnalyticsChartRenderLimitModal.vue
+++ b/apps/frontend/src/components/analytics-dashboard/analytics-chart/analytics-chart-header/AnalyticsChartRenderLimitModal.vue
@@ -12,23 +12,19 @@
-
-
- {{ formatMessage(analyticsChartMessages.cancelButton) }}
-
-
-
-
- {{ formatMessage(analyticsChartMessages.showAll) }}
-
-
+
+ {{ formatMessage(analyticsChartMessages.cancelButton) }}
+
+
+ {{ formatMessage(analyticsChartMessages.showAll) }}
+
diff --git a/apps/frontend/src/components/ui/AuthorizationCard.vue b/apps/frontend/src/components/ui/AuthorizationCard.vue
index 58eee3d8cb..37507e272b 100644
--- a/apps/frontend/src/components/ui/AuthorizationCard.vue
+++ b/apps/frontend/src/components/ui/AuthorizationCard.vue
@@ -40,12 +40,10 @@
-
-
-
- {{ formatMessage(messages.revokeAction) }}
-
-
+
+
+ {{ formatMessage(messages.revokeAction) }}
+
@@ -82,7 +80,7 @@ import type { Labrinth } from '@modrinth/api-client'
import { BadgeCheckIcon, CheckIcon, IssuesIcon, XCircleIcon } from '@modrinth/assets'
import {
Avatar,
- ButtonStyled,
+ Button,
commonMessages,
defineMessages,
IntlFormatted,
diff --git a/apps/frontend/src/components/ui/Chips.vue b/apps/frontend/src/components/ui/Chips.vue
deleted file mode 100644
index 17905aa13c..0000000000
--- a/apps/frontend/src/components/ui/Chips.vue
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
- {{ formatLabel(item) }}
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/components/ui/ConfirmTransferOrgModal.vue b/apps/frontend/src/components/ui/ConfirmTransferOrgModal.vue
index e4f62b43f0..606be33b05 100644
--- a/apps/frontend/src/components/ui/ConfirmTransferOrgModal.vue
+++ b/apps/frontend/src/components/ui/ConfirmTransferOrgModal.vue
@@ -57,18 +57,14 @@
-
-
-
- Cancel
-
-
-
-
-
- Transfer ownership
-
-
+
+
+ Cancel
+
+
+
+ Transfer ownership
+
@@ -76,7 +72,7 @@
-
-
-
- {{ formatMessage(messages.subscribe) }}
-
- {{ formatMessage(messages.subscribed) }}
-
-
+
+
+ {{ formatMessage(messages.subscribe) }}
+
+ {{ formatMessage(messages.subscribed) }}
+
diff --git a/apps/frontend/src/components/ui/NotificationItem.vue b/apps/frontend/src/components/ui/NotificationItem.vue
index 1bbac8bf38..4f3cfa001b 100644
--- a/apps/frontend/src/components/ui/NotificationItem.vue
+++ b/apps/frontend/src/components/ui/NotificationItem.vue
@@ -46,18 +46,18 @@
class="flex flex-wrap items-center gap-3"
:class="{ 'gap-2': compact }"
>
-
-
-
- Accept
-
-
-
-
-
- Decline
-
-
+
+
+ Accept
+
+
+
+ Decline
+
-
- {
+ acceptTeamInvite(notification.body.team_id)
+ read()
+ }
+ "
+ >
+
+
+ {
+ removeSelfFromTeam(notification.body.team_id)
+ read()
+ }
+ "
+ >
+
+
+
+
+
+
+
+
+
+
+ {
acceptTeamInvite(notification.body.team_id)
@@ -287,11 +331,11 @@
"
>
-
-
-
-
+ {
removeSelfFromTeam(notification.body.team_id)
@@ -300,75 +344,40 @@
"
>
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- acceptTeamInvite(notification.body.team_id)
- read()
- }
- "
- >
-
- Accept
-
-
-
- {
- removeSelfFromTeam(notification.body.team_id)
- read()
- }
- "
- >
-
- Decline
-
-
+ Decline
+
-
-
-
- Mark as read
-
-
+
+
+ Mark as read
+
-
-
-
- Open link
-
-
-
-
-
-
- {{ action.title }}
-
-
-
-
-
- Mark as read
-
-
+
+
+ Open link
+
+
+
+
+ {{ action.title }}
+
+
+
+ Mark as read
+
@@ -390,10 +399,12 @@ import {
} from '@modrinth/assets'
import {
Avatar,
- ButtonStyled,
+ Button,
+ ButtonLink,
Categories,
CopyCode,
DoubleIcon,
+ IconButton,
injectModrinthClient,
injectNotificationManager,
ProjectStatusBadge,
diff --git a/apps/frontend/src/components/ui/OptionGroup.vue b/apps/frontend/src/components/ui/OptionGroup.vue
deleted file mode 100644
index 36313921ef..0000000000
--- a/apps/frontend/src/components/ui/OptionGroup.vue
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/components/ui/OrganizationPageHeader.vue b/apps/frontend/src/components/ui/OrganizationPageHeader.vue
index c5f74542df..6063423a50 100644
--- a/apps/frontend/src/components/ui/OrganizationPageHeader.vue
+++ b/apps/frontend/src/components/ui/OrganizationPageHeader.vue
@@ -38,21 +38,19 @@
-
-
-
- {{ formatMessage(messages.manage) }}
-
-
-
-
-
-
-
+
+
+ {{ formatMessage(messages.manage) }}
+
+
+
+
@@ -68,18 +66,17 @@ import {
SettingsIcon,
UsersIcon,
} from '@modrinth/assets'
+import { ButtonLink, TeleportOverflowMenu } from '@modrinth/ui'
import {
Avatar,
- ButtonStyled,
commonMessages,
defineMessages,
+ type OverflowMenuOption,
PageHeader,
PageHeaderActions,
PageHeaderBadgeItem,
PageHeaderMetadata,
PageHeaderMetadataNumberItem,
- TeleportOverflowMenu,
- type TeleportOverflowMenuItem,
useFormatNumber,
useVIntl,
} from '@modrinth/ui'
@@ -135,7 +132,7 @@ const emit = defineEmits<{
const { formatMessage } = useVIntl()
const formatNumber = useFormatNumber()
-const moreActions = computed
(() => [
+const moreActions = computed(() => [
{
id: 'manage-projects',
label: formatMessage(messages.manageProjects),
@@ -143,10 +140,7 @@ const moreActions = computed(() => [
action: () => emit('manageProjects'),
shown: props.canManage,
},
- {
- divider: true,
- shown: props.canManage,
- },
+ { type: 'divider', shown: props.canManage },
{
id: 'copy-id',
label: formatMessage(commonMessages.copyIdButton),
diff --git a/apps/frontend/src/components/ui/OrganizationProjectTransferModal.vue b/apps/frontend/src/components/ui/OrganizationProjectTransferModal.vue
index 6f66486fd0..46524dbff5 100644
--- a/apps/frontend/src/components/ui/OrganizationProjectTransferModal.vue
+++ b/apps/frontend/src/components/ui/OrganizationProjectTransferModal.vue
@@ -65,38 +65,37 @@
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
-
- {{
- formatMessage(messages.transferSelectedProjects, {
- count: selectedProjects.length,
- })
- }}
-
-
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+ {{
+ formatMessage(messages.transferSelectedProjects, {
+ count: selectedProjects.length,
+ })
+ }}
+
-
-
-
- {{ formatMessage(messages.transferProjectsTitle) }}
-
-
+
+
+ {{ formatMessage(messages.transferProjectsTitle) }}
+
+
+
+
+
+
+
Completed ({{ completedEntries.length }})
+
+
+ {{
+ entry.title
+ }}
+
+
+
+
+
+
Skipped ({{ skippedEntries.length }})
+
+
+ {{
+ entry.title
+ }}
+
+
+
+
+
+ No projects were reviewed during this queue.
+
+
+
+
+
+ Review skipped ({{ skippedEntries.length }})
+
+
+
+ Close
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/moderation/SharedInstanceReportContext.vue b/apps/frontend/src/components/ui/moderation/SharedInstanceReportContext.vue
index 3f3b0d9ad5..e3839dd4a6 100644
--- a/apps/frontend/src/components/ui/moderation/SharedInstanceReportContext.vue
+++ b/apps/frontend/src/components/ui/moderation/SharedInstanceReportContext.vue
@@ -11,13 +11,13 @@ import {
UsersIcon,
VersionIcon,
} from '@modrinth/assets'
+import { Button, IconButton } from '@modrinth/ui'
import {
Avatar,
- ButtonStyled,
ConfirmLeaveModal,
type ContentItem,
injectModrinthClient,
- ModpackContentModal,
+ ManagedContentModal,
Table,
type TableColumn,
useFormatDateTime,
@@ -76,7 +76,7 @@ const emit = defineEmits<{
contentError: [error: unknown]
}>()
-const contentModal = ref | null>(null)
+const contentModal = ref | null>(null)
const banModal = ref | null>(null)
const client = injectModrinthClient()
const contentByVersion = new Map()
@@ -322,12 +322,14 @@ function formattedLoader(version: SharedInstanceReportVersion) {
-
-
-
- View content
-
-
+
+
+ View content
+
@@ -363,15 +365,14 @@ function formattedLoader(version: SharedInstanceReportVersion) {
{{ instance.member_count === 1 ? 'member' : 'members' }}
-
-
-
-
-
+
+
+
@@ -392,20 +393,24 @@ function formattedLoader(version: SharedInstanceReportVersion) {
launching them.
-
-
-
- {{ banButtonLabel }}
-
-
+
+
+ {{ banButtonLabel }}
+
-
+
+
+
+
+
+ {{ formatMessage(commonMessages.reportButton) }}
+
+
+
+ {{ formatMessage(commonMessages.reportButton) }}
+
+
+
+ {{ formatMessage(commonMessages.copyIdButton) }}
+
+
+
+ {{ formatMessage(commonMessages.copyPermalinkButton) }}
+
+
-
-
-
- {{ formatMessage(commonMessages.downloadButton) }}
-
-
-
-
-
-
-
- {{ formatMessage(messages.copySha1) }}
-
-
-
- {{ formatMessage(messages.copySha512) }}
-
-
-
+
+
+ {{ formatMessage(commonMessages.downloadButton) }}
+
+
+
+
+
+ {{ formatMessage(messages.copySha1) }}
+
+
+
+ {{ formatMessage(messages.copySha512) }}
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
getSignInRouteObj(route))
const versionRouteParam = computed(() => route.params.version as string)
diff --git a/apps/frontend/src/pages/[type]/[project]/versions.vue b/apps/frontend/src/pages/[type]/[project]/versions.vue
index 7770d541b6..adefb0711f 100644
--- a/apps/frontend/src/pages/[type]/[project]/versions.vue
+++ b/apps/frontend/src/pages/[type]/[project]/versions.vue
@@ -41,192 +41,217 @@
:open-modal="currentMember ? () => handleOpenCreateVersionModal() : undefined"
>
-
-
+
+
+
+
+
+
+
+
+
+
+ Edit files
+
+
+
+ Edit details
+
+
+
+ Edit metadata
+
+
+
+
+
-
-
-
-
-
-
-
- Edit files
-
-
-
- Edit details
-
-
-
- Edit metadata
-
-
-
-
-
-
-
-
- Download
-
-
-
- Open in new tab
-
-
-
- Copy link
-
-
-
- Share
-
-
-
- Report
-
-
-
- Edit files
-
-
-
- Edit details
-
-
-
- Edit metadata
-
-
-
- Delete
-
-
-
- Copy ID
-
-
-
- Copy Maven coordinates
-
-
-
+ Download
+
+
+
+ Open in new tab
+
+
+
+ Copy link
+
+
+
+ Share
+
+
+
+ Report
+
+
+
+ Edit files
+
+
+
+ Edit details
+
+
+
+ Edit metadata
+
+
+
+ Delete
+
+
+
+ Copy ID
+
+
+
+ Copy Maven coordinates
+
+
@@ -258,15 +283,17 @@ import {
SpinnerIcon,
TrashIcon,
} from '@modrinth/assets'
+import { moderationSettings } from '@modrinth/moderation'
import {
- ButtonStyled,
+ ButtonLink,
ConfirmModal,
injectModrinthClient,
injectNotificationManager,
injectProjectPageContext,
- OverflowMenu,
ProjectPageVersions,
+ TeleportOverflowMenu,
} from '@modrinth/ui'
+import { isStaff } from '@modrinth/utils'
import { onMounted, useTemplateRef, watch } from 'vue'
import CreateProjectVersionModal from '~/components/ui/create-project-version/CreateProjectVersionModal.vue'
@@ -279,6 +306,7 @@ const { createProjectDownloadUrl, updateVersionsFilterContext } = useCdnDownload
const tags = useGeneratedState()
const flags = useFeatureFlags()
+const modSettings = useModerationSettings()
const auth = await useAuth()
const client = injectModrinthClient()
diff --git a/apps/frontend/src/pages/admin/affiliates.vue b/apps/frontend/src/pages/admin/affiliates.vue
index 92925757ce..c67abeb81c 100644
--- a/apps/frontend/src/pages/admin/affiliates.vue
+++ b/apps/frontend/src/pages/admin/affiliates.vue
@@ -27,12 +27,10 @@
placeholder="Search affiliates..."
clearable
/>
-
-
-
- Create affiliate code
-
-
+
+
+ Create affiliate code
+
@@ -90,7 +88,7 @@ import {
AffiliateLinkCard,
AffiliateLinkCreateModal,
Avatar,
- ButtonStyled,
+ Button,
ConfirmModal,
injectModrinthClient,
injectNotificationManager,
diff --git a/apps/frontend/src/pages/admin/analytics/events.vue b/apps/frontend/src/pages/admin/analytics/events.vue
index a471615ce9..f3a9dddfb3 100644
--- a/apps/frontend/src/pages/admin/analytics/events.vue
+++ b/apps/frontend/src/pages/admin/analytics/events.vue
@@ -33,19 +33,20 @@
-
- Cancel
-
-
-
-
- {{ modalMode === 'create' ? 'Create event' : 'Save' }}
-
-
+ Cancel
+
+
+ {{ modalMode === 'create' ? 'Create event' : 'Save' }}
+
@@ -137,12 +139,10 @@
clearable
wrapper-class="w-full sm:w-72"
/>
-
-
-
- New event
-
-
+
+
+ New event
+
@@ -196,21 +196,23 @@
-
-
-
-
-
-
-
- Edit
-
-
-
+
+
+
+
+ Edit
+
+
@@ -239,8 +241,8 @@ import {
SpinnerIcon,
TrashIcon,
} from '@modrinth/assets'
+import { Button, ButtonLink, IconButton } from '@modrinth/ui'
import {
- ButtonStyled,
ConfirmModal,
DatePicker,
injectModrinthClient,
diff --git a/apps/frontend/src/pages/admin/billing/[user].vue b/apps/frontend/src/pages/admin/billing/[user].vue
index 936ac39ca3..e8e9d75300 100644
--- a/apps/frontend/src/pages/admin/billing/[user].vue
+++ b/apps/frontend/src/pages/admin/billing/[user].vue
@@ -43,18 +43,14 @@
-
-
-
- Refund charge
-
-
-
-
-
- Cancel
-
-
+
+
+ Refund charge
+
+
+
+ Cancel
+
@@ -82,18 +78,14 @@
-
-
-
- Modify charge
-
-
-
-
-
- Cancel
-
-
+
+
+ Modify charge
+
+
+
+ Cancel
+
@@ -117,18 +109,14 @@
-
-
-
- Apply credit
-
-
-
-
-
- Cancel
-
-
+
+
+ Apply credit
+
+
+
+ Cancel
+
@@ -141,13 +129,11 @@
-
-
-
- User profile
-
-
-
+
+
+ User profile
+
+
@@ -176,25 +162,20 @@
-
-
- Server panel
-
-
-
-
-
- Credit
-
-
+ Server panel
+
+
+
+ Credit
+
@@ -226,7 +207,8 @@ import {
} from '@modrinth/assets'
import {
Avatar,
- ButtonStyled,
+ Button,
+ ButtonLink,
CopyCode,
defineMessages,
DropdownSelect,
diff --git a/apps/frontend/src/pages/admin/docs.vue b/apps/frontend/src/pages/admin/docs.vue
index 557caf30fd..59847b213a 100644
--- a/apps/frontend/src/pages/admin/docs.vue
+++ b/apps/frontend/src/pages/admin/docs.vue
@@ -1,6 +1,6 @@
-
+
| null = null
const HOVER_DURATION_TO_PREFETCH_MS = 500
const handleProjectMouseEnter = (result: Labrinth.Search.v3.ResultSearchProject) => {
- const slug = result.slug || result.project_id
+ const projectId = result.project_id
prefetchTimeout = useTimeoutFn(
() => {
- queryClient.prefetchQuery(projectQueryOptions.v2(slug, client))
- queryClient.prefetchQuery(projectQueryOptions.v3(result.project_id, client))
- queryClient.prefetchQuery(projectQueryOptions.members(result.project_id, client))
- queryClient.prefetchQuery(projectQueryOptions.dependencies(result.project_id, client))
- queryClient.prefetchQuery(projectQueryOptions.versionsV3(result.project_id, client))
+ warmProjectCheckCaches(queryClient, result)
+ queryClient.prefetchQuery(projectQueryOptions.v2(projectId, client))
+ queryClient.prefetchQuery(projectQueryOptions.v3(projectId, client))
+ queryClient.prefetchQuery(projectQueryOptions.members(projectId, client))
+ queryClient.prefetchQuery(projectQueryOptions.dependencies(projectId, client))
+ queryClient.prefetchQuery(projectQueryOptions.versionsV3(projectId, client))
},
HOVER_DURATION_TO_PREFETCH_MS,
{ immediate: false },
@@ -83,12 +84,13 @@ const handleProjectMouseEnter = (result: Labrinth.Search.v3.ResultSearchProject)
}
const handleServerProjectMouseEnter = (result: Labrinth.Search.v3.ResultSearchProject) => {
- const slug = result.slug || result.project_id
+ const projectId = result.project_id
prefetchTimeout = useTimeoutFn(
async () => {
- queryClient.prefetchQuery(projectQueryOptions.v2(slug, client))
- queryClient.prefetchQuery(projectQueryOptions.v3(slug, client))
+ warmProjectCheckCaches(queryClient, result)
+ queryClient.prefetchQuery(projectQueryOptions.v2(projectId, client))
+ queryClient.prefetchQuery(projectQueryOptions.v3(projectId, client))
const content = result.minecraft_java_server?.content
if (content?.kind === 'modpack' && content.version_id) {
@@ -228,6 +230,19 @@ function parseSearchParams(requestParams: string): Labrinth.Search.SearchParams
}
}
+// Search returns expanded dependency data that no card renders and that isn't part of
+// ResultSearchProject. On modpacks it is ~90% of the response, and everything cached here
+// is serialized into the SSR payload, so drop it before it reaches the query cache.
+function stripUnrenderedFields(
+ hits: Labrinth.Search.v3.ResultSearchProject[],
+): Labrinth.Search.v3.ResultSearchProject[] {
+ return hits.map((hit) => {
+ const { dependencies, dependency_project_ids, compatible_dependency_project_ids, ...rendered } =
+ hit as Labrinth.Search.v3.ResultSearchProject & Record
+ return rendered as Labrinth.Search.v3.ResultSearchProject
+ })
+}
+
async function fetchSearch(requestParams: string) {
debug('search() called', {
requestParams: requestParams.substring(0, 100),
@@ -241,17 +256,19 @@ async function fetchSearch(requestParams: string) {
debug('search() response', { total_hits: raw.total_hits, hitCount: raw.hits?.length })
+ const hits = stripUnrenderedFields(raw.hits ?? [])
+
if (isServerType.value) {
return {
projectHits: [],
- serverHits: raw.hits,
+ serverHits: hits,
total_hits: raw.total_hits,
per_page: raw.hits_per_page,
}
}
return {
- projectHits: raw.hits,
+ projectHits: hits,
serverHits: [],
total_hits: raw.total_hits,
per_page: raw.hits_per_page,
@@ -401,6 +418,14 @@ const advancedFiltersCollapsed = computed({
},
})
+const dismissedPhotosensitivityFilterWarning = computed({
+ get: () => flags.value.dismissedPhotosensitivityFilterWarning,
+ set: (value) => {
+ flags.value.dismissedPhotosensitivityFilterWarning = value
+ saveFeatureFlags()
+ },
+})
+
const projectTypeId = computed(() => projectType.value?.id ?? 'mod')
debug('projectTypeId:', projectTypeId.value)
@@ -422,6 +447,15 @@ const searchState = useBrowseSearch({
})
setBrowseSearchState(searchState)
+// Warm check caches for every visible hit so clicking a result skips /project/{slug}/check
+watch(
+ [() => searchState.projectHits.value, () => searchState.serverHits.value],
+ ([projectHits, serverHits]) => {
+ warmProjectCheckCaches(queryClient, [...projectHits, ...serverHits])
+ },
+ { immediate: true },
+)
+
watch(
() =>
searchState.isServerType.value
@@ -510,6 +544,7 @@ provideBrowseManager({
serverOnlyLabel: computed(() => formatMessage(commonMessages.serverOnlyLabel)),
hiddenFilterTypes: computed(() => (showServerOnlyToggle.value ? ['environment'] : [])),
advancedFiltersCollapsed,
+ dismissedPhotosensitivityFilterWarning,
displayMode: resultsDisplayMode,
cycleDisplayMode: cycleSearchDisplayMode,
maxResultsOptions: currentMaxResultsOptions,
diff --git a/apps/frontend/src/pages/hosting/index.vue b/apps/frontend/src/pages/hosting/index.vue
index dece65edec..827298042b 100644
--- a/apps/frontend/src/pages/hosting/index.vue
+++ b/apps/frontend/src/pages/hosting/index.vue
@@ -33,7 +33,7 @@
{{ formatMessage(commonMessages.betaRelease) }}
@@ -50,21 +50,23 @@
-
-
-
- {{
- hasServers
- ? formatMessage(messages.startANewServer)
- : formatMessage(messages.startYourServer)
- }}
-
-
-
-
- {{ formatMessage(messages.manageYourServers) }}
-
-
+
+
+ {{
+ hasServers
+ ? formatMessage(messages.startANewServer)
+ : formatMessage(messages.startYourServer)
+ }}
+
+
+ {{ formatMessage(messages.manageYourServers) }}
+
@@ -108,7 +110,7 @@
{{ formatMessage(messages.whyModrinthHosting) }}
@@ -152,7 +154,7 @@
-
+
{{ formatMessage(messages.yourFavoriteMods) }}
-
-
-
-
- {{ formatMessage(creatingLink ? messages.creatingButton : messages.createButton) }}
-
-
+
+
+
+ {{ formatMessage(creatingLink ? messages.creatingButton : messages.createButton) }}
+
@@ -62,9 +65,11 @@
import { AffiliateIcon, PlusIcon, SpinnerIcon, UserIcon } from '@modrinth/assets'
import { computed, ref, useTemplateRef } from 'vue'
+import { Button } from '#ui/components/base/buttons'
+
import { defineMessages, useVIntl } from '../../composables/i18n'
import { commonMessages } from '../../utils/common-messages'
-import { AutoBrandIcon, ButtonStyled, NewModal, StyledInput } from '../index'
+import { AutoBrandIcon, NewModal, StyledInput } from '../index'
export type CreateAffiliateProps = { sourceName: string; username?: string }
const props = withDefaults(
diff --git a/packages/ui/src/components/base/Admonition.vue b/packages/ui/src/components/base/Admonition.vue
index 26a3bfef62..43d82ba0da 100644
--- a/packages/ui/src/components/base/Admonition.vue
+++ b/packages/ui/src/components/base/Admonition.vue
@@ -1,7 +1,8 @@
@@ -39,7 +40,7 @@
{{ relativeTimeLabel }}
-
@@ -58,17 +59,22 @@
class="col-start-3 row-start-1 flex shrink-0 items-center gap-2 self-start"
>
-
-
-
-
-
+
+
(),
{
type: 'info',
@@ -125,6 +133,7 @@ const props = withDefaults(
progressColor: undefined,
waiting: false,
timestamp: undefined,
+ centerContent: false,
},
)
diff --git a/packages/ui/src/components/base/BaseTerminal.vue b/packages/ui/src/components/base/BaseTerminal.vue
index ff1f37419b..cc78d727eb 100644
--- a/packages/ui/src/components/base/BaseTerminal.vue
+++ b/packages/ui/src/components/base/BaseTerminal.vue
@@ -12,11 +12,9 @@
/>
-
-
-
-
-
+
+
+
+import { renderBasicInlineMarkdown } from '@modrinth/utils'
+import { computed } from 'vue'
+
+const props = withDefaults(
+ defineProps<{
+ text: string
+ target?: string
+ }>(),
+ {
+ target: '_blank',
+ },
+)
+
+const html = computed(() =>
+ renderBasicInlineMarkdown(props.text, {
+ target: props.target,
+ }),
+)
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/Button.vue b/packages/ui/src/components/base/Button.vue
deleted file mode 100644
index 48416b4f51..0000000000
--- a/packages/ui/src/components/base/Button.vue
+++ /dev/null
@@ -1,142 +0,0 @@
-
-
-
- {
- if (disabled) {
- event.preventDefault()
- return
- }
- if (action) {
- action(event)
- }
- }
- "
- >
-
-
-
-
- {
- if (disabled) {
- event.preventDefault()
- return
- }
- if (action) {
- action(event)
- }
- }
- "
- >
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/ui/src/components/base/ButtonStyled.vue b/packages/ui/src/components/base/ButtonStyled.vue
deleted file mode 100644
index f546054c16..0000000000
--- a/packages/ui/src/components/base/ButtonStyled.vue
+++ /dev/null
@@ -1,397 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/packages/ui/src/components/base/Card.vue b/packages/ui/src/components/base/Card.vue
index f52f4533b0..c481f17eb0 100644
--- a/packages/ui/src/components/base/Card.vue
+++ b/packages/ui/src/components/base/Card.vue
@@ -2,7 +2,7 @@
import { DropdownIcon } from '@modrinth/assets'
import { reactive } from 'vue'
-import ButtonStyled from './ButtonStyled.vue'
+import { IconButton } from '#ui/components/base/buttons'
const props = defineProps({
collapsible: {
@@ -33,11 +33,9 @@ function toggleCollapsed() {
diff --git a/packages/ui/src/components/base/Chips.vue b/packages/ui/src/components/base/Chips.vue
index e1359c469e..e7daddc930 100644
--- a/packages/ui/src/components/base/Chips.vue
+++ b/packages/ui/src/components/base/Chips.vue
@@ -15,7 +15,11 @@
}"
@click="toggleItem(item)"
>
-
+
{{ formatLabel(item) }}
@@ -24,7 +28,7 @@
+
+
diff --git a/packages/ui/src/components/base/FloatingActionBar.vue b/packages/ui/src/components/base/FloatingActionBar.vue
index 6b69515363..3f50e745bc 100644
--- a/packages/ui/src/components/base/FloatingActionBar.vue
+++ b/packages/ui/src/components/base/FloatingActionBar.vue
@@ -225,7 +225,7 @@ defineOptions({
'bar-compact': compact,
'floating-action-bar-attention': attentionRequested,
},
- inline ? 'w-full' : 'mx-auto md:max-w-[60vw]',
+ inline ? 'w-full' : 'mx-auto md:max-w-[min(calc(100vw-120px),1050px)]',
]"
@animationend="attentionRequested = false"
>
diff --git a/packages/ui/src/components/base/FloatingPanel.vue b/packages/ui/src/components/base/FloatingPanel.vue
index b4d45d1267..e06aa00761 100644
--- a/packages/ui/src/components/base/FloatingPanel.vue
+++ b/packages/ui/src/components/base/FloatingPanel.vue
@@ -2,7 +2,7 @@
import { onClickOutside } from '@vueuse/core'
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
-import ButtonStyled from './ButtonStyled.vue'
+import { Button } from '#ui/components/base/buttons'
const PANEL_VIEWPORT_MARGIN = 8
@@ -249,19 +249,18 @@ defineExpose({
-
-
-
-
-
+
+
+
`${panelHeight.value - 120}px`)
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/IconSelect.vue b/packages/ui/src/components/base/IconSelect.vue
index 61b0231753..aec022db6d 100644
--- a/packages/ui/src/components/base/IconSelect.vue
+++ b/packages/ui/src/components/base/IconSelect.vue
@@ -1,8 +1,10 @@
-
import IntlMessageFormat, { type FormatXMLElementFn, type PrimitiveType } from 'intl-messageformat'
-import { computed, markRaw, useSlots, type VNode } from 'vue'
+import { computed, defineComponent, markRaw, type PropType, useSlots, type VNode } from 'vue'
import type { MessageDescriptor } from '../../composables/i18n'
import { injectI18nDebug } from '../../composables/i18n-debug'
import { injectI18n } from '../../providers/i18n'
+const VNodeRenderer = defineComponent({
+ props: {
+ node: { type: Object as PropType, required: true },
+ },
+ setup(props) {
+ return () => props.node
+ },
+})
+
const props = defineProps<{
messageId: MessageDescriptor
values?: Record
@@ -49,11 +58,13 @@ const formattedParts = computed(() => {
slotHandlers[normalizedName] = (chunks) => {
const slot = slots[slotName]
if (slot) {
- return markRaw(
- slot({
- children: chunks,
- }),
- ) as VNode[]
+ const nodes = slot({
+ children: chunks,
+ })
+ if (Array.isArray(nodes) && nodes.length === 1) {
+ return markRaw(nodes[0]) as VNode
+ }
+ return markRaw(nodes) as VNode[]
}
return markRaw(chunks) as VNode[]
}
@@ -71,33 +82,35 @@ const formattedParts = computed(() => {
...slotHandlers,
})
- // ensure result array items are marked as raw if they're VNodes
- // prevents VNodes from entering the reactive system and SSR payload
- if (Array.isArray(result)) {
- return result.map((part) =>
- typeof part === 'object' && part !== null ? markRaw(part) : part,
- )
- }
- return [typeof result === 'object' && result !== null ? markRaw(result) : result]
+ return toFormattedParts(result)
} catch {
return [msg]
}
})
+
+function toFormattedParts(value: unknown): unknown[] {
+ if (Array.isArray(value)) {
+ return value.flatMap(toFormattedParts)
+ }
+ if (typeof value === 'object' && value !== null) {
+ return [markRaw(value)]
+ }
+ return [value]
+}
+
+function isVNodePart(part: unknown): part is VNode {
+ return typeof part === 'object' && part !== null
+}
-
+
{{ part }}
-
-
- {{ part }}
-
diff --git a/packages/ui/src/components/base/JoinedButtons.vue b/packages/ui/src/components/base/JoinedButtons.vue
deleted file mode 100644
index 44ffb3a424..0000000000
--- a/packages/ui/src/components/base/JoinedButtons.vue
+++ /dev/null
@@ -1,151 +0,0 @@
-
-
-
-
-
- {{ primaryAction.label }}
-
-
-
-
-
-
-
- {{ action.label }}
-
-
-
-
-
-
-
-
-
diff --git a/packages/ui/src/components/base/ManySelect.vue b/packages/ui/src/components/base/ManySelect.vue
index ed495af309..b3c927d039 100644
--- a/packages/ui/src/components/base/ManySelect.vue
+++ b/packages/ui/src/components/base/ManySelect.vue
@@ -1,23 +1,19 @@
-
- {
- searchQuery = ''
- }
- "
- >
+
+
-
+
+
+
{{ getOptionLabel(option) }}
{{ getOptionLabel(option) }}
-
-
-
+
+
+
-
-
diff --git a/packages/ui/src/components/base/Pagination.vue b/packages/ui/src/components/base/Pagination.vue
index ba1eae2cda..f7a6e08cb5 100644
--- a/packages/ui/src/components/base/Pagination.vue
+++ b/packages/ui/src/components/base/Pagination.vue
@@ -1,18 +1,20 @@
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+ {{ formatMessage(optionalMessage) }}
+
+
+
+ {{ title }}
+
+ {{ formatMessage(optionalMessage) }}
+
+
+
+
+ {{ description }}
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/SettingsInlineWarning.vue b/packages/ui/src/components/base/SettingsInlineWarning.vue
new file mode 100644
index 0000000000..3b9073c331
--- /dev/null
+++ b/packages/ui/src/components/base/SettingsInlineWarning.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/packages/ui/src/components/base/SettingsOptionCard.vue b/packages/ui/src/components/base/SettingsOptionCard.vue
new file mode 100644
index 0000000000..5c2036c050
--- /dev/null
+++ b/packages/ui/src/components/base/SettingsOptionCard.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
diff --git a/packages/ui/src/components/base/SettingsToggleCard.vue b/packages/ui/src/components/base/SettingsToggleCard.vue
new file mode 100644
index 0000000000..993d6cbcae
--- /dev/null
+++ b/packages/ui/src/components/base/SettingsToggleCard.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/SmartClickable.vue b/packages/ui/src/components/base/SmartClickable.vue
index 961de1732d..ad34fdb86c 100644
--- a/packages/ui/src/components/base/SmartClickable.vue
+++ b/packages/ui/src/components/base/SmartClickable.vue
@@ -5,7 +5,8 @@
v-bind="$attrs"
class="smart-clickable__contents"
:class="{
- 'pointer-events-none': !!$slots.clickable,
+ 'smart-clickable__contents--disabled': disabled,
+ 'pointer-events-none': !!$slots.clickable && !disabled,
}"
>
@@ -14,6 +15,10 @@
diff --git a/packages/ui/src/components/base/TimeFramePicker.vue b/packages/ui/src/components/base/TimeFramePicker.vue
index 0db65f9e14..2be4e72e73 100644
--- a/packages/ui/src/components/base/TimeFramePicker.vue
+++ b/packages/ui/src/components/base/TimeFramePicker.vue
@@ -5,6 +5,9 @@
:display-value="selectedTimeframeLabel"
:max-height="maxHeight"
:trigger-class="triggerClass"
+ :trigger-type="triggerType"
+ :trigger-size="triggerSize"
+ :trigger-interaction="triggerInteraction"
:dropdown-min-width="timeframeDropdownMinWidth"
:outside-click-ignore="timeframeDropdownOutsideClickIgnore"
:dropdown-class="
@@ -103,16 +106,18 @@
-
-
- {{ formatMessage(messages.cancel) }}
-
-
-
-
- {{ formatMessage(messages.apply) }}
-
-
+
+ {{ formatMessage(messages.cancel) }}
+
+
+ {{ formatMessage(messages.apply) }}
+
@@ -196,8 +201,14 @@
import { MinusIcon, PlusIcon } from '@modrinth/assets'
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
+import {
+ Button,
+ type ButtonInteraction,
+ type ButtonSize,
+ type ButtonType,
+} from '#ui/components/base/buttons'
+
import { defineMessages, useVIntl } from '../../composables/i18n'
-import ButtonStyled from './ButtonStyled.vue'
import Combobox, { type ComboboxOption } from './Combobox.vue'
import DatePicker from './DatePicker.vue'
@@ -391,11 +402,17 @@ const props = withDefaults(
nowTimestamp?: number
maxHeight?: number
triggerClass?: string
+ triggerType?: ButtonType
+ triggerSize?: ButtonSize
+ triggerInteraction?: ButtonInteraction
dropdownMinWidth?: string | number
customRangeDropdownMinWidth?: string | number
}>(),
{
maxHeight: TIMEFRAME_DROPDOWN_MAX_HEIGHT,
+ triggerType: 'base',
+ triggerSize: 'md',
+ triggerInteraction: 'surface',
dropdownMinWidth: TIMEFRAME_DROPDOWN_MIN_WIDTH,
customRangeDropdownMinWidth: CUSTOM_RANGE_DROPDOWN_MIN_WIDTH,
},
diff --git a/packages/ui/src/components/base/ToggleCard.vue b/packages/ui/src/components/base/ToggleCard.vue
new file mode 100644
index 0000000000..3daf0d1f6f
--- /dev/null
+++ b/packages/ui/src/components/base/ToggleCard.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/UnsavedChangesPopup.vue b/packages/ui/src/components/base/UnsavedChangesPopup.vue
index 4606042c86..c910b1ce19 100644
--- a/packages/ui/src/components/base/UnsavedChangesPopup.vue
+++ b/packages/ui/src/components/base/UnsavedChangesPopup.vue
@@ -3,9 +3,10 @@ import { HistoryIcon, SaveIcon, SpinnerIcon } from '@modrinth/assets'
import { isEqual } from 'es-toolkit'
import { type Component, computed, ref } from 'vue'
+import { Button } from '#ui/components/base/buttons'
+
import { defineMessage, type MessageDescriptor, useVIntl } from '../../composables/i18n'
import { commonMessages } from '../../utils'
-import ButtonStyled from './ButtonStyled.vue'
import FloatingActionBar from './FloatingActionBar.vue'
const { formatMessage } = useVIntl()
@@ -14,20 +15,25 @@ const emit = defineEmits<{
(e: 'reset' | 'save', event: MouseEvent): void
}>()
+type SaveDisabledReason = MessageDescriptor | string
+
const props = withDefaults(
defineProps<{
canReset?: boolean
+ canSave?: boolean
original: T
modified: Partial
saving?: boolean
text?: MessageDescriptor | string
saveLabel?: MessageDescriptor | string
savingLabel?: MessageDescriptor | string
+ saveDisabledReason?: SaveDisabledReason | SaveDisabledReason[]
saveIcon?: Component
inline?: boolean
}>(),
{
canReset: true,
+ canSave: true,
saving: false,
text: () =>
defineMessage({
@@ -36,19 +42,38 @@ const props = withDefaults(
}),
saveLabel: () => commonMessages.saveButton,
savingLabel: () => commonMessages.savingButton,
+ saveDisabledReason: undefined,
saveIcon: SaveIcon,
inline: false,
},
)
-const shown = computed(() =>
- Object.keys(props.modified).some((key) => !isEqual(props.original[key], props.modified[key])),
+const shown = computed(
+ () =>
+ props.saving ||
+ Object.keys(props.modified).some((key) => !isEqual(props.original[key], props.modified[key])),
)
function localizeIfPossible(message: MessageDescriptor | string) {
return typeof message === 'string' ? message : formatMessage(message)
}
+const saveDisabled = computed(() => props.saving || !props.canSave)
+
+const saveDisabledTooltip = computed(() => {
+ if (!saveDisabled.value || props.saving || !props.saveDisabledReason) {
+ return undefined
+ }
+
+ const reasons = (
+ Array.isArray(props.saveDisabledReason) ? props.saveDisabledReason : [props.saveDisabledReason]
+ ).map(localizeIfPossible)
+
+ return reasons.length > 0
+ ? { content: reasons.join('\n'), popperClass: 'unsaved-changes-save-tooltip' }
+ : undefined
+})
+
const actionBar = ref | null>(null)
function nudge(): void {
@@ -62,18 +87,35 @@ defineExpose({ nudge })
{{ localizeIfPossible(text) }}
-
- emit('reset', e)">
- {{ formatMessage(commonMessages.resetButton) }}
-
-
-
- emit('save', e)">
+ emit('reset', e)">
+ {{ formatMessage(commonMessages.resetButton) }}
+
+
+ emit('save', e)"
+ >
{{ localizeIfPossible(saving ? savingLabel : saveLabel) }}
-
-
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/Button.vue b/packages/ui/src/components/base/buttons/Button.vue
new file mode 100644
index 0000000000..6d9f4e2b44
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/Button.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/ButtonFrame.vue b/packages/ui/src/components/base/buttons/ButtonFrame.vue
new file mode 100644
index 0000000000..a51df9d063
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/ButtonFrame.vue
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/ButtonGroup.vue b/packages/ui/src/components/base/buttons/ButtonGroup.vue
new file mode 100644
index 0000000000..04af5b1261
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/ButtonGroup.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/ButtonLink.vue b/packages/ui/src/components/base/buttons/ButtonLink.vue
new file mode 100644
index 0000000000..cb11c7c6c6
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/ButtonLink.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/FileButton.vue b/packages/ui/src/components/base/buttons/FileButton.vue
new file mode 100644
index 0000000000..0c6c09b2ee
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/FileButton.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+ {{ props.prompt }}
+
+
+
diff --git a/packages/ui/src/components/base/buttons/IconButton.vue b/packages/ui/src/components/base/buttons/IconButton.vue
new file mode 100644
index 0000000000..6fe601fb2b
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/IconButton.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/SplitButton.vue b/packages/ui/src/components/base/buttons/SplitButton.vue
new file mode 100644
index 0000000000..40badebad8
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/SplitButton.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/TeleportOverflowMenu.vue b/packages/ui/src/components/base/buttons/TeleportOverflowMenu.vue
new file mode 100644
index 0000000000..a9f638197d
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/TeleportOverflowMenu.vue
@@ -0,0 +1,484 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/TeleportPopoutMenu.vue b/packages/ui/src/components/base/buttons/TeleportPopoutMenu.vue
new file mode 100644
index 0000000000..d365b1673a
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/TeleportPopoutMenu.vue
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/base/buttons/index.ts b/packages/ui/src/components/base/buttons/index.ts
new file mode 100644
index 0000000000..cbfc192984
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/index.ts
@@ -0,0 +1,23 @@
+export { default as Button } from './Button.vue'
+export { default as ButtonGroup } from './ButtonGroup.vue'
+export { default as ButtonLink } from './ButtonLink.vue'
+export { default as FileButton } from './FileButton.vue'
+export { default as IconButton } from './IconButton.vue'
+export { default as SplitButton } from './SplitButton.vue'
+export { default as TeleportOverflowMenu } from './TeleportOverflowMenu.vue'
+export { default as TeleportPopoutMenu } from './TeleportPopoutMenu.vue'
+export type {
+ ButtonColor,
+ ButtonElementHandle,
+ ButtonInteraction,
+ ButtonLinkDestination,
+ ButtonNativeType,
+ ButtonSize,
+ ButtonType,
+ ButtonVisualProps,
+ OverflowMenuAction,
+ OverflowMenuDivider,
+ OverflowMenuLink,
+ OverflowMenuOption,
+ TeleportPlacement,
+} from './types'
diff --git a/packages/ui/src/components/base/buttons/types.ts b/packages/ui/src/components/base/buttons/types.ts
new file mode 100644
index 0000000000..2e8e7f5d81
--- /dev/null
+++ b/packages/ui/src/components/base/buttons/types.ts
@@ -0,0 +1,109 @@
+import type { Component } from 'vue'
+import type { RouteLocationRaw } from 'vue-router'
+
+import type { AnchoredTeleportPlacement } from '../../../utils/use-anchored-teleport'
+
+export type ButtonType = 'base' | 'colored' | 'colored-text' | 'outlined' | 'quiet'
+
+export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+
+export type ButtonInteraction = 'surface' | 'filled' | 'none'
+
+// TODO: Standardized color string enum props across @modrinth/ui
+export type ButtonColor =
+ | 'brand'
+ | 'red'
+ | 'orange'
+ | 'green'
+ | 'blue'
+ | 'purple'
+ | 'medal_promotion'
+
+export type ButtonVisualProps = {
+ size?: ButtonSize
+ interaction?: ButtonInteraction
+} & (
+ | {
+ type?: 'base'
+ color?: never
+ }
+ | {
+ type: 'outlined'
+ color?: ButtonColor
+ }
+ | {
+ type: 'colored'
+ color?: ButtonColor
+ }
+ | {
+ type: 'colored-text'
+ color?: ButtonColor
+ }
+ | {
+ type: 'quiet'
+ color?: ButtonColor
+ }
+)
+
+export type ButtonNativeType = 'button' | 'submit' | 'reset'
+
+export interface ButtonProps {
+ type?: ButtonType
+ color?: ButtonColor
+ size?: ButtonSize
+ interaction?: ButtonInteraction
+ nativeType?: ButtonNativeType
+ disabled?: boolean
+ loading?: boolean
+}
+
+export type ButtonLinkDestination =
+ | {
+ to: RouteLocationRaw
+ href?: never
+ }
+ | {
+ href: string
+ to?: never
+ }
+
+export type TeleportPlacement = AnchoredTeleportPlacement
+
+export interface OverflowMenuItemBase {
+ id: string
+ label: string
+ icon?: Component
+ shown?: boolean
+ disabled?: boolean
+ tooltip?: string
+ remainOpen?: boolean
+ tone?: 'default' | ButtonColor
+ hoverFilled?: boolean
+ hoverFilledOnly?: boolean
+}
+
+export interface OverflowMenuAction extends OverflowMenuItemBase {
+ type?: 'action'
+ action: (event: MouseEvent) => void
+}
+
+export interface OverflowMenuLink extends OverflowMenuItemBase {
+ type: 'link'
+ to?: RouteLocationRaw
+ href?: string
+ target?: string
+ rel?: string
+ download?: string | boolean
+}
+
+export interface OverflowMenuDivider {
+ type: 'divider'
+ id?: string
+ shown?: boolean
+}
+
+export type OverflowMenuOption = OverflowMenuAction | OverflowMenuLink | OverflowMenuDivider
+
+export interface ButtonElementHandle {
+ element: HTMLElement | null
+}
diff --git a/packages/ui/src/components/base/index.ts b/packages/ui/src/components/base/index.ts
index 1373522c33..3a82053838 100644
--- a/packages/ui/src/components/base/index.ts
+++ b/packages/ui/src/components/base/index.ts
@@ -7,10 +7,30 @@ export { default as AutoLink } from './AutoLink.vue'
export { default as Avatar } from './Avatar.vue'
export { default as Badge } from './Badge.vue'
export { default as BaseTerminal } from './BaseTerminal.vue'
+export { default as BasicMarkdownText } from './BasicMarkdownText.vue'
export { default as BigOptionButton } from './BigOptionButton.vue'
export { default as BulletDivider } from './BulletDivider.vue'
-export { default as Button } from './Button.vue'
-export { default as ButtonStyled } from './ButtonStyled.vue'
+export { default as Button } from './buttons/Button.vue'
+export { default as ButtonGroup } from './buttons/ButtonGroup.vue'
+export { default as ButtonLink } from './buttons/ButtonLink.vue'
+export { default as FileButton } from './buttons/FileButton.vue'
+export { default as IconButton } from './buttons/IconButton.vue'
+export { default as SplitButton } from './buttons/SplitButton.vue'
+export { default as TeleportOverflowMenu } from './buttons/TeleportOverflowMenu.vue'
+export { default as TeleportPopoutMenu } from './buttons/TeleportPopoutMenu.vue'
+export type {
+ ButtonColor,
+ ButtonInteraction,
+ ButtonNativeType,
+ ButtonSize,
+ ButtonType,
+ ButtonVisualProps,
+ OverflowMenuAction,
+ OverflowMenuDivider,
+ OverflowMenuLink,
+ OverflowMenuOption,
+ TeleportPlacement,
+} from './buttons/types'
export { default as Card } from './Card.vue'
export { default as Checkbox } from './Checkbox.vue'
export { default as Chips } from './Chips.vue'
@@ -46,8 +66,6 @@ export { default as HorizontalRule } from './HorizontalRule.vue'
export { default as I18nDebugPanel } from './I18nDebugPanel.vue'
export { default as IconSelect } from './IconSelect.vue'
export { default as IntlFormatted } from './IntlFormatted.vue'
-export type { JoinedButtonAction } from './JoinedButtons.vue'
-export { default as JoinedButtons } from './JoinedButtons.vue'
export { default as LoadingBar } from './LoadingBar.vue'
export { default as LoadingIndicator } from './LoadingIndicator.vue'
export { default as ManySelect } from './ManySelect.vue'
@@ -62,8 +80,6 @@ export type { MaybeCtxFn, StageButtonConfig, StageConfigInput } from './MultiSta
export { default as MultiStageModal, resolveCtxFn } from './MultiStageModal.vue'
export { default as NavTabs } from './NavTabs.vue'
export { default as OptionGroup } from './OptionGroup.vue'
-export type { Option as OverflowMenuOption } from './OverflowMenu.vue'
-export { default as OverflowMenu } from './OverflowMenu.vue'
export { default as Page } from './Page.vue'
export { default as PageHeader } from './page-header/index.vue'
export { default as PageHeaderMetadata } from './page-header/metadata/index.vue'
@@ -92,7 +108,11 @@ export { default as RadioButtons } from './RadioButtons.vue'
export { default as ReadyTransition } from './ReadyTransition.vue'
export { default as ScrollablePanel } from './ScrollablePanel.vue'
export { default as ServerNotice } from './ServerNotice.vue'
+export { default as SettingsFormGroup } from './SettingsFormGroup.vue'
+export { default as SettingsInlineWarning } from './SettingsInlineWarning.vue'
export { default as SettingsLabel } from './SettingsLabel.vue'
+export { default as SettingsOptionCard } from './SettingsOptionCard.vue'
+export { default as SettingsToggleCard } from './SettingsToggleCard.vue'
export { default as SimpleBadge } from './SimpleBadge.vue'
export { default as Slider } from './Slider.vue'
export { default as SmartClickable } from './SmartClickable.vue'
@@ -104,13 +124,9 @@ export type { SortDirection, TableColumn } from './Table.vue'
export { default as Table } from './Table.vue'
export type { TabsTab, TabsValue } from './Tabs.vue'
export { default as Tabs } from './Tabs.vue'
+export { default as TagIcon } from './TagIcon.vue'
export { default as TagItem } from './TagItem.vue'
export { default as TagTagItem } from './TagTagItem.vue'
-export type {
- Item as TeleportOverflowMenuItem,
- Option as TeleportOverflowMenuOption,
-} from './TeleportOverflowMenu.vue'
-export { default as TeleportOverflowMenu } from './TeleportOverflowMenu.vue'
export type {
TimeFrameLastUnit,
TimeFrameLastUnitOption,
@@ -121,4 +137,5 @@ export type {
export { default as TimeFramePicker } from './TimeFramePicker.vue'
export { default as Timeline } from './Timeline.vue'
export { default as Toggle } from './Toggle.vue'
+export { default as ToggleCard } from './ToggleCard.vue'
export { default as UnsavedChangesPopup } from './UnsavedChangesPopup.vue'
diff --git a/packages/ui/src/components/billing/AddPaymentMethodModal.vue b/packages/ui/src/components/billing/AddPaymentMethodModal.vue
index 8e1361adb6..a05eaf4f20 100644
--- a/packages/ui/src/components/billing/AddPaymentMethodModal.vue
+++ b/packages/ui/src/components/billing/AddPaymentMethodModal.vue
@@ -3,9 +3,11 @@ import { PlusIcon, XIcon } from '@modrinth/assets'
import type Stripe from 'stripe'
import { nextTick, ref, useTemplateRef } from 'vue'
+import { Button } from '#ui/components/base/buttons'
+
import { defineMessages, useVIntl } from '../../composables/i18n'
import { commonMessages } from '../../utils'
-import { ButtonStyled, NewModal } from '../index'
+import { NewModal } from '../index'
import type { AddPaymentMethodProps } from './AddPaymentMethod.vue'
import AddPaymentMethod from './AddPaymentMethod.vue'
@@ -57,18 +59,14 @@ defineExpose({
@stop-loading="loading = false"
/>
diff --git a/packages/ui/src/components/billing/ModrinthServersPurchaseModal.vue b/packages/ui/src/components/billing/ModrinthServersPurchaseModal.vue
index bdae9d75ed..14c1eacd8a 100644
--- a/packages/ui/src/components/billing/ModrinthServersPurchaseModal.vue
+++ b/packages/ui/src/components/billing/ModrinthServersPurchaseModal.vue
@@ -12,12 +12,12 @@ import { useQueryClient } from '@tanstack/vue-query'
import type Stripe from 'stripe'
import { computed, nextTick, onBeforeUnmount, ref, toRef, useTemplateRef, watch } from 'vue'
+import { Button } from '#ui/components/base/buttons'
import { injectNotificationManager } from '#ui/providers/web-notifications.ts'
import { defineMessage, type MessageDescriptor, useVIntl } from '../../composables/i18n'
import { useStripe } from '../../composables/stripe'
import { commonMessages } from '../../utils'
-import { ButtonStyled } from '../index'
import ModalLoadingIndicator from '../modal/ModalLoadingIndicator.vue'
import NewModal from '../modal/NewModal.vue'
import PlanSelector from './ServersPurchase0Plan.vue'
@@ -555,51 +555,50 @@ function goToBreadcrumbStep(id: string) {
-
-
- {{ formatMessage(commonMessages.backButton) }}
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
- {
- if (props.onFinalizeNoPaymentChange) {
- try {
- await props.onFinalizeNoPaymentChange()
- } catch (e) {
- return
- }
+
+ {{ formatMessage(commonMessages.backButton) }}
+
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+ {
+ if (props.onFinalizeNoPaymentChange) {
+ try {
+ await props.onFinalizeNoPaymentChange()
+ } catch (e) {
+ return
}
- modal?.hide()
- })()
- : setStep(nextStep)
- "
- >
-
- Confirm Change
-
-
-
- Subscribe
-
-
+ }
+ modal?.hide()
+ })()
+ : setStep(nextStep)
+ "
+ >
+
+ Confirm Change
- {{ formatMessage(commonMessages.nextButton) }}
+
+
+ Subscribe
-
-
+
+
+ {{ formatMessage(commonMessages.nextButton) }}
+
+
diff --git a/packages/ui/src/components/billing/PurchaseModal.vue b/packages/ui/src/components/billing/PurchaseModal.vue
index d1753d10a0..5c291fb92a 100644
--- a/packages/ui/src/components/billing/PurchaseModal.vue
+++ b/packages/ui/src/components/billing/PurchaseModal.vue
@@ -86,7 +86,7 @@
}"
@click="serverLoader = loader"
>
-
+
{{ loader }}
@@ -478,9 +478,9 @@ import Checkbox from '../base/Checkbox.vue'
import Combobox from '../base/Combobox.vue'
import Slider from '../base/Slider.vue'
import StyledInput from '../base/StyledInput.vue'
+import TagIcon from '../base/TagIcon.vue'
import AnimatedLogo from '../brand/AnimatedLogo.vue'
import NewModal from '../modal/NewModal.vue'
-import LoaderIcon from '../servers/icons/LoaderIcon.vue'
const { formatMessage } = useVIntl()
const formatPrice = useFormatPrice()
diff --git a/packages/ui/src/components/billing/ResubscribeModal.vue b/packages/ui/src/components/billing/ResubscribeModal.vue
index 298416af3b..084f3a0a35 100644
--- a/packages/ui/src/components/billing/ResubscribeModal.vue
+++ b/packages/ui/src/components/billing/ResubscribeModal.vue
@@ -78,18 +78,14 @@
-
-
-
- {{ formatMessage(messages.cancelButton) }}
-
-
-
-
-
- {{ formatMessage(messages.resubscribeButton) }}
-
-
+
+
+ {{ formatMessage(messages.cancelButton) }}
+
+
+
+ {{ formatMessage(messages.resubscribeButton) }}
+
@@ -100,12 +96,13 @@ import type { Labrinth } from '@modrinth/api-client'
import { RotateCounterClockwiseIcon, XIcon } from '@modrinth/assets'
import { computed, ref, useTemplateRef } from 'vue'
+import { Button } from '#ui/components/base/buttons'
import { injectNotificationManager } from '#ui/providers/web-notifications.ts'
import { useFormatDateTime, useFormatPrice } from '../../composables'
import { defineMessages, useVIntl } from '../../composables/i18n'
import IntlFormatted from '../base/IntlFormatted.vue'
-import { ButtonStyled, NewModal } from '../index'
+import { NewModal } from '../index'
const { addNotification } = injectNotificationManager()
const { formatMessage } = useVIntl()
diff --git a/packages/ui/src/components/billing/ServersGuestPlanModal.vue b/packages/ui/src/components/billing/ServersGuestPlanModal.vue
index f99f2ecc52..f1322c88ac 100644
--- a/packages/ui/src/components/billing/ServersGuestPlanModal.vue
+++ b/packages/ui/src/components/billing/ServersGuestPlanModal.vue
@@ -3,7 +3,8 @@ import type { Labrinth } from '@modrinth/api-client'
import { ChevronRightIcon, ExternalIcon, XIcon } from '@modrinth/assets'
import { computed, ref, useTemplateRef } from 'vue'
-import ButtonStyled from '../base/ButtonStyled.vue'
+import { Button, IconButton } from '#ui/components/base/buttons'
+
import NewModal from '../modal/NewModal.vue'
import type { ServerBillingInterval } from './ModrinthServersPurchaseModal.vue'
import PlanSelector from './ServersPurchase0Plan.vue'
@@ -143,11 +144,9 @@ defineExpose({
class="absolute inset-x-0 bottom-0 -m-px z-30 rounded-2xl border border-solid border-surface-5 bg-bg-raised p-6 shadow-2xl"
>
-
-
-
-
-
+
+
+
@@ -155,12 +154,10 @@ defineExpose({
Sign in to continue your purchase
You need a Modrinth account to add your billing details.
-
-
- Sign in or create an account
-
-
-
+
+ Sign in or create an account
+
+
diff --git a/packages/ui/src/components/billing/ServersPurchase0Plan.vue b/packages/ui/src/components/billing/ServersPurchase0Plan.vue
index 456b324aea..16d85c9fbb 100644
--- a/packages/ui/src/components/billing/ServersPurchase0Plan.vue
+++ b/packages/ui/src/components/billing/ServersPurchase0Plan.vue
@@ -3,10 +3,11 @@ import type { Labrinth } from '@modrinth/api-client'
import { RightArrowIcon } from '@modrinth/assets'
import { computed } from 'vue'
+import { Button } from '#ui/components/base/buttons'
+
import { useFormatPrice } from '../../composables'
import { defineMessages, useVIntl } from '../../composables/i18n'
import { getPriceForInterval, monthsInInterval } from '../../utils/product-utils'
-import ButtonStyled from '../base/ButtonStyled.vue'
import OptionGroup from '../base/OptionGroup.vue'
import type { ServerBillingInterval } from './ModrinthServersPurchaseModal.vue'
import ServersSpecs from './ServersSpecs.vue'
@@ -218,19 +219,19 @@ function selectCustom() {
-
-
- {{
- existingPlan?.id === plansByRam.small.id
- ? formatMessage(messages.yourCurrentPlan)
- : formatMessage(messages.selectPlan)
- }}
-
-
+
+ {{
+ existingPlan?.id === plansByRam.small.id
+ ? formatMessage(messages.yourCurrentPlan)
+ : formatMessage(messages.selectPlan)
+ }}
+
-
+
{{ formatMessage(messages.mostPopular) }}
@@ -281,19 +280,19 @@ function selectCustom() {
-
-
- {{
- existingPlan?.id === plansByRam.medium.id
- ? formatMessage(messages.yourCurrentPlan)
- : formatMessage(messages.selectPlan)
- }}
-
-
+
+ {{
+ existingPlan?.id === plansByRam.medium.id
+ ? formatMessage(messages.yourCurrentPlan)
+ : formatMessage(messages.selectPlan)
+ }}
+
-
-
- {{
- existingPlan?.id === plansByRam.large.id
- ? formatMessage(messages.yourCurrentPlan)
- : formatMessage(messages.selectPlan)
- }}
-
-
+
+ {{
+ existingPlan?.id === plansByRam.large.id
+ ? formatMessage(messages.yourCurrentPlan)
+ : formatMessage(messages.selectPlan)
+ }}
+
-
-
- {{ formatMessage(messages.getStarted) }}
-
-
+
+ {{ formatMessage(messages.getStarted) }}
+
Starting at {{ formatPrice(customStartingPrice, currency, true) }}/mo
diff --git a/packages/ui/src/components/billing/ServersPurchase3Review.vue b/packages/ui/src/components/billing/ServersPurchase3Review.vue
index bfe6096c8d..ce76cbc1af 100644
--- a/packages/ui/src/components/billing/ServersPurchase3Review.vue
+++ b/packages/ui/src/components/billing/ServersPurchase3Review.vue
@@ -15,11 +15,12 @@ import dayjs from 'dayjs'
import type Stripe from 'stripe'
import { computed } from 'vue'
+import { Button } from '#ui/components/base/buttons'
+
import { useFormatPrice } from '../../composables'
import { useVIntl } from '../../composables/i18n'
import { getPriceForInterval, monthsInInterval } from '../../utils/product-utils'
import { regionOverrides } from '../../utils/regions'
-import ButtonStyled from '../base/ButtonStyled.vue'
import Checkbox from '../base/Checkbox.vue'
import TagItem from '../base/TagItem.vue'
import ModrinthServersIcon from '../servers/ModrinthServersIcon.vue'
@@ -323,12 +324,10 @@ function setInterval(newInterval: ServerBillingInterval) {
No payment method selected
-
-
- Change
- Select payment method
-
-
+
+ Change
+ Select payment method
+
diff --git a/packages/ui/src/components/chart/Chart.vue b/packages/ui/src/components/chart/Chart.vue
index 43c11e1fb5..72d42bc67a 100644
--- a/packages/ui/src/components/chart/Chart.vue
+++ b/packages/ui/src/components/chart/Chart.vue
@@ -4,7 +4,7 @@ import dayjs from 'dayjs'
import { defineAsyncComponent, onMounted, ref } from 'vue'
import { useFormatNumber } from '../../composables/index.ts'
-import Button from '../base/Button.vue'
+import { IconButton } from '../base/buttons'
import Checkbox from '../base/Checkbox.vue'
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
@@ -231,12 +231,16 @@ defineExpose({
diff --git a/packages/ui/src/components/content/ArticleBody.vue b/packages/ui/src/components/content/ArticleBody.vue
index 492f1011d8..94e80da768 100644
--- a/packages/ui/src/components/content/ArticleBody.vue
+++ b/packages/ui/src/components/content/ArticleBody.vue
@@ -2,6 +2,7 @@
import { type Component, computed } from 'vue'
import PrideCollectionWidget from './PrideCollectionWidget.vue'
+import Rule6Widget from './Rule6Widget.vue'
import SparkLiveWidget from './SparkLiveWidget.vue'
import SparkLiveWidgetEmbed from './SparkLiveWidgetEmbed.vue'
@@ -9,6 +10,7 @@ const ARTICLE_WIDGETS: Record = {
'spark-live-widget': SparkLiveWidget,
'spark-live-widget-embed': SparkLiveWidgetEmbed,
'pride-collection-widget': PrideCollectionWidget,
+ 'rule-6': Rule6Widget,
}
type ArticleBodyPart = { type: 'html'; content: string } | { type: 'widget'; id: string }
diff --git a/packages/ui/src/components/content/Rule6Widget.vue b/packages/ui/src/components/content/Rule6Widget.vue
new file mode 100644
index 0000000000..b2477df0e8
--- /dev/null
+++ b/packages/ui/src/components/content/Rule6Widget.vue
@@ -0,0 +1,71 @@
+
+
+
+ 6. Usage of Generative "AI"
+
+
+
+ Projects must be forthright and honest about the usage of generative AI in their production,
+ publication, and within the project itself. Projects cannot be entirely or primarily comprised
+ of content created or derived from generative AI output.
+
+
+
6.1. Disclosure of AI generated content
+
+
You must apply the appropriate “Contains AI-generated content” content disclosure when:
+
+ a substantial portion of the project's code is a product of AI output.
+
+ the project includes any assets that are primarily or entirely a product of AI output.
+
+ the project's design or functionality relies on the use of generative AI.
+
+ any element of the project's page such as description or publishing relies on generative AI.
+
+
+
+
6.2. Prohibited AI generated content
+
+
+
+ No images uploaded to a gallery, icon, description, or any other part of a project page may
+ be created or derived from generative AI output. Any such images may be removed.
+
+
+ Projects may not be published publicly if the contents are primarily or entirely a product
+ of AI output.
+
+
+
+
+
diff --git a/packages/ui/src/components/external_files/AddFilesToAttributionGroupModal.vue b/packages/ui/src/components/external_files/AddFilesToAttributionGroupModal.vue
index fc94cf5af1..effcec44fa 100644
--- a/packages/ui/src/components/external_files/AddFilesToAttributionGroupModal.vue
+++ b/packages/ui/src/components/external_files/AddFilesToAttributionGroupModal.vue
@@ -3,7 +3,8 @@ import type { Labrinth } from '@modrinth/api-client'
import { CheckIcon, PlusIcon, SearchIcon, SpinnerIcon, XIcon } from '@modrinth/assets'
import { computed, nextTick, ref } from 'vue'
-import { ButtonStyled, NewModal, StyledInput } from '#ui/components'
+import { NewModal, StyledInput } from '#ui/components'
+import { Button } from '#ui/components/base/buttons'
import { commonMessages } from '#ui/utils'
import { defineMessages, useVIntl } from '../../composables/i18n'
@@ -263,23 +264,21 @@ defineExpose({ show, hide })
{{ formatMessage(messages.addFilesModalSelectedCount, { count: selectedFileCount }) }}
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
-
-
- {{ formatMessage(messages.addFilesModalConfirm, { count: selectedFileCount }) }}
-
-
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+
+ {{ formatMessage(messages.addFilesModalConfirm, { count: selectedFileCount }) }}
+
diff --git a/packages/ui/src/components/external_files/AddToExistingExternalProjectModal.vue b/packages/ui/src/components/external_files/AddToExistingExternalProjectModal.vue
index 9ad61e3b1a..85ccadcae4 100644
--- a/packages/ui/src/components/external_files/AddToExistingExternalProjectModal.vue
+++ b/packages/ui/src/components/external_files/AddToExistingExternalProjectModal.vue
@@ -4,7 +4,8 @@ import { PlusIcon, SearchIcon, SpinnerIcon, XIcon } from '@modrinth/assets'
import { useMutation } from '@tanstack/vue-query'
import { computed, ref, useTemplateRef } from 'vue'
-import { Accordion, ButtonStyled, NewModal, StyledInput } from '#ui/components'
+import { Accordion, NewModal, StyledInput } from '#ui/components'
+import { Button } from '#ui/components/base/buttons'
import { injectModrinthClient, injectNotificationManager } from '../../providers'
import AttributionGroupFilePicker from './AttributionGroupFilePicker.vue'
@@ -228,12 +229,15 @@ defineExpose({ show, hide })
wrapper-class="flex-1 min-w-[12rem]"
:disabled="addFilesMutation.isPending.value"
/>
-
-
-
- Search
-
-
+
+
+ Search
+
-
-
- {{ selectedProjectId === project.id ? 'Selected' : 'Select' }}
-
-
+
+ {{ selectedProjectId === project.id ? 'Selected' : 'Select' }}
+
@@ -306,22 +308,29 @@ defineExpose({ show, hide })
/>
-
-
-
- Cancel
-
-
-
-
-
-
- Add files to entry
-
-
+
+
+ Cancel
+
+
+
+
+ Add files to entry
+
diff --git a/packages/ui/src/components/external_files/AddToGlobalPermissionsDatabaseModal.vue b/packages/ui/src/components/external_files/AddToGlobalPermissionsDatabaseModal.vue
index c3a55d80d0..e36d1785d9 100644
--- a/packages/ui/src/components/external_files/AddToGlobalPermissionsDatabaseModal.vue
+++ b/packages/ui/src/components/external_files/AddToGlobalPermissionsDatabaseModal.vue
@@ -4,14 +4,8 @@ import { PlusIcon, SpinnerIcon, XIcon } from '@modrinth/assets'
import { useMutation } from '@tanstack/vue-query'
import { computed, ref, useTemplateRef } from 'vue'
-import {
- Accordion,
- ButtonStyled,
- Combobox,
- type ComboboxOption,
- NewModal,
- StyledInput,
-} from '#ui/components'
+import { Accordion, Combobox, type ComboboxOption, NewModal, StyledInput } from '#ui/components'
+import { Button } from '#ui/components/base/buttons'
import { injectModrinthClient, injectNotificationManager } from '../../providers'
import AttributionGroupFilePicker from './AttributionGroupFilePicker.vue'
@@ -223,22 +217,26 @@ defineExpose({ show, hide })
-
-
-
- Cancel
-
-
-
-
-
-
- Add to global database
-
-
+
+
+ Cancel
+
+
+
+
+ Add to global database
+
diff --git a/packages/ui/src/components/external_files/AttributionEditor.vue b/packages/ui/src/components/external_files/AttributionEditor.vue
index 3694793a02..82e99ad7cb 100644
--- a/packages/ui/src/components/external_files/AttributionEditor.vue
+++ b/packages/ui/src/components/external_files/AttributionEditor.vue
@@ -14,8 +14,9 @@ import { builtinLicenses } from '@modrinth/utils'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { computed, ref, watch } from 'vue'
-import { ButtonStyled, Chips, Combobox, type ComboboxOption, StyledInput } from '#ui/components'
+import { Chips, Combobox, type ComboboxOption, StyledInput } from '#ui/components'
import { FileInput } from '#ui/components/base'
+import { Button, IconButton } from '#ui/components/base/buttons'
import { commonMessages } from '#ui/utils'
import { defineMessage, defineMessages, useVIntl } from '../../composables/i18n'
@@ -577,15 +578,14 @@ function cancelEditing() {
class="flex w-full object-contain bg-surface-3"
/>
-
-
-
-
-
+
+
+
@@ -633,29 +633,29 @@ function cancelEditing() {
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
-
-
- {{ formatMessage(commonMessages.savingButton) }}
-
-
- {{ formatMessage(messages.saveAttribution) }}
-
- {{ formatMessage(messages.addAttribution) }}
-
-
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+
+ {{ formatMessage(commonMessages.savingButton) }}
+
+
+ {{ formatMessage(messages.saveAttribution) }}
+
+ {{ formatMessage(messages.addAttribution) }}
+
diff --git a/packages/ui/src/components/external_files/ExternalProjectLookupCard.vue b/packages/ui/src/components/external_files/ExternalProjectLookupCard.vue
index 4bf6a34a92..2467b5d3cf 100644
--- a/packages/ui/src/components/external_files/ExternalProjectLookupCard.vue
+++ b/packages/ui/src/components/external_files/ExternalProjectLookupCard.vue
@@ -9,7 +9,8 @@ import {
import { Menu } from 'floating-vue'
import { computed } from 'vue'
-import { ButtonStyled, CopyCode } from '#ui/components'
+import { CopyCode } from '#ui/components'
+import { IconButton } from '#ui/components/base/buttons'
import ExternalProjectLicenseStateTag from './ExternalProjectLicenseStateTag.vue'
import type { ExternalLicenseStatus } from './types.ts'
@@ -58,11 +59,16 @@ async function copyProjectLink() {
Project link
-
-
-
-
-
+
+
+
diff --git a/packages/ui/src/components/external_files/ExternalProjectPermissionsCard.vue b/packages/ui/src/components/external_files/ExternalProjectPermissionsCard.vue
index bb26531235..9dc39af921 100644
--- a/packages/ui/src/components/external_files/ExternalProjectPermissionsCard.vue
+++ b/packages/ui/src/components/external_files/ExternalProjectPermissionsCard.vue
@@ -18,8 +18,9 @@ import { renderString } from '@modrinth/utils'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { computed, ref, useTemplateRef, watch } from 'vue'
-import { ButtonStyled, Collapsible, ConfirmModal, OverflowMenu } from '#ui/components'
+import { Collapsible, ConfirmModal } from '#ui/components'
import type { OverflowMenuOption } from '#ui/components/base'
+import { Button, IconButton, TeleportOverflowMenu } from '#ui/components/base/buttons'
import { commonMessages } from '#ui/utils'
import { defineMessage, defineMessages, useVIntl } from '../../composables/i18n'
@@ -498,6 +499,7 @@ const visibleQuickReplies = computed(() => {
(reply) =>
({
id: reply.label,
+ label: reply.label,
action: () => handleQuickReply(reply),
}) as OverflowMenuOption,
)
@@ -577,28 +579,27 @@ const visibleQuickReplies = computed(() => {
-
-
-
-
-
-
+
+
+
+
-
-
- {{ formatMessage(messages.addFilesToGroup) }}
-
-
+
+ {{ formatMessage(messages.addFilesToGroup) }}
+
@@ -644,11 +645,9 @@ const visibleQuickReplies = computed(() => {
"
#actions
>
-
-
- {{ formatMessage(commonMessages.editButton) }}
-
-
+
+ {{ formatMessage(commonMessages.editButton) }}
+
-
-
- Reply presets
-
-
-
-
-
-
-
- Approve
-
-
-
-
-
-
- Reject: Insufficient proof
-
-
-
-
-
-
- Reject: Not allowed
-
-
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
+
+ Reply presets
+
+
+
+
+
+ Approve
+
+
+
+
+ Reject: Insufficient proof
+
+
+
+
+ Reject: Not allowed
+
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
-
-
- Add files to database...
-
-
-
-
- Add to existing entry...
-
-
+
+ Add files to database...
+
+
+ Add to existing entry...
+
@@ -808,12 +809,10 @@ const visibleQuickReplies = computed(() => {
"
class="ml-auto"
>
-
-
-
- {{ formatMessage(commonMessages.editButton) }}
-
-
+
+
+ {{ formatMessage(commonMessages.editButton) }}
+
@@ -835,16 +834,19 @@ const visibleQuickReplies = computed(() => {
/>
-
-
-
-
- {{ formatMessage(messages.removeGroup) }}
-
-
+
+
+
+ {{ formatMessage(messages.removeGroup) }}
+
diff --git a/packages/ui/src/components/flows/creation-flow-modal/components/CustomSetupStage.vue b/packages/ui/src/components/flows/creation-flow-modal/components/CustomSetupStage.vue
index 2d20d1a1a0..9899a8d370 100644
--- a/packages/ui/src/components/flows/creation-flow-modal/components/CustomSetupStage.vue
+++ b/packages/ui/src/components/flows/creation-flow-modal/components/CustomSetupStage.vue
@@ -4,18 +4,14 @@
-
-
-
- {{ formatMessage(messages.selectIcon) }}
-
-
-
-
-
- {{ formatMessage(messages.removeIcon) }}
-
-
+
+
+ {{ formatMessage(messages.selectIcon) }}
+
+
+
+ {{ formatMessage(messages.removeIcon) }}
+
@@ -153,11 +149,11 @@ import { EyeIcon, EyeOffIcon, UploadIcon, XIcon } from '@modrinth/assets'
import { commonMessages, defineMessages, useVIntl } from '@modrinth/ui'
import { computed, onMounted, ref, watch } from 'vue'
+import { Button } from '#ui/components/base/buttons'
import { useDebugLogger } from '#ui/composables/debug-logger'
import { injectFilePicker, injectModrinthClient, injectTags } from '../../../../providers'
import Avatar from '../../../base/Avatar.vue'
-import ButtonStyled from '../../../base/ButtonStyled.vue'
import Chips from '../../../base/Chips.vue'
import Collapsible from '../../../base/Collapsible.vue'
import Combobox, { type ComboboxOption } from '../../../base/Combobox.vue'
diff --git a/packages/ui/src/components/flows/creation-flow-modal/components/ImportInstanceStage.vue b/packages/ui/src/components/flows/creation-flow-modal/components/ImportInstanceStage.vue
index 6351399bd3..3102c9bf78 100644
--- a/packages/ui/src/components/flows/creation-flow-modal/components/ImportInstanceStage.vue
+++ b/packages/ui/src/components/flows/creation-flow-modal/components/ImportInstanceStage.vue
@@ -5,13 +5,14 @@
{{
formatMessage(messages.launcherInstancesTitle)
}}
- {{ formatMessage(messages.clearAll) }}
- {{ formatMessage(messages.clearAll) }}
-
@@ -76,28 +77,22 @@
-
-
- {{ formatMessage(messages.addLauncherPath) }}
-
-
+
+ {{ formatMessage(messages.addLauncherPath) }}
+
-
-
-
-
-
+
+
+
-
-
- {{ formatMessage(messages.add) }}
-
-
+
+ {{ formatMessage(messages.add) }}
+
@@ -108,9 +103,10 @@ import { ChevronRightIcon, FolderSearchIcon, SearchIcon } from '@modrinth/assets
import { defineMessages, useVIntl } from '@modrinth/ui'
import { computed, onMounted, ref, watch } from 'vue'
+import { Button, IconButton } from '#ui/components/base/buttons'
+
import { injectInstanceImport, injectNotificationManager } from '../../../../providers'
import type { ImportableLauncher } from '../../../../providers/instance-import'
-import ButtonStyled from '../../../base/ButtonStyled.vue'
import Checkbox from '../../../base/Checkbox.vue'
import Collapsible from '../../../base/Collapsible.vue'
import StyledInput from '../../../base/StyledInput.vue'
diff --git a/packages/ui/src/components/flows/creation-flow-modal/components/ModpackStage.vue b/packages/ui/src/components/flows/creation-flow-modal/components/ModpackStage.vue
index e0860dd303..8fc5605aa3 100644
--- a/packages/ui/src/components/flows/creation-flow-modal/components/ModpackStage.vue
+++ b/packages/ui/src/components/flows/creation-flow-modal/components/ModpackStage.vue
@@ -30,28 +30,27 @@
-
-
-
- {{ formatMessage(messages.importModpack) }}
-
-
-
-
-
- {{ formatMessage(messages.browseModpacks) }}
-
-
+
+
+ {{ formatMessage(messages.importModpack) }}
+
+
+
+ {{ formatMessage(messages.browseModpacks) }}
+
@@ -61,10 +60,10 @@ import { CompassIcon, ImportIcon, RightArrowIcon } from '@modrinth/assets'
import { commonMessages, defineMessages, useVIntl } from '@modrinth/ui'
import { defineAsyncComponent, h, onMounted, ref, watch } from 'vue'
+import { Button } from '#ui/components/base/buttons'
import { useDebugLogger } from '#ui/composables/debug-logger'
import { injectFilePicker } from '../../../../providers'
-import ButtonStyled from '../../../base/ButtonStyled.vue'
import Combobox from '../../../base/Combobox.vue'
import { injectCreationFlowContext } from '../creation-flow-context'
diff --git a/packages/ui/src/components/modal/ConfirmLeaveModal.vue b/packages/ui/src/components/modal/ConfirmLeaveModal.vue
index cba7b8468c..b49b7c0665 100644
--- a/packages/ui/src/components/modal/ConfirmLeaveModal.vue
+++ b/packages/ui/src/components/modal/ConfirmLeaveModal.vue
@@ -8,18 +8,14 @@
-
-
-
- {{ localizeIfPossible(stayLabel) }}
-
-
-
-
-
- {{ localizeIfPossible(leaveLabel) }}
-
-
+
+
+ {{ localizeIfPossible(stayLabel) }}
+
+
+
+ {{ localizeIfPossible(leaveLabel) }}
+
@@ -30,7 +26,7 @@ import { RightArrowIcon, XIcon } from '@modrinth/assets'
import { ref } from 'vue'
import Admonition from '#ui/components/base/Admonition.vue'
-import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
+import { Button } from '#ui/components/base/buttons'
import { defineMessage, type MessageDescriptor, useVIntl } from '#ui/composables/i18n'
import NewModal from './NewModal.vue'
diff --git a/packages/ui/src/components/modal/ConfirmModal.vue b/packages/ui/src/components/modal/ConfirmModal.vue
index 87a091324e..023daefcda 100644
--- a/packages/ui/src/components/modal/ConfirmModal.vue
+++ b/packages/ui/src/components/modal/ConfirmModal.vue
@@ -1,10 +1,12 @@
-
-
-
-
-
-
+
To confirm you want to proceed, type
- {{ confirmationText }} below:
+ {{ confirmationText }} below:
-
-
-
- Cancel
-
-
-
-
-
- {{ proceedLabel }}
-
-
+
+
+ Cancel
+
+
+
+ {{ proceedLabel }}
+
@@ -53,7 +56,8 @@ import { TrashIcon, XIcon } from '@modrinth/assets'
import { renderString } from '@modrinth/utils'
import { computed, ref } from 'vue'
-import ButtonStyled from '../base/ButtonStyled.vue'
+import { Button } from '#ui/components/base/buttons'
+
import StyledInput from '../base/StyledInput.vue'
import NewModal from './NewModal.vue'
diff --git a/packages/ui/src/components/modal/NewModal.vue b/packages/ui/src/components/modal/NewModal.vue
index 803b831078..c5cb846bcd 100644
--- a/packages/ui/src/components/modal/NewModal.vue
+++ b/packages/ui/src/components/modal/NewModal.vue
@@ -43,33 +43,28 @@
-
-
-
-
-
+
+
+
-
-
-
-
-
+
+
@@ -116,8 +114,10 @@ import { CheckIcon, DownloadIcon, XIcon } from '@modrinth/assets'
import { commonMessages } from '@modrinth/ui'
import { computed, nextTick, onUnmounted, ref } from 'vue'
+import { Button, ButtonLink } from '#ui/components/base/buttons'
+
import { defineMessages, useVIntl } from '../../composables/i18n'
-import { Avatar, ButtonStyled } from '../base'
+import { Avatar } from '../base'
import ServerOnlinePlayers from '../project/server/ServerOnlinePlayers.vue'
import ServerRegion from '../project/server/ServerRegion.vue'
diff --git a/packages/ui/src/components/modal/PhotosensitivityWarningModal.vue b/packages/ui/src/components/modal/PhotosensitivityWarningModal.vue
new file mode 100644
index 0000000000..bd1292b40e
--- /dev/null
+++ b/packages/ui/src/components/modal/PhotosensitivityWarningModal.vue
@@ -0,0 +1,104 @@
+
+
+
+
+ {{ formatMessage(messages.body1) }}
+
+
+ {{ formatMessage(messages.body2) }}
+
+
+ {{ formatMessage(messages.body3) }}
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.iUnderstandButton) }}
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/modal/ShareModal.vue b/packages/ui/src/components/modal/ShareModal.vue
index db9c485c1b..70cf15203c 100644
--- a/packages/ui/src/components/modal/ShareModal.vue
+++ b/packages/ui/src/components/modal/ShareModal.vue
@@ -12,9 +12,10 @@ import {
import QrcodeVue from 'qrcode.vue'
import { computed, nextTick, ref } from 'vue'
+import { ButtonLink, IconButton } from '#ui/components/base/buttons'
import { injectNotificationManager } from '#ui/providers'
-import { ButtonStyled, NewModal, StyledInput } from '../index'
+import { NewModal, StyledInput } from '../index'
const props = defineProps({
header: {
@@ -156,16 +157,15 @@ defineExpose({
-
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
-
-
- Open in new tab
-
-
-
+
+ Open in new tab
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/components/modal/UnknownFileWarningModal.vue b/packages/ui/src/components/modal/UnknownFileWarningModal.vue
index 247ff96c04..43284e5be7 100644
--- a/packages/ui/src/components/modal/UnknownFileWarningModal.vue
+++ b/packages/ui/src/components/modal/UnknownFileWarningModal.vue
@@ -86,17 +86,13 @@
/>
-
-
- {{ formatMessage(messages.installAnyway) }}
-
-
-
-
-
- {{ formatMessage(messages.dontInstall) }}
-
-
+
+ {{ formatMessage(messages.installAnyway) }}
+
+
+
+ {{ formatMessage(messages.dontInstall) }}
+
@@ -106,10 +102,11 @@
import { BanIcon } from '@modrinth/assets'
import { computed, nextTick, ref, useTemplateRef } from 'vue'
+import { Button } from '#ui/components/base/buttons'
+
import { defineMessages, useVIntl } from '../../composables/i18n'
import { useScrollIndicator } from '../../composables/scroll-indicator'
import Admonition from '../base/Admonition.vue'
-import ButtonStyled from '../base/ButtonStyled.vue'
import Checkbox from '../base/Checkbox.vue'
import Table, { type TableColumn } from '../base/Table.vue'
import NewModal from './NewModal.vue'
@@ -167,8 +164,7 @@ const messages = defineMessages({
},
reviewedFiles: {
id: 'unknown-file-warning-modal.reviewed-files',
- defaultMessage:
- 'A file is only reviewed if it’s published to Modrinth, regardless of its file format (including .mrpack).',
+ defaultMessage: "Files that aren't published to Modrinth aren't reviewed.",
},
unrecognizedFiles: {
id: 'unknown-file-warning-modal.unrecognized-files',
diff --git a/packages/ui/src/components/modal/index.ts b/packages/ui/src/components/modal/index.ts
index 4f27f8c31c..76f7171a9b 100644
--- a/packages/ui/src/components/modal/index.ts
+++ b/packages/ui/src/components/modal/index.ts
@@ -3,6 +3,7 @@ export { default as ConfirmModal } from './ConfirmModal.vue'
export { default as NewModal } from './NewModal.vue'
export type { ServerProject as OpenInAppModalServerProject } from './OpenInAppModal.vue'
export { default as OpenInAppModal } from './OpenInAppModal.vue'
+export { default as PhotosensitivityWarningModal } from './PhotosensitivityWarningModal.vue'
export { default as ShareModal } from './ShareModal.vue'
export type { Tab as TabbedModalTab } from './TabbedModal.vue'
export { default as TabbedModal } from './TabbedModal.vue'
diff --git a/packages/ui/src/components/nav/NotificationPanel.vue b/packages/ui/src/components/nav/NotificationPanel.vue
index 95626d907e..0f0a592d53 100644
--- a/packages/ui/src/components/nav/NotificationPanel.vue
+++ b/packages/ui/src/components/nav/NotificationPanel.vue
@@ -59,22 +59,27 @@
x{{ item.count }}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
- {{ button.label }}
-
-
+
+ {{ button.label }}
+
@@ -121,6 +132,7 @@ import {
} from '@modrinth/assets'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
+import { Button, IconButton } from '#ui/components/base/buttons'
import { useModalStack } from '#ui/composables/modal-stack.ts'
import {
@@ -128,7 +140,6 @@ import {
type WebNotification,
type WebNotificationButton,
} from '../../providers'
-import ButtonStyled from '../base/ButtonStyled.vue'
const notificationManager = injectNotificationManager()
const notifications = computed(() => notificationManager.getNotifications())
diff --git a/packages/ui/src/components/nav/PopupNotificationPanel.vue b/packages/ui/src/components/nav/PopupNotificationPanel.vue
index 49c55ccd58..6bc6c9c748 100644
--- a/packages/ui/src/components/nav/PopupNotificationPanel.vue
+++ b/packages/ui/src/components/nav/PopupNotificationPanel.vue
@@ -17,6 +17,7 @@
>
-
+
handleProgressItemAction(progressItem, index)"
+ @action="(index) => handleProgressItemAction(item, progressItem, index)"
/>
-
+
-
-
-
-
-
+
+
+
{{ item.text }}
@@ -142,16 +153,28 @@
full-width
/>
-
-
-
- {{ btn.label }}
-
-
+
+ {{ btn.label }}
+
@@ -171,6 +194,8 @@ import {
} from '@modrinth/assets'
import { computed, ref } from 'vue'
+import { Button, IconButton } from '#ui/components/base/buttons'
+
import { useModalStack } from '../../composables/modal-stack'
import {
injectPopupNotificationManager,
@@ -178,13 +203,12 @@ import {
type PopupNotificationButton,
type PopupNotificationProgressItem,
} from '../../providers'
-import ButtonStyled from '../base/ButtonStyled.vue'
import ProgressBar from '../base/ProgressBar.vue'
import NotificationToast from '../notifications/NotificationToast.vue'
const popupNotificationManager = injectPopupNotificationManager()
const notifications = computed(() =>
- popupNotificationManager.getNotifications(),
+ popupNotificationManager.getVisibleNotifications(),
)
const { stackCount } = useModalStack()
const hasModalActive = computed(() => stackCount.value > 0)
@@ -196,7 +220,6 @@ const activeToastActions = ref>({})
const stopTimer = (n: PopupNotification) => popupNotificationManager.stopNotificationTimer(n)
const setNotificationTimer = (n: PopupNotification) =>
popupNotificationManager.setNotificationTimer(n)
-const dismiss = (id: string | number) => popupNotificationManager.removeNotification(id)
const toastActionLoading = (id: string | number) => activeToastActions.value[String(id)] ?? null
function isDownloadNotification(item: PopupNotification) {
@@ -208,7 +231,7 @@ function isDownloadNotification(item: PopupNotification) {
function downloadToastItems(item: PopupNotification): PopupNotificationProgressItem[] {
if (item.progressItems?.length) {
- return item.progressItems
+ return popupNotificationManager.getVisibleDownloadProgressItems(item)
}
return [
@@ -225,35 +248,32 @@ function downloadToastItems(item: PopupNotification): PopupNotificationProgressI
]
}
-async function handleProgressItemDismiss(
+function handleProgressItemDismiss(
item: PopupNotification,
progressItem: PopupNotificationProgressItem,
) {
- if (progressItem.onDismiss) {
- await progressItem.onDismiss()
- return
- }
-
- dismiss(item.id)
+ popupNotificationManager.hideDownloadItem(item.id, progressItem.id)
}
async function handleProgressItemAction(
+ item: PopupNotification,
progressItem: PopupNotificationProgressItem,
index: number,
) {
const button = progressItem.buttons?.[index]
if (button) {
- await handleProgressItemButtonClick(progressItem, button)
+ await handleProgressItemButtonClick(item, progressItem, button)
}
}
async function handleProgressItemButtonClick(
+ item: PopupNotification,
progressItem: PopupNotificationProgressItem,
btn: PopupNotificationButton,
) {
await btn.action()
if (!btn.keepOpen) {
- await progressItem.onDismiss?.()
+ popupNotificationManager.hideDownloadItem(item.id, progressItem.id)
}
}
@@ -264,6 +284,11 @@ async function handleButtonClick(id: string | number, btn: PopupNotificationButt
}
}
+async function handleNotificationDismiss(item: PopupNotification) {
+ await item.onDismiss?.()
+ popupNotificationManager.removeNotification(item.id)
+}
+
async function handleToastAction(item: PopupNotification, action?: () => void | Promise) {
popupNotificationManager.removeNotification(item.id)
await action?.()
@@ -364,6 +389,21 @@ withDefaults(
.popup-notifs-leave-to {
opacity: 0;
- transform: translateX(100%) scale(0.8);
+ transform: translateX(100%);
+}
+
+.popup-downloads-move {
+ transition: transform 0.3s ease-in-out;
+}
+
+.popup-downloads-leave-active {
+ transition:
+ opacity 0.3s ease-in-out,
+ transform 0.3s ease-in-out;
+}
+
+.popup-downloads-leave-to {
+ opacity: 0;
+ transform: translateX(100%);
}
diff --git a/packages/ui/src/components/notifications/NotificationToast.vue b/packages/ui/src/components/notifications/NotificationToast.vue
index 185fee06d7..82169e0044 100644
--- a/packages/ui/src/components/notifications/NotificationToast.vue
+++ b/packages/ui/src/components/notifications/NotificationToast.vue
@@ -49,31 +49,33 @@
-
-
-
-
-
+
+
+
-
-
-
-
- Accept
-
-
-
-
-
- Decline
-
-
+
+
+
+ Accept
+
+
+
+ Decline
+
@@ -96,16 +98,17 @@
{{ entityLabel }}
-
-
-
-
-
+
+
+
-
- Launch game
-
-
- Instance
-
+ Launch game
+ Instance
{{ progressLabel }}
@@ -145,16 +144,28 @@
v-if="type === 'instance-download' && actions?.length"
class="col-start-1 col-end-3 row-start-3 mt-2 flex min-w-0 flex-wrap items-center gap-2"
>
-
-
-
- {{ action.label }}
-
-
+
+ {{ action.label }}
+
@@ -182,11 +193,12 @@
import { CheckIcon, SpinnerIcon, XIcon } from '@modrinth/assets'
import { computed, ref } from 'vue'
+import { Button, IconButton } from '#ui/components/base/buttons'
+
import { useFormatBytes, useFormatNumber } from '../../composables'
import type { PopupNotificationButton, PopupNotificationProgressType } from '../../providers'
import { truncatedTooltip } from '../../utils/truncate'
import Avatar from '../base/Avatar.vue'
-import ButtonStyled from '../base/ButtonStyled.vue'
type NotificationToastType =
| 'friend-request'
diff --git a/packages/ui/src/components/page/NormalPage.vue b/packages/ui/src/components/page/NormalPage.vue
index ce3f0e1689..3acc18993e 100644
--- a/packages/ui/src/components/page/NormalPage.vue
+++ b/packages/ui/src/components/page/NormalPage.vue
@@ -3,6 +3,7 @@ import { injectPageContext } from '@modrinth/ui'
defineProps<{
sidebar?: 'right' | 'left'
+ fullWidth?: boolean
}>()
const { hierarchicalSidebarAvailable } = injectPageContext()
@@ -12,6 +13,7 @@ const { hierarchicalSidebarAvailable } = injectPageContext()
:class="{
'ui-normal-page--sidebar-left': sidebar === 'left' && !hierarchicalSidebarAvailable,
'ui-normal-page--sidebar-right': sidebar === 'right' && !hierarchicalSidebarAvailable,
+ 'ui-normal-page--full-width': fullWidth,
}"
>
@@ -83,16 +86,16 @@
placeholder="e.g. Secondary allocation"
/>
-
-
-
- Create allocation
-
-
+
+
+ Create allocation
+
@@ -105,30 +108,33 @@
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
@@ -153,16 +159,14 @@
:placeholder="exampleDomain"
/>
-
-
-
- Export
-
-
+
+
+ Export
+
@@ -223,8 +227,9 @@ import {
import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { computed, nextTick, ref } from 'vue'
-import { ButtonStyled, ConfirmModal, NewModal, StyledInput, Table, TagItem } from '#ui/components'
+import { ConfirmModal, NewModal, StyledInput, Table, TagItem } from '#ui/components'
import type { TableColumn } from '#ui/components/base'
+import { Button, IconButton } from '#ui/components/base/buttons'
import { useServerPermissions } from '#ui/composables/server-permissions'
import {
injectModrinthClient,
diff --git a/packages/ui/src/layouts/shared/user-profile/components/edit-user-modal.vue b/packages/ui/src/layouts/shared/user-profile/components/edit-user-modal.vue
new file mode 100644
index 0000000000..64e3e27043
--- /dev/null
+++ b/packages/ui/src/layouts/shared/user-profile/components/edit-user-modal.vue
@@ -0,0 +1,310 @@
+
+
+
+
+
Profile picture
+
+
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.removeImageButton) }}
+
+
+
+ {{ formatMessage(commonMessages.resetButton) }}
+
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.usernameLabel) }}
+
+
+
+
+ {{ form.username.length }}/39
+
+
+
+
+
+
Bio
+
+
+ {{ form.bio.length }}/160
+
+
+
+
+ Role
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+
+ {{ formatMessage(commonMessages.savingButton) }}
+
+
+
+ {{ formatMessage(commonMessages.saveChangesButton) }}
+
+
+
+
+
+
+
+
diff --git a/packages/ui/src/layouts/shared/user-profile/layout.vue b/packages/ui/src/layouts/shared/user-profile/layout.vue
index 9c3b008a6b..8ffe648c35 100644
--- a/packages/ui/src/layouts/shared/user-profile/layout.vue
+++ b/packages/ui/src/layouts/shared/user-profile/layout.vue
@@ -13,60 +13,31 @@
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
-
-
- {{ formatMessage(messages.blockButton) }}
-
-
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+
+ {{ formatMessage(messages.blockButton) }}
+
-
-
-
-
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
-
-
- {{ formatMessage(messages.savingLabel) }}
-
-
-
- {{ formatMessage(commonMessages.saveChangesButton) }}
-
-
-
-
-
-
+
-
+
@@ -284,7 +255,11 @@
}"
:layout="displayMode === 'list' ? 'list' : 'grid'"
:status="project.status"
- />
+ >
+
+
+
+
-
-
- {{ formatMessage(messages.createProjectButton) }}
-
-
+
+ {{ formatMessage(messages.createProjectButton) }}
+
@@ -380,11 +353,9 @@
"
>
-
-
- {{ formatMessage(messages.createCollectionButton) }}
-
-
+
+ {{ formatMessage(messages.createCollectionButton) }}
+
@@ -437,11 +408,9 @@
:description="formatMessage(messages.userLoadErrorDescription)"
>
-
-
- {{ formatMessage(commonMessages.retryButton) }}
-
-
+
+ {{ formatMessage(commonMessages.retryButton) }}
+
@@ -457,7 +426,6 @@ import {
LibraryIcon,
LinkIcon,
LockIcon,
- SaveIcon,
SpinnerIcon,
XIcon,
} from '@modrinth/assets'
@@ -473,8 +441,7 @@ import { useRoute, useRouter } from 'vue-router'
import Admonition from '#ui/components/base/Admonition.vue'
import AutoLink from '#ui/components/base/AutoLink.vue'
import Avatar from '#ui/components/base/Avatar.vue'
-import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
-import Combobox from '#ui/components/base/Combobox.vue'
+import { Button } from '#ui/components/base/buttons'
import EmptyState from '#ui/components/base/EmptyState.vue'
import IntlFormatted from '#ui/components/base/IntlFormatted.vue'
import NavTabs from '#ui/components/base/NavTabs.vue'
@@ -493,8 +460,9 @@ import {
injectPageContext,
injectTags,
} from '#ui/providers'
-import { commonMessages, getProjectTypeTitleMessage } from '#ui/utils'
+import { commonMessages, getProjectTypeTitleMessage, sortProjectTypes } from '#ui/utils'
+import EditUserModal from './components/edit-user-modal.vue'
import { blockedUsersQueryKey, injectUserProfile } from './providers'
import {
hasActivePride26Midas,
@@ -568,18 +536,6 @@ const messages = defineMessages({
id: 'profile.collection.projects-count',
defaultMessage: '{count, plural, one {# project} other {# projects}}',
},
- savingLabel: {
- id: 'profile.label.saving',
- defaultMessage: 'Saving...',
- },
- editRoleButton: {
- id: 'profile.button.edit-role',
- defaultMessage: 'Edit role',
- },
- selectRolePlaceholder: {
- id: 'profile.role.select-placeholder',
- defaultMessage: 'Select a role',
- },
userDetailsTitle: {
id: 'profile.details.title',
defaultMessage: 'User details',
@@ -689,14 +645,6 @@ const messages = defineMessages({
defaultMessage:
'The official user account of Modrinth. Get support at or via email at ',
},
- roleUpdateErrorTitle: {
- id: 'profile.role.update-error-title',
- defaultMessage: 'Failed to update role',
- },
- roleUpdateErrorDescription: {
- id: 'profile.role.update-error-description',
- defaultMessage: 'An error occurred while updating the user role. Please try again.',
- },
blockButton: {
id: 'profile.button.block',
defaultMessage: 'Block',
@@ -837,7 +785,7 @@ const projectTypes = computed(() => {
const types = new Set(projects.value.map((project) => project.resolvedProjectType))
if (collections.value.length > 0) types.add('collection')
types.delete('project')
- return [...types]
+ return sortProjectTypes(types)
})
const navLinks = computed(() => {
@@ -848,15 +796,13 @@ const navLinks = computed(() => {
label: formatMessage(commonMessages.allProjectType),
href: profilePath,
},
- ...projectTypes.value
- .map((projectType) => ({
- label:
- projectType === 'collection'
- ? formatMessage(messages.collectionsLabel)
- : formatMessage(getProjectTypeTitleMessage(projectType), { count: 2 }),
- href: `${profilePath}/${projectType}s`,
- }))
- .sort((first, second) => first.label.localeCompare(second.label)),
+ ...projectTypes.value.map((projectType) => ({
+ label:
+ projectType === 'collection'
+ ? formatMessage(messages.collectionsLabel)
+ : formatMessage(getProjectTypeTitleMessage(projectType), { count: 2 }),
+ href: `${profilePath}/${projectType}s`,
+ })),
]
})
@@ -1042,35 +988,15 @@ async function retryQueries(): Promise {
}
const userDetailsModal = ref(null)
-const editRoleModal = ref(null)
+const editUserModal = ref | null>(null)
const blockUserModal = ref(null)
-const selectedRole = ref(null)
-const isSavingRole = ref(false)
const isBlockingUser = ref(false)
const isUnblockingUser = ref(false)
-const roleOptions = [
- { value: 'developer', label: 'Developer' },
- { value: 'moderator', label: 'Moderator' },
- { value: 'admin', label: 'Admin' },
-] satisfies { value: Labrinth.Users.v3.Role; label: string }[]
-
-watch(
- user,
- (currentUser) => {
- selectedRole.value = currentUser?.role ?? null
- },
- { immediate: true },
-)
function openUserDetails(): void {
userDetailsModal.value?.show()
}
-function openRoleEditModal(): void {
- selectedRole.value = user.value?.role ?? null
- editRoleModal.value?.show()
-}
-
async function handleBlockAction(): Promise {
if (!auth.user.value) {
await auth.requestSignIn(route.fullPath)
@@ -1147,11 +1073,6 @@ async function unblockCurrentUser(): Promise {
}
}
-function cancelRoleEdit(): void {
- selectedRole.value = user.value?.role ?? null
- editRoleModal.value?.hide()
-}
-
async function toggleAffiliate(): Promise {
if (!user.value) return
await userProfile.patchUser(user.value.id, {
@@ -1159,23 +1080,4 @@ async function toggleAffiliate(): Promise {
})
await queryClient.invalidateQueries({ queryKey: ['user', props.userId] })
}
-
-async function saveRoleEdit(): Promise {
- if (!user.value || !selectedRole.value || selectedRole.value === user.value.role) return
-
- isSavingRole.value = true
- try {
- await userProfile.patchUser(user.value.id, { role: selectedRole.value })
- await queryClient.invalidateQueries({ queryKey: ['user', props.userId] })
- editRoleModal.value?.hide()
- } catch {
- notificationManager.addNotification({
- type: 'error',
- title: formatMessage(messages.roleUpdateErrorTitle),
- text: formatMessage(messages.roleUpdateErrorDescription),
- })
- } finally {
- isSavingRole.value = false
- }
-}
diff --git a/packages/ui/src/layouts/shared/user-profile/providers/user-profile.ts b/packages/ui/src/layouts/shared/user-profile/providers/user-profile.ts
index 6314ece5c6..58270661bd 100644
--- a/packages/ui/src/layouts/shared/user-profile/providers/user-profile.ts
+++ b/packages/ui/src/layouts/shared/user-profile/providers/user-profile.ts
@@ -9,8 +9,10 @@ export interface UserProfileContext {
getCollections: (userId: string) => Promise
patchUser: (
userId: string,
- patch: Partial>,
+ patch: Partial>,
) => Promise
+ changeAvatar: (userId: string, file: Blob, extension: string) => Promise
+ deleteAvatar: (userId: string) => Promise
getBlockedUsers: () => Promise
blockUser: (userId: string) => Promise
unblockUser: (userId: string) => Promise
diff --git a/packages/ui/src/layouts/wrapped/AccountProfileSettings.vue b/packages/ui/src/layouts/wrapped/AccountProfileSettings.vue
index 1cd295cdcc..f38537a444 100644
--- a/packages/ui/src/layouts/wrapped/AccountProfileSettings.vue
+++ b/packages/ui/src/layouts/wrapped/AccountProfileSettings.vue
@@ -15,12 +15,10 @@
-
-
-
- {{ formatMessage(commonMessages.signInButton) }}
-
-
+
+
+ {{ formatMessage(commonMessages.signInButton) }}
+
@@ -56,30 +54,33 @@
-
-
-
-
-
-
-
-
- {{ formatMessage(commonMessages.removeImageButton) }}
-
-
-
-
-
- {{ formatMessage(commonMessages.resetButton) }}
-
-
+
+
+
+
+
+ {{ formatMessage(commonMessages.removeImageButton) }}
+
+
+
+ {{ formatMessage(commonMessages.resetButton) }}
+
@@ -135,9 +136,8 @@ import { computed, onBeforeUnmount, ref, shallowRef, watch } from 'vue'
import { RouterLink } from 'vue-router'
import Avatar from '#ui/components/base/Avatar.vue'
-import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
+import { Button, FileButton } from '#ui/components/base/buttons'
import EmptyState from '#ui/components/base/EmptyState.vue'
-import FileInput from '#ui/components/base/FileInput.vue'
import IntlFormatted from '#ui/components/base/IntlFormatted.vue'
import StyledInput from '#ui/components/base/StyledInput.vue'
import { defineMessages, useVIntl } from '#ui/composables'
diff --git a/packages/ui/src/layouts/wrapped/AccountSocialSettings.vue b/packages/ui/src/layouts/wrapped/AccountSocialSettings.vue
index 6d2f4f5d8c..240744fa31 100644
--- a/packages/ui/src/layouts/wrapped/AccountSocialSettings.vue
+++ b/packages/ui/src/layouts/wrapped/AccountSocialSettings.vue
@@ -15,12 +15,10 @@
-
-
-
- {{ formatMessage(commonMessages.signInButton) }}
-
-
+
+
+ {{ formatMessage(commonMessages.signInButton) }}
+
@@ -112,11 +110,9 @@
{{ formatMessage(messages.loadError) }}
-
-
- {{ formatMessage(commonMessages.retryButton) }}
-
-
+
+ {{ formatMessage(commonMessages.retryButton) }}
+
{{ formatMessage(messages.noBlockedUsers) }}
@@ -145,25 +141,24 @@
-
-
-
- {{ formatMessage(messages.unblockButton) }}
-
-
+
+
+ {{ formatMessage(messages.unblockButton) }}
+
@@ -195,7 +190,7 @@ import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { computed, ref } from 'vue'
import Avatar from '#ui/components/base/Avatar.vue'
-import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
+import { Button } from '#ui/components/base/buttons'
import Chips from '#ui/components/base/Chips.vue'
import EmptyState from '#ui/components/base/EmptyState.vue'
import Table, { type TableColumn } from '#ui/components/base/Table.vue'
diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/[id]/access/access.vue b/packages/ui/src/layouts/wrapped/hosting/manage/[id]/access/access.vue
index 96cc63944a..b85f8d8fe3 100644
--- a/packages/ui/src/layouts/wrapped/hosting/manage/[id]/access/access.vue
+++ b/packages/ui/src/layouts/wrapped/hosting/manage/[id]/access/access.vue
@@ -14,23 +14,25 @@
v-model="roleFilter"
:options="roleFilterOptions"
:display-value="selectedRoleFilterLabel"
- trigger-class="min-w-[225px] !h-10 !min-h-10 !py-0"
+ trigger-size="lg"
+ trigger-class="min-w-[225px]"
>
-
-
-
- {{ formatMessage(messages.inviteFriends) }}
-
-
+
+
+ {{ formatMessage(messages.inviteFriends) }}
+
@@ -113,7 +115,7 @@ import { FilterIcon, SearchIcon, UserPlusIcon } from '@modrinth/assets'
import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { computed, ref, watch } from 'vue'
-import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
+import { Button } from '#ui/components/base/buttons'
import Combobox, { type ComboboxOption } from '#ui/components/base/Combobox.vue'
import DropdownFilterBar from '#ui/components/base/DropdownFilterBar.vue'
import StyledInput from '#ui/components/base/StyledInput.vue'
diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/[id]/onboarding.vue b/packages/ui/src/layouts/wrapped/hosting/manage/[id]/onboarding.vue
index bcdebf6392..f231ba7956 100644
--- a/packages/ui/src/layouts/wrapped/hosting/manage/[id]/onboarding.vue
+++ b/packages/ui/src/layouts/wrapped/hosting/manage/[id]/onboarding.vue
@@ -42,22 +42,22 @@
-
-
-
- {{ formatMessage(messages.uploadingProgress, { percent: uploadPercent }) }}
-
-
-
-
- {{ formatMessage(messages.setupServerButton) }}
-
-
+
+
+ {{ formatMessage(messages.uploadingProgress, { percent: uploadPercent }) }}
+
+
+ {{ formatMessage(messages.setupServerButton) }}
+
{{ error.message }}
-
- Retry
-
+ Retry
@@ -71,16 +71,16 @@
{{ formatMessage(commonMessages.allProjectType) }}
-
-
-
- {{ formatMessage(messages.createBackup) }}
-
-
+
+
+ {{ formatMessage(messages.createBackup) }}
+
@@ -95,17 +95,17 @@
:description="formatMessage(messages.emptyDescription)"
>
-
-
-
- {{ formatMessage(messages.createBackup) }}
-
-
+
+
+ {{ formatMessage(messages.createBackup) }}
+
-
-
- {{ formatMessage(messages.clearFilters) }}
-
-
+
+ {{ formatMessage(messages.clearFilters) }}
+
@@ -198,30 +196,30 @@
}}
-
-
- {{ formatMessage(commonMessages.clearButton) }}
-
-
+
+ {{ formatMessage(commonMessages.clearButton) }}
+
-
-
-
- {{ formatMessage(commonMessages.deleteLabel) }}
-
-
+
+
+ {{ formatMessage(commonMessages.deleteLabel) }}
+
@@ -236,7 +234,9 @@
role="progressbar"
:aria-valuemin="0"
:aria-valuemax="bulkTotal"
- style="box-shadow: 0px -2px 4px 0px rgba(27, 217, 106, 0.1)"
+ style="
+ box-shadow: 0px -2px 4px 0px color-mix(in srgb, var(--color-brand) 10%, transparent);
+ "
/>
@@ -273,7 +273,7 @@ import type { Component } from 'vue'
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
-import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
+import { Button } from '#ui/components/base/buttons'
import Checkbox from '#ui/components/base/Checkbox.vue'
import EmptyState from '#ui/components/base/EmptyState.vue'
import FilterPills, { type FilterPillOption } from '#ui/components/base/FilterPills.vue'
diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/content.vue b/packages/ui/src/layouts/wrapped/hosting/manage/content.vue
index bcfd4afc38..a08df7dd64 100644
--- a/packages/ui/src/layouts/wrapped/hosting/manage/content.vue
+++ b/packages/ui/src/layouts/wrapped/hosting/manage/content.vue
@@ -33,19 +33,15 @@ import {
getStoredServerAddonInstallQueue,
getTargetInstallPreferences,
} from '../../../shared/browse-tab/composables/install-logic'
+import ManagedContentModal from '../../../shared/content-tab/components/managed-content-modal/index.vue'
import ConfirmModpackUpdateModal from '../../../shared/content-tab/components/modals/ConfirmModpackUpdateModal.vue'
import ConfirmUnlinkModal from '../../../shared/content-tab/components/modals/ConfirmUnlinkModal.vue'
import ContentUpdaterModal from '../../../shared/content-tab/components/modals/content-updater-modal/index.vue'
-import ModpackContentModal from '../../../shared/content-tab/components/modals/ModpackContentModal.vue'
import ContentPageLayout from '../../../shared/content-tab/layout.vue'
-import type { ContentModpackData } from '../../../shared/content-tab/providers/content-manager'
+import type { ManagedContentData } from '../../../shared/content-tab/providers/content-manager'
import { provideContentManager } from '../../../shared/content-tab/providers/content-manager'
-import type {
- ContentItem,
- ContentModpackCardCategory,
- ContentModpackCardProject,
- ContentModpackCardVersion,
-} from '../../../shared/content-tab/types'
+import type { ContentItem } from '../../../shared/content-tab/types'
+import { summarizeManagedContent } from '../../../shared/content-tab/utils/managed-content'
type AddonWithUiState = Archon.Content.v1.Addon & { installing?: boolean }
type ContentOwnerAvatarSource = {
@@ -65,6 +61,10 @@ const props = withDefaults(
const { formatMessage } = useVIntl()
const messages = defineMessages({
+ modpackContent: {
+ id: 'hosting.content.managed-content.modpack-header',
+ defaultMessage: 'Modpack content',
+ },
failedToRemoveContent: {
id: 'hosting.content.failed-to-remove',
defaultMessage: 'Failed to remove content',
@@ -172,19 +172,21 @@ const modpackContentQuery = useQuery({
})
const setupActionDisabled = computed(() => !canSetup.value || busyReasons.value.length > 0)
-const setupActionBusyMessage = computed(() => {
- if (!canSetup.value) return permissionDeniedMessage.value
-
- const bannerCoversInstalling =
+const isInstallingContent = computed(
+ () =>
server.value?.status === 'installing' ||
isSyncingContent.value ||
busyReasons.value.some(
(r) =>
r.reason.id === 'servers.busy.installing' || r.reason.id === 'servers.busy.syncing-content',
- )
+ ),
+)
+const setupActionBusyMessage = computed(() => {
+ if (!canSetup.value) return permissionDeniedMessage.value
+
const filteredReasons = busyReasons.value.filter((r) => {
if (
- bannerCoversInstalling &&
+ isInstallingContent.value &&
(r.reason.id === 'servers.busy.installing' || r.reason.id === 'servers.busy.syncing-content')
)
return false
@@ -256,54 +258,38 @@ const newestModpackUpdateVersion = computed(() => {
)
})
-const modpack = computed(() => {
+const managedContent = computed(() => {
const mp = contentQuery.data.value?.modpack
if (!mp) return null
const isLocal = mp.spec.platform === 'local_file'
const project = projectQuery.data.value
const projectId = isLocal ? null : mp.spec.project_id
- return {
- project: {
- id: projectId ?? mp.title ?? '',
- slug: project?.slug ?? projectId ?? '',
- title: mp.title ?? (isLocal ? mp.spec.name : projectId) ?? '',
- icon_url: mp.icon_url ?? undefined,
- description: mp.description ?? '',
- downloads: mp.downloads,
- followers: mp.followers,
- filename: isLocal ? mp.spec.filename : undefined,
- } as ContentModpackCardProject,
- projectLink: projectId ? `/project/${project?.slug ?? projectId}` : undefined,
- version: isLocal
+ const addons = modpackContentQuery.data.value?.addons
+ const summary = addons
+ ? summarizeManagedContent(addons.map(addonToContentItem))
+ : modpackContentQuery.isLoading.value
? undefined
- : ({
- id: mp.spec.version_id,
- version_number: mp.version_number ?? '',
- date_published: mp.date_published ?? '',
- } as ContentModpackCardVersion),
- versionLink:
- projectId && !isLocal
- ? `/project/${project?.slug ?? projectId}/version/${mp.spec.version_id}`
- : undefined,
- owner: mp.owner
- ? {
- id: mp.owner.id,
- name: mp.owner.name,
- type: mp.owner.type,
- avatar_url: getContentOwnerAvatarUrl(mp.owner),
- link:
- mp.owner.type === 'organization'
- ? `/organization/${mp.owner.id}`
- : `/user/${mp.owner.id}`,
- }
- : undefined,
- categories: (project?.categories ?? []).map((name) => ({
- name,
- icon: name,
- project_type: 'modpack',
- header: 'categories',
- })) as ContentModpackCardCategory[],
- hasUpdate: !!mp.has_update || !!newestModpackUpdateVersion.value,
+ : []
+ const title = isLocal
+ ? (mp.title ?? mp.spec.name)
+ : (project?.title ?? mp.title ?? projectId ?? '')
+ return {
+ card: {
+ kind: 'modpack',
+ installing: isInstallingContent.value,
+ manager: {
+ name: title,
+ iconUrl: (isLocal ? mp.icon_url : (project?.icon_url ?? mp.icon_url)) ?? undefined,
+ link: projectId ? `/project/${project?.slug ?? projectId}` : undefined,
+ },
+ summary,
+ versionNumber: isLocal ? undefined : (mp.version_number ?? undefined),
+ versionLink:
+ projectId && mp.spec.platform === 'modrinth'
+ ? `/project/${project?.slug ?? projectId}/version/${mp.spec.version_id}`
+ : undefined,
+ updatedAt: isLocal ? undefined : (mp.date_published ?? undefined),
+ },
}
})
@@ -329,6 +315,31 @@ const addonLookup = computed(() => {
})
const pendingServerContentInstalls = ref([])
+const projectMetadataBatchSize = 800
+const contentProjectIds = computed(() =>
+ [...(contentQuery.data.value?.addons ?? []), ...modpackAddons.value]
+ .map((addon) => addon.project_id)
+ .concat(pendingServerContentInstalls.value.map((item) => item.projectId))
+ .filter((id): id is string => !!id)
+ .filter((id, index, ids) => ids.indexOf(id) === index)
+ .sort(),
+)
+const contentProjectsQuery = useQuery({
+ queryKey: computed(() => ['labrinth', 'projects', 'v2', contentProjectIds.value]),
+ queryFn: async () => {
+ const batches = []
+ for (let index = 0; index < contentProjectIds.value.length; index += projectMetadataBatchSize) {
+ batches.push(contentProjectIds.value.slice(index, index + projectMetadataBatchSize))
+ }
+ return (
+ await Promise.all(batches.map((ids) => client.labrinth.projects_v2.getMultiple(ids)))
+ ).flat()
+ },
+ enabled: computed(() => contentProjectIds.value.length > 0),
+})
+const contentProjectsById = computed(
+ () => new Map((contentProjectsQuery.data.value ?? []).map((project) => [project.id, project])),
+)
const lastStableContentKeys = ref>(new Set())
const contentInstallBaselineKeys = ref | null>(null)
const contentInstallAddedKeys = ref>(new Set())
@@ -506,12 +517,14 @@ async function flushStoredServerInstalls() {
}
function pendingInstallToContentItem(item: PendingServerContentInstall): ContentItem {
+ const projectMetadata = contentProjectsById.value.get(item.projectId)
return {
project: {
+ ...(projectMetadata ?? {}),
id: item.projectId,
- slug: item.slug ?? item.projectId,
- title: item.title,
- icon_url: item.iconUrl ?? undefined,
+ slug: item.slug ?? projectMetadata?.slug ?? item.projectId,
+ title: projectMetadata?.title ?? item.title,
+ icon_url: item.iconUrl ?? projectMetadata?.icon_url ?? undefined,
},
version: {
id: item.versionId,
@@ -854,7 +867,7 @@ async function handleBulkDisable(items: ContentItem[]) {
}
const modpackUnlinkModal = ref>()
-const modpackContentModal = ref>()
+const modpackContentModal = ref>()
const contentUpdaterModal = ref>()
const updatingProject = ref(null)
@@ -1002,12 +1015,16 @@ function handleUnknownFileContinue(dontShowAgain: boolean) {
}
function addonToContentItem(addon: AddonWithUiState): ContentItem {
+ const projectMetadata = addon.project_id
+ ? contentProjectsById.value.get(addon.project_id)
+ : undefined
return {
project: {
+ ...(projectMetadata ?? {}),
id: addon.project_id ?? addon.filename,
- slug: addon.project_id ?? addon.filename,
- title: friendlyAddonName(addon),
- icon_url: addon.icon_url ?? undefined,
+ slug: projectMetadata?.slug ?? addon.project_id ?? addon.filename,
+ title: projectMetadata?.title ?? friendlyAddonName(addon),
+ icon_url: addon.icon_url ?? projectMetadata?.icon_url ?? undefined,
},
version: {
id: addon.version?.id ?? addon.filename,
@@ -1378,7 +1395,7 @@ provideContentManager({
items: contentItems,
loading: computed(() => contentQuery.isLoading.value),
error: computed(() => contentQuery.error.value ?? null),
- modpack,
+ managedContent,
isPackLocked: ref(false),
isBusy: setupActionDisabled,
busyMessage: setupActionBusyMessage,
@@ -1396,13 +1413,14 @@ provideContentManager({
browse: handleBrowseContent,
uploadFiles: handleUploadFiles,
deletionContext: 'server',
+ showEnvironmentWarnings: true,
hasUpdateSupport: true,
updateItem: handleUpdateItem,
bulkUpdateItems: handleBulkUpdate,
- updateModpack: handleModpackUpdate,
- viewModpackContent: handleViewModpackContent,
+ runManagedContentPrimaryAction: handleModpackUpdate,
+ viewManagedContent: handleViewModpackContent,
unlinkModpack: handleModpackUnlink,
- openSettings: () => openServerSettings({ tabId: 'installation' }),
+ openManagedContentSettings: () => openServerSettings({ tabId: 'installation' }),
switchVersion: handleSwitchVersion,
getOverflowOptions,
getItemId: getContentItemId,
@@ -1423,6 +1441,7 @@ provideContentManager({
owner: item.owner
? { ...item.owner, link: item.owner.link ?? `/${item.owner.type}/${item.owner.id}` }
: undefined,
+ external: item.external ?? !hasModrinthProject,
enabled: item.enabled,
}
},
@@ -1448,11 +1467,13 @@ provideContentManager({
:action-disabled-tooltip="setupActionBusyMessage ?? undefined"
@unlink="handleModpackUnlinkConfirm"
/>
-
-
- {{
- formatMessage(messages.contactSupportButton)
- }}
-
- router.go(0)">
- {{ formatMessage(messages.reloadButton) }}
-
+ {{ formatMessage(messages.contactSupportButton) }}
+ router.go(0)">{{
+ formatMessage(messages.reloadButton)
+ }}
@@ -106,12 +109,10 @@
:placeholder="formatMessage(messages.searchPlaceholder, { count: filteredData.length })"
wrapper-class="w-full md:w-72"
/>
-
-
-
- {{ formatMessage(messages.newServerButton) }}
-
-
+
+
+ {{ formatMessage(messages.newServerButton) }}
+
@@ -231,8 +232,6 @@
import type { Archon, Labrinth } from '@modrinth/api-client'
import { HammerIcon, LoaderCircleIcon, PlusIcon, SearchIcon } from '@modrinth/assets'
import {
- AutoLink,
- ButtonStyled,
CopyCode,
defineMessages,
injectAuth,
@@ -255,6 +254,7 @@ import type Stripe from 'stripe'
import { type ComponentPublicInstance, computed, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
+import { Button, ButtonLink } from '#ui/components/base/buttons'
import ServersUpgradeModalWrapper from '#ui/components/billing/ServersUpgradeModalWrapper.vue'
import type { ServerListingOwner } from '#ui/components/servers/access'
import MedalServerListing from '#ui/components/servers/marketing/MedalServerListing.vue'
diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/root.vue b/packages/ui/src/layouts/wrapped/hosting/manage/root.vue
index c781570242..978b6b6c49 100644
--- a/packages/ui/src/layouts/wrapped/hosting/manage/root.vue
+++ b/packages/ui/src/layouts/wrapped/hosting/manage/root.vue
@@ -142,8 +142,8 @@
{{ formatLoaderLabel(serverData.loader) }} {{ serverData.mc_version }}
@@ -181,31 +181,30 @@
:auto-hide="false"
placement="bottom-end"
>
-
-
-
-
-
+
+
+
{{ formatMessage(settingsHintMessages.title) }}
-
-
-
-
-
+
+
+
{{ formatMessage(settingsHintMessages.description) }}
@@ -213,15 +212,15 @@
-
-
-
-
-
+
+
+
@@ -284,13 +283,11 @@
If you're stuck, please contact Modrinth Support with the information below:
-
-
-
-
- Copy Debug Info
-
-
+
+
+
+ Copy Debug Info
+
An internal error occurred while installing your server. Don't fret — try
@@ -310,25 +307,23 @@
v-if="errorTitle === 'Installation error'"
class="mt-2 flex flex-col gap-4 sm:flex-row"
>
-
- Open Installation Log
-
-
-
-
-
- Copy Debug Info
-
-
-
-
-
- Change Loader
-
-
+ Open Installation Log
+
+
+
+ Copy Debug Info
+
+
+
+ Change Loader
+
@@ -430,7 +425,7 @@ import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, watch
import { onBeforeRouteLeave, useRoute, useRouter } from 'vue-router'
import Avatar from '#ui/components/base/Avatar.vue'
-import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
+import { Button, IconButton, TeleportOverflowMenu } from '#ui/components/base/buttons'
import ErrorInformationCard from '#ui/components/base/ErrorInformationCard.vue'
import NavTabs from '#ui/components/base/NavTabs.vue'
import PageHeader from '#ui/components/base/page-header/index.vue'
@@ -438,10 +433,9 @@ import PageHeaderMetadata from '#ui/components/base/page-header/metadata/index.v
import PageHeaderMetadataItem from '#ui/components/base/page-header/metadata/page-header-metadata-item.vue'
import PageHeaderActions from '#ui/components/base/page-header/page-header-actions.vue'
import ServerNotice from '#ui/components/base/ServerNotice.vue'
-import TeleportOverflowMenu from '#ui/components/base/TeleportOverflowMenu.vue'
+import TagIcon from '#ui/components/base/TagIcon.vue'
import ConfirmLeaveModal from '#ui/components/modal/ConfirmLeaveModal.vue'
import ServerPanelAdmonitions from '#ui/components/servers/admonitions/ServerPanelAdmonitions.vue'
-import LoaderIcon from '#ui/components/servers/icons/LoaderIcon.vue'
import ServerIcon from '#ui/components/servers/icons/ServerIcon.vue'
import MedalServerCountdown from '#ui/components/servers/marketing/MedalServerCountdown.vue'
import { PanelServerActionButton } from '#ui/components/servers/server-header'
diff --git a/packages/ui/src/locales/cs-CZ/index.json b/packages/ui/src/locales/cs-CZ/index.json
index 3ca7ba4115..be61453f5d 100644
--- a/packages/ui/src/locales/cs-CZ/index.json
+++ b/packages/ui/src/locales/cs-CZ/index.json
@@ -548,18 +548,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Názvy projektů"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Abecedně"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Od nejnovějších"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Od nejstarších"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Seřadit {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Aktualizovat vše"
},
@@ -1130,9 +1118,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Soubor uložen"
},
- "files.editor.find-close": {
- "defaultMessage": "Zavřít"
- },
"files.editor.find-in-file": {
"defaultMessage": "Najít"
},
@@ -1835,18 +1820,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Vybrat ikonu"
},
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Nebyl nalezen obsah"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Obsah modpacku"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Načítání obsahu..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Žádné projekty neodpovídají tvému vyhledávání."
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Mometálně"
},
diff --git a/packages/ui/src/locales/da-DK/index.json b/packages/ui/src/locales/da-DK/index.json
index 3277f89162..257dba321b 100644
--- a/packages/ui/src/locales/da-DK/index.json
+++ b/packages/ui/src/locales/da-DK/index.json
@@ -161,6 +161,9 @@
"button.enable": {
"defaultMessage": "Aktiver"
},
+ "button.extract": {
+ "defaultMessage": "Pak ud"
+ },
"button.follow": {
"defaultMessage": "Følg"
},
@@ -272,12 +275,24 @@
"changelog.product.hosting": {
"defaultMessage": "Hosting"
},
+ "changelog.product.web": {
+ "defaultMessage": "Platform"
+ },
"collection-widget.loading-projects": {
"defaultMessage": "Indlæser projekter..."
},
+ "collection-widget.search-placeholder": {
+ "defaultMessage": "Søg efter projekter"
+ },
"collections.label.private": {
"defaultMessage": "Privat"
},
+ "content-type.content.lowercase": {
+ "defaultMessage": "indhold"
+ },
+ "content-type.item.lowercase": {
+ "defaultMessage": "{count, plural, one {genstand} other {genstande}}"
+ },
"content.card.select-project": {
"defaultMessage": "Vælg {project}"
},
@@ -380,12 +395,6 @@
"content.page-layout.share.label": {
"defaultMessage": "Del"
},
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Ældst først"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sorter efter {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Opdater alle"
},
@@ -542,9 +551,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Fil gemt"
},
- "files.editor.find-close": {
- "defaultMessage": "Luk"
- },
"files.editor.find-in-file": {
"defaultMessage": "Find"
},
@@ -794,9 +800,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Vælg ikon"
},
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Ekstern"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Nuværrende"
},
diff --git a/packages/ui/src/locales/de-CH/index.json b/packages/ui/src/locales/de-CH/index.json
index bb3ed6010b..6999a0c627 100644
--- a/packages/ui/src/locales/de-CH/index.json
+++ b/packages/ui/src/locales/de-CH/index.json
@@ -617,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Projektnamen"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alphabetisch"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Neuste zuerst"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Älteste zuerst"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sortieren nach {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Alle aktualisieren"
},
@@ -1301,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Datei gespeichert"
},
- "files.editor.find-close": {
- "defaultMessage": "Schliessen"
- },
"files.editor.find-in-file": {
"defaultMessage": "Finden"
},
@@ -2081,33 +2066,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Icon auswählen"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Dieses Modpack enthält keine zusätzlichen inhalte."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Keine Inhalte gefunden"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Extern"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "Diese Datei ist nicht auf Modrinth veröffentlicht."
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Modpack Inhalt"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Lade Inhalte..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Keine Projekte entsprechen deiner Suche."
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "In Slicer öffnen"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Durchsuche {count, number} {count, plural, one {Projekt} other {Projekte}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Aktuell"
},
@@ -2240,6 +2198,9 @@
"label.details": {
"defaultMessage": "Details"
},
+ "label.discover-content": {
+ "defaultMessage": "Inhalte erkunden"
+ },
"label.done": {
"defaultMessage": "Fertig"
},
@@ -2318,6 +2279,9 @@
"label.password": {
"defaultMessage": "Passwort"
},
+ "label.permissions": {
+ "defaultMessage": "Berechtigungen"
+ },
"label.plan-custom": {
"defaultMessage": "Benutzerdefiniert"
},
@@ -2849,9 +2813,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Ein Modrinth-Ersteller."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Ein Modrinth-Nutzer."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} wird dir keine Freundschaftsanfragen mehr senden können, dich nicht zu geteilten Instanzen einladen können und dich nicht mehr zu Modrinth-Hosting Servern einladen können."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Bist du dir sicher, dass du diesen Nutzer blockieren willst?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Beim Blockieren dieses Nutzers ist ein Fehler aufgetreten. Bitte versuche es erneut."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Blockierung fehlgeschlagen"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} wurde blockiert."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Nutzer blockiert"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Blockiere {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Benutzeranalysen anzeigen"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Benutzerabrechnung verwalten"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Blockieren"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Sammlung erstellen"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Projekt erstellen"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Nutzerdetails anzeigen"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Projekte verwalten"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Als Partner entfernen"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Als Partner festlegen"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Freigeben"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# Projekt} other {# Projekte}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Erlaube Pop-Ups für Modrinth und versuche es erneut."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "Das GitHub-Profil konnte nicht abgerufen werden. Bitte versuche es erneut."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Das GitHub-Profil konnte nicht geöffnet werden"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Authentifizierungsanbieter"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "E-Mail verifiziert"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Hat Passwort"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Hat TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Wird geladen..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Zahlungsmethoden"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Profil anzeigen"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Nutzerdetails"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "E-Mail nicht verifiziert"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "E-Mail verifiziert"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Das Nutzerprofil konnte nicht geladen werden."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Nutzer nicht gefunden"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Partner"
+ },
"profile.label.badges": {
"defaultMessage": "Abzeichen"
},
+ "profile.label.collection": {
+ "defaultMessage": "Kollektion"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {Download} other {Downloads}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Beigetreten"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Dieser Nutzer hat keine Kollektionen!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Du hast noch keine Kollektionen."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Dieser Nutzer hat keine Projekte!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Du hast noch keine Projekte."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organisationen"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {Projekt} other {Projekte}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Offizielles Modrinth-Konto"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Das offizielle Benutzerkonto von Modrinth. Erhalte Hilfe unter oder per E-Mail unter "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Beim Freigeben dieses Nutzers ist ein Fehler aufgetreten. Bitte versuche es erneut."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Nutzer konnte nicht freigegeben werden"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} wurde freigegeben."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Benutzer freigegeben"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Veröffentlicht {date}"
},
@@ -2879,6 +2996,9 @@
"project-type.all": {
"defaultMessage": "Alle"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Kollektionen"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Datenpaket} other {Datenpakete}}"
},
@@ -3671,15 +3791,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Erweitert"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Datenpakete ausschließen"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Mods ausschließen"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Plugins ausschließen"
- },
"search.filter_type.environment": {
"defaultMessage": "Umgebung"
},
@@ -5105,9 +5216,120 @@
"settings.pats.title": {
"defaultMessage": "Persöhnlich Zugangstoken"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Eine kurze Beschreibung um allen ein bisschen von dir zu erzählen."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Bio"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Profil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Profilbild"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "Deine Profilinformationen sind öffentlich auf Modrinth und über die Modrinth-API sichtbar."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Profil konnte nicht aktualisiert werden"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Beim Aktualisieren deines Profils ist ein Fehler aufgetreten. Bitte versuche es erneut."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Melde dich mit einem Modrinth-Konto an, um dein öffentliches Profil anzupassen."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Modrinth-Konto benötigt"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Ein eindeutiger Name für dein Profil, bei dem Groß- und Kleinschreibung nicht unterschieden wird."
+ },
"settings.sessions.title": {
"defaultMessage": "Sitzungen"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Aktionen"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Nutzer"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Dies sind die Benutzer, die du auf Modrinth blockiert hast. Diese können nicht:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Du hast niemanden blockiert."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Blockierte Nutzer konnten nicht geladen werden."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Blockierte Nutzer werden geladen…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Dir Freundschaftsanfragen senden"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Dich zu einem Modrinth-Hosting Server einladen."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Dich zu geteilten Instanzen einladen"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Blockierte Nutzer"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Freigeben"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Benutzer konnte nicht freigegeben werden"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Beim Freigeben dieses Nutzers ist ein Fehler aufgetreten. Bitte versuche es erneut."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "{username} freigeben"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Avatar von {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Lege fest, wer dir auf Modrinth Freundschaftsanfragen senden kann."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Freundschaftsanfragen"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Bald verfügbar!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Jeder"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Freunde"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Freunde von Freunden"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Niemand"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Steuere, wer dir Einladungen zu geteilten Instanzen und Modrinth-Hosting-Panels senden kann."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Einladungen"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Mit einem Modrinth-Konto kannst du festlegen, wer mit dir interagieren kann, und blockierte Nutzer verwalten"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Modrinth-Konto benötigt"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Sozial"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Hinzufügen"
},
@@ -5117,14 +5339,17 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "Dieser Benutzer wurde bereits eingeladen."
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Anwenden"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "Avatar von {username}"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Abbrechen"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Benutzerdefiniert..."
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Abbrechen"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Benutzerdefiniert: {date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "Einladungslink bearbeiten."
@@ -5132,6 +5357,24 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "Einladungslink bearbeiten"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "In 1 Tag"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "In 1 Stunde"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "In 7 Tagen"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "In 6 Stunden"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "In 3 Tagen"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "In 12 Stunden"
+ },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "Ablaufdatum"
},
diff --git a/packages/ui/src/locales/de-DE/index.json b/packages/ui/src/locales/de-DE/index.json
index c6f62eb559..b94986963e 100644
--- a/packages/ui/src/locales/de-DE/index.json
+++ b/packages/ui/src/locales/de-DE/index.json
@@ -291,7 +291,7 @@
"defaultMessage": "Registrieren"
},
"button.stop": {
- "defaultMessage": "Stopp"
+ "defaultMessage": "Stoppen"
},
"button.switch-to-version": {
"defaultMessage": "Zur Version wechseln"
@@ -617,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Projektnamen"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alphabetisch"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Neuste zuerst"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Älteste zuerst"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sortieren nach {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Alle aktualisieren"
},
@@ -1301,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Datei gespeichert"
},
- "files.editor.find-close": {
- "defaultMessage": "Schließen"
- },
"files.editor.find-in-file": {
"defaultMessage": "Finden"
},
@@ -2081,33 +2066,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Icon auswählen"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Dieses Modpack enthält keine zusätzlichen Inhalte."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Keine Inhalte gefunden"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Extern"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "Diese Datei ist nicht auf Modrinth veröffentlicht."
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Modpack-Inhalt"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Lade Inhalte..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Keine Projekte entsprechen deiner Suche."
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "In Slicer öffnen"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Durchsuche {count, number} {count, plural, one {Projekt} other {Projekte}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Aktuell"
},
@@ -2240,6 +2198,9 @@
"label.details": {
"defaultMessage": "Details"
},
+ "label.discover-content": {
+ "defaultMessage": "Inhalte erkunden"
+ },
"label.done": {
"defaultMessage": "Fertig"
},
@@ -2292,7 +2253,7 @@
"defaultMessage": "Inhalt wird installiert"
},
"label.loading": {
- "defaultMessage": "Lädt..."
+ "defaultMessage": "Wird geladen..."
},
"label.moderation": {
"defaultMessage": "Moderation"
@@ -2318,6 +2279,9 @@
"label.password": {
"defaultMessage": "Passwort"
},
+ "label.permissions": {
+ "defaultMessage": "Berechtigungen"
+ },
"label.plan-custom": {
"defaultMessage": "Benutzerdefiniert"
},
@@ -2849,9 +2813,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Ein Modrinth-Ersteller."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Ein Modrinth-Nutzer."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} wird dir keine Freundschaftsanfragen mehr senden können, dich nicht zu geteilten Instanzen einladen können und dich nicht mehr zu Modrinth-Hosting Servern einladen können."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Bist du dir sicher, dass du diesen Nutzer blockieren willst?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Beim Blockieren dieses Nutzers ist ein Fehler aufgetreten. Bitte versuche es erneut."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Blockierung fehlgeschlagen"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} wurde blockiert."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Nutzer blockiert"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Blockiere {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Benutzeranalysen anzeigen"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Benutzerabrechnung verwalten"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Blockieren"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Sammlung erstellen"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Projekt erstellen"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Nutzerdetails anzeigen"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Projekte verwalten"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Als Partner entfernen"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Als Partner festlegen"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Freigeben"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# Projekt} other {# Projekte}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Erlaube Pop-Ups für Modrinth und versuche es erneut."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "Das GitHub-Profil konnte nicht abgerufen werden. Bitte versuche es erneut."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Das GitHub-Profil konnte nicht geöffnet werden"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Authentifizierungsanbieter"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "E-Mail verifiziert"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Hat Passwort"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Hat TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Wird geladen..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Zahlungsmethoden"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Profil anzeigen"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Nutzerdetails"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "E-Mail nicht verifiziert"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "E-Mail verifiziert"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Das Nutzerprofil konnte nicht geladen werden."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Nutzer nicht gefunden"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Partner"
+ },
"profile.label.badges": {
"defaultMessage": "Abzeichen"
},
+ "profile.label.collection": {
+ "defaultMessage": "Kollektion"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {Download} other {Downloads}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Beigetreten"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Dieser Nutzer hat keine Kollektionen!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Du hast noch keine Kollektionen."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Dieser Nutzer hat keine Projekte!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Du hast noch keine Projekte."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organisationen"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {Projekt} other {Projekte}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Offizielles Modrinth-Konto"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Das offizielle Benutzerkonto von Modrinth. Erhalte Hilfe unter oder per E-Mail unter "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Beim Freigeben dieses Nutzers ist ein Fehler aufgetreten. Bitte versuche es erneut."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Nutzer konnte nicht freigegeben werden"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} wurde freigegeben."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Benutzer freigegeben"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Veröffentlicht am {date}"
},
@@ -2879,6 +2996,9 @@
"project-type.all": {
"defaultMessage": "Alle"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Kollektionen"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Datenpaket} other {Datenpakete}}"
},
@@ -3671,15 +3791,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Erweitert"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Datenpakete ausschließen"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Mods ausschließen"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Plugins ausschließen"
- },
"search.filter_type.environment": {
"defaultMessage": "Umgebung"
},
@@ -5105,9 +5216,120 @@
"settings.pats.title": {
"defaultMessage": "Persönliche Zugangstoken"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Eine kurze Beschreibung um allen ein bisschen von dir zu erzählen."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Bio"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Profil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Profilbild"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "Deine Profilinformationen sind öffentlich auf Modrinth und über die Modrinth-API sichtbar."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Profil konnte nicht aktualisiert werden"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Beim Aktualisieren deines Profils ist ein Fehler aufgetreten. Bitte versuche es erneut."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Melde dich mit einem Modrinth-Konto an, um dein öffentliches Profil anzupassen."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Modrinth-Konto benötigt"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Ein eindeutiger Name für dein Profil, bei dem Groß- und Kleinschreibung nicht unterschieden wird."
+ },
"settings.sessions.title": {
"defaultMessage": "Sitzungen"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Aktionen"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Nutzer"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Dies sind die Benutzer, die du auf Modrinth blockiert hast. Diese können nicht:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Du hast niemanden blockiert."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Blockierte Nutzer konnten nicht geladen werden."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Blockierte Nutzer werden geladen…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Dir Freundschaftsanfragen senden"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Dich zu einem Modrinth-Hosting Server einladen."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Dich zu geteilten Instanzen einladen"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Blockierte Nutzer"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Freigeben"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Benutzer konnte nicht freigegeben werden"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Beim Freigeben dieses Nutzers ist ein Fehler aufgetreten. Bitte versuche es erneut."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "{username} freigeben"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Avatar von {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Lege fest, wer dir auf Modrinth Freundschaftsanfragen senden kann."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Freundschaftsanfragen"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Bald verfügbar!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Jeder"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Freunde"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Freunde von Freunden"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Niemand"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Steuere, wer dir Einladungen zu geteilten Instanzen und Modrinth-Hosting-Panels senden kann."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Einladungen"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Mit einem Modrinth-Konto kannst du festlegen, wer mit dir interagieren kann, und blockierte Nutzer verwalten"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Modrinth-Konto benötigt"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Sozial"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Hinzufügen"
},
@@ -5117,14 +5339,17 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "Dieser Benutzer wurde bereits eingeladen."
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Anwenden"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "Avatar von {username}"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Abbrechen"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Benutzerdefiniert..."
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Abbrechen"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Benutzerdefiniert: {date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "Einladungslink bearbeiten."
@@ -5132,6 +5357,24 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "Einladungslink bearbeiten"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "In 1 Tag"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "In 1 Stunde"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "In 7 Tagen"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "In 6 Stunden"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "In 3 Tagen"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "In 12 Stunden"
+ },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "Ablaufdatum"
},
diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json
index f842c47c3d..aaa994bd13 100644
--- a/packages/ui/src/locales/en-US/index.json
+++ b/packages/ui/src/locales/en-US/index.json
@@ -92,6 +92,15 @@
"billing.resubscribe-modal.title": {
"defaultMessage": "Resubscribe to Server"
},
+ "browse.advanced-filters.apply-saved-preferences": {
+ "defaultMessage": "Apply saved preferences"
+ },
+ "browse.advanced-filters.link-overriding-preferences": {
+ "defaultMessage": "This link's filters differ from your saved advanced exclusions"
+ },
+ "browse.advanced-filters.persistence-note": {
+ "defaultMessage": "Advanced exclusions are saved across sessions. Opening a shared link with filters will override them."
+ },
"browse.filter-results": {
"defaultMessage": "Filter results..."
},
@@ -131,6 +140,9 @@
"button.accept": {
"defaultMessage": "Accept"
},
+ "button.add-another": {
+ "defaultMessage": "Add another"
+ },
"button.add-server-to-instance": {
"defaultMessage": "Add server to instance"
},
@@ -203,6 +215,9 @@
"button.hide-snapshots": {
"defaultMessage": "Hide snapshots"
},
+ "button.i-understand": {
+ "defaultMessage": "I understand"
+ },
"button.install": {
"defaultMessage": "Install"
},
@@ -347,9 +362,15 @@
"content-type.item.lowercase": {
"defaultMessage": "{count, plural, one {item} other {items}}"
},
+ "content.card.frozen": {
+ "defaultMessage": "This project is locked to its current version until unfrozen."
+ },
"content.card.select-project": {
"defaultMessage": "Select {project}"
},
+ "content.card.uploaded": {
+ "defaultMessage": "Uploaded"
+ },
"content.confirm-bulk-update.admonition-body": {
"defaultMessage": "Are you sure you want to update {count, plural, one {# project} other {# projects}} to their latest compatible version? It's recommended to update content one-by-one."
},
@@ -507,7 +528,7 @@
"defaultMessage": "{count} removed (disabled)"
},
"content.diff-modal.reviewed-files": {
- "defaultMessage": "A file is only reviewed if it’s published to Modrinth, regardless of its file format (including .mrpack)."
+ "defaultMessage": "Files that aren't published to Modrinth aren't reviewed."
},
"content.diff-modal.unknown-content-body": {
"defaultMessage": "Some content on your server could not be analyzed and may be affected by this change."
@@ -566,9 +587,96 @@
"content.inline-backup.world-label": {
"defaultMessage": "world"
},
- "content.modpack-card.installation-settings": {
+ "content.managed-card.managed-by": {
+ "defaultMessage": "Managed by"
+ },
+ "content.managed-card.modpack-content": {
+ "defaultMessage": "Modpack content"
+ },
+ "content.managed-card.server-suffix": {
+ "defaultMessage": "server"
+ },
+ "content.managed-card.settings": {
"defaultMessage": "Installation settings"
},
+ "content.managed-card.shared-content": {
+ "defaultMessage": "Shared content"
+ },
+ "content.managed-card.summary.empty": {
+ "defaultMessage": "No managed content"
+ },
+ "content.managed-card.summary.installing": {
+ "defaultMessage": "Installing content..."
+ },
+ "content.managed-card.summary.loading": {
+ "defaultMessage": "Loading managed content summary"
+ },
+ "content.managed-card.switch-version": {
+ "defaultMessage": "Switch version"
+ },
+ "content.managed-card.synced": {
+ "defaultMessage": "Synced {time}"
+ },
+ "content.managed-card.update-available": {
+ "defaultMessage": "Update available"
+ },
+ "content.managed-card.updated": {
+ "defaultMessage": "Updated {time}"
+ },
+ "content.managed-card.updating": {
+ "defaultMessage": "Updating..."
+ },
+ "content.managed-card.view-content": {
+ "defaultMessage": "View content"
+ },
+ "content.metadata-filter.author": {
+ "defaultMessage": "Author"
+ },
+ "content.metadata-filter.environment": {
+ "defaultMessage": "Environment"
+ },
+ "content.metadata-filter.open-source": {
+ "defaultMessage": "Open source"
+ },
+ "content.metadata-filter.shared-content": {
+ "defaultMessage": "Shared content"
+ },
+ "content.metadata-filter.source.external": {
+ "defaultMessage": "External"
+ },
+ "content.metadata-filter.state": {
+ "defaultMessage": "State"
+ },
+ "content.metadata-filter.state.disabled": {
+ "defaultMessage": "Disabled"
+ },
+ "content.metadata-filter.state.enabled": {
+ "defaultMessage": "Enabled"
+ },
+ "content.metadata-filter.update.available": {
+ "defaultMessage": "Update available"
+ },
+ "content.metadata-filter.update.up-to-date": {
+ "defaultMessage": "Up to date"
+ },
+ "content.metadata-filter.updates": {
+ "defaultMessage": "Updates"
+ },
+ "content.metadata-filter.warning.client-depends": {
+ "defaultMessage": "Client depends on file"
+ },
+ "content.metadata-filter.warning.client-only": {
+ "defaultMessage": "Client-only content"
+ },
+ "content.metadata-filter.warning.client-retained": {
+ "defaultMessage": "Client file retained"
+ },
+ "content.metadata-filter.warning.none": {
+ "defaultMessage": "No warnings"
+ },
+ "content.metadata-filter.warnings": {
+ "defaultMessage": "Warnings"
+ },
"content.page-layout.additional-content": {
"defaultMessage": "Additional content"
},
@@ -593,6 +701,12 @@
"content.page-layout.failed-to-load": {
"defaultMessage": "Failed to load content"
},
+ "content.page-layout.filter.add": {
+ "defaultMessage": "Filter"
+ },
+ "content.page-layout.filter.author-count": {
+ "defaultMessage": "{count, plural, one {# author} other {# authors}}"
+ },
"content.page-layout.loading": {
"defaultMessage": "Loading content..."
},
@@ -620,8 +734,11 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Project names"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alphabetical"
+ "content.page-layout.sort.alphabetical-ascending": {
+ "defaultMessage": "Name (A-Z)"
+ },
+ "content.page-layout.sort.alphabetical-descending": {
+ "defaultMessage": "Name (Z-A)"
},
"content.page-layout.sort.date-added-newest": {
"defaultMessage": "Newest first"
@@ -956,6 +1073,9 @@
"creation-flow.title.set-up-server": {
"defaultMessage": "Set up server"
},
+ "empty-state.upload-versions.description": {
+ "defaultMessage": "Come back once you've uploaded your versions."
+ },
"external-files.permissions-card.add-files-modal.confirm": {
"defaultMessage": "{count, plural, one {Add file} other {Add files}}"
},
@@ -1304,9 +1424,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "File saved"
},
- "files.editor.find-close": {
- "defaultMessage": "Close"
- },
"files.editor.find-in-file": {
"defaultMessage": "Find"
},
@@ -1775,6 +1892,9 @@
"hosting.content.failed-to-upload": {
"defaultMessage": "Failed to upload file"
},
+ "hosting.content.managed-content.modpack-header": {
+ "defaultMessage": "Modpack content"
+ },
"hosting.loader.failed-to-change-version": {
"defaultMessage": "Failed to change modpack version"
},
@@ -2084,31 +2204,31 @@
"instances.content-install.select-icon": {
"defaultMessage": "Select icon"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "This modpack does not include any additional content."
+ "instances.managed-content-modal.empty-description": {
+ "defaultMessage": "This source does not include any managed content."
},
- "instances.modpack-content-modal.empty-title": {
+ "instances.managed-content-modal.empty-title": {
"defaultMessage": "No content found"
},
- "instances.modpack-content-modal.external-content": {
+ "instances.managed-content-modal.external-content": {
"defaultMessage": "External"
},
- "instances.modpack-content-modal.external-content-description": {
+ "instances.managed-content-modal.external-content-description": {
"defaultMessage": "This file is not published on Modrinth."
},
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Modpack content"
+ "instances.managed-content-modal.header": {
+ "defaultMessage": "Managed content"
},
- "instances.modpack-content-modal.loading": {
+ "instances.managed-content-modal.loading": {
"defaultMessage": "Loading content..."
},
- "instances.modpack-content-modal.no-results": {
+ "instances.managed-content-modal.no-results": {
"defaultMessage": "No projects match your search."
},
- "instances.modpack-content-modal.open-in-slicer": {
+ "instances.managed-content-modal.open-in-slicer": {
"defaultMessage": "Open in Slicer"
},
- "instances.modpack-content-modal.search-placeholder": {
+ "instances.managed-content-modal.search-placeholder": {
"defaultMessage": "Search {count, number} {count, plural, one {project} other {projects}}"
},
"instances.updater-modal.badge.current": {
@@ -2261,6 +2381,9 @@
"label.error": {
"defaultMessage": "Error"
},
+ "label.explanation": {
+ "defaultMessage": "Explanation"
+ },
"label.extract-failed": {
"defaultMessage": "Extract failed"
},
@@ -2900,9 +3023,6 @@
"profile.button.create-project": {
"defaultMessage": "Create a project"
},
- "profile.button.edit-role": {
- "defaultMessage": "Edit role"
- },
"profile.button.info": {
"defaultMessage": "View user details"
},
@@ -2999,24 +3119,12 @@
"profile.label.project-count": {
"defaultMessage": "{count, plural, one {project} other {projects}}"
},
- "profile.label.saving": {
- "defaultMessage": "Saving..."
- },
"profile.official-account": {
"defaultMessage": "Official Modrinth account"
},
"profile.official-account.bio": {
"defaultMessage": "The official user account of Modrinth. Get support at or via email at "
},
- "profile.role.select-placeholder": {
- "defaultMessage": "Select a role"
- },
- "profile.role.update-error-description": {
- "defaultMessage": "An error occurred while updating the user role. Please try again."
- },
- "profile.role.update-error-title": {
- "defaultMessage": "Failed to update role"
- },
"profile.unblock-user.error-description": {
"defaultMessage": "An error occurred while unblocking this user. Please try again."
},
@@ -3257,6 +3365,48 @@
"project.about.tags.title": {
"defaultMessage": "Tags"
},
+ "project.disclosure.advertising.title": {
+ "defaultMessage": "Contains advertising"
+ },
+ "project.disclosure.ai-generated-content.title": {
+ "defaultMessage": "Contains AI-generated {types}"
+ },
+ "project.disclosure.ai-generated-content.use.assets": {
+ "defaultMessage": "assets"
+ },
+ "project.disclosure.ai-generated-content.use.code": {
+ "defaultMessage": "code"
+ },
+ "project.disclosure.ai-generated-content.use.content": {
+ "defaultMessage": "content"
+ },
+ "project.disclosure.ai-generated-content.use.functionality": {
+ "defaultMessage": "functionality"
+ },
+ "project.disclosure.ai-generated-content.use.text": {
+ "defaultMessage": "text"
+ },
+ "project.disclosure.derivative-work.show-fewer": {
+ "defaultMessage": "Show fewer"
+ },
+ "project.disclosure.derivative-work.show-more": {
+ "defaultMessage": "Show {count} more"
+ },
+ "project.disclosure.derivative-work.title": {
+ "defaultMessage": "This is a derivative work of:"
+ },
+ "project.disclosure.paid-features.title": {
+ "defaultMessage": "Contains paid features"
+ },
+ "project.disclosure.photosensitivity.title": {
+ "defaultMessage": "Photosensitivity warning"
+ },
+ "project.disclosure.system-interactions.title": {
+ "defaultMessage": "Contains external system interactions"
+ },
+ "project.disclosure.telemetry.title": {
+ "defaultMessage": "Contains {consent, select, opt_in {opt-in telemetry} opt_out {opt-out telemetry} always_active {always-active telemetry} other {telemetry}}"
+ },
"project.download-count-tooltip": {
"defaultMessage": "{count, number} {count, plural, one {download} other {downloads}}"
},
@@ -3620,6 +3770,30 @@
"project.settings.description.title": {
"defaultMessage": "Description"
},
+ "project.settings.disclosures.ai.types-assets": {
+ "defaultMessage": "Assets"
+ },
+ "project.settings.disclosures.ai.types-code": {
+ "defaultMessage": "Code"
+ },
+ "project.settings.disclosures.ai.types-functionality": {
+ "defaultMessage": "Functionality"
+ },
+ "project.settings.disclosures.ai.types-text": {
+ "defaultMessage": "Text"
+ },
+ "project.settings.disclosures.telemetry.consent-always-active": {
+ "defaultMessage": "Always active"
+ },
+ "project.settings.disclosures.telemetry.consent-opt-in": {
+ "defaultMessage": "Opt-in"
+ },
+ "project.settings.disclosures.telemetry.consent-opt-out": {
+ "defaultMessage": "Opt-out"
+ },
+ "project.settings.disclosures.title": {
+ "defaultMessage": "Disclosures"
+ },
"project.settings.environment.client_and_server.description": {
"defaultMessage": "Has some functionality on both the client and server, even if only partially."
},
@@ -3749,6 +3923,12 @@
"project.stats.followers-label": {
"defaultMessage": "{count, plural, one {follower} other {followers}}"
},
+ "project.status.archived.body": {
+ "defaultMessage": "{title} will not receive any further updates unless the author decides to unarchive the project."
+ },
+ "project.status.archived.header": {
+ "defaultMessage": "{title} has been archived"
+ },
"project.versions.channel.alpha.symbol": {
"defaultMessage": "A"
},
@@ -3815,6 +3995,24 @@
"report.item-type.version": {
"defaultMessage": "version"
},
+ "report.type.copyright": {
+ "defaultMessage": "Reuploaded work"
+ },
+ "report.type.inappropriate": {
+ "defaultMessage": "Inappropriate"
+ },
+ "report.type.malicious": {
+ "defaultMessage": "Malicious"
+ },
+ "report.type.missing-disclosure": {
+ "defaultMessage": "Missing or incorrect disclosure"
+ },
+ "report.type.name-squatting": {
+ "defaultMessage": "Name squatting"
+ },
+ "report.type.spam": {
+ "defaultMessage": "Spam"
+ },
"s.bg": {
"defaultMessage": "Background task running"
},
@@ -3848,17 +4046,41 @@
"search.filter.option.show_more": {
"defaultMessage": "Show more"
},
+ "search.filter.option.sub_options.collapse.tooltip": {
+ "defaultMessage": "Hide more options"
+ },
+ "search.filter.option.sub_options.expand.tooltip": {
+ "defaultMessage": "Show more options"
+ },
"search.filter_type.advanced": {
- "defaultMessage": "Advanced"
+ "defaultMessage": "Advanced exclusions"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Exclude data packs"
+ "search.filter_type.advanced.disclosure.advertisements": {
+ "defaultMessage": "Advertisements"
},
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Exclude mods"
+ "search.filter_type.advanced.disclosure.ai_content": {
+ "defaultMessage": "AI-generated content"
},
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Exclude plugins"
+ "search.filter_type.advanced.disclosure.ai_content.usage": {
+ "defaultMessage": "AI {usage}"
+ },
+ "search.filter_type.advanced.disclosure.archived": {
+ "defaultMessage": "Archived"
+ },
+ "search.filter_type.advanced.disclosure.derivative_work": {
+ "defaultMessage": "Derivative content"
+ },
+ "search.filter_type.advanced.disclosure.epilepsy_triggers": {
+ "defaultMessage": "Photosensitivity triggers"
+ },
+ "search.filter_type.advanced.disclosure.paid_features": {
+ "defaultMessage": "Paid features"
+ },
+ "search.filter_type.advanced.disclosure.system_interactions": {
+ "defaultMessage": "External system interactions"
+ },
+ "search.filter_type.advanced.disclosure.telemetry": {
+ "defaultMessage": "Telemetry"
},
"search.filter_type.environment": {
"defaultMessage": "Environment"
@@ -3911,6 +4133,21 @@
"search.filter_type.shader_loader": {
"defaultMessage": "Loader"
},
+ "search.photosensitivity-warning-modal.body.1": {
+ "defaultMessage": "We cannot guarantee that all content on Modrinth has been labeled appropriately."
+ },
+ "search.photosensitivity-warning-modal.body.2": {
+ "defaultMessage": "Content labels for photosensitivity triggers are self-assigned by the creators who upload their content to Modrinth. These projects have not gone through any safety testing."
+ },
+ "search.photosensitivity-warning-modal.body.3": {
+ "defaultMessage": "Using any content on Modrinth is at your own risk. Please stay safe! 💚"
+ },
+ "search.photosensitivity-warning-modal.dont-show-again": {
+ "defaultMessage": "Don't show this again"
+ },
+ "search.photosensitivity-warning-modal.title": {
+ "defaultMessage": "Results are not guaranteed to be safe"
+ },
"search.server_content_type.modpack": {
"defaultMessage": "Modded"
},
@@ -5252,6 +5489,9 @@
"settings.feature-flags.title": {
"defaultMessage": "Feature flags"
},
+ "settings.form.group.optional": {
+ "defaultMessage": "(optional)"
+ },
"settings.language.categories.default": {
"defaultMessage": "Standard languages"
},
@@ -5414,12 +5654,6 @@
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "{username}'s avatar"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Cancel"
- },
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Cancel"
- },
"sharing.invite-players-modal.custom-expiry": {
"defaultMessage": "Custom..."
},
@@ -6063,7 +6297,7 @@
"defaultMessage": "Unknown files warning"
},
"unknown-file-warning-modal.reviewed-files": {
- "defaultMessage": "A file is only reviewed if it’s published to Modrinth, regardless of its file format (including .mrpack)."
+ "defaultMessage": "Files that aren't published to Modrinth aren't reviewed."
},
"unknown-file-warning-modal.unrecognized-files": {
"defaultMessage": "Unrecognized files"
diff --git a/packages/ui/src/locales/es-419/index.json b/packages/ui/src/locales/es-419/index.json
index 700b0fd3dd..f19710b8a4 100644
--- a/packages/ui/src/locales/es-419/index.json
+++ b/packages/ui/src/locales/es-419/index.json
@@ -39,7 +39,7 @@
"defaultMessage": "Error al cargar la configuración del servidor"
},
"badge.alpha": {
- "defaultMessage": "Alpha"
+ "defaultMessage": "Alfa"
},
"badge.beta": {
"defaultMessage": "Beta"
@@ -377,6 +377,9 @@
"content.confirm-deletion.header": {
"defaultMessage": "Eliminar {itemType}"
},
+ "content.confirm-disable.header": {
+ "defaultMessage": "Desactivar {itemType}"
+ },
"content.confirm-modpack-update.admonition-body": {
"defaultMessage": "{action, select, downgrade {Bajar de versión} other {Actualizar}} puede causar problemas de compatibilidad. Los mods o contenido que agregaste sobre el modpack se mantendrán, pero podrían no ser compatibles con la nueva versión."
},
@@ -446,33 +449,63 @@
"content.diff-modal.added-count": {
"defaultMessage": "{count} añadido"
},
+ "content.diff-modal.config-files-updated": {
+ "defaultMessage": "Archivos de configuración cambiados"
+ },
"content.diff-modal.diff-type.added": {
- "defaultMessage": "Añadido (dependencia)"
+ "defaultMessage": "Se añadió (dependencia)"
},
"content.diff-modal.diff-type.removed": {
- "defaultMessage": "Desactivado"
+ "defaultMessage": "Se desactivó"
+ },
+ "content.diff-modal.diff-type.removed-disabled": {
+ "defaultMessage": "Se eliminó (desactivado)"
},
"content.diff-modal.diff-type.updated": {
- "defaultMessage": "Actualizado"
+ "defaultMessage": "Se actualizó"
},
"content.diff-modal.dont-install": {
"defaultMessage": "No instalar"
},
"content.diff-modal.external-diff-type.added": {
- "defaultMessage": "Agregado"
+ "defaultMessage": "Se añadió"
},
"content.diff-modal.external-diff-type.removed": {
- "defaultMessage": "Eliminado"
+ "defaultMessage": "Se eliminó"
},
"content.diff-modal.external-diff-type.updated": {
- "defaultMessage": "Actualizado"
+ "defaultMessage": "Se actualizó"
+ },
+ "content.diff-modal.file-count": {
+ "defaultMessage": "{count, plural, one {# archivo} other {# archivos}}"
+ },
+ "content.diff-modal.game-version-updated": {
+ "defaultMessage": "Versión del juego"
},
"content.diff-modal.install-anyway": {
"defaultMessage": "Instalar de todos modos"
},
+ "content.diff-modal.loader-updated": {
+ "defaultMessage": "Loader"
+ },
+ "content.diff-modal.modpack-linked": {
+ "defaultMessage": "Modpack vinculado"
+ },
+ "content.diff-modal.modpack-unlinked": {
+ "defaultMessage": "Modpack desvinculado"
+ },
+ "content.diff-modal.modpack-updated": {
+ "defaultMessage": "Modpack actualizado"
+ },
+ "content.diff-modal.no-content-changes": {
+ "defaultMessage": "Sin cambios al contenido"
+ },
"content.diff-modal.removed-count": {
"defaultMessage": "{count} eliminados"
},
+ "content.diff-modal.removed-disabled-count": {
+ "defaultMessage": "{count} eliminados (desactivados)"
+ },
"content.diff-modal.reviewed-files": {
"defaultMessage": "Un archivo solo se revisa si se publica en Modrinth, sin importar su formato (incluido el .mrpack)."
},
@@ -584,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nombres de los proyectos"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Allfabético"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Más recientes primero"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Más antiguo primero"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Ordenar por {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Actualizar todo"
},
@@ -921,7 +942,7 @@
"defaultMessage": "Configurar servidor"
},
"external-files.permissions-card.add-files-modal.confirm": {
- "defaultMessage": "{count, plural, one {Agregar archivo} other {Agregar archivos}}"
+ "defaultMessage": "{count, plural, one {Añadir archivo} other {Añadir archivos}}"
},
"external-files.permissions-card.add-files-modal.description": {
"defaultMessage": "Selecciona cualquier archivo que deba ser movido a este grupo."
@@ -930,7 +951,7 @@
"defaultMessage": "No hay archivos en otros grupos que se puedan mover aquí."
},
"external-files.permissions-card.add-files-modal.load-error.title": {
- "defaultMessage": "No se pudieron cargar los archivos."
+ "defaultMessage": "No se pudieron cargar los archivos"
},
"external-files.permissions-card.add-files-modal.no-search-results": {
"defaultMessage": "No hay archivos que coincidan con tu búsqueda."
@@ -945,10 +966,10 @@
"defaultMessage": "Añadir archivos a este grupo"
},
"external-files.permissions-card.add-files-to-group": {
- "defaultMessage": "Agregar archivos..."
+ "defaultMessage": "Añadir archivos..."
},
"external-files.permissions-card.assign-files-error.title": {
- "defaultMessage": "No se pudieron agregar los archivos"
+ "defaultMessage": "No se pudieron añadir los archivos"
},
"external-files.permissions-card.attribution.moderation-status.content-not-allowed": {
"defaultMessage": "Contenido no permitido"
@@ -1077,7 +1098,7 @@
"defaultMessage": "Grupo de atribución {id}"
},
"external-files.permissions-card.file-count": {
- "defaultMessage": "{count, plural, one {Agregar archivo} other {Agregar archivos}}"
+ "defaultMessage": "{count, plural, one {Añadir archivo} other {Añadir archivos}}"
},
"external-files.permissions-card.included-files": {
"defaultMessage": "Archivos incluidos:"
@@ -1101,7 +1122,7 @@
"defaultMessage": "Motivo"
},
"external-files.permissions-card.moderation.error.title": {
- "defaultMessage": "No se pudo guardar la revisión de moderación."
+ "defaultMessage": "No se pudo guardar la revisión de moderación"
},
"external-files.permissions-card.not-used-in-versions": {
"defaultMessage": "Estos archivos no están siendo utilizados actualmente por ninguna versión."
@@ -1160,6 +1181,21 @@
"external-files.permissions-card.reason.special-permission.description": {
"defaultMessage": "Has obtenido permiso especial para redistribuir este trabajo en tu modpack."
},
+ "external-files.permissions-card.remove-group": {
+ "defaultMessage": "Borrar grupo"
+ },
+ "external-files.permissions-card.remove-group-confirmation.description": {
+ "defaultMessage": "Esto eliminará permanentemente este grupo de atribución y todos los archivos dentro. Esta acción no se puede deshacer."
+ },
+ "external-files.permissions-card.remove-group-confirmation.title": {
+ "defaultMessage": "¿Borrar {title}?"
+ },
+ "external-files.permissions-card.remove-group-error.title": {
+ "defaultMessage": "No se pudo borrar el grupo"
+ },
+ "external-files.permissions-card.remove-group-shift-hint": {
+ "defaultMessage": "Mantén Shift al hacer clic para saltar la confirmación."
+ },
"external-files.permissions-card.split-file": {
"defaultMessage": "Eliminar del grupo"
},
@@ -1253,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Archivo guardado"
},
- "files.editor.find-close": {
- "defaultMessage": "Cerrar"
- },
"files.editor.find-in-file": {
"defaultMessage": "Buscar"
},
@@ -1899,7 +1932,7 @@
"defaultMessage": "Reinstalando modpack"
},
"installation-settings.removed-incompatible": {
- "defaultMessage": "Eliminado (incompatible)"
+ "defaultMessage": "Se eliminó (incompatible)"
},
"installation-settings.repair.instance-description": {
"defaultMessage": "Reinstala las dependencias de Minecraft y verifica si hay archivos corruptos. Esto puede solucionar problemas si tu juego no se inicia debido a errores relacionados con el launcher."
@@ -2033,24 +2066,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Seleccionar ícono"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Este modpack no incluye ningún contenido adicional."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "No se encontró contenido"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Contenido del modpack"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Cargando contenido..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Ningún proyecto coincide con tu búsqueda."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Buscar en {count, number} {count, plural, one {proyecto} other {proyectos}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Actual"
},
@@ -2183,6 +2198,9 @@
"label.details": {
"defaultMessage": "Detalles"
},
+ "label.discover-content": {
+ "defaultMessage": "Descubrir contenido"
+ },
"label.done": {
"defaultMessage": "Listo"
},
@@ -2261,6 +2279,9 @@
"label.password": {
"defaultMessage": "Contraseña"
},
+ "label.permissions": {
+ "defaultMessage": "Permisos"
+ },
"label.plan-custom": {
"defaultMessage": "Personalizado"
},
@@ -2616,7 +2637,7 @@
"defaultMessage": "URL del video de YouTube"
},
"modal.add-payment-method.action": {
- "defaultMessage": "Agregar método de pago"
+ "defaultMessage": "Añadir método de pago"
},
"modal.add-payment-method.title": {
"defaultMessage": "Añadiendo método de pago"
@@ -2792,9 +2813,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Un creador de Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Un usuario de Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} no podrá enviarte solicitudes de amistad, invitarte a instancias compartidas o invitarte a servidores de Modrinth Hosting."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "¿Estás seguro de que quieres bloquear a este usuario?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Ocurrió un error al bloquear a este usuario. Por favor inténtalo otra vez."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Error al bloquear usuario"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "Bloqueaste a {username}."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Usuario bloqueado"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Bloquear a {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Ver analíticas del usuario"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Gestionar facturación del usuario"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Bloquear"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Crear una colección"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Crear un proyecto"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Ver detalles del usuario"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Gestionar proyectos"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Remover como afiliado"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Configurar como afiliado"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Desbloquear"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# proyecto} other {# proyectos}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Permite las ventanas emergentes para Modrinth, y luego vuelve a intentarlo."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "Este perfil de GitHub no pudo ser cargado. Por favor inténtalo otra vez."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Error al abrir el perfil de GitHub"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Proveedores de autenticación"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "Correo verificado"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Tiene contraseña"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Tiene TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Cargando..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Métodos de pago"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Ver perfil"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Detalles de usuario"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "Correo sin verificar"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "Correo verificado"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Este perfil de usuario no se pudo cargar."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Usuario no encontrado"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Afiliado"
+ },
"profile.label.badges": {
"defaultMessage": "Insignias"
},
+ "profile.label.collection": {
+ "defaultMessage": "Colección"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {descarga} other {descargas}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Se unió"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "¡Este usuario no tiene colecciones!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Todavía no tienes ninguna colección."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "¡Este usuario no tiene proyectos!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Todavía no tienes ningún proyecto."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organizaciones"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {proyecto} other {proyectos}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Cuenta oficial de Modrinth"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "La cuenta oficial de Modrinth. Consigue ayuda en o escríbenos por correo electrónico: "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Ocurrió un error al desbloquear a este usuario. Por favor inténtalo otra vez."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Error al desbloquear usuario"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "Desbloqueaste a {username}."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Usuario desbloqueado"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Publicado el {date}"
},
@@ -2810,12 +2984,21 @@
"project-card.environment.client-or-server": {
"defaultMessage": "Cliente o servidor"
},
+ "project-card.environment.dedicated-server": {
+ "defaultMessage": "Servidor dedicado"
+ },
"project-card.environment.server": {
"defaultMessage": "Servidor"
},
+ "project-card.environment.singleplayer": {
+ "defaultMessage": "Un solo jugador"
+ },
"project-type.all": {
"defaultMessage": "Todo"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Colecciones"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Data Pack} other {Data Packs}}"
},
@@ -2943,7 +3126,7 @@
"defaultMessage": "Enviado {date}"
},
"project.about.details.updated": {
- "defaultMessage": "Actualizado {date}"
+ "defaultMessage": "Actualizado el {date}"
},
"project.about.links.discord": {
"defaultMessage": "Únete al servidor de Discord"
@@ -3086,6 +3269,15 @@
"project.follower-count-tooltip": {
"defaultMessage": "{count, number} {count, plural, one {seguidor} other {seguidores}}"
},
+ "project.license.error": {
+ "defaultMessage": "No se pudo conseguir el texto de la licencia."
+ },
+ "project.license.loading": {
+ "defaultMessage": "Cargando el texto de la licencia..."
+ },
+ "project.license.title": {
+ "defaultMessage": "Licencia"
+ },
"project.online-player-count": {
"defaultMessage": "{count, number} en línea"
},
@@ -3491,6 +3683,12 @@
"project.settings.view.title": {
"defaultMessage": "Ver"
},
+ "project.stats.downloads-label": {
+ "defaultMessage": "{count, plural, one {descarga} other {descargas}}"
+ },
+ "project.stats.followers-label": {
+ "defaultMessage": "{count, plural, one {seguidor} other {seguidores}}"
+ },
"project.versions.channel.alpha.symbol": {
"defaultMessage": "A"
},
@@ -3593,15 +3791,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Avanzado"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Excluir paquetes de datos"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Excluir mods"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Excluir complementos"
- },
"search.filter_type.environment": {
"defaultMessage": "Entorno"
},
@@ -5022,14 +5211,221 @@
"defaultMessage": "Idioma"
},
"settings.language.warning": {
- "defaultMessage": "Cambiar el idioma de {platform} podría provocar que parte del contenido aparezca en inglés si no hay una traducción disponible. {platform} Aún no está completamente traducida, por lo que parte del contenido podría permanecer en inglés en ciertos idiomas."
+ "defaultMessage": "Cambiar el idioma de la {platform} podría provocar que parte del contenido aparezca en inglés si no hay una traducción disponible. La {platform} aún no está completamente traducida, por lo que parte del contenido podría permanecer en inglés en ciertos idiomas."
},
"settings.pats.title": {
"defaultMessage": "Tokens de acceso personal"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Una descripción corta que le cuente a todos un poquito sobre tí."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Biografía"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Perfil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Foto de perfil"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "La información de tu perfil es visible públicamente en Modrinth y también a través de la Modrinth API ."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Error al actualizar perfil"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Ocurrió un error al actualizar tu perfil. Por favor inténtalo otra vez."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Regístrate con una cuenta Modrinth para personalizar tu perfil."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Cuenta Modrinth requerida"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Un nombre único, sin distinción de mayúsculas y minúsculas, para identificar tu perfil."
+ },
"settings.sessions.title": {
"defaultMessage": "Sesiones"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Acciones"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Usuario"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Estos son los usuarios que has bloqueado en Modrinth. Ellos no pueden:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "No has bloqueado a nadie."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "No se pudo cargar los usuarios bloqueados."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Cargando usuarios bloqueados…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Enviarte solicitudes de amistad"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Invitarte a gestionar un servidor de Modrinth Hosting."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Invitarte a instancias compartidas"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Usuarios bloqueados"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Desbloquear"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Error al desbloquear usuario"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Ocurrió un error al desbloquear a este usuario. Por favor inténtalo otra vez."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Desbloquear a {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Avatar de {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Controla quién puede enviarte solicitudes de amistad en Modrinth."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Solicitudes de amistad"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "¡Próximamente!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Todos"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Amigos"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Amigos de amigos"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Nadie"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Controla quién te puede enviar invitaciones a instancias compartidas y paneles de Modrinth Hosting."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Invitaciones"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Puedes controlar quién puede interactuar contigo, y gestionar los usuarios bloqueados con una Cuenta Modrinth"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Cuenta Modrinth requerida"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Social"
+ },
+ "sharing.invite-players-modal.add": {
+ "defaultMessage": "Añadir"
+ },
+ "sharing.invite-players-modal.added": {
+ "defaultMessage": "Añadido"
+ },
+ "sharing.invite-players-modal.already-invited": {
+ "defaultMessage": "Este usuario ya fue invitado."
+ },
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Aplicar"
+ },
+ "sharing.invite-players-modal.avatar-alt": {
+ "defaultMessage": "Avatar de {username}"
+ },
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Otro..."
+ },
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Otro: {date}"
+ },
+ "sharing.invite-players-modal.edit-invite-link": {
+ "defaultMessage": "Editar link de invitación."
+ },
+ "sharing.invite-players-modal.edit-invite-link-title": {
+ "defaultMessage": "Editar link de invitación"
+ },
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "En 1 día"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "En 1 hora"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "En 7 días"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "En 6 horas"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "En 3 días"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "En 12 horas"
+ },
+ "sharing.invite-players-modal.expiry-label": {
+ "defaultMessage": "Fecha de expiración"
+ },
+ "sharing.invite-players-modal.friends-heading": {
+ "defaultMessage": "Tus amigos - {count}"
+ },
+ "sharing.invite-players-modal.invite": {
+ "defaultMessage": "Invitar"
+ },
+ "sharing.invite-players-modal.invite-expiry-description": {
+ "defaultMessage": "Tu link de invitación expira en {duration}."
+ },
+ "sharing.invite-players-modal.invite-link-heading": {
+ "defaultMessage": "O usa un link de invitación"
+ },
+ "sharing.invite-players-modal.link-copied-text": {
+ "defaultMessage": "El link de invitación fue copiado a tu portapapeles."
+ },
+ "sharing.invite-players-modal.link-copied-title": {
+ "defaultMessage": "Link copiado"
+ },
+ "sharing.invite-players-modal.link-copy-failed-title": {
+ "defaultMessage": "Error al copiar link"
+ },
+ "sharing.invite-players-modal.max-uses-label": {
+ "defaultMessage": "Usos máximos"
+ },
+ "sharing.invite-players-modal.no-friends": {
+ "defaultMessage": "No tienes amigos."
+ },
+ "sharing.invite-players-modal.no-search-results": {
+ "defaultMessage": "No se encontró ningún usuario coincidente."
+ },
+ "sharing.invite-players-modal.requested": {
+ "defaultMessage": "Solicitud enviada"
+ },
+ "sharing.invite-players-modal.requested-tooltip": {
+ "defaultMessage": "{username} debe aceptar tu solicitud de amistad primero"
+ },
+ "sharing.invite-players-modal.save-button": {
+ "defaultMessage": "Guardar"
+ },
+ "sharing.invite-players-modal.search-placeholder": {
+ "defaultMessage": "Introduce el nombre de usuario de Modrinth"
+ },
+ "sharing.invite-players-modal.searching": {
+ "defaultMessage": "Buscando..."
+ },
+ "sharing.invite-players-modal.update-invite-link-failed-title": {
+ "defaultMessage": "Error al actualizar link de invitación"
+ },
"tag.category.128x": {
"defaultMessage": "128x"
},
@@ -5181,7 +5577,7 @@
"defaultMessage": "Kit PvP"
},
"tag.category.library": {
- "defaultMessage": "Librería"
+ "defaultMessage": "Biblioteca"
},
"tag.category.lifesteal": {
"defaultMessage": "Lifesteal"
@@ -5445,7 +5841,7 @@
"defaultMessage": "Sponge"
},
"tag.loader.vanilla": {
- "defaultMessage": "Shader vanilla"
+ "defaultMessage": "Shader Vanilla"
},
"tag.loader.velocity": {
"defaultMessage": "Velocity"
diff --git a/packages/ui/src/locales/es-ES/index.json b/packages/ui/src/locales/es-ES/index.json
index bfeabbbb50..0f497a9b33 100644
--- a/packages/ui/src/locales/es-ES/index.json
+++ b/packages/ui/src/locales/es-ES/index.json
@@ -221,6 +221,9 @@
"button.open-folder": {
"defaultMessage": "Abrir carpeta"
},
+ "button.open-in-browser": {
+ "defaultMessage": "Abrir en el navegador"
+ },
"button.open-in-folder": {
"defaultMessage": "Abrir en carpeta"
},
@@ -236,6 +239,9 @@
"button.reinstall-modpack": {
"defaultMessage": "Reinstalar modpack"
},
+ "button.remove": {
+ "defaultMessage": "Eliminar"
+ },
"button.remove-image": {
"defaultMessage": "Eliminar imagen"
},
@@ -287,6 +293,9 @@
"button.stop": {
"defaultMessage": "Detener"
},
+ "button.switch-to-version": {
+ "defaultMessage": "Cambiar a la versión"
+ },
"button.switch-version": {
"defaultMessage": "Cambiar versión"
},
@@ -314,6 +323,21 @@
"changelog.product.web": {
"defaultMessage": "Plataforma"
},
+ "collection-widget.empty-collection": {
+ "defaultMessage": "Esta colección está vacía."
+ },
+ "collection-widget.loading-projects": {
+ "defaultMessage": "Cargando proyectos..."
+ },
+ "collection-widget.no-search-results": {
+ "defaultMessage": "No proyectos coinciden con tu búsqueda."
+ },
+ "collection-widget.project-count": {
+ "defaultMessage": "{count, plural, one {# proyecto} other {# proyectos}}"
+ },
+ "collection-widget.search-placeholder": {
+ "defaultMessage": "Buscar proyectos"
+ },
"collections.label.private": {
"defaultMessage": "Privado"
},
@@ -353,6 +377,9 @@
"content.confirm-deletion.header": {
"defaultMessage": "Borrar {itemType}"
},
+ "content.confirm-disable.header": {
+ "defaultMessage": "Desactivar {itemType}"
+ },
"content.confirm-modpack-update.admonition-body": {
"defaultMessage": "{action, select,downgrade {Bajar de versión} other {Actualizar}} puede causar problemas de compatibilidad. Mods o contenido que tu has añandido encima del modpack se quedara, pero no podria ser compatible con la nueva version."
},
@@ -422,21 +449,78 @@
"content.diff-modal.added-count": {
"defaultMessage": "{count} añadido/s"
},
+ "content.diff-modal.config-files-updated": {
+ "defaultMessage": "Archivos de configuración modificados"
+ },
"content.diff-modal.diff-type.added": {
"defaultMessage": "Añadido (dependencia)"
},
"content.diff-modal.diff-type.removed": {
"defaultMessage": "Desactivado"
},
+ "content.diff-modal.diff-type.removed-disabled": {
+ "defaultMessage": "Removido (desactivado)"
+ },
"content.diff-modal.diff-type.updated": {
"defaultMessage": "Actualizado"
},
+ "content.diff-modal.dont-install": {
+ "defaultMessage": "No instalar"
+ },
+ "content.diff-modal.external-diff-type.added": {
+ "defaultMessage": "Añadido"
+ },
+ "content.diff-modal.external-diff-type.removed": {
+ "defaultMessage": "Eliminado"
+ },
+ "content.diff-modal.external-diff-type.updated": {
+ "defaultMessage": "Actualizado"
+ },
+ "content.diff-modal.file-count": {
+ "defaultMessage": "{count, plural, one {# archivo} other {# archivos}}"
+ },
+ "content.diff-modal.game-version-updated": {
+ "defaultMessage": "Versión del juego"
+ },
+ "content.diff-modal.install-anyway": {
+ "defaultMessage": "Instalar de todas formas"
+ },
+ "content.diff-modal.loader-updated": {
+ "defaultMessage": "Cargador"
+ },
+ "content.diff-modal.modpack-linked": {
+ "defaultMessage": "Modpack vinculado"
+ },
+ "content.diff-modal.modpack-unlinked": {
+ "defaultMessage": "Modpack desvinculado"
+ },
+ "content.diff-modal.modpack-updated": {
+ "defaultMessage": "Modpack actualizado"
+ },
+ "content.diff-modal.no-content-changes": {
+ "defaultMessage": "No hay cambios en el contenido"
+ },
"content.diff-modal.removed-count": {
"defaultMessage": "{count} eliminado"
},
+ "content.diff-modal.removed-disabled-count": {
+ "defaultMessage": "{count} removido (desactivado)"
+ },
+ "content.diff-modal.reviewed-files": {
+ "defaultMessage": "Un archivo es revisado si es que está publicado en Modrinth, sin imputar su formato de archivo (Incluyendo .mrpack)."
+ },
"content.diff-modal.unknown-content-body": {
"defaultMessage": "No se ha podido analizar parte del contenido de su servidor, por lo que podría verse afectado por este cambio."
},
+ "content.diff-modal.unknown-files-description": {
+ "defaultMessage": "Esta actualización contiene archivos que no están publicados en Modrinth. Te recomendamos instalar archivos de fuentes de confianza."
+ },
+ "content.diff-modal.unknown-files-warning": {
+ "defaultMessage": "Advertencia de archivos desconocidos"
+ },
+ "content.diff-modal.unknown-project": {
+ "defaultMessage": "Desconocido"
+ },
"content.diff-modal.updated-count": {
"defaultMessage": "{count} actualizado/s"
},
@@ -533,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nombres de los proyectos"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Por orden alfabético"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Más recientes primero"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Más antiguo primero"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Ordenar por {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Actualizar todo"
},
@@ -560,24 +632,36 @@
"content.selection-bar.bulk.deleting": {
"defaultMessage": "Eliminando {progress}/{total} {contentType}..."
},
+ "content.selection-bar.bulk.deleting-count": {
+ "defaultMessage": "Eliminando {count, number} {contentType}"
+ },
"content.selection-bar.bulk.deleting-waiting": {
"defaultMessage": "Eliminando {contentType}..."
},
"content.selection-bar.bulk.disabling": {
"defaultMessage": "Desactivando {progress}/{total} {contentType}..."
},
+ "content.selection-bar.bulk.disabling-count": {
+ "defaultMessage": "Desactivando {count, number} {contentType}"
+ },
"content.selection-bar.bulk.disabling-waiting": {
"defaultMessage": "Desactivando {contentType}..."
},
"content.selection-bar.bulk.enabling": {
"defaultMessage": "Activando {progress}/{total} {contentType}..."
},
+ "content.selection-bar.bulk.enabling-count": {
+ "defaultMessage": "Activando {count, number} {contentType}"
+ },
"content.selection-bar.bulk.enabling-waiting": {
"defaultMessage": "Activando {contentType}..."
},
"content.selection-bar.bulk.updating": {
"defaultMessage": "Actualizando {progress}/{total} {contentType}..."
},
+ "content.selection-bar.bulk.updating-count": {
+ "defaultMessage": "Actualizando {count, number} {contentType}"
+ },
"content.selection-bar.bulk.updating-waiting": {
"defaultMessage": "Actualizando {contentType}..."
},
@@ -872,6 +956,9 @@
"external-files.permissions-card.add-files-modal.no-search-results": {
"defaultMessage": "No hay archivos que coincidan con tu búsqueda."
},
+ "external-files.permissions-card.add-files-modal.search-placeholder": {
+ "defaultMessage": "Buscar archivos..."
+ },
"external-files.permissions-card.add-files-modal.selected-count": {
"defaultMessage": "{count, plural, one {# archivo seleccionado} other {# archivos seleccionados}}"
},
@@ -1094,6 +1181,21 @@
"external-files.permissions-card.reason.special-permission.description": {
"defaultMessage": "Has obtenido permiso especial para redistribuir este trabajo en tu modpack."
},
+ "external-files.permissions-card.remove-group": {
+ "defaultMessage": "Eliminar grupo"
+ },
+ "external-files.permissions-card.remove-group-confirmation.description": {
+ "defaultMessage": "Esto elimina permanentemente el grupo de atribución y todos los archivos dentro de ellos. Esta ación no se puede deshacer."
+ },
+ "external-files.permissions-card.remove-group-confirmation.title": {
+ "defaultMessage": "¿Borrar {title}?"
+ },
+ "external-files.permissions-card.remove-group-error.title": {
+ "defaultMessage": "No se pudo eliminar el grupo"
+ },
+ "external-files.permissions-card.remove-group-shift-hint": {
+ "defaultMessage": "Mantén pulsada el Shift mientras haces clic para omitir la confirmación."
+ },
"external-files.permissions-card.split-file": {
"defaultMessage": "Eliminar del grupo"
},
@@ -1187,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Archivo guardado"
},
- "files.editor.find-close": {
- "defaultMessage": "Cerrar"
- },
"files.editor.find-in-file": {
"defaultMessage": "Encontrar"
},
@@ -1379,6 +1478,9 @@
"files.row.item-count": {
"defaultMessage": "{count, plural, one {# elemento} other {# elementos}}"
},
+ "files.row.parent-folder": {
+ "defaultMessage": "Carpeta principal"
+ },
"files.table-header.created": {
"defaultMessage": "Creado"
},
@@ -1964,24 +2066,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Seleccionar icono"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Este modpack no incluye contenido adicional."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "No se ha encontrado contenido"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Contenido del modpack"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Cargando contenido..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "No hay proyectos que coincidan con tu búsqueda."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Buscar {count, number} {count, plural, one {proyecto} other {proyectos}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Actual"
},
@@ -2111,6 +2195,9 @@
"label.details": {
"defaultMessage": "Detalles"
},
+ "label.discover-content": {
+ "defaultMessage": "Descubrir contenido"
+ },
"label.done": {
"defaultMessage": "Hecho"
},
@@ -2141,6 +2228,9 @@
"label.game-version": {
"defaultMessage": "Versión del juego"
},
+ "label.hide-installed-content": {
+ "defaultMessage": "Esconder contenido ya instalado"
+ },
"label.hide-selected-content": {
"defaultMessage": "Ocultar contenido seleccionado"
},
@@ -2186,6 +2276,9 @@
"label.password": {
"defaultMessage": "Contraseña"
},
+ "label.permissions": {
+ "defaultMessage": "Permisos"
+ },
"label.plan-custom": {
"defaultMessage": "Personalizado"
},
@@ -2243,6 +2336,9 @@
"label.server": {
"defaultMessage": "Servidor"
},
+ "label.server-only": {
+ "defaultMessage": "Solo servidor"
+ },
"label.servers": {
"defaultMessage": "Servidores"
},
@@ -2714,9 +2810,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Creador en Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Usuario de Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} no podrá enviarte solicitudes de amistad, invitarte a instancias compartidas o invítate a Servers en Modrinth."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "¿Estás seguro de que deseas bloquear este usuario?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Ocurrió un error al bloquear este usuario: Por favor intenta de nuevo."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "No se pudo bloquear el usuario"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} fue bloqueado."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Usuario bloqueado"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Bloquear {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Ver analíticas del usuario"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Gestionar la facturación de los usuarios"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Bloquear"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Crear una colección"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Crear un proyecto"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Ver detalles del usuario"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Gestionar proyectos"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Borrar como afiliado"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Poner como afiliado"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Desbloquear"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# proyecto} other {# proyectos}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Permite las ventanas emergentes para Modrinth e inténtalo de nuevo."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "No se pudo mostrar el perfil de GitHub. Por favor intenta de nuevo."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "No se pudo abrir el perfil de GitHub"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Proveedores de autenticación"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "Correo verificado"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Tiene contraseña"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Tiene TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Cargando..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Métodos de pago"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Ver perfil"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Detalles de usuario"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "Correo no verificado"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "Correo verificado"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "El perfil del usuario no pudo cargar."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Usuario no encontrado"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Afiliado"
+ },
"profile.label.badges": {
"defaultMessage": "Medallas"
},
+ "profile.label.collection": {
+ "defaultMessage": "Colección"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {descarga} other {descargas}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Se unió hace"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "¡Este usuario no tiene colecciones!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "No tienes una colección aun."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "¡Este usuario no tiene proyectos!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "No tienes ningún proyecto aun."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organizaciones"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {proyecto} other {proyectos}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Cuenta oficial de Modrinth"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Cuenta oficial de Modrinth. Obtén soporte en o vía correo a "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Ocurrió un error al desbloquear este usuario. Por favor intenta de nuevo."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "No se pudo desbloquear el usuario"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} fue desbloqueado."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Usuario desbloqueado"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Publicado el {date}"
},
@@ -2732,12 +2981,21 @@
"project-card.environment.client-or-server": {
"defaultMessage": "Cliente o servidor"
},
+ "project-card.environment.dedicated-server": {
+ "defaultMessage": "Servidor dedicado"
+ },
"project-card.environment.server": {
"defaultMessage": "Servidor"
},
+ "project-card.environment.singleplayer": {
+ "defaultMessage": "Un jugador"
+ },
"project-type.all": {
"defaultMessage": "Todos"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Colecciones"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Paquete de Datos} other {Paquetes de Datos}}"
},
@@ -3008,6 +3266,15 @@
"project.follower-count-tooltip": {
"defaultMessage": "{count, number} {count, plural, one {seguidor} other {seguidores}}"
},
+ "project.license.error": {
+ "defaultMessage": "No se pudo coger el texto de la Licencia."
+ },
+ "project.license.loading": {
+ "defaultMessage": "Cargando texto de la licencia..."
+ },
+ "project.license.title": {
+ "defaultMessage": "Licencia"
+ },
"project.online-player-count": {
"defaultMessage": "{count, number} en línea"
},
@@ -3413,6 +3680,12 @@
"project.settings.view.title": {
"defaultMessage": "Vista"
},
+ "project.stats.downloads-label": {
+ "defaultMessage": "{count, plural, one {descarga} other {descargas}}"
+ },
+ "project.stats.followers-label": {
+ "defaultMessage": "{count, plural, one {seguidor} other {seguidores}}"
+ },
"project.versions.channel.alpha.symbol": {
"defaultMessage": "A"
},
@@ -3422,6 +3695,12 @@
"project.versions.channel.release.symbol": {
"defaultMessage": "R"
},
+ "project.versions.filter.toggle-tooltip": {
+ "defaultMessage": "Alternar filtro para {filter}"
+ },
+ "project.versions.platform.modloader.short": {
+ "defaultMessage": "Cargador de mod"
+ },
"project.versions.version.withheld": {
"defaultMessage": "Retenido"
},
@@ -3506,6 +3785,9 @@
"search.filter.option.show_more": {
"defaultMessage": "Mostrar más"
},
+ "search.filter_type.advanced": {
+ "defaultMessage": "Avanzado"
+ },
"search.filter_type.environment": {
"defaultMessage": "Entorno"
},
@@ -4931,9 +5213,216 @@
"settings.pats.title": {
"defaultMessage": "Tokens de acceso personal"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Una breve descripción para contar a todos sobre ti."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Biografía"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Perfil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Foto de perfil"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "La información de tu perfil está visible públicamente en Modrinth y a la Modrinth API ."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "No se pudo actualizar el perfil"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Ocurrió un error al actualizar tu perfil. Por favor intenta de nuevo."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Inicia sesión con una cuenta de Modrinth para editar tu perfil público."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Cuenta de Modrinth requerida"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Un nombre que no distingue de mayúsculas o minúsculas para identificar tu perfil."
+ },
"settings.sessions.title": {
"defaultMessage": "Sesiones"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Acciones"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Usuario"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Estos son los usuarios que bloqueaste en Modrinth. Ellos no pueden:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "No bloqueaste a nadie."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "No se pudo cargar los usuarios bloqueados."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Cargando usuarios bloqueados…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Enviar solicitudes de amistad"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Invitarte a administrar un Servidor en Modrinth."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Invitarte a instancias compartidas"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Usuarios bloqueados"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Desbloquear"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "No se pudo desbloquear el usuario"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Ocurrió un error al desbloquear este usuario. por favor intenta de nuevo."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Desbloquear {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Avatar de {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Controla quien puede enviarte solicitudes de amistad en Modrinth."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Solicitudes de amistad"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "¡Próximamente!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Todos"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Amigos"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Amigos de amigos"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Ninguno"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Controla quien puede enviarte invitaciones a instancias compartidas y servidores en Modrinth."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Invitaciones"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Puedes controlar quien puede interactuar contigo, y gestionar los usuarios bloqueados con una cuenta de Modrinth"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Cuenta de Modrinth requerida"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Social"
+ },
+ "sharing.invite-players-modal.add": {
+ "defaultMessage": "Añadir"
+ },
+ "sharing.invite-players-modal.added": {
+ "defaultMessage": "Añadido"
+ },
+ "sharing.invite-players-modal.already-invited": {
+ "defaultMessage": "Este usuario ya fue invitado."
+ },
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Aplicar"
+ },
+ "sharing.invite-players-modal.avatar-alt": {
+ "defaultMessage": "Avatar de {username}"
+ },
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Personalizado..."
+ },
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Personalizado: {date}"
+ },
+ "sharing.invite-players-modal.edit-invite-link": {
+ "defaultMessage": "Editar enlace de invitación."
+ },
+ "sharing.invite-players-modal.edit-invite-link-title": {
+ "defaultMessage": "Editar enlace de invitación"
+ },
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "En 1 día"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "En 1 hora"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "En 7 días"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "En 6 horas"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "En 3 días"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "En 12 horas"
+ },
+ "sharing.invite-players-modal.expiry-label": {
+ "defaultMessage": "Día de caducidad"
+ },
+ "sharing.invite-players-modal.friends-heading": {
+ "defaultMessage": "Tus amigos - {count}"
+ },
+ "sharing.invite-players-modal.invite": {
+ "defaultMessage": "Invitar"
+ },
+ "sharing.invite-players-modal.invite-expiry-description": {
+ "defaultMessage": "Tu link de invitación expira en {duration}."
+ },
+ "sharing.invite-players-modal.invite-link-heading": {
+ "defaultMessage": "O usa un link de invitación"
+ },
+ "sharing.invite-players-modal.link-copied-text": {
+ "defaultMessage": "La URL del link de invitación fue copiado al portapapeles."
+ },
+ "sharing.invite-players-modal.link-copied-title": {
+ "defaultMessage": "Link Copiado"
+ },
+ "sharing.invite-players-modal.link-copy-failed-title": {
+ "defaultMessage": "No se pudo copiar el link"
+ },
+ "sharing.invite-players-modal.max-uses-label": {
+ "defaultMessage": "Usos máximos"
+ },
+ "sharing.invite-players-modal.no-friends": {
+ "defaultMessage": "No tienes amigos."
+ },
+ "sharing.invite-players-modal.no-search-results": {
+ "defaultMessage": "No se encontraron usuarios coincidentes."
+ },
+ "sharing.invite-players-modal.requested": {
+ "defaultMessage": "Solicitud enviada"
+ },
+ "sharing.invite-players-modal.requested-tooltip": {
+ "defaultMessage": "{username} debe de aceptar tu solicitud de amistad primero"
+ },
+ "sharing.invite-players-modal.save-button": {
+ "defaultMessage": "Guardar"
+ },
+ "sharing.invite-players-modal.search-placeholder": {
+ "defaultMessage": "Introduce el nombre de usuario de Modrinth"
+ },
+ "sharing.invite-players-modal.searching": {
+ "defaultMessage": "Buscando..."
+ },
+ "sharing.invite-players-modal.update-invite-link-failed-title": {
+ "defaultMessage": "No se pudo actualizar el enlace de invitación"
+ },
"tag.category.128x": {
"defaultMessage": "128x"
},
@@ -5468,6 +5957,39 @@
"ui.stacked-admonitions.dismiss-all": {
"defaultMessage": "Descartar todas"
},
+ "unknown-file-warning-modal.dont-install": {
+ "defaultMessage": "No instalar"
+ },
+ "unknown-file-warning-modal.dont-show-again": {
+ "defaultMessage": "No mostar esta advertencia de nuevo"
+ },
+ "unknown-file-warning-modal.header": {
+ "defaultMessage": "Confirmar Instalación"
+ },
+ "unknown-file-warning-modal.install-anyway": {
+ "defaultMessage": "Instalar de todas formas"
+ },
+ "unknown-file-warning-modal.malware-warning": {
+ "defaultMessage": "Malware suele distribuir a través de archivos de mods compartidos en plataformas como Discord."
+ },
+ "unknown-file-warning-modal.mod-warning-body": {
+ "defaultMessage": " no está publicado en Modrinth. Te recomendamos instalar archivos de fuentes de confianza."
+ },
+ "unknown-file-warning-modal.mod-warning-title": {
+ "defaultMessage": "Advertencia de archivo desconocido"
+ },
+ "unknown-file-warning-modal.modpack-warning-body": {
+ "defaultMessage": " contiene archivos que no están publicados en Modrinth. Te recomendamos instalar archivos de fuentes de confianza."
+ },
+ "unknown-file-warning-modal.modpack-warning-title": {
+ "defaultMessage": "Advertencia de archivos desconocidos"
+ },
+ "unknown-file-warning-modal.reviewed-files": {
+ "defaultMessage": "Un archivo es revisado si es que está publicado en Modrinth, sin importar su formato de archivo (Incluyendo .mrpack)."
+ },
+ "unknown-file-warning-modal.unrecognized-files": {
+ "defaultMessage": "Archivos sin reconocer"
+ },
"user.profile.badge.alpha.about.1": {
"defaultMessage": "Este usuario ha estado presente desde la Alpha de Modrinth, la cuál terminó en noviembre de 2020."
},
diff --git a/packages/ui/src/locales/fi-FI/index.json b/packages/ui/src/locales/fi-FI/index.json
index 0f53d3fe32..f7213394cc 100644
--- a/packages/ui/src/locales/fi-FI/index.json
+++ b/packages/ui/src/locales/fi-FI/index.json
@@ -567,3 +567,4 @@
"defaultMessage": "Sinulla on tallentamattomia muutoksia."
}
}
+
diff --git a/packages/ui/src/locales/fil-PH/index.json b/packages/ui/src/locales/fil-PH/index.json
index 554ae942b3..9f07dfbca4 100644
--- a/packages/ui/src/locales/fil-PH/index.json
+++ b/packages/ui/src/locales/fil-PH/index.json
@@ -266,15 +266,6 @@
"content.page-layout.share.project-links": {
"defaultMessage": "Mga link ng proyekto"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alpabetiko"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Pinakabago ang mauuna"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Pinakaluma ang mauuna"
- },
"content.selection-bar.all-already-disabled": {
"defaultMessage": "Nakapatay na ang lahat ng piniling konento"
},
@@ -341,9 +332,6 @@
"external-project-license-status.yes": {
"defaultMessage": "Oo"
},
- "files.editor.find-close": {
- "defaultMessage": "Isara"
- },
"files.editor.find-in-file": {
"defaultMessage": "Hahanapin"
},
@@ -665,24 +653,6 @@
"instances.content-install.no-instances": {
"defaultMessage": "Walang mahanap na magkatugmang instansiya"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Hindi naglalaman ng karagdagang kontento ang modpack na ito."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Walang mahanap na kontento"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Kontentong modpack"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Inihahanda ang kontento..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Walang proyektong tumugma sa iyong paghanap."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Maghanap sa {count, number} {count, plural, one {proyekto} other {na proyekto}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Kasalukuyan"
},
diff --git a/packages/ui/src/locales/fr-FR/index.json b/packages/ui/src/locales/fr-FR/index.json
index 4d7ec28f42..f2807e196f 100644
--- a/packages/ui/src/locales/fr-FR/index.json
+++ b/packages/ui/src/locales/fr-FR/index.json
@@ -138,7 +138,7 @@
"defaultMessage": "Liens affiliés"
},
"button.analytics": {
- "defaultMessage": "Analyses"
+ "defaultMessage": "Statistiques"
},
"button.back": {
"defaultMessage": "Retour"
@@ -617,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Noms des projets"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alphabétique"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Plus récent en premier"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Plus ancien en premier"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Trier par {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Tout mettre à jour"
},
@@ -1298,9 +1286,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Fichier sauvegardé"
},
- "files.editor.find-close": {
- "defaultMessage": "Fermer"
- },
"files.editor.find-in-file": {
"defaultMessage": "Trouver"
},
@@ -2075,33 +2060,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Sélectionnez l'icône"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Aucun contenu supplémentaire n'est inclus dans ce modpack."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Aucun contenu trouvé"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Externe"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "Ce fichier n'est pas publié sur Modrinth."
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Contenu du modpack"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Chargement du contenu..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Aucun projet correspond à votre recherche."
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "Ouvrir dans Slicer"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Rechercher {count, number} {count, plural, one {projet} other {projets}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Actuel"
},
@@ -2234,6 +2192,9 @@
"label.details": {
"defaultMessage": "Détails"
},
+ "label.discover-content": {
+ "defaultMessage": "Découvrir du contenu"
+ },
"label.done": {
"defaultMessage": "Terminé"
},
@@ -2312,6 +2273,9 @@
"label.password": {
"defaultMessage": "Mot de passe"
},
+ "label.permissions": {
+ "defaultMessage": "Permissions"
+ },
"label.plan-custom": {
"defaultMessage": "Personnalisé"
},
@@ -2682,16 +2646,16 @@
"defaultMessage": "Garder les fichiers à jour quand le serveur change"
},
"modal.open-in-app.get-app": {
- "defaultMessage": "Obtenir l'application Modrinth"
+ "defaultMessage": "Obtenir Modrinth App"
},
"modal.open-in-app.opening-automatically": {
- "defaultMessage": "L'application Modrinth s'ouvrira automatiquement..."
+ "defaultMessage": "Modrinth App s'ouvrira automatiquement..."
},
"modal.open-in-app.title": {
"defaultMessage": "L'application Modrinth est en cours d'ouverture"
},
"modal.open-in-app.why-use": {
- "defaultMessage": "Pourquoi utiliser l'application Modrinth"
+ "defaultMessage": "Pourquoi utiliser Modrinth App"
},
"notification.error.title": {
"defaultMessage": "Une erreur est survenue"
@@ -2843,9 +2807,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Un créateur Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Un utilisateur Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} ne va pas pouvoir vous envoyer de demande d'ami, vous inviter aux instances partagées ni à des serveurs Modrinth Hosting."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Êtes-vous sûr de vouloir bloquer cet utilisateur ?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Une erreur s'est produite pendant le blocage de cet utilisateur. Veuillez réessayer."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Impossible de bloquer l'utilisateur"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} a été bloqué."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Utilisateur bloqué"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Bloquer {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Voir les statistiques de l'utilisateur"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Gérer la facturation de l’utilisateur"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Bloquer"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Créer une collection"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Créer un projet"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Voir les détails de l'utilisateur"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Gérer les projets"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Retirer l'affiliation"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Se mettre comme affilié"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Débloquer"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural,one {# projet} other {# projets}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Autorisez les pop-ups pour Modrinth, puis réessayez."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "Le profil GitHub n'a pas pu être récupéré. Veuillez réessayer."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Impossible d'ouvrir le profil GitHub"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Fournisseurs d’authentification"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "Adresse e-mail vérifiée"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Dispose d'un mot de passe"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Dispose d'un TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Chargement..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Moyens de paiements"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Voir le profil"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Détails de l'utilisateur"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "Adresse e-mail non vérifiée"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "Adresse e-mail vérifiée"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Impossible de charger le profil."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Utilisateur introuvable"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Affilié"
+ },
"profile.label.badges": {
"defaultMessage": "Badges"
},
+ "profile.label.collection": {
+ "defaultMessage": "Collection"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {téléchargement} other {téléchargements}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Rejoint"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Cet utilisateur n'a pas de collection !"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Vous n'avez pas encore de collection."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Cet utilisateur n'a pas de projet !"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Vous n'avez pas encore de projet."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organisations"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural,one {projet}other {projets}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Compte Modrinth officiel"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Le compte utilisateur officiel de Modrinth. Obtenez de l’aide via ou par e-mail à "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Une erreur s'est produite pendant le déblocage de cet utilisateur. Veuillez réessayer."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Impossible de débloquer l'utilisateur"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} a été débloqué."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Utilisateur débloqué"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Publié {date}"
},
@@ -2873,6 +2990,9 @@
"project-type.all": {
"defaultMessage": "Tout"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Collections"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Data Pack} other {Data Packs}}"
},
@@ -3665,15 +3785,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Avancé"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Exclure les data packs"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Exclure les mods"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Exclure les plugins"
- },
"search.filter_type.environment": {
"defaultMessage": "Environnement"
},
@@ -4680,7 +4791,7 @@
"defaultMessage": "Détails de l'erreur :"
},
"servers.manage.error.queue-notice": {
- "defaultMessage": "Si vous avez acheté votre serveur Modrinth Hosting récemment, alors il fait actuellement la queue et apparaîtra ici dès qu'il est près. N'essayez pas d'acheter un nouveau serveur. "
+ "defaultMessage": "Si vous avez acheté votre serveur Modrinth Hosting récemment, alors il fait actuellement la queue et apparaîtra ici dès qu'il est prêt. N'essayez pas d'acheter un nouveau serveur. "
},
"servers.manage.error.support-notice": {
"defaultMessage": "Si vous avez besoin de soutien personnalisé à propos du status de votre serveur, veuillez contacter Modrinth Support."
@@ -5099,9 +5210,117 @@
"settings.pats.title": {
"defaultMessage": "Jetons d'accès personnel"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Une courte description pour permettre à tout le monde d'en savoir un peu plus sur vous."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Biographie"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Profil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Photo de profil"
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Impossible de mettre à jour le profil"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Une erreur s'est produite en essayant de mettre à jour votre profil. Veuillez réessayer."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Connectez-vous avec votre compte Modrinth pour personnaliser votre profil public."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Compte Modrinth requis"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Un nom unique, insensible à la casse, permettant d'identifier votre profil."
+ },
"settings.sessions.title": {
"defaultMessage": "Sessions"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Actions"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Utilisateur"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Voici les utilisateurs que vous avez bloqués sur Modrinth. Ils ne peuvent pas :"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Vous n'avez bloqué personne."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Impossible de charger les utilisateurs bloqués."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Chargement des utilisateurs bloqués…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Vous envoyer des demandes d'ami"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Vous inviter à gérer un serveur Modrinth Hosting."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Vous inviter à des instances partagées"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Utilisateurs bloqués"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Débloquer"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Impossible de débloquer l'utilisateur"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Une erreur s'est produite en essayant de débloquer cet utilisateur. Veuillez réessayer."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Débloquer {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "avatar de {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Contrôlez qui peut vous envoyer des demandes d'ami sur Modrinth."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Demandes d'ami"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "À venir !"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Tout le monde"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Amis"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Amis d'amis"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Personne"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Contrôlez qui peut vous inviter à des instances partagées et à des panneaux Modrinth Hosting."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Invitations"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Vous pouvez contrôler qui peut interagir avec vous, et gérer les utilisateurs bloqués avec un compte Modrinth"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Compte Modrinth requis"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Social"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Ajouter"
},
@@ -5111,14 +5330,17 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "Cet utilisateur a déjà été invité."
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Appliquer"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "Avatar de {username}"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Annuler"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Personnaliser..."
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Annuler"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Personnalisé : {date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "Modifier le lien d'invitation."
@@ -5126,6 +5348,24 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "Modifier le lien d'invitation"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "Dans 1 jour"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "Dans 1 heure"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "Dans 7 jours"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "Dans 6 heures"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "Dans 3 jours"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "Dans 12 jours"
+ },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "Date d'expiration"
},
diff --git a/packages/ui/src/locales/fr-FR/meta.json b/packages/ui/src/locales/fr-FR/meta.json
index 0d64aef5ba..29f12c6283 100644
--- a/packages/ui/src/locales/fr-FR/meta.json
+++ b/packages/ui/src/locales/fr-FR/meta.json
@@ -1,7 +1,7 @@
{
"displayName": {
"description": "Please enter the name of the language in its specific variant or regional form (e.g., English (US) for American English, not just English). If the language does not have any specific variant, simply enter the name of the language (e.g., Français, Deutsch).",
- "message": "Français (France)"
+ "message": "Français"
},
"searchTerms": {
"description": "Please provide additional search terms associated with the language, if needed, to enhance the search functionality (e.g., American English, Deutschland). Each search term should be entered on a separate line. Translate as a hyphen (-) if no additional terms are needed.",
diff --git a/packages/ui/src/locales/hu-HU/index.json b/packages/ui/src/locales/hu-HU/index.json
index faa51d7f32..ab3def99e4 100644
--- a/packages/ui/src/locales/hu-HU/index.json
+++ b/packages/ui/src/locales/hu-HU/index.json
@@ -54,7 +54,7 @@
"defaultMessage": "Mégse"
},
"billing.resubscribe-modal.cpus": {
- "defaultMessage": "{sharedCpus} Megosztott CPU-k"
+ "defaultMessage": "{sharedCpus} megosztott CPU"
},
"billing.resubscribe-modal.description": {
"defaultMessage": "Ön újra elő fog fizetni {serverName} szerverre. Az előfizetése újra fog aktiválódni és a szervere kimaradás nélkül tovább fog működni."
@@ -123,7 +123,7 @@
"defaultMessage": "Elfogadás"
},
"button.add-server-to-instance": {
- "defaultMessage": "Szerver hozzáadása a játékpéldányhoz"
+ "defaultMessage": "Szerver hozzáadása a játékprofilhoz"
},
"button.affiliate-links": {
"defaultMessage": "Társulati linkek"
@@ -212,6 +212,9 @@
"button.open-folder": {
"defaultMessage": "Mappa megnyitása"
},
+ "button.open-in-browser": {
+ "defaultMessage": "Megnyitás a böngészőben"
+ },
"button.open-in-folder": {
"defaultMessage": "Megnyitás mappában"
},
@@ -305,6 +308,9 @@
"changelog.product.web": {
"defaultMessage": "Platform"
},
+ "collection-widget.loading-projects": {
+ "defaultMessage": "Projektek betöltése..."
+ },
"collection-widget.project-count": {
"defaultMessage": "{count} projekt"
},
@@ -378,7 +384,7 @@
"defaultMessage": "Néhány kijelölt projekt függőségként van telepítve. Ha törlöd őket, a {context} hibásan működhet, vagy a tőlük függő tartalmak nem fognak megfelelően betöltődni."
},
"content.dependency-warning.context.instance": {
- "defaultMessage": "játékpéldány"
+ "defaultMessage": "játékprofil"
},
"content.dependency-warning.context.server": {
"defaultMessage": "szerver"
@@ -440,6 +446,9 @@
"content.diff-modal.unknown-files-warning": {
"defaultMessage": "Ismeretlen fájlok"
},
+ "content.diff-modal.unknown-project": {
+ "defaultMessage": "Ismeretlen"
+ },
"content.diff-modal.updated-count": {
"defaultMessage": "{count} frissítve"
},
@@ -474,7 +483,7 @@
"defaultMessage": "Biztonsági mentés létrehozása"
},
"content.inline-backup.instance-label": {
- "defaultMessage": "játékpéldány"
+ "defaultMessage": "játékprofil"
},
"content.inline-backup.shift-click-hint": {
"defaultMessage": "A megerősítés kihagyásához tartsd lenyomva a Shift billentyűt a kattintás közben."
@@ -536,18 +545,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Projektnevek"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Ábécé sorrendben"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Legújabbak elöl"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Legrégebbiek elöl"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Rendezés {mode} szerint"
- },
"content.page-layout.update-all": {
"defaultMessage": "Összes frissítése"
},
@@ -588,7 +585,7 @@
"defaultMessage": "{count, number} kiválasztva"
},
"creation-flow.button.create-instance": {
- "defaultMessage": "Játékpéldány létrehozása"
+ "defaultMessage": "Játékprofil létrehozása"
},
"creation-flow.button.create-world": {
"defaultMessage": "Világ létrehozása"
@@ -600,7 +597,7 @@
"defaultMessage": "Importálás"
},
"creation-flow.button.import-instances": {
- "defaultMessage": "{count} játékpéldány importálása"
+ "defaultMessage": "{count} játékprofil importálása"
},
"creation-flow.button.setup-server": {
"defaultMessage": "Szerver beállítása"
@@ -654,7 +651,7 @@
"defaultMessage": "Név"
},
"creation-flow.modal.custom-setup.name.placeholder": {
- "defaultMessage": "Add meg a játékpéldány nevét"
+ "defaultMessage": "Add meg a játékprofil nevét"
},
"creation-flow.modal.custom-setup.options.no-versions-available": {
"defaultMessage": "Nincsenek elérhető verziók"
@@ -698,6 +695,9 @@
"creation-flow.modal.final-config.generate-structures.label": {
"defaultMessage": "Struktúrák generálása"
},
+ "creation-flow.modal.final-config.generator-settings-json.placeholder": {
+ "defaultMessage": "Add meg a generátor beállításait JSON formátumban"
+ },
"creation-flow.modal.final-config.generator-settings.custom": {
"defaultMessage": "Egyéni"
},
@@ -758,20 +758,26 @@
"creation-flow.modal.import-instance.custom-launcher.name": {
"defaultMessage": "Egyéni ({pathName})"
},
+ "creation-flow.modal.import-instance.detecting-launcher-instances": {
+ "defaultMessage": "Indító-játékprofilok észlelése..."
+ },
"creation-flow.modal.import-instance.launcher-instances.title": {
- "defaultMessage": "Más indítók játékpéldányai"
+ "defaultMessage": "Más indítók játékprofiljai"
+ },
+ "creation-flow.modal.import-instance.launcher-path.add": {
+ "defaultMessage": "Add meg az elérési utat az indítóhoz"
},
"creation-flow.modal.import-instance.launcher-path.placeholder": {
"defaultMessage": "Elérési útvonal az indítóhoz..."
},
"creation-flow.modal.import-instance.notification.no-instances-found.text": {
- "defaultMessage": "Nem találtunk importálható játékpéldányokat a megadott útvonalon."
+ "defaultMessage": "Nem találtunk importálható játékprofilokat a megadott útvonalon."
},
"creation-flow.modal.import-instance.notification.no-instances-found.title": {
- "defaultMessage": "Nem található játékpéldány"
+ "defaultMessage": "Nem található játékprofil"
},
"creation-flow.modal.import-instance.search.placeholder": {
- "defaultMessage": "Játékpéldánynév keresése..."
+ "defaultMessage": "Játékprofilnév keresése..."
},
"creation-flow.modal.import-instance.selection.clear-all": {
"defaultMessage": "Összes törlése"
@@ -792,7 +798,7 @@
"defaultMessage": "Modcsomag keresése"
},
"creation-flow.modal.setup-type.instance.description": {
- "defaultMessage": "A játékpéldány egy külön Minecraft-környezet egy adott modbetöltővel, verzióval és modokkal."
+ "defaultMessage": "A játékprofil egy külön Minecraft-környezet egy adott modbetöltővel, verzióval és modokkal."
},
"creation-flow.modal.setup-type.option.custom-setup.description": {
"defaultMessage": "Kezdés alapoktól: válassz betöltőt és játékverziót."
@@ -801,10 +807,10 @@
"defaultMessage": "Egyedi beállítás"
},
"creation-flow.modal.setup-type.option.import-instance.description": {
- "defaultMessage": "Importálj egy játékpéldányt a Prismből, CurseForge-ból, vagy hasonló forrásból."
+ "defaultMessage": "Importálj egy játékprofilt a Prismből, CurseForge-ból, vagy hasonló forrásból."
},
"creation-flow.modal.setup-type.option.import-instance.title": {
- "defaultMessage": "Játékpéldány importálása"
+ "defaultMessage": "Játékprofil importálása"
},
"creation-flow.modal.setup-type.option.modpack-base.description": {
"defaultMessage": "Böngéssz modcsomagokat a Modrinthon, vagy tölts be egyet fájlból."
@@ -822,7 +828,7 @@
"defaultMessage": "Telepítés típusa"
},
"creation-flow.modal.setup-type.title.instance": {
- "defaultMessage": "Játékpéldány típusa"
+ "defaultMessage": "Játékprofil típusa"
},
"creation-flow.modal.setup-type.title.world": {
"defaultMessage": "Világ típusa"
@@ -831,13 +837,13 @@
"defaultMessage": "Modcsomag kiválasztása"
},
"creation-flow.title.create-instance": {
- "defaultMessage": "Játékpéldány létrehozása"
+ "defaultMessage": "Játékprofil létrehozása"
},
"creation-flow.title.create-world": {
"defaultMessage": "Világ létrehozása"
},
"creation-flow.title.import-instance": {
- "defaultMessage": "Játékpéldány importálása"
+ "defaultMessage": "Játékprofil importálása"
},
"creation-flow.title.reset-server": {
"defaultMessage": "Szerver visszaállítása"
@@ -875,6 +881,9 @@
"external-files.permissions-card.custom-license-option": {
"defaultMessage": "Egyéb"
},
+ "external-files.permissions-card.editor.add": {
+ "defaultMessage": "Hozzárendelés hozzáadása"
+ },
"external-files.permissions-card.editor.custom-license-label": {
"defaultMessage": "Hivatkozás a lincenszhez"
},
@@ -905,9 +914,15 @@
"external-files.permissions-card.editor.notes-placeholder": {
"defaultMessage": "Írj valamit ide..."
},
+ "external-files.permissions-card.editor.save": {
+ "defaultMessage": "Hossárendelés mentése"
+ },
"external-files.permissions-card.editor.select-license-label": {
"defaultMessage": "Válassz egy licenszt..."
},
+ "external-files.permissions-card.fallback-group-title": {
+ "defaultMessage": "A(z) {id} hozzárendelési csoport"
+ },
"external-files.permissions-card.file-count": {
"defaultMessage": "{count} fájl"
},
@@ -932,6 +947,9 @@
"external-files.permissions-card.reason.my-project": {
"defaultMessage": "Az én projektem"
},
+ "external-files.permissions-card.remove-group-confirmation.title": {
+ "defaultMessage": "{title} törlése?"
+ },
"external-files.permissions-card.updated-by-moderator": {
"defaultMessage": "Moderátor"
},
@@ -995,9 +1013,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "A fájl mentve"
},
- "files.editor.find-close": {
- "defaultMessage": "Bezárás"
- },
"files.editor.find-in-file": {
"defaultMessage": "Keresés"
},
@@ -1467,7 +1482,7 @@
"defaultMessage": "{storage} GB Tárhely"
},
"hosting.specs.shared-cpus": {
- "defaultMessage": "{cpus} Megosztott CPU-k"
+ "defaultMessage": "{cpus} megosztott CPU"
},
"icon-select.edit": {
"defaultMessage": "Ikon szerkesztése"
@@ -1569,13 +1584,13 @@
"defaultMessage": "Modcsomag újratelepítése..."
},
"installation-settings.removed-incompatible": {
- "defaultMessage": "Eltávolítva (inkompatibilis)"
+ "defaultMessage": "Eltávolítva: (inkompatibilis)"
},
"installation-settings.repair.instance-description": {
"defaultMessage": "Újratelepíti a Minecraft függőségeit, és ellenőrzi, hogy nincsenek-e sérült fájlok. Ez megoldhatja azokat a problémákat, ha a játék az indítóval kapcsolatos hibák miatt nem indul el."
},
"installation-settings.repair.instance-title": {
- "defaultMessage": "Játékpéldány javítása"
+ "defaultMessage": "Játékprofil javítása"
},
"installation-settings.repair.server-description": {
"defaultMessage": "Újratelepíti a betöltőt és a Minecraft függőségeit anélkül, hogy törölné a tartalmaidat. Ez megoldhatja a problémákat, ha a szervered nem indul el megfelelően."
@@ -1590,10 +1605,10 @@
"defaultMessage": "Játékverzió keresése..."
},
"installation-settings.type.instance": {
- "defaultMessage": "játékpéldány"
+ "defaultMessage": "játékprofil"
},
"installation-settings.type.instance-possessive": {
- "defaultMessage": "játékpéldány"
+ "defaultMessage": "játékprofil"
},
"installation-settings.type.server": {
"defaultMessage": "szerver"
@@ -1632,7 +1647,7 @@
"defaultMessage": "{type} javítása"
},
"instance.confirm-repair.instance-label": {
- "defaultMessage": "Játékpéldány"
+ "defaultMessage": "Példány"
},
"instance.confirm-repair.repair-button": {
"defaultMessage": "Javítás"
@@ -1656,10 +1671,10 @@
"defaultMessage": "Ismeretlen játékmód"
},
"instances.content-install.compatible-count": {
- "defaultMessage": "{count} kompatiblis játékpéldány"
+ "defaultMessage": "{count} kompatiblis játékprofil"
},
"instances.content-install.existing-tab": {
- "defaultMessage": "Meglévő játékpéldány"
+ "defaultMessage": "Meglévő játékprofil"
},
"instances.content-install.game-version-placeholder": {
"defaultMessage": "Játékverzió kiválasztása"
@@ -1668,7 +1683,7 @@
"defaultMessage": "Projekt letöltése"
},
"instances.content-install.incompatible-tooltip": {
- "defaultMessage": "Ez a játékpéldány olyan betöltőt vagy játékverziót használ, amelyet ez a projekt nem támogat."
+ "defaultMessage": "Ez a játékprofil olyan betöltőt vagy játékverziót használ, amelyet ez a projekt nem támogat."
},
"instances.content-install.install-button": {
"defaultMessage": "Letöltés"
@@ -1689,7 +1704,7 @@
"defaultMessage": "Add meg a profil nevét"
},
"instances.content-install.new-tab": {
- "defaultMessage": "Új profil"
+ "defaultMessage": "Új játékprofil"
},
"instances.content-install.no-instances": {
"defaultMessage": "Nem található kompatibilis profil"
@@ -1703,24 +1718,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Ikon feltöltése"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Ez a modcsomag nem tartalmaz további tartalmakat."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Nincsen tartalom"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Modcsomag tartalma"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Tartalmak betöltése..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Nincsen olyan projekt ami keresnél."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Keresés {count, number} projekt között"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Jelenlegi"
},
@@ -1788,7 +1785,7 @@
"defaultMessage": "Frissítés a(z) {version} verzióra"
},
"instances.updater-modal.warning-app": {
- "defaultMessage": "A frissítés meghibásodást okozhat a játékpéldányban. Először nézd át a változásnaplót, és készíts biztonsági mentést."
+ "defaultMessage": "A frissítés meghibásodást okozhat a játékprofilban. Először nézd át a változásnaplót, és készíts biztonsági mentést."
},
"instances.updater-modal.warning-web": {
"defaultMessage": "A frissítés meghibásodást okozhat a világban. Először nézd át a változásnaplót, és készíts biztonsági mentést."
@@ -1853,6 +1850,9 @@
"label.details": {
"defaultMessage": "Részletek"
},
+ "label.discover-content": {
+ "defaultMessage": "Tartalom felfedezése"
+ },
"label.done": {
"defaultMessage": "Kész"
},
@@ -2298,7 +2298,7 @@
"defaultMessage": "Szerezd meg a Modrinth Appot"
},
"modal.open-in-app.opening-automatically": {
- "defaultMessage": "A Modrinth alkalmazás automatikusan megnyílik..."
+ "defaultMessage": "A Modrinth App automatikusan megnyílik..."
},
"modal.open-in-app.title": {
"defaultMessage": "A Modrinth App megnyitása"
@@ -2453,9 +2453,135 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Egy Modrinth fejlesztő."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Egy Modrinth felhasználó."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} nem fog tudni neked barátkérelmet küldeni, meghívni téged megosztott játékprofilokba, illetve meghívni téged a Modrinth Hosting szervereire."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Biztosan le szeretnéd tiltani ezt a felhasználót?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Hiba történt a felhasználó letiltása közben. Kérlek próbáld meg újra."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "A felhasználó letiltása nem sikerült"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} le lett tiltva"
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Felhasználó letiltva"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "{username} letiltása"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Felhasználói statisztikák megtekintése"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Letiltás"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Gyűjtemény létrehozása"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Projekt létrehozása"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Felhasználói adatok megtekintése"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Projektek kezelése"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Letiltás feloldása"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count} projekt"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Hitelesítési szolgáltatók"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "E-mail cím hitelesítve"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Van jelszava"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Kétlépcsős hitelesítést használ"
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Fizetési módok"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Felhasználó adatai"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "Nem hitelesített e-mail cím"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "Hitelesített e-mail cím"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "A felhasználói profil betöltése nem sikerült."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Felhasználó nem található"
+ },
"profile.label.badges": {
"defaultMessage": "Jelvények"
},
+ "profile.label.collection": {
+ "defaultMessage": "Gyűjtemény"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "letöltés"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Csatlakozott"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Ennek a felhasználónak nincsenek gyűjteményei!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Még nincs gyűjteményed."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Ennek a felhasználónak nincsenek projektjei!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Még nincsenek projektjeid."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Szervezetek"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "projekt"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Hivatalos Modrinth-fiók"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "A Modrinth hivatalos felhasználói fiókja. Támogatás a oldalon kaphatsz vagy e-mailben a címen."
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Hiba történt a felhasználó letiltásának feloldása közben. Kérlek próbáld meg újra."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "A felhasználó letiltásának feloldása nem sikerült"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} letiltása fel lett oldva"
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Felhasználó letiltása feloldva"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Közzététel: {date}"
},
@@ -2477,8 +2603,11 @@
"project-type.all": {
"defaultMessage": "Összes"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Gyűjtemények"
+ },
"project-type.datapack.capital": {
- "defaultMessage": "{count, plural, one {Adatcsomag} other {Adatcsomagok}}"
+ "defaultMessage": "adatcsomag"
},
"project-type.datapack.category": {
"defaultMessage": "Adatcsomagok"
@@ -2487,7 +2616,7 @@
"defaultMessage": "adatcsomag"
},
"project-type.mod.capital": {
- "defaultMessage": "{count, plural,one {Mod} other {Modok}}"
+ "defaultMessage": "mod"
},
"project-type.mod.category": {
"defaultMessage": "Modok"
@@ -2505,7 +2634,7 @@
"defaultMessage": "modcsomag"
},
"project-type.plugin.capital": {
- "defaultMessage": "{count, plural,one {Bővítmény} other {Bővítmények}}"
+ "defaultMessage": "bővítmény"
},
"project-type.plugin.category": {
"defaultMessage": "Bővítmények"
@@ -2523,7 +2652,7 @@
"defaultMessage": "projekt"
},
"project-type.resourcepack.capital": {
- "defaultMessage": "{count, plural,one {Forráscsomag} other {Forráscsomagok}}"
+ "defaultMessage": "forráscsomag"
},
"project-type.resourcepack.category": {
"defaultMessage": "Forráscsomagok"
@@ -2541,7 +2670,7 @@
"defaultMessage": "szerver"
},
"project-type.shader.capital": {
- "defaultMessage": "{count, plural,one {Shader} other {Shaderek}}"
+ "defaultMessage": "shader"
},
"project-type.shader.category": {
"defaultMessage": "Shaderek"
@@ -2735,6 +2864,9 @@
"project.follower-count-tooltip": {
"defaultMessage": "{count, number} követő"
},
+ "project.license.title": {
+ "defaultMessage": "Licensz"
+ },
"project.online-player-count": {
"defaultMessage": "{count, number} online"
},
@@ -3053,6 +3185,9 @@
"project.settings.environment.notice.review-options.description": {
"defaultMessage": "Nemrégiben átalakítottuk a Modrinth környezetrendszerét, és mostantól új beállítási lehetőségek állnak rendelkezésre. Kérjük, győződj meg arról, hogy az alábbiak közül a megfelelő opciót választottad ki, majd ha kész vagy, kattints az „Ellenőrzés” gombra!"
},
+ "project.settings.environment.notice.review-options.title": {
+ "defaultMessage": "Kérjük, tekintsd át az alábbi lehetőségeket"
+ },
"project.settings.environment.notice.wrong-project-type.description": {
"defaultMessage": "Csak a mod- vagy modcsomag-projektek rendelkezhetnek környezeti metaadatokkal."
},
@@ -3132,7 +3267,7 @@
"defaultMessage": "letöltés"
},
"project.stats.followers-label": {
- "defaultMessage": "{count} követő"
+ "defaultMessage": "követő"
},
"project.versions.channel.alpha.symbol": {
"defaultMessage": "A"
@@ -3143,6 +3278,9 @@
"project.versions.channel.release.symbol": {
"defaultMessage": "K"
},
+ "project.versions.platform.modloader.short": {
+ "defaultMessage": "ModLoader"
+ },
"project.visibility.archived": {
"defaultMessage": "Archiválva"
},
@@ -3354,7 +3492,7 @@
"defaultMessage": "Újraindított szerver"
},
"servers.access-page.activity-log-filter.instances": {
- "defaultMessage": "Játékpéldányok"
+ "defaultMessage": "Játékprofilok"
},
"servers.access-page.activity-log-filter.server-scoped-instance": {
"defaultMessage": "Szerver"
@@ -3420,7 +3558,7 @@
"defaultMessage": "Szerkesztő"
},
"servers.access-page.role.editor-description": {
- "defaultMessage": "A játékpéldány tartalmának, fájljainak, biztonsági mentéseinek és egyéb beállításainak kezelése."
+ "defaultMessage": "A játékprofil tartalmának, fájljainak, biztonsági mentéseinek és egyéb beállításainak kezelése."
},
"servers.access-page.role.owner": {
"defaultMessage": "Tulajdonos"
@@ -3498,7 +3636,7 @@
"defaultMessage": "Felhasználó"
},
"servers.audit-log.column.world": {
- "defaultMessage": "Játékpéldány"
+ "defaultMessage": "Játékprofil"
},
"servers.audit-log.column.world.tooltip-title": {
"defaultMessage": "Hamarosan érkezik!"
@@ -3519,7 +3657,7 @@
"defaultMessage": "Leválasztott modcsomag-verzió "
},
"servers.audit-log.event.server-plan.ram-mb": {
- "defaultMessage": "{amount, number} MB RAM"
+ "defaultMessage": "{amount, number} MB memória"
},
"servers.audit-log.event.server-plan.storage-gb": {
"defaultMessage": "{amount, number} GB tárhely"
@@ -3723,7 +3861,7 @@
"defaultMessage": "Szerkesztő"
},
"servers.grant-access-modal.role.editor-description": {
- "defaultMessage": "A játékpéldány tartalmának, fájljainak, biztonsági mentéseinek és egyéb beállításainak kezelése."
+ "defaultMessage": "A játékprofil tartalmának, fájljainak, biztonsági mentéseinek és egyéb beállításainak kezelése."
},
"servers.grant-access-modal.role.label": {
"defaultMessage": "Rang kiválasztása"
@@ -3806,6 +3944,9 @@
"servers.list-empty.no-servers-title": {
"defaultMessage": "Még nincsenek szerverek"
},
+ "servers.list-empty.one-click-mod-installs-description": {
+ "defaultMessage": "Válaszd ki a kedvenc modjaidat, a többit bízd ránk!"
+ },
"servers.list-empty.one-click-mod-installs-title": {
"defaultMessage": "Modok telepítése egy kattintással"
},
@@ -3899,6 +4040,9 @@
"servers.manage.no-servers-found": {
"defaultMessage": "Nem található szerver."
},
+ "servers.manage.no-shared-servers-found": {
+ "defaultMessage": "Egy megosztott szerver sem egyezik a kereséssel."
+ },
"servers.manage.reload-button": {
"defaultMessage": "Újra"
},
@@ -3920,6 +4064,9 @@
"servers.manage.settings-hint.title": {
"defaultMessage": "A szerver beállításait áthelyeztük"
},
+ "servers.manage.shared-servers-title": {
+ "defaultMessage": "Megosztott szerverek"
+ },
"servers.medal-listing.countdown.remaining": {
"defaultMessage": "{days} nap {hours} óra {minutes} perc és {seconds} másodperc van hátra..."
},
@@ -4017,7 +4164,7 @@
"defaultMessage": "Legnépszerűbb"
},
"servers.purchase.step.plan.select": {
- "defaultMessage": "Válasz előfizetést"
+ "defaultMessage": "Csomag kiválasztása"
},
"servers.purchase.step.plan.small": {
"defaultMessage": "Kicsi"
@@ -4026,7 +4173,7 @@
"defaultMessage": "Tökéletes 1–5 barát számára, néhány kisebb moddal."
},
"servers.purchase.step.plan.title": {
- "defaultMessage": "Előfizetés"
+ "defaultMessage": "Csomag"
},
"servers.purchase.step.plan.your-current-plan": {
"defaultMessage": "Jelenlegi csomag"
@@ -4046,6 +4193,15 @@
"servers.region.custom.prompt-ram-only": {
"defaultMessage": "memória"
},
+ "servers.region.north-america-central": {
+ "defaultMessage": "Észak-Amerika középső része"
+ },
+ "servers.region.north-america-east": {
+ "defaultMessage": "Észak-Amerika keleti része"
+ },
+ "servers.region.north-america-west": {
+ "defaultMessage": "Észak-Amerika nyugati része"
+ },
"servers.region.prompt": {
"defaultMessage": "Hol szeretnéd elhelyezni a szerveredet?"
},
@@ -4166,6 +4322,9 @@
"settings.display.theme.title": {
"defaultMessage": "Téma"
},
+ "settings.feature-flags.title": {
+ "defaultMessage": "Funkciójelzők"
+ },
"settings.language.categories.default": {
"defaultMessage": "Alapértelmezett nyelvek"
},
@@ -4199,9 +4358,120 @@
"settings.pats.title": {
"defaultMessage": "Személyes hozzáférési tokenek"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Egy rövid leírás, hogy mindenki megismerjen téged."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Bemutatkozás"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Profil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Profilkép"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "A profiladataid nyilvánosan megtekinthetők a Modrinthon és a Modrinth API -n keresztül."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "A profil frissítése nem sikerült"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Hiba történt a profilod frissítése közben. Kérlek, próbáld meg újra."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Jelentkezz be egy Modrinth-fiókkal, hogy személyre szabhasd a nyilvános profilodat."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Modrinth-fiók szükséges"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Egyedi, kis- és nagybetűktől független név a profilod azonosításához."
+ },
"settings.sessions.title": {
"defaultMessage": "Munkamenetek"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Műveletek"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Felhasználó"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Ezek azok a felhasználók, akiket a Modrinthon letiltottál. Ők nem tudnak:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Nem tiltottál le senkit."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "A letiltott felhasználók betöltése nem sikerült."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "A letiltott felhasználók betöltése…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Barátkérelmeket küldeni neked"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Meghívni téged, hogy kezelj egy Modrinth Hosting szervert."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Meghívni téged megosztott játékprofilokba"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Letiltott felhasználók"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Letiltás feloldása"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "A felhasználó letiltásának feloldása nem sikerült"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Hiba történt a felhasználó letiltásának feloldása közben. Kérlek próbáld meg újra."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "{username} letiltásának feloldása"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "{username} avatárja"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Állítsd be, hogy ki küldhet neked barátkérelmeket a Modrinthon."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Barátkérelmek"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Hamarosan érkezik!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Bárki"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Barátok"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "A barátok barátai"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Senki"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Állítsd be, hogy kik küldhetnek neked meghívókat a megosztott játékprofilokhoz és a Modrinth Hosting vezérlőpultjaihoz."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Meghívók"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "A Modrinth-fiókod segítségével beállíthatod, hogy kik léphetnek veled kapcsolatba, és kezelheted a letiltott felhasználókat"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Modrinth-fiók szükséges"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Közösségi"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Hozzáadás"
},
@@ -4214,12 +4484,6 @@
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "{username} avatárja"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Mégse"
- },
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Mégse"
- },
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "Meghívólink szerkesztése."
},
@@ -4247,6 +4511,15 @@
"sharing.invite-players-modal.link-copied-title": {
"defaultMessage": "Link kimásolva"
},
+ "sharing.invite-players-modal.link-copy-failed-title": {
+ "defaultMessage": "A link másolása nem sikerült"
+ },
+ "sharing.invite-players-modal.max-uses-label": {
+ "defaultMessage": "Maximális felhasználások száma"
+ },
+ "sharing.invite-players-modal.no-friends": {
+ "defaultMessage": "Nem találhatók barátok."
+ },
"sharing.invite-players-modal.no-search-results": {
"defaultMessage": "Nem található a keresésnek megfelelő felhasználó."
},
@@ -4775,6 +5048,9 @@
"ui.stacked-admonitions.alert-count": {
"defaultMessage": "{count} figyelmeztetés"
},
+ "unknown-file-warning-modal.malware-warning": {
+ "defaultMessage": "A rosszindulatú programokat gyakran modfájlokon keresztül terjesztik, például a Discordhoz hasonló platformokon történő megosztás révén."
+ },
"unknown-file-warning-modal.modpack-warning-title": {
"defaultMessage": "Ismeretlen fájlok"
},
@@ -4873,5 +5149,14 @@
},
"user.profile.badge.staff.name": {
"defaultMessage": "A Modrinth-csapat"
+ },
+ "version.section.content": {
+ "defaultMessage": "Tartalom"
+ },
+ "version.section.content.search-placeholder": {
+ "defaultMessage": "Tartalom keresése..."
+ },
+ "version.section.required-content": {
+ "defaultMessage": "Kötelező tartalom"
}
}
diff --git a/packages/ui/src/locales/id-ID/index.json b/packages/ui/src/locales/id-ID/index.json
index 8ad53fed3f..6235f9fe9a 100644
--- a/packages/ui/src/locales/id-ID/index.json
+++ b/packages/ui/src/locales/id-ID/index.json
@@ -503,18 +503,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nama proyek"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Menurut abjad"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Terbaru dahulu"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Tertua dahulu"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Urutkan berdasarkan {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Perbarui semua"
},
@@ -824,9 +812,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Berkas disimpan"
},
- "files.editor.find-close": {
- "defaultMessage": "Tutup"
- },
"files.editor.find-in-file": {
"defaultMessage": "Cari"
},
@@ -1175,24 +1160,6 @@
"instance.worlds.game_mode.unknown": {
"defaultMessage": "Mode permainan tak dikenal"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Paket mod ini tidak termasuk konten tambahan."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Konten tidak ditemukan"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Konten paket mod"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Sedang memuat konten..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Tidak ada proyek yang cocok dengan pencarian Anda."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Cari {count, number} {count, plural, other {proyek}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Saat ini"
},
diff --git a/packages/ui/src/locales/it-IT/index.json b/packages/ui/src/locales/it-IT/index.json
index 8ff9e91298..28ce02f5c1 100644
--- a/packages/ui/src/locales/it-IT/index.json
+++ b/packages/ui/src/locales/it-IT/index.json
@@ -596,18 +596,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nomi dei progetti"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabetico"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Più recenti prima"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Meno recenti prima"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Ordina per {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Aggiorna tutto"
},
@@ -732,7 +720,7 @@
"defaultMessage": "Nessuna versione trovata"
},
"creation-flow.modal.final-config.additional-settings.title": {
- "defaultMessage": "Opzioni aggiuntive"
+ "defaultMessage": "Impostazioni aggiuntive"
},
"creation-flow.modal.final-config.backup.before-reset-server.name": {
"defaultMessage": "Prima della reimpostazione"
@@ -1173,7 +1161,7 @@
"defaultMessage": "Elimina gruppo"
},
"external-files.permissions-card.remove-group-confirmation.description": {
- "defaultMessage": "Questo gruppo di attribuzione sarà rimosso per sempre. Quest'azione non può essere annullata."
+ "defaultMessage": "Il gruppo di attribuzione e i suoi contenuti saranno eliminati per sempre. Questa azione è irreversibile."
},
"external-files.permissions-card.remove-group-confirmation.title": {
"defaultMessage": "Eliminare {title}?"
@@ -1248,10 +1236,10 @@
"defaultMessage": "Elimina file"
},
"files.delete-modal.warning.file": {
- "defaultMessage": "Questo file verrà eliminato permanentemente. Questa azione non può essere annullata."
+ "defaultMessage": "Il file sarà eliminato per sempre. Questa azione è irreversibile."
},
"files.delete-modal.warning.folder": {
- "defaultMessage": "Questa cartella e tutti i suoi contenuti verranno eliminati permanentemente. Questa azione non può essere annullata."
+ "defaultMessage": "La cartella e i suoi contenuti saranno eliminati per sempre. Questa azione è irreversibile."
},
"files.editor.failed-to-open-text": {
"defaultMessage": "Impossibile caricare i contenuti del file."
@@ -1271,9 +1259,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "File salvato"
},
- "files.editor.find-close": {
- "defaultMessage": "Chiudi"
- },
"files.editor.find-in-file": {
"defaultMessage": "Trova"
},
@@ -2039,33 +2024,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Scegli un'icona"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Questo pacchetto di mod non include alcun contenuto aggiuntivo."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Nessun contenuto trovato"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Esterno"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "Questo file non è su Modrinth."
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Contenuto del pacchetto"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Caricamento contenuto..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Nessun progetto corrisponde alla tua ricerca."
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "Apri con Slicer"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Cerca tra {count, number} {count, plural, one {progetto} other {progetti}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Attuale"
},
@@ -2198,6 +2156,9 @@
"label.details": {
"defaultMessage": "Dettagli"
},
+ "label.discover-content": {
+ "defaultMessage": "Sfoglia i contenuti"
+ },
"label.done": {
"defaultMessage": "Fatto"
},
@@ -2276,6 +2237,9 @@
"label.password": {
"defaultMessage": "Password"
},
+ "label.permissions": {
+ "defaultMessage": "Permessi"
+ },
"label.plan-custom": {
"defaultMessage": "Ad hoc"
},
@@ -2807,9 +2771,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Creatore su Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Utente di Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} non potrà inviarti richieste di amicizia, invitarti alle istanze condivise o invitarti ai server Modrinth Hosting."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Vuoi davvero bloccare quest'utente?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Sì è verificato un errore nel bloccare l'utente. Riprova più tardi."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Impossibile bloccare l'utente"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "Utente {username} bloccato."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Utente bloccato"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Blocca {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Mostra analitiche utente"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Gestisci fatturato utente"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Blocca"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Crea una raccolta"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Crea un progetto"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Mostra info utente"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Gestisci progetti"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Rimuovi da affiliato"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Imposta come affiliato"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Sblocca"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# progetto} other {# progetti}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Consentì i pop-up per Modrinth, poi riprova."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "Impossibile recuperare il profilo GitHub. Riprova più tardi."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Errore nell'apertura del profilo GitHub"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Fornitori d'autenticazione"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "Email verificata"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Usa una password"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Usa un TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Caricamento..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Metodi di pagamento"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Visita profilo"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Informazioni"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "Email non verificata"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "Email verificata"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Non è stato possibile caricare il profilo."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Utente non trovato"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Affiliato"
+ },
"profile.label.badges": {
"defaultMessage": "Distintivi"
},
+ "profile.label.collection": {
+ "defaultMessage": "Raccolta"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "download"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Iscrizione"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Nessuna raccolta qui!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Ancora nessuna raccolta."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Nessun progetto qui!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Ancora nessun progetto."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organizzazioni"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {progetto} other {progetti}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Account Modrinth ufficiale"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "L'account ufficiale di Modrinth. Ricevi assistenza presso o tramite mail presso "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Sì è verificato un errore nello sbloccare l'utente. Riprova più tardi."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Impossibile sbloccare l'utente"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "Utente {username} sbloccato."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Utente sbloccato"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Pubblicato {date}"
},
@@ -2837,6 +2954,9 @@
"project-type.all": {
"defaultMessage": "Tutto"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Raccolte"
+ },
"project-type.datapack.capital": {
"defaultMessage": "Pacchett{count, plural, one {o} other {i}} di dati"
},
@@ -3629,15 +3749,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Avanzate"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Escludi pacchetti di dati"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Escludi mod"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Escludi plugin"
- },
"search.filter_type.environment": {
"defaultMessage": "Ambiente"
},
@@ -4464,7 +4575,7 @@
"defaultMessage": "Installazione fallita"
},
"servers.installing-banner.error.internal-platform": {
- "defaultMessage": "Si è verificato un errore nell'installazione della piattaforma. Riprova più tardi."
+ "defaultMessage": "Si è verificato un errore durante l'installazione della piattaforma. Riprova più tardi."
},
"servers.installing-banner.error.invalid-loader-version": {
"defaultMessage": "Questa versione di Minecraft o del loader non è potuta essere installata. Potrebbe essere non valida o non supportata."
@@ -5063,9 +5174,120 @@
"settings.pats.title": {
"defaultMessage": "Token di accesso (PAT)"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Una breve descrizione per raccontare a tutti qualcosa su di te."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Bio"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Profilo"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Foto profilo"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "Le informazioni del tuo profilo sono visibili pubblicamente su Modrinth e tramite l''API di Modrinth ."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Impossibile salvare il profilo"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Si è verificato un errore nel salvataggio del profilo. Riprova più tardi."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Accedi con un account Modrinth per personalizzare il tuo profilo pubblico."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Account Modrinth richiesto"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Un nome univoco per identificare il tuo profilo (maiuscole irrilevanti)."
+ },
"settings.sessions.title": {
"defaultMessage": "Sessioni"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Azioni"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Utente"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Questi sono gli utenti che hai bloccato su Modrinth. Non potranno:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Non hai bloccato nessuno."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Impossibile caricare gli utenti bloccati."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Caricamento utenti bloccati…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Inviarti richieste di amicizia"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Invitarti a gestire un server Modrinth Hosting."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Invitarti nelle istanze condivise"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Utenti bloccati"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Sblocca"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Impossibile sbloccare l'utente"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Sì è verificato un errore nello sbloccare l'utente. Riprova più tardi."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Sblocca {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Foto profilo di {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Controlla chi può inviarti richieste d'amicizia su Modrinth."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Richieste di amicizia"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "In arrivo!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Tutti"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Amici"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Amici di amici"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Nessuno"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Controlla chi può invitarti alle istanze condivise e pannelli di Modrinth Hosting."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Inviti"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Puoi controllare chi può interagire con te e gestire gli utenti bloccati con un account Modrinth"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Account Modrinth richiesto"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Interazioni"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Aggiungi"
},
@@ -5075,14 +5297,17 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "Quest'utente ha già ricevuto un invito."
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Applica"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "Foto profilo di {username}"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Annulla"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Personalizzata..."
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Annulla"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Personalizzata: {date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "Modifica link d'invito."
@@ -5090,6 +5315,24 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "Modifica link di invito"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "In 1 giorno"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "In 1 ora"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "In 7 giorni"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "In 6 ore"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "In 3 giorni"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "In 12 ore"
+ },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "Scadenza"
},
@@ -5430,7 +5673,7 @@
"defaultMessage": "SMP"
},
"tag.category.social": {
- "defaultMessage": "Società"
+ "defaultMessage": "Interazione"
},
"tag.category.storage": {
"defaultMessage": "Immagazzinamento"
diff --git a/packages/ui/src/locales/ja-JP/index.json b/packages/ui/src/locales/ja-JP/index.json
index 10ed45ffbf..5ea12218d0 100644
--- a/packages/ui/src/locales/ja-JP/index.json
+++ b/packages/ui/src/locales/ja-JP/index.json
@@ -1,6 +1,6 @@
{
"action.no-permission": {
- "defaultMessage": "権限がありません"
+ "defaultMessage": "権限がありません。"
},
"affiliate.create.button": {
"defaultMessage": "アフィリエイトリンクを作成"
@@ -449,12 +449,18 @@
"content.diff-modal.added-count": {
"defaultMessage": "{count} 件追加されました"
},
+ "content.diff-modal.config-files-updated": {
+ "defaultMessage": "設定変更"
+ },
"content.diff-modal.diff-type.added": {
"defaultMessage": "追加 (依存関係)"
},
"content.diff-modal.diff-type.removed": {
"defaultMessage": "無効化済み"
},
+ "content.diff-modal.diff-type.removed-disabled": {
+ "defaultMessage": "削除済み(無効)"
+ },
"content.diff-modal.diff-type.updated": {
"defaultMessage": "アップデート済み"
},
@@ -470,12 +476,33 @@
"content.diff-modal.external-diff-type.updated": {
"defaultMessage": "更新されました"
},
+ "content.diff-modal.game-version-updated": {
+ "defaultMessage": "ゲームバージョン変更"
+ },
"content.diff-modal.install-anyway": {
"defaultMessage": "それでもインストールする"
},
+ "content.diff-modal.loader-updated": {
+ "defaultMessage": "Modローダー変更"
+ },
+ "content.diff-modal.modpack-linked": {
+ "defaultMessage": "リンク済みモッドパック"
+ },
+ "content.diff-modal.modpack-unlinked": {
+ "defaultMessage": "未リンクのモッドパック"
+ },
+ "content.diff-modal.modpack-updated": {
+ "defaultMessage": "Modパックのアップデート"
+ },
+ "content.diff-modal.no-content-changes": {
+ "defaultMessage": "変更点なし"
+ },
"content.diff-modal.removed-count": {
"defaultMessage": "{count} 件削除されました"
},
+ "content.diff-modal.removed-disabled-count": {
+ "defaultMessage": "{count}件 削除済み(無効)"
+ },
"content.diff-modal.reviewed-files": {
"defaultMessage": "ファイルは、(.mrpackなどのファイル形式に関係なく)Modrinthに公開されたもののみ審査されます。"
},
@@ -587,18 +614,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "プロジェクト名"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "名前順"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "新しい順"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "古い順"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "{mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "すべて更新"
},
@@ -959,6 +974,9 @@
"external-files.permissions-card.attribution.moderation-status.passed": {
"defaultMessage": "審査を通りました"
},
+ "external-files.permissions-card.attribution.moderation-status.rejected-proof": {
+ "defaultMessage": "証明が拒否されました"
+ },
"external-files.permissions-card.badge.attributed": {
"defaultMessage": "完了しました"
},
@@ -983,6 +1001,9 @@
"external-files.permissions-card.editor.all-rights-reserved": {
"defaultMessage": "無断転載禁止/ライセンスなし"
},
+ "external-files.permissions-card.editor.custom-license-label": {
+ "defaultMessage": "ライセンスへのリンク"
+ },
"external-files.permissions-card.editor.custom-license-my-project-label": {
"defaultMessage": "ライセンス名はSPDX識別子であることが望ましい"
},
@@ -1019,9 +1040,36 @@
"external-files.permissions-card.editor.notes-placeholder": {
"defaultMessage": "何かここに書いてください..."
},
+ "external-files.permissions-card.editor.proof-image-alt": {
+ "defaultMessage": "証明のスクリーンショット {n}"
+ },
+ "external-files.permissions-card.editor.proof-image-remove": {
+ "defaultMessage": "画像を削除"
+ },
+ "external-files.permissions-card.editor.proof-images-label": {
+ "defaultMessage": "証明画像"
+ },
+ "external-files.permissions-card.editor.proof-images-upload-prompt": {
+ "defaultMessage": "ドラッグ&ドロップしてアップロード、またはクリックして画像を選択"
+ },
+ "external-files.permissions-card.editor.proof-warning.body": {
+ "defaultMessage": "虚偽の申告や画像の改ざんが発覚した場合、プロジェクトの削除およびアカウントの停止措置が取られる可能性があります。"
+ },
+ "external-files.permissions-card.editor.proof-warning.title": {
+ "defaultMessage": "Modrinthスタッフが提出された証明を確認・検証する場合があります"
+ },
+ "external-files.permissions-card.editor.save": {
+ "defaultMessage": "帰属情報を保存"
+ },
"external-files.permissions-card.editor.select-license-label": {
"defaultMessage": "ライセンスを選んでください…"
},
+ "external-files.permissions-card.editor.type-label": {
+ "defaultMessage": "パーミッションの理由"
+ },
+ "external-files.permissions-card.error.custom-license-required": {
+ "defaultMessage": "ライセンスへのリンクを含めてください。ライセンスがない場合は、「All Rights Reserved / ライセンスなし」を選択することをお勧めします。"
+ },
"external-files.permissions-card.error.explanation-or-images-required": {
"defaultMessage": "説明や根拠となる画像を少なくとも一枚提示してください。"
},
@@ -1130,12 +1178,30 @@
"external-files.permissions-card.reason.special-permission.description": {
"defaultMessage": "あなたは、自身のModパックでこの作品を再配布するための特別な許可を得ています。"
},
+ "external-files.permissions-card.remove-group": {
+ "defaultMessage": "グループを削除"
+ },
+ "external-files.permissions-card.remove-group-confirmation.description": {
+ "defaultMessage": "この操作により、この帰属グループとグループ内のすべてのファイルが完全に削除されます。この操作を取り消すことはできません。"
+ },
+ "external-files.permissions-card.remove-group-confirmation.title": {
+ "defaultMessage": "「{title}」を削除しますか?"
+ },
+ "external-files.permissions-card.remove-group-error.title": {
+ "defaultMessage": "グループを削除できませんでした"
+ },
+ "external-files.permissions-card.remove-group-shift-hint": {
+ "defaultMessage": "Shiftキーを押しながらクリックすると確認をスキップします"
+ },
"external-files.permissions-card.split-file": {
"defaultMessage": "グループから削除する"
},
"external-files.permissions-card.split-file-error.title": {
"defaultMessage": "ファイルの分割に失敗"
},
+ "external-files.permissions-card.unnamed-multi-group-title": {
+ "defaultMessage": "{filename} ほか{count}件"
+ },
"external-files.permissions-card.updated-by-moderator": {
"defaultMessage": "モデレーター"
},
@@ -1220,9 +1286,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "保存済み"
},
- "files.editor.find-close": {
- "defaultMessage": "閉じる"
- },
"files.editor.find-in-file": {
"defaultMessage": "検索"
},
@@ -2000,24 +2063,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "アイコンを選択"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "このModパックに追加コンテンツは一切含まれていません。"
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "コンテンツが見つかりません"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Modpackコンテンツ"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "コンテンツを読み込み中…"
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "該当するプロジェクトがありません。"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "{count, number}件のプロジェクトを検索"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "現在"
},
@@ -2150,6 +2195,9 @@
"label.details": {
"defaultMessage": "詳細"
},
+ "label.discover-content": {
+ "defaultMessage": "コンテンツを探す"
+ },
"label.done": {
"defaultMessage": "完了"
},
@@ -2228,6 +2276,9 @@
"label.password": {
"defaultMessage": "パスワード"
},
+ "label.permissions": {
+ "defaultMessage": "権限"
+ },
"label.plan-custom": {
"defaultMessage": "カスタム"
},
@@ -2759,9 +2810,90 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Modrinth クリエイター"
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Modrinth ユーザー"
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} はあなたにフレンドリクエストの送信、共有インスタンスへの招待、および Modrinth Hosting サーバーへの招待ができなくなります。"
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "このユーザーをブロックしてもよろしいですか?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "このユーザーのブロック中にエラーが発生しました。もう一度お試しください。"
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "ユーザーのブロックに失敗しました"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} をブロックしました"
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "ユーザーをブロックしました"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "{username} をブロック"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "ユーザーアナリティクスを表示"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "ユーザーの請求情報を管理"
+ },
+ "profile.button.block": {
+ "defaultMessage": "ブロック"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "コレクションを作成"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "プロジェクトを作成"
+ },
+ "profile.button.info": {
+ "defaultMessage": "ユーザーの詳細を表示"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "プロジェクトを管理"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "アフィリエイトから削除"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "アフィリエイトに設定"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "ブロック解除"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Modrinth でのポップアップを許可してから、もう一度お試しください。"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "読み込み中…"
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "ユーザーが見つかりません"
+ },
"profile.label.badges": {
"defaultMessage": "バッジ"
},
+ "profile.label.no-projects": {
+ "defaultMessage": "このユーザーはまだプロジェクトがありません!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "まだプロジェクトを何も持っていないようです。"
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "組織"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Modrinth 公式アカウント"
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "ユーザーのブロックを解除しました"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "{date}に公開済み"
},
@@ -2780,9 +2912,15 @@
"project-card.environment.server": {
"defaultMessage": "サーバー"
},
+ "project-card.environment.singleplayer": {
+ "defaultMessage": "シングルプレイヤー"
+ },
"project-type.all": {
"defaultMessage": "すべて"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "コレクション"
+ },
"project-type.datapack.capital": {
"defaultMessage": "データパック"
},
@@ -3572,9 +3710,6 @@
"search.filter_type.advanced": {
"defaultMessage": "もっと見る"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "データパックを除く"
- },
"search.filter_type.environment": {
"defaultMessage": "環境"
},
@@ -3641,9 +3776,54 @@
"servers.access-page.activity-log-filter.action-types": {
"defaultMessage": "アクション"
},
+ "servers.access-page.activity-log-filter.action.addon-disabled": {
+ "defaultMessage": "無効化されたコンテンツ"
+ },
+ "servers.access-page.activity-log-filter.action.addon-enabled": {
+ "defaultMessage": "有効化されたコンテンツ"
+ },
+ "servers.access-page.activity-log-filter.action.addon-updated": {
+ "defaultMessage": "更新されたコンテンツ"
+ },
+ "servers.access-page.activity-log-filter.action.addon-uploaded": {
+ "defaultMessage": "アップロードされたコンテンツ"
+ },
+ "servers.access-page.activity-log-filter.action.backup-created": {
+ "defaultMessage": "バックアップを作成しました"
+ },
"servers.access-page.activity-log-filter.action.backup-deleted": {
"defaultMessage": "削除されたバックアップ"
},
+ "servers.access-page.activity-log-filter.action.backup-renamed": {
+ "defaultMessage": "バックアップの名前を変更しました"
+ },
+ "servers.access-page.activity-log-filter.action.backup-restored": {
+ "defaultMessage": "バックアップを復元しました"
+ },
+ "servers.access-page.activity-log-filter.action.changed-server-name": {
+ "defaultMessage": "サーバー名を変更しました"
+ },
+ "servers.access-page.activity-log-filter.action.changed-server-subdomain": {
+ "defaultMessage": "サーバーのサブドメインを変更しました"
+ },
+ "servers.access-page.activity-log-filter.action.console-cleared": {
+ "defaultMessage": "コンソールをクリアしました"
+ },
+ "servers.access-page.activity-log-filter.action.console-command-executed": {
+ "defaultMessage": "コンソールコマンドを実行しました"
+ },
+ "servers.access-page.activity-log-filter.action.file-deleted": {
+ "defaultMessage": "ファイルを削除しました"
+ },
+ "servers.access-page.activity-log-filter.action.file-edited": {
+ "defaultMessage": "ファイルを編集しました"
+ },
+ "servers.access-page.activity-log-filter.action.file-renamed": {
+ "defaultMessage": "ファイル名を変更しました"
+ },
+ "servers.access-page.activity-log-filter.action.file-uploaded": {
+ "defaultMessage": "ファイルをアップロードしました"
+ },
"servers.access-page.activity-log-filter.action.game-version-edited": {
"defaultMessage": "Minecraftのバージョンを変更しました"
},
@@ -3950,6 +4130,93 @@
"servers.audit-log.event.config-changed": {
"defaultMessage": "サーバーの設定が変更されました"
},
+ "servers.audit-log.event.console-cleared": {
+ "defaultMessage": "コンソールをクリアしました"
+ },
+ "servers.audit-log.event.console-command-executed": {
+ "defaultMessage": "コンソールコマンド「 」を実行しました"
+ },
+ "servers.audit-log.event.entity-list.hidden-count": {
+ "defaultMessage": "+{count, number}"
+ },
+ "servers.audit-log.event.file-changed": {
+ "defaultMessage": "ファイル「 」を変更しました"
+ },
+ "servers.audit-log.event.file-deleted": {
+ "defaultMessage": "ファイル「 」を削除しました"
+ },
+ "servers.audit-log.event.file-edited": {
+ "defaultMessage": "ファイル「 」を編集しました"
+ },
+ "servers.audit-log.event.file-renamed": {
+ "defaultMessage": "「 」の名前を「 」に変更しました"
+ },
+ "servers.audit-log.event.file-uploaded": {
+ "defaultMessage": " をアップロードしました"
+ },
+ "servers.audit-log.event.game-version-changed": {
+ "defaultMessage": "Minecraftのバージョンを に変更しました"
+ },
+ "servers.audit-log.event.java-runtime-modified": {
+ "defaultMessage": "Javaの実行環境を に変更しました"
+ },
+ "servers.audit-log.event.java-version-modified": {
+ "defaultMessage": "Javaのバージョンを に変更しました"
+ },
+ "servers.audit-log.event.loader-and-version-changed": {
+ "defaultMessage": "ローダーを に変更しました"
+ },
+ "servers.audit-log.event.loader-changed": {
+ "defaultMessage": "ローダーを に変更しました"
+ },
+ "servers.audit-log.event.loader-version-changed": {
+ "defaultMessage": "ローダーのバージョンを に変更しました"
+ },
+ "servers.audit-log.event.loader-version-cleared": {
+ "defaultMessage": "ローダーのバージョン設定を消去しました"
+ },
+ "servers.audit-log.event.modpack-changed": {
+ "defaultMessage": "モッドパックを変更しました"
+ },
+ "servers.audit-log.event.modpack-changed-to-modpack": {
+ "defaultMessage": "モッドパックを に変更しました"
+ },
+ "servers.audit-log.event.modpack-changed-to-version": {
+ "defaultMessage": "モッドパックのバージョンを に変更しました"
+ },
+ "servers.audit-log.event.modpack-unlinked": {
+ "defaultMessage": "モッドパックの連携を解除しました"
+ },
+ "servers.audit-log.event.modpack-unlinked-modpack": {
+ "defaultMessage": "モッドパック の連携を解除しました"
+ },
+ "servers.audit-log.event.modpack-unlinked-version": {
+ "defaultMessage": "モッドパックのバージョン の連携を解除しました"
+ },
+ "servers.audit-log.event.port-allocation-added": {
+ "defaultMessage": "ポート割り当て を追加しました"
+ },
+ "servers.audit-log.event.port-allocation-removed": {
+ "defaultMessage": "ポート割り当て を削除しました"
+ },
+ "servers.audit-log.event.server-created": {
+ "defaultMessage": "サーバーを作成しました"
+ },
+ "servers.audit-log.event.server-killed": {
+ "defaultMessage": "サーバーを強制終了しました"
+ },
+ "servers.audit-log.event.server-metadata-changed": {
+ "defaultMessage": "サーバーのメタデータを変更しました"
+ },
+ "servers.audit-log.event.server-name-changed": {
+ "defaultMessage": "サーバー名を に変更しました"
+ },
+ "servers.audit-log.event.server-plan-changed": {
+ "defaultMessage": "プランを に変更しました"
+ },
+ "servers.audit-log.event.server-plan.new-plan": {
+ "defaultMessage": "新しいプラン"
+ },
"servers.audit-log.event.server-plan.ram-gb": {
"defaultMessage": "メモリ {amount, number} GB"
},
@@ -3962,6 +4229,21 @@
"servers.audit-log.event.server-plan.storage-mb": {
"defaultMessage": "ストレージ {amount, number} MB"
},
+ "servers.audit-log.event.server-properties-modified": {
+ "defaultMessage": "サーバープロパティ を変更しました"
+ },
+ "servers.audit-log.event.server-properties-modified-label": {
+ "defaultMessage": "サーバープロパティを変更しました"
+ },
+ "servers.audit-log.event.server-reallocated": {
+ "defaultMessage": "サーバーの割り当てを変更しました"
+ },
+ "servers.audit-log.event.server-repaired": {
+ "defaultMessage": "サーバーを修復しました"
+ },
+ "servers.audit-log.event.server-reset": {
+ "defaultMessage": "サーバーをリセットしました"
+ },
"servers.audit-log.scope.server": {
"defaultMessage": "サーバー"
},
@@ -4292,15 +4574,66 @@
"servers.listing.notice.pending-change": {
"defaultMessage": "あなたのサーバーは {formattedDate} に {planSize} へと {verb, select, downgrade {ダウングレード} other {アップグレード}} されます。"
},
+ "servers.listing.support-label": {
+ "defaultMessage": "サポート"
+ },
+ "servers.manage.new-server-button": {
+ "defaultMessage": "新しいサーバー"
+ },
+ "servers.manage.no-servers-found": {
+ "defaultMessage": "サーバーは見つかりませんでした。"
+ },
"servers.manage.reload-button": {
"defaultMessage": "再読み込み"
},
+ "servers.manage.resubscribe-submitted.text": {
+ "defaultMessage": "現在サーバーがキャンセルされている場合、再課金の試行までに最大10分ほどかかることがあります。"
+ },
+ "servers.manage.resubscribe-submitted.title": {
+ "defaultMessage": "再購読のリクエストを送信しました"
+ },
+ "servers.manage.resubscribe-success.text": {
+ "defaultMessage": "サーバーのサブスクリプションが完了しました"
+ },
+ "servers.manage.resubscribe-success.title": {
+ "defaultMessage": "成功"
+ },
+ "servers.manage.servers-title": {
+ "defaultMessage": "Modrinth ホスティング"
+ },
+ "servers.manage.settings-hint.description": {
+ "defaultMessage": "こちらに移動しました!"
+ },
+ "servers.manage.settings-hint.dismiss": {
+ "defaultMessage": "次回から表示しない"
+ },
+ "servers.manage.settings-hint.title": {
+ "defaultMessage": "サーバー設定の場所が移動しました"
+ },
+ "servers.manage.shared-servers-title": {
+ "defaultMessage": "共有サーバー"
+ },
"servers.manage.your-servers-title": {
"defaultMessage": "あなたのサーバー"
},
"servers.medal-listing.new-server-label": {
"defaultMessage": "新しいサーバー"
},
+ "servers.medal-listing.notice.medal-trial-ended": {
+ "defaultMessage": "Medalサーバーの試用期間が終了し、サーバーがサスペンド(停止)されました。サーバーを引き続き利用するにはアップグレードしてください。"
+ },
+ "servers.medal-listing.notice.suspended": {
+ "defaultMessage": "サーバーがサスペンド(停止)されました。請求情報を更新するか、詳細は Modrinth サポートにお問い合わせください。"
+ },
+ "servers.medal-listing.notice.suspended-with-reason": {
+ "defaultMessage": "サーバーがサスペンド(停止)されました: {reason}。請求情報を更新するか、詳細は Modrinth サポートにお問い合わせください。"
+ },
+ "servers.medal-listing.notice.upgrading": {
+ "defaultMessage": "サーバーのハードウェアをアップグレード中です。まもなくオンラインに戻ります。"
+ },
+ "servers.medal-listing.owner-avatar-alt": {
+ "defaultMessage": "{username} のアバター"
+ },
"servers.medal-listing.owner-tooltip": {
"defaultMessage": "{username}によって所有されています"
},
@@ -4355,9 +4688,15 @@
"servers.purchase.step.payment.title": {
"defaultMessage": "支払い方法"
},
+ "servers.purchase.step.plan.billing-subtitle": {
+ "defaultMessage": "北米、ヨーロッパ、東南アジアでご利用いただけます。"
+ },
"servers.purchase.step.plan.custom.desc": {
"defaultMessage": "必要な仕様だけのカスタマイズされたプランを選択。"
},
+ "servers.purchase.step.plan.custom.heading": {
+ "defaultMessage": "必要なものがお決まりですか?"
+ },
"servers.purchase.step.plan.get-started": {
"defaultMessage": "始めましょう"
},
@@ -4388,6 +4727,9 @@
"servers.purchase.step.plan.title": {
"defaultMessage": "プラン"
},
+ "servers.purchase.step.plan.your-current-plan": {
+ "defaultMessage": "現在のプラン"
+ },
"servers.purchase.step.region.title": {
"defaultMessage": "地域"
},
@@ -4427,12 +4769,99 @@
"servers.region.western-europe": {
"defaultMessage": "西ヨーロッパ"
},
+ "servers.remove-access-modal.added-label": {
+ "defaultMessage": "{time} に追加済み"
+ },
+ "servers.remove-access-modal.cancel-button": {
+ "defaultMessage": "招待を取り消す"
+ },
+ "servers.remove-access-modal.cancel-effect-access": {
+ "defaultMessage": "このサーバーには追加されません"
+ },
+ "servers.remove-access-modal.cancel-effect-invite": {
+ "defaultMessage": "あとから再度招待を送ることもできます"
+ },
+ "servers.remove-access-modal.cancel-header": {
+ "defaultMessage": "招待を取り消す"
+ },
+ "servers.remove-access-modal.cancel-warning-body": {
+ "defaultMessage": "この招待を取り消すと、{username} がこのサーバーに参加するには新しい招待が必要になります。"
+ },
+ "servers.remove-access-modal.header": {
+ "defaultMessage": "アクセス権を取り消す"
+ },
+ "servers.remove-access-modal.invited-label": {
+ "defaultMessage": "{time} に招待済み"
+ },
+ "servers.remove-access-modal.pending-invite-label": {
+ "defaultMessage": "保留中の招待"
+ },
+ "servers.remove-access-modal.remove-button": {
+ "defaultMessage": "アクセス権を取り消す"
+ },
+ "servers.remove-access-modal.remove-effect-access": {
+ "defaultMessage": "サーバーパネルへのアクセス権が即座に無効化され、コンテンツの編集ができなくなります"
+ },
+ "servers.remove-access-modal.remove-effect-join": {
+ "defaultMessage": "個別に設定を変更しない限り、ユーザーは引き続きサーバーに参加してプレイすることができます"
+ },
+ "servers.remove-access-modal.unknown-added-label": {
+ "defaultMessage": "追加日不明"
+ },
+ "servers.remove-access-modal.user-avatar-alt": {
+ "defaultMessage": "{username} のアバター"
+ },
+ "servers.remove-access-modal.warning-body": {
+ "defaultMessage": "ユーザーのサーバーアクセス権を取り消した場合、アクセスを復元するには再度招待し直す必要があります。"
+ },
+ "servers.remove-access-modal.what-happens-label": {
+ "defaultMessage": "どうなるの?"
+ },
+ "servers.setup.onboarding.installation-failed.text": {
+ "defaultMessage": "インストール中に予期しないエラーが発生しました。時間をおいて再度お試しください。"
+ },
+ "servers.setup.onboarding.installation-failed.title": {
+ "defaultMessage": "インストールの失敗"
+ },
+ "servers.setup.onboarding.modpack-upload-failed.text": {
+ "defaultMessage": "アップロード中に予期しないエラーが発生しました。時間をおいて再度お試しください。"
+ },
+ "servers.setup.onboarding.modpack-upload-failed.title": {
+ "defaultMessage": "モッドパックのアップロード失敗"
+ },
"servers.setup.onboarding.setup-server.button": {
"defaultMessage": "サーバーをセットアップ"
},
+ "servers.setup.onboarding.step.choose.description": {
+ "defaultMessage": "Modrinthからお気に入りのモッドパックを選ぶか、ローダーを選択して好きなModを追加してください"
+ },
+ "servers.setup.onboarding.step.choose.title": {
+ "defaultMessage": "プレイするものを選ぶ"
+ },
+ "servers.setup.onboarding.step.configure-world.description": {
+ "defaultMessage": "シングルプレイと同じようにワールドを設定できます。ゲームモードとワールドシード値を選択してください"
+ },
+ "servers.setup.onboarding.step.configure-world.title": {
+ "defaultMessage": "ワールドを設定する"
+ },
+ "servers.setup.onboarding.step.invite-friends.description": {
+ "defaultMessage": "アドレスをコピーして友達に共有し、参加に必要なModを教えてあげましょう"
+ },
"servers.setup.onboarding.step.invite-friends.title": {
"defaultMessage": "フレンドを招待"
},
+ "servers.setup.onboarding.steps.heading": {
+ "defaultMessage": "サーバーをセットアップする(約2分)"
+ },
+ "servers.setup.onboarding.uploading.progress": {
+ "defaultMessage": "アップロード中 ({percent, number}%)"
+ },
+ "servers.setup.onboarding.welcome.description": {
+ "defaultMessage": "サーバーの準備が完了しました。プレイを開始する手順は以下の通りです!"
+ },
+ "servers.setup.onboarding.welcome.title": {
+ "defaultMessage": "Modrinth ホスティングへようこそ"
+ },
"servers.setup.rate-limit.text": {
"defaultMessage": "レート制限に達しました。時間をおいて再試行してください。"
},
@@ -4493,6 +4922,9 @@
"settings.display.theme.title": {
"defaultMessage": "カラーテーマ"
},
+ "settings.feature-flags.title": {
+ "defaultMessage": "機能フラグ"
+ },
"settings.language.categories.default": {
"defaultMessage": "一般的な言語"
},
@@ -4526,9 +4958,57 @@
"settings.pats.title": {
"defaultMessage": "個人用アクセストークン"
},
+ "settings.profile.bio.title": {
+ "defaultMessage": "自己紹介"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "プロファイル"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "プロファイルアイコン"
+ },
"settings.sessions.title": {
"defaultMessage": "セッション"
},
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "ブロックを解除"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "近日公開!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "全員"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "フレンド"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "フレンドのフレンド"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "なし"
+ },
+ "sharing.invite-players-modal.add": {
+ "defaultMessage": "追加"
+ },
+ "sharing.invite-players-modal.added": {
+ "defaultMessage": "追加済み"
+ },
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "適用"
+ },
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "カスタム…"
+ },
+ "sharing.invite-players-modal.friends-heading": {
+ "defaultMessage": "あなたのフレンド - {count} 人"
+ },
+ "sharing.invite-players-modal.invite": {
+ "defaultMessage": "招待"
+ },
+ "sharing.invite-players-modal.save-button": {
+ "defaultMessage": "保存"
+ },
"tag.category.128x": {
"defaultMessage": "128x"
},
@@ -4998,16 +5478,16 @@
"defaultMessage": "一般的にマルウェアは、Discord等のプラットフォーム上でModファイルを配布して拡散されます"
},
"user.profile.badge.alpha.about.1": {
- "defaultMessage": "2020年11月までのModrinthがAlpha版だった頃から活動しています"
+ "defaultMessage": "2020年11月までのModrinthがAlpha版の頃から活動しています"
},
"user.profile.badge.alpha.name": {
"defaultMessage": "Alpha Tester"
},
"user.profile.badge.beta.about.1": {
- "defaultMessage": "2022年2月までのModrinthがBeta版だった頃から活動しています"
+ "defaultMessage": "2022年2月までのModrinthがBeta版の頃から活動しています"
},
"user.profile.badge.beta.link": {
- "defaultMessage": "クリックすると、ModrinthのBeta版のリリース記事を読むことができます。"
+ "defaultMessage": "クリックするとModrinthのBeta版リリース記事を読むことができます"
},
"user.profile.badge.beta.name": {
"defaultMessage": "Beta Tester"
@@ -5021,6 +5501,12 @@
"user.profile.badge.moderator.name": {
"defaultMessage": "コンテンツモデレーター"
},
+ "user.profile.badge.plus.about.1": {
+ "defaultMessage": "Modrinthとクリエイターに特別なサポートを贈っています!"
+ },
+ "user.profile.badge.plus.link": {
+ "defaultMessage": "クリックしてModrinth+のメンバーになる方法を知る"
+ },
"user.profile.badge.plus.name": {
"defaultMessage": "Modrinth+ Member"
},
@@ -5045,6 +5531,9 @@
"version.section.content.search-placeholder": {
"defaultMessage": "コンテンツを検索…"
},
+ "version.section.dependencies.any-version": {
+ "defaultMessage": "すべてのバージョン"
+ },
"version.section.files": {
"defaultMessage": "ファイル"
},
diff --git a/packages/ui/src/locales/ko-KR/index.json b/packages/ui/src/locales/ko-KR/index.json
index 33db6fadd9..15607e421c 100644
--- a/packages/ui/src/locales/ko-KR/index.json
+++ b/packages/ui/src/locales/ko-KR/index.json
@@ -377,6 +377,9 @@
"content.confirm-deletion.header": {
"defaultMessage": "{itemType} 삭제"
},
+ "content.confirm-disable.header": {
+ "defaultMessage": "{itemType} 비활성화"
+ },
"content.confirm-modpack-update.admonition-body": {
"defaultMessage": "{action, select, downgrade {다운그레이드 진행 중} other {업데이트 진행 중}}에는 호환성 문제가 발생할 수 있습니다. 모드팩에 추가한 모드나 콘텐츠는 유지되지만, 새 버전과 호환되지 않을 수 있습니다."
},
@@ -446,12 +449,18 @@
"content.diff-modal.added-count": {
"defaultMessage": "{count}개 추가됨"
},
+ "content.diff-modal.config-files-updated": {
+ "defaultMessage": "변경된 설정 파일"
+ },
"content.diff-modal.diff-type.added": {
"defaultMessage": "추가됨 (종속성)"
},
"content.diff-modal.diff-type.removed": {
"defaultMessage": "비활성화"
},
+ "content.diff-modal.diff-type.removed-disabled": {
+ "defaultMessage": "제거됨 (비활성화됨)"
+ },
"content.diff-modal.diff-type.updated": {
"defaultMessage": "업데이트됨"
},
@@ -467,12 +476,36 @@
"content.diff-modal.external-diff-type.updated": {
"defaultMessage": "업데이트됨"
},
+ "content.diff-modal.file-count": {
+ "defaultMessage": "{count, plural, one {#개 파일} other {#개 파일}}"
+ },
+ "content.diff-modal.game-version-updated": {
+ "defaultMessage": "게임 버전"
+ },
"content.diff-modal.install-anyway": {
"defaultMessage": "무시하고 설치"
},
+ "content.diff-modal.loader-updated": {
+ "defaultMessage": "로더"
+ },
+ "content.diff-modal.modpack-linked": {
+ "defaultMessage": "연동된 모드팩"
+ },
+ "content.diff-modal.modpack-unlinked": {
+ "defaultMessage": "연동 해제된 모드팩"
+ },
+ "content.diff-modal.modpack-updated": {
+ "defaultMessage": "업데이트된 모드팩"
+ },
+ "content.diff-modal.no-content-changes": {
+ "defaultMessage": "콘텐츠 변경 사항 없음"
+ },
"content.diff-modal.removed-count": {
"defaultMessage": "{count}개 제거됨"
},
+ "content.diff-modal.removed-disabled-count": {
+ "defaultMessage": "{count} 제거됨 (비활성화됨)"
+ },
"content.diff-modal.reviewed-files": {
"defaultMessage": "모든 파일은 형식(.mrpack 포함)에 무관하게 Modrinth에 게시되어야만 검수를 거칩니다."
},
@@ -584,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "프로젝트 이름"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "알파벳순"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "최신순"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "오래된순"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "{mode}으로 정렬"
- },
"content.page-layout.update-all": {
"defaultMessage": "모두 업데이트"
},
@@ -1160,6 +1181,21 @@
"external-files.permissions-card.reason.special-permission.description": {
"defaultMessage": "이 작업물을 모드팩에 재배포할 수 있는 특별 허가를 받았습니다."
},
+ "external-files.permissions-card.remove-group": {
+ "defaultMessage": "그룹 삭제"
+ },
+ "external-files.permissions-card.remove-group-confirmation.description": {
+ "defaultMessage": "이 작업은 해당 출처 표시 그룹 및 내부의 모든 파일을 영구 삭제합니다. 이 작업은 되돌릴 수 없습니다."
+ },
+ "external-files.permissions-card.remove-group-confirmation.title": {
+ "defaultMessage": "{title}를 삭제하시겠습니까?"
+ },
+ "external-files.permissions-card.remove-group-error.title": {
+ "defaultMessage": "그룹을 삭제할 수 없습니다"
+ },
+ "external-files.permissions-card.remove-group-shift-hint": {
+ "defaultMessage": "Shift 키를 누른 채 클릭하면 확인 절차를 생략합니다."
+ },
"external-files.permissions-card.split-file": {
"defaultMessage": "그룹에서 제거"
},
@@ -1253,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "파일 저장됨"
},
- "files.editor.find-close": {
- "defaultMessage": "닫다"
- },
"files.editor.find-in-file": {
"defaultMessage": "찾다"
},
@@ -2033,24 +2066,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "아이콘 선택"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "이 모드팩에는 추가 콘텐츠가 포함되어 있지 않습니다."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "콘텐츠를 찾을 수 없습니다"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "모드팩 콘텐츠"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "콘텐츠 불러오는 중..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "검색 결과와 일치하는 프로젝트가 없습니다."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "{count, number}개의 프로젝트 검색"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "현재"
},
@@ -2183,6 +2198,9 @@
"label.details": {
"defaultMessage": "세부 사항"
},
+ "label.discover-content": {
+ "defaultMessage": "콘텐츠 둘러보기"
+ },
"label.done": {
"defaultMessage": "완료"
},
@@ -2261,6 +2279,9 @@
"label.password": {
"defaultMessage": "비밀번호"
},
+ "label.permissions": {
+ "defaultMessage": "권한"
+ },
"label.plan-custom": {
"defaultMessage": "사용자 지정"
},
@@ -2792,9 +2813,147 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Modrinth 크리에이터입니다."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Modrinth 사용자입니다."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} 님은 친구 요청을 보내거나, 공유 인스턴스 초대 및 Modrinth Hosting 서버 초대를 할 수 없게 됩니다."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "이 사용자를 차단하시겠습니까?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "이 사용자를 차단하는 중 오류가 발생했습니다. 다시 시도해 주세요."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "사용자 차단 실패"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} 님을 차단했습니다."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "사용자 차단됨"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "{username} 차단"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "사용자 분석 보기"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "사용자 결제 관리"
+ },
+ "profile.button.block": {
+ "defaultMessage": "차단"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "컬렉션 만들기"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "프로젝트 만들기"
+ },
+ "profile.button.info": {
+ "defaultMessage": "사용자 상세 정보 보기"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "프로젝트 관리"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "제휴 자격 해제"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "제휴 자격 부여"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "차단 해제"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {프로젝트 #개} other {프로젝트 #개}}"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "인증 제공자"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "이메일 인증됨"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "비밀번호 설정됨"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "TOTP 설정됨"
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "결제 수단"
+ },
+ "profile.details.title": {
+ "defaultMessage": "사용자 상세 정보"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "이메일 미인증"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "이메일 인증됨"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "사용자 프로필을 불러올 수 없습니다."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "사용자를 찾을 수 없음"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "제휴 파트너"
+ },
"profile.label.badges": {
"defaultMessage": "배지"
},
+ "profile.label.collection": {
+ "defaultMessage": "컬렉션"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, other {다운로드}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "가입일"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "이 사용자는 컬렉션이 없습니다!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "아직 컬렉션이 없습니다."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "이 사용자는 프로젝트가 없습니다!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "아직 프로젝트가 없습니다."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "조직"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, other {프로젝트}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "공식 Modrinth 계정"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Modrinth의 공식 사용자 계정입니다. 또는 을 통해 문의해 주세요"
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "이 사용자의 차단을 해제하는 동안 오류가 발생했습니다. 다시 시도해 주세요."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "사용자 차단 해제 실패"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username}님의 차단이 해제되었습니다."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "사용자 차단 해제됨"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "{date}에 게시됨"
},
@@ -2810,12 +2969,21 @@
"project-card.environment.client-or-server": {
"defaultMessage": "클라이언트 또는 서버"
},
+ "project-card.environment.dedicated-server": {
+ "defaultMessage": "전용 서버"
+ },
"project-card.environment.server": {
"defaultMessage": "서버"
},
+ "project-card.environment.singleplayer": {
+ "defaultMessage": "싱글플레이어"
+ },
"project-type.all": {
"defaultMessage": "모두"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "컬렉션"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, other {데이터 팩}}"
},
@@ -3608,15 +3776,6 @@
"search.filter_type.advanced": {
"defaultMessage": "고급"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "데이터 팩 제외"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "모드 제외"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "플러그인 제외"
- },
"search.filter_type.environment": {
"defaultMessage": "실행 환경"
},
@@ -5039,9 +5198,216 @@
"settings.pats.title": {
"defaultMessage": "개인 액세스 토큰"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "자신을 알릴 수 있는 간단한 소개글입니다."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "자기소개"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "프로필"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "프로필 사진"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "프로필 정보는 Modrinth에서 누구나 볼 수 있게 공개 되며, Modrinth API 를 통해서도 확인할 수 있습니다."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "프로필 업데이트 실패"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "프로필을 업데이트하는 동안 오류가 발생했습니다. 다시 시도해 주세요."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "공개 프로필을 맞춤 설정하려면 Modrinth 계정에 로그인하세요."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Modrinth 계정 필요"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "프로필을 식별하기 위한 대소문자 구분 없는 고유한 이름입니다."
+ },
"settings.sessions.title": {
"defaultMessage": "세션"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "작업"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "사용자"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Modrinth에서 차단한 사용자 목록입니다. 해당 사용자는 다음 행위를 할 수 없습니다:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "차단한 사용자가 없습니다."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "차단된 사용자 목록을 불러올 수 없습니다."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "차단된 사용자 목록 불러오는 중…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "나에게 친구 요청 전송"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Modrinth 호스팅 서버 관리 초대."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "공유 인스턴스에 초대"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "차단된 사용자"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "차단 해제"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "사용자 차단 해제 실패"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "이 사용자의 차단을 해제하는 중 오류가 발생했습니다. 다시 시도해 주세요."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "{username} 차단 해제"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "{username} 님의 아바타"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Modrinth에서 본인에게 친구 요청을 보낼 수 있는 사람을 설정합니다."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "친구 요청"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "곧 제공할 예정입니다!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "모든 사람"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "친구"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "친구의 친구"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "아무도 없음"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "공유 인스턴스 및 Modrinth Hosting 패널 초대를 보낼 수 있는 사람을 설정합니다."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "초대"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Modrinth 계정이 있으면 본인과 소통 가능한 사람을 설정하고 차단된 사용자를 관리할 수 있습니다"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Modrinth 계정이 필요합니다"
+ },
+ "settings.social.title": {
+ "defaultMessage": "소셜"
+ },
+ "sharing.invite-players-modal.add": {
+ "defaultMessage": "추가"
+ },
+ "sharing.invite-players-modal.added": {
+ "defaultMessage": "추가됨"
+ },
+ "sharing.invite-players-modal.already-invited": {
+ "defaultMessage": "이 사용자는 이미 초대되었습니다."
+ },
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "선택"
+ },
+ "sharing.invite-players-modal.avatar-alt": {
+ "defaultMessage": "{username} 님의 아바타"
+ },
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "커스텀..."
+ },
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "커스텀: {date}"
+ },
+ "sharing.invite-players-modal.edit-invite-link": {
+ "defaultMessage": "초대 링크 수정."
+ },
+ "sharing.invite-players-modal.edit-invite-link-title": {
+ "defaultMessage": "초대 링크 수정"
+ },
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "1일 후"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "1시간 후"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "7일 후"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "6시간 후"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "3일 후"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "12시간 후"
+ },
+ "sharing.invite-players-modal.expiry-label": {
+ "defaultMessage": "만료일"
+ },
+ "sharing.invite-players-modal.friends-heading": {
+ "defaultMessage": "당신의 친구 - {count}"
+ },
+ "sharing.invite-players-modal.invite": {
+ "defaultMessage": "초대"
+ },
+ "sharing.invite-players-modal.invite-expiry-description": {
+ "defaultMessage": "초대 링크는 {duration} 후 만료됩니다."
+ },
+ "sharing.invite-players-modal.invite-link-heading": {
+ "defaultMessage": "또는 초대 링크 사용"
+ },
+ "sharing.invite-players-modal.link-copied-text": {
+ "defaultMessage": "초대 링크가 클립보드에 복사되었습니다."
+ },
+ "sharing.invite-players-modal.link-copied-title": {
+ "defaultMessage": "링크 복사됨"
+ },
+ "sharing.invite-players-modal.link-copy-failed-title": {
+ "defaultMessage": "링크 복사 실패"
+ },
+ "sharing.invite-players-modal.max-uses-label": {
+ "defaultMessage": "최대 사용 횟수"
+ },
+ "sharing.invite-players-modal.no-friends": {
+ "defaultMessage": "친구가 없습니다."
+ },
+ "sharing.invite-players-modal.no-search-results": {
+ "defaultMessage": "일치하는 사용자를 찾을 수 없습니다."
+ },
+ "sharing.invite-players-modal.requested": {
+ "defaultMessage": "요청 전송됨"
+ },
+ "sharing.invite-players-modal.requested-tooltip": {
+ "defaultMessage": "{username}님이 먼저 친구 요청을 수락해야 합니다"
+ },
+ "sharing.invite-players-modal.save-button": {
+ "defaultMessage": "저장"
+ },
+ "sharing.invite-players-modal.search-placeholder": {
+ "defaultMessage": "Modrinth 사용자 이름 입력"
+ },
+ "sharing.invite-players-modal.searching": {
+ "defaultMessage": "검색 중..."
+ },
+ "sharing.invite-players-modal.update-invite-link-failed-title": {
+ "defaultMessage": "초대 링크 업데이트 실패"
+ },
"tag.category.128x": {
"defaultMessage": "128x"
},
diff --git a/packages/ui/src/locales/ms-MY/index.json b/packages/ui/src/locales/ms-MY/index.json
index 26c129ef81..ae5c62cbf3 100644
--- a/packages/ui/src/locales/ms-MY/index.json
+++ b/packages/ui/src/locales/ms-MY/index.json
@@ -386,6 +386,9 @@
"content.diff-modal.diff-type.updated": {
"defaultMessage": "Dikemas Kini"
},
+ "content.diff-modal.external-diff-type.added": {
+ "defaultMessage": "Ditambah"
+ },
"content.diff-modal.removed-count": {
"defaultMessage": "{count} dialih keluar"
},
@@ -485,18 +488,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nama projek"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Mengikut abjad"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Paling baharu dahulu"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Paling lama dahulu"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Isih mengikut {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Kemas kini semua"
},
@@ -911,9 +902,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Fail disimpan"
},
- "files.editor.find-close": {
- "defaultMessage": "Tutup"
- },
"files.editor.find-in-file": {
"defaultMessage": "Cari"
},
@@ -1679,24 +1667,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Pilih ikon"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Pek mod ini tidak menyertakan sebarang kandungan tambahan."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Tiada kandungan dijumpai"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Kandungan pek mod"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Sedang memuat kandungan..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Tiada projek yang sepadan dengan carian anda."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Cari {count, number} {count, plural, other {projek}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Semasa"
},
@@ -2402,6 +2372,9 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.button.block": {
+ "defaultMessage": "Sekat"
+ },
"profile.label.badges": {
"defaultMessage": "Lencana"
},
@@ -4442,9 +4415,27 @@
"settings.pats.title": {
"defaultMessage": "Token akses peribadi"
},
+ "settings.profile.bio.title": {
+ "defaultMessage": "Bio"
+ },
"settings.sessions.title": {
"defaultMessage": "Sesi"
},
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Pengguna"
+ },
+ "sharing.invite-players-modal.add": {
+ "defaultMessage": "Tambah"
+ },
+ "sharing.invite-players-modal.added": {
+ "defaultMessage": "Ditambah"
+ },
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Terapkan"
+ },
+ "sharing.invite-players-modal.save-button": {
+ "defaultMessage": "Simpan"
+ },
"tag.category.128x": {
"defaultMessage": "128x"
},
diff --git a/packages/ui/src/locales/nl-NL/index.json b/packages/ui/src/locales/nl-NL/index.json
index 12973c623a..1773510c25 100644
--- a/packages/ui/src/locales/nl-NL/index.json
+++ b/packages/ui/src/locales/nl-NL/index.json
@@ -3,22 +3,22 @@
"defaultMessage": "Je hebt geen toestemming."
},
"affiliate.create.button": {
- "defaultMessage": "Maak een affiliatelink"
+ "defaultMessage": "Partnerlink aanmaken"
},
"affiliate.create.header": {
- "defaultMessage": "Nieuwe affiliate aanmaken"
+ "defaultMessage": "Nieuwe partnercode aanmaken"
},
"affiliate.create.title.description": {
- "defaultMessage": "Geef je affiliate-link een naam, zodat je weet waar mensen vandaan komen!"
+ "defaultMessage": "Geef je partnerlink een naam, zodat je weet waar mensen vandaan komen!"
},
"affiliate.create.title.label": {
- "defaultMessage": "Titel van affiliate-link"
+ "defaultMessage": "Titel van de partnerlink"
},
"affiliate.create.title.placeholder": {
- "defaultMessage": "bijvoorbeeld YouTube"
+ "defaultMessage": "bijv. YouTube"
},
"affiliate.create.user.description": {
- "defaultMessage": "De gebruikersnaam van de gebruiker voor wie de affiliatecode moet worden aangemaakt"
+ "defaultMessage": "De gebruikersnaam van de gebruiker voor wie de partnercode moet worden aangemaakt"
},
"affiliate.create.user.placeholder": {
"defaultMessage": "Voer gebruikersnaam in..."
@@ -27,13 +27,13 @@
"defaultMessage": "Gemaakt door {user}"
},
"affiliate.creating.button": {
- "defaultMessage": "Affiliate-link maken..."
+ "defaultMessage": "Partnerlink maken..."
},
"affiliate.revoke": {
- "defaultMessage": "Affiliatie-link intrekken"
+ "defaultMessage": "Partnerlink intrekken"
},
"affiliate.viewAnalytics": {
- "defaultMessage": "Bekijk analyses"
+ "defaultMessage": "Statistieken bekijken"
},
"app.server-settings.failed-to-load-server": {
"defaultMessage": "Serverinstellingen konden niet worden geladen"
@@ -135,7 +135,7 @@
"defaultMessage": "Voeg server toevoegen aan instantie"
},
"button.affiliate-links": {
- "defaultMessage": "Affiliatelinks"
+ "defaultMessage": "Partnerlinks"
},
"button.analytics": {
"defaultMessage": "Analytica"
@@ -617,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Projectnamen"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabetisch"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Nieuwste eerst"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Oudste eerst"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sorteer op {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Werk alles bij"
},
@@ -1301,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Bestand opgeslagen"
},
- "files.editor.find-close": {
- "defaultMessage": "Sluiten"
- },
"files.editor.find-in-file": {
"defaultMessage": "Vind"
},
@@ -2078,33 +2063,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Selecteer pictogram"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Deze modpack bevat geen extra inhoud."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Geen inhoud gevonden"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Extern"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "Dit bestand is niet gepubliceerd op Modrinth."
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Inhoud van modpack"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Inhoud aan het laden..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Geen projecten voldoen aan je zoekopdracht."
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "In Slicer openen"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Zoek naar {count, number} {count, plural, one {project} other {projecten}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Huidige"
},
@@ -2231,6 +2189,9 @@
"label.details": {
"defaultMessage": "Details"
},
+ "label.discover-content": {
+ "defaultMessage": "Ontdek inhoud"
+ },
"label.done": {
"defaultMessage": "Klaar"
},
@@ -2309,6 +2270,9 @@
"label.password": {
"defaultMessage": "Wachtwoord"
},
+ "label.permissions": {
+ "defaultMessage": "Machtigingen"
+ },
"label.plan-custom": {
"defaultMessage": "Op maat"
},
@@ -2840,9 +2804,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Een maker op Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Een gebruiker van Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} zal je geen vriendschapsverzoeken kunnen sturen, je niet kunnen uitnodigen voor gedeelde instanties en je ook niet kunnen uitnodigen voor Modrinth Hosting-servers."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Weet je zeker dat je deze gebruiker wilt blokkeren?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Er is een fout opgetreden bij het blokkeren van deze gebruiker. Probeer het nog eens."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Gebruiker blokkeren mislukt"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} is geblokkeerd."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Gebruiker geblokkeerd"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "{username} blokkeren"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Gebruikersstatistieken bekijken"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Gebruikersfacturering beheren"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Blokkeren"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Een collectie aanmaken"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Een project aanmaken"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Gebruikersgegevens bekijken"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Projecten beheren"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Als partner verwijderen"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Als partner instellen"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Deblokkeren"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# project} other {# projecten}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Schakel pop-ups voor Modrinth in en probeer het vervolgens opnieuw."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "Het GitHub-profiel kon niet worden opgehaald. Probeer het nog eens."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Kan GitHub-profiel niet openen"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Authenticatieproviders"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "E-mailadres geverifieerd"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Heeft wachtwoord"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Heeft TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Laden..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Betaalmethoden"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Profiel bekijken"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Gebruikersgegevens"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "E-mailadres niet geverifieerd"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "E-mailadres geverifieerd"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Het profiel kon niet worden geladen."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Gebruiker niet gevonden"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Partner"
+ },
"profile.label.badges": {
"defaultMessage": "Badges"
},
+ "profile.label.collection": {
+ "defaultMessage": "Collectie"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {download} other {downloads}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Lid sinds"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Deze gebruiker heeft geen collecties!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Je hebt nog geen collecties."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Deze gebruiker heeft geen projecten!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Je hebt nog geen projecten."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organisaties"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {project} other {projecten}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Officieel Modrinth-account"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Het officiële gebruikersaccount van Modrinth. Neem contact op met het Helpcentrum via of per e-mail via "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Er is een fout opgetreden bij het deblokkeren van deze gebruiker. Probeer het nog eens."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Kan gebruiker niet deblokkeren"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} is gedeblokkeerd."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Gebruiker gedeblokkeerd"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Gepubliceerd op {date}"
},
@@ -2870,6 +2987,9 @@
"project-type.all": {
"defaultMessage": "Alles"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Collecties"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Gegevenspakket} other {Gegevenspakketten}}"
},
@@ -3546,7 +3666,7 @@
"defaultMessage": "Upload"
},
"project.settings.versions.permissions": {
- "defaultMessage": "Toestemmingen"
+ "defaultMessage": "Machtigingen"
},
"project.settings.versions.title": {
"defaultMessage": "Versies"
@@ -3662,15 +3782,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Gevorderd"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Gegevenspakketten uitsluiten"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Mods uitsluiten"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Plug-ins uitsluiten"
- },
"search.filter_type.environment": {
"defaultMessage": "Omgeving"
},
@@ -4632,7 +4743,7 @@
"defaultMessage": "Je abonnement wordt op {formattedDate} opgezegd. "
},
"servers.listing.notice.suspended": {
- "defaultMessage": "Je server is opgeschort. Neem contact op met de klantenservice van Modrinth voor meer informatie."
+ "defaultMessage": "Je server is opgeschort. Neem contact op met Modrinth-ondersteuning voor meer informatie."
},
"servers.listing.notice.upgrading": {
"defaultMessage": "De hardware van uw server wordt momenteel geüpgraded en zal binnenkort weer online zijn."
@@ -4665,7 +4776,7 @@
"defaultMessage": "Bezig met uploaden"
},
"servers.manage.contact-support-button": {
- "defaultMessage": "Neem contact op met de klantenservice van Modrinth"
+ "defaultMessage": "Contact opnemen met Modrinth-ondersteuning"
},
"servers.manage.error.alert-notice": {
"defaultMessage": "Onze systemen waarschuwen ons team automatisch wanneer er een probleem is. We zijn al bezig om ze weer online te krijgen."
@@ -4680,7 +4791,7 @@
"defaultMessage": "Als je kort geleden een Modrinth Hosting-server hebt gekocht, staat deze momenteel in de wachtrij en zal hij hier verschijnen zodra hij klaar is. Probeer geen nieuwe server aan te schaffen. "
},
"servers.manage.error.support-notice": {
- "defaultMessage": "Als je persoonlijke ondersteuning nodig hebt met betrekking tot de status van uw server, neem dan contact op met Modrinth Support."
+ "defaultMessage": "Als je persoonlijke ondersteuning nodig hebt met de status van je server, neem dan contact op met Modrinth-ondersteuning."
},
"servers.manage.error.title": {
"defaultMessage": "De servers konden niet worden geladen"
@@ -4758,10 +4869,10 @@
"defaultMessage": "De proefperiode van je Medal-server is afgelopen en je server is opgeschort. Voer een upgrade uit om je server te kunnen blijven gebruiken."
},
"servers.medal-listing.notice.suspended": {
- "defaultMessage": "Je server is opgeschort. Werk je factuurgegevens bij of neem contact op met de klantenservice van Modrinth voor meer informatie."
+ "defaultMessage": "Je server is opgeschort. Werk je factuurgegevens bij of neem contact op met Modrinth-ondersteuning voor meer informatie."
},
"servers.medal-listing.notice.suspended-with-reason": {
- "defaultMessage": "Je server is opgeschort met de reden: {reason}. Werk je factuurgegevens bij of neem contact op met de klantenservice van Modrinth voor meer informatie."
+ "defaultMessage": "Je server is opgeschort met de reden: {reason}. Werk je factuurgegevens bij of neem contact op met Modrinth-ondersteuning voor meer informatie."
},
"servers.medal-listing.notice.upgrading": {
"defaultMessage": "De hardware van je server wordt momenteel geüpgraded en zal binnenkort weer online zijn."
@@ -5096,9 +5207,120 @@
"settings.pats.title": {
"defaultMessage": "Persoonlijke toegangstokens"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Een korte beschrijving om iedereen iets over jezelf te vertellen."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Bio"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Profiel"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Profielfoto"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "Je profielgegevens zijn openbaar te bekijken op Modrinth en via de Modrinth API ."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Het bijwerken van het profiel is mislukt"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Er is een fout opgetreden bij het bijwerken van je profiel. Probeer het nog eens."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Log in met een Modrinth-account om je openbare profiel aan te passen."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Modrinth-account vereist"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Een unieke, hoofdletterongevoelige naam waarmee je profiel wordt geïdentificeerd."
+ },
"settings.sessions.title": {
"defaultMessage": "Sessies"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Acties"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Gebruiker"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Dit zijn de gebruikers die je op Modrinth hebt geblokkeerd. Zij kunnen jou niet:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Je hebt niemand geblokkeerd."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "De geblokkeerde gebruikers konden niet worden geladen."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Geblokkeerde gebruikers laden…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Een vriendschapsverzoek sturen"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Uitnodigen om een Modrinth Hosting-server te beheren."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Uitnodigen voor gedeelde instanties"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Geblokkeerde gebruikers"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Deblokkeren"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Kan gebruiker niet deblokkeren"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Er is een fout opgetreden bij het deblokkeren van deze gebruiker. Probeer het nog eens."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "{username} deblokkeren"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Avatar van {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Bepaal zelf wie je vriendschapsverzoeken kan sturen op Modrinth."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Vriendschapsverzoeken"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Binnenkort beschikbaar!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Iedereen"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Vrienden"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Vrienden van vrienden"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Niemand"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Bepaal zelf wie je uitnodigingen kan sturen voor gedeelde instanties en Modrinth Hosting-panelen."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Uitnodigingen"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Met een Modrinth-account kun je bepalen wie er contact met je kan opnemen en kun je geblokkeerde gebruikers beheren"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Modrinth-account vereist"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Sociaal"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Toevoegen"
},
@@ -5108,14 +5330,17 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "Deze gebruiker is al uitgenodigd."
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Toepassen"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "Avatar van {username}"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Annuleren"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Aangepast..."
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Annuleren"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Aangepast: {date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "Uitnodigingslink bewerken."
@@ -5123,6 +5348,24 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "Uitnodigingslink bewerken"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "Over 1 dag"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "Over 1 uur"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "Over 7 dagen"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "Over 6 uur"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "Over 3 dagen"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "Over 12 uur"
+ },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "Vervaldatum"
},
diff --git a/packages/ui/src/locales/no-NO/index.json b/packages/ui/src/locales/no-NO/index.json
index 0d28108348..b770cb83a2 100644
--- a/packages/ui/src/locales/no-NO/index.json
+++ b/packages/ui/src/locales/no-NO/index.json
@@ -413,18 +413,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Prosjektnavn"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabetisk"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Nyeste først"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Eldste først"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sorter etter {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Oppdater alle"
},
@@ -872,18 +860,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Velg ikon"
},
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Ingen innhold funnet"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Laster inn innhold..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Ingen prosjekter samsvarte med søket ditt."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Søk etter {count, number} {count, plural, one {prosjekt} other {prosjekter}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Nåværende"
},
diff --git a/packages/ui/src/locales/pl-PL/index.json b/packages/ui/src/locales/pl-PL/index.json
index 6b58310342..ff4f04dfe0 100644
--- a/packages/ui/src/locales/pl-PL/index.json
+++ b/packages/ui/src/locales/pl-PL/index.json
@@ -617,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nazwy projektów"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabetycznie"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Od najnowszych"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Od najstarszych"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sortuj według: {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Zaktualizuj wszystko"
},
@@ -1196,6 +1184,9 @@
"external-files.permissions-card.remove-group": {
"defaultMessage": "Usuń grupę"
},
+ "external-files.permissions-card.remove-group-confirmation.description": {
+ "defaultMessage": "Trwale usunie to grupę atrybucji i wszystkie zawarte w niej pliki. Tej akcji nie można cofnąć."
+ },
"external-files.permissions-card.remove-group-confirmation.title": {
"defaultMessage": "Usuń {title}?"
},
@@ -1269,10 +1260,10 @@
"defaultMessage": "Usuń plik"
},
"files.delete-modal.warning.file": {
- "defaultMessage": "Ten plik zostanie trwale usunięty. Tej akcji nie będzie można cofnąć."
+ "defaultMessage": "Ten plik zostanie trwale usunięty. Tej akcji nie można cofnąć."
},
"files.delete-modal.warning.folder": {
- "defaultMessage": "Ten folder wraz z całą jego zawartością zostanie trwale usunięty. Tej akcji nie będzie można cofnąć."
+ "defaultMessage": "Ten folder wraz z całą jego zawartością zostanie trwale usunięty. Tej akcji nie można cofnąć."
},
"files.editor.failed-to-open-text": {
"defaultMessage": "Nie udało się odczytać danych z pliku."
@@ -1292,9 +1283,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Plik zapisany"
},
- "files.editor.find-close": {
- "defaultMessage": "Zamknij"
- },
"files.editor.find-in-file": {
"defaultMessage": "Znajdź"
},
@@ -2069,30 +2057,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Wybierz ikonę"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Ta paczka modów nie zawiera żadnych innych treści."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Nie znaleziono treści"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Zewnętrzne"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "Ten plik nie jest opublikowany na Modrinth."
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Zawartość paczki modów"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Ładowanie treści..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Nie znaleziono żadnego projektu pasującego do Twojego wyszukiwania."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Szukaj wśród {count, number} {count, plural, one {projektu} other {projektów}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Aktualny"
},
@@ -2225,6 +2189,9 @@
"label.details": {
"defaultMessage": "Szczegóły"
},
+ "label.discover-content": {
+ "defaultMessage": "Odkrywaj zawartość"
+ },
"label.done": {
"defaultMessage": "Gotowe"
},
@@ -2303,6 +2270,9 @@
"label.password": {
"defaultMessage": "Hasło"
},
+ "label.permissions": {
+ "defaultMessage": "Uprawnienia"
+ },
"label.plan-custom": {
"defaultMessage": "Niestandardowy"
},
@@ -2834,9 +2804,138 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Twórca na Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Użytkownik Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "Użytkownik {username} nie będzie mógł wysyłać ci zaproszeń do znajomych, zapraszać się do udostępnionych instancji lub zapraszać się do serwerów Modrinth Hosting."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Czy na pewno chcesz zablokować tego użytkownika?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Wystąpił błąd podczas blokowania tego użytkownika. Spróbuj ponownie później."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Nie udało się zablokować użytkownika"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "Użytkownik {username} został zablokowany."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Zablokowano użytkownika"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Zablokuj {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Pokaż dane analityczne użytkownika"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Zarządzaj rozliczaniem użytkownika"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Zablokuj"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Utwórz kolekcję"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Utwórz projekt"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Otwórz szczegóły użytkownika"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Zarządzaj projektami"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Odblokuj"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# projekt} few {# projekty} other {# projektów}}"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Dostawcy uwierzytelniania"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "Zweryfikowano e-mail"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Ma hasło"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Ma TOTP"
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Metody płatności"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Szczegóły użytkownika"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "E-mail nie jest zweryfikowany"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "E-mail jest zweryfikowany"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Nie udało się załadować profilu tego użytkownika."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Nie znaleziono użytkownika"
+ },
"profile.label.badges": {
"defaultMessage": "Odznaki"
},
+ "profile.label.collection": {
+ "defaultMessage": "Kolekcja"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {pobranie} few {pobrania} other {pobrań}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Dołączył(-a)"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Ten użytkownik nie ma żadnych kolekcji!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Nie masz jeszcze żadnych kolekcji."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Ten użytkownik nie ma żadnych projektów!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Nie masz jeszcze żadnych projektów."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organizacje"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {projekt} few {projekty} other {projektów}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Oficjalne konto Modrinth"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Oficjalne konto Modrinth. Otrzymaj wsparcie na stronie lub poprzez e-mail "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Wystąpił błąd podczas odblokowywania tego użytkownika. Spróbuj ponownie później."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Nie udało się odblokować użytkownika"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "Użytkownik {username} został odblokowany."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Użytkownik odblokowany"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Opublikowany {date}"
},
@@ -2864,6 +2963,9 @@
"project-type.all": {
"defaultMessage": "Wszystko"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Kolekcje"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Paczka danych} few {Paczki danych} other {Paczek danych}}"
},
@@ -3134,6 +3236,9 @@
"project.follower-count-tooltip": {
"defaultMessage": "{count, number} {count, plural, one {obserwujący} other {obserwujących}}"
},
+ "project.license.error": {
+ "defaultMessage": "Nie można pobrać tekstu licencji."
+ },
"project.license.loading": {
"defaultMessage": "Ładowanie treści licencji..."
},
@@ -3653,15 +3758,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Zaawansowane"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Wyklucz paczki danych"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Wyklucz mody"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Wyklucz pluginy"
- },
"search.filter_type.environment": {
"defaultMessage": "Środowisko"
},
@@ -5087,9 +5183,111 @@
"settings.pats.title": {
"defaultMessage": "Klucze dostępu osobistego"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Krótki opis, aby powiedzieć wszystkim trochę o Tobie."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "O mnie"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Profil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Zdjęcie profilowe"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "Twoje informacje profilowe są publicznie dostępne na Modrinth i poprzez Modrinth API ."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Nie udało się zaktualizować profilu"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Wystąpił błąd podczas aktualizowania profilu. Spróbuj ponownie później."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Zaloguj się na konto Modrinth, by dostosować swój publiczny profil."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Wymagane jest konto Modrinth"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Unikatowa bez uwzględniania wielkości liter nazwa identyfikująca Twój profil."
+ },
"settings.sessions.title": {
"defaultMessage": "Sesje"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Akcje"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Użytkownik"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Lista użytkowników zablokowanych na Modrinth. Nie mogą oni:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Brak zablokowanych użytkowników."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Nie udała się załadować zablokowanych użytkowników."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Ładowanie zablokowanych użytkowników…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Wysyłać ci zaproszeń do znajomych"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Zapraszać cię do zarządzania serwerem Modrinth Hosting."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Zapraszać cię do udostępnionych instancji"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Zablokowani użytkownicy"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Odblokuj"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Nie udało się odblokować użytkownika"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Wystąpił błąd podczas odblokowywania tego użytkownika. Spróbuj ponownie później."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Odblokuj {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Awatar użytkownika {username}"
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Zaproszenia do znajomych"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Już wkrótce!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Wszyscy"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Znajomi"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Znajomi znajomych"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Nikt"
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Zaproszenia"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Wymagane jest konto Modrinth"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Społeczne"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Dodaj"
},
@@ -5099,15 +5297,12 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "Ten użytkownik został już zaproszony."
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Zastosuj"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "Awatar użytkownika {username}"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Anuluj"
- },
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Anuluj"
- },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "Data wygaśnięcia"
},
diff --git a/packages/ui/src/locales/pt-BR/index.json b/packages/ui/src/locales/pt-BR/index.json
index 27fb435faf..f2b189a6a5 100644
--- a/packages/ui/src/locales/pt-BR/index.json
+++ b/packages/ui/src/locales/pt-BR/index.json
@@ -617,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nomes dos projetos"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabético"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Mais recentes primeiro"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Mais antigos primeiro"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Ordenar por {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Atualizar tudo"
},
@@ -1301,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Arquivo salvo"
},
- "files.editor.find-close": {
- "defaultMessage": "Fechar"
- },
"files.editor.find-in-file": {
"defaultMessage": "Localizar"
},
@@ -2081,33 +2066,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Selecionar ícone"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Este pacote de mods não inclui nenhum conteúdo adicional."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Nenhum conteúdo encontrado"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Externo"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "Este arquivo não está publicado no Modrinth."
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Conteúdo do pacote de mods"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Carregando conteúdo..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Nenhum projeto corresponde com sua busca."
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "Abrir no Slicer"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Busque {count, number} {count, plural, one {projeto} other {projetos}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Atual"
},
@@ -2240,6 +2198,9 @@
"label.details": {
"defaultMessage": "Detalhes"
},
+ "label.discover-content": {
+ "defaultMessage": "Descobrir conteúdo"
+ },
"label.done": {
"defaultMessage": "Feito"
},
@@ -2318,6 +2279,9 @@
"label.password": {
"defaultMessage": "Senha"
},
+ "label.permissions": {
+ "defaultMessage": "Permissões"
+ },
"label.plan-custom": {
"defaultMessage": "Personalizado"
},
@@ -2849,9 +2813,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Um criador Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Um usuário do Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} não poderá enviar solicitações de amizade para você, convidar você para instâncias compartilhadas ou convidar você para servidores do Modrinth Hosting."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Deseja mesmo bloquear este usuário?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Ocorreu um erro ao bloquear este usuário. Tente novamente."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Falha ao bloquear usuário"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} bloqueado."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Usuário bloqueado"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Bloquear {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Ver estatísticas do usuário"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Gerenciar cobrança do usuário"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Bloquear"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Criar coleção"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Criar projeto"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Ver detalhes do usuário"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Gerenciar projetos"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Remover como afiliado"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Definir como afiliado"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Desbloquear"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# projeto} other {# projetos}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Permita pop-ups para o Modrinth e tente novamente."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "O perfil do GitHub não pode ser recuperado. Tente novamente."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Não foi possível abrir o perfil do GitHub"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Provedores de autenticação"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "E-mail verificado"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Possui senha"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Possui TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Carregando..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Métodos de pagamento"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Ver perfil"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Detalhes do usuário"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "E-mail não verificado"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "E-mail verificado"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "O perfil do usuário não pôde ser carregado."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Usuário não encontrado"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Afiliado"
+ },
"profile.label.badges": {
"defaultMessage": "Emblemas"
},
+ "profile.label.collection": {
+ "defaultMessage": "Coleção"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {download} other {downloads}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Entrou"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Este usuário não tem coleções!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Você ainda não tem nenhuma coleção."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Este usuário não tem projetos!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Você ainda não tem projetos."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organizações"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {projeto} other {projetos}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Conta oficial do Modrinth"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Conta oficial do Modrinth. Obtenha suporte em ou por e-mail via "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Ocorreu um erro ao desbloquear este usuário. Tente novamente."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Falha ao desbloquear usuário"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} desbloqueado."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Usuário desbloqueado"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Publicado {date}"
},
@@ -2879,6 +2996,9 @@
"project-type.all": {
"defaultMessage": "Todos"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Coleções"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Pacote de dados} other {Pacotes de dados}}"
},
@@ -3159,7 +3279,10 @@
"defaultMessage": "Licença"
},
"project.online-player-count": {
- "defaultMessage": "{count, plural, =0 {Ninguém online} other {{count} online}}"
+ "defaultMessage": "{count, number} online"
+ },
+ "project.online-player-count.tooltip": {
+ "defaultMessage": "{count} {countPlural, plural, one {jogador} other {jogadores}} online"
},
"project.recent-plays": {
"defaultMessage": "{countPlural, plural, =0 {Nenhuma entrada recente} one {{count} entrada recente} other {{count} entradas recentes}}"
@@ -3668,15 +3791,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Avançado"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Excluir pacotes de dados"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Excluir mods"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Excluir plugins"
- },
"search.filter_type.environment": {
"defaultMessage": "Ambiente"
},
@@ -5102,9 +5216,120 @@
"settings.pats.title": {
"defaultMessage": "Token de acesso pessoal"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Uma breve descrição para falar um pouco sobre você para todos."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Sobre"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Perfil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Foto de perfil"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "As informações do seu perfil são visíveis publicamente no Modrinth e através da API do Modrinth ."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Falha ao atualizar o perfil"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Ocorreu um erro ao atualizar seu perfil. Tente novamente."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Inicie sessão com uma conta Modrinth para personalizar seu perfil público."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Conta Modrinth necessária"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Um nome único sem distinção de maiúsculas e minúsculas para identificar o seu perfil."
+ },
"settings.sessions.title": {
"defaultMessage": "Sessões"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Ações"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Usuário"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Estes são os usuários que você bloqueou no Modrinth. Eles não poderão:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Você não bloqueou ninguém."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Os usuários bloqueados não puderam ser carregados."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Carregando usuários bloqueados…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Enviar solicitações de amizade"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Convidar você para gerenciar um servidor Modrinth Hosting."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Convidar você para instâncias compartilhadas"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Usuários bloqueados"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Desbloquear"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Falha ao desbloquear usuário"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Ocorreu um erro ao desbloquear este usuário. Tente novamente."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Desbloquear {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Foto de perfil de {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Controle quem pode enviá-lo solicitações de amizade no Modrinth."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Solicitações de amizade"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Em breve!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Todos"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Amigos"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Amigos de amigos"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Ninguém"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Controle quem pode enviá-lo convites a instâncias compartilhadas e painéis do Modrinth Hosting."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Convites"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "Você pode controlar quem interagir com você e gerenciar usuários bloqueados com uma conta Modrinth"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Conta Modrinth necessária"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Social"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Adicionar"
},
@@ -5114,14 +5339,17 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "Este usuário já foi convidado."
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Aplicar"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "Avatar de {username}"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Cancelar"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Personalizado..."
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Cancelar"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Personalizado: {date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "Editar link de convite."
@@ -5129,6 +5357,24 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "Editar link de convite"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "Em 1 dia"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "Em 1 hora"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "Em 7 dias"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "Em 6 horas"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "Em 3 dias"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "Em 12 horas"
+ },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "Data de expiração"
},
diff --git a/packages/ui/src/locales/pt-PT/index.json b/packages/ui/src/locales/pt-PT/index.json
index f27ed83e44..99fa4888bf 100644
--- a/packages/ui/src/locales/pt-PT/index.json
+++ b/packages/ui/src/locales/pt-PT/index.json
@@ -398,18 +398,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nomes dos projetos"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabético"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Mais recentes primeiro"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Mais antigos primeiro"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Ordenar por {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Atualizar tudo"
},
@@ -497,9 +485,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Ficheiro salvo"
},
- "files.editor.find-close": {
- "defaultMessage": "Fechar"
- },
"files.editor.find-in-file": {
"defaultMessage": "Encontrar"
},
@@ -752,21 +737,6 @@
"instance.worlds.game_mode.unknown": {
"defaultMessage": "Modo de jogo desconhecido"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Este modpack não inclui nenhum conteúdo adicional."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Nenhum conteúdo encontrado"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Conteúdo do modpack"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "A carregar conteúdo..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Nenhum projeto corresponde à tua pesquisa."
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Atual"
},
diff --git a/packages/ui/src/locales/ro-RO/index.json b/packages/ui/src/locales/ro-RO/index.json
index 689a414b43..e608d4140f 100644
--- a/packages/ui/src/locales/ro-RO/index.json
+++ b/packages/ui/src/locales/ro-RO/index.json
@@ -425,18 +425,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Nume ale proiectului"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabetic"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Cele noi mai întâi"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Cele vechi mai întâi"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sortează cu {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Actualizează tot"
},
@@ -551,9 +539,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Fișier salvat"
},
- "files.editor.find-close": {
- "defaultMessage": "Închide"
- },
"files.editor.find-in-file": {
"defaultMessage": "Caută"
},
@@ -1025,24 +1010,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Selectează iconița"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Acest modpack nu include niciun conținut suplimentar."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Nu a fost găsit niciun conținut"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Conținutul Modpack"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Se încarcă materialul..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Niciun proiect nu corespunde căutării dvs."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Căutare {count, number}{count, plural,one {proiect}other {proiecte}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Curent"
},
diff --git a/packages/ui/src/locales/ru-RU/index.json b/packages/ui/src/locales/ru-RU/index.json
index 072d67b335..04829d0c5a 100644
--- a/packages/ui/src/locales/ru-RU/index.json
+++ b/packages/ui/src/locales/ru-RU/index.json
@@ -348,10 +348,10 @@
"defaultMessage": "Выбрать {project}"
},
"content.confirm-bulk-update.admonition-body": {
- "defaultMessage": "Вы уверены, что хотите обновить {count, plural, one {# проект} few {# проекта} other {# проектов}} до их последней совместимой версии? Рекомендуется обновлять контент по отдельности."
+ "defaultMessage": "Вы точно хотите обновить {count, plural, one {# проект} few {# проекта} other {# проектов}} до {count, plural, =1 {последней совместимой версии} other {последних совместимых версий}}? Рекомендуется обновлять контент по очереди."
},
"content.confirm-bulk-update.admonition-header": {
- "defaultMessage": "Предупреждение об обновлении"
+ "defaultMessage": "Предупреждение об обновлении"
},
"content.confirm-bulk-update.header": {
"defaultMessage": "Обновление проектов"
@@ -363,10 +363,10 @@
"defaultMessage": "Обновить {count, plural, one {# проект} few {# проекта} other {# проектов}}"
},
"content.confirm-deletion.admonition-body": {
- "defaultMessage": "Удаление мода может необратимо повлиять на ваш мир, что приведет к потере контента или непредвиденным ошибкам при следующей загрузке."
+ "defaultMessage": "Удаление модов может повлиять на миры и привести к необратимой пропаже контента или ошибкам при следующей загрузке."
},
"content.confirm-deletion.admonition-header": {
- "defaultMessage": "Предупреждение об удалении"
+ "defaultMessage": "Предупреждение об удалении"
},
"content.confirm-deletion.header": {
"defaultMessage": "Удалить {itemType}"
@@ -375,10 +375,10 @@
"defaultMessage": "Отключить {itemType}"
},
"content.confirm-modpack-update.admonition-body": {
- "defaultMessage": "{action, select, downgrade {Понижение версии} other {Обновление}} может привести к проблемам с совместимостью. Моды или другой контент, который вы установили в сборку, сохранятся, но могут быть несовместимы с новой версией."
+ "defaultMessage": "{action, select, downgrade {Откат} other {Обновление}} может нарушить совместимость. Добавленные вами моды и контент останутся, но могут перестать работать в новой версии."
},
"content.confirm-modpack-update.admonition-header": {
- "defaultMessage": "Предупреждение: {action, select, downgrade {откат} other {обновление}} версии"
+ "defaultMessage": "Предупреждение об {action, select, downgrade {откате} other {обновлении}}"
},
"content.confirm-modpack-update.confirm-button": {
"defaultMessage": "{action, select, downgrade {Откатить} other {Обновить}} сборку"
@@ -387,7 +387,7 @@
"defaultMessage": "{action, select, downgrade {Откат} other {Обновление}} сборки"
},
"content.confirm-unlink.admonition-body": {
- "defaultMessage": "Моды и контент будут объединены с тем, что вы добавили в сборку. После этого сборка перестанет получать обновления."
+ "defaultMessage": "Моды и контент объединятся с вашими добавлениями, но сборка перестанет получать обновления."
},
"content.confirm-unlink.admonition-header": {
"defaultMessage": "Отвязка сборки"
@@ -471,13 +471,13 @@
"defaultMessage": "Загрузчик"
},
"content.diff-modal.modpack-linked": {
- "defaultMessage": "Связанная сборка"
+ "defaultMessage": "Привязана сборка"
},
"content.diff-modal.modpack-unlinked": {
- "defaultMessage": "Несвязанная сборка"
+ "defaultMessage": "Отвязана сборка"
},
"content.diff-modal.modpack-updated": {
- "defaultMessage": "Обновлённая сборка"
+ "defaultMessage": "Обновлена сборка"
},
"content.diff-modal.no-content-changes": {
"defaultMessage": "Без изменений"
@@ -584,18 +584,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Названия проектов"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "По алфавиту"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Сначала новые"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Сначала старые"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Сортировка: {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Обновить всё"
},
@@ -846,7 +834,7 @@
"defaultMessage": "Начать с нуля, выбрав загрузчик и версию игры."
},
"creation-flow.modal.setup-type.option.custom-setup.title": {
- "defaultMessage": "Пользовательская настройка"
+ "defaultMessage": "Собственная настройка"
},
"creation-flow.modal.setup-type.option.import-instance.description": {
"defaultMessage": "Импортировать сборку из Prism, CurseForge, или похожего лаунчера."
@@ -1229,9 +1217,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Файл сохранён"
},
- "files.editor.find-close": {
- "defaultMessage": "Закрыть"
- },
"files.editor.find-in-file": {
"defaultMessage": "Найти"
},
@@ -1809,52 +1794,52 @@
"defaultMessage": "Настройка установки"
},
"installation-settings.edit.warning-instance": {
- "defaultMessage": "Мы не рекомендуем изменять настройки сборки после установки контента. Если вы всё же хотите их изменить, будьте осторожны, так как это может вызвать проблемы."
+ "defaultMessage": "Не рекомендуется изменять установку после добавления контента. Это может привести к ошибкам."
},
"installation-settings.edit.warning-server": {
- "defaultMessage": "Не рекомендуется менять настройки инсталляции после установки контента. Если вы всё же хотите изменить их, перезагрузите сервер."
+ "defaultMessage": "Не рекомендуется изменять установку после добавления контента. Лучше сразу переустановить сервер."
},
"installation-settings.incompatible-content.auto-fix-button": {
- "defaultMessage": "Авто-исправление"
+ "defaultMessage": "Исправить"
},
"installation-settings.incompatible-content.change-loader-button": {
"defaultMessage": "Сменить загрузчик"
},
"installation-settings.incompatible-content.disable-conflicts-button": {
- "defaultMessage": "Отключить конфликты"
+ "defaultMessage": "Отключить"
},
"installation-settings.incompatible-content.game-version-warning-body": {
- "defaultMessage": "При изменении версии игры вы можете либо отключить несовместимый контент, либо попытаться устранить несовместимости."
+ "defaultMessage": "При смене версии игры можно отключить несовместимый контент или попытаться исправить несовместимости автоматически."
},
"installation-settings.incompatible-content.game-version-warning-title": {
- "defaultMessage": "Предупреждение о несовместимости"
+ "defaultMessage": "Предупреждение о несовместимости"
},
"installation-settings.incompatible-content.header": {
- "defaultMessage": "Установлены несовместимые проекты"
+ "defaultMessage": "Нарушение совместимости"
},
"installation-settings.incompatible-content.loader-change-body": {
- "defaultMessage": "При смене загрузчика модов, все установленные проекты будут отключены. Вместо этого рекомендуется сбросить сервер."
+ "defaultMessage": "Смена загрузчика отключит установленный контент. Лучше сразу переустановить сервер."
},
"installation-settings.incompatible-content.loader-change-title": {
"defaultMessage": "Смена загрузчика небезопасна"
},
"installation-settings.linked-instance.title": {
- "defaultMessage": "Связанный {projectType}"
+ "defaultMessage": "Отвязка {projectType}"
},
"installation-settings.linked.modpack": {
- "defaultMessage": "сборка"
+ "defaultMessage": "сборки"
},
"installation-settings.linked.server-project": {
- "defaultMessage": "серверный проект"
+ "defaultMessage": "серверного проекта"
},
"installation-settings.loader-version": {
"defaultMessage": "Версия {loader}"
},
"installation-settings.platform-lock-tooltip": {
- "defaultMessage": "Необходимо сбросить сервер для изменения загрузчика."
+ "defaultMessage": "Для смены загрузчика необходимо переустановить сервер."
},
"installation-settings.reinstall-modpack.description": {
- "defaultMessage": "Переустановка сборки сбросит контент, который использует {type}, до исходного состояния, удалив все добавленные вами моды и файлы."
+ "defaultMessage": "Переустановка сбросит {type} к исходному состоянию, удалив все добавленные вами моды и контент."
},
"installation-settings.reinstall-modpack.title": {
"defaultMessage": "Переустановка сборки"
@@ -1884,31 +1869,31 @@
"defaultMessage": "Поиск версии игры..."
},
"installation-settings.type.instance": {
- "defaultMessage": "сборка"
+ "defaultMessage": "сборку"
},
"installation-settings.type.instance-possessive": {
- "defaultMessage": "сборки"
+ "defaultMessage": "сборку"
},
"installation-settings.type.server": {
"defaultMessage": "сервер"
},
"installation-settings.type.server-possessive": {
- "defaultMessage": "серверы"
+ "defaultMessage": "сервер"
},
"installation-settings.unlink": {
"defaultMessage": "Отвязать"
},
"installation-settings.unlink.description": {
- "defaultMessage": "Отвязка навсегда отключит этот {type} от проекта {projectType}, что позволит вам изменить загрузчик и версию Minecraft, но вы больше не сможете получать обновления."
+ "defaultMessage": "Отвязка навсегда отключит {type} от исходного проекта. Это откроет доступ к смене версии игры и загрузчика, но получение обновлений прекратится."
},
"installation-settings.verifying": {
"defaultMessage": "Проверка..."
},
"instance.confirm-reinstall.admonition-body": {
- "defaultMessage": "Переустановка сбросит весь установленный или изменённый контент к начальному состоянию, удалив моды и контент, добавленные поверх исходной установки."
+ "defaultMessage": "Переустановка сбросит установленное содержимое к исходному состоянию, удалив добавленные вами моды и контент."
},
"instance.confirm-reinstall.admonition-header": {
- "defaultMessage": "Предупреждение переустановки"
+ "defaultMessage": "Предупреждение о переустановке"
},
"instance.confirm-reinstall.header": {
"defaultMessage": "Переустановка сборки"
@@ -1997,33 +1982,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Выбрать иконку"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "В сборке нет дополнительного контента."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Сборка пуста"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "Сторонний"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "Файл не опубликован на Modrinth."
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Содержимое сборки"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Загрузка содержимого..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Не найдены проекты, соответствующие запросу."
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "Открыть в Slicer"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Поиск по {count, number} {count, plural, one {проекту} other {проектам}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Текущая"
},
@@ -2156,6 +2114,9 @@
"label.details": {
"defaultMessage": "Сведения"
},
+ "label.discover-content": {
+ "defaultMessage": "Найти проекты"
+ },
"label.done": {
"defaultMessage": "Готово"
},
@@ -2234,6 +2195,9 @@
"label.password": {
"defaultMessage": "Пароль"
},
+ "label.permissions": {
+ "defaultMessage": "Разрешения"
+ },
"label.plan-custom": {
"defaultMessage": "Свой"
},
@@ -2762,9 +2726,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Автор на Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Пользователь Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} не сможет отправлять вам запросы в друзья, приглашать вас в сборки или приглашать вас управлять сервером Modrinth Hosting."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Вы действительно хотите заблокировать этого пользователя?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Произошла ошибка при блокировке пользователя. Попробуйте снова."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Не удалось заблокировать"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} заблокирован."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Пользователь заблокирован"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Заблокировать {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Посмотреть аналитику"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Управление платежами"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Заблокировать"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Создать коллекцию"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Создать проект"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Посмотреть подробности"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Управление проектами"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Убрать из партнёров"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Сделать партнёром"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Разблокировать"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# проект} few {# проекта} other {# проектов}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Разрешите всплывающие окна для Modrinth и повторите попытку."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "Не удалось получить профиль GitHub. Повторите попытку."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Не удалось открыть профиль GitHub"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Сервисы входа"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "Почта подтверждена"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Есть пароль"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Есть TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Загрузка..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Способы оплаты"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Посмотреть профиль"
+ },
+ "profile.details.title": {
+ "defaultMessage": "О пользователе"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "Почта не подтверждена"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "Почта подтверждена"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Не удалось загрузить профиль."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Пользователь не найден"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Партнёр"
+ },
"profile.label.badges": {
"defaultMessage": "Значки"
},
+ "profile.label.collection": {
+ "defaultMessage": "Коллекция"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {скачивание} few {скачивания} other {скачиваний}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Регистрация:"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "У этого пользователя нет коллекций!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Коллекций пока нет."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "У этого пользователя нет проектов!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Проектов пока нет."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Организации"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {проект} few {проекта} other {проектов}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Официальный аккаунт Modrinth"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Официальный аккаунт Modrinth. Связь с поддержкой: или по почте "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Произошла ошибка при разблокировке пользователя. Попробуйте снова."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Не удалось разблокировать"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} разблокирован."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Пользователь разблокирован"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Опубликован {date}"
},
@@ -2792,6 +2909,9 @@
"project-type.all": {
"defaultMessage": "Всё"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Коллекции"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {набор данных} few {набора данных} other {наборов данных}}"
},
@@ -3584,15 +3704,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Расширенные"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Исключать наборы данных"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Исключать моды"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Исключать плагины"
- },
"search.filter_type.environment": {
"defaultMessage": "Среда"
},
@@ -4290,7 +4401,7 @@
"defaultMessage": "После удаления {count, plural, one {эта резервная копия не может быть восстановлена} other {эти резервные копии не могут быть восстановлены}}. Удаление необратимо."
},
"servers.backups.delete-modal.admonition-header": {
- "defaultMessage": "Предупреждение об удалении"
+ "defaultMessage": "Предупреждение об удалении"
},
"servers.backups.delete-modal.backups-label": {
"defaultMessage": "{count, plural, one {Резервная копия} other {Резервные копии ({count})}}"
@@ -4746,7 +4857,7 @@
"defaultMessage": "Способ оплаты"
},
"servers.purchase.step.plan.billed": {
- "defaultMessage": "оплата {interval, select, monthly {ежемесячно} quarterly {ежеквартально} yearly {ежегодно} other {{interval}}}"
+ "defaultMessage": "{interval, select, monthly {за месяц} quarterly {за 3 месяца} yearly {за год} other {billed {interval}}}"
},
"servers.purchase.step.plan.billing-subtitle": {
"defaultMessage": "Доступно в Северной Америке, Европе и Юго‑Восточной Азии."
@@ -5018,9 +5129,120 @@
"settings.pats.title": {
"defaultMessage": "Личные токены доступа"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Возможность кратко рассказать всем о себе."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "О себе"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Профиль"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Изображение профиля"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "Информация в вашем профиле доступна публично на Modrinth и через API Modrinth ."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Не удалось обновить профиль"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Произошла ошибка при обновлении профиля. Попробуйте снова."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Войдите в аккаунт Modrinth для кастомизации вашего публичного профиля."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Требуется аккаунт Modrinth"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Уникальное имя для идентификации профиля."
+ },
"settings.sessions.title": {
"defaultMessage": "Сеансы"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Действия"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Пользователь"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Это пользователи, которых вы заблокировали на Modrinth. Они не могут:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Вы никого не заблокировали."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Заблокированные пользователи не загрузились."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Загрузка заблокированных пользователей..."
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Отправлять вам запросы в друзья"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Приглашать вас управлять сервером Modrinth Hosting."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Приглашать вас в сборки"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Заблокированные пользователи"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Разблокировать"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Не удалось разблокировать"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Произошла ошибка при разблокировке пользователя. Попробуйте снова."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Разблокировать {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Аватар {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Настройте, кто может отправить вам заявку в друзья на Modrinth."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Запросы в друзья"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Скоро будет!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Все"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Друзья"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Друзья друзей"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Никто"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Настройте, кто вам может отправить заявку на общие сборки и панели Modrinth Hosting."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Приглашения"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "С помощью аккаунта Modrinth, вы можете настраивать кто может взаимодействовать с вами, а также управлять заблокированными пользователями"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Требуется аккаунт Modrinth"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Общение"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "Добавить"
},
@@ -5030,14 +5252,17 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "Этот пользователь уже приглашён."
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Применить"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "Аватар {username}"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "Отозвать"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Другое..."
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "Отмена"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Другое: {date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "Настроить ссылку."
@@ -5045,6 +5270,24 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "Настройка ссылки"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "1 день"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "1 час"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "7 дней"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "6 часов"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "3 дня"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "12 часов"
+ },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "Срок действия"
},
diff --git a/packages/ui/src/locales/sr-CS/index.json b/packages/ui/src/locales/sr-CS/index.json
index 6117939c7d..91ea30e3f4 100644
--- a/packages/ui/src/locales/sr-CS/index.json
+++ b/packages/ui/src/locales/sr-CS/index.json
@@ -584,18 +584,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Imena projekata"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabetski"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Najnovije prvo"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Najstarije prvo"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sortiraj so {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Ažuiraj sve"
},
@@ -1253,9 +1241,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Datoteka sačuvana"
},
- "files.editor.find-close": {
- "defaultMessage": "Zatvori"
- },
"files.editor.find-in-file": {
"defaultMessage": "Pronađi"
},
@@ -2033,24 +2018,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Izaberi ikonu"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Ovaj modpack ne uključuje nikakav dodatni sadržaj."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Nema pronađenog sadržaja"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Sadržaj modpacka"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Učitavanje sadržaja..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Nijedan projekat ne odgovara tvojoj pretrazi."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Pretraga {count, number} {count, plural, one {projekta} few {projekta} other {projekata}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Upravo"
},
@@ -3593,15 +3560,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Napredno"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Isključi data pakete"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Isključi modove"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Isključi plugine"
- },
"search.filter_type.environment": {
"defaultMessage": "Okruže"
},
diff --git a/packages/ui/src/locales/sv-SE/index.json b/packages/ui/src/locales/sv-SE/index.json
index fa83bc14dd..e42b371e02 100644
--- a/packages/ui/src/locales/sv-SE/index.json
+++ b/packages/ui/src/locales/sv-SE/index.json
@@ -117,7 +117,7 @@
"defaultMessage": "Du har valt {count, number} projekt att installera. Installera dem nu eller gå tillbaka utan att installera dem."
},
"browse.selected-projects-leave-modal.admonition-header": {
- "defaultMessage": "Valda projekt är inte installerade än"
+ "defaultMessage": "De valda projekten är inte installerade än"
},
"browse.selected-projects-leave-modal.discard": {
"defaultMessage": "Kasta"
@@ -377,6 +377,9 @@
"content.confirm-deletion.header": {
"defaultMessage": "Radera {itemType}"
},
+ "content.confirm-disable.header": {
+ "defaultMessage": "Inaktivera {itemType}"
+ },
"content.confirm-modpack-update.admonition-body": {
"defaultMessage": "Att {action, select, downgrade {nedgradera} other {uppdatera}} kan orsaka kompatibilitetsproblem. Moddar eller innehåller du själv lagt till kommer behållas, men är kanske inte kompatibel med den nya versionen."
},
@@ -455,6 +458,9 @@
"content.diff-modal.diff-type.removed": {
"defaultMessage": "Inaktiverade"
},
+ "content.diff-modal.diff-type.removed-disabled": {
+ "defaultMessage": "Tog bort (inaktiverad)"
+ },
"content.diff-modal.diff-type.updated": {
"defaultMessage": "Uppdaterade"
},
@@ -470,18 +476,33 @@
"content.diff-modal.external-diff-type.updated": {
"defaultMessage": "Uppdaterad"
},
+ "content.diff-modal.file-count": {
+ "defaultMessage": "{count, plural, one {# fil} other {# filer}}"
+ },
"content.diff-modal.game-version-updated": {
"defaultMessage": "Spelversion"
},
"content.diff-modal.install-anyway": {
"defaultMessage": "Installera ändå"
},
+ "content.diff-modal.modpack-linked": {
+ "defaultMessage": "Länkat modpaket"
+ },
+ "content.diff-modal.modpack-unlinked": {
+ "defaultMessage": "Avlänkat modpaket"
+ },
+ "content.diff-modal.modpack-updated": {
+ "defaultMessage": "Uppdaterat modpaket"
+ },
"content.diff-modal.no-content-changes": {
"defaultMessage": "Inga innehållsändringar"
},
"content.diff-modal.removed-count": {
"defaultMessage": "{count} borttagna"
},
+ "content.diff-modal.reviewed-files": {
+ "defaultMessage": "En fil granskas bara om den publiceras på Modrinth, oavsett dess filformat (däribland .mrpack)."
+ },
"content.diff-modal.unknown-content-body": {
"defaultMessage": "Något innehåll på din server kunde inte analyseras och kommer kanske påverkas av denna ändring."
},
@@ -590,18 +611,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Projektnamn"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabetisk"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Nyaste först"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Äldsta först"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sortera i {mode} ordning"
- },
"content.page-layout.update-all": {
"defaultMessage": "Uppdatera alla"
},
@@ -774,7 +783,7 @@
"defaultMessage": "Ange världnamn"
},
"creation-flow.modal.final-config.world-seed.description": {
- "defaultMessage": "Lämna tom för slumpmässig utsäde."
+ "defaultMessage": "Lämna tom för slumpmässig frö."
},
"creation-flow.modal.final-config.world-seed.placeholder": {
"defaultMessage": "Ange världsfrö"
@@ -842,12 +851,21 @@
"creation-flow.modal.setup-type.option.import-instance.title": {
"defaultMessage": "Importera instans"
},
+ "creation-flow.modal.setup-type.option.modpack-base.description": {
+ "defaultMessage": "Bläddra bland modpaket på Modrinth eller importera ett från en fil."
+ },
"creation-flow.modal.setup-type.option.modpack-base.title": {
"defaultMessage": "Installera modpaket"
},
"creation-flow.modal.setup-type.option.vanilla-minecraft.description": {
"defaultMessage": "Klassiska Minecraft, utan moddar eller plugin."
},
+ "creation-flow.modal.setup-type.option.vanilla-minecraft.title": {
+ "defaultMessage": "Vanilla Minecraft"
+ },
+ "creation-flow.modal.setup-type.title.installation": {
+ "defaultMessage": "Välj installationstyp"
+ },
"creation-flow.modal.setup-type.title.instance": {
"defaultMessage": "Välj instanstyp"
},
@@ -869,9 +887,15 @@
"creation-flow.title.reset-server": {
"defaultMessage": "Starta om server"
},
+ "creation-flow.title.set-up-server": {
+ "defaultMessage": "Ställ in server"
+ },
"external-files.permissions-card.add-files-modal.confirm": {
"defaultMessage": "Lägg till {count, plural, one {# fil} other {# filer}}"
},
+ "external-files.permissions-card.add-files-modal.load-error.title": {
+ "defaultMessage": "Kunde inte ladda filer"
+ },
"external-files.permissions-card.add-files-modal.no-search-results": {
"defaultMessage": "Inga filer matchade din sökning."
},
@@ -896,9 +920,15 @@
"external-files.permissions-card.attribution.moderation-status.passed": {
"defaultMessage": "Godkänd"
},
+ "external-files.permissions-card.badge.no-permission": {
+ "defaultMessage": "Ingen tillåtelse"
+ },
"external-files.permissions-card.badge.not-allowed": {
"defaultMessage": "Inte tillåten"
},
+ "external-files.permissions-card.badge.pending": {
+ "defaultMessage": "Väntar"
+ },
"external-files.permissions-card.custom-license-option": {
"defaultMessage": "Annan"
},
@@ -962,6 +992,12 @@
"external-files.permissions-card.file-count": {
"defaultMessage": "{count, plural, one {# fil} other {# filer}}"
},
+ "external-files.permissions-card.included-files": {
+ "defaultMessage": "Inkluderade filer:"
+ },
+ "external-files.permissions-card.included-in-versions": {
+ "defaultMessage": "Inkuderad i {count, plural, one {# verion} other {# versioner}}:"
+ },
"external-files.permissions-card.last-updated": {
"defaultMessage": "Senast uppdaterad den {date} av {user}"
},
@@ -1010,6 +1046,18 @@
"external-files.permissions-card.reason.special-permission.description": {
"defaultMessage": "Du har erhållit speciell tillåtelse för att distribuera detta verk i ditt modpaket."
},
+ "external-files.permissions-card.remove-group": {
+ "defaultMessage": "Radera grupp"
+ },
+ "external-files.permissions-card.remove-group-confirmation.title": {
+ "defaultMessage": "Radera {title}?"
+ },
+ "external-files.permissions-card.remove-group-error.title": {
+ "defaultMessage": "Kunde inte radera grupp"
+ },
+ "external-files.permissions-card.remove-group-shift-hint": {
+ "defaultMessage": "Håll skift medan du klickar för att hoppa över bekräftelsen."
+ },
"external-files.permissions-card.split-file": {
"defaultMessage": "Ta bort från grupp"
},
@@ -1094,9 +1142,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Filen sparades"
},
- "files.editor.find-close": {
- "defaultMessage": "Stäng"
- },
"files.editor.find-in-file": {
"defaultMessage": "Hitta"
},
@@ -1145,12 +1190,18 @@
"files.image_viewer.image_too_large": {
"defaultMessage": "Bilden är för stor för att se (högst {maxDimension}x{maxDimension} pixlar)"
},
+ "files.image_viewer.invalid_image": {
+ "defaultMessage": "Ogiltig eller tom bildfil."
+ },
"files.image_viewer.load_failed": {
"defaultMessage": "Kunde inte ladda bilden"
},
"files.image_viewer.reset_zoom": {
"defaultMessage": "Återställ zoom"
},
+ "files.image_viewer.viewed_image_alt": {
+ "defaultMessage": "Visad bild"
+ },
"files.image_viewer.zoom_in": {
"defaultMessage": "Zooma in"
},
@@ -1190,6 +1241,9 @@
"files.move-modal.header": {
"defaultMessage": "Flytta {type}"
},
+ "files.navbar.back-to-home": {
+ "defaultMessage": "Tillbaka hem"
+ },
"files.navbar.breadcrumb-navigation": {
"defaultMessage": "Länkstigsnavigering"
},
@@ -1220,9 +1274,24 @@
"files.navbar.upload-from-zip": {
"defaultMessage": "Ladda upp .zip-fil"
},
+ "files.navbar.upload-from-zip-url": {
+ "defaultMessage": "Uppladdad från .zip-URL"
+ },
"files.operations.current-file": {
"defaultMessage": "Nuvarande fil: {file}"
},
+ "files.operations.extracted": {
+ "defaultMessage": "{size} packas upp"
+ },
+ "files.operations.extracting": {
+ "defaultMessage": "Packar upp {source}"
+ },
+ "files.operations.extracting-completed": {
+ "defaultMessage": "Uppackning {source} slutförd"
+ },
+ "files.operations.extracting-failed": {
+ "defaultMessage": "Uppackning {source} misslyckad"
+ },
"files.operations.modpack-from-url": {
"defaultMessage": "modpaket från en webbadress"
},
@@ -1437,7 +1506,7 @@
"defaultMessage": "Prestandapåverkan"
},
"header.category.resolutions": {
- "defaultMessage": "Kvalitet"
+ "defaultMessage": "Upplösning"
},
"hosting.content.failed-to-bulk-delete": {
"defaultMessage": "Kunde inte radera innehållet"
@@ -1496,6 +1565,9 @@
"hosting.loader.loader-version": {
"defaultMessage": "{loader, select, null {Loader} other {{loader}}} version"
},
+ "hosting.loader.reset-server": {
+ "defaultMessage": "Återställ server"
+ },
"hosting.specs.burst": {
"defaultMessage": "Ökar upp till {cpus} CPU:er"
},
@@ -1571,9 +1643,15 @@
"installation-settings.incompatible-content.auto-fix-button": {
"defaultMessage": "Auto-fix"
},
+ "installation-settings.linked-instance.title": {
+ "defaultMessage": "Länkat {projectType}"
+ },
"installation-settings.linked.modpack": {
"defaultMessage": "modpaket"
},
+ "installation-settings.linked.server-project": {
+ "defaultMessage": "serverprojekt"
+ },
"installation-settings.loader-version": {
"defaultMessage": "{loader} version"
},
@@ -1581,7 +1659,7 @@
"defaultMessage": "Du kommer att behöva ställa om din server för att ändra loader."
},
"installation-settings.reinstall-modpack.description": {
- "defaultMessage": "Ominstallering av modpaketet återställer {type} innehåll till dess ursprungliga skick, vilket tar bort moddar eller innehåll du lagt till."
+ "defaultMessage": "Ominstallering av modpaketet återställer {type}innehållet till dess ursprungliga skick, vilket tar bort moddar eller innehåll du lagt till."
},
"installation-settings.reinstall-modpack.title": {
"defaultMessage": "Ominstallera modpaket"
@@ -1709,24 +1787,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Välj ikon"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Modpaketet innehåller inget ytterligare innehåll."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Inget innehåll hittades"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Modpaketets innehåll"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Laddar innehåll..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Inga projekt matchar din sökning."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Sök genom {count, number} projekt"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Nuvarande"
},
@@ -1823,6 +1883,9 @@
"label.copied-path": {
"defaultMessage": "Kopiera sökväg"
},
+ "label.create-failed": {
+ "defaultMessage": "Skapning misslyckades"
+ },
"label.created-ago": {
"defaultMessage": "Skapad {ago}"
},
@@ -1844,6 +1907,9 @@
"label.details": {
"defaultMessage": "Detaljer"
},
+ "label.discover-content": {
+ "defaultMessage": "Upptäck innehåll"
+ },
"label.done": {
"defaultMessage": "Klart"
},
@@ -1859,6 +1925,9 @@
"label.error": {
"defaultMessage": "Fel"
},
+ "label.extract-failed": {
+ "defaultMessage": "Uppackning misslyckades"
+ },
"label.filter-by": {
"defaultMessage": "Filtrera efter"
},
@@ -1874,6 +1943,9 @@
"label.hide-installed-content": {
"defaultMessage": "Göm redan installerat innehåll"
},
+ "label.hide-selected-content": {
+ "defaultMessage": "Göm valt innehåll"
+ },
"label.installation-info": {
"defaultMessage": "Installationsinfo"
},
@@ -1898,6 +1970,9 @@
"label.modpack": {
"defaultMessage": "Modpaket"
},
+ "label.move-failed": {
+ "defaultMessage": "Flytt misslyckades"
+ },
"label.no": {
"defaultMessage": "Nej"
},
@@ -1913,6 +1988,9 @@
"label.password": {
"defaultMessage": "Lösenord"
},
+ "label.permissions": {
+ "defaultMessage": "Behörigheter"
+ },
"label.plan-custom": {
"defaultMessage": "Anpassad"
},
@@ -1943,6 +2021,9 @@
"label.rejected": {
"defaultMessage": "Nekad"
},
+ "label.rename-failed": {
+ "defaultMessage": "Namnbyte misslyckades"
+ },
"label.rewards-program-terms-agreement": {
"defaultMessage": "Jag godkänner Belöningsprogrammets Villkor "
},
@@ -1958,12 +2039,18 @@
"label.select-all": {
"defaultMessage": "Välj alla"
},
+ "label.selected": {
+ "defaultMessage": "Vald"
+ },
"label.selection-actions": {
"defaultMessage": "Valåtgärder"
},
"label.server": {
"defaultMessage": "Server"
},
+ "label.server-only": {
+ "defaultMessage": "Endast server"
+ },
"label.servers": {
"defaultMessage": "Servrar"
},
@@ -1994,6 +2081,9 @@
"label.updating": {
"defaultMessage": "Uppdaterar..."
},
+ "label.upload-failed": {
+ "defaultMessage": "Uppladdning misslyckades"
+ },
"label.username": {
"defaultMessage": "Användarnamn"
},
@@ -2162,6 +2252,9 @@
"markdown-editor.markdown-formatting-support": {
"defaultMessage": "Denna redigerare stödjer markdown formatering ."
},
+ "markdown-editor.max-length.label": {
+ "defaultMessage": "Max längd:"
+ },
"markdown-editor.max-length.unlimited": {
"defaultMessage": "Obegränsad"
},
@@ -2420,6 +2513,108 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.user": {
+ "defaultMessage": "En Modrinth-användare."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Är du säker på att du vill blocka den här användaren?"
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Användare blockerad"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Blocka {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Visa användarstatistik"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Blockera"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Skapa ett projekt"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Visa användardetaljer"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Hantera projekt"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Avblockera"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "projekt"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "E-post verifierad"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Har lösenord"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Har TOTP"
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Betalningsmetoder"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Användardetaljer"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "E-post ej verifierad"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "E-post verifierad"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Användarprofilen kunde inte laddas in."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Användare hittades inte"
+ },
+ "profile.label.collection": {
+ "defaultMessage": "Sammling"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {nedladdning} other {nedladdningar}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Gick med"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Den här användaren har inga samlingar!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Du har inga samlingar än."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Den här användaren har inga projekt!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Du har inga projekt än."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Organisationer"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "Projekt"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Officiellt Modrinth-konto"
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Ett fel inträffade under avblockeringen av den här användaren. Vänligen försök igen."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Misslyckades att avblockera användare"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} har avblockerats."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Användare avblockerad"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Skapades {date}"
},
@@ -2438,9 +2633,15 @@
"project-card.environment.server": {
"defaultMessage": "Server"
},
+ "project-card.environment.singleplayer": {
+ "defaultMessage": "Enspelarläge"
+ },
"project-type.all": {
"defaultMessage": "Alla"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Samlingar"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Datapaket} other {Datapaket}}"
},
@@ -2540,6 +2741,9 @@
"project.about.compatibility.platforms": {
"defaultMessage": "Plattformar"
},
+ "project.about.compatibility.platforms-plural": {
+ "defaultMessage": "Platform{count, plural, one {} other {ar}}"
+ },
"project.about.compatibility.title": {
"defaultMessage": "Kompatibilitet"
},
@@ -2708,6 +2912,9 @@
"project.follower-count-tooltip": {
"defaultMessage": "{count, number} följare"
},
+ "project.license.title": {
+ "defaultMessage": "Licens"
+ },
"project.online-player-count": {
"defaultMessage": "{count, number} online"
},
@@ -3113,6 +3320,12 @@
"project.settings.view.title": {
"defaultMessage": "Visa"
},
+ "project.stats.downloads-label": {
+ "defaultMessage": "nedladdning{count, plural, one {} other {ar}}"
+ },
+ "project.stats.followers-label": {
+ "defaultMessage": "följare"
+ },
"project.versions.channel.alpha.symbol": {
"defaultMessage": "A"
},
@@ -3122,6 +3335,9 @@
"project.versions.channel.release.symbol": {
"defaultMessage": "R"
},
+ "project.versions.platform.modloader.short": {
+ "defaultMessage": "ModLoader"
+ },
"project.visibility.archived": {
"defaultMessage": "Arkiverad"
},
@@ -3200,12 +3416,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Avancerat"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Exkludera datapaket"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Exkludera moddar"
- },
"search.filter_type.environment": {
"defaultMessage": "Miljö"
},
@@ -3338,6 +3548,9 @@
"servers.access-page.activity-log-filter.action.java-version-modified": {
"defaultMessage": "Ändrade Java-version"
},
+ "servers.access-page.activity-log-filter.action.loader-version-edited": {
+ "defaultMessage": "Ändrade loaderversion"
+ },
"servers.access-page.activity-log-filter.action.modpack-changed": {
"defaultMessage": "Ändrade modpaket"
},
@@ -3638,6 +3851,18 @@
"servers.audit-log.event.java-version-modified": {
"defaultMessage": "Ändrade Java-version till "
},
+ "servers.audit-log.event.loader-and-version-changed": {
+ "defaultMessage": "Ändrade loader till "
+ },
+ "servers.audit-log.event.loader-changed": {
+ "defaultMessage": "Ändrade loader till "
+ },
+ "servers.audit-log.event.loader-version-changed": {
+ "defaultMessage": "Ändrare loaderversion till "
+ },
+ "servers.audit-log.event.loader-version-cleared": {
+ "defaultMessage": "Rensade laoaderversion"
+ },
"servers.audit-log.event.modpack-changed": {
"defaultMessage": "Ändrade modpaket"
},
@@ -3695,6 +3920,9 @@
"servers.audit-log.event.server-properties-modified-label": {
"defaultMessage": "Modifierade serveregenskaper"
},
+ "servers.audit-log.event.server-reset": {
+ "defaultMessage": "Återställ server"
+ },
"servers.audit-log.event.server-restarted": {
"defaultMessage": "Startade om server"
},
@@ -3767,30 +3995,75 @@
"servers.backups.admonition.fallback-name": {
"defaultMessage": "Din säkerhetskopia"
},
+ "servers.backups.admonition.restore-cancelled.title": {
+ "defaultMessage": "Återställning avbröts"
+ },
"servers.backups.admonition.restore-failed.description": {
"defaultMessage": "Något gick fel när vi försökte återställa från säkerhetskopian {backupName}. Vänligen försök igen eller kontakta support om felet återkommer."
},
+ "servers.backups.admonition.restore-failed.title": {
+ "defaultMessage": "Återställning misslyckades"
+ },
"servers.backups.admonition.restore-queued.description": {
"defaultMessage": "Återställning från {backupName} är köad och kommer att börja strax."
},
"servers.backups.admonition.restore-successful.description": {
"defaultMessage": "Din server har återställts till {backupName} och är redo för att startas."
},
+ "servers.backups.admonition.restore-successful.title": {
+ "defaultMessage": "Återställning slutförd"
+ },
"servers.backups.admonition.restoring-backup.description": {
"defaultMessage": "Återställer din server från {backupName}. Detta kan ta några minuter."
},
"servers.backups.admonition.restoring-backup.title": {
"defaultMessage": "Återställer från säkerhetskopia"
},
+ "servers.backups.bulk-bar.deleting": {
+ "defaultMessage": "Raderar {total, plural, one {# säkerhetskopia} other {# säkerhetskopior}}..."
+ },
+ "servers.backups.bulk-bar.selected-count": {
+ "defaultMessage": "{count, plural, one {# säkerhetskopia vald} other {# säkerhetskopior valda}}"
+ },
"servers.backups.delete-modal.admonition-body": {
"defaultMessage": "När {count, plural, one {denna säkerhetskopia raderas kan den} other {dessa säkerhetskopior raderas kan de}} inte återställas. Radering är permanent."
},
+ "servers.backups.delete-modal.admonition-header": {
+ "defaultMessage": "Raderingsvarning"
+ },
+ "servers.backups.delete-modal.backups-label": {
+ "defaultMessage": "{count, plural, one {Säkerhetskopia} other {Säkerhetskopior ({count})}}"
+ },
+ "servers.backups.delete-modal.confirm": {
+ "defaultMessage": "Radera {count, plural, one {säkerhetskopia} other {# säkerhetskopior}}"
+ },
+ "servers.backups.delete-modal.header": {
+ "defaultMessage": "Radera {count, plural, one {säkerhetskopia} other {säkerhetskopior}}"
+ },
+ "servers.backups.empty.description": {
+ "defaultMessage": "Skapa din första säkerhetskopia"
+ },
+ "servers.backups.empty.heading": {
+ "defaultMessage": "Inga säkerhetskopior än"
+ },
+ "servers.backups.filtered-empty.clear-filters": {
+ "defaultMessage": "Töm filter"
+ },
+ "servers.backups.filtered-empty.description": {
+ "defaultMessage": "Prova ett annat filer eller töm filtren för att se alla säkerhetskopior."
+ },
+ "servers.backups.filtered-empty.heading": {
+ "defaultMessage": "Inga säkerhetskopior matchar"
+ },
"servers.backups.item.auto": {
"defaultMessage": "Auto"
},
"servers.backups.item.backup-schedule": {
"defaultMessage": "Säkerhetskopieringschema"
},
+ "servers.backups.item.creator-avatar-alt": {
+ "defaultMessage": "{username}s avatar"
+ },
"servers.backups.item.manual-backup": {
"defaultMessage": "Manuel säkerhetskopiering"
},
@@ -3800,6 +4073,9 @@
"servers.backups.item.restore": {
"defaultMessage": "Återställ"
},
+ "servers.backups.select-backup-aria": {
+ "defaultMessage": "Välj säkerhetskopia {name}"
+ },
"servers.backups.toolbar.create-backup": {
"defaultMessage": "Skapa säkerhetskopia"
},
@@ -3872,12 +4148,18 @@
"servers.installing-banner.error.internal-platform": {
"defaultMessage": "Ett internt fel inträffade när plattformen installerades. Vänligen försök igen."
},
+ "servers.installing-banner.error.invalid-loader-version": {
+ "defaultMessage": "Den angivna loader eller Minecraft-versionen kunde inte installeras. Den kan vara ogiltig eller stöds inte."
+ },
"servers.installing-banner.error.modpack-install-failed": {
"defaultMessage": "Modpaketet kunde inte installeras. Det kanske är korrumperad eller inkompatibel."
},
"servers.installing-banner.error.unknown": {
"defaultMessage": "Ett oväntat fel inträffade under installeringen."
},
+ "servers.installing-banner.error.unsupported-loader-version": {
+ "defaultMessage": "Denna version av Minecraft eller loader stöds ännu inte av Modrinth Hosting."
+ },
"servers.installing-banner.phase.installing-addons": {
"defaultMessage": "Installerar tillägg..."
},
@@ -3906,7 +4188,7 @@
"defaultMessage": "Ny server"
},
"servers.list-empty.no-servers-description": {
- "defaultMessage": "Installera moddar, bjud in vänner och spela tillsammans, allt från Modrinth-appen."
+ "defaultMessage": "Installera moddar, bjud in vänner och spela tillsammans, allt från Modrinth App."
},
"servers.list-empty.no-servers-title": {
"defaultMessage": "Inga servrar än"
@@ -3983,6 +4265,9 @@
"servers.manage.error.details": {
"defaultMessage": "Feldetaljer:"
},
+ "servers.manage.error.title": {
+ "defaultMessage": "Servrar kunde inte laddas in"
+ },
"servers.manage.handle-error.title": {
"defaultMessage": "Ett fel inträffade"
},
@@ -4001,6 +4286,9 @@
"servers.manage.purchase-unavailable.text": {
"defaultMessage": "Betalningsinformation laddar fortfarande. Öppnar kassan så snart som möjligt."
},
+ "servers.manage.purchase-unavailable.title": {
+ "defaultMessage": "Köp otillgängligt"
+ },
"servers.manage.reload-button": {
"defaultMessage": "Ladda om"
},
@@ -4034,9 +4322,15 @@
"servers.manage.your-servers-title": {
"defaultMessage": "Dina servrar"
},
+ "servers.medal-listing.countdown.remaining": {
+ "defaultMessage": "{days} {days, plural, one {dag} other {dagar}} {hours} {hours, plural, one {timme} other {timmar}} {minutes} {minutes, plural, one {minut} other {minuter}} {seconds} {seconds, plural, one {sekund} other {sekunder}} återstår..."
+ },
"servers.medal-listing.new-server-label": {
"defaultMessage": "Ny server"
},
+ "servers.medal-listing.notice.upgrading": {
+ "defaultMessage": "Din servers hårdvara uppgraderas just nu och kommer snart vara online igen."
+ },
"servers.medal-listing.owner-avatar-alt": {
"defaultMessage": "{username}s avatar"
},
@@ -4232,6 +4526,12 @@
"servers.setup.onboarding.modpack-upload-failed.title": {
"defaultMessage": "Modpaket-uppladdning misslyckades"
},
+ "servers.setup.onboarding.setup-server.button": {
+ "defaultMessage": "Ställ in server"
+ },
+ "servers.setup.onboarding.step.choose.description": {
+ "defaultMessage": "Välj ditt favorit modpaket från Modrinth, eller välj en loader och lägg till de moddar du vill."
+ },
"servers.setup.onboarding.step.choose.title": {
"defaultMessage": "Välj vad du vill spela"
},
@@ -4241,6 +4541,9 @@
"servers.setup.onboarding.step.invite-friends.title": {
"defaultMessage": "Bjud in dina vänner"
},
+ "servers.setup.onboarding.steps.heading": {
+ "defaultMessage": "Ställ in din server (≈ 2 min)"
+ },
"servers.setup.onboarding.uploading.progress": {
"defaultMessage": "Laddar upp ({percent, number}%)"
},
@@ -4275,7 +4578,7 @@
"defaultMessage": "Dina applikationer"
},
"settings.authorized-apps.title": {
- "defaultMessage": "Auktoriserade appar"
+ "defaultMessage": "Behöriga appar"
},
"settings.billing.title": {
"defaultMessage": "Prenumerationer"
@@ -4293,10 +4596,10 @@
"defaultMessage": "OLED"
},
"settings.display.theme.preferred-dark-theme": {
- "defaultMessage": "Önskat mörkt tema"
+ "defaultMessage": "Föredraget mörkt tema"
},
"settings.display.theme.preferred-light-theme": {
- "defaultMessage": "Önskat ljust tema"
+ "defaultMessage": "Föredraget ljust tema"
},
"settings.display.theme.retro": {
"defaultMessage": "Retro"
@@ -4340,9 +4643,177 @@
"settings.pats.title": {
"defaultMessage": "Personliga åtkomstnycklar"
},
+ "settings.profile.bio.title": {
+ "defaultMessage": "Biografi"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Profil"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Profilbild"
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Misslyckades att uppdatera profil"
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Logga in på ett Modrinth-konto för att anpassa din offentliga profil."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Modrinth-konto behövs"
+ },
"settings.sessions.title": {
"defaultMessage": "Sessioner"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Åtgärder"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Användare"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Det här är användare du har blockat på Modrinth. De kan inte:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Du har inte blockerat någon."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Blockerade användare kunde inte laddas in."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Laddar in blockerade användare…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Skicka vänförfrågan till dig"
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Bjuda in dig till en delad instans"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Blockerade användare"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Avblockera"
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Avblockera {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "{username}s avatar"
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Vänförfrågningar"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Kommer snart!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Alla"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Vänner"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Vänners vänner"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Ingen"
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Inbjudningar"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Modrinth-konto krävs"
+ },
+ "sharing.invite-players-modal.add": {
+ "defaultMessage": "Lägg till"
+ },
+ "sharing.invite-players-modal.added": {
+ "defaultMessage": "Tillagd"
+ },
+ "sharing.invite-players-modal.already-invited": {
+ "defaultMessage": "Den här användaren har redan bjudits in."
+ },
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Tillämpa"
+ },
+ "sharing.invite-players-modal.avatar-alt": {
+ "defaultMessage": "{username}s avatar"
+ },
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Anpassat..."
+ },
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Anpassat: {date}"
+ },
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "Om 1 dag"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "Om 1 timme"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "Om 7 dagar"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "Om 6 timmar"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "Om 3 dagar"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "Om 12 timmar"
+ },
+ "sharing.invite-players-modal.expiry-label": {
+ "defaultMessage": "Utgångsdatum"
+ },
+ "sharing.invite-players-modal.friends-heading": {
+ "defaultMessage": "Dina vänner – {count}"
+ },
+ "sharing.invite-players-modal.invite": {
+ "defaultMessage": "Bjud in"
+ },
+ "sharing.invite-players-modal.invite-expiry-description": {
+ "defaultMessage": "Din inbjudningslänk går ut om {duration}."
+ },
+ "sharing.invite-players-modal.invite-link-heading": {
+ "defaultMessage": "Eller använd en inbjudningslänk"
+ },
+ "sharing.invite-players-modal.link-copied-text": {
+ "defaultMessage": "Inbjudningslänken har kopierats till urklippet."
+ },
+ "sharing.invite-players-modal.link-copied-title": {
+ "defaultMessage": "Länk kopierad"
+ },
+ "sharing.invite-players-modal.link-copy-failed-title": {
+ "defaultMessage": "Kunde inte kopiera länk"
+ },
+ "sharing.invite-players-modal.max-uses-label": {
+ "defaultMessage": "Högst antal användningar"
+ },
+ "sharing.invite-players-modal.no-friends": {
+ "defaultMessage": "Inga vänner hittades."
+ },
+ "sharing.invite-players-modal.no-search-results": {
+ "defaultMessage": "Inga matchande användare hittades."
+ },
+ "sharing.invite-players-modal.requested": {
+ "defaultMessage": "Förfrågan skickad"
+ },
+ "sharing.invite-players-modal.requested-tooltip": {
+ "defaultMessage": "{username} behöver acceptera din vänförfrågan först"
+ },
+ "sharing.invite-players-modal.save-button": {
+ "defaultMessage": "Spara"
+ },
+ "sharing.invite-players-modal.search-placeholder": {
+ "defaultMessage": "Ange Modrinth-användarnamn"
+ },
+ "sharing.invite-players-modal.searching": {
+ "defaultMessage": "Söker..."
+ },
+ "sharing.invite-players-modal.update-invite-link-failed-title": {
+ "defaultMessage": "Kunde inte uppdatera inbjudningslänken"
+ },
"tag.category.128x": {
"defaultMessage": "128x"
},
@@ -4844,6 +5315,9 @@
"ui.confirm-leave-modal.title": {
"defaultMessage": "Lämna sidan?"
},
+ "ui.stacked-admonitions.dismiss-all": {
+ "defaultMessage": "Avvisa alla"
+ },
"unknown-file-warning-modal.dont-install": {
"defaultMessage": "Installera inte"
},
@@ -4889,12 +5363,18 @@
"user.profile.badge.pride.about.1": {
"defaultMessage": "Denna användare har deltagit i åtminstone ett av Modrinths Pride-insamlingar för LGBTQ+ gemenskapen."
},
+ "user.profile.badge.staff.name": {
+ "defaultMessage": "Modrinth-team"
+ },
"version.content.name": {
"defaultMessage": "Namn"
},
"version.content.version": {
"defaultMessage": "Version"
},
+ "version.file-type.primary": {
+ "defaultMessage": "Primär"
+ },
"version.file-type.signature": {
"defaultMessage": "Signaturfil"
},
@@ -4925,6 +5405,9 @@
"version.section.included-content": {
"defaultMessage": "Inkluderat innehåll"
},
+ "version.section.no-modpack-mod-loader": {
+ "defaultMessage": "Ingen modloader"
+ },
"version.supplementary-resources.file": {
"defaultMessage": "Fil"
},
diff --git a/packages/ui/src/locales/th-TH/index.json b/packages/ui/src/locales/th-TH/index.json
index 4908b72a79..8be06fa3ac 100644
--- a/packages/ui/src/locales/th-TH/index.json
+++ b/packages/ui/src/locales/th-TH/index.json
@@ -317,15 +317,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "เลือกไอคอน"
},
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "ไม่พบเนื้อหา"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "เนื้อหาม็อดแพ็ค"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "กำลังโหลดเนื้อหา"
- },
"label.available": {
"defaultMessage": "ว่างอยู่ {amount}"
},
diff --git a/packages/ui/src/locales/tr-TR/index.json b/packages/ui/src/locales/tr-TR/index.json
index 5d52c8ea46..41a6191f92 100644
--- a/packages/ui/src/locales/tr-TR/index.json
+++ b/packages/ui/src/locales/tr-TR/index.json
@@ -467,9 +467,21 @@
"content.diff-modal.external-diff-type.updated": {
"defaultMessage": "Güncellendi"
},
+ "content.diff-modal.file-count": {
+ "defaultMessage": "{count, plural,one {# dosya}other {# dosya}}"
+ },
+ "content.diff-modal.game-version-updated": {
+ "defaultMessage": "Oyun sürümü"
+ },
"content.diff-modal.install-anyway": {
"defaultMessage": "Yine de indir"
},
+ "content.diff-modal.loader-updated": {
+ "defaultMessage": "Yükleyici"
+ },
+ "content.diff-modal.modpack-linked": {
+ "defaultMessage": "Bağlantılı mod paketi"
+ },
"content.diff-modal.removed-count": {
"defaultMessage": "{count} kaldırıldı"
},
@@ -584,18 +596,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Proje isimleri"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Alfabetik"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Önce en yeni"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Önce en eski"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sıralama şekli {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Tümünü güncelle"
},
@@ -1160,6 +1160,15 @@
"external-files.permissions-card.reason.special-permission.description": {
"defaultMessage": "Bu çalışmayı mod paketinizde yeniden dağıtmak için özel izin alınmıştır."
},
+ "external-files.permissions-card.remove-group": {
+ "defaultMessage": "Grubu sil"
+ },
+ "external-files.permissions-card.remove-group-confirmation.title": {
+ "defaultMessage": "{title} silinsin mi?"
+ },
+ "external-files.permissions-card.remove-group-error.title": {
+ "defaultMessage": "Grup silinemedi"
+ },
"external-files.permissions-card.split-file": {
"defaultMessage": "Gruptan kaldır"
},
@@ -1253,9 +1262,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Dosya kaydedildi"
},
- "files.editor.find-close": {
- "defaultMessage": "Kapat"
- },
"files.editor.find-in-file": {
"defaultMessage": "Bul"
},
@@ -2033,24 +2039,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Simge seç"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Bu mod paketi başka hiç bir ekstra işerik içermez."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "İçerik bulunamadı"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Mod paketi içeriği"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "İçerik yükleniyor..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Aramanızla eşleşen proje yok."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Search {count, number} {count, plural, one {project} other {projects}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Şu anki"
},
@@ -2792,6 +2780,42 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Bir Modrinth kullanıcısı."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Bu kullanıcıyı engellemek istediğinize emin misiniz?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Kullanıcıyı engellerken bir sorun oluştu. Lütfen tekrar deneyin."
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} engellendi."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Kullanıcı engellendi"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "{username}'i engelle"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Kullanıcı analizlerini göster"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Engelle"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Kullanıcı detaylarını göster"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Engellemeyi kaldır"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural,one{# proje} other{# proje}}"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Kullanıcı profili yüklenemedi."
+ },
"profile.label.badges": {
"defaultMessage": "Rozetler"
},
@@ -3593,15 +3617,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Gelişmiş"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Veri paketlerini hariç tut"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Modları hariç tut"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Eklentileri hariç tut"
- },
"search.filter_type.environment": {
"defaultMessage": "Ortam"
},
diff --git a/packages/ui/src/locales/uk-UA/index.json b/packages/ui/src/locales/uk-UA/index.json
index 67d677efb3..bbab12eba5 100644
--- a/packages/ui/src/locales/uk-UA/index.json
+++ b/packages/ui/src/locales/uk-UA/index.json
@@ -374,6 +374,9 @@
"content.confirm-deletion.header": {
"defaultMessage": "Видалити {itemType}"
},
+ "content.confirm-disable.header": {
+ "defaultMessage": "Вимкнути {itemType}"
+ },
"content.confirm-modpack-update.admonition-body": {
"defaultMessage": "{action, select, downgrade {Пониження} other {Підвищення}} може спричинити проблеми сумісности. Моди чи вміст, який ви додали в збірку, буде збережено, але може бути несумісним із новою версією."
},
@@ -443,12 +446,18 @@
"content.diff-modal.added-count": {
"defaultMessage": "Додано {count}"
},
+ "content.diff-modal.config-files-updated": {
+ "defaultMessage": "Змінені конфігураційні файли"
+ },
"content.diff-modal.diff-type.added": {
"defaultMessage": "Додано (залежності)"
},
"content.diff-modal.diff-type.removed": {
"defaultMessage": "Вимкнено"
},
+ "content.diff-modal.diff-type.removed-disabled": {
+ "defaultMessage": "Видалено (вимкнено)"
+ },
"content.diff-modal.diff-type.updated": {
"defaultMessage": "Оновлено"
},
@@ -464,12 +473,36 @@
"content.diff-modal.external-diff-type.updated": {
"defaultMessage": "Оновлено"
},
+ "content.diff-modal.file-count": {
+ "defaultMessage": "{count, plural, one {# файл} few {# файли} many {# файлів} other {# файлу}}"
+ },
+ "content.diff-modal.game-version-updated": {
+ "defaultMessage": "Версія гри"
+ },
"content.diff-modal.install-anyway": {
"defaultMessage": "Усе одно встановити"
},
+ "content.diff-modal.loader-updated": {
+ "defaultMessage": "Завантажувач"
+ },
+ "content.diff-modal.modpack-linked": {
+ "defaultMessage": "Прив'язана збірка"
+ },
+ "content.diff-modal.modpack-unlinked": {
+ "defaultMessage": "Відв'язана збірка"
+ },
+ "content.diff-modal.modpack-updated": {
+ "defaultMessage": "Оновлена збірка"
+ },
+ "content.diff-modal.no-content-changes": {
+ "defaultMessage": "Без змін у вмісті"
+ },
"content.diff-modal.removed-count": {
"defaultMessage": "Видалено {count}"
},
+ "content.diff-modal.removed-disabled-count": {
+ "defaultMessage": "Видалено (вимкнено): {count}"
+ },
"content.diff-modal.reviewed-files": {
"defaultMessage": "Файл перевірятиметься, лише якщо його опубліковано на Modrinth, незалежно від його формату (включно з .mrpack)."
},
@@ -525,7 +558,7 @@
"defaultMessage": "Утримуйте клавішу Shift під час натискання, щоб пропустити підтвердження."
},
"content.inline-backup.warning-body": {
- "defaultMessage": "Ми рекомендуємо створити резервну копію перш ніж продовжувати, щоб ви могли відновити свій {type}, якщо щось піде не так."
+ "defaultMessage": "Радимо створити резервну копію перед тим, як продовжити, щоб ви могли відновити ваш {type}, якщо щось зламається."
},
"content.inline-backup.world-label": {
"defaultMessage": "світ"
@@ -575,18 +608,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Назви проєктів"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "За абеткою"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Спочатку новіші"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Спочатку старіші"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Сортування: {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Оновити все"
},
@@ -810,7 +831,7 @@
"defaultMessage": "Переглянути збірки"
},
"creation-flow.modal.modpack.action.import": {
- "defaultMessage": "Імпортувати збірку"
+ "defaultMessage": "Перенести збірку"
},
"creation-flow.modal.modpack.known-modpack.prompt": {
"defaultMessage": "Уже знаєте яку збірку хочете встановити?"
@@ -831,13 +852,13 @@
"defaultMessage": "Власне налаштування"
},
"creation-flow.modal.setup-type.option.import-instance.description": {
- "defaultMessage": "Імпортуйте збірку з Prism, CurseForge або подібних програм."
+ "defaultMessage": "Перенесіть збірку з Prism, CurseForge абощо."
},
"creation-flow.modal.setup-type.option.import-instance.title": {
"defaultMessage": "Імпорт збірки"
},
"creation-flow.modal.setup-type.option.modpack-base.description": {
- "defaultMessage": "Перегляньте збірки на Modrinth або імпортуйте їх з файлу."
+ "defaultMessage": "Перегляньте збірки на Modrinth або перенесіть їх із файлу."
},
"creation-flow.modal.setup-type.option.modpack-base.title": {
"defaultMessage": "Установити збірку"
@@ -1115,6 +1136,21 @@
"external-files.permissions-card.reason.special-permission.description": {
"defaultMessage": "Ви отримали особливі дозволи для поширення цієї роботи у вашій збірці."
},
+ "external-files.permissions-card.remove-group": {
+ "defaultMessage": "Видалити групу"
+ },
+ "external-files.permissions-card.remove-group-confirmation.description": {
+ "defaultMessage": "Це назавжди видалить цю групу атрибуції та всі файли в ній. Цю дію неможливо скасувати."
+ },
+ "external-files.permissions-card.remove-group-confirmation.title": {
+ "defaultMessage": "Видалити {title}?"
+ },
+ "external-files.permissions-card.remove-group-error.title": {
+ "defaultMessage": "Групу не видалено"
+ },
+ "external-files.permissions-card.remove-group-shift-hint": {
+ "defaultMessage": "Утримуйте Shift під час кліку, щоб пропустити підтвердження."
+ },
"external-files.permissions-card.split-file": {
"defaultMessage": "Видалити з групи"
},
@@ -1208,9 +1244,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Файл збережено"
},
- "files.editor.find-close": {
- "defaultMessage": "Закрити"
- },
"files.editor.find-in-file": {
"defaultMessage": "Знайти"
},
@@ -1800,10 +1833,10 @@
"defaultMessage": "Редагувати інсталяцію"
},
"installation-settings.edit.warning-instance": {
- "defaultMessage": "Ми не рекомендуємо змінювати налаштування інсталяції після встановлення вмісту. Якщо ви все ж хочете їх змінити, будьте обережні, оскільки це може спричинити проблеми."
+ "defaultMessage": "Не радимо відміняти налаштування інсталяції після встановлення вмісту. Коли все ж бажаєте їх змінити, то будьте обережні, адже це може завдати вам клопоту."
},
"installation-settings.edit.warning-server": {
- "defaultMessage": "Ми не рекомендуємо змінювати налаштування інсталяції після встановлення вмісту. Якщо ви все ж хочете їх змінити, скиньте ваш сервер."
+ "defaultMessage": "Не радимо змінювати налаштування інсталяції після встановлення вмісту. Коли все ж хочете їх змінити, то скиньте свій сервер."
},
"installation-settings.incompatible-content.auto-fix-button": {
"defaultMessage": "Виправити автоматично"
@@ -1988,24 +2021,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Вибрати значок"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Збірка не включає додатковий уміст."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Умісту не знайдено"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Уміст збірки"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Завантаження вмісту…"
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "За вашим запитом не знайдено жодного проєкту."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Пошук {count, number} {count, plural, one {проєкту} other {проєктів}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Поточна"
},
@@ -2138,6 +2153,9 @@
"label.details": {
"defaultMessage": "Деталі"
},
+ "label.discover-content": {
+ "defaultMessage": "Огляд вмісту"
+ },
"label.done": {
"defaultMessage": "Готово"
},
@@ -2216,6 +2234,9 @@
"label.password": {
"defaultMessage": "Пароль"
},
+ "label.permissions": {
+ "defaultMessage": "Дозволи"
+ },
"label.plan-custom": {
"defaultMessage": "Власний"
},
@@ -2747,9 +2768,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "Творець Modrinth."
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "Користувач Modrinth."
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} Не зможе надсилати вам запити в друзі, запрошувати до спільних збірок або запрошувати на сервери Modrinth Hosting."
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "Дійсно заблокувати цього користувача?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "Виникла помилка під час блокування користувача. Спробуйте знову."
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "Не вдалося заблокувати користувача"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} заблоковано."
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "Користувача заблоковано"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "Заблокувати {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "Переглянути аналітику користувача"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "Керувати виплатами користувача"
+ },
+ "profile.button.block": {
+ "defaultMessage": "Заблокувати"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "Створити добірку"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "Створити проєкт"
+ },
+ "profile.button.info": {
+ "defaultMessage": "Деталі про користувача"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "Керувати проєктами"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "Видалити як партнера"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "Призначити партнером"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "Розблокувати"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, one {# проєкт} few {# проєкти} many {# проєктів} other {# проєкту}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "Дозвольте спливні вікна для Modrinth, потім спробуйте знову."
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "Не вдалося отримати профіль GitHub. Спробуйте знову."
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "Не вдалося відкрити профіль GitHub"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "Сервіси автентифікації"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "Підтверджена електронна пошта"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "Має пароль"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "Має TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "Завантаження…"
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "Способи оплати"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "Переглянути профіль"
+ },
+ "profile.details.title": {
+ "defaultMessage": "Деталі користувача"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "Пошту не підтверджено"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "Пошту підтверджено"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "Не вдалося завантажити профіль користувача."
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "Користувача не знайдено"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "Партнер"
+ },
"profile.label.badges": {
"defaultMessage": "Значки"
},
+ "profile.label.collection": {
+ "defaultMessage": "Добірка"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, one {завантаження} few {завантаження} many {завантажень} other {завантаження}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "Приєднався"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "Цей користувач не має добірок!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "Ви поки не маєте добірок."
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "Цей користувач не має проєктів!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "Ви поки не маєте проєктів."
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "Організації"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, one {проєкт} few {проєкти} many {проєктів} other {проєктів}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Офіційний обліковий запис Modrinth"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Офіційний обліковий запис Modrinth. Зв'язатися з підтримкою можна за або через електронну пошту за "
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "Виникла помилка під час розблокування користувача. Спробуйте знову."
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "Не вдалося розблокувати користувача"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} розблоковано."
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "Користувача розблоковано"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "Опубліковано {date}"
},
@@ -2765,12 +2939,21 @@
"project-card.environment.client-or-server": {
"defaultMessage": "Клієнт чи сервер"
},
+ "project-card.environment.dedicated-server": {
+ "defaultMessage": "Виділений сервер"
+ },
"project-card.environment.server": {
"defaultMessage": "Сервер"
},
+ "project-card.environment.singleplayer": {
+ "defaultMessage": "Одиночна гра"
+ },
"project-type.all": {
"defaultMessage": "Усі"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "Добірки"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, one {Пакет даних} few {Пакети даних} many {Пакетів даних} other {Пакетів даних}}"
},
@@ -3563,15 +3746,6 @@
"search.filter_type.advanced": {
"defaultMessage": "Більше"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "Виключити пакети даних"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "Виключити моди"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "Виключити плаґіни"
- },
"search.filter_type.environment": {
"defaultMessage": "Середовище"
},
@@ -4997,9 +5171,216 @@
"settings.pats.title": {
"defaultMessage": "Особистий токен доступу"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "Короткий опис, щоб розповісти іншим трохи про себе."
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "Про себе"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "Профіль"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "Зображення профілю"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "Інформація з вашого профілю є загальнодоступною на Modrinth та через Modrinth API ."
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "Не вдалося оновити профіль"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "Виникла помилка під час оновлення вашого профілю Спробуйте знову."
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "Увійдіть за допомогою облікового запису Modrinth, щоб налаштувати свій публічний профіль."
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "Потрібен обліковий запис Modrinth"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "Унікальне ім'я для ідентифікації вашого профілю."
+ },
"settings.sessions.title": {
"defaultMessage": "Сеанси"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "Дії"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "Користувач"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "Це користувачі, яких ви заблокували на Modrinth. Вони не можуть:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "Ви нікого не заблокували."
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "Не вдалося завантажити заблокованих користувачів."
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "Завантаження заблокованих користувачів…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "Надсилати вам запити в друзі"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "Запрошувати вас керувати сервером Modrinth Hosting."
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "Запрошувати вас до спільних збірок"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "Заблоковані користувачі"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "Розблокувати"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "Не вдалося розблокувати користувача"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "Сталася помилка під час розблокування цього користувача. Будь ласка, спробуйте ще раз."
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "Розблокувати {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "Аватар користувача {username}"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "Керуйте тим, хто може надсилати вам запити в друзі на Modrinth."
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "Запити в друзі"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "Незабаром!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "Усі"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "Друзі"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "Друзі друзів"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "Ніхто"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "Керуйте тим, хто може надсилати вам запрошення до спільних збірок та панелей Modrinth Hosting."
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "Запрошення"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "З обліковим записом Modrinth ви можете налаштувати, хто може взаємодіяти з вами, або керувати заблокованими користувачами"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "Потрібен обліковий запис Modrinth"
+ },
+ "settings.social.title": {
+ "defaultMessage": "Соціальні мережі"
+ },
+ "sharing.invite-players-modal.add": {
+ "defaultMessage": "Додати"
+ },
+ "sharing.invite-players-modal.added": {
+ "defaultMessage": "Додано"
+ },
+ "sharing.invite-players-modal.already-invited": {
+ "defaultMessage": "Цього користувача вже запрошено."
+ },
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "Застосувати"
+ },
+ "sharing.invite-players-modal.avatar-alt": {
+ "defaultMessage": "Аватар користувача {username}"
+ },
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "Власна…"
+ },
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "Власна: {date}"
+ },
+ "sharing.invite-players-modal.edit-invite-link": {
+ "defaultMessage": "Редагувати посилання-запрошення."
+ },
+ "sharing.invite-players-modal.edit-invite-link-title": {
+ "defaultMessage": "Редагувати посилання-запрошення"
+ },
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "Через 1 день"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "Через 1 годину"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "Через 7 днів"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "Через 6 годин"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "Через 3 дні"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "Через 12 годин"
+ },
+ "sharing.invite-players-modal.expiry-label": {
+ "defaultMessage": "Термін дії"
+ },
+ "sharing.invite-players-modal.friends-heading": {
+ "defaultMessage": "Ваші друзі — {count}"
+ },
+ "sharing.invite-players-modal.invite": {
+ "defaultMessage": "Запросити"
+ },
+ "sharing.invite-players-modal.invite-expiry-description": {
+ "defaultMessage": "Термін дії вашого посилання-запрошення закінчується через {duration}."
+ },
+ "sharing.invite-players-modal.invite-link-heading": {
+ "defaultMessage": "Або використайте посилання-запрошення"
+ },
+ "sharing.invite-players-modal.link-copied-text": {
+ "defaultMessage": "Посилання-запрошення скопійовано до буфера обміну."
+ },
+ "sharing.invite-players-modal.link-copied-title": {
+ "defaultMessage": "Посилання скопійовано"
+ },
+ "sharing.invite-players-modal.link-copy-failed-title": {
+ "defaultMessage": "Не вдалося скопіювати посилання"
+ },
+ "sharing.invite-players-modal.max-uses-label": {
+ "defaultMessage": "Максимальна кількість використань"
+ },
+ "sharing.invite-players-modal.no-friends": {
+ "defaultMessage": "Не знайдено друзів."
+ },
+ "sharing.invite-players-modal.no-search-results": {
+ "defaultMessage": "Відповідних користувачів не знайдено."
+ },
+ "sharing.invite-players-modal.requested": {
+ "defaultMessage": "Запит відправлено"
+ },
+ "sharing.invite-players-modal.requested-tooltip": {
+ "defaultMessage": "{username} спочатку має прийняти ваш запит у друзі"
+ },
+ "sharing.invite-players-modal.save-button": {
+ "defaultMessage": "Зберегти"
+ },
+ "sharing.invite-players-modal.search-placeholder": {
+ "defaultMessage": "Уведіть ім’я користувача Modrinth"
+ },
+ "sharing.invite-players-modal.searching": {
+ "defaultMessage": "Шукаємо…"
+ },
+ "sharing.invite-players-modal.update-invite-link-failed-title": {
+ "defaultMessage": "Не вдалося оновити посилання"
+ },
"tag.category.128x": {
"defaultMessage": "×128"
},
@@ -5166,7 +5547,7 @@
"defaultMessage": "Низьке"
},
"tag.category.magic": {
- "defaultMessage": "Магія"
+ "defaultMessage": "Чаклунство"
},
"tag.category.management": {
"defaultMessage": "Керування"
@@ -5190,7 +5571,7 @@
"defaultMessage": "ММО"
},
"tag.category.mobs": {
- "defaultMessage": "Моби"
+ "defaultMessage": "Сутності"
},
"tag.category.modded": {
"defaultMessage": "Для модів"
@@ -5550,13 +5931,13 @@
"defaultMessage": "Шкідливе програмне забезпечення часто поширюють через моди, які публікуються на таких платформах, як Discord."
},
"unknown-file-warning-modal.mod-warning-body": {
- "defaultMessage": " не є опублікований на Modrinth. Ми наполегливо рекомендуємо встановлювати лише ті файли, яким довіряєте."
+ "defaultMessage": " не викладено на Modrinth. Наполегливо радимо встановлювати вміст лише з тих джерел, яким ви довіряєте."
},
"unknown-file-warning-modal.mod-warning-title": {
"defaultMessage": "Попередження про невідомий файл"
},
"unknown-file-warning-modal.modpack-warning-body": {
- "defaultMessage": " містить файли, які не є опубліковані на Modrinth. Ми наполегливо рекомендуємо встановлювати лише ті файли, яким довіряєте."
+ "defaultMessage": " містить файли, котрі не викладені на Modrinth. Наполегливо радимо встановлювати вміст лише з тих джерел, яким ви довіряєте."
},
"unknown-file-warning-modal.modpack-warning-title": {
"defaultMessage": "Попередження про невідомі файли"
diff --git a/packages/ui/src/locales/vi-VN/index.json b/packages/ui/src/locales/vi-VN/index.json
index 50d370d6d4..9e4f34f272 100644
--- a/packages/ui/src/locales/vi-VN/index.json
+++ b/packages/ui/src/locales/vi-VN/index.json
@@ -530,18 +530,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "Tên dự án"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "Thứ tự bảng chữ cái"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "Mới nhất"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "Cũ nhất"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "Sắp xếp theo {mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "Cập nhật tất cả"
},
@@ -935,9 +923,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "Tệp đã được lưu"
},
- "files.editor.find-close": {
- "defaultMessage": "Đóng"
- },
"files.editor.find-in-file": {
"defaultMessage": "Tìm"
},
@@ -1712,24 +1697,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "Chọn biểu tượng"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "Gói modpack này không bao gồm các nội dung bổ sung nào."
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "Không có nội dung nào được tìm thấy"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "Nội dung modpack"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "Đang tải nội dung..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "Không có dự án nào phù hợp với kết quả tìm kiếm."
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "Tìm {count, number} {count, plural, other {dự án}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "Hiện tại"
},
diff --git a/packages/ui/src/locales/zh-CN/index.json b/packages/ui/src/locales/zh-CN/index.json
index e4f883d767..c173ccbcb1 100644
--- a/packages/ui/src/locales/zh-CN/index.json
+++ b/packages/ui/src/locales/zh-CN/index.json
@@ -617,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "项目名称"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "按字母顺序"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "按从新到旧顺序"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "按从旧到新顺序"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "按{mode}排序"
- },
"content.page-layout.update-all": {
"defaultMessage": "更新所有"
},
@@ -1301,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "文件已保存"
},
- "files.editor.find-close": {
- "defaultMessage": "关闭"
- },
"files.editor.find-in-file": {
"defaultMessage": "查找"
},
@@ -2081,33 +2066,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "选择图标"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "这个整合包不包含任何额外内容。"
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "未找到内容"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "外部来源"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "此文件未发布于 Modrinth 平台。"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "整合包内容"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "加载内容……"
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "没有符合搜索条件的项目。"
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "在 Slicer 中打开"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "搜索 {count, number} {count, plural, other {个项目}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "当前"
},
@@ -2240,6 +2198,9 @@
"label.details": {
"defaultMessage": "信息"
},
+ "label.discover-content": {
+ "defaultMessage": "发现内容"
+ },
"label.done": {
"defaultMessage": "完成"
},
@@ -2318,6 +2279,9 @@
"label.password": {
"defaultMessage": "密码"
},
+ "label.permissions": {
+ "defaultMessage": "权限"
+ },
"label.plan-custom": {
"defaultMessage": "自定义"
},
@@ -2849,9 +2813,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "一位 Modrinth 创作者。"
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "一位 Modrinth 用户。"
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} 将无法向你发送好友请求、将你邀请到共享实例或 Modrinth Hosting 服务器。"
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "你确定要屏蔽该用户吗?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "屏蔽该用户时发生了错误。请重试。"
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "屏蔽用户失败"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} 已被屏蔽。"
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "用户已屏蔽"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "屏蔽 {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "查看用户分析"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "管理用户财务"
+ },
+ "profile.button.block": {
+ "defaultMessage": "屏蔽"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "创建收藏夹"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "创建项目"
+ },
+ "profile.button.info": {
+ "defaultMessage": "查看用户详情"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "管理项目"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "解除作为联盟伙伴"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "设置为联盟伙伴"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "解除屏蔽"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, other {# 个项目}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "请在来自 Modrinth 的弹出窗口中选择允许,然后重试。"
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "无法获取 GitHub 个人资料。请重试。"
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "无法打开 GitHub 个人主页"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "身份验证提供器"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "电子邮箱已验证"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "是否有密码"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "是否有 TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "正在加载……"
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "支付方式"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "查看个人资料"
+ },
+ "profile.details.title": {
+ "defaultMessage": "用户详情"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "电子邮箱未验证"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "电子邮箱已验证"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "无法加载该用户的个人资料。"
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "未找到用户"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "联盟"
+ },
"profile.label.badges": {
"defaultMessage": "荣誉徽章"
},
+ "profile.label.collection": {
+ "defaultMessage": "收藏"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, other {次下载}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "加入于"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "该用户没有收藏夹!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "你还没有任何收藏夹。"
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "该用户没有项目!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "你还没有任何项目。"
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "组织"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, other {项目}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "官方 Modrinth 账户"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Modrinth 的官方用户账号。可通过 或电子邮件 获取支持"
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "解除屏蔽该用户时发生了错误。请重试。"
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "解除屏蔽用户失败"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} 已被解除屏蔽。"
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "用户已解除屏蔽"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "发布于 {date}"
},
@@ -2879,6 +2996,9 @@
"project-type.all": {
"defaultMessage": "全部"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "收藏夹"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, other {数据包}}"
},
@@ -3564,10 +3684,10 @@
"defaultMessage": "视图"
},
"project.stats.downloads-label": {
- "defaultMessage": "{count, plural, other {下载量}}"
+ "defaultMessage": "{count, plural, other {次下载}}"
},
"project.stats.followers-label": {
- "defaultMessage": "{count, plural, other {关注者}}"
+ "defaultMessage": "{count, plural, other {人关注}}"
},
"project.versions.channel.alpha.symbol": {
"defaultMessage": "A"
@@ -3671,15 +3791,6 @@
"search.filter_type.advanced": {
"defaultMessage": "高级"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "排除数据包"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "排除模组"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "排除插件"
- },
"search.filter_type.environment": {
"defaultMessage": "运行环境"
},
@@ -3969,7 +4080,7 @@
"defaultMessage": "角色:{role}"
},
"servers.access-page.role.editor": {
- "defaultMessage": "编辑"
+ "defaultMessage": "编辑者"
},
"servers.access-page.role.editor-description": {
"defaultMessage": "管理实例内容、文件、备份及其他设置。"
@@ -3984,13 +4095,13 @@
"defaultMessage": "受限"
},
"servers.access-page.role.viewer-description": {
- "defaultMessage": "可启动、停止并查看服务器状态,但无法进行更改。"
+ "defaultMessage": "可启动、停止和查看服务器,但无法进行更改。"
},
"servers.access-page.search-users-placeholder": {
"defaultMessage": "搜索 {count} {count, plural, one {用户} other {用户}}………"
},
"servers.access-role.editor": {
- "defaultMessage": "编辑"
+ "defaultMessage": "编辑者"
},
"servers.access-role.owner": {
"defaultMessage": "所有者"
@@ -4467,7 +4578,7 @@
"defaultMessage": "邀请"
},
"servers.grant-access-modal.permissions-help": {
- "defaultMessage": "在 这里查看各职务的完整清单。"
+ "defaultMessage": "在 这里查看各角色权限的完整列表。"
},
"servers.grant-access-modal.role.editor": {
"defaultMessage": "编辑"
@@ -4476,13 +4587,13 @@
"defaultMessage": "管理实例内容、文件、备份及其他设置。"
},
"servers.grant-access-modal.role.label": {
- "defaultMessage": "选择职能"
+ "defaultMessage": "选择角色"
},
"servers.grant-access-modal.role.viewer": {
- "defaultMessage": "受制"
+ "defaultMessage": "受限"
},
"servers.grant-access-modal.role.viewer-description": {
- "defaultMessage": "可以启动、停止与查看服务器,但无法进行任何更改。"
+ "defaultMessage": "可启动、停止和查看服务器,但无法进行更改。"
},
"servers.grant-access-modal.suggestion-avatar-alt": {
"defaultMessage": "{username}的头像"
@@ -5105,9 +5216,120 @@
"settings.pats.title": {
"defaultMessage": "个人访问令牌"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "用一段简短的描述,向大家展示你自己。"
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "简介"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "个人资料"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "头像"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "您的个人资料信息可以在 Modrinth 上公开查看 ,也可通过 Modrinth API 获取。"
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "更新档案失败"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "更新个人资料失败,请稍后重试。"
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "登录 Modrinth 账号以自定义您的公开资料。"
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "需要 Modrinth 账户"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "用于识别您个人资料的唯一名称。"
+ },
"settings.sessions.title": {
"defaultMessage": "会话"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "活动"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "用户"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "这些是你在 Modrinth 中屏蔽的用户。他们无法:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "你还没有屏蔽任何人。"
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "无法加载被屏蔽的用户。"
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "正在加载被屏蔽的用户…"
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "给你发送好友邀请"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "邀请你管理 Modrinth 托管服务器。"
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "邀请你加入共享实例"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "被屏蔽的用户"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "解除屏蔽"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "解除屏蔽用户失败"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "解除屏蔽该用户时发生了错误。请重试。"
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "解除屏蔽 {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "{username} 的头像"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "控制谁可以在 Modrinth 上向你发送好友申请。"
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "好友邀请"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "即将到来!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "所有人"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "好友"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "好友的好友"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "无"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "控制谁可以向您发送共享实例和 Modrinth 托管面板的邀请。"
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "邀请"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "使用 Modrinth 账号,你可以控制谁能与你互动,并管理黑名单用户"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "需要登录 Modrinth 账号"
+ },
+ "settings.social.title": {
+ "defaultMessage": "社交"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "添加"
},
@@ -5117,14 +5339,17 @@
"sharing.invite-players-modal.already-invited": {
"defaultMessage": "此用户已被邀请。"
},
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "应用"
+ },
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "{username} 的头像"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "取消"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "自定义……"
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "取消"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "自定义:{date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "编辑邀请链接。"
@@ -5132,6 +5357,24 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "编辑邀请链接"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "1 天"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "1 小时"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "7 天"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "6 小时"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "3 天"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "12 小时"
+ },
"sharing.invite-players-modal.expiry-label": {
"defaultMessage": "过期日期"
},
diff --git a/packages/ui/src/locales/zh-TW/index.json b/packages/ui/src/locales/zh-TW/index.json
index 191ff0108f..62ea4f4436 100644
--- a/packages/ui/src/locales/zh-TW/index.json
+++ b/packages/ui/src/locales/zh-TW/index.json
@@ -561,7 +561,7 @@
"defaultMessage": "按住 Shift 鍵並點選以跳過確認。"
},
"content.inline-backup.warning-body": {
- "defaultMessage": "我們建議您在繼續操作之前建立備份,以便在出現任何問題時可以還原您的{type}。"
+ "defaultMessage": "我們建議在繼續操作前先建立備份,以便在發生問題時還原你的{type}。"
},
"content.inline-backup.world-label": {
"defaultMessage": "世界"
@@ -617,18 +617,6 @@
"content.page-layout.share.project-names": {
"defaultMessage": "專案名稱"
},
- "content.page-layout.sort.alphabetical": {
- "defaultMessage": "字母順序"
- },
- "content.page-layout.sort.date-added-newest": {
- "defaultMessage": "最新在前"
- },
- "content.page-layout.sort.date-added-oldest": {
- "defaultMessage": "最舊在前"
- },
- "content.page-layout.sort.label": {
- "defaultMessage": "排序依據:{mode}"
- },
"content.page-layout.update-all": {
"defaultMessage": "更新全部"
},
@@ -1278,10 +1266,10 @@
"defaultMessage": "刪除檔案"
},
"files.delete-modal.warning.file": {
- "defaultMessage": "此檔案將永久刪除。此操作無法撤銷。"
+ "defaultMessage": "這個檔案將永久刪除,這項動作無法復原。"
},
"files.delete-modal.warning.folder": {
- "defaultMessage": "此資料夾及其所有內容將永久刪除。此操作無法撤銷。"
+ "defaultMessage": "這個資料夾及其所有內容將永久刪除,這項動作無法復原。"
},
"files.editor.failed-to-open-text": {
"defaultMessage": "無法載入檔案內容。"
@@ -1301,9 +1289,6 @@
"files.editor.file-saved-title": {
"defaultMessage": "已儲存檔案"
},
- "files.editor.find-close": {
- "defaultMessage": "關閉"
- },
"files.editor.find-in-file": {
"defaultMessage": "尋找"
},
@@ -2081,33 +2066,6 @@
"instances.content-install.select-icon": {
"defaultMessage": "選擇圖示"
},
- "instances.modpack-content-modal.empty-description": {
- "defaultMessage": "這個模組包不包含任何額外內容。"
- },
- "instances.modpack-content-modal.empty-title": {
- "defaultMessage": "找不到內容"
- },
- "instances.modpack-content-modal.external-content": {
- "defaultMessage": "外部"
- },
- "instances.modpack-content-modal.external-content-description": {
- "defaultMessage": "這個檔案未在 Modrinth 上發布。"
- },
- "instances.modpack-content-modal.header": {
- "defaultMessage": "模組包內容"
- },
- "instances.modpack-content-modal.loading": {
- "defaultMessage": "正在載入內容..."
- },
- "instances.modpack-content-modal.no-results": {
- "defaultMessage": "沒有專案符合你的搜尋字詞。"
- },
- "instances.modpack-content-modal.open-in-slicer": {
- "defaultMessage": "在 Slicer 中開啟"
- },
- "instances.modpack-content-modal.search-placeholder": {
- "defaultMessage": "搜尋 {count, number} {count, plural, other {個專案}}"
- },
"instances.updater-modal.badge.current": {
"defaultMessage": "目前"
},
@@ -2240,6 +2198,9 @@
"label.details": {
"defaultMessage": "詳細資訊"
},
+ "label.discover-content": {
+ "defaultMessage": "探索內容"
+ },
"label.done": {
"defaultMessage": "完成"
},
@@ -2318,6 +2279,9 @@
"label.password": {
"defaultMessage": "密碼"
},
+ "label.permissions": {
+ "defaultMessage": "權限"
+ },
"label.plan-custom": {
"defaultMessage": "自訂"
},
@@ -2766,7 +2730,7 @@
"defaultMessage": "由工作人員設為不公開"
},
"omorphia.component.copy.action.copy": {
- "defaultMessage": "將程式碼複製到剪貼簿"
+ "defaultMessage": "將代碼複製到剪貼簿"
},
"omorphia.component.environment-indicator.label.client": {
"defaultMessage": "用戶端"
@@ -2849,9 +2813,162 @@
"payment-method.visa": {
"defaultMessage": "Visa"
},
+ "profile.bio.fallback.creator": {
+ "defaultMessage": "一位 Modrinth 創作者。"
+ },
+ "profile.bio.fallback.user": {
+ "defaultMessage": "一位 Modrinth 使用者。"
+ },
+ "profile.block-user.admonition-body": {
+ "defaultMessage": "{username} 將無法向你傳送好友邀請、邀請你加入共用實例,或邀請你加入 Modrinth Hosting 伺服器。"
+ },
+ "profile.block-user.admonition-title": {
+ "defaultMessage": "確定要封鎖這位使用者嗎?"
+ },
+ "profile.block-user.error-description": {
+ "defaultMessage": "封鎖使用者時發生錯誤,請再試一次。"
+ },
+ "profile.block-user.error-title": {
+ "defaultMessage": "無法封鎖使用者"
+ },
+ "profile.block-user.success-description": {
+ "defaultMessage": "{username} 已被封鎖。"
+ },
+ "profile.block-user.success-title": {
+ "defaultMessage": "使用者已封鎖"
+ },
+ "profile.block-user.title": {
+ "defaultMessage": "封鎖 {username}"
+ },
+ "profile.button.analytics": {
+ "defaultMessage": "檢視使用者數據分析"
+ },
+ "profile.button.billing": {
+ "defaultMessage": "管理使用者帳務"
+ },
+ "profile.button.block": {
+ "defaultMessage": "封鎖"
+ },
+ "profile.button.create-collection": {
+ "defaultMessage": "建立收藏"
+ },
+ "profile.button.create-project": {
+ "defaultMessage": "建立專案"
+ },
+ "profile.button.info": {
+ "defaultMessage": "檢視使用者詳細資訊"
+ },
+ "profile.button.manage-projects": {
+ "defaultMessage": "管理專案"
+ },
+ "profile.button.remove-affiliate": {
+ "defaultMessage": "移除聯盟行銷夥伴資格"
+ },
+ "profile.button.set-affiliate": {
+ "defaultMessage": "設為聯盟行銷夥伴"
+ },
+ "profile.button.unblock": {
+ "defaultMessage": "解除封鎖"
+ },
+ "profile.collection.projects-count": {
+ "defaultMessage": "{count, plural, other {# 個專案}}"
+ },
+ "profile.details.error.github-popup-blocked": {
+ "defaultMessage": "請允許 Modrinth 的彈出式視窗,然後再試一次。"
+ },
+ "profile.details.error.github-profile-message": {
+ "defaultMessage": "無法擷取 GitHub 個人檔案,請再試一次。"
+ },
+ "profile.details.error.github-profile-title": {
+ "defaultMessage": "無法開啟 GitHub 個人檔案"
+ },
+ "profile.details.label.auth-providers": {
+ "defaultMessage": "驗證提供商"
+ },
+ "profile.details.label.email-verified": {
+ "defaultMessage": "電子郵件已驗證"
+ },
+ "profile.details.label.has-password": {
+ "defaultMessage": "是否有密碼"
+ },
+ "profile.details.label.has-totp": {
+ "defaultMessage": "是否有 TOTP"
+ },
+ "profile.details.label.loading-github-profile": {
+ "defaultMessage": "載入中..."
+ },
+ "profile.details.label.payment-methods": {
+ "defaultMessage": "付款方式"
+ },
+ "profile.details.label.view-github-profile": {
+ "defaultMessage": "查看個人檔案"
+ },
+ "profile.details.title": {
+ "defaultMessage": "使用者詳細資訊"
+ },
+ "profile.details.tooltip.email-not-verified": {
+ "defaultMessage": "電子郵件尚未驗證"
+ },
+ "profile.details.tooltip.email-verified": {
+ "defaultMessage": "電子郵件已驗證"
+ },
+ "profile.error.load-description": {
+ "defaultMessage": "無法載入使用者個人檔案。"
+ },
+ "profile.error.not-found": {
+ "defaultMessage": "找不到使用者"
+ },
+ "profile.label.affiliate": {
+ "defaultMessage": "聯盟行銷"
+ },
"profile.label.badges": {
"defaultMessage": "徽章"
},
+ "profile.label.collection": {
+ "defaultMessage": "收藏"
+ },
+ "profile.label.download-count": {
+ "defaultMessage": "{count, plural, other {次下載}}"
+ },
+ "profile.label.joined": {
+ "defaultMessage": "加入時間:"
+ },
+ "profile.label.no-collections": {
+ "defaultMessage": "這位使用者沒有任何收藏!"
+ },
+ "profile.label.no-collections-auth-description": {
+ "defaultMessage": "你還沒有任何收藏。"
+ },
+ "profile.label.no-projects": {
+ "defaultMessage": "這位使用者沒有任何專案!"
+ },
+ "profile.label.no-projects-auth-description": {
+ "defaultMessage": "你還沒有任何專案。"
+ },
+ "profile.label.organizations": {
+ "defaultMessage": "組織"
+ },
+ "profile.label.project-count": {
+ "defaultMessage": "{count, plural, other {個專案}}"
+ },
+ "profile.official-account": {
+ "defaultMessage": "Modrinth 官方帳號"
+ },
+ "profile.official-account.bio": {
+ "defaultMessage": "Modrinth 的官方使用者帳號。請至 取得支援,或透過電子郵件 聯絡客服團隊"
+ },
+ "profile.unblock-user.error-description": {
+ "defaultMessage": "解除封鎖使用者時發生錯誤,請再試一次。"
+ },
+ "profile.unblock-user.error-title": {
+ "defaultMessage": "無法解除封鎖使用者"
+ },
+ "profile.unblock-user.success-description": {
+ "defaultMessage": "{username} 已解除封鎖。"
+ },
+ "profile.unblock-user.success-title": {
+ "defaultMessage": "使用者已解除封鎖"
+ },
"project-card.date.published.tooltip": {
"defaultMessage": "發布時間:{date}"
},
@@ -2879,6 +2996,9 @@
"project-type.all": {
"defaultMessage": "全部"
},
+ "project-type.collection.plural": {
+ "defaultMessage": "收藏"
+ },
"project-type.datapack.capital": {
"defaultMessage": "{count, plural, other {資料包}}"
},
@@ -3540,7 +3660,7 @@
"defaultMessage": "成員"
},
"project.settings.notice.no-permission.description": {
- "defaultMessage": "你沒有編輯這個設定的權限。"
+ "defaultMessage": "你沒有編輯這項設定的權限。"
},
"project.settings.notice.no-permission.title": {
"defaultMessage": "沒有權限"
@@ -3561,7 +3681,7 @@
"defaultMessage": "版本"
},
"project.settings.view.title": {
- "defaultMessage": "檢視"
+ "defaultMessage": "檢視方式"
},
"project.stats.downloads-label": {
"defaultMessage": "{count, plural, other {次下載}}"
@@ -3671,15 +3791,6 @@
"search.filter_type.advanced": {
"defaultMessage": "進階篩選"
},
- "search.filter_type.advanced.exclude_datapack": {
- "defaultMessage": "排除資料包"
- },
- "search.filter_type.advanced.exclude_mod": {
- "defaultMessage": "排除模組"
- },
- "search.filter_type.advanced.exclude_plugin": {
- "defaultMessage": "排除插件"
- },
"search.filter_type.environment": {
"defaultMessage": "環境"
},
@@ -4011,7 +4122,7 @@
"defaultMessage": "{seconds} 秒後可重新傳送"
},
"servers.access-table.column.actions": {
- "defaultMessage": "操作"
+ "defaultMessage": "動作"
},
"servers.access-table.column.joined": {
"defaultMessage": "加入時間"
@@ -5105,9 +5216,120 @@
"settings.pats.title": {
"defaultMessage": "個人存取權杖"
},
+ "settings.profile.bio.description": {
+ "defaultMessage": "簡單介紹一下你自己。"
+ },
+ "settings.profile.bio.title": {
+ "defaultMessage": "關於我"
+ },
+ "settings.profile.navigation-title": {
+ "defaultMessage": "個人檔案"
+ },
+ "settings.profile.profile-picture.title": {
+ "defaultMessage": "個人檔案相片"
+ },
+ "settings.profile.public-information.description": {
+ "defaultMessage": "你的個人檔案資訊會公開顯示在 Modrinth 上 ,並可透過 Modrinth API 查詢。"
+ },
+ "settings.profile.save-error": {
+ "defaultMessage": "無法更新個人檔案"
+ },
+ "settings.profile.save-error-description": {
+ "defaultMessage": "更新個人檔案時發生錯誤,請再試一次。"
+ },
+ "settings.profile.sign-in-required.description": {
+ "defaultMessage": "登入 Modrinth 帳號即可自訂你的公開個人檔案。"
+ },
+ "settings.profile.sign-in-required.title": {
+ "defaultMessage": "需要 Modrinth 帳號"
+ },
+ "settings.profile.username.description": {
+ "defaultMessage": "獨特且不區分大小寫的名稱,用於識別你的個人檔案。"
+ },
"settings.sessions.title": {
"defaultMessage": "工作階段"
},
+ "settings.social.blocked-users.column.actions": {
+ "defaultMessage": "動作"
+ },
+ "settings.social.blocked-users.column.user": {
+ "defaultMessage": "使用者"
+ },
+ "settings.social.blocked-users.description": {
+ "defaultMessage": "以下是你在 Modrinth 上封鎖的使用者。他們無法:"
+ },
+ "settings.social.blocked-users.empty": {
+ "defaultMessage": "你沒有封鎖任何使用者。"
+ },
+ "settings.social.blocked-users.load-error": {
+ "defaultMessage": "無法載入已封鎖的使用者。"
+ },
+ "settings.social.blocked-users.loading": {
+ "defaultMessage": "正在載入已封鎖的使用者..."
+ },
+ "settings.social.blocked-users.restriction.friend-requests": {
+ "defaultMessage": "傳送好友邀請給你"
+ },
+ "settings.social.blocked-users.restriction.hosting": {
+ "defaultMessage": "邀請你管理 Modrinth Hosting 伺服器。"
+ },
+ "settings.social.blocked-users.restriction.shared-instances": {
+ "defaultMessage": "邀請你加入共用實例"
+ },
+ "settings.social.blocked-users.title": {
+ "defaultMessage": "封鎖名單"
+ },
+ "settings.social.blocked-users.unblock": {
+ "defaultMessage": "解除封鎖"
+ },
+ "settings.social.blocked-users.unblock-error": {
+ "defaultMessage": "無法解除封鎖使用者"
+ },
+ "settings.social.blocked-users.unblock-error-description": {
+ "defaultMessage": "解除封鎖使用者時發生錯誤,請再試一次。"
+ },
+ "settings.social.blocked-users.unblock-user": {
+ "defaultMessage": "解除封鎖 {username}"
+ },
+ "settings.social.blocked-users.user-avatar": {
+ "defaultMessage": "{username} 的顯示圖片"
+ },
+ "settings.social.friend-requests.description": {
+ "defaultMessage": "控制誰可以在 Modrinth 向你傳送好友邀請。"
+ },
+ "settings.social.friend-requests.title": {
+ "defaultMessage": "好友邀請"
+ },
+ "settings.social.interaction-source.coming-soon": {
+ "defaultMessage": "即將推出!"
+ },
+ "settings.social.interaction-source.everyone": {
+ "defaultMessage": "所有人"
+ },
+ "settings.social.interaction-source.friends": {
+ "defaultMessage": "好友"
+ },
+ "settings.social.interaction-source.friends-of-friends": {
+ "defaultMessage": "好友的好友"
+ },
+ "settings.social.interaction-source.no-one": {
+ "defaultMessage": "沒有人"
+ },
+ "settings.social.shared-instance-invites.description": {
+ "defaultMessage": "控制誰可以向你傳送共用實例和 Modrinth Hosting 面板的邀請。"
+ },
+ "settings.social.shared-instance-invites.title": {
+ "defaultMessage": "邀請"
+ },
+ "settings.social.sign-in-required.description": {
+ "defaultMessage": "你可以透過 Modrinth 帳號控制誰可以與你互動,並管理被封鎖的使用者"
+ },
+ "settings.social.sign-in-required.title": {
+ "defaultMessage": "需要 Modrinth 帳號"
+ },
+ "settings.social.title": {
+ "defaultMessage": "社交"
+ },
"sharing.invite-players-modal.add": {
"defaultMessage": "新增"
},
@@ -5115,16 +5337,19 @@
"defaultMessage": "已加入"
},
"sharing.invite-players-modal.already-invited": {
- "defaultMessage": "這個使用者已經被邀請。"
+ "defaultMessage": "這位使用者已經被邀請。"
+ },
+ "sharing.invite-players-modal.apply-button": {
+ "defaultMessage": "套用"
},
"sharing.invite-players-modal.avatar-alt": {
"defaultMessage": "{username} 的顯示圖片"
},
- "sharing.invite-players-modal.cancel": {
- "defaultMessage": "取消"
+ "sharing.invite-players-modal.custom-expiry": {
+ "defaultMessage": "自訂..."
},
- "sharing.invite-players-modal.cancel-button": {
- "defaultMessage": "取消"
+ "sharing.invite-players-modal.custom-expiry-value": {
+ "defaultMessage": "自訂:{date}"
},
"sharing.invite-players-modal.edit-invite-link": {
"defaultMessage": "編輯邀請連結。"
@@ -5132,8 +5357,26 @@
"sharing.invite-players-modal.edit-invite-link-title": {
"defaultMessage": "編輯邀請連結"
},
+ "sharing.invite-players-modal.expiry-in-one-day": {
+ "defaultMessage": "1 天"
+ },
+ "sharing.invite-players-modal.expiry-in-one-hour": {
+ "defaultMessage": "1 小時"
+ },
+ "sharing.invite-players-modal.expiry-in-seven-days": {
+ "defaultMessage": "7 天"
+ },
+ "sharing.invite-players-modal.expiry-in-six-hours": {
+ "defaultMessage": "6 小時"
+ },
+ "sharing.invite-players-modal.expiry-in-three-days": {
+ "defaultMessage": "3 天"
+ },
+ "sharing.invite-players-modal.expiry-in-twelve-hours": {
+ "defaultMessage": "12 小時"
+ },
"sharing.invite-players-modal.expiry-label": {
- "defaultMessage": "有效期限"
+ "defaultMessage": "有效時間"
},
"sharing.invite-players-modal.friends-heading": {
"defaultMessage": "你的好友 - {count}"
diff --git a/packages/ui/src/providers/content-manager.ts b/packages/ui/src/providers/content-manager.ts
index 936ee5ac06..b50e1122d0 100644
--- a/packages/ui/src/providers/content-manager.ts
+++ b/packages/ui/src/providers/content-manager.ts
@@ -1,7 +1,7 @@
export {
type ContentManagerContext,
- type ContentModpackData,
injectContentManager,
+ type ManagedContentData,
provideContentManager,
type UploadState,
} from '../layouts/shared/content-tab/providers/content-manager'
diff --git a/packages/ui/src/providers/index.ts b/packages/ui/src/providers/index.ts
index 9f7801eaf0..d86d8310ff 100644
--- a/packages/ui/src/providers/index.ts
+++ b/packages/ui/src/providers/index.ts
@@ -18,4 +18,5 @@ export * from './project-page-new'
export * from './server-context'
export * from './server-settings-modal'
export * from './tags'
+export * from './user-country'
export * from './web-notifications'
diff --git a/packages/ui/src/providers/popup-notifications.ts b/packages/ui/src/providers/popup-notifications.ts
index 493354cc4a..2c1c545e3b 100644
--- a/packages/ui/src/providers/popup-notifications.ts
+++ b/packages/ui/src/providers/popup-notifications.ts
@@ -1,4 +1,4 @@
-import type { Component } from 'vue'
+import { type Component, type Ref, ref } from 'vue'
import { createContext } from '.'
@@ -25,7 +25,6 @@ export interface PopupNotificationProgressItem {
progressCurrent?: number
progressTotal?: number
dismissible?: boolean
- onDismiss?: () => void | Promise
buttons?: PopupNotificationButton[]
}
@@ -73,15 +72,51 @@ export interface PopupNotification {
buttons?: PopupNotificationButton[]
toast?: PopupNotificationToast
dismissible?: boolean
+ onDismiss?: () => void | Promise
autoCloseMs?: number | null
timer?: NodeJS.Timeout
}
+export interface PopupNotificationDownloadState {
+ total: number
+ hidden: number
+}
+
export abstract class AbstractPopupNotificationManager {
protected readonly DEFAULT_AUTO_CLOSE_MS = 30 * 1000
+ private readonly hiddenDownloadItemKeys: Ref> = ref(new Set())
abstract getNotifications(): PopupNotification[]
+ getDownloadState = (): PopupNotificationDownloadState => {
+ const itemKeys = this.getDownloadNotifications().flatMap((notification) =>
+ this.getDownloadItemKeys(notification),
+ )
+ return {
+ total: itemKeys.length,
+ hidden: itemKeys.filter((key) => this.hiddenDownloadItemKeys.value.has(key)).length,
+ }
+ }
+
+ getVisibleNotifications = (): PopupNotification[] =>
+ this.getNotifications().filter(
+ (notification) =>
+ !this.isDownloadNotification(notification) ||
+ this.getDownloadItemKeys(notification).some(
+ (key) => !this.hiddenDownloadItemKeys.value.has(key),
+ ),
+ )
+
+ getVisibleDownloadProgressItems = (
+ notification: PopupNotification,
+ ): PopupNotificationProgressItem[] =>
+ (notification.progressItems ?? []).filter(
+ (progressItem) =>
+ !this.hiddenDownloadItemKeys.value.has(
+ this.getDownloadItemKey(notification.id, progressItem.id),
+ ),
+ )
+
protected abstract addNotificationToStorage(notification: PopupNotification): void
protected abstract removeNotificationFromStorage(id: string | number): void
protected abstract clearAllNotificationsFromStorage(): void
@@ -103,6 +138,9 @@ export abstract class AbstractPopupNotificationManager {
const notification = notifications.find((n) => n.id === id)
if (notification) {
this.clearNotificationTimer(notification)
+ this.getDownloadItemKeys(notification).forEach((key) =>
+ this.hiddenDownloadItemKeys.value.delete(key),
+ )
this.removeNotificationFromStorage(id)
}
}
@@ -110,6 +148,45 @@ export abstract class AbstractPopupNotificationManager {
clearAllNotifications = (): void => {
this.getNotifications().forEach((n) => this.clearNotificationTimer(n))
this.clearAllNotificationsFromStorage()
+ this.hiddenDownloadItemKeys.value.clear()
+ }
+
+ hideDownloadItem = (notificationId: string | number, progressItemId: string): void => {
+ const notification = this.getDownloadNotifications().find(
+ (candidate) => candidate.id === notificationId,
+ )
+ if (!notification?.progressItems?.some((item) => item.id === progressItemId)) return
+
+ this.hiddenDownloadItemKeys.value.add(this.getDownloadItemKey(notificationId, progressItemId))
+ if (
+ this.getDownloadItemKeys(notification).every((key) =>
+ this.hiddenDownloadItemKeys.value.has(key),
+ )
+ ) {
+ this.clearNotificationTimer(notification)
+ }
+ }
+
+ toggleDownloadNotifications = (): void => {
+ const downloadNotifications = this.getDownloadNotifications()
+ const hasHiddenDownloads = downloadNotifications.some((notification) =>
+ this.getDownloadItemKeys(notification).some((key) =>
+ this.hiddenDownloadItemKeys.value.has(key),
+ ),
+ )
+
+ if (hasHiddenDownloads) {
+ this.hiddenDownloadItemKeys.value.clear()
+ downloadNotifications.forEach((notification) => this.setNotificationTimer(notification))
+ return
+ }
+
+ downloadNotifications.forEach((notification) => {
+ this.getDownloadItemKeys(notification).forEach((key) =>
+ this.hiddenDownloadItemKeys.value.add(key),
+ )
+ this.clearNotificationTimer(notification)
+ })
}
setNotificationTimer = (notification: PopupNotification): void => {
@@ -134,6 +211,30 @@ export abstract class AbstractPopupNotificationManager {
notification.timer = undefined
}
}
+
+ private isDownloadNotification(notification: PopupNotification): boolean {
+ return notification.type === 'download' || notification.toast?.type === 'instance-download'
+ }
+
+ private getDownloadNotifications(): PopupNotification[] {
+ return this.getNotifications().filter((notification) =>
+ this.isDownloadNotification(notification),
+ )
+ }
+
+ private getDownloadItemKeys(notification: PopupNotification): string[] {
+ if (!this.isDownloadNotification(notification)) return []
+ if (notification.progressItems?.length) {
+ return notification.progressItems.map((progressItem) =>
+ this.getDownloadItemKey(notification.id, progressItem.id),
+ )
+ }
+ return [this.getDownloadItemKey(notification.id)]
+ }
+
+ private getDownloadItemKey(notificationId: string | number, progressItemId?: string): string {
+ return JSON.stringify([typeof notificationId, notificationId, progressItemId ?? null])
+ }
}
export const [injectPopupNotificationManager, providePopupNotificationManager] =
diff --git a/packages/ui/src/providers/project-page.ts b/packages/ui/src/providers/project-page.ts
index c81f83b9fd..dce8569c92 100644
--- a/packages/ui/src/providers/project-page.ts
+++ b/packages/ui/src/providers/project-page.ts
@@ -15,7 +15,7 @@ export interface ProjectPageContext {
allMembers: Ref
organization: Ref
// Lazy version loading (client-side only)
- versions: Ref
+ versions: Ref
versionsLoading: Ref
versionsLoaded: Ref
// Lazy dependencies loading (client-side only)
diff --git a/packages/ui/src/providers/user-country.ts b/packages/ui/src/providers/user-country.ts
new file mode 100644
index 0000000000..a0100e0dc8
--- /dev/null
+++ b/packages/ui/src/providers/user-country.ts
@@ -0,0 +1,28 @@
+import { setMarkdownUserCountryResolver } from '@modrinth/utils'
+import type { Ref } from 'vue'
+import { hasInjectionContext } from 'vue'
+
+import { createContext } from './create-context'
+
+const [injectUserCountryContext, provideUserCountryContext] = createContext[>(
+ 'root',
+ 'userCountry',
+)
+
+let clientCountry: Ref] | null = null
+
+export const injectUserCountry = injectUserCountryContext
+export const useUserCountry = injectUserCountryContext
+
+export function provideUserCountry(country: Ref) {
+ if (typeof window !== 'undefined') {
+ clientCountry = country
+ }
+
+ return provideUserCountryContext(country)
+}
+
+setMarkdownUserCountryResolver(() => {
+ const injectedCountry = hasInjectionContext() ? injectUserCountryContext(null) : null
+ return injectedCountry?.value ?? clientCountry?.value
+})
diff --git a/packages/ui/src/stories/add-stories.md b/packages/ui/src/stories/add-stories.md
index 19f83c3ba9..2132d4f14c 100644
--- a/packages/ui/src/stories/add-stories.md
+++ b/packages/ui/src/stories/add-stories.md
@@ -153,16 +153,14 @@ For components that need user interaction to show:
```typescript
export const Default: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { Button, NewModal },
setup() {
const modalRef = ref | null>(null)
return { modalRef }
},
template: /* html */ `
-
- Open Modal
-
+
Open Modal
Modal content
@@ -199,10 +197,10 @@ Components should use relative imports, not the package alias:
```typescript
// ❌ BAD - Causes circular dependency in Storybook
-import { ButtonStyled } from '@modrinth/ui'
+import { Button } from '@modrinth/ui'
// ✅ GOOD - Use relative imports
-import ButtonStyled from '../base/ButtonStyled.vue'
+import Button from '../components/base/buttons/Button.vue'
```
### 2. Object/Array Prop Defaults Must Be Factory Functions
diff --git a/packages/ui/src/stories/base/Admonition.stories.ts b/packages/ui/src/stories/base/Admonition.stories.ts
index 413e2a1b6d..bcd6894084 100644
--- a/packages/ui/src/stories/base/Admonition.stories.ts
+++ b/packages/ui/src/stories/base/Admonition.stories.ts
@@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'
import { ref } from 'vue'
import Admonition from '../../components/base/Admonition.vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import { Button } from '../../components/base/buttons'
const meta = {
title: 'Base/Admonition',
@@ -78,7 +78,7 @@ export const HeaderWithTimestamp: Story = {
export const WithTopRightActions: Story = {
render: () => ({
- components: { Admonition, ButtonStyled },
+ components: { Admonition, Button },
template: /*html*/ `
Uploading server files...
-
- Cancel
-
+ Cancel
Something went wrong while extracting the archive.
-
- Retry
-
+ Retry
@@ -115,7 +111,7 @@ export const WithTopRightActions: Story = {
export const WithProgressBar: Story = {
render: () => ({
- components: { Admonition, ButtonStyled },
+ components: { Admonition, Button },
template: /*html*/ `
128 KB / 1.2 MB (45%)
-
- Cancel
-
+ Cancel
24 MB extracted — config/settings.yml
-
- Cancel
-
+ Cancel
({
- components: { Button },
- setup() {
- return { args }
- },
- template: /*html*/ `
- Click me
- `,
- }),
-} satisfies Meta
-
-export default meta
-type Story = StoryObj
-
-export const Default: Story = {}
-
-export const Primary: Story = {
- args: {
- color: 'primary',
- },
-}
-
-export const Danger: Story = {
- args: {
- color: 'danger',
- },
-}
-
-export const AllColors: Story = {
- render: () => ({
- components: { Button },
- template: /*html*/ `
-
- Default
- Primary
- Danger
- Red
- Orange
- Green
- Blue
- Purple
-
- `,
- }),
-}
-
-export const Large: Story = {
- args: {
- large: true,
- },
-}
-
-export const Outline: Story = {
- args: {
- outline: true,
- },
-}
-
-export const Transparent: Story = {
- args: {
- transparent: true,
- },
-}
-
-export const Disabled: Story = {
- args: {
- disabled: true,
- },
-}
-
-export const AsLink: Story = {
- args: {
- link: 'https://modrinth.com',
- external: true,
- },
-}
diff --git a/packages/ui/src/stories/base/ButtonStyled.stories.ts b/packages/ui/src/stories/base/ButtonStyled.stories.ts
deleted file mode 100644
index 852ceab118..0000000000
--- a/packages/ui/src/stories/base/ButtonStyled.stories.ts
+++ /dev/null
@@ -1,226 +0,0 @@
-import { DownloadIcon, HeartIcon, SettingsIcon } from '@modrinth/assets'
-import type { Meta, StoryObj } from '@storybook/vue3-vite'
-
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
-
-const colors = ['standard', 'brand', 'red', 'orange', 'green', 'blue', 'purple'] as const
-const types = [
- 'standard',
- 'outlined',
- 'transparent',
- 'highlight',
- 'highlight-colored-text',
- 'chip',
-] as const
-const sizes = ['small', 'standard', 'large'] as const
-
-const meta = {
- title: 'Base/ButtonStyled',
- component: ButtonStyled,
- argTypes: {
- color: {
- control: 'select',
- options: [...colors, 'medal-promo'],
- },
- size: {
- control: 'select',
- options: [...sizes],
- },
- type: {
- control: 'select',
- options: [...types],
- },
- circular: { control: 'boolean' },
- colorFill: {
- control: 'select',
- options: ['auto', 'background', 'text', 'none'],
- },
- hoverColorFill: {
- control: 'select',
- options: ['auto', 'background', 'text', 'none'],
- },
- highlighted: { control: 'boolean' },
- highlightedStyle: {
- control: 'select',
- options: ['main-nav-primary', 'main-nav-secondary'],
- },
- },
- args: {
- color: 'standard',
- size: 'standard',
- type: 'standard',
- circular: false,
- colorFill: 'auto',
- hoverColorFill: 'auto',
- highlighted: false,
- highlightedStyle: 'main-nav-primary',
- },
- render: (args) => ({
- components: { ButtonStyled, DownloadIcon },
- setup() {
- return { args }
- },
- template: /*html*/ `
-
- Button
-
- `,
- }),
-} satisfies Meta
-
-export default meta
-type Story = StoryObj
-
-export const Default: Story = {
- args: {
- type: 'standard',
- },
-}
-
-export const AllVariants: Story = {
- render: () => ({
- components: { ButtonStyled },
- setup() {
- return { colors, types }
- },
- template: /*html*/ `
-
-
-
-
- Color / Type
- {{ type }}
-
-
-
-
- {{ color }}
-
-
- Button
-
-
-
-
-
-
- `,
- }),
-}
-
-export const AllVariantsHighlighted: Story = {
- render: () => ({
- components: { ButtonStyled },
- setup() {
- return { colors, types }
- },
- template: /*html*/ `
-
-
-
-
- Color / Type
- {{ type }}
-
-
-
-
- {{ color }}
-
-
- Button
-
-
-
-
-
-
- `,
- }),
-}
-
-export const Sizes: Story = {
- render: () => ({
- components: { ButtonStyled },
- setup() {
- return { sizes, types }
- },
- template: /*html*/ `
-
-
-
-
- Size / Type
- {{ type }}
-
-
-
-
- {{ size }}
-
-
- Button
-
-
-
-
-
-
- `,
- }),
-}
-
-export const WithIcons: Story = {
- render: () => ({
- components: { ButtonStyled, DownloadIcon, HeartIcon, SettingsIcon },
- setup() {
- return { types }
- },
- template: /*html*/ `
-
-
-
-
- Variant
- {{ type }}
-
-
-
-
- Icon + text
-
-
- Download
-
-
-
-
- Icon only
-
-
-
-
-
-
-
-
-
- `,
- }),
-}
-
-export const Disabled: Story = {
- render: () => ({
- components: { ButtonStyled },
- setup() {
- return { types }
- },
- template: /*html*/ `
-
-
- {{ type }}
-
-
- `,
- }),
-}
diff --git a/packages/ui/src/stories/base/EmptyState.stories.ts b/packages/ui/src/stories/base/EmptyState.stories.ts
index f698148b9b..8fa5be7f23 100644
--- a/packages/ui/src/stories/base/EmptyState.stories.ts
+++ b/packages/ui/src/stories/base/EmptyState.stories.ts
@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from '@storybook/vue3-vite'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import { Button } from '../../components/base/buttons'
import EmptyState from '../../components/base/EmptyState.vue'
const meta = {
@@ -42,7 +42,7 @@ export const Default: Story = {
export const WithActions: StoryObj = {
render: () => ({
- components: { EmptyState, ButtonStyled },
+ components: { EmptyState, Button },
template: /*html*/ `
-
- Create backup
-
+ Create backup
`,
diff --git a/packages/ui/src/stories/base/FileTreeSelect.stories.ts b/packages/ui/src/stories/base/FileTreeSelect.stories.ts
index a85d13ab5e..acaf6eb8e4 100644
--- a/packages/ui/src/stories/base/FileTreeSelect.stories.ts
+++ b/packages/ui/src/stories/base/FileTreeSelect.stories.ts
@@ -39,30 +39,37 @@ export const ModpackExport: StoryObj = {
render: () => ({
components: { FileTreeSelect },
setup() {
- const selected = ref([
- 'config/fabric_loader_dependencies.json',
- 'config/crash_assistant/settings.toml',
- 'config/defaultoptions/options.txt',
- 'mods/sodium-fabric-0.6.13+mc1.21.6.jar',
- 'mods/iris-fabric-1.8.8+mc1.21.6.jar',
- 'resourcepacks/FreshAnimations_v1.9.3.zip',
- 'shaderpacks/ComplementaryUnbound_r5.5.1.zip',
- ])
- const selectedLabel = computed(() => `${selected.value.length} selected`)
+ const included = ref(['config', 'mods'])
+ const excluded = ref(['config/defaultoptions'])
+ const selectedLabel = computed(
+ () => `${included.value.length} includes, ${excluded.value.length} exclusions`,
+ )
return {
+ excluded,
+ included,
items: MODPACK_FILES,
- selected,
selectedLabel,
}
},
template: /*html*/ `
-
+
{{ selectedLabel }}
-
-
{{ path }}
+
+
+ Included
+ {{ path }}
+
+
+ Excluded
+ {{ path }}
+
@@ -74,12 +81,17 @@ export const EmptyRoot: StoryObj = {
render: () => ({
components: { FileTreeSelect },
setup() {
- const selected = ref
([])
- return { selected }
+ const excluded = ref([])
+ const included = ref([])
+ return { excluded, included }
},
template: /*html*/ `
-
+
`,
}),
diff --git a/packages/ui/src/stories/base/JoinedButtons.stories.ts b/packages/ui/src/stories/base/JoinedButtons.stories.ts
deleted file mode 100644
index c007e3631d..0000000000
--- a/packages/ui/src/stories/base/JoinedButtons.stories.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-import { PlayIcon, SlashIcon, StopCircleIcon, UpdatedIcon } from '@modrinth/assets'
-import type { Meta, StoryObj } from '@storybook/vue3-vite'
-
-import JoinedButtons from '../../components/base/JoinedButtons.vue'
-
-const meta = {
- title: 'Base/JoinedButtons',
- component: JoinedButtons,
- argTypes: {
- color: {
- control: 'select',
- options: ['standard', 'brand', 'red', 'orange', 'green', 'blue', 'purple'],
- },
- size: {
- control: 'select',
- options: ['small', 'standard', 'large'],
- },
- disabled: { control: 'boolean' },
- primaryDisabled: { control: 'boolean' },
- dropdownDisabled: { control: 'boolean' },
- primaryMuted: { control: 'boolean' },
- },
-} satisfies Meta
-
-export default meta
-type Story = StoryObj
-
-export const Start: Story = {
- args: {
- color: 'brand',
- size: 'large',
- actions: [
- {
- id: 'start',
- label: 'Start',
- icon: PlayIcon,
- action: () => console.log('Start'),
- },
- ],
- },
-}
-
-export const StopWithKill: Story = {
- args: {
- color: 'red',
- size: 'large',
- actions: [
- {
- id: 'stop',
- label: 'Stop',
- icon: StopCircleIcon,
- action: () => console.log('Stop'),
- },
- {
- id: 'kill_server',
- label: 'Kill server',
- icon: SlashIcon,
- action: () => console.log('Kill'),
- },
- ],
- },
-}
-
-export const Stopping: Story = {
- args: {
- color: 'red',
- size: 'large',
- primaryDisabled: true,
- primaryMuted: true,
- actions: [
- {
- id: 'stop',
- label: 'Stopping',
- icon: StopCircleIcon,
- action: () => console.log('Stop'),
- },
- {
- id: 'kill_server',
- label: 'Kill server',
- icon: SlashIcon,
- action: () => console.log('Kill'),
- },
- ],
- },
-}
-
-export const Restart: Story = {
- args: {
- color: 'orange',
- size: 'large',
- actions: [
- {
- id: 'restart',
- label: 'Restart',
- icon: UpdatedIcon,
- action: () => console.log('Restart'),
- },
- ],
- },
-}
-
-export const Disabled: Story = {
- args: {
- color: 'red',
- size: 'large',
- disabled: true,
- actions: [
- {
- id: 'stop',
- label: 'Stop',
- icon: StopCircleIcon,
- action: () => console.log('Stop'),
- },
- {
- id: 'kill_server',
- label: 'Kill server',
- icon: SlashIcon,
- action: () => console.log('Kill'),
- },
- ],
- },
-}
diff --git a/packages/ui/src/stories/base/OverflowMenu.stories.ts b/packages/ui/src/stories/base/OverflowMenu.stories.ts
deleted file mode 100644
index 0adec75cf2..0000000000
--- a/packages/ui/src/stories/base/OverflowMenu.stories.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import { MoreHorizontalIcon } from '@modrinth/assets'
-import type { Meta, StoryObj } from '@storybook/vue3-vite'
-
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
-import OverflowMenu from '../../components/base/OverflowMenu.vue'
-
-const meta = {
- title: 'Base/OverflowMenu',
- component: OverflowMenu,
- render: (args) => ({
- components: { OverflowMenu, MoreHorizontalIcon, ButtonStyled },
- setup() {
- return { args }
- },
- template: /*html*/ `
-
-
-
- Edit
- Delete
- Share
-
-
- `,
- }),
-} satisfies Meta
-
-export default meta
-type Story = StoryObj
-
-export const Default: Story = {
- args: {
- options: [
- { id: 'edit', action: () => console.log('Edit clicked') },
- { id: 'share', action: () => console.log('Share clicked') },
- { divider: true },
- { id: 'delete', action: () => console.log('Delete clicked'), color: 'danger' },
- ],
- },
-}
-
-export const WithDifferentPlacements: StoryObj = {
- render: () => ({
- components: { OverflowMenu, MoreHorizontalIcon, ButtonStyled },
- template: /*html*/ `
-
-
- bottom-end (default)
-
-
-
- Edit
- Delete
-
-
-
-
- bottom-start
-
-
-
- Edit
- Delete
-
-
-
-
- `,
- }),
-}
diff --git a/packages/ui/src/stories/base/PageHeader.stories.ts b/packages/ui/src/stories/base/PageHeader.stories.ts
index 73ad628820..a8344567da 100644
--- a/packages/ui/src/stories/base/PageHeader.stories.ts
+++ b/packages/ui/src/stories/base/PageHeader.stories.ts
@@ -20,9 +20,13 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'
import AutoLink from '../../components/base/AutoLink.vue'
import Avatar from '../../components/base/Avatar.vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import {
+ Button,
+ IconButton,
+ SplitButton,
+ TeleportOverflowMenu,
+} from '../../components/base/buttons'
import FormattedTag from '../../components/base/FormattedTag.vue'
-import JoinedButtons from '../../components/base/JoinedButtons.vue'
import PageHeader from '../../components/base/page-header/index.vue'
import PageHeaderMetadata from '../../components/base/page-header/metadata/index.vue'
import PageHeaderMetadataItem from '../../components/base/page-header/metadata/page-header-metadata-item.vue'
@@ -31,9 +35,8 @@ import PageHeaderMetadataTagsItem from '../../components/base/page-header/metada
import PageHeaderMetadataTimeItem from '../../components/base/page-header/metadata/page-header-metadata-time-item.vue'
import PageHeaderActions from '../../components/base/page-header/page-header-actions.vue'
import PageHeaderBadgeItem from '../../components/base/page-header/page-header-badge-item.vue'
+import TagIcon from '../../components/base/TagIcon.vue'
import TagItem from '../../components/base/TagItem.vue'
-import TeleportOverflowMenu from '../../components/base/TeleportOverflowMenu.vue'
-import LoaderIcon from '../../components/servers/icons/LoaderIcon.vue'
import ServerIcon from '../../components/servers/icons/ServerIcon.vue'
const noop = () => undefined
@@ -87,9 +90,10 @@ const pageHeaderIcons = {
const pageHeaderComponents = {
AutoLink,
Avatar,
- ButtonStyled,
+ Button,
FormattedTag,
- JoinedButtons,
+ IconButton,
+ SplitButton,
PageHeader,
PageHeaderActions,
PageHeaderBadgeItem,
@@ -111,7 +115,7 @@ const meta = {
},
decorators: [
(story) => ({
- components: { story },
+ components: { story, TeleportOverflowMenu },
template: '
',
}),
],
@@ -157,17 +161,13 @@ export const ProjectHeader: Story = {
-
-
-
- Download
-
-
-
-
-
-
-
+
+
+ Download
+
+
+
+
@@ -207,12 +207,10 @@ export const CreatorHeader: Story = {
-
-
-
- Follow
-
-
+
+
+ Follow
+
@@ -222,14 +220,11 @@ export const CreatorHeader: Story = {
export const AppInstanceHeader: Story = {
render: () => ({
- components: {
- ...pageHeaderComponents,
- LoaderIcon,
- },
+ components: { ...pageHeaderComponents, TagIcon, TeleportOverflowMenu },
setup() {
return {
...pageHeaderIcons,
- LoaderIcon,
+ TagIcon,
menuActions,
noop,
}
@@ -243,7 +238,7 @@ export const AppInstanceHeader: Story = {
Minecraft 1.20.1
-
+
Fabric 0.16.14
12 hours
@@ -252,22 +247,16 @@ export const AppInstanceHeader: Story = {
-
-
-
- Play
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ Play
+
+
+
+
+
+
+
@@ -277,25 +266,20 @@ export const AppInstanceHeader: Story = {
export const BrowseHeader: Story = {
render: () => ({
- components: {
- ...pageHeaderComponents,
- LoaderIcon,
- },
+ components: { ...pageHeaderComponents, TagIcon, TeleportOverflowMenu },
setup() {
return {
...pageHeaderIcons,
- LoaderIcon,
+ TagIcon,
noop,
}
},
template: `
-
-
-
-
-
+
+
+
@@ -305,7 +289,7 @@ export const BrowseHeader: Story = {
Minecraft 1.20.1
-
+
Fabric
@@ -317,10 +301,7 @@ export const BrowseHeader: Story = {
export const ServerPanelRootHeader: Story = {
render: () => ({
- components: {
- ...pageHeaderComponents,
- ServerIcon,
- },
+ components: { ...pageHeaderComponents, ServerIcon, TeleportOverflowMenu },
setup() {
return {
...pageHeaderIcons,
@@ -346,17 +327,13 @@ export const ServerPanelRootHeader: Story = {
-
-
-
- Start server
-
-
-
-
-
-
-
+
+
+ Start server
+
+
+
+
@@ -366,32 +343,27 @@ export const ServerPanelRootHeader: Story = {
export const ServerPanelInstanceHeader: Story = {
render: () => ({
- components: {
- ...pageHeaderComponents,
- LoaderIcon,
- },
+ components: { ...pageHeaderComponents, TagIcon, TeleportOverflowMenu },
setup() {
return {
...pageHeaderIcons,
joinedActions,
- LoaderIcon,
+ TagIcon,
noop,
}
},
template: `
-
-
-
-
-
+
+
+
Minecraft 1.20.1
-
+
Fabric 0.19.2
Last active 2 weeks ago
@@ -400,18 +372,24 @@ export const ServerPanelInstanceHeader: Story = {
-
-
-
- Start instance
-
-
-
-
-
-
-
-
+
+
+ Start instance
+
+
+
+ Stop
+
+
+
+
diff --git a/packages/ui/src/stories/base/PopoutMenu.stories.ts b/packages/ui/src/stories/base/PopoutMenu.stories.ts
deleted file mode 100644
index 7e3d02a512..0000000000
--- a/packages/ui/src/stories/base/PopoutMenu.stories.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import { SettingsIcon } from '@modrinth/assets'
-import type { Meta, StoryObj } from '@storybook/vue3-vite'
-
-import Button from '../../components/base/Button.vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
-import PopoutMenu from '../../components/base/PopoutMenu.vue'
-
-const meta = {
- title: 'Base/PopoutMenu',
- component: PopoutMenu,
- render: (args) => ({
- components: { PopoutMenu, Button, ButtonStyled, SettingsIcon },
- setup() {
- return { args }
- },
- template: /*html*/ `
-
-
-
-
-
- Option 1
- Option 2
- Option 3
-
-
-
-
- `,
- }),
-} satisfies Meta
-
-export default meta
-type Story = StoryObj
-
-export const Default: Story = {}
-
-export const WithTooltip: Story = {
- args: {
- tooltip: 'Click for more options',
- },
-}
-
-export const DifferentPlacements: StoryObj = {
- render: () => ({
- components: { PopoutMenu, Button, ButtonStyled, SettingsIcon },
- template: /*html*/ `
-
-
-
bottom-end (default)
-
-
-
-
-
- Option 1
- Option 2
-
-
-
-
-
-
-
bottom-start
-
-
-
-
-
- Option 1
- Option 2
-
-
-
-
-
-
-
top-end
-
-
-
-
-
- Option 1
- Option 2
-
-
-
-
-
-
- `,
- }),
-}
diff --git a/packages/ui/src/stories/base/StackedAdmonitions.stories.ts b/packages/ui/src/stories/base/StackedAdmonitions.stories.ts
index c0683ad7df..fbef68fb42 100644
--- a/packages/ui/src/stories/base/StackedAdmonitions.stories.ts
+++ b/packages/ui/src/stories/base/StackedAdmonitions.stories.ts
@@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'
import { ref } from 'vue'
import Admonition from '../../components/base/Admonition.vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import { Button } from '../../components/base/buttons'
import StackedAdmonitionsRaw, {
type StackedAdmonitionItem,
} from '../../components/base/StackedAdmonitions.vue'
@@ -383,7 +383,7 @@ interface RichItem extends StackedAdmonitionItem {
export const RichContent: Story = {
render: () => ({
- components: { StackedAdmonitions, Admonition, ButtonStyled },
+ components: { StackedAdmonitions, Admonition, Button },
setup() {
const items = ref([
{
@@ -429,12 +429,8 @@ export const RichContent: Story = {
>
{{ item.body }}
-
- Cancel
-
-
- Retry
-
+ Cancel
+ Retry
diff --git a/packages/ui/src/stories/base/Table.stories.ts b/packages/ui/src/stories/base/Table.stories.ts
index 157c1ffbcb..6448cbe7bd 100644
--- a/packages/ui/src/stories/base/Table.stories.ts
+++ b/packages/ui/src/stories/base/Table.stories.ts
@@ -3,8 +3,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'
import { computed, ref } from 'vue'
import Badge from '../../components/base/Badge.vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
-import OverflowMenu from '../../components/base/OverflowMenu.vue'
+import { Button, TeleportOverflowMenu } from '../../components/base/buttons'
import Table from '../../components/base/Table.vue'
interface User {
@@ -54,7 +53,7 @@ export default meta
export const Default: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -74,7 +73,7 @@ export const Default: StoryObj = {
export const HorizontalOverflow: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -103,7 +102,7 @@ export const HorizontalOverflow: StoryObj = {
export const CustomClasses: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name', cellClass: '!overflow-visible py-3' },
@@ -129,7 +128,7 @@ export const CustomClasses: StoryObj = {
export const WithSelection: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -160,7 +159,7 @@ export const WithSelection: StoryObj = {
export const WithSelectionData: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -193,7 +192,7 @@ export const WithSelectionData: StoryObj = {
export const WithSelectionIds: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -233,7 +232,7 @@ export const WithSorting: StoryObj = {
},
},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name', enableSorting: true },
@@ -269,7 +268,7 @@ export const WithSorting: StoryObj = {
export const WithColumnAlignment: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name', align: 'left' as const },
@@ -289,7 +288,7 @@ export const WithColumnAlignment: StoryObj = {
export const WithCustomCellSlots: StoryObj = {
args: {},
render: () => ({
- components: { Table, Badge },
+ components: { Table, Badge, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -335,7 +334,7 @@ export const WithCustomCellSlots: StoryObj = {
export const WithCustomHeaderSlots: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -365,7 +364,7 @@ export const WithCustomHeaderSlots: StoryObj = {
export const WithHeaderSlot: StoryObj = {
args: {},
render: () => ({
- components: { Table, ButtonStyled },
+ components: { Table, Button, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -383,9 +382,7 @@ export const WithHeaderSlot: StoryObj = {
Team Members
-
- Invite member
-
+ Invite member
@@ -397,7 +394,7 @@ export const WithHeaderSlot: StoryObj = {
export const WithActionsColumn: StoryObj = {
args: {},
render: () => ({
- components: { Table, ButtonStyled, EditIcon, TrashIcon },
+ components: { Table, EditIcon, TrashIcon, Button, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -421,18 +418,14 @@ export const WithActionsColumn: StoryObj = {
-
-
-
- Edit
-
-
-
-
-
- Delete
-
-
+
+
+ Edit
+
+
+
+ Delete
+
@@ -443,7 +436,7 @@ export const WithActionsColumn: StoryObj = {
export const WithLocalizedActionsColumn: StoryObj = {
args: {},
render: () => ({
- components: { Table, ButtonStyled, EditIcon, TrashIcon },
+ components: { Table, EditIcon, TrashIcon, Button, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Nombre' },
@@ -467,18 +460,14 @@ export const WithLocalizedActionsColumn: StoryObj = {
-
-
-
- Editar
-
-
-
-
-
- Eliminar
-
-
+
+
+ Editar
+
+
+
+ Eliminar
+
@@ -489,7 +478,7 @@ export const WithLocalizedActionsColumn: StoryObj = {
export const FullFeatured: StoryObj = {
args: {},
render: () => ({
- components: { Table, Badge, ButtonStyled, EditIcon, TrashIcon },
+ components: { Table, Badge, EditIcon, TrashIcon, Button, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name', enableSorting: true },
@@ -565,18 +554,14 @@ export const FullFeatured: StoryObj = {
-
-
-
- Edit
-
-
-
-
-
- Delete
-
-
+
+
+ Edit
+
+
+
+ Delete
+
@@ -592,7 +577,7 @@ export const FullFeatured: StoryObj = {
export const VirtualizedLargeData: StoryObj = {
args: {},
render: () => ({
- components: { Table, Badge },
+ components: { Table, Badge, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name', enableSorting: true },
@@ -710,7 +695,15 @@ export const VirtualizedLargeData: StoryObj = {
export const WithOverflowMenu: StoryObj = {
args: {},
render: () => ({
- components: { Table, Badge, ButtonStyled, OverflowMenu, MoreVerticalIcon, EditIcon, TrashIcon },
+ components: {
+ Table,
+ Badge,
+ MoreVerticalIcon,
+ EditIcon,
+ TrashIcon,
+ Button,
+ TeleportOverflowMenu,
+ },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
@@ -737,17 +730,19 @@ export const WithOverflowMenu: StoryObj = {
const getMenuOptions = (row: User) => [
{
id: 'edit',
+ label: 'Edit',
action: () => alert(`Edit user: ${row.name}`),
},
{
id: 'duplicate',
+ label: 'Duplicate',
action: () => alert(`Duplicate user: ${row.name}`),
},
- { divider: true },
+ { type: 'divider' },
{
id: 'delete',
- color: 'red' as const,
- hoverFilled: true,
+ label: 'Delete',
+ tone: 'red',
action: () => alert(`Delete user: ${row.name}`),
},
]
@@ -766,26 +761,23 @@ export const WithOverflowMenu: StoryObj = {
-
-
-
-
-
- Edit
-
-
-
- Duplicate
-
-
-
- Delete
-
-
-
+
+
+
+ Edit
+
+
+
+ Duplicate
+
+
+
+ Delete
+
+
@@ -796,7 +788,7 @@ export const WithOverflowMenu: StoryObj = {
export const EmptyState: StoryObj = {
args: {},
render: () => ({
- components: { Table },
+ components: { Table, TeleportOverflowMenu },
setup() {
const columns = [
{ key: 'name', label: 'Name' },
diff --git a/packages/ui/src/stories/buttons/Button.stories.ts b/packages/ui/src/stories/buttons/Button.stories.ts
new file mode 100644
index 0000000000..85bfe95332
--- /dev/null
+++ b/packages/ui/src/stories/buttons/Button.stories.ts
@@ -0,0 +1,213 @@
+import { DownloadIcon, ExternalIcon, HeartIcon, SettingsIcon } from '@modrinth/assets'
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import Button from '../../components/base/buttons/Button.vue'
+import ButtonLink from '../../components/base/buttons/ButtonLink.vue'
+import IconButton from '../../components/base/buttons/IconButton.vue'
+
+const types = ['base', 'colored', 'outlined', 'quiet'] as const
+const sizes = ['sm', 'md', 'lg', 'xl'] as const
+const colors = ['brand', 'red', 'orange', 'green', 'blue', 'purple', 'medal_promotion'] as const
+const sizeColumns = [
+ { value: 'sm', label: 'Small' },
+ { value: 'md', label: 'Medium' },
+ { value: 'lg', label: 'Large' },
+ { value: 'xl', label: 'Extra large' },
+] as const
+const typeRows = [
+ { label: 'Base', type: 'base' },
+ { label: 'Outlined', type: 'outlined' },
+ { label: 'Quiet', type: 'quiet' },
+ ...colors.map((color) => ({
+ label: `Colored / ${color.charAt(0).toUpperCase()}${color.slice(1)}`,
+ type: 'colored' as const,
+ color,
+ })),
+ ...colors.map((color) => ({
+ label: `Outlined / ${color.charAt(0).toUpperCase()}${color.slice(1)}`,
+ type: 'outlined' as const,
+ color,
+ })),
+ ...colors.map((color) => ({
+ label: `Quiet / ${color.charAt(0).toUpperCase()}${color.slice(1)}`,
+ type: 'quiet' as const,
+ color,
+ })),
+]
+
+const meta = {
+ title: 'Buttons/Button',
+ component: Button,
+ argTypes: {
+ type: {
+ control: 'select',
+ options: types,
+ },
+ size: {
+ control: 'select',
+ options: sizes,
+ },
+ color: {
+ control: 'select',
+ options: colors,
+ },
+ nativeType: {
+ control: 'select',
+ options: ['button', 'submit', 'reset'],
+ },
+ disabled: { control: 'boolean' },
+ loading: { control: 'boolean' },
+ },
+ args: {
+ type: 'base',
+ size: 'md',
+ color: 'brand',
+ nativeType: 'button',
+ disabled: false,
+ loading: false,
+ },
+ render: (args) => ({
+ components: { Button, DownloadIcon },
+ setup() {
+ return { args }
+ },
+ template: /*html*/ `
+
+
+ Download
+
+ `,
+ }),
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Playground: Story = {}
+
+export const AllTypes: Story = {
+ render: () => ({
+ components: { Button, DownloadIcon },
+ setup() {
+ return { sizeColumns, typeRows }
+ },
+ template: /*html*/ `
+
+
+
+ {{ size.label }}
+
+
+
+ {{ row.label }}
+
+ Button
+
+
+
+ `,
+ }),
+}
+
+export const Quiet: Story = {
+ render: () => ({
+ components: { Button, DownloadIcon, IconButton, SettingsIcon },
+ template: /*html*/ `
+
+ Quiet
+ Quiet destructive
+
+
+ `,
+ }),
+}
+
+export const Sizes: Story = {
+ render: () => ({
+ components: { Button, DownloadIcon, IconButton },
+ setup() {
+ return { sizes }
+ },
+ template: /*html*/ `
+
+
+ {{ size }}
+
+
+
+ `,
+ }),
+}
+
+export const Colors: Story = {
+ render: () => ({
+ components: { Button },
+ setup() {
+ return { colors }
+ },
+ template: /*html*/ `
+
+
+ {{ color }}
+
+
+ `,
+ }),
+}
+
+export const Content: Story = {
+ render: () => ({
+ components: { Button, DownloadIcon, SettingsIcon },
+ template: /*html*/ `
+
+ Text only
+ Leading icon
+ Trailing icon
+ Full width
+ Continue with a deliberately long translated action label
+
+ `,
+ }),
+}
+
+export const InteractionStates: Story = {
+ render: () => ({
+ components: { Button },
+ template: /*html*/ `
+
+ Enabled
+ Disabled
+ Loading
+ Colored
+ Colored disabled
+ Outlined
+ Quiet
+
+ `,
+ }),
+}
+
+export const LinksAndIconButton: Story = {
+ render: () => ({
+ components: { ButtonLink, ExternalIcon, HeartIcon, IconButton },
+ template: /*html*/ `
+
+ Internal link
+
+ Modrinth
+
+ Disabled link
+
+
+
+
+
+ `,
+ }),
+}
diff --git a/packages/ui/src/stories/buttons/ButtonGroup.stories.ts b/packages/ui/src/stories/buttons/ButtonGroup.stories.ts
new file mode 100644
index 0000000000..3f234148c4
--- /dev/null
+++ b/packages/ui/src/stories/buttons/ButtonGroup.stories.ts
@@ -0,0 +1,82 @@
+import { PlayIcon, SettingsIcon, StopCircleIcon, TrashIcon } from '@modrinth/assets'
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import Button from '../../components/base/buttons/Button.vue'
+import ButtonGroup from '../../components/base/buttons/ButtonGroup.vue'
+import SplitButton from '../../components/base/buttons/SplitButton.vue'
+import type { OverflowMenuOption } from '../../components/base/buttons/types'
+
+const splitOptions: OverflowMenuOption[] = [
+ {
+ id: 'settings',
+ label: 'Server settings',
+ icon: SettingsIcon,
+ action: () => undefined,
+ },
+ { type: 'divider' },
+ {
+ id: 'delete',
+ label: 'Delete server',
+ icon: TrashIcon,
+ tone: 'red',
+ action: () => undefined,
+ },
+]
+
+const meta = {
+ title: 'Buttons/Button Group',
+ component: ButtonGroup,
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Joined: Story = {
+ render: () => ({
+ components: { Button, ButtonGroup },
+ template: /*html*/ `
+
+ Previous
+ Next
+
+ `,
+ }),
+}
+
+export const Split: Story = {
+ render: () => ({
+ components: { PlayIcon, SplitButton },
+ setup() {
+ return { splitOptions }
+ },
+ template: /*html*/ `
+
+ Start server
+
+ `,
+ }),
+}
+
+export const IndependentDisabledStates: Story = {
+ render: () => ({
+ components: { SplitButton, StopCircleIcon },
+ setup() {
+ return { splitOptions }
+ },
+ template: /*html*/ `
+
+
+ Primary disabled
+
+
+ Menu disabled
+
+
+ `,
+ }),
+}
diff --git a/packages/ui/src/stories/buttons/FileButton.stories.ts b/packages/ui/src/stories/buttons/FileButton.stories.ts
new file mode 100644
index 0000000000..2f07b27acc
--- /dev/null
+++ b/packages/ui/src/stories/buttons/FileButton.stories.ts
@@ -0,0 +1,61 @@
+import { UploadIcon } from '@modrinth/assets'
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import FileButton from '../../components/base/buttons/FileButton.vue'
+
+const meta = {
+ title: 'Buttons/File Button',
+ component: FileButton,
+ argTypes: {
+ type: {
+ control: 'select',
+ options: ['base', 'colored', 'outlined', 'quiet'],
+ },
+ size: {
+ control: 'select',
+ options: ['sm', 'md', 'lg', 'xl'],
+ },
+ color: {
+ control: 'select',
+ options: ['brand', 'red', 'orange', 'green', 'blue', 'purple', 'medal_promotion'],
+ },
+ },
+ args: {
+ prompt: 'Select file',
+ type: 'base',
+ size: 'md',
+ multiple: false,
+ disabled: false,
+ },
+ render: (args) => ({
+ components: { FileButton, UploadIcon },
+ setup() {
+ return { args }
+ },
+ template: /*html*/ `
+
+
+
+ `,
+ }),
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {}
+
+export const MultipleImages: Story = {
+ args: {
+ prompt: 'Select images',
+ accept: 'image/*',
+ multiple: true,
+ type: 'colored',
+ },
+}
+
+export const Disabled: Story = {
+ args: {
+ disabled: true,
+ },
+}
diff --git a/packages/ui/src/stories/buttons/TeleportOverflowMenu.stories.ts b/packages/ui/src/stories/buttons/TeleportOverflowMenu.stories.ts
new file mode 100644
index 0000000000..5ed21392f1
--- /dev/null
+++ b/packages/ui/src/stories/buttons/TeleportOverflowMenu.stories.ts
@@ -0,0 +1,104 @@
+import {
+ DownloadIcon,
+ ExternalIcon,
+ MoreVerticalIcon,
+ SettingsIcon,
+ TrashIcon,
+} from '@modrinth/assets'
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import TeleportOverflowMenu from '../../components/base/buttons/TeleportOverflowMenu.vue'
+import type { OverflowMenuOption } from '../../components/base/buttons/types'
+
+const options: OverflowMenuOption[] = [
+ {
+ id: 'download',
+ label: 'Download',
+ icon: DownloadIcon,
+ action: () => undefined,
+ },
+ {
+ id: 'settings',
+ label: 'Project settings',
+ icon: SettingsIcon,
+ type: 'link',
+ to: '/settings',
+ },
+ {
+ id: 'website',
+ label: 'Open website',
+ icon: ExternalIcon,
+ type: 'link',
+ href: 'https://modrinth.com',
+ target: '_blank',
+ },
+ {
+ id: 'unavailable',
+ label: 'Unavailable action',
+ disabled: true,
+ tooltip: 'This action is currently unavailable',
+ action: () => undefined,
+ },
+ { type: 'divider' },
+ {
+ id: 'delete',
+ label: 'Delete project',
+ icon: TrashIcon,
+ tone: 'red',
+ action: () => undefined,
+ },
+]
+
+const meta = {
+ title: 'Buttons/Teleport Overflow Menu',
+ component: TeleportOverflowMenu,
+ args: {
+ label: 'More actions',
+ options,
+ type: 'base',
+ size: 'md',
+ placement: 'bottom-end',
+ disabled: false,
+ hoverable: false,
+ },
+ render: (args) => ({
+ components: { MoreVerticalIcon, TeleportOverflowMenu },
+ setup() {
+ return { args }
+ },
+ template: /*html*/ `
+
+
+
+ `,
+ }),
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {}
+
+export const ColoredTrigger: Story = {
+ args: {
+ type: 'colored',
+ },
+}
+
+export const OutlinedTrigger: Story = {
+ args: {
+ type: 'outlined',
+ },
+}
+
+export const QuietTrigger: Story = {
+ args: {
+ type: 'quiet',
+ },
+}
+
+export const Hoverable: Story = {
+ args: {
+ hoverable: true,
+ },
+}
diff --git a/packages/ui/src/stories/buttons/TeleportPopoutMenu.stories.ts b/packages/ui/src/stories/buttons/TeleportPopoutMenu.stories.ts
new file mode 100644
index 0000000000..d6b183197c
--- /dev/null
+++ b/packages/ui/src/stories/buttons/TeleportPopoutMenu.stories.ts
@@ -0,0 +1,50 @@
+import { SettingsIcon } from '@modrinth/assets'
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import Button from '../../components/base/buttons/Button.vue'
+import TeleportPopoutMenu from '../../components/base/buttons/TeleportPopoutMenu.vue'
+
+const meta = {
+ title: 'Buttons/Teleport Popout Menu',
+ component: TeleportPopoutMenu,
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const ArbitraryContent: Story = {
+ render: () => ({
+ components: { Button, SettingsIcon, TeleportPopoutMenu },
+ template: /*html*/ `
+
+
+ Configure
+
+
+
+
+
+ Version name
+
+
+ Apply
+
+
+
+ `,
+ }),
+}
+
+export const IconTrigger: Story = {
+ render: () => ({
+ components: { SettingsIcon, TeleportPopoutMenu },
+ template: /*html*/ `
+
+
+
+ Arbitrary teleported content can live here.
+
+
+ `,
+ }),
+}
diff --git a/packages/ui/src/stories/instances/ContentCardTable.stories.ts b/packages/ui/src/stories/instances/ContentCardTable.stories.ts
index 486a4c909e..ca6ab56abf 100644
--- a/packages/ui/src/stories/instances/ContentCardTable.stories.ts
+++ b/packages/ui/src/stories/instances/ContentCardTable.stories.ts
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'
import { fn } from 'storybook/test'
import { onMounted, onUnmounted, ref } from 'vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import { Button, IconButton } from '../../components/base/buttons'
import ContentCardTable from '../../layouts/shared/content-tab/components/ContentCardTable.vue'
import type { ContentCardTableItem } from '../../layouts/shared/content-tab/types'
@@ -119,6 +119,7 @@ const etfItem: ContentCardTableItem = {
const importedModItem: ContentCardTableItem = {
id: 'imported123',
+ external: true,
project: {
id: 'imported123',
slug: 'import-mod',
@@ -539,7 +540,7 @@ export const InteractiveActions: Story = {
export const WithCustomItemButtons: Story = {
render: () => ({
- components: { ContentCardTable, ButtonStyled, EyeIcon, FolderOpenIcon, DownloadIcon },
+ components: { ContentCardTable, EyeIcon, FolderOpenIcon, DownloadIcon, Button, IconButton },
setup() {
return { items: sampleItems }
},
@@ -551,23 +552,17 @@ export const WithCustomItemButtons: Story = {
@delete="(id) => console.log('Delete', id)"
>
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
`,
@@ -582,15 +577,13 @@ export const WithEmptyState: Story = {
export const WithCustomEmptyState: Story = {
render: () => ({
- components: { ContentCardTable, ButtonStyled },
+ components: { ContentCardTable, Button, IconButton },
template: /*html*/ `
No mods installed
-
- Browse mods
-
+ Browse mods
@@ -781,7 +774,7 @@ export const WithOverflowMenu: Story = {
export const BulkActionsDemo: Story = {
render: () => ({
- components: { ContentCardTable, ButtonStyled },
+ components: { ContentCardTable, Button, IconButton },
setup() {
const items = ref([
{ ...sodiumItem, enabled: true },
@@ -825,15 +818,9 @@ export const BulkActionsDemo: Story = {
{{ selectedIds.length }} selected
-
- Enable
-
-
- Disable
-
-
- Delete
-
+ Enable
+ Disable
+ Delete
export const InstanceDependency: Story = {
render: () => ({
- components: { ButtonStyled, ContentDependencyWarningModal },
+ components: { ContentDependencyWarningModal, Button },
setup() {
const modalRef = ref | null>(null)
const deleted = ref(false)
@@ -186,9 +186,7 @@ export const InstanceDependency: Story = {
},
template: /* html */ `
-
- Delete dependency
-
+
Delete dependency
Dependency deletion confirmed
({
- components: { ButtonStyled, ContentDependencyWarningModal },
+ components: { ContentDependencyWarningModal, Button },
setup() {
const modalRef = ref | null>(null)
const deleted = ref(false)
@@ -227,9 +225,7 @@ export const ServerDependency: Story = {
},
template: /* html */ `
-
- Delete server dependency
-
+
Delete server dependency
Server dependency deletion confirmed
({
- components: { ButtonStyled, ContentDependencyWarningModal },
+ components: { ContentDependencyWarningModal, Button },
setup() {
const modalRef = ref | null>(null)
const deleted = ref(false)
@@ -267,9 +263,7 @@ export const BulkDependencies: Story = {
},
template: /* html */ `
-
- Delete selected dependencies
-
+
Delete selected dependencies
Bulk dependency deletion confirmed
-
-export default meta
-type Story = StoryObj
-
-// ============================================
-// All Types Overview
-// ============================================
-
-export const AllTypes: Story = {
- args: {
- project: fabulouslyOptimizedProject,
- },
- render: () => ({
- components: { ContentModpackCard },
- setup() {
- const cards = [
- {
- label: 'Full featured (all actions)',
- project: fabulouslyOptimizedProject,
- version: fabulouslyOptimizedVersion,
- owner: userOwner,
- categories: optimizationCategories,
- hasUpdate: true,
- hasContent: true,
- hasUnlink: true,
- },
- {
- label: 'With update available only',
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: cobblemonOwner,
- categories: cobblemonCategories,
- hasUpdate: true,
- },
- {
- label: 'With content button only',
- project: simplyOptimizedProject,
- version: fabulouslyOptimizedVersion,
- owner: userOwner,
- hasContent: true,
- },
- {
- label: 'Minimal (project only)',
- project: fabulouslyOptimizedProject,
- },
- {
- label: 'With version info only',
- project: cobblemonProject,
- version: cobblemonVersion,
- },
- {
- label: 'With owner only',
- project: simplyOptimizedProject,
- owner: userOwner,
- },
- {
- label: 'Disabled state',
- project: fabulouslyOptimizedProject,
- version: fabulouslyOptimizedVersion,
- owner: userOwner,
- categories: optimizationCategories,
- disabled: true,
- },
- ]
-
- return { cards }
- },
- template: /*html*/ `
-
-
- {{ card.label }}
- {} : undefined"
- @content="card.hasContent ? () => {} : undefined"
- @unlink="card.hasUnlink ? () => {} : undefined"
- />
-
-
- `,
- }),
-}
-
-// ============================================
-// Basic Stories
-// ============================================
-
-export const Default: Story = {
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- onUpdate: fn(),
- onContent: fn(),
- onUnlink: fn(),
- },
-}
-
-export const MinimalProjectOnly: Story = {
- args: {
- project: cobblemonProject,
- },
-}
-
-export const WithVersion: Story = {
- args: {
- project: simplyOptimizedProject,
- version: fabulouslyOptimizedVersion,
- },
-}
-
-export const WithUserOwner: Story = {
- args: {
- project: simplyOptimizedProject,
- version: fabulouslyOptimizedVersion,
- owner: userOwner,
- categories: [
- { name: 'Adventure', icon: 'adventure', project_type: 'modpack', header: 'categories' },
- ],
- },
-}
-
-export const WithOrganizationOwner: Story = {
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- },
-}
-
-// ============================================
-// Action Button Stories
-// ============================================
-
-export const WithUpdateButton: Story = {
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- onUpdate: fn(),
- },
-}
-
-export const WithContentButton: Story = {
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- onContent: fn(),
- },
-}
-
-export const WithUnlinkButton: Story = {
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- onUnlink: fn(),
- },
-}
-
-export const WithAllActions: Story = {
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- onUpdate: fn(),
- onContent: fn(),
- onUnlink: fn(),
- overflowOptions: [
- { id: 'view', action: () => console.log('View') },
- { id: 'settings', action: () => console.log('Settings') },
- { divider: true },
- { id: 'remove', action: () => console.log('Remove'), color: 'red' },
- ],
- },
-}
-
-// ============================================
-// State Stories
-// ============================================
-
-export const Disabled: Story = {
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- disabled: true,
- },
-}
-
-export const LongTitle: Story = {
- args: {
- project: {
- ...cobblemonProject,
- title: 'Super Long Modpack Title That Should Display Properly On All Screen Sizes',
- description:
- 'This is an extremely long description that should wrap properly and not break the layout. It contains lots of information about what this modpack includes and what makes it special compared to other modpacks available on the platform.',
- },
- version: cobblemonVersion,
- owner: {
- ...userOwner,
- name: 'Really Long Organization Name Studios',
- },
- categories: [
- { name: 'Adventure', icon: 'adventure', project_type: 'modpack', header: 'categories' },
- { name: 'Technology', icon: 'technology', project_type: 'modpack', header: 'categories' },
- { name: 'Magic', icon: 'magic', project_type: 'modpack', header: 'categories' },
- { name: 'Exploration', icon: 'exploration', project_type: 'modpack', header: 'categories' },
- { name: 'Multiplayer', icon: 'multiplayer', project_type: 'modpack', header: 'categories' },
- ],
- onUpdate: fn(),
- onContent: fn(),
- },
-}
-
-export const NoDescription: Story = {
- args: {
- project: {
- ...cobblemonProject,
- description: undefined,
- },
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- },
-}
-
-export const NoStats: Story = {
- args: {
- project: {
- ...cobblemonProject,
- downloads: undefined,
- followers: undefined,
- },
- version: cobblemonVersion,
- owner: userOwner,
- },
-}
-
-// ============================================
-// Categories Stories
-// ============================================
-
-export const WithClickableCategories: Story = {
- render: (args) => ({
- components: { ContentModpackCard },
- setup() {
- const clickedCategory = ref(null)
- const categories: ContentModpackCardCategory[] = [
- {
- name: 'Adventure',
- icon: 'adventure',
- project_type: 'modpack',
- header: 'categories',
- action: () => (clickedCategory.value = 'Adventure'),
- },
- {
- name: 'Lightweight',
- icon: 'lightweight',
- project_type: 'modpack',
- header: 'categories',
- action: () => (clickedCategory.value = 'Lightweight'),
- },
- {
- name: 'Multiplayer',
- icon: 'multiplayer',
- project_type: 'modpack',
- header: 'categories',
- action: () => (clickedCategory.value = 'Multiplayer'),
- },
- ]
- return { args, categories, clickedCategory }
- },
- template: /*html*/ `
-
-
-
- Clicked category: {{ clickedCategory || 'None' }}
-
-
- `,
- }),
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- },
-}
-
-// ============================================
-// Overflow Menu Stories
-// ============================================
-
-export const WithOverflowMenu: Story = {
- render: (args) => ({
- components: { ContentModpackCard },
- setup() {
- return { args }
- },
- template: /*html*/ `
-
- View on Modrinth
- Settings
- Remove modpack
-
- `,
- }),
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- overflowOptions: [
- { id: 'view', action: () => console.log('View') },
- { id: 'settings', action: () => console.log('Settings') },
- { divider: true },
- { id: 'remove', action: () => console.log('Remove'), color: 'red' },
- ],
- },
-}
-
-// ============================================
-// Interactive Stories
-// ============================================
-
-export const WithContentModal: Story = {
- args: {
- project: cobblemonProject,
- },
- render: () => ({
- components: { ContentModpackCard, NewModal, ContentCardItem },
- setup() {
- const modalRef = ref | null>(null)
- const modpackContent = [
- {
- project: {
- id: '1',
- slug: 'sodium',
- title: 'Sodium',
- icon_url:
- 'https://cdn.modrinth.com/data/AANobbMI/295862f4724dc3f78df3447ad6072b2dcd3ef0c9_96.webp',
- },
- version: { id: 'v1', version_number: '0.8.2', file_name: 'sodium-fabric-0.8.2.jar' },
- },
- {
- project: {
- id: '2',
- slug: 'modmenu',
- title: 'Mod Menu',
- icon_url:
- 'https://cdn.modrinth.com/data/mOgUt4GM/5a20ed1450a0e1e79a1fe04e61bb4e5878bf1d20.png',
- },
- version: { id: 'v2', version_number: '16.0.0', file_name: 'modmenu-16.0.0.jar' },
- },
- {
- project: {
- id: '3',
- slug: 'fabric-api',
- title: 'Fabric API',
- icon_url: 'https://cdn.modrinth.com/data/P7dR8mSH/icon.png',
- },
- version: { id: 'v3', version_number: '0.141.3', file_name: 'fabric-api-0.141.3.jar' },
- },
- ]
-
- return {
- cobblemonProject,
- cobblemonVersion,
- userOwner,
- optimizationCategories,
- modalRef,
- modpackContent,
- }
- },
- template: /*html*/ `
-
-
alert('Update clicked')"
- />
-
-
-
-
-
-
- `,
- }),
-}
-
-// ============================================
-// Responsive Stories
-// ============================================
-
-export const ResponsiveView: Story = {
- args: {
- project: cobblemonProject,
- },
- render: () => ({
- components: { ContentModpackCard },
- setup() {
- return {
- cobblemonProject,
- cobblemonVersion,
- userOwner,
- optimizationCategories,
- }
- },
- template: /*html*/ `
-
-
-
Desktop (full width)
-
- {}"
- @content="() => {}"
- @unlink="() => {}"
- />
-
-
-
-
Mobile (<640px)
-
- {}"
- @content="() => {}"
- />
-
-
-
- `,
- }),
-}
-
-// ============================================
-// Edge Cases
-// ============================================
-
-export const NoIcon: Story = {
- args: {
- project: {
- ...cobblemonProject,
- icon_url: undefined,
- },
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- },
-}
-
-export const NoOwnerAvatar: Story = {
- args: {
- project: cobblemonProject,
- version: cobblemonVersion,
- owner: {
- ...userOwner,
- avatar_url: undefined,
- },
- categories: optimizationCategories,
- },
-}
-
-export const HighDownloadCounts: Story = {
- args: {
- project: {
- ...cobblemonProject,
- downloads: 1234567890,
- followers: 9876543,
- },
- version: cobblemonVersion,
- owner: userOwner,
- categories: optimizationCategories,
- },
-}
diff --git a/packages/ui/src/stories/instances/ContentUpdaterModal.stories.ts b/packages/ui/src/stories/instances/ContentUpdaterModal.stories.ts
index 909463c837..129f602d60 100644
--- a/packages/ui/src/stories/instances/ContentUpdaterModal.stories.ts
+++ b/packages/ui/src/stories/instances/ContentUpdaterModal.stories.ts
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite'
import { fn } from 'storybook/test'
import { ref } from 'vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import { Button } from '../../components/base/buttons'
import ContentUpdaterModal from '../../layouts/shared/content-tab/components/modals/content-updater-modal/index.vue'
// Real version data from Modrinth API - Sodium (mod)
@@ -265,7 +265,7 @@ type Story = StoryObj
export const ModExample: Story = {
render: (args) => ({
- components: { ContentUpdaterModal, ButtonStyled },
+ components: { ContentUpdaterModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show()
@@ -277,9 +277,7 @@ export const ModExample: Story = {
},
template: /*html*/ `
-
- Update Sodium
-
+
Update Sodium
({
- components: { ContentUpdaterModal, ButtonStyled },
+ components: { ContentUpdaterModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show()
@@ -318,9 +316,7 @@ export const ModpackExample: Story = {
},
template: /*html*/ `
-
- Update Cobblemon Modpack
-
+
Update Cobblemon Modpack
({
- components: { ContentUpdaterModal, ButtonStyled },
+ components: { ContentUpdaterModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show()
@@ -355,9 +351,7 @@ export const WithIncompatibleVersions: Story = {
},
template: /*html*/ `
-
- Update (Shows Incompatible)
-
+
Update (Shows Incompatible)
({
- components: { ContentUpdaterModal, ButtonStyled },
+ components: { ContentUpdaterModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show()
@@ -389,9 +383,7 @@ export const AllVersionTypes: Story = {
},
template: /*html*/ `
-
- View All Version Types
-
+
View All Version Types
({
+ components: { story },
+ template: '
',
+ }),
+ ],
+ args: {
+ showViewContent: true,
+ showSettings: true,
+ showPrimaryAction: true,
+ onViewContent: fn(),
+ onSettings: fn(),
+ onPrimaryAction: fn(),
+ },
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Modpack: Story = {
+ args: {
+ data: modpackCard,
+ },
+}
+
+export const Server: Story = {
+ args: {
+ data: serverCard,
+ },
+}
+
+export const SharedInstance: Story = {
+ args: {
+ data: sharedInstanceCard,
+ },
+}
+
+export const NarrowWidth: Story = {
+ args: {
+ data: serverCard,
+ },
+ render: (args) => ({
+ components: { ManagedContentCard },
+ setup: () => ({ args }),
+ template: /*html*/ `
+
+
+
+ `,
+ }),
+}
+
+export const LongManagerName: Story = {
+ args: {
+ data: {
+ ...sharedInstanceCard,
+ manager: {
+ ...sharedInstanceCard.manager,
+ name: 'A shared-instance manager with a very long display name',
+ },
+ },
+ },
+}
+
+export const MissingManagerIcon: Story = {
+ args: {
+ data: {
+ ...serverCard,
+ manager: {
+ name: 'Modrinth SMP',
+ },
+ },
+ },
+}
+
+export const ImportedModpack: Story = {
+ args: {
+ data: {
+ kind: 'modpack',
+ manager: {
+ name: 'Imported from Prism Launcher',
+ },
+ summary: figmaSummary,
+ },
+ showPrimaryAction: false,
+ },
+}
+
+export const LoadingCounts: Story = {
+ args: {
+ data: {
+ ...modpackCard,
+ summary: undefined,
+ },
+ },
+}
+
+export const ZeroContent: Story = {
+ args: {
+ data: {
+ ...sharedInstanceCard,
+ summary: [],
+ updateAvailable: false,
+ },
+ showPrimaryAction: false,
+ },
+}
+
+export const ApplyingUpdate: Story = {
+ args: {
+ data: serverCard,
+ disabled: true,
+ disabledText: 'Updating...',
+ },
+}
+
+export const AccountLocked: Story = {
+ args: {
+ data: {
+ ...sharedInstanceCard,
+ updateAvailable: false,
+ },
+ showPrimaryAction: false,
+ },
+}
+
+export const EveryContentType: Story = {
+ args: {
+ data: {
+ ...serverCard,
+ summary: [
+ { type: 'mod', count: 52 },
+ { type: 'plugin', count: 4 },
+ { type: 'datapack', count: 3 },
+ { type: 'resourcepack', count: 2 },
+ { type: 'shader', count: 1 },
+ ],
+ },
+ },
+}
diff --git a/packages/ui/src/stories/instances/ModpackContentModal.stories.ts b/packages/ui/src/stories/instances/ManagedContentModal.stories.ts
similarity index 73%
rename from packages/ui/src/stories/instances/ModpackContentModal.stories.ts
rename to packages/ui/src/stories/instances/ManagedContentModal.stories.ts
index d86dafbe05..40fd718614 100644
--- a/packages/ui/src/stories/instances/ModpackContentModal.stories.ts
+++ b/packages/ui/src/stories/instances/ManagedContentModal.stories.ts
@@ -1,11 +1,10 @@
import type { Meta, StoryObj } from '@storybook/vue3-vite'
import { ref } from 'vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
-import ModpackContentModal from '../../layouts/shared/content-tab/components/modals/ModpackContentModal.vue'
+import { Button } from '../../components/base/buttons'
+import ManagedContentModal from '../../layouts/shared/content-tab/components/managed-content-modal/index.vue'
import type { ContentItem } from '../../layouts/shared/content-tab/types'
-// Sample modpack content items (representing mods included in a modpack)
const sodiumItem: ContentItem = {
file_name: 'sodium-fabric-0.8.2+mc1.21.1.jar',
file_path: '',
@@ -201,7 +200,6 @@ const entityTextureFeaturesItem: ContentItem = {
update_version_id: null,
}
-// Shader pack item
const complementaryShaderItem: ContentItem = {
file_name: 'ComplementaryReimagined_r5.3.zip',
file_path: '',
@@ -256,7 +254,6 @@ const bslShaderItem: ContentItem = {
update_version_id: null,
}
-// Resource pack items
const faithfulItem: ContentItem = {
file_name: 'Faithful 32x - 1.21.zip',
file_path: '',
@@ -339,7 +336,6 @@ const stayTrueItem: ContentItem = {
update_version_id: null,
}
-// Mixed content (mods + shaders + resource packs)
const mixedModpackContent: ContentItem[] = [
sodiumItem,
lithiumItem,
@@ -355,7 +351,6 @@ const mixedModpackContent: ContentItem[] = [
stayTrueItem,
]
-// Mods only
const modsOnlyContent: ContentItem[] = [
sodiumItem,
lithiumItem,
@@ -366,7 +361,6 @@ const modsOnlyContent: ContentItem[] = [
entityTextureFeaturesItem,
]
-// Large modpack content (40+ items for testing scrolling)
const largeModpackContent: ContentItem[] = [
...mixedModpackContent,
...Array.from({ length: 35 }, (_, i) => ({
@@ -393,37 +387,31 @@ const largeModpackContent: ContentItem[] = [
]
const meta = {
- title: 'Instances/ModpackContentModal',
- component: ModpackContentModal,
+ title: 'Instances/ManagedContentModal',
+ component: ManagedContentModal,
parameters: {
layout: 'centered',
},
-} satisfies Meta
+} satisfies Meta
export default meta
type Story = StoryObj
-// ============================================
-// Basic Examples
-// ============================================
-
export const Default: Story = {
render: () => ({
- components: { ModpackContentModal, ButtonStyled },
+ components: { ManagedContentModal, Button },
setup() {
- const modalRef = ref | null>(null)
+ const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show(mixedModpackContent)
return { modalRef, openModal }
},
template: /*html*/ `
-
- View Modpack Content (Mixed)
-
- View Modpack Content (Mixed)
+
`,
@@ -432,35 +420,28 @@ export const Default: Story = {
export const ModsOnly: Story = {
render: () => ({
- components: { ModpackContentModal, ButtonStyled },
+ components: { ManagedContentModal, Button },
setup() {
- const modalRef = ref | null>(null)
+ const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show(modsOnlyContent)
return { modalRef, openModal }
},
template: /*html*/ `
-
- View Modpack Content (Mods Only)
-
-
+ View Modpack Content (Mods Only)
+
`,
}),
}
-// ============================================
-// Loading State
-// ============================================
-
export const LoadingState: Story = {
render: () => ({
- components: { ModpackContentModal, ButtonStyled },
+ components: { ManagedContentModal, Button },
setup() {
- const modalRef = ref | null>(null)
+ const modalRef = ref | null>(null)
const openModal = () => {
modalRef.value?.showLoading()
- // Simulate loading delay
setTimeout(() => {
modalRef.value?.show(mixedModpackContent)
}, 2000)
@@ -469,78 +450,60 @@ export const LoadingState: Story = {
},
template: /*html*/ `
-
- View Content (With Loading)
-
- View Content (With Loading)
+
`,
}),
}
-// ============================================
-// Empty State
-// ============================================
-
export const EmptyContent: Story = {
render: () => ({
- components: { ModpackContentModal, ButtonStyled },
+ components: { ManagedContentModal, Button },
setup() {
- const modalRef = ref | null>(null)
+ const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show([])
return { modalRef, openModal }
},
template: /*html*/ `
-
- View Empty Modpack
-
-
+ View Empty Modpack
+
`,
}),
}
-// ============================================
-// Large Content List
-// ============================================
-
export const LargeModpack: Story = {
render: () => ({
- components: { ModpackContentModal, ButtonStyled },
+ components: { ManagedContentModal, Button },
setup() {
- const modalRef = ref | null>(null)
+ const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show(largeModpackContent)
return { modalRef, openModal }
},
template: /*html*/ `
-
- View Large Modpack (47 items)
-
- View Large Modpack (47 items)
+
`,
}),
}
-// ============================================
-// Search Functionality
-// ============================================
-
export const SearchDemo: Story = {
render: () => ({
- components: { ModpackContentModal, ButtonStyled },
+ components: { ManagedContentModal, Button },
setup() {
- const modalRef = ref | null>(null)
+ const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show(mixedModpackContent)
return { modalRef, openModal }
},
@@ -549,24 +512,18 @@ export const SearchDemo: Story = {
Click the button and try searching for "sodium", "shader", or "faithful" to test the search functionality.
-
- Test Search
-
-
+ Test Search
+
`,
}),
}
-// ============================================
-// Filter Demo
-// ============================================
-
export const FilterDemo: Story = {
render: () => ({
- components: { ModpackContentModal, ButtonStyled },
+ components: { ManagedContentModal, Button },
setup() {
- const modalRef = ref | null>(null)
+ const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show(mixedModpackContent)
return { modalRef, openModal }
},
@@ -575,25 +532,18 @@ export const FilterDemo: Story = {
Click the button and try the filter chips (Mods, Shaders, Resource Packs) to filter content by type.
-
- Test Filters
-
-
+ Test Filters
+
`,
}),
}
-// ============================================
-// Mixed Owner Types
-// ============================================
-
export const MixedOwnerTypes: Story = {
render: () => ({
- components: { ModpackContentModal, ButtonStyled },
+ components: { ManagedContentModal, Button },
setup() {
- const modalRef = ref | null>(null)
- // Mix of user and organization owners
+ const modalRef = ref | null>(null)
const mixedContent = [
sodiumItem, // User owner
fabricApiItem, // Organization owner
@@ -608,10 +558,8 @@ export const MixedOwnerTypes: Story = {
Shows content with different owner types: users (circular avatar) and organizations (rounded + icon).
-
- View Mixed Owners
-
-
+ View Mixed Owners
+
`,
}),
diff --git a/packages/ui/src/stories/modal/ConfirmLeaveModal.stories.ts b/packages/ui/src/stories/modal/ConfirmLeaveModal.stories.ts
index 9509d27ac1..ac33eb8886 100644
--- a/packages/ui/src/stories/modal/ConfirmLeaveModal.stories.ts
+++ b/packages/ui/src/stories/modal/ConfirmLeaveModal.stories.ts
@@ -1,7 +1,7 @@
import type { StoryObj } from '@storybook/vue3-vite'
import { ref } from 'vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import { Button } from '../../components/base/buttons'
import ConfirmLeaveModal from '../../components/modal/ConfirmLeaveModal.vue'
const meta = {
@@ -14,7 +14,7 @@ type Story = StoryObj
export const Default: Story = {
render: () => ({
- components: { ConfirmLeaveModal, ButtonStyled },
+ components: { ConfirmLeaveModal, Button },
setup() {
const modalRef = ref | null>(null)
const result = ref('')
@@ -27,9 +27,7 @@ export const Default: Story = {
},
template: /* html */ `
-
- Trigger Leave Confirmation
-
+
Trigger Leave Confirmation
{{ result }}
@@ -39,7 +37,7 @@ export const Default: Story = {
export const CustomMessages: Story = {
render: () => ({
- components: { ConfirmLeaveModal, ButtonStyled },
+ components: { ConfirmLeaveModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.prompt()
@@ -47,9 +45,7 @@ export const CustomMessages: Story = {
},
template: /* html */ `
-
- Discard Draft?
-
+
Discard Draft?
({
- components: { ConfirmLeaveModal, ButtonStyled },
+ components: { ConfirmLeaveModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.prompt()
@@ -73,9 +69,7 @@ export const WarningAdmonition: Story = {
},
template: /* html */ `
-
- Open Warning Variant
-
+
Open Warning Variant
export const Default: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { NewModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show()
@@ -22,9 +22,7 @@ export const Default: Story = {
},
template: `
-
- Open Modal
-
+
Open Modal
This is the modal content.
You can put any content here.
@@ -36,7 +34,7 @@ export const Default: Story = {
export const WithActions: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { NewModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => modalRef.value?.show()
@@ -44,19 +42,13 @@ export const WithActions: Story = {
},
template: `
-
- Open Modal with Actions
-
+
Open Modal with Actions
Are you sure you want to proceed with this action?
-
- Cancel
-
-
- Confirm
-
+ Cancel
+ Confirm
@@ -67,7 +59,7 @@ export const WithActions: Story = {
export const DangerFade: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { NewModal, Button },
setup() {
const modalRef = ref
| null>(null)
const openModal = () => modalRef.value?.show()
@@ -75,19 +67,13 @@ export const DangerFade: Story = {
},
template: `
-
- Open Danger Modal
-
+
Open Danger Modal
Are you sure you want to delete this item? This action cannot be undone.
-
- Cancel
-
-
- Delete
-
+ Cancel
+ Delete
@@ -98,7 +84,7 @@ export const DangerFade: Story = {
export const WarningFade: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { NewModal, Button },
setup() {
const modalRef = ref
| null>(null)
const openModal = () => modalRef.value?.show()
@@ -106,19 +92,13 @@ export const WarningFade: Story = {
},
template: `
-
- Open Warning Modal
-
+
Open Warning Modal
This action may have unintended consequences. Please review before proceeding.
-
- Cancel
-
-
- Proceed
-
+ Cancel
+ Proceed
@@ -129,7 +109,7 @@ export const WarningFade: Story = {
export const Scrollable: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { NewModal, Button },
setup() {
const modalRef = ref
| null>(null)
const openModal = () => modalRef.value?.show()
@@ -137,9 +117,7 @@ export const Scrollable: Story = {
},
template: `
-
- Open Scrollable Modal
-
+
Open Scrollable Modal
@@ -148,9 +126,7 @@ export const Scrollable: Story = {
-
- Close
-
+ Close
@@ -161,7 +137,7 @@ export const Scrollable: Story = {
export const MergedHeader: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { NewModal, Button },
setup() {
const modalRef = ref
| null>(null)
const openModal = () => modalRef.value?.show()
@@ -169,9 +145,7 @@ export const MergedHeader: Story = {
},
template: `
-
- Open Modal (Merged Header)
-
+
Open Modal (Merged Header)
Custom Header Area
@@ -185,7 +159,7 @@ export const MergedHeader: Story = {
export const NotClosable: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { NewModal, Button },
setup() {
const modalRef = ref
| null>(null)
const openModal = () => modalRef.value?.show()
@@ -193,17 +167,13 @@ export const NotClosable: Story = {
},
template: `
-
- Open Non-Closable Modal
-
+
Open Non-Closable Modal
This modal cannot be closed by clicking outside or pressing escape.
Only the action button can close it.
-
- I understand, close
-
+ I understand, close
@@ -214,7 +184,7 @@ export const NotClosable: Story = {
export const NoPadding: Story = {
render: () => ({
- components: { NewModal, ButtonStyled },
+ components: { NewModal, Button },
setup() {
const modalRef = ref
| null>(null)
const openModal = () => modalRef.value?.show()
@@ -222,16 +192,12 @@ export const NoPadding: Story = {
},
template: `
-
- Open Modal (No Padding)
-
+
Open Modal (No Padding)
This modal has no default padding on the content area.
-
- Close
-
+ Close
diff --git a/packages/ui/src/stories/modal/ShareModal.stories.ts b/packages/ui/src/stories/modal/ShareModal.stories.ts
index 10b07701f4..28c81af2ae 100644
--- a/packages/ui/src/stories/modal/ShareModal.stories.ts
+++ b/packages/ui/src/stories/modal/ShareModal.stories.ts
@@ -1,7 +1,7 @@
import type { StoryObj } from '@storybook/vue3-vite'
import { ref } from 'vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import { Button } from '../../components/base/buttons'
import ShareModal from '../../components/modal/ShareModal.vue'
const meta = {
@@ -20,7 +20,7 @@ export const LinkShare: Story = {
link: true,
},
render: (args) => ({
- components: { ShareModal, ButtonStyled },
+ components: { ShareModal, Button },
setup() {
const modalRef = ref
| null>(null)
const openModal = () => {
@@ -30,9 +30,7 @@ export const LinkShare: Story = {
},
template: `
-
- Open Link Share Modal
-
+ Open Link Share Modal
`,
@@ -47,7 +45,7 @@ export const TextShare: Story = {
link: false,
},
render: (args) => ({
- components: { ShareModal, ButtonStyled },
+ components: { ShareModal, Button },
setup() {
const modalRef = ref | null>(null)
const openModal = () => {
@@ -57,9 +55,7 @@ export const TextShare: Story = {
},
template: `
-
- Open Text Share Modal
-
+ Open Text Share Modal
`,
diff --git a/packages/ui/src/stories/modal/TabbedModal.stories.ts b/packages/ui/src/stories/modal/TabbedModal.stories.ts
index aee894f212..5d85e192ef 100644
--- a/packages/ui/src/stories/modal/TabbedModal.stories.ts
+++ b/packages/ui/src/stories/modal/TabbedModal.stories.ts
@@ -14,7 +14,7 @@ import {
import type { StoryObj } from '@storybook/vue3-vite'
import { defineComponent, h, ref } from 'vue'
-import ButtonStyled from '../../components/base/ButtonStyled.vue'
+import { Button } from '../../components/base/buttons'
import UnsavedChangesPopup from '../../components/base/UnsavedChangesPopup.vue'
import TabbedModal from '../../components/modal/TabbedModal.vue'
@@ -42,7 +42,7 @@ export default meta
export const Default: StoryObj = {
render: () => ({
- components: { TabbedModal, ButtonStyled },
+ components: { TabbedModal, Button },
setup() {
const modalRef = ref | null>(null)
const tabs = [
@@ -66,9 +66,7 @@ export const Default: StoryObj = {
},
template: /* html */ `
-
- Open Tabbed Modal
-
+ Open Tabbed Modal
`,
@@ -77,7 +75,7 @@ export const Default: StoryObj = {
export const WithTitleSlot: StoryObj = {
render: () => ({
- components: { TabbedModal, ButtonStyled, SettingsIcon },
+ components: { TabbedModal, SettingsIcon, Button },
setup() {
const modalRef = ref | null>(null)
const tabs = [
@@ -96,9 +94,7 @@ export const WithTitleSlot: StoryObj = {
},
template: /* html */ `
-
- Open with Title Slot
-
+ Open with Title Slot