Compare commits

...
Author SHA1 Message Date
François-X. T. 72e528b33f Revert "Changelog"
This reverts commit 0c1c7e2fe8.
2026-03-24 16:36:42 -04:00
François-X. T. 0c1c7e2fe8 Changelog 2026-03-24 16:33:09 -04:00
François-X. T. cf16939519 Add Java 25, handle new version format 2026-03-24 16:28:37 -04:00
Modrinth BotandGitHub f9004dc2f6 New translations from Crowdin (main) (#5638) 2026-03-23 23:44:53 +00:00
Calum H.andGitHub cf7c77700a fix: bugs with changelog collect (#5648) 2026-03-23 20:39:40 +00:00
Calum H.andGitHub c09f7fd5e6 devex: changelog system (#5309)
* devex: changelog system

* feat: changelog CIs

* feat: web alias for platform + hosting

* feat: upload binaries to gh release

* feat: improve copy text

* fix: release workflow

* fix: changelog CIs + PR health check comment

* fix: action

* fix: comment style

* fix: comment

* fix: remove health

* fix: deploy use Modrinth bot machine account

* feat: new system

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

* fix: server

* fix: lint

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

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

* better normalization of title/author names for indexing

* replace println with warn

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

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

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

* fix: ssr

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

* fix use head referencing undefined

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

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

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

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

* fix: vue-router resolve workaround

* fix: show disable/enable btns same time

* fix: remove mr-2 on toggle

* fix: type errors + add ModpackAlreadyInstalledModal

* fix: bulk actions + overflow menu hitting ad container

* fix: responsiveness of ContentSelectionBar

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

* fix: lint

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

* move plan names to common messages

* unknown -> plan-unknown

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

* fix: browse content bug

Fixes #5570

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

Fixes #5602

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

Fixes #5598

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

Fixes #5600

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

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

* fix: billing page api-client ditch useBaseFetch

* fix: remove org icon from project card items

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

* Move increment to top of function

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

---------

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

* apply `prettier`

---------

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

This reverts commit f4f33db701.

* fix: bugs

* fix: analytics

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

* Set team_members to unknown[]

* Additional fixes after merge

* Additional translations

* Replace "IP" with "server address"

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

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

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

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

* style: run pnpm run fix on affected files

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

* fix: guard project middleware on client

* fix: lint

---------

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

* refactor report list and report view

* refactor organization page to use tanstack query

* fix types

* refactor collection page and include proper loading state

* fix followed projects proper loading state

* fix 404 handling

* fix organization loading and 404 states

* pnpm prepr

* refactor: remove useAsyncData on newsletter button

* refactor: remove useAsyncData on auth globals fetch

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

* refactor: user page to remove useAsyncData

* pnpm prepr

* fix reports pages

* fix notifications page

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

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

* fix stale data after removing organization from project

* pnpm prepr

* fix news erroring in build

* fix: project page loads header only after content

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

* fix: start swapping useBaseFetch usages to api-client

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

This reverts commit 3df3fab11d.

* fix: remove debug logging

* fix: lint

---------

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

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

* feat: DI stability

* fix: lint

* fix: play server project deep link

* switch toggle icons

* pnpm prepr

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
2026-03-16 17:10:55 +00:00
295 changed files with 28141 additions and 5120 deletions
+14 -152
View File
@@ -1,156 +1,18 @@
# Adding a New API Module
---
name: api-module
description: Add a new API endpoint module to packages/api-client from an OpenAPI schema. Use when adding new backend endpoints, creating API client modules, or when an openapi.yml is provided.
argument-hint: <path-to-openapi.yml>
---
How to add a new API endpoint module to `packages/api-client`.
Refer to the standard: @standards/frontend/ADDING_API_MODULES.md
## Steps
### 1. Define types in the module's `types.ts`
Types must match 1:1 with the backend API response. Do not reshape, rename, or omit fields.
Add to an existing namespace or create a new one:
```ts
// modules/labrinth/types.ts (existing namespace)
export namespace Labrinth {
export namespace MyDomain {
export namespace v3 {
export type Thing = {
id: string
name: string
created: string
// ... matches API response exactly
}
export type CreateThingRequest = {
name: string
}
}
}
}
```
For a new API service, create `modules/<service>/types.ts` with a new top-level namespace and re-export it from `modules/types.ts`.
### 2. Create the module class
Create `modules/<api>/<domain>/v<N>.ts`:
```ts
// modules/labrinth/things/v3.ts
import { AbstractModule } from '../../../core/abstract-module'
import type { Labrinth } from '../types'
export class LabrinthThingsV3Module extends AbstractModule {
public getModuleID(): string {
return 'labrinth_things_v3'
}
public async get(id: string): Promise<Labrinth.MyDomain.v3.Thing> {
return this.client.request<Labrinth.MyDomain.v3.Thing>(`/thing/${id}`, {
api: 'labrinth',
version: 3,
method: 'GET',
})
}
public async create(data: Labrinth.MyDomain.v3.CreateThingRequest): Promise<Labrinth.MyDomain.v3.Thing> {
return this.client.request<Labrinth.MyDomain.v3.Thing>(`/thing`, {
api: 'labrinth',
version: 3,
method: 'POST',
body: data,
})
}
public async delete(id: string): Promise<void> {
return this.client.request(`/thing/${id}`, {
api: 'labrinth',
version: 3,
method: 'DELETE',
})
}
}
```
#### Request options
| Field | Values | Purpose |
|-------|--------|---------|
| `api` | `'labrinth'`, `'archon'`, or a full URL | Which base URL to use |
| `version` | `2`, `3`, `'internal'`, `'modrinth/v0'`, etc. | URL version segment |
| `method` | `'GET'`, `'POST'`, `'PUT'`, `'PATCH'`, `'DELETE'` | HTTP method |
| `body` | object | JSON request body |
| `params` | `Record<string, string>` | Query parameters |
| `skipAuth` | `boolean` | Skip auth feature for this request |
| `useNodeAuth` | `boolean` | Use node-level auth (kyros) |
| `timeout` | `number` | Request timeout in ms |
| `retry` | `boolean \| number` | Override retry behavior |
#### For uploads
Return an `UploadHandle` instead of a `Promise`:
```ts
public uploadThing(id: string, file: File): UploadHandle<void> {
return this.client.upload<void>(`/thing/${id}/file`, {
api: 'labrinth',
version: 3,
file,
})
}
// Or with FormData for multipart:
public createWithFiles(data: CreateRequest, files: File[]): UploadHandle<Thing> {
const formData = new FormData()
formData.append('data', JSON.stringify(data))
files.forEach((f, i) => formData.append(`file-${i}`, f, f.name))
return this.client.upload<Thing>(`/thing`, {
api: 'labrinth',
version: 3,
formData,
timeout: 60 * 5 * 1000, // longer timeout for uploads
})
}
```
### 3. Register in the MODULE_REGISTRY
Add to `modules/index.ts`:
```ts
import { LabrinthThingsV3Module } from './labrinth/things/v3'
export const MODULE_REGISTRY = {
// ... existing modules
labrinth_things_v3: LabrinthThingsV3Module,
} as const
```
The naming convention is `<api>_<domain>_<version>`. This flat key gets transformed into nested access: `client.labrinth.things_v3`.
### 4. Export types
If you added to an existing namespace, types are already re-exported. If you created a new `types.ts`, add it to `modules/types.ts`:
```ts
export * from './<service>/types'
```
## Naming Conventions
| Convention | Example |
|-----------|---------|
| Module class | `LabrinthThingsV3Module``{Api}{Domain}V{N}Module` |
| Module ID | `labrinth_things_v3``{api}_{domain}_v{n}` |
| Type namespace | `Labrinth.MyDomain.v3.Thing` |
| File path | `modules/labrinth/things/v3.ts` |
## Key Files
- `src/core/abstract-module.ts` — base class all modules extend
- `src/core/abstract-client.ts``request()` and `upload()` methods
- `src/modules/index.ts``MODULE_REGISTRY` and `buildModuleStructure()`
- `src/modules/<api>/types.ts` — type definitions per API
- `src/types/upload.ts``UploadHandle`, `UploadProgress`, `UploadRequestOptions`
1. **Read the OpenAPI schema** at `$ARGUMENTS` — identify the endpoints, request/response shapes, and path parameters.
2. **Read the standard above** for naming conventions, type rules, and the module registration pattern.
3. **Determine the service and version** — the URL path prefix tells you which service directory and version namespace to use (e.g. `/v3/projects``labrinth/v3/`).
4. **Define types in `types.ts`** — types must match the API response 1:1. Use the OpenAPI schema as the source of truth. Do not reshape or rename fields.
5. **Create the module class** — extend `BaseModule`, implement each endpoint as a method. Use the correct HTTP verb and request options pattern from the standard.
6. **Register in `MODULE_REGISTRY`** — add the module entry so it's auto-instantiated on the client.
7. **Export types** from the service's barrel `index.ts`.
8. **Verify** — check that the module compiles and the types are accessible from `@modrinth/api-client`.
+22 -141
View File
@@ -1,144 +1,25 @@
# Cross-Platform Page System
---
name: cross-platform-pages
description: Convert a page to the cross-platform page system so it works in both the website and the desktop app. Use when moving a page into packages/ui/src/layouts/, creating shared or wrapped layouts, or setting up DI contracts for platform abstraction.
argument-hint: <path-to-page>
---
When a page needs to exist in both the Modrinth App (`apps/app-frontend`) and the Modrinth Website (`apps/frontend`), use the cross-platform page system.
Refer to the standards: @standards/frontend/CROSS_PLATFORM_PAGES.md and @standards/frontend/DEPENDENCY_INJECTION.md
## How It Works
## Steps
1. **Pages live as Vue SFCs in `packages/ui`** — either in `src/pages/` or `src/layout/` (if `src/pages/` doesn't exist, it's been renamed to `src/layout/`).
2. **Platform-dependent data flows via DI** — the app uses Tauri `invoke` commands, the website uses `api-client` or the legacy `useBaseFetch` composable. The shared page never knows which. See the `dependency-injection` skill for full DI docs.
3. **Non-platform-dependent data flows via props** — if data doesn't change based on _how_ it's fetched, just pass it as a prop.
## Example: Content Page
`ContentPageLayout` demonstrates the full pattern.
### 1. Define a DI contract in `packages/ui/src/providers/`
The provider interface abstracts all platform-specific operations:
```ts
// packages/ui/src/providers/content-manager.ts
export interface ContentManagerContext {
items: Ref<ContentItem[]>
loading: Ref<boolean>
error: Ref<Error | null>
contentTypeLabel: Ref<string>
// These are the platform-abstracted operations:
// App uses invoke(), website uses api-client
toggleEnabled: (item: ContentItem) => Promise<void>
deleteItem: (item: ContentItem) => Promise<void>
refresh: () => Promise<void>
browse: () => void
uploadFiles: () => void
// Optional capabilities — not every platform supports everything
hasUpdateSupport: boolean
updateItem?: (item: ContentItem) => Promise<void>
bulkUpdateItem?: (items: ContentItem[]) => Promise<void>
mapToTableItem: (item: ContentItem) => ContentCardTableItem
}
export const [injectContentManager, provideContentManager] =
createContext<ContentManagerContext>('ContentManager')
```
### 2. Build the shared page in `packages/ui`
The page component injects the context and handles all UI logic (search, filtering, selection, bulk operations, empty states, modals) without knowing the platform:
```vue
<!-- packages/ui/src/components/instances/ContentPageLayout.vue -->
<script setup lang="ts">
import { injectContentManager } from '../../providers/content-manager'
const { items, loading, toggleEnabled, deleteItem, refresh, mapToTableItem } =
injectContentManager()
// All UI logic lives here — search, filters, sort, bulk ops, etc.
</script>
<template>
<ContentCardTable :items="filteredItems" />
</template>
```
### 3. Each platform provides its implementation
**Website (Nuxt)** — uses `api-client` or `useBaseFetch`:
```vue
<!-- apps/frontend/src/pages/hosting/manage/[id]/content.vue -->
<script setup lang="ts">
import { provideContentManager, ContentPageLayout } from '@modrinth/ui'
const { labrinth } = injectModrinthClient()
const { data: items } = useQuery({
queryKey: ['content', serverId],
queryFn: () => labrinth.servers_v0.getAddons(serverId),
})
provideContentManager({
items: computed(() => items.value?.map(addonToContentItem) ?? []),
deleteItem: async (item) => {
await labrinth.servers_v0.deleteAddon(serverId, item.id)
},
// ... rest of the contract
})
</script>
<template>
<ContentPageLayout />
</template>
```
**App (Tauri)** — uses `invoke`:
```vue
<!-- apps/app-frontend/src/pages/instance/Content.vue -->
<script setup lang="ts">
import { provideContentManager, ContentPageLayout } from '@modrinth/ui'
import { invoke } from '@tauri-apps/api/core'
const items = ref<ContentItem[]>([])
await invoke('get_instance_content', { instanceId }).then(/* map to ContentItem[] */)
provideContentManager({
items,
deleteItem: async (item) => {
await invoke('delete_content', { instanceId, path: item.file_path })
},
// ... rest of the contract
})
</script>
<template>
<ContentPageLayout />
</template>
```
## When to Use Props vs DI
| Use | When |
| --------- | -------------------------------------------------------------------------------------------------------- |
| **DI** | The data depends on _how_ it's fetched (different per platform) — API calls, file operations, navigation |
| **Props** | The data is the same regardless of platform — configuration flags, display options |
## Composables for Shared Logic
Extract reusable stateful logic into composables in `packages/ui/src/composables/`. The shared page orchestrates them internally:
- Search (Fuse.js fuzzy search over items)
- Filtering (dynamic filter pills)
- Selection (multi-select with bulk operations)
- Bulk operations (sequential execution with progress tracking)
## Key Files
- `packages/ui/src/pages/` (or `src/layout/`) — shared page components
- `packages/ui/src/providers/` — DI contracts
- `packages/ui/src/composables/` — shared stateful logic
- `apps/frontend/src/app.vue` — website root provider setup
- `apps/app-frontend/src/App.vue` — app root provider setup
- `apps/app-frontend/src/routes.js` — app route definitions
1. **Read the target page** at `$ARGUMENTS` and understand its data sources, mutations, and navigation.
2. **Read the standards above** to understand the shared vs wrapped distinction and the DI pattern.
3. **Decide the category:**
- **Wrapped** (`layouts/wrapped/`) — if the page uses the same API source on both platforms (e.g. web requests, not Tauri plugins). Just move the page component into `packages/ui` and import it from both frontends.
- **Shared** (`layouts/shared/`) — if the page has different data-fetching logic per platform (e.g. website uses `api-client`, app uses Tauri `invoke`). Requires a DI contract.
4. **For shared layouts:**
- Define a DI contract interface in `providers/` capturing all platform-specific operations.
- Create the layout component that injects the context and handles all UI logic.
- Extract reusable stateful logic (search, filtering, selection) into `composables/`.
- Implement the contract separately in each frontend (`apps/frontend/`, `apps/app-frontend/`).
5. **For wrapped pages:**
- Move the page component into `packages/ui/src/layouts/wrapped/` matching the route structure.
- Replace any platform-specific imports with shared utilities.
- Import and render the wrapped page from both frontends as a simple component.
6. **Verify** the page renders correctly by checking for missing imports and that all DI contracts are satisfied.
+19 -42
View File
@@ -1,45 +1,22 @@
# Figma MCP Usage
---
name: figma-mcp
description: Use the Figma MCP server to translate a Figma design into a Vue page or component layout. Use when the user provides a Figma URL, asks to implement a design, or wants to draft a page layout from Figma.
argument-hint: <figma-url>
---
When the Figma MCP server is connected, use it to translate Figma designs into production-ready Vue components for this monorepo.
Refer to the standard: @standards/frontend/FIGMA_MCP_USAGE.md
Also read @packages/ui/CLAUDE.md for color token mapping and component conventions.
## Workflow
## Steps
### 1. Get the design context
Use `get_design_context` with the node ID from a Figma URL. If the URL is `https://figma.com/design/:fileKey/:fileName?node-id=1-2`, the node ID is `1:2`.
```
get_design_context(nodeId: "1:2", clientLanguages: "typescript,html,css", clientFrameworks: "vue")
```
This returns reference code, a screenshot, and metadata. Always start here.
### 2. Get a screenshot for visual reference
Use `get_screenshot` if you need to see the design without full code context:
```
get_screenshot(nodeId: "1:2")
```
### 3. Get variable definitions
Use `get_variable_defs` to see what design tokens are applied to a node:
```
get_variable_defs(nodeId: "1:2")
```
### 4. Get metadata for structure overview
Use `get_metadata` to get an XML overview of node IDs, layer types, names, positions and sizes — useful for understanding the structure of a complex frame before diving into individual nodes.
## Adapting Figma Output
The Figma MCP returns generic reference code. Adapt it to match the Modrinth codebase:
1. **Read `packages/ui/CLAUDE.md`** for color usage rules, surface token mapping, and component patterns.
2. **Map Figma color variables to `surface-*` tokens** — never use Figma's aliased names like `bg/default` or `bg/raised` directly. The CLAUDE.md has the full mapping table.
3. **Check `packages/assets/styles/variables.scss`** for tokens not exposed in Figma (brand highlights, semantic backgrounds, shadows).
4. **Check for existing components** in `packages/ui/src/components/` before building from scratch.
5. **Match spacing exactly** — do not approximate values from the design.
1. **Parse the Figma URL** from `$ARGUMENTS` — extract the `fileKey` and `nodeId`. Convert `-` to `:` in the node ID.
2. **Read the standards above** for the available tools, adaptation rules, and color usage.
3. **Call `get_design_context`** with the extracted `nodeId` and `fileKey`, using `clientLanguages: "typescript,html,css"` and `clientFrameworks: "vue"`. This is always the first tool to call.
5. **Adapt the output to the Modrinth codebase:**
- Map Figma color variables to `surface-*` / `text-*` tokens — never use Figma's aliased names directly.
- Check `packages/ui/src/components/` for existing components that match elements in the design (buttons, cards, modals, inputs, etc.).
- Check `packages/assets/styles/variables.scss` for tokens not exposed in Figma.
- Match spacing values exactly from the design.
6. **Use `get_screenshot`** if you need a closer visual reference of specific nodes.
7. **Use `get_variable_defs`** to verify which design tokens are applied to ambiguous elements.
8. **Build the component** as a Vue SFC using Tailwind classes and the project's existing component library.
-105
View File
@@ -1,105 +0,0 @@
# i18n String Conversion
Convert hard-coded natural-language strings in Vue SFCs into the localization system using utilities from `@modrinth/ui`.
## Rules
### 1. Identify translatable strings
- Scan `<template>` for all user-visible strings: inner text, alt attributes, placeholders, button labels, etc.
- Check `<script>` too: dropdown option labels, notification messages, etc.
- Do NOT extract dynamic expressions (`{{ user.name }}`) or HTML tags — only static human-readable text.
### 2. Create message definitions
Import `defineMessage` or `defineMessages` from `@modrinth/ui` in `<script setup>`. Define messages with a unique `id` (descriptive prefix based on component path) and `defaultMessage` equal to the original English string:
```ts
const messages = defineMessages({
welcomeTitle: { id: 'auth.welcome.title', defaultMessage: 'Welcome' },
welcomeDescription: { id: 'auth.welcome.description', defaultMessage: "You're now part of the community…" },
})
```
### 3. Handle variables and ICU formats
- Dynamic parts become ICU placeholders: `"Hello, ${user.name}!"``defaultMessage: 'Hello, {name}!'`
- Numbers/dates/times use ICU options: `{price, number, ::currency/USD}`
- Plurals/selects use ICU: `'{count, plural, one {# message} other {# messages}}'`
### 4. Rich-text messages (links/markup)
Wrap link/markup ranges with tags in `defaultMessage`:
```
"By creating an account, you agree to our <terms-link>Terms</terms-link> and <privacy-link>Privacy Policy</privacy-link>."
```
Render with `<IntlFormatted>` from `@modrinth/ui` using named slots:
```vue
<IntlFormatted :message-id="messages.tosLabel">
<template #terms-link="{ children }">
<NuxtLink to="/terms">
<component :is="() => children" />
</NuxtLink>
</template>
<template #privacy-link="{ children }">
<NuxtLink to="/privacy">
<component :is="() => children" />
</NuxtLink>
</template>
</IntlFormatted>
```
For simple emphasis: `'Welcome to <strong>Modrinth</strong>!'` with a slot:
```vue
<template #strong="{ children }">
<strong><component :is="() => children" /></strong>
</template>
```
For complex child handling, use `normalizeChildren` from `@modrinth/ui`:
```vue
<template #bold="{ children }">
<strong><component :is="() => normalizeChildren(children)" /></strong>
</template>
```
### 5. Formatting in templates
Use `useVIntl()` from `@modrinth/ui`; prefer `formatMessage` for simple strings:
```ts
const { formatMessage } = useVIntl()
```
```vue
<button>{{ formatMessage(messages.welcomeTitle) }}</button>
{{ formatMessage(messages.greeting, { name: user.name }) }}
```
### 6. Naming conventions
Make `id`s descriptive and stable (e.g., `error.generic.default.title`). Group related messages with `defineMessages`.
### 7. Avoid Vue/ICU delimiter collisions
If an ICU placeholder ends right before `}}` in a Vue template, insert a space: `} }` to avoid parsing issues.
### 8. Imports
Ensure these are imported from `@modrinth/ui` as needed: `defineMessage`/`defineMessages`, `useVIntl`, `IntlFormatted`, `normalizeChildren`.
### 9. Preserve functionality
Do not change logic, layout, reactivity, or bindings — only refactor strings into i18n.
## Reference Examples
- Variables/plurals: `apps/frontend/src/pages/frog.vue`
- Rich-text link tags: `apps/frontend/src/pages/auth/welcome.vue` and `apps/frontend/src/error.vue`
When finished, there should be no hard-coded English strings left in the template — everything comes from `formatMessage` or `<IntlFormatted>`.
+24
View File
@@ -0,0 +1,24 @@
---
name: i18n-pass
description: Perform an i18n localization pass on changed files or a pull request, converting hard-coded English strings to the @modrinth/ui i18n system. Use when internationalizing a set of changes, reviewing a PR for untranslated strings, or converting a specific component.
argument-hint: [file-path-or-pr-number]
---
Refer to the standard: @standards/frontend/INTERNATIONALIZATION.md
## Steps
1. **Identify the scope of changes:**
- If `$ARGUMENTS` is a PR number, run `gh pr diff $ARGUMENTS` to get the changed files.
- If `$ARGUMENTS` is a file path, use that directly.
- If no argument, check `git diff` for uncommitted changes.
2. **Read the standard above** for the message definition pattern, ICU format rules, and `IntlFormatted` usage.
3. **Filter to Vue SFCs** — only `.vue` files need i18n passes. Skip non-component files.
4. **For each file, scan for hard-coded strings:**
- `<template>`: inner text, `alt`, `placeholder`, `aria-label`, button labels, tooltip text.
- `<script>`: string literals passed to user-visible UI (notification messages, dropdown labels, error messages).
- Skip: dynamic expressions, HTML tag names, CSS classes, internal identifiers, log messages.
5. **Define messages** with `defineMessages` — use descriptive, stable `id`s based on the component's domain (e.g. `project.settings.title`).
6. **Replace strings in templates** with `formatMessage()` calls, or `<IntlFormatted>` for strings containing links or markup.
7. **Handle ICU edge cases** — add a space before `}}` if an ICU placeholder ends at a Vue template delimiter boundary.
8. **Verify** no hard-coded English strings remain in the changed templates. Do not alter logic, layout, or reactivity.
-215
View File
@@ -1,215 +0,0 @@
# Multistage Modals
The `MultiStageModal` component (`packages/ui/src/components/base/MultiStageModal.vue`) provides a wizard-like modal with progress tracking, conditional stages, and per-stage button configuration.
## Architecture
A multistage modal has three parts:
1. **Context** — A DI provider that holds all state, business logic, and stage configs
2. **Stage configs** — Data objects describing each stage (title, component, buttons, skip conditions)
3. **Stage components** — Vue components rendered inside the modal, consuming the context
## Building a Multistage Modal
### 1. Define the context
Create a DI provider with all the state your wizard needs. Include the modal ref and stage configs.
```ts
// providers/my-feature/my-modal.ts
import type { ShallowRef } from 'vue'
import type { ComponentExposed } from 'vue-component-type-helpers'
import type { MultiStageModal, StageConfigInput } from '@modrinth/ui'
import { createContext } from '@modrinth/ui'
export interface MyModalContext {
// State
formData: Ref<MyFormData>
isSubmitting: Ref<boolean>
// Modal control
modal: ShallowRef<ComponentExposed<typeof MultiStageModal> | null>
stageConfigs: StageConfigInput<MyModalContext>[]
// Business logic
handleSubmit: () => Promise<void>
}
export const [injectMyModalContext, provideMyModalContext] =
createContext<MyModalContext>('MyModal')
export function createMyModalContext(
modal: ShallowRef<ComponentExposed<typeof MultiStageModal> | null>,
): MyModalContext {
const formData = ref<MyFormData>({ ... })
const isSubmitting = ref(false)
async function handleSubmit() {
isSubmitting.value = true
try {
await saveData(formData.value)
modal.value?.hide()
} finally {
isSubmitting.value = false
}
}
return { formData, isSubmitting, modal, stageConfigs, handleSubmit }
}
```
### 2. Define stage configs
Each stage is a `StageConfigInput<T>` where `T` is your context type. Most fields accept either a static value or a function receiving the context (`MaybeCtxFn<T, R>`).
```ts
// providers/my-feature/stages/details-stage.ts
import { markRaw } from 'vue'
import type { StageConfigInput } from '@modrinth/ui'
import type { MyModalContext } from '../my-modal'
import DetailsStage from './DetailsStage.vue'
import { RightArrowIcon, SaveIcon } from '@modrinth/assets'
export const detailsStageConfig: StageConfigInput<MyModalContext> = {
id: 'details',
stageContent: markRaw(DetailsStage),
title: 'Details',
// Conditional behavior based on context
skip: (ctx) => ctx.shouldSkipDetails.value,
cannotNavigateForward: (ctx) => !ctx.formData.value.name,
disableClose: (ctx) => ctx.isSubmitting.value,
leftButtonConfig: (ctx) => ({
label: 'Cancel',
onClick: () => ctx.modal.value?.hide(),
}),
rightButtonConfig: (ctx) => ({
label: 'Next',
icon: RightArrowIcon,
iconPosition: 'after',
disabled: !ctx.formData.value.name,
onClick: () => ctx.modal.value?.nextStage(),
}),
}
```
**Stage config fields:**
| Field | Type | Purpose |
|-------|------|---------|
| `id` | `string` | Unique stage identifier (used with `setStage()`) |
| `stageContent` | `Component` | Vue component to render (wrap with `markRaw()`) |
| `title` | `MaybeCtxFn<T, string>` | Stage title in breadcrumbs |
| `skip` | `MaybeCtxFn<T, boolean>` | Skip this stage conditionally |
| `nonProgressStage` | `MaybeCtxFn<T, boolean>` | Exclude from progress bar (for edit sub-flows) |
| `hideStageInBreadcrumb` | `MaybeCtxFn<T, boolean>` | Hide from breadcrumb nav |
| `cannotNavigateForward` | `MaybeCtxFn<T, boolean>` | Block forward navigation (validation) |
| `disableClose` | `MaybeCtxFn<T, boolean>` | Disable closing the modal |
| `leftButtonConfig` | `MaybeCtxFn<T, StageButtonConfig \| null>` | Left action button |
| `rightButtonConfig` | `MaybeCtxFn<T, StageButtonConfig \| null>` | Right action button |
| `maxWidth` | `MaybeCtxFn<T, string>` | Per-stage max width (default `560px`) |
**Button config fields:**
| Field | Purpose |
|-------|---------|
| `label` | Button text |
| `icon` | Icon component |
| `iconPosition` | `'before'` or `'after'` |
| `color` | ButtonStyled color prop |
| `disabled` | Disable the button |
| `onClick` | Click handler |
### 3. Create stage components
Stage components inject the context and render their UI:
```vue
<!-- providers/my-feature/stages/DetailsStage.vue -->
<script setup lang="ts">
import { injectMyModalContext } from '../my-modal'
const { formData } = injectMyModalContext()
</script>
<template>
<div class="flex flex-col gap-4">
<StyledInput v-model="formData.name" label="Name" />
<StyledInput v-model="formData.description" label="Description" />
</div>
</template>
```
### 4. Create the wrapper component
The wrapper provides context and renders `MultiStageModal`:
```vue
<!-- components/MyModalWrapper.vue -->
<script setup lang="ts">
import { shallowRef } from 'vue'
import { MultiStageModal } from '@modrinth/ui'
import { createMyModalContext, provideMyModalContext } from '../providers/my-feature/my-modal'
const modal = shallowRef<InstanceType<typeof MultiStageModal> | null>(null)
const ctx = createMyModalContext(modal)
provideMyModalContext(ctx)
defineExpose({ show: () => modal.value?.show() })
</script>
<template>
<MultiStageModal ref="modal" :stages="ctx.stageConfigs" :context="ctx" />
</template>
```
## Modal API
`MultiStageModal` exposes via ref:
| Method/Property | Description |
|----------------|-------------|
| `show()` | Open the modal |
| `hide()` | Close the modal |
| `setStage(indexOrId)` | Jump to stage by index or string id |
| `nextStage()` | Advance to next non-skipped stage |
| `prevStage()` | Go back to previous stage |
| `currentStageIndex` | Ref to current stage index |
## Non-Progress Stages (Edit Sub-Flows)
For stages that shouldn't appear in the progress bar (e.g. editing a specific field from a summary page):
```ts
export const editLoadersStageConfig: StageConfigInput<MyContext> = {
id: 'edit-loaders',
nonProgressStage: true,
stageContent: markRaw(EditLoadersStage),
title: 'Edit loaders',
leftButtonConfig: (ctx) => ({
label: 'Back',
onClick: () => ctx.modal.value?.setStage('summary'),
}),
rightButtonConfig: (ctx) => ({
...ctx.saveButtonConfig(),
label: 'Save',
}),
}
```
Navigate to it with `modal.value?.setStage('edit-loaders')` — it won't affect the progress indicator.
## Reference Implementation
The version creation/edit modal is the most complete example:
| File | Purpose |
|------|---------|
| `apps/frontend/src/providers/version/manage-version-modal.ts` | Context creation + business logic |
| `apps/frontend/src/providers/version/stages/index.ts` | Stage config barrel export |
| `apps/frontend/src/providers/version/stages/*-stage.ts` | Individual stage configs |
The context includes computed properties for conditional UI, watchers for auto-fetching dependencies, loading states for granular button disabling, and both "create" and "edit" flows sharing the same stages with different button configs.
+24 -151
View File
@@ -1,154 +1,27 @@
# TanStack Query
---
name: tanstack-query
description: Convert a page or component from useAsyncData/manual ref patterns to TanStack Query for server state management. Use when migrating data fetching to useQuery/useMutation, adding cache invalidation, or replacing useAsyncData with TanStack Query.
argument-hint: <path-to-file>
---
TanStack Query (`@tanstack/vue-query` v5) is used for server state management — caching, background refetching, and cache invalidation. Use it instead of manual `ref()` + `await` patterns for any data that comes from an API.
Refer to the standard: @standards/frontend/FETCHING_DATA.md
A TanStack MCP server is available — use `tanstack_doc` and `tanstack_search_docs` tools to look up API details when needed.
## Steps
## Setup
TanStack Query is configured in `apps/frontend/src/plugins/tanstack.ts` as a Nuxt plugin with SSR hydration support. Default stale time is 5 seconds. The `QueryClient` is available via `useQueryClient()` or `useAppQueryClient()` (which also works in middleware).
## Queries
Use `useQuery` with the api-client for data fetching:
```ts
const client = injectModrinthClient()
const { data, isPending, isError, error } = useQuery({
queryKey: ['project', 'v3', projectId],
queryFn: () => client.labrinth.projects_v3.get(projectId),
staleTime: 1000 * 60 * 5,
})
```
In templates:
```vue
<span v-if="isPending">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<div v-else>{{ data.title }}</div>
```
### Query Option Factories
For queries used across multiple components, define reusable query option factories in `packages/ui/src/queries/`:
```ts
// composables/queries/project.ts
export const STALE_TIME = 1000 * 60 * 5
export const STALE_TIME_LONG = 1000 * 60 * 10
export const projectQueryOptions = {
v3: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', 'v3', projectId] as const,
queryFn: () => client.labrinth.projects_v3.get(projectId),
staleTime: STALE_TIME,
}),
members: (projectId: string, client: AbstractModrinthClient) => ({
queryKey: ['project', projectId, 'members'] as const,
queryFn: () => client.labrinth.projects_v3.getMembers(projectId),
staleTime: STALE_TIME,
}),
}
```
Then use them:
```ts
const { data } = useQuery(projectQueryOptions.v3(projectId, client))
```
### Conditional Queries
Use `enabled` as a computed for queries that depend on other data:
```ts
const { data: members } = useQuery({
queryKey: ['project', projectId, 'members'],
queryFn: () => client.labrinth.projects_v3.getMembers(projectId),
enabled: computed(() => !!projectId.value),
})
```
## Mutations
Use `useMutation` for create/update/delete operations. Invalidate related queries on success:
```ts
const queryClient = useQueryClient()
const client = injectModrinthClient()
const createMutation = useMutation({
mutationFn: (name: string) => client.archon.backups_v0.create(serverId, { name }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['backups', 'list', serverId] }),
})
```
Use `createMutation.isPending.value` to disable buttons during submission.
### Optimistic Updates
For mutations where responsiveness matters, use optimistic updates with rollback:
```ts
const patchMutation = useMutation({
mutationFn: async ({ projectId, data }) => {
await client.labrinth.projects_v3.patch(projectId, data)
return data
},
onMutate: async ({ projectId, data }) => {
await queryClient.cancelQueries({ queryKey: ['project', 'v3', projectId] })
const previous = queryClient.getQueryData(['project', 'v3', projectId])
queryClient.setQueryData(['project', 'v3', projectId], (old) => {
if (!old) return old
return { ...old, ...data }
})
return { previous }
},
onError: (_err, _variables, context) => {
if (context?.previous) {
queryClient.setQueryData(['project', 'v3', projectId], context.previous)
}
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['project', 'v3', projectId] })
},
})
```
## Query Keys
Keys use a hierarchical array pattern:
```ts
// Resource type → version/qualifier → ID
['project', 'v3', projectId]
// Resource type → ID → sub-resource
['project', projectId, 'members']
['project', projectId, 'versions', 'v3']
// Domain → action → ID
['backups', 'list', serverId]
['tech-reviews']
```
Use `as const` for type safety. Put the resource ID last when possible — this makes partial key matching work for invalidation:
```ts
// Invalidates all project queries for this ID
queryClient.invalidateQueries({ queryKey: ['project', projectId] })
```
## Key Files
- `apps/frontend/src/plugins/tanstack.ts` — QueryClient setup + SSR hydration
- `apps/frontend/src/composables/query-client.ts``useAppQueryClient()` helper
- `apps/frontend/src/composables/queries/` — reusable query option factories
1. **Read the target file** at `$ARGUMENTS` and identify all data-fetching patterns: `useAsyncData`, `useFetch`, manual `ref()` + `await`, or `onMounted` fetch calls.
2. **Read the standard above** for the query/mutation patterns, query key conventions, and optimistic update approach.
3. **Convert queries:**
- Replace `useAsyncData` / `useFetch` / manual fetches with `useQuery`.
- Use the `api-client` via `injectModrinthClient()` for the `queryFn`.
- Design query keys with the `['resource', 'version', ...params]` convention.
- Use `computed` query keys for reactive parameters.
- Use the `enabled` option for conditional queries that depend on other data.
4. **Convert mutations:**
- Replace manual `try/catch` + `ref` patterns with `useMutation`.
- Add `onSuccess` handlers that invalidate or update related query caches.
- Consider optimistic updates for UI-critical mutations (follow the pattern in the standard).
5. **Clean up:**
- Remove manual loading/error `ref()`s that are now handled by TanStack Query's return values (`isPending`, `isError`, `error`).
- Remove manual `onMounted` fetch calls.
- Ensure SSR compatibility — queries in Nuxt pages are automatically awaited during SSR.
6. **Verify** the page still renders correctly and that cache invalidation triggers re-fetches where expected.
+121
View File
@@ -0,0 +1,121 @@
name: Changelog Comment
on:
pull_request:
types: [opened, reopened]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to post the changelog comment on (for testing)'
required: true
type: number
jobs:
comment:
name: Post changelog comment
runs-on: ubuntu-latest
steps:
- name: 💬 Post or update changelog comment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.CROWDIN_GH_TOKEN }}
script: |
const marker = '<!-- changelog -->';
const mergedMarker = '<!-- changelog-merged -->';
const sections = ['### Added', '', '### Changed', '', '### Deprecated', '', '### Removed', '', '### Fixed', '', '### Security'].join('\n');
const productBlock = (name) => `<details>\n<summary>${name}</summary>\n\n${sections}\n\n</details>`;
const template = [
marker,
'## Pull request changelog',
'',
'<!-- Fill in the changelog under each product area this PR affects.',
' Empty sections are ignored. Leave a product collapsed/empty',
' if it doesn\'t apply. -->',
'',
productBlock('App'),
'',
productBlock('Website'),
'',
productBlock('Hosting'),
].join('\n');
// Resolve PR number from event or workflow_dispatch input
const prNumber = context.payload.pull_request?.number
?? parseInt('${{ github.event.inputs.pr_number }}', 10);
if (!prNumber || isNaN(prNumber)) {
core.setFailed('Could not determine PR number');
return;
}
// Get PR details (need base ref for child PR detection)
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
// Check if bot comment already exists
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const existingComment = comments.find(c => c.body.includes(marker));
if (existingComment) {
core.info('Changelog comment already exists, skipping');
return;
}
// Post the template comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: template,
});
core.info(`Posted changelog comment on PR #${prNumber}`);
// Detect child PR: check if this PR's base branch is another open PR's head branch
const baseRef = pr.base.ref;
if (baseRef === 'main' || baseRef === 'prod') {
return;
}
// Look for a parent PR whose head branch matches our base branch
const { data: candidatePRs } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
head: `${context.repo.owner}:${baseRef}`,
});
if (candidatePRs.length === 0) {
return;
}
const parentPR = candidatePRs[0];
core.info(`Detected parent PR #${parentPR.number} for child PR #${prNumber}`);
// Add admonition to child PR's changelog comment
const { data: childComments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const childChangelogComment = childComments.find(c => c.body.includes(marker));
if (childChangelogComment && !childChangelogComment.body.includes(mergedMarker)) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: childChangelogComment.id,
body: `${mergedMarker}\n> [!NOTE]\n> This changelog has been merged into the changelog for #${parentPR.number}\n\n${childChangelogComment.body}`,
});
}
+2 -1
View File
@@ -50,14 +50,15 @@ jobs:
uses: peter-evans/find-comment@v3
id: fc
with:
token: ${{ secrets.CROWDIN_GH_TOKEN }}
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: Frontend previews
- name: Comment deploy URL on PR
if: github.event_name == 'pull_request'
uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ secrets.CROWDIN_GH_TOKEN }}
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.fc.outputs.comment-id }}
body: |
+27 -17
View File
@@ -1,47 +1,43 @@
name: Modrinth App release
on:
workflow_dispatch:
inputs:
version-tag:
description: Version tag to release to the wide public
type: string
required: true
release-notes:
description: Release notes to include in the Tauri version manifest
default: A new release of the Modrinth App is available!
type: string
required: true
workflow_run:
workflows: ['Modrinth App build']
types: [completed]
jobs:
release:
name: Release Modrinth App
if: >-
github.event.workflow_run.conclusion == 'success' &&
startsWith(github.event.workflow_run.head_branch, 'v')
runs-on: ubuntu-latest
env:
VERSION_TAG: ${{ github.event.workflow_run.head_branch }}
LINUX_X64_BUNDLE_ARTIFACT_NAME: App bundle (x86_64-unknown-linux-gnu)
WINDOWS_X64_BUNDLE_ARTIFACT_NAME: App bundle (x86_64-pc-windows-msvc)
MACOS_UNIVERSAL_BUNDLE_ARTIFACT_NAME: App bundle (universal-apple-darwin)
LAUNCHER_FILES_BUCKET_BASE_URL: https://launcher-files.modrinth.com
steps:
- name: 📥 Check out code
uses: actions/checkout@v4
- name: 📥 Download Modrinth App artifacts
uses: dawidd6/action-download-artifact@v11
with:
workflow: theseus-build.yml
workflow_conclusion: success
event: push
branch: ${{ inputs.version-tag }}
branch: ${{ env.VERSION_TAG }}
use_unzip: true
- name: 🛠️ Generate version manifest
env:
VERSION_TAG: ${{ inputs.version-tag }}
RELEASE_NOTES: ${{ inputs.release-notes }}
run: |
# Reference: https://tauri.app/plugin/updater/#server-support
jq -nc \
--arg versionTag "${VERSION_TAG#v}" \
--arg releaseNotes "$RELEASE_NOTES" \
--arg releaseNotes "See the full changelog at https://modrinth.com/news/changelog" \
--rawfile macOsAarch64UpdateArtifactSignature "${MACOS_UNIVERSAL_BUNDLE_ARTIFACT_NAME}/universal-apple-darwin/release/bundle/macos/Modrinth App.app.tar.gz.sig" \
--rawfile macOsX64UpdateArtifactSignature "${MACOS_UNIVERSAL_BUNDLE_ARTIFACT_NAME}/universal-apple-darwin/release/bundle/macos/Modrinth App.app.tar.gz.sig" \
--rawfile linuxX64UpdateArtifactSignature "${LINUX_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/appimage/Modrinth App_${VERSION_TAG#v}_amd64.AppImage.tar.gz.sig" \
@@ -83,7 +79,6 @@ jobs:
- name: 📤 Upload release artifacts
env:
VERSION_TAG: ${{ inputs.version-tag }}
AWS_ACCESS_KEY_ID: ${{ secrets.LAUNCHER_FILES_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.LAUNCHER_FILES_BUCKET_SECRET_ACCESS_KEY }}
AWS_BUCKET: ${{ secrets.LAUNCHER_FILES_BUCKET_NAME }}
@@ -116,3 +111,18 @@ jobs:
done
aws s3 cp updates.json "s3://${AWS_BUCKET}"
- name: 🏷️ Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION="${VERSION_TAG#v}"
gh release create "$VERSION_TAG" \
--title "Modrinth App ${VERSION}" \
--notes "See the full changelog at https://modrinth.com/news/changelog" \
"${WINDOWS_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/nsis/Modrinth App_${VERSION}_x64-setup.exe" \
"${MACOS_UNIVERSAL_BUNDLE_ARTIFACT_NAME}/universal-apple-darwin/release/bundle/dmg/Modrinth App_${VERSION}_universal.dmg" \
"${LINUX_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/appimage/Modrinth App_${VERSION}_amd64.AppImage" \
"${LINUX_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/deb/Modrinth App_${VERSION}_amd64.deb" \
"${LINUX_X64_BUNDLE_ARTIFACT_NAME}/release/bundle/rpm/Modrinth App-${VERSION}-1.x86_64.rpm"
+4 -23
View File
@@ -30,7 +30,7 @@ This is the Modrinth monorepo — it contains all Modrinth projects, both fronte
| `api-client` | API client for Nuxt, Tauri, and Node/browser |
| `app-lib` | Shared app library |
| `blog` | Blog system and changelog data |
| `utils` | Shared utility functions |
| `utils` | Shared utility functions (mostly deprecated) |
| `moderation` | Moderation utilities |
| `daedalus` | Daedalus protocol |
| `tooling-config` | ESLint, Prettier, TypeScript configs |
@@ -67,18 +67,6 @@ Each project may have its own `CLAUDE.md` with detailed instructions:
- [`apps/labrinth/CLAUDE.md`](apps/labrinth/CLAUDE.md) — Backend API
- [`apps/frontend/CLAUDE.md`](apps/frontend/CLAUDE.md) - Frontend Website
## Skills (`.claude/skills/`)
Project-specific skill files with detailed patterns. Use them when the task matches:
- **`api-module`** — Adding a new API endpoint module to `packages/api-client` (types, module class, registry registration)
- **`cross-platform-pages`** — Building a page that needs to work in both the website (`apps/frontend`) and the desktop app (`apps/app-frontend`)
- **`dependency-injection`** — Creating or wiring up a `provide`/`inject` context for platform abstraction or deep component state sharing
- **`figma-mcp`** — Translating a Figma design into Vue components using the Figma MCP tools
- **`i18n-convert`** — Converting hardcoded English strings in Vue SFCs into the `@modrinth/ui` i18n system (`defineMessages`, `formatMessage`, `IntlFormatted`)
- **`multistage-modals`** — Building a wizard-like modal with multiple stages, progress tracking, and per-stage buttons using `MultiStageModal`
- **`tanstack-query`** — Fetching, caching, or mutating server data with `@tanstack/vue-query` (queries, mutations, invalidation, optimistic updates)
## Code Guidelines
### Comments
@@ -97,6 +85,7 @@ Project-specific skill files with detailed patterns. Use them when the task matc
### General
- Do not create new non-source code files (e.g. Bash scripts, SQL scripts) unless explicitly prompted to
- For Frontend, when doing lint checks, only use the `prepr` commands, do not use `typecheck` or `tsc` etc.
- Types in `@modrinth/utils` are considered highly outdated, if a component needs them, check if you can switch said component to use types from `packages/api-client`
## Edit Tool - Whitespace Handling (CLAUDE ONLY)
@@ -115,14 +104,6 @@ For Edit, use: ` private byte tag;` (copy everything after →, including the t
**IMPORTANT**: Trust the Read tool output. Copy what's after `→` into Edit immediately. DO NOT verify with sed/od/grep first - that's wasting time and the instructions already tell you to stop if Edit fails, not to pre-verify.
## Skills
## Standards
Project-specific skills (patterns, conventions, and implementation guides) are located in [`.claude/skills/`](./.claude/skills/). Each skill has a `SKILL.md` describing the pattern:
- **[Dependency Injection](./.claude/skills/dependency-injection/SKILL.md)** — Vue provide/inject DI layer using `createContext`
- **[Cross-Platform Pages](./.claude/skills/cross-platform-pages/SKILL.md)** — Shared component architecture across Nuxt and Tauri frontends
- **[Multistage Modals](./.claude/skills/multistage-modals/SKILL.md)** — Wizard-like modal flows with `MultiStageModal`
- **[Figma MCP](./.claude/skills/figma-mcp/SKILL.md)** — Translating Figma designs to Modrinth Vue components
- **[i18n Convert](./.claude/skills/i18n-convert/SKILL.md)** — Converting hard-coded strings to vue-i18n localization
- **[API Module](./.claude/skills/api-module/SKILL.md)** — Adding new endpoint modules to `@modrinth/api-client`
- **[TanStack Query](./.claude/skills/tanstack-query/SKILL.md)** — Server state management with `@tanstack/vue-query` v5
Standards available at the @standards/ folder.
+37 -12
View File
@@ -68,23 +68,22 @@ import ErrorModal from '@/components/ui/ErrorModal.vue'
import FriendsList from '@/components/ui/friends/FriendsList.vue'
import AddServerToInstanceModal from '@/components/ui/install_flow/AddServerToInstanceModal.vue'
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
import InstallConfirmModal from '@/components/ui/install_flow/InstallConfirmModal.vue'
import MinecraftAuthErrorModal from '@/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue'
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
import AuthGrantFlowWaitModal from '@/components/ui/modal/AuthGrantFlowWaitModal.vue'
import InstallToPlayModal from '@/components/ui/modal/InstallToPlayModal.vue'
import ModpackAlreadyInstalledModal from '@/components/ui/modal/ModpackAlreadyInstalledModal.vue'
import UpdateToPlayModal from '@/components/ui/modal/UpdateToPlayModal.vue'
import NavButton from '@/components/ui/NavButton.vue'
import PromotionWrapper from '@/components/ui/PromotionWrapper.vue'
import QuickInstanceSwitcher from '@/components/ui/QuickInstanceSwitcher.vue'
import RunningAppBar from '@/components/ui/RunningAppBar.vue'
import SplashScreen from '@/components/ui/SplashScreen.vue'
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
import { hide_ads_window, init_ads_window, show_ads_window } from '@/helpers/ads.js'
import { debugAnalytics, initAnalytics, trackEvent } from '@/helpers/analytics'
import { check_reachable } from '@/helpers/auth.js'
import { get_user } from '@/helpers/cache.js'
import { get_user, get_version } from '@/helpers/cache.js'
import { command_listener, warning_listener } from '@/helpers/events.js'
import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.ts'
import { create_profile_and_install_from_file } from '@/helpers/pack'
@@ -152,13 +151,14 @@ const {
handleBrowseModpacks,
searchModpacks,
getProjectVersions,
setModpackAlreadyInstalledModal,
handleModpackDuplicateCreateAnyway,
handleModpackDuplicateGoToInstance,
} = setupProviders(notificationManager)
const news = ref([])
const availableSurvey = ref(false)
const urlModal = ref(null)
const offline = ref(!navigator.onLine)
window.addEventListener('offline', () => {
offline.value = true
@@ -421,12 +421,15 @@ const {
preferredLoader: contentInstallPreferredLoader,
preferredGameVersion: contentInstallPreferredGameVersion,
releaseGameVersions: contentInstallReleaseGameVersions,
projectInfo: contentInstallProjectInfo,
handleInstallToInstance,
handleCreateAndInstall,
handleNavigate: handleContentInstallNavigate,
handleCancel: handleContentInstallCancel,
setContentInstallModal,
setInstallConfirmModal: setContentInstallConfirmModal,
setModpackAlreadyInstalledModal: setContentInstallModpackAlreadyInstalledModal,
handleModpackDuplicateCreateAnyway: handleContentInstallModpackDuplicateCreateAnyway,
handleModpackDuplicateGoToInstance: handleContentInstallModpackDuplicateGoToInstance,
setIncompatibilityWarningModal: setContentIncompatibilityWarningModal,
} = contentInstall
@@ -436,11 +439,13 @@ const {
setInstallToPlayModal: setServerInstallToPlayModal,
setUpdateToPlayModal: setServerUpdateToPlayModal,
setAddServerToInstanceModal: setServerAddServerToInstanceModal,
playServerProject,
} = serverInstall
const modInstallModal = ref()
const modpackAlreadyInstalledModal = ref()
const contentInstallModpackAlreadyInstalledModal = ref()
const addServerToInstanceModal = ref()
const installConfirmModal = ref()
const incompatibilityWarningModal = ref()
const installToPlayModal = ref()
const updateToPlayModal = ref()
@@ -520,8 +525,9 @@ onMounted(() => {
error.setMinecraftAuthErrorModal(minecraftAuthErrorModal.value)
setContentIncompatibilityWarningModal(incompatibilityWarningModal.value)
setContentInstallConfirmModal(installConfirmModal.value)
setContentInstallModal(modInstallModal.value)
setContentInstallModpackAlreadyInstalledModal(contentInstallModpackAlreadyInstalledModal.value)
setModpackAlreadyInstalledModal(modpackAlreadyInstalledModal.value)
setServerAddServerToInstanceModal(addServerToInstanceModal.value)
setServerInstallToPlayModal(installToPlayModal.value)
setServerUpdateToPlayModal(updateToPlayModal.value)
@@ -545,9 +551,19 @@ async function handleCommand(e) {
} else if (e.event === 'InstallServer') {
await router.push(`/project/${e.id}`)
await playServerProject(e.id).catch(handleError)
} else if (e.event === 'InstallVersion') {
const version = await get_version(e.id, 'must_revalidate').catch(handleError)
if (version) {
await contentInstall
.install(version.project_id, version.id, null, 'URLConfirmModal', undefined, undefined, {
showProjectInfo: true,
})
.catch(handleError)
}
} else {
// Other commands are URL-based (deep linking)
urlModal.value.show(e)
await contentInstall
.install(e.id, null, null, 'URLConfirmModal', undefined, undefined, { showProjectInfo: true })
.catch(handleError)
}
}
@@ -1265,7 +1281,6 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</template>
</div>
</div>
<URLConfirmModal ref="urlModal" />
<I18nDebugPanel />
<NotificationPanel has-sidebar />
<PopupNotificationPanel has-sidebar />
@@ -1281,14 +1296,24 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
:preferred-loader="contentInstallPreferredLoader"
:preferred-game-version="contentInstallPreferredGameVersion"
:release-game-versions="contentInstallReleaseGameVersions"
:project-info="contentInstallProjectInfo"
@install="handleInstallToInstance"
@create-and-install="handleCreateAndInstall"
@navigate="handleContentInstallNavigate"
@cancel="handleContentInstallCancel"
/>
<ModpackAlreadyInstalledModal
ref="modpackAlreadyInstalledModal"
@create-anyway="handleModpackDuplicateCreateAnyway"
@go-to-instance="handleModpackDuplicateGoToInstance"
/>
<AddServerToInstanceModal ref="addServerToInstanceModal" />
<IncompatibilityWarningModal ref="incompatibilityWarningModal" />
<InstallConfirmModal ref="installConfirmModal" />
<ModpackAlreadyInstalledModal
ref="contentInstallModpackAlreadyInstalledModal"
@create-anyway="handleContentInstallModpackDuplicateCreateAnyway"
@go-to-instance="handleContentInstallModpackDuplicateGoToInstance"
/>
<InstallToPlayModal ref="installToPlayModal" />
<UpdateToPlayModal ref="updateToPlayModal" />
</template>
@@ -20,6 +20,14 @@
:date-updated="project.date_modified"
:banner="project.featured_gallery ?? undefined"
:color="project.color ?? undefined"
:environment="
['mod', 'modpack'].includes(projectType)
? {
clientSide: project.client_side?.[0],
serverSide: project.server_side?.[0],
}
: undefined
"
layout="list"
>
<template #actions>
@@ -1,77 +0,0 @@
<script setup>
import { DownloadIcon, XIcon } from '@modrinth/assets'
import { Button, injectNotificationManager } from '@modrinth/ui'
import { ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { create_profile_and_install as pack_install } from '@/helpers/pack'
const { handleError } = injectNotificationManager()
const versionId = ref()
const project = ref()
const confirmModal = ref(null)
const installing = ref(false)
const onInstall = ref(() => {})
const onCreateInstance = ref(() => {})
defineExpose({
show: (projectVal, versionIdVal, callback, createInstanceCallback) => {
project.value = projectVal
versionId.value = versionIdVal
installing.value = false
confirmModal.value.show()
onInstall.value = callback
onCreateInstance.value = createInstanceCallback
trackEvent('PackInstallStart')
},
})
async function install() {
installing.value = true
confirmModal.value.hide()
await pack_install(
project.value.id,
versionId.value,
project.value.title,
project.value.icon_url,
onCreateInstance.value,
).catch(handleError)
trackEvent('PackInstall', {
id: project.value.id,
version_id: versionId.value,
title: project.value.title,
source: 'ConfirmModal',
})
onInstall.value(versionId.value)
installing.value = false
}
</script>
<template>
<ModalWrapper ref="confirmModal" header="Are you sure?" :on-hide="onInstall">
<div class="modal-body">
<p>You already have this modpack installed. Are you sure you want to install it again?</p>
<div class="input-group push-right">
<Button @click="() => $refs.confirmModal.hide()"><XIcon />Cancel</Button>
<Button color="primary" :disabled="installing" @click="install()"
><DownloadIcon /> {{ installing ? 'Installing' : 'Install' }}</Button
>
</div>
</div>
</ModalWrapper>
</template>
<style lang="scss" scoped>
.modal-body {
display: flex;
flex-direction: column;
gap: 1rem;
}
</style>
@@ -18,8 +18,9 @@ import { useRouter } from 'vue-router'
import ConfirmDeleteInstanceModal from '@/components/ui/modal/ConfirmDeleteInstanceModal.vue'
import { trackEvent } from '@/helpers/analytics'
import { duplicate, edit, edit_icon, list, remove } from '@/helpers/profile'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { GameInstance, InstanceSettingsTabProps } from '../../../helpers/types'
import type { GameInstance } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
@@ -27,21 +28,21 @@ const router = useRouter()
const deleteConfirmModal = ref()
const props = defineProps<InstanceSettingsTabProps>()
const { instance } = injectInstanceSettings()
const title = ref(props.instance.name)
const icon: Ref<string | undefined> = ref(props.instance.icon_path)
const groups = ref(props.instance.groups)
const title = ref(instance.name)
const icon: Ref<string | undefined> = ref(instance.icon_path)
const groups = ref(instance.groups)
const newCategoryInput = ref('')
const installing = computed(() => props.instance.install_stage !== 'installed')
const installing = computed(() => instance.install_stage !== 'installed')
async function duplicateProfile() {
await duplicate(props.instance.path).catch(handleError)
await duplicate(instance.path).catch(handleError)
trackEvent('InstanceDuplicate', {
loader: props.instance.loader,
game_version: props.instance.game_version,
loader: instance.loader,
game_version: instance.game_version,
})
}
@@ -52,7 +53,7 @@ const availableGroups = computed(() => [
async function resetIcon() {
icon.value = undefined
await edit_icon(props.instance.path, null).catch(handleError)
await edit_icon(instance.path, null).catch(handleError)
trackEvent('InstanceRemoveIcon')
}
@@ -70,7 +71,7 @@ async function setIcon() {
if (!value) return
icon.value = value
await edit_icon(props.instance.path, icon.value).catch(handleError)
await edit_icon(instance.path, icon.value).catch(handleError)
trackEvent('InstanceSetIcon')
}
@@ -101,7 +102,7 @@ watch(
[title, groups, groups],
async () => {
if (removing.value) return
await edit(props.instance.path, editProfileObject.value).catch(handleError)
await edit(instance.path, editProfileObject.value).catch(handleError)
},
{ deep: true },
)
@@ -109,11 +110,11 @@ watch(
const removing = ref(false)
async function removeProfile() {
removing.value = true
const path = props.instance.path
const path = instance.path
trackEvent('InstanceRemove', {
loader: props.instance.loader,
game_version: props.instance.game_version,
loader: instance.loader,
game_version: instance.game_version,
})
await router.push({ path: '/' })
@@ -218,7 +219,7 @@ const messages = defineMessages({
:src="icon ? convertFileSrc(icon) : icon"
size="108px"
class="!border-4 group-hover:brightness-75"
:tint-by="props.instance.path"
:tint-by="instance.path"
no-shadow
/>
<div class="absolute top-0 right-0 m-2">
@@ -10,22 +10,21 @@ import { computed, ref, watch } from 'vue'
import { edit } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { AppSettings, Hooks, InstanceSettingsTabProps } from '../../../helpers/types'
import type { AppSettings, Hooks } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const { instance } = injectInstanceSettings()
const globalSettings = (await get().catch(handleError)) as AppSettings
const overrideHooks = ref(
!!props.instance.hooks.pre_launch ||
!!props.instance.hooks.wrapper ||
!!props.instance.hooks.post_exit,
!!instance.hooks.pre_launch || !!instance.hooks.wrapper || !!instance.hooks.post_exit,
)
const hooks = ref(props.instance.hooks ?? globalSettings.hooks)
const hooks = ref(instance.hooks ?? globalSettings.hooks)
const editProfileObject = computed(() => {
const editProfile: {
@@ -41,7 +40,7 @@ const editProfileObject = computed(() => {
watch(
[overrideHooks, hooks],
async () => {
await edit(props.instance.path, editProfileObject.value)
await edit(instance.path, editProfileObject.value)
},
{ deep: true },
)
@@ -27,17 +27,15 @@ import {
update_repair_modrinth,
} from '@/helpers/profile'
import { get_game_versions, get_loaders } from '@/helpers/tags'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { InstanceSettingsTabProps, Manifest } from '../../../helpers/types'
import type { Manifest } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const queryClient = useQueryClient()
const props = defineProps<InstanceSettingsTabProps>()
const emit = defineEmits<{
unlinked: []
}>()
const { instance, offline, isMinecraftServer, onUnlinked } = injectInstanceSettings()
const [
fabric_versions,
@@ -75,9 +73,9 @@ const [
])
const { data: modpackInfo } = useQuery({
queryKey: computed(() => ['linkedModpackInfo', props.instance.path]),
queryFn: () => get_linked_modpack_info(props.instance.path, 'must_revalidate'),
enabled: computed(() => !!props.instance.linked_data?.project_id && !props.offline),
queryKey: computed(() => ['linkedModpackInfo', instance.path]),
queryFn: () => get_linked_modpack_info(instance.path, 'must_revalidate'),
enabled: computed(() => !!instance.linked_data?.project_id && !offline),
})
const repairing = ref(false)
@@ -103,13 +101,13 @@ function getManifest(loader: string) {
provideAppBackup({
async createBackup() {
const allProfiles = await list()
const prefix = `${props.instance.name} - Backup #`
const prefix = `${instance.name} - Backup #`
const existingNums = allProfiles
.filter((p) => p.name.startsWith(prefix))
.map((p) => parseInt(p.name.slice(prefix.length), 10))
.filter((n) => !isNaN(n))
const nextNum = existingNums.length > 0 ? Math.max(...existingNums) + 1 : 1
const newPath = await duplicate(props.instance.path)
const newPath = await duplicate(instance.path)
await edit(newPath, { name: `${prefix}${nextNum}` })
},
})
@@ -120,30 +118,27 @@ provideInstallationSettings({
const rows = [
{
label: formatMessage(commonMessages.platformLabel),
value: formatLoaderLabel(props.instance.loader),
value: formatLoaderLabel(instance.loader),
},
{
label: formatMessage(commonMessages.gameVersionLabel),
value: props.instance.game_version,
value: instance.game_version,
},
]
if (props.instance.loader !== 'vanilla' && props.instance.loader_version) {
if (instance.loader !== 'vanilla' && instance.loader_version) {
rows.push({
label: formatMessage(messages.loaderVersion, {
loader: formatLoaderLabel(props.instance.loader),
loader: formatLoaderLabel(instance.loader),
}),
value: props.instance.loader_version,
value: instance.loader_version,
})
}
return rows
}),
isLinked: computed(() => !!props.instance.linked_data?.locked),
isLinked: computed(() => !!instance.linked_data?.locked),
isBusy: computed(
() =>
props.instance.install_stage !== 'installed' ||
repairing.value ||
reinstalling.value ||
!!props.offline,
instance.install_stage !== 'installed' || repairing.value || reinstalling.value || !!offline,
),
modpack: computed(() => {
if (!modpackInfo.value) return null
@@ -154,9 +149,9 @@ provideInstallationSettings({
versionNumber: modpackInfo.value.version?.version_number,
}
}),
currentPlatform: computed(() => props.instance.loader),
currentGameVersion: computed(() => props.instance.game_version),
currentLoaderVersion: computed(() => props.instance.loader_version ?? ''),
currentPlatform: computed(() => instance.loader),
currentGameVersion: computed(() => instance.game_version),
currentLoaderVersion: computed(() => instance.loader_version ?? ''),
availablePlatforms: loaders?.value?.map((x) => x.name) ?? [],
resolveGameVersions(loader, showSnapshots) {
@@ -199,50 +194,50 @@ provideInstallationSettings({
if (platform !== 'vanilla' && loaderVersionId) {
editProfile.loader_version = loaderVersionId
}
await edit(props.instance.path, editProfile).catch(handleError)
await edit(instance.path, editProfile).catch(handleError)
},
afterSave: async () => {
await install(props.instance.path, false).catch(handleError)
await install(instance.path, false).catch(handleError)
trackEvent('InstanceRepair', {
loader: props.instance.loader,
game_version: props.instance.game_version,
loader: instance.loader,
game_version: instance.game_version,
})
},
async repair() {
repairing.value = true
await install(props.instance.path, true).catch(handleError)
await install(instance.path, true).catch(handleError)
repairing.value = false
trackEvent('InstanceRepair', {
loader: props.instance.loader,
game_version: props.instance.game_version,
loader: instance.loader,
game_version: instance.game_version,
})
},
async reinstallModpack() {
reinstalling.value = true
await update_repair_modrinth(props.instance.path).catch(handleError)
await update_repair_modrinth(instance.path).catch(handleError)
reinstalling.value = false
trackEvent('InstanceRepair', {
loader: props.instance.loader,
game_version: props.instance.game_version,
loader: instance.loader,
game_version: instance.game_version,
})
},
async unlinkModpack() {
await edit(props.instance.path, {
await edit(instance.path, {
linked_data: null as unknown as undefined,
})
await queryClient.invalidateQueries({
queryKey: ['linkedModpackInfo', props.instance.path],
queryKey: ['linkedModpackInfo', instance.path],
})
emit('unlinked')
onUnlinked()
},
getCachedModpackVersions: () => null,
async fetchModpackVersions() {
const versions = await get_project_versions(props.instance.linked_data!.project_id!).catch(
const versions = await get_project_versions(instance.linked_data!.project_id!).catch(
handleError,
)
return (versions ?? []) as Labrinth.Versions.v2.Version[]
@@ -255,25 +250,25 @@ provideInstallationSettings({
},
async onModpackVersionConfirm(version) {
await update_managed_modrinth_version(props.instance.path, version.id)
await update_managed_modrinth_version(instance.path, version.id)
await queryClient.invalidateQueries({
queryKey: ['linkedModpackInfo', props.instance.path],
queryKey: ['linkedModpackInfo', instance.path],
})
},
updaterModalProps: computed(() => ({
isApp: true,
currentVersionId:
modpackInfo.value?.update_version_id ?? props.instance.linked_data?.version_id ?? '',
modpackInfo.value?.update_version_id ?? instance.linked_data?.version_id ?? '',
projectIconUrl: modpackInfo.value?.project?.icon_url,
projectName: modpackInfo.value?.project?.title ?? 'Modpack',
currentGameVersion: props.instance.game_version,
currentLoader: props.instance.loader,
currentGameVersion: instance.game_version,
currentLoader: instance.loader,
})),
isServer: false,
isApp: true,
showModpackVersionActions: !props.isMinecraftServer,
showModpackVersionActions: !isMinecraftServer.value,
repairing,
reinstalling,
})
@@ -14,34 +14,31 @@ import JavaSelector from '@/components/ui/JavaSelector.vue'
import useMemorySlider from '@/composables/useMemorySlider'
import { edit, get_optimal_jre_key } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { AppSettings, InstanceSettingsTabProps } from '../../../helpers/types'
import type { AppSettings } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const { instance } = injectInstanceSettings()
const globalSettings = (await get().catch(handleError)) as unknown as AppSettings
const overrideJavaInstall = ref(!!props.instance.java_path)
const optimalJava = readonly(await get_optimal_jre_key(props.instance.path).catch(handleError))
const javaInstall = ref({ path: optimalJava.path ?? props.instance.java_path })
const overrideJavaInstall = ref(!!instance.java_path)
const optimalJava = readonly(await get_optimal_jre_key(instance.path).catch(handleError))
const javaInstall = ref({ path: optimalJava.path ?? instance.java_path })
const overrideJavaArgs = ref((props.instance.extra_launch_args?.length ?? 0) > 0)
const javaArgs = ref(
(props.instance.extra_launch_args ?? globalSettings.extra_launch_args).join(' '),
)
const overrideJavaArgs = ref((instance.extra_launch_args?.length ?? 0) > 0)
const javaArgs = ref((instance.extra_launch_args ?? globalSettings.extra_launch_args).join(' '))
const overrideEnvVars = ref((props.instance.custom_env_vars?.length ?? 0) > 0)
const overrideEnvVars = ref((instance.custom_env_vars?.length ?? 0) > 0)
const envVars = ref(
(props.instance.custom_env_vars ?? globalSettings.custom_env_vars)
.map((x) => x.join('='))
.join(' '),
(instance.custom_env_vars ?? globalSettings.custom_env_vars).map((x) => x.join('=')).join(' '),
)
const overrideMemorySettings = ref(!!props.instance.memory)
const memory = ref(props.instance.memory ?? globalSettings.memory)
const overrideMemorySettings = ref(!!instance.memory)
const memory = ref(instance.memory ?? globalSettings.memory)
const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) as unknown as {
maxMemory: number
snapPoints: number[]
@@ -79,7 +76,7 @@ watch(
memory,
],
async () => {
await edit(props.instance.path, editProfileObject.value)
await edit(instance.path, editProfileObject.value)
},
{ deep: true },
)
@@ -11,24 +11,23 @@ import { computed, type Ref, ref, watch } from 'vue'
import { edit } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { injectInstanceSettings } from '@/providers/instance-settings'
import type { AppSettings, InstanceSettingsTabProps } from '../../../helpers/types'
import type { AppSettings } from '../../../helpers/types'
const { handleError } = injectNotificationManager()
const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const { instance } = injectInstanceSettings()
const globalSettings = (await get().catch(handleError)) as AppSettings
const overrideWindowSettings = ref(
!!props.instance.game_resolution || !!props.instance.force_fullscreen,
)
const overrideWindowSettings = ref(!!instance.game_resolution || !!instance.force_fullscreen)
const resolution: Ref<[number, number]> = ref(
props.instance.game_resolution ?? (globalSettings.game_resolution.slice() as [number, number]),
instance.game_resolution ?? (globalSettings.game_resolution.slice() as [number, number]),
)
const fullscreenSetting: Ref<boolean> = ref(
props.instance.force_fullscreen ?? globalSettings.force_fullscreen,
instance.force_fullscreen ?? globalSettings.force_fullscreen,
)
const editProfileObject = computed(() => {
@@ -47,7 +46,7 @@ const editProfileObject = computed(() => {
watch(
[overrideWindowSettings, resolution, fullscreenSetting],
async () => {
await edit(props.instance.path, editProfileObject.value)
await edit(instance.path, editProfileObject.value)
},
{ deep: true },
)
@@ -20,9 +20,8 @@ import {
} from '@modrinth/ui'
import { getVersion } from '@tauri-apps/api/app'
import { platform as getOsPlatform, version as getOsVersion } from '@tauri-apps/plugin-os'
import { computed, ref, watch } from 'vue'
import { ref, watch } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import AppearanceSettings from '@/components/ui/settings/AppearanceSettings.vue'
import DefaultInstanceSettings from '@/components/ui/settings/DefaultInstanceSettings.vue'
import FeatureFlagSettings from '@/components/ui/settings/FeatureFlagSettings.vue'
@@ -106,15 +105,13 @@ const tabs = [
},
]
const modal = ref()
const modal = ref<InstanceType<typeof TabbedModal> | null>(null)
function show() {
modal.value.show()
modal.value?.show()
}
const isOpen = computed(() => modal.value?.isOpen)
defineExpose({ show, isOpen })
defineExpose({ show })
const { progress, version: downloadingVersion } = injectAppUpdateDownloadProgress()
@@ -138,8 +135,8 @@ function devModeCount() {
settings.value.developer_mode = !!themeStore.devMode
devModeCounter.value = 0
if (!themeStore.devMode && tabs[modal.value.selectedTab].developerOnly) {
modal.value.setTab(0)
if (!themeStore.devMode && tabs[modal.value!.selectedTab].developerOnly) {
modal.value!.setTab(0)
}
}
}
@@ -152,49 +149,46 @@ const messages = defineMessages({
})
</script>
<template>
<ModalWrapper ref="modal">
<TabbedModal ref="modal" :tabs="tabs.filter((t) => !t.developerOnly || themeStore.devMode)">
<template #title>
<span class="flex items-center gap-2 text-lg font-extrabold text-contrast">
<SettingsIcon /> Settings
</span>
</template>
<TabbedModal :tabs="tabs.filter((t) => !t.developerOnly || themeStore.devMode)">
<template #footer>
<div class="mt-auto text-secondary text-sm">
<div class="mb-3">
<template v-if="progress > 0 && progress < 1">
<p class="m-0 mb-2">
{{ formatMessage(messages.downloading, { version: downloadingVersion }) }}
</p>
<ProgressBar :progress="progress" />
</template>
</div>
<p v-if="themeStore.devMode" class="text-brand font-semibold m-0 mb-2">
{{ formatMessage(developerModeEnabled) }}
</p>
<div class="flex items-center gap-3">
<button
class="p-0 m-0 bg-transparent border-none cursor-pointer button-animation"
:class="{
'text-brand': themeStore.devMode,
'text-secondary': !themeStore.devMode,
}"
@click="devModeCount"
>
<ModrinthIcon class="w-6 h-6" />
</button>
<div>
<p class="m-0">Modrinth App {{ version }}</p>
<p class="m-0">
<span v-if="osPlatform === 'macos'">macOS</span>
<span v-else class="capitalize">{{ osPlatform }}</span>
{{ osVersion }}
</p>
</div>
<template #footer>
<div class="mt-auto text-secondary text-sm">
<div class="mb-3">
<template v-if="progress > 0 && progress < 1">
<p class="m-0 mb-2">
{{ formatMessage(messages.downloading, { version: downloadingVersion }) }}
</p>
<ProgressBar :progress="progress" />
</template>
</div>
<p v-if="themeStore.devMode" class="text-brand font-semibold m-0 mb-2">
{{ formatMessage(developerModeEnabled) }}
</p>
<div class="flex items-center gap-3">
<button
class="p-0 m-0 bg-transparent border-none cursor-pointer button-animation"
:class="{
'text-brand': themeStore.devMode,
'text-secondary': !themeStore.devMode,
}"
@click="devModeCount"
>
<ModrinthIcon class="w-6 h-6" />
</button>
<div>
<p class="m-0">Modrinth App {{ version }}</p>
<p class="m-0">
<span v-if="osPlatform === 'macos'">macOS</span>
<span v-else class="capitalize">{{ osPlatform }}</span>
{{ osVersion }}
</p>
</div>
</div>
</template>
</TabbedModal>
</ModalWrapper>
</div>
</template>
</TabbedModal>
</template>
@@ -12,14 +12,13 @@ import {
Avatar,
commonMessages,
defineMessage,
NewModal,
TabbedModal,
type TabbedModalTab,
useVIntl,
} from '@modrinth/ui'
import { useQueryClient } from '@tanstack/vue-query'
import { convertFileSrc } from '@tauri-apps/api/core'
import { computed, nextTick, ref, useTemplateRef, watch } from 'vue'
import { computed, nextTick, ref, watch } from 'vue'
import GeneralSettings from '@/components/ui/instance_settings/GeneralSettings.vue'
import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
@@ -28,12 +27,16 @@ import JavaSettings from '@/components/ui/instance_settings/JavaSettings.vue'
import WindowSettings from '@/components/ui/instance_settings/WindowSettings.vue'
import { get_project_v3 } from '@/helpers/cache'
import { get_linked_modpack_info } from '@/helpers/profile'
import { provideInstanceSettings } from '@/providers/instance-settings'
import type { InstanceSettingsTabProps } from '../../../helpers/types'
import type { GameInstance } from '../../../helpers/types'
const { formatMessage } = useVIntl()
const props = defineProps<InstanceSettingsTabProps>()
const props = defineProps<{
instance: GameInstance
offline?: boolean
}>()
const emit = defineEmits<{
unlinked: []
}>()
@@ -41,6 +44,13 @@ const emit = defineEmits<{
const isMinecraftServer = ref(false)
const handleUnlinked = () => emit('unlinked')
provideInstanceSettings({
instance: props.instance,
offline: props.offline,
isMinecraftServer,
onUnlinked: handleUnlinked,
})
watch(
() => props.instance,
(instance) => {
@@ -58,7 +68,7 @@ watch(
{ immediate: true },
)
const tabs = computed<TabbedModalTab<InstanceSettingsTabProps>[]>(() => [
const tabs = computed<TabbedModalTab[]>(() => [
{
name: defineMessage({
id: 'instance.settings.tabs.general',
@@ -102,8 +112,7 @@ const tabs = computed<TabbedModalTab<InstanceSettingsTabProps>[]>(() => [
])
const queryClient = useQueryClient()
const modal = ref()
const tabbedModal = useTemplateRef('tabbedModal')
const tabbedModal = ref<InstanceType<typeof TabbedModal> | null>(null)
function show(tabIndex?: number) {
if (props.instance.linked_data?.project_id) {
@@ -112,7 +121,7 @@ function show(tabIndex?: number) {
queryFn: () => get_linked_modpack_info(props.instance.path, 'stale_while_revalidate'),
})
}
modal.value.show()
tabbedModal.value?.show()
if (tabIndex !== undefined) {
nextTick(() => tabbedModal.value?.setTab(tabIndex))
}
@@ -121,8 +130,9 @@ function show(tabIndex?: number) {
defineExpose({ show })
</script>
<template>
<NewModal
ref="modal"
<TabbedModal
ref="tabbedModal"
:tabs="tabs"
:max-width="'min(928px, calc(95vw - 10rem))'"
:width="'min(928px, calc(95vw - 10rem))'"
>
@@ -139,19 +149,5 @@ defineExpose({ show })
}}</span>
</span>
</template>
<TabbedModal
ref="tabbedModal"
:tabs="
tabs.map((tab) => ({
...tab,
props: {
...props,
isMinecraftServer,
onUnlinked: handleUnlinked,
},
}))
"
/>
</NewModal>
</TabbedModal>
</template>
@@ -0,0 +1,84 @@
<template>
<NewModal ref="modal" :header="formatMessage(messages.header)" fade="warning" max-width="500px">
<Admonition type="warning" :header="formatMessage(messages.admonitionHeader)">
{{ formatMessage(messages.admonitionBody, { instanceName }) }}
</Admonition>
<template #actions>
<div class="flex gap-2 justify-end">
<ButtonStyled type="outlined">
<button class="!border !border-surface-4" @click="handleGoToInstance">
<ExternalIcon />
{{ formatMessage(messages.goToInstance) }}
</button>
</ButtonStyled>
<ButtonStyled color="orange">
<button @click="handleCreateAnyway">
<PlusIcon />
{{ formatMessage(messages.createAnyway) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
</template>
<script setup lang="ts">
import { ExternalIcon, PlusIcon } from '@modrinth/assets'
import { Admonition, ButtonStyled, defineMessages, NewModal, useVIntl } from '@modrinth/ui'
import { ref } from 'vue'
const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'app.instance.modpack-already-installed.header',
defaultMessage: 'Modpack already installed',
},
admonitionHeader: {
id: 'app.instance.modpack-already-installed.admonition-header',
defaultMessage: 'Duplicate modpack',
},
admonitionBody: {
id: 'app.instance.modpack-already-installed.admonition-body',
defaultMessage: 'This modpack is already installed in the "{instanceName}" instance.',
},
goToInstance: {
id: 'app.instance.modpack-already-installed.go-to-instance',
defaultMessage: 'Go to instance',
},
createAnyway: {
id: 'app.instance.modpack-already-installed.create-anyway',
defaultMessage: 'Create anyway',
},
})
const emit = defineEmits<{
(e: 'go-to-instance', instancePath: string): void
(e: 'create-anyway'): void
}>()
const modal = ref<InstanceType<typeof NewModal>>()
const instanceName = ref('')
const instancePath = ref('')
function show(name: string, path: string) {
instanceName.value = name
instancePath.value = path
modal.value?.show()
}
function handleGoToInstance() {
modal.value?.hide()
emit('go-to-instance', instancePath.value)
}
function handleCreateAnyway() {
modal.value?.hide()
emit('create-anyway')
}
defineExpose({
show,
})
</script>
+2 -8
View File
@@ -1,6 +1,6 @@
import type { ModrinthId } from '@modrinth/utils'
type GameInstance = {
export type GameInstance = {
path: string
install_stage: InstallStage
@@ -46,7 +46,7 @@ type LinkedData = {
locked: boolean
}
type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
export type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
type ContentFile = {
metadata?: {
@@ -128,9 +128,3 @@ type AppSettings = {
prev_custom_dir?: string
migrated: boolean
}
export type InstanceSettingsTabProps = {
instance: GameInstance
offline?: boolean
isMinecraftServer?: boolean
}
@@ -5,6 +5,96 @@
"app.auth-servers.unreachable.header": {
"message": "تعذر الوصول إلى خوادم المصادقة"
},
"app.export-modal.description-placeholder": {
"message": "ادخل وصف التعديل..."
},
"app.export-modal.export-button": {
"message": "تصدير"
},
"app.export-modal.header": {
"message": "تصدير حزمة التعديل"
},
"app.export-modal.modpack-name-label": {
"message": "إسم حزمة التعديل"
},
"app.export-modal.modpack-name-placeholder": {
"message": "إسم حزمة التعديل"
},
"app.export-modal.select-files-label": {
"message": "حدد الملفات والمجلدات المراد تضمينها في الحزمة"
},
"app.export-modal.version-number-label": {
"message": "رقم الإصدار"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "سيتم حذف جميع البيانات الخاصة بمثيلك نهائيًا، بما في ذلك عوالمك والتكوينات وكل المحتوى المثبت."
},
"app.instance.confirm-delete.admonition-header": {
"message": "لا يمكن التراجع عن هذا الإجراء"
},
"app.instance.confirm-delete.delete-button": {
"message": "حذف المثيل"
},
"app.instance.confirm-delete.header": {
"message": "حذف المثيل"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "تم تثبيت حزمة التعديل هذه بالفعل في مثيل \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "حزمة تعديل مكررة"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "إنشاء على أي حال"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "انتقل إلى المثال"
},
"app.instance.modpack-already-installed.header": {
"message": "تم تثبيت حزمة التعديل بالفعل"
},
"app.instance.mods.content-type-project": {
"message": "مشروع"
},
"app.instance.mods.copy-link": {
"message": "نسخ الرابط"
},
"app.instance.mods.installing": {
"message": "جاري التثبيت..."
},
"app.instance.mods.modpack-fallback": {
"message": "حزمة التعديل"
},
"app.instance.mods.project-was-added": {
"message": "تمت إضافة \"{name}\"."
},
"app.instance.mods.projects-were-added": {
"message": "تمت إضافة {count} من المشاريع"
},
"app.instance.mods.share-text": {
"message": "تحقق من المشاريع التي أستخدمها في حزمة التعديل الخاص بي!"
},
"app.instance.mods.share-title": {
"message": "مشاركة محتوى حزمة التعديل"
},
"app.instance.mods.show-file": {
"message": "عرض الملف"
},
"app.instance.mods.successfully-uploaded": {
"message": "تم الرفع بنجاح"
},
"app.instance.mods.unknown-version": {
"message": "غير معروف"
},
"app.instance.mods.updating": {
"message": "جارٍ التحديث..."
},
"app.modal.install-to-play.content-required": {
"message": "المحتوى مطلوب"
},
"app.modal.install-to-play.header": {
"message": "نزل للعب"
},
@@ -14,12 +104,21 @@
"app.modal.install-to-play.mod-count": {
"message": ""
},
"app.modal.install-to-play.required-modpack": {
"message": "حزمة التعديل مطلوبة"
},
"app.modal.install-to-play.server-requires-mods": {
"message": "يتطلب هذا الخادم تعديلات للعب. انقر فوق \"تثبيت\" لإعداد الملفات المطلوبة من Modrinth، ثم قم بتشغيله مباشرة إلى الخادم."
},
"app.modal.install-to-play.shared-instance": {
"message": "حُزْمَة مشاركة"
},
"app.modal.install-to-play.shared-server-instance": {
"message": "حُزْمَة خادم مشاركة"
},
"app.modal.install-to-play.view-contents": {
"message": "عرض المحتويات"
},
"app.modal.update-to-play.header": {
"message": "حدث للعب"
},
@@ -56,6 +155,33 @@
"app.settings.tabs.resource-management": {
"message": "إدارة الموارد"
},
"app.update-popup.body": {
"message": "تطبيق Modrinth v{version} جاهز للتثبيت! أعد التحميل للتحديث الآن، أو تلقائيًا عند إغلاق تطبيق Modrinth."
},
"app.update-popup.body.download-complete": {
"message": "انتهى تنزيل تطبيق Modrinth v{version}. أعد التحميل للتحديث الآن، أو تلقائيًا عند إغلاق تطبيق Modrinth."
},
"app.update-popup.body.linux": {
"message": "تطبيق Modrinth v {version} متاح. استخدم مدير الحزم الخاص بك للتحديث للحصول على أحدث الميزات والإصلاحات!"
},
"app.update-popup.body.metered": {
"message": "تطبيق Modrinth v{version} متاح الآن! وبما أنك متصل بشبكة مقيّدة، لم نقم بتنزيله تلقائيًا."
},
"app.update-popup.changelog": {
"message": "سجل التغيير"
},
"app.update-popup.download": {
"message": "تنزيل ({size})"
},
"app.update-popup.download-complete": {
"message": "اكتمل التنزيل"
},
"app.update-popup.reload": {
"message": "إعادة تحميل"
},
"app.update-popup.title": {
"message": "تحديث متاح"
},
"app.update.complete-toast.text": {
"message": "انقر هنا لعرض سجلّ التغييرات."
},
@@ -353,6 +479,9 @@
"instance.worlds.incompatible_server": {
"message": "الخادم غير متوافق"
},
"instance.worlds.linked_server": {
"message": "تدار بواسطة مشروع الخادم"
},
"instance.worlds.no_contact": {
"message": "تعذّر الاتصال بالخادم"
},
@@ -388,5 +517,17 @@
},
"search.filter.locked.instance.sync": {
"message": "مزامنة مع النسخة"
},
"search.filter.locked.server": {
"message": "يقدمها الخادم"
},
"search.filter.locked.server-environment.title": {
"message": "يمكن إضافة التعديلات من جانب العميل فقط إلى مثيل الخادم"
},
"search.filter.locked.server-game-version.title": {
"message": "يتم توفير نسخة اللعبة من قبل الخادم"
},
"search.filter.locked.server-loader.title": {
"message": "يتم توفير المحمّل من قبل الخادم"
}
}
+19 -1
View File
@@ -5,6 +5,12 @@
"app.auth-servers.unreachable.header": {
"message": "Připojení k autorizačním serverům se nezdařilo"
},
"app.export-modal.description-placeholder": {
"message": "Přidej popis modpacku..."
},
"app.instance.confirm-delete.admonition-body": {
"message": "Všechna data z instance budou navždy smazána, včetně světů, nastavení a všeho ostatního."
},
"app.modal.install-to-play.header": {
"message": "Nainstaluj ke hraní"
},
@@ -56,6 +62,9 @@
"app.settings.tabs.resource-management": {
"message": "Správa zdrojů"
},
"app.update-popup.download": {
"message": "Stáhnout ({size})"
},
"app.update.complete-toast.text": {
"message": "Kliknutím sem zobrazíte seznam změn."
},
@@ -384,9 +393,18 @@
"message": "Verze hry je poskytnut instanci"
},
"search.filter.locked.instance-loader.title": {
"message": "Spouštěč je poskytnut instanci"
"message": "Spouštěč je poskytnut instancí"
},
"search.filter.locked.instance.sync": {
"message": "Synchronizováno z instancí"
},
"search.filter.locked.server-environment.title": {
"message": "Jen klientské mody mohou být přidány na server"
},
"search.filter.locked.server-game-version.title": {
"message": "Verzi hry poskytuje server"
},
"search.filter.locked.server-loader.title": {
"message": "Loader zprostředkovává server"
}
}
@@ -5,6 +5,78 @@
"app.auth-servers.unreachable.header": {
"message": "Kan ikke nå autentificeringsservere"
},
"app.export-modal.description-placeholder": {
"message": "Indtast modpack beskrivelse..."
},
"app.export-modal.export-button": {
"message": "Eksporter"
},
"app.export-modal.header": {
"message": "Eksporter modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Modpack Navn"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpack navn"
},
"app.export-modal.select-files-label": {
"message": "Vælg filer og mapper til at inkludere i pakken"
},
"app.export-modal.version-number-label": {
"message": "Versionsnummer"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Al' data for din instance vil blive permanent slettet, dette inkludere dine verdener, konfigurationer, og alt installeret indhold."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Denne handling kan ikke fortrydes"
},
"app.instance.confirm-delete.delete-button": {
"message": "Slet instance"
},
"app.instance.confirm-delete.header": {
"message": "Slet instance"
},
"app.instance.mods.content-type-project": {
"message": "projekt"
},
"app.instance.mods.copy-link": {
"message": "Kopier link"
},
"app.instance.mods.installing": {
"message": "Installer..."
},
"app.instance.mods.modpack-fallback": {
"message": "Modpack"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" blev tilføjet"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projekter blev tilføjet"
},
"app.instance.mods.share-text": {
"message": "Tjek ud disse projekter jeg bruger i min modpack!"
},
"app.instance.mods.share-title": {
"message": "Deler modpack indhold"
},
"app.instance.mods.show-file": {
"message": "Vis filer"
},
"app.instance.mods.successfully-uploaded": {
"message": "Uploadet"
},
"app.instance.mods.unknown-version": {
"message": "Ukendt"
},
"app.instance.mods.updating": {
"message": "Opdatere..."
},
"app.modal.install-to-play.content-required": {
"message": "Indhold krævet"
},
@@ -392,6 +464,9 @@
"instance.worlds.incompatible_server": {
"message": "Serveren er uforenelig"
},
"instance.worlds.linked_server": {
"message": "Styret af server projektet"
},
"instance.worlds.no_contact": {
"message": "Serveren kunne ikke blive kontaktet"
},
@@ -428,6 +503,12 @@
"search.filter.locked.instance.sync": {
"message": "Synkroniser med instance"
},
"search.filter.locked.server": {
"message": "Givet af serveren"
},
"search.filter.locked.server-environment.title": {
"message": "Kun klient-sided mods kan blive tilføjet til denne server instance"
},
"search.filter.locked.server-game-version.title": {
"message": "Spille version er givet af serveren"
},
+15 -3
View File
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "Instanz löschen"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Dieses Modpack ist bereits in der Instanz „{instanceName}“ installiert."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Modpack duplizieren"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Trotzdem erstellen"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Gehe zu Instanz"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack bereits installiert"
},
"app.instance.mods.content-type-project": {
"message": "Projekt"
},
@@ -71,9 +86,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "Erfolgreich hochgeladen"
},
"app.instance.mods.switch-version": {
"message": "Version wechseln"
},
"app.instance.mods.unknown-version": {
"message": "Unbekannt"
},
+15 -3
View File
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "Instanz löschen"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Dieses Modpack ist bereits in der Instanz „{instanceName}“ installiert."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Modpack duplizieren"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Trotzdem erstellen"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Gehe zu Instanz"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack bereits installiert"
},
"app.instance.mods.content-type-project": {
"message": "Projekt"
},
@@ -71,9 +86,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "Erfolgreich hochgeladen"
},
"app.instance.mods.switch-version": {
"message": "Version wechseln"
},
"app.instance.mods.unknown-version": {
"message": "Unbekannt"
},
+15 -3
View File
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "Delete instance"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "This modpack is already installed in the \"{instanceName}\" instance."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Duplicate modpack"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Create anyway"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Go to instance"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack already installed"
},
"app.instance.mods.content-type-project": {
"message": "project"
},
@@ -71,9 +86,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "Successfully uploaded"
},
"app.instance.mods.switch-version": {
"message": "Switch version"
},
"app.instance.mods.unknown-version": {
"message": "Unknown"
},
@@ -5,8 +5,86 @@
"app.auth-servers.unreachable.header": {
"message": "No se puede acceder a los servidores de autenticación"
},
"app.instance.mods.switch-version": {
"message": "Cambiar versión"
"app.export-modal.description-placeholder": {
"message": "Escribe la descripción del modpack..."
},
"app.export-modal.export-button": {
"message": "Exportar"
},
"app.export-modal.header": {
"message": "Exportar modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Nombre del modpack"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nombre del modpack"
},
"app.export-modal.select-files-label": {
"message": "Seleccione archivos y carpetas para incluir en el paquete"
},
"app.export-modal.version-number-label": {
"message": "Número de versión"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Todos los datos de su instancia se eliminarán permanentemente, incluidos sus mundos, configuraciones y todo el contenido instalado."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Esta acción no se puede deshacer"
},
"app.instance.confirm-delete.delete-button": {
"message": "Eliminar instancia"
},
"app.instance.confirm-delete.header": {
"message": "Eliminar instancia"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Este modpack ya está instalado en la instancia \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Modpack duplicado"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Crea de todos modos"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Ir a la instancia"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack ya está instalado"
},
"app.instance.mods.content-type-project": {
"message": "proyecto"
},
"app.instance.mods.copy-link": {
"message": "Copiar enlace"
},
"app.instance.mods.installing": {
"message": "Instalando..."
},
"app.instance.mods.modpack-fallback": {
"message": "Modpack"
},
"app.instance.mods.project-was-added": {
"message": "Se ha añadido \"{name}\""
},
"app.instance.mods.projects-were-added": {
"message": "Se han añadido {count} proyectos"
},
"app.instance.mods.share-text": {
"message": "¡Echa un vistazo a los proyectos que utilizo en mi modpack!"
},
"app.instance.mods.share-title": {
"message": "Compartir contenido del modpack"
},
"app.instance.mods.show-file": {
"message": "Mostrar archivo"
},
"app.instance.mods.successfully-uploaded": {
"message": "Se ha subido correctamente"
},
"app.instance.mods.unknown-version": {
"message": "Desconocido"
+112 -1
View File
@@ -5,8 +5,95 @@
"app.auth-servers.unreachable.header": {
"message": "No se puede conectar con los servidores de autenticación"
},
"app.export-modal.description-placeholder": {
"message": "Escribe la descripción del modpack..."
},
"app.export-modal.export-button": {
"message": "Exportar"
},
"app.export-modal.header": {
"message": "Exportar modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Nombre del modpack"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nombre del modpack"
},
"app.export-modal.select-files-label": {
"message": "Seleccione archivos y carpetas para incluir en el paquete"
},
"app.export-modal.version-number-label": {
"message": "Número de versión"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Todos los datos de su instancia se eliminarán permanentemente, incluidos sus mundos, configuraciones y todo el contenido instalado."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Esta acción no se puede deshacer"
},
"app.instance.confirm-delete.delete-button": {
"message": "Eliminar instancia"
},
"app.instance.confirm-delete.header": {
"message": "Eliminar instancia"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Este modpack ya está instalado en la instancia \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Modpack duplicado"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Crea de todos modos"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Ir a la instancia"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack ya está instalado"
},
"app.instance.mods.content-type-project": {
"message": "proyecto"
},
"app.instance.mods.copy-link": {
"message": "Copiar enlace"
},
"app.instance.mods.installing": {
"message": "Instalando..."
},
"app.instance.mods.modpack-fallback": {
"message": "Modpack"
},
"app.instance.mods.project-was-added": {
"message": "Se ha añadido \"{name}\""
},
"app.instance.mods.projects-were-added": {
"message": "Se han añadido {count} proyectos"
},
"app.instance.mods.share-text": {
"message": "¡Echa un vistazo a los proyectos que utilizo en mi modpack!"
},
"app.instance.mods.share-title": {
"message": "Compartir contenido del modpack"
},
"app.instance.mods.show-file": {
"message": "Mostrar archivo"
},
"app.instance.mods.successfully-uploaded": {
"message": "Se ha subido correctamente"
},
"app.instance.mods.unknown-version": {
"message": "Desconocido"
},
"app.instance.mods.updating": {
"message": "Actualizando..."
},
"app.modal.install-to-play.content-required": {
"message": "Contenido requerido"
"message": "Contenido obligatorio"
},
"app.modal.install-to-play.header": {
"message": "Instala para jugar"
@@ -71,6 +158,15 @@
"app.update-popup.body": {
"message": "¡La versión v{version} de Modrinth está lista para instalarse! Actualiza ahora o automáticamente al cerrar la aplicación."
},
"app.update-popup.body.download-complete": {
"message": "Modrinth App v{version} se ha descargado. Actualiza la página ahora o espera a que se actualice automáticamente al cerrar Modrinth App."
},
"app.update-popup.body.linux": {
"message": "Ya está disponible Modrinth App v{version}. ¡Utiliza tu gestor de paquetes para actualizarla y disfrutar de las últimas funciones y correcciones!"
},
"app.update-popup.body.metered": {
"message": "¡Modrinth App v{version} ya está disponible! Como estás conectado a una red con tarifa por datos, no la hemos descargado automáticamente."
},
"app.update-popup.changelog": {
"message": "Registro de cambios"
},
@@ -80,6 +176,9 @@
"app.update-popup.download-complete": {
"message": "Descarga completada"
},
"app.update-popup.reload": {
"message": "Recargar"
},
"app.update-popup.title": {
"message": "Actualización disponible"
},
@@ -380,6 +479,9 @@
"instance.worlds.incompatible_server": {
"message": "Servidor es incompatible"
},
"instance.worlds.linked_server": {
"message": "Gestionado por el proyecto del servidor"
},
"instance.worlds.no_contact": {
"message": "No se pudo contactar con el servidor"
},
@@ -416,7 +518,16 @@
"search.filter.locked.instance.sync": {
"message": "Sincronizar con la instancia"
},
"search.filter.locked.server": {
"message": "Proporcionado por el servidor"
},
"search.filter.locked.server-environment.title": {
"message": "Solo se pueden añadir a la instancia del servidor modificaciones del lado del cliente"
},
"search.filter.locked.server-game-version.title": {
"message": "La versión del juego es proporcionada por el servidor"
},
"search.filter.locked.server-loader.title": {
"message": "El cargador lo proporciona el servidor"
}
}
+19 -1
View File
@@ -5,6 +5,24 @@
"app.auth-servers.unreachable.header": {
"message": "Todennuspalvelimiin ei saada yhteyttä"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpack nimi"
},
"app.export-modal.select-files-label": {
"message": "Valitse tiedostot ja kansiot pakettiin"
},
"app.export-modal.version-number-label": {
"message": "Versio numero"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" lisättiin"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projektia lisättiin"
},
"app.modal.install-to-play.content-required": {
"message": "Sisältö vaaditaan"
},
@@ -429,7 +447,7 @@
"message": "Lataajan antaa instanssi"
},
"search.filter.locked.instance.sync": {
"message": "Synkkaa instanssin kanssa"
"message": "Synkronoi instanssin kanssa"
},
"search.filter.locked.server": {
"message": "Palvelimen tarjoama"
@@ -5,9 +5,18 @@
"app.auth-servers.unreachable.header": {
"message": "Hindi maabot ang mga authentication server"
},
"app.export-modal.description-placeholder": {
"message": "Ilagay ang paglalarawan ng modpack..."
},
"app.export-modal.export-button": {
"message": "Iluwas"
},
"app.export-modal.modpack-name-label": {
"message": "Pangalan ng Modpack"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Pangalan ng modpack"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
@@ -17,6 +26,9 @@
"app.instance.mods.content-type-project": {
"message": "proyekto"
},
"app.instance.mods.copy-link": {
"message": "Kopyahin ang link"
},
"app.instance.mods.modpack-fallback": {
"message": "Modpack"
},
+17 -5
View File
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "Supprimer l'instance"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Ce modpack est déjà installé dans linstance « {instanceName} »."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Dupliquer le modpack"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Créer quand même"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Aller à linstance"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack déjà installé"
},
"app.instance.mods.content-type-project": {
"message": "projet"
},
@@ -71,9 +86,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "Mis en ligne avec succès"
},
"app.instance.mods.switch-version": {
"message": "Changer de version"
},
"app.instance.mods.unknown-version": {
"message": "Inconnu"
},
@@ -477,7 +489,7 @@
"message": "Vous pouvez seulement entrer directement dans les serveurs sur Minecraft Alpha 1.0.5+"
},
"instance.worlds.no_singleplayer_quick_play": {
"message": "Vous pouvez seulement entrer directement dans les mondes solo sur Minecraft Alpha 1.20+"
"message": "Vous pouvez seulement entrer directement dans les mondes solo sur Minecraft 1.20+"
},
"instance.worlds.play_instance": {
"message": "Jouer à l'instance"
@@ -516,6 +528,6 @@
"message": "Version du jeu est procurée par le serveur"
},
"search.filter.locked.server-loader.title": {
"message": "Loader est procuré par le serveur"
"message": "Le loader est procuré par le serveur"
}
}
@@ -5,6 +5,78 @@
"app.auth-servers.unreachable.header": {
"message": "לא ניתן לגשת לשרתי האימות"
},
"app.export-modal.description-placeholder": {
"message": "הזן את תיאור חבילת המודים..."
},
"app.export-modal.export-button": {
"message": "יצוא"
},
"app.export-modal.header": {
"message": "יצוא חבילת מודים"
},
"app.export-modal.modpack-name-label": {
"message": "שם חבילת המודים"
},
"app.export-modal.modpack-name-placeholder": {
"message": "שם חבילת המודים"
},
"app.export-modal.select-files-label": {
"message": "בחר קבצים ותיקיות להכללה בחבילה הזו"
},
"app.export-modal.version-number-label": {
"message": "מספר גרסה"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "כל הנתונים של ההתקנה שלך ימחקו לתמיד, זה כולל את העולמות שלך, ההגדרות וכל התוכן שהתקנת."
},
"app.instance.confirm-delete.admonition-header": {
"message": "הפעולה הזו לא ניתנת לביטול"
},
"app.instance.confirm-delete.delete-button": {
"message": "מחק התקנה"
},
"app.instance.confirm-delete.header": {
"message": "מחיקת התקנה"
},
"app.instance.mods.content-type-project": {
"message": "פרויקט"
},
"app.instance.mods.copy-link": {
"message": "העתק קישור"
},
"app.instance.mods.installing": {
"message": "מתקין..."
},
"app.instance.mods.modpack-fallback": {
"message": "חבילת מודים"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" נוסף"
},
"app.instance.mods.projects-were-added": {
"message": "{count} פרויקטים נוספו"
},
"app.instance.mods.share-text": {
"message": "בדוק את הפרויקטים שאני משתמש בהם בחבילת המודים שלי!"
},
"app.instance.mods.share-title": {
"message": "משתף את התוכן של חבילת המודים"
},
"app.instance.mods.show-file": {
"message": "מצא קובץ"
},
"app.instance.mods.successfully-uploaded": {
"message": "הועלה בהצלחה"
},
"app.instance.mods.unknown-version": {
"message": "לא ידוע"
},
"app.instance.mods.updating": {
"message": "מעדכן..."
},
"app.modal.install-to-play.content-required": {
"message": "תוכן נדרש"
},
+19 -1
View File
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "Profil törlése"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Ez a modcsomag már telepítve van a „{instanceName}” profilban."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Modcsomag duplikálása"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Létrehozás mindenképpen"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Profil megnyitása"
},
"app.instance.modpack-already-installed.header": {
"message": "A modcsomag már telepítve van"
},
"app.instance.mods.content-type-project": {
"message": "projekt"
},
@@ -62,6 +77,9 @@
"app.instance.mods.share-text": {
"message": "Nézd meg, milyen projekteket használok a modcsomagomban!"
},
"app.instance.mods.share-title": {
"message": "Modcsomag-tartalmak megosztása"
},
"app.instance.mods.show-file": {
"message": "Fájl megjelenítése"
},
@@ -99,7 +117,7 @@
"message": "Megosztott szerverprofil"
},
"app.modal.install-to-play.view-contents": {
"message": "Tartalom megjelenítése"
"message": "Tartalom megtekintése"
},
"app.modal.update-to-play.header": {
"message": "Frissítsd a játékhoz"
@@ -5,6 +5,93 @@
"app.auth-servers.unreachable.header": {
"message": "Tidak dapat terhubung ke server autentikasi"
},
"app.export-modal.description-placeholder": {
"message": "Masukkan deskripsi paket mod..."
},
"app.export-modal.export-button": {
"message": "Ekspor"
},
"app.export-modal.header": {
"message": "Ekspor paket mod"
},
"app.export-modal.modpack-name-label": {
"message": "Nama Paket Mod"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nama paket mod"
},
"app.export-modal.select-files-label": {
"message": "Pilih berkas dan folder yang ingin dimasukkan ke paket"
},
"app.export-modal.version-number-label": {
"message": "Nomor versi"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Semua data dari instans Anda akan dihapus secara permanen, termasuk dunia, konfigurasi, dan konten terpasang Anda."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Tindakan ini tidak dapat dibatalkan"
},
"app.instance.confirm-delete.delete-button": {
"message": "Hapus instans"
},
"app.instance.confirm-delete.header": {
"message": "Hapus instans"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Paket mod ini telah terpasang pada instans \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Gandakan paket mod"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Tetap buat"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Pergi ke instans"
},
"app.instance.modpack-already-installed.header": {
"message": "Paket mod telah terpasang"
},
"app.instance.mods.content-type-project": {
"message": "proyek"
},
"app.instance.mods.copy-link": {
"message": "Salin tautan"
},
"app.instance.mods.installing": {
"message": "Memasang..."
},
"app.instance.mods.modpack-fallback": {
"message": "Paket Mod"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" telah ditambahkan"
},
"app.instance.mods.projects-were-added": {
"message": "{count} proyek telah ditambahkan"
},
"app.instance.mods.share-text": {
"message": "Lihat proyek-proyek yang saya pakai di paket mod saya!"
},
"app.instance.mods.share-title": {
"message": "Membagi konten paket mod"
},
"app.instance.mods.show-file": {
"message": "Tampilkan berkas"
},
"app.instance.mods.successfully-uploaded": {
"message": "Berhasil diunggah"
},
"app.instance.mods.unknown-version": {
"message": "Tidak diketahui"
},
"app.instance.mods.updating": {
"message": "Memperbarui..."
},
"app.modal.install-to-play.content-required": {
"message": "Konten diperlukan"
},
+18 -6
View File
@@ -12,7 +12,7 @@
"message": "Esporta"
},
"app.export-modal.header": {
"message": "Esporta un pacchetto di mod"
"message": "Esporta pacchetto"
},
"app.export-modal.modpack-name-label": {
"message": "Nome del pacchetto"
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "Elimina istanza"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Questo pacchetto è già stato installato nell'istanza \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Pacchetto duplicato"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Crea comunque"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Vai all'istanza"
},
"app.instance.modpack-already-installed.header": {
"message": "Pacchetto già installato"
},
"app.instance.mods.content-type-project": {
"message": "progetto"
},
@@ -71,9 +86,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "Caricato con successo"
},
"app.instance.mods.switch-version": {
"message": "Cambia versione"
},
"app.instance.mods.unknown-version": {
"message": "Sconosciuta"
},
@@ -234,7 +246,7 @@
"message": "Online"
},
"friends.heading.pending": {
"message": "In sospeso"
"message": "In attesa"
},
"friends.no-friends-match": {
"message": "Nessuna amicizia corrisponde a ''{query}''"
@@ -369,7 +381,7 @@
"message": "Inserisci comando post-uscita..."
},
"instance.settings.tabs.hooks.pre-launch": {
"message": "Pre-lancio"
"message": "Pre-avvio"
},
"instance.settings.tabs.hooks.pre-launch.description": {
"message": "Eseguito prima dell'avvio dell'istanza."
+16 -1
View File
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "インスタンスを削除"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "このModパックは「{instanceName}」インスタンスにすでにインストールされています。"
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "重複したModパック"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "とにかく作成する"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "インスタンスに移動"
},
"app.instance.modpack-already-installed.header": {
"message": "Modパックはすでにインストール済み"
},
"app.instance.mods.content-type-project": {
"message": "プロジェクト"
},
@@ -303,7 +318,7 @@
"message": "インスタンスを削除"
},
"instance.settings.tabs.general.delete.description": {
"message": "デバイスからインスタンスを削除します。これらには、ワールド、設定などのてのインストール済みのファイルが含まれます。インスタンスを削除すると復元することはできません。"
"message": "デバイスからインスタンスを削除します。これらには、ワールド、設定などのすべてのインストール済みのファイルが含まれます。インスタンスを削除すると復元することはできません。"
},
"instance.settings.tabs.general.deleting.button": {
"message": "削除中…"
+82 -1
View File
@@ -1,10 +1,91 @@
{
"app.auth-servers.unreachable.body": {
"message": "Pelayan pengesahan Minecraft mungkin sedang tergendala sekarang. Periksa sambungan internet anda dan cuba lagi nanti."
"message": "Pelayan pengesahan Minecraft mungkin sedang tergendala sekarang. Periksa sambungan internet anda dan cuba lagi kemudian."
},
"app.auth-servers.unreachable.header": {
"message": "Tidak dapat mencapai pelayan pengesahan"
},
"app.export-modal.description-placeholder": {
"message": "Masukkan keterangan pek mod..."
},
"app.export-modal.export-button": {
"message": "Eksport"
},
"app.export-modal.header": {
"message": "Eksport pek mod"
},
"app.export-modal.modpack-name-label": {
"message": "Nama Pek Mod"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Nama pek mod"
},
"app.export-modal.select-files-label": {
"message": "Pilih fail dan folder untuk disertakan dalam pek mod"
},
"app.export-modal.version-number-label": {
"message": "Nombor versi"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Semua data untuk pemasangan anda akan dipadamkan secara kekal, termasuk dunia, konfigurasi dan semua kandungan yang dipasang."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Tindakan ini tidak boleh dibatalkan"
},
"app.instance.confirm-delete.delete-button": {
"message": "Padam pemasangan"
},
"app.instance.confirm-delete.header": {
"message": "Padam pemasangan"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Pek mod ini sudah pun dipasang di dalam pemasangan \"{instanceName}\"."
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Pergi ke pemasangan"
},
"app.instance.modpack-already-installed.header": {
"message": "Pek mod sudah dipasang"
},
"app.instance.mods.content-type-project": {
"message": "projek"
},
"app.instance.mods.copy-link": {
"message": "Salin pautan"
},
"app.instance.mods.installing": {
"message": "Sedang memasang..."
},
"app.instance.mods.modpack-fallback": {
"message": "Pek Mod"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" telah ditambahkan"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projek telah ditambahkan"
},
"app.instance.mods.share-text": {
"message": "Lihat projek-projek yang saya gunakan dalam pek mod saya!"
},
"app.instance.mods.share-title": {
"message": "Berkongsi kandungan pek mod"
},
"app.instance.mods.show-file": {
"message": "Tunjukkan fail"
},
"app.instance.mods.successfully-uploaded": {
"message": "Berjaya dimuat naik"
},
"app.instance.mods.unknown-version": {
"message": "Tidak Diketahui"
},
"app.instance.mods.updating": {
"message": "Sedang mengemas kini..."
},
"app.modal.install-to-play.content-required": {
"message": "Kandungan yang diperlukan"
},
@@ -5,15 +5,57 @@
"app.auth-servers.unreachable.header": {
"message": "Authenticatieservers kunnen niet worden bereikt"
},
"app.export-modal.description-placeholder": {
"message": "Voeg modpack beschrijving in..."
},
"app.export-modal.export-button": {
"message": "Exporteer"
},
"app.export-modal.header": {
"message": "Exporteer modpack"
},
"app.export-modal.modpack-name-label": {
"message": "Modpack Naam"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpack naam"
},
"app.export-modal.select-files-label": {
"message": "Selecteer bestanden en mappen om toe te voegen aan pack"
},
"app.export-modal.version-number-label": {
"message": "Versie nummer"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Alle data van je instantie zal permanent verwijderd worden, inclusief al je werelden, voorkeuren, en alle geïnstalleerde content."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Deze actie kan niet ongedaan gemaakt worden"
},
"app.instance.confirm-delete.delete-button": {
"message": "Verwijder instantie"
},
"app.instance.confirm-delete.header": {
"message": "Verwijder instantie"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Deze modpack is al geïnstalleerd in de \"{instanceName}\" instantie."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Dupliceer modpack"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Maak toch"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Ga naar instantie"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack is al geïnstalleerd"
},
"app.instance.mods.content-type-project": {
"message": "project"
},
@@ -17,6 +17,66 @@
"app.export-modal.modpack-name-placeholder": {
"message": "Nazwa paczki modów"
},
"app.export-modal.select-files-label": {
"message": "Wybierz pliki i foldery, które mają znaleźć się w paczce"
},
"app.export-modal.version-number-label": {
"message": "Numer wersji"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Wszystkie dane z Twojej instancji zostaną trwale usunięte, w tym Twoje światy, pliki konfiguracji i wszystkie zainstalowane treści."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Tej akcji nie można odwrócić"
},
"app.instance.confirm-delete.delete-button": {
"message": "Usuń instancję"
},
"app.instance.confirm-delete.header": {
"message": "Usuń instancję"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Ta paczka modów jest już zainstalowana w instancji \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Duplikat paczki modów"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Utwórz mimo to"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Przejdź do instancji"
},
"app.instance.modpack-already-installed.header": {
"message": "Paczka modów jest już zainstalowana"
},
"app.instance.mods.content-type-project": {
"message": "projekt"
},
"app.instance.mods.copy-link": {
"message": "Kopiuj łącze"
},
"app.instance.mods.installing": {
"message": "Instalowanie..."
},
"app.instance.mods.modpack-fallback": {
"message": "Paczka modów"
},
"app.instance.mods.project-was-added": {
"message": "Dodano \"{name}\""
},
"app.instance.mods.projects-were-added": {
"message": "Dodano {count} {count, plural, one {projekt} few {projekty} other {projektów}}"
},
"app.instance.mods.show-file": {
"message": "Pokaż plik"
},
"app.instance.mods.successfully-uploaded": {
"message": "Przesyłanie powiodło się"
},
"app.modal.install-to-play.content-required": {
"message": "Wymagane treści"
},
+17 -5
View File
@@ -1,6 +1,6 @@
{
"app.auth-servers.unreachable.body": {
"message": "Os servidores de autenticação do Minecraft podem estar indisponíveis no momento. Cheque sua conexão com a internet e tente novamente mais tarde."
"message": "Os servidores de autenticação do Minecraft podem estar indisponíveis no momento. Verifique sua conexão com a internet e tente novamente mais tarde."
},
"app.auth-servers.unreachable.header": {
"message": "Não foi possível acessar os servidores de autenticação"
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "Excluir instância"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Este pacote de mods já está instalado na instância \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Pacote de mods duplicado"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Criar mesmo assim"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Ir para a instância"
},
"app.instance.modpack-already-installed.header": {
"message": "O pacote de mods já está instalado"
},
"app.instance.mods.content-type-project": {
"message": "projeto"
},
@@ -71,9 +86,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "Enviado com sucesso"
},
"app.instance.mods.switch-version": {
"message": "Trocar versão"
},
"app.instance.mods.unknown-version": {
"message": "Desconhecido"
},
@@ -90,7 +102,7 @@
"message": "Instalar"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, =0 {Nenhum mod} one {# mod} other {# mods}}\n"
"message": "{count, plural, =0 {Nenhum mod} one {# mod} other {# mods}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Pacote de mods necessário"
+32 -20
View File
@@ -6,22 +6,22 @@
"message": "Нет связи с серверами аутентификации"
},
"app.export-modal.description-placeholder": {
"message": "Введите описание сборки модов..."
"message": "Введите описание сборки..."
},
"app.export-modal.export-button": {
"message": "Экспортировать"
},
"app.export-modal.header": {
"message": "Экспортировать сборку модов"
"message": "Экспорт модпака"
},
"app.export-modal.modpack-name-label": {
"message": "Название сборки модов"
"message": "Название сборки"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Название сборки модов"
"message": "Название сборки"
},
"app.export-modal.select-files-label": {
"message": "Выберите файлы и папки для добавления в пак"
"message": "Выберите элементы экспорта в модпак"
},
"app.export-modal.version-number-label": {
"message": "Номер версии"
@@ -30,22 +30,37 @@
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-body": {
"message": "Все данные вашей установки будут окончательно удалены, включая ваши миры, настройки и весь установленный контент."
"message": "Все данные вашей инстанции будут окончательно удалены, включая ваши миры, настройки и весь установленный контент."
},
"app.instance.confirm-delete.admonition-header": {
"message": "Это действие не может быть возвращено"
"message": "Это действие нельзя обратить"
},
"app.instance.confirm-delete.delete-button": {
"message": "Удалить установку"
"message": "Удалить сборку"
},
"app.instance.confirm-delete.header": {
"message": "Удалить установку"
"message": "Удаление сборки"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Этот модпак уже установлен в инстанции \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Дублировать модпак"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Всё равно создать"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "К инстанции"
},
"app.instance.modpack-already-installed.header": {
"message": "Модпак уже установлен"
},
"app.instance.mods.content-type-project": {
"message": "проект"
},
"app.instance.mods.copy-link": {
"message": "Скопировать ссылку"
"message": "Копировать ссылку"
},
"app.instance.mods.installing": {
"message": "Установка..."
@@ -57,25 +72,22 @@
"message": "\"{name}\" был добавлен"
},
"app.instance.mods.projects-were-added": {
"message": "{count} проектов были добавлены"
"message": "Проектов добавлено: {count}"
},
"app.instance.mods.share-text": {
"message": "Посмотрите проекты, которые я использую в моей сборке модов!"
"message": "Посмотрите проекты, в моём модпаке!"
},
"app.instance.mods.share-title": {
"message": "Поделится контентом сборки модов"
"message": "Содержимое сборки"
},
"app.instance.mods.show-file": {
"message": "Показать файл"
"message": "Показать в папке"
},
"app.instance.mods.successfully-uploaded": {
"message": "Успешно загружено"
},
"app.instance.mods.switch-version": {
"message": "Сменить версию"
},
"app.instance.mods.unknown-version": {
"message": "Неизвестная"
"message": "Неизвестно"
},
"app.instance.mods.updating": {
"message": "Обновление..."
@@ -105,7 +117,7 @@
"message": "Общая сборка сервера"
},
"app.modal.install-to-play.view-contents": {
"message": "Посмотреть содержимое"
"message": "Посмотреть"
},
"app.modal.update-to-play.header": {
"message": "Обновление перед запуском"
@@ -246,7 +258,7 @@
"message": "{title} — {count}"
},
"friends.sign-in-to-add-friends": {
"message": "<link>Войдите в аккаунт Modrinth</link>, чтобы добавлять друзей и видеть, во что они играют!"
"message": "<link>Войдите в аккаунт Modrinth</link>, вы сможете добавлять друзей и видеть их статус!"
},
"instance.add-server.add-and-play": {
"message": "Добавить и играть"
@@ -41,6 +41,9 @@
"app.instance.confirm-delete.header": {
"message": "Radera instans"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Skapa ändå"
},
"app.instance.mods.content-type-project": {
"message": "projekt"
},
@@ -51,7 +54,7 @@
"message": "Installerar..."
},
"app.instance.mods.modpack-fallback": {
"message": "Modd-paket"
"message": "Modpaket"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" lades till"
@@ -60,10 +63,10 @@
"message": "{count} projekt lades till"
},
"app.instance.mods.share-text": {
"message": "Kolla in projekten jag använder i mitt modd-paket!"
"message": "Kolla in projekten jag använder i mitt modpaket!"
},
"app.instance.mods.share-title": {
"message": "Delar innehåll från modd-paket"
"message": "Delar innehåll från modpaket"
},
"app.instance.mods.show-file": {
"message": "Visa fil"
@@ -71,9 +74,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "Uppladdning lyckades"
},
"app.instance.mods.switch-version": {
"message": "Byt version"
},
"app.instance.mods.unknown-version": {
"message": "Okänt"
},
@@ -165,7 +165,7 @@
"message": "Nedladdning slutförd"
},
"app.update-popup.reload": {
"message": "Ladda om"
"message": "Kolla efter uppdateringar"
},
"app.update-popup.title": {
"message": "Uppdatering tillgänglig"
@@ -5,6 +5,69 @@
"app.auth-servers.unreachable.header": {
"message": "Doğrulama sunucularına erişilemedi"
},
"app.export-modal.description-placeholder": {
"message": "Mod paketi açıklaması yazın..."
},
"app.export-modal.export-button": {
"message": "Çıkart"
},
"app.export-modal.header": {
"message": "Modpaketi çıkart"
},
"app.export-modal.modpack-name-label": {
"message": "Modpaketi adı"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modpaketi adı"
},
"app.export-modal.version-number-label": {
"message": "Sürüm numarası"
},
"app.export-modal.version-number-placeholder": {
"message": "1.0.0"
},
"app.instance.confirm-delete.admonition-header": {
"message": "Bu eylem geri alınamaz"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Yinede oluştur"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpaketi zaten kurulu"
},
"app.instance.mods.content-type-project": {
"message": "proje"
},
"app.instance.mods.copy-link": {
"message": "Bağlantıyı kopyala"
},
"app.instance.mods.installing": {
"message": "Kuruluyor..."
},
"app.instance.mods.modpack-fallback": {
"message": "Modpaketi"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" eklendi"
},
"app.instance.mods.projects-were-added": {
"message": "{count} projeler eklendi"
},
"app.instance.mods.share-text": {
"message": "Modpaketimde kullandığım projelere göz at!"
},
"app.instance.mods.show-file": {
"message": "Dosya göster"
},
"app.instance.mods.successfully-uploaded": {
"message": "Başarı ile yüklendi"
},
"app.instance.mods.unknown-version": {
"message": "Bilinmeyen"
},
"app.instance.mods.updating": {
"message": "Güncelleniyor..."
},
"app.modal.install-to-play.content-required": {
"message": "İçerik gerekli"
},
+19 -7
View File
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "Видалити профіль"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Цю збірку вже встановлено в профілі «{instanceName}»."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Дублікат збірки"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Все одно створити"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Перейти до профілю"
},
"app.instance.modpack-already-installed.header": {
"message": "Збірку вже встановлено"
},
"app.instance.mods.content-type-project": {
"message": "проєкт"
},
@@ -48,13 +63,13 @@
"message": "Копіювати посилання"
},
"app.instance.mods.installing": {
"message": "Встановлення..."
"message": "Установлення"
},
"app.instance.mods.modpack-fallback": {
"message": "Збірка модів"
"message": "Збірка"
},
"app.instance.mods.project-was-added": {
"message": "\"{name}\" був доданий"
"message": "«{name}» було додано"
},
"app.instance.mods.projects-were-added": {
"message": "{count} проєктів було додано"
@@ -71,9 +86,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "Успішно вивантажено"
},
"app.instance.mods.switch-version": {
"message": "Змінити версію"
},
"app.instance.mods.unknown-version": {
"message": "Невідомо"
},
@@ -183,7 +195,7 @@
"message": "Завантаження оновлення ({percent}%)"
},
"app.update.reload-to-update": {
"message": "Перезапустіть, аби встановити оновлення"
"message": "Перезавантажте, щоб установити оновлення"
},
"friends.action.add-friend": {
"message": "Додати друга"
+22 -7
View File
@@ -36,10 +36,25 @@
"message": "Hành động này sẽ không thể huỷ bỏ"
},
"app.instance.confirm-delete.delete-button": {
"message": "Hoá hồ sơ"
"message": "Xoá hồ sơ"
},
"app.instance.confirm-delete.header": {
"message": "Xoá hồ xe"
"message": "Xoá hồ "
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "Modpack này đã được cài đặt trong phiên chơi \"{instanceName}\"."
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "Nhân bản modpack"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "Vẫn tiếp tục tạo"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "Đi đến phiên chơi"
},
"app.instance.modpack-already-installed.header": {
"message": "Modpack đã được cài đặt"
},
"app.instance.mods.content-type-project": {
"message": "Dự án"
@@ -204,7 +219,7 @@
"message": "Tên người dùng Modrinth của bạn của bạn là gì?"
},
"friends.add-friends-to-share": {
"message": "Hãy <link>Thêm bạn bè</link> để biết họ đang chơi gì!"
"message": "Hãy <link>thêm bạn bè</link> để biết họ đang chơi gì!"
},
"friends.friend.cancel-request": {
"message": "Huỷ yêu cầu"
@@ -216,7 +231,7 @@
"message": "Đã gửi yêu cầu kết bạn"
},
"friends.friend.view-profile": {
"message": "Xem hồ sơ"
"message": "Xem thông tin"
},
"friends.heading": {
"message": "Bạn bè"
@@ -279,7 +294,7 @@
"message": "Đặt lại biểu tượng"
},
"instance.edit-world.title": {
"message": "Sửa th giới"
"message": "Chỉnh sửa thế giới"
},
"instance.server-modal.address": {
"message": "Địa chỉ"
@@ -318,7 +333,7 @@
"message": "Nhân bản hồ sơ"
},
"instance.settings.tabs.general.duplicate-instance.description": {
"message": "Tạo ra một bản sao của hiện thể này, bao gồm các thế giới, cấu hình, mod, v.v.."
"message": "Tạo ra một bản sao của hồ sơ này, bao gồm các thế giới, cấu hình, mod, v.v."
},
"instance.settings.tabs.general.edit-icon": {
"message": "Sửa biểu tượng"
@@ -495,7 +510,7 @@
"message": "Được cung cấp bởi phiên bản"
},
"search.filter.locked.instance-game-version.title": {
"message": "Phiên bản trò chơi được cung cấp bởi instance này"
"message": "Phiên bản trò chơi được cung cấp bởi hồ sơ này"
},
"search.filter.locked.instance-loader.title": {
"message": "Loader được cung cấp bởi hồ sơ"
+17 -5
View File
@@ -6,7 +6,7 @@
"message": "无法连接到身份验证服务器"
},
"app.export-modal.description-placeholder": {
"message": "输入整合包描述内容..."
"message": "输入整合包描述……"
},
"app.export-modal.export-button": {
"message": "导出"
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "删除实例"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "这个整合包已经安装在\"{instanceName}\"实例中了。"
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "重复的整合包"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "在任何地方创建"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "前往实例"
},
"app.instance.modpack-already-installed.header": {
"message": "整合包已安装"
},
"app.instance.mods.content-type-project": {
"message": "项目"
},
@@ -71,14 +86,11 @@
"app.instance.mods.successfully-uploaded": {
"message": "上传成功"
},
"app.instance.mods.switch-version": {
"message": "切换版本"
},
"app.instance.mods.unknown-version": {
"message": "未知"
},
"app.instance.mods.updating": {
"message": "正在更新……"
"message": "更新……"
},
"app.modal.install-to-play.content-required": {
"message": "内容需求"
+15 -3
View File
@@ -41,6 +41,21 @@
"app.instance.confirm-delete.header": {
"message": "刪除實例"
},
"app.instance.modpack-already-installed.admonition-body": {
"message": "這個模組包已經安裝在「{instanceName}」實例中了。"
},
"app.instance.modpack-already-installed.admonition-header": {
"message": "複製模組包"
},
"app.instance.modpack-already-installed.create-anyway": {
"message": "仍要建立"
},
"app.instance.modpack-already-installed.go-to-instance": {
"message": "前往實例"
},
"app.instance.modpack-already-installed.header": {
"message": "模組包已經安裝"
},
"app.instance.mods.content-type-project": {
"message": "專案"
},
@@ -71,9 +86,6 @@
"app.instance.mods.successfully-uploaded": {
"message": "上傳成功"
},
"app.instance.mods.switch-version": {
"message": "切換版本"
},
"app.instance.mods.unknown-version": {
"message": "未知"
},
+7 -12
View File
@@ -109,6 +109,10 @@ const instanceHideInstalled = ref(false)
const newlyInstalled = ref<string[]>([])
const isServerInstance = ref(false)
const allInstalledIds = computed(
() => new Set([...newlyInstalled.value, ...(installedProjectIds.value ?? [])]),
)
const PERSISTENT_QUERY_PARAMS = ['i', 'ai']
await initInstanceContext()
@@ -485,17 +489,8 @@ async function refreshSearch() {
link: `/browse/${projectType.value}`,
query: params,
})
const queryString = Object.entries(params)
.flatMap(([key, value]) => {
const values = Array.isArray(value) ? value : [value]
return values
.filter((v): v is string => v != null)
.map((v) => `${encodeURIComponent(key)}=${encodeURIComponent(v)}`)
})
.join('&')
const newUrl = `${route.path}${queryString ? '?' + queryString : ''}`
debugLog('updating URL', newUrl)
window.history.replaceState(window.history.state, '', newUrl)
debugLog('updating URL', params)
router.replace({ path: route.path, query: params })
loading.value = false
debugLog('refreshSearch complete', { version })
@@ -947,7 +942,7 @@ previousFilterState.value = JSON.stringify({
loader.supported_project_types?.includes(projectType),
),
]"
:installed="result.installed || newlyInstalled.includes(result.project_id || '')"
:installed="result.installed || allInstalledIds.has(result.project_id || '')"
@install="
(id) => {
newlyInstalled.push(id)
+28 -23
View File
@@ -20,6 +20,11 @@
<ConfirmModpackUpdateModal
ref="modpackUpdateConfirmModal"
:downgrade="isModpackUpdateDowngrade"
:backup-tip="
[linkedModpackProject?.title, pendingModpackUpdateVersion?.version_number]
.filter(Boolean)
.join(' ')
"
@confirm="handleModpackUpdateConfirm"
@cancel="handleModpackUpdateCancel"
/>
@@ -58,7 +63,7 @@
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import { ArrowLeftRightIcon, ClipboardCopyIcon, FolderOpenIcon } from '@modrinth/assets'
import { ClipboardCopyIcon, FolderOpenIcon } from '@modrinth/assets'
import {
ConfirmModpackUpdateModal,
type ContentItem,
@@ -160,10 +165,6 @@ const messages = defineMessages({
id: 'app.instance.mods.copy-link',
defaultMessage: 'Copy link',
},
switchVersion: {
id: 'app.instance.mods.switch-version',
defaultMessage: 'Switch version',
},
})
let savedModalState: ModpackContentModalState | null = null
@@ -381,7 +382,7 @@ async function switchProjectVersion(mod: ContentItem, version: Labrinth.Versions
}
async function handleUpdate(id: string) {
const item = projects.value.find((p) => p.file_name === id)
const item = projects.value.find((p) => p.id === id)
if (!item?.has_update || !item.project?.id || !item.version?.id) return
debug('handleUpdate triggered', {
@@ -471,7 +472,7 @@ async function handleModpackContentToggle(item: ContentItem) {
}
async function handleModpackContentBulkToggle(items: ContentItem[]) {
await Promise.all(items.map((item) => toggleDisableMod(item)))
await Promise.all(items.map((item) => _toggleDisableMod(item)))
}
async function handleModpackContent() {
@@ -658,14 +659,6 @@ async function handleShareItems(
function getOverflowOptions(item: ContentItem): OverflowMenuOption[] {
const options: OverflowMenuOption[] = []
if (item.project?.id && item.version?.id && !item.has_update) {
options.push({
id: formatMessage(messages.switchVersion),
icon: ArrowLeftRightIcon,
action: () => handleSwitchVersion(item),
})
}
options.push({
id: formatMessage(messages.showFile),
icon: FolderOpenIcon,
@@ -781,11 +774,17 @@ provideContentManager({
linkedModpackProject.value
? {
project: linkedModpackProject.value,
projectLink: `/project/${linkedModpackProject.value.slug ?? linkedModpackProject.value.id}`,
projectLink: {
path: `/project/${linkedModpackProject.value.slug ?? linkedModpackProject.value.id}`,
query: { i: props.instance.path },
},
version: linkedModpackVersion.value ?? undefined,
versionLink:
linkedModpackProject.value && linkedModpackVersion.value
? `/project/${linkedModpackProject.value.slug ?? linkedModpackProject.value.id}/version/${linkedModpackVersion.value.id}`
? {
path: `/project/${linkedModpackProject.value.slug ?? linkedModpackProject.value.id}/version/${linkedModpackVersion.value.id}`,
query: { i: props.instance.path },
}
: undefined,
owner: linkedModpackOwner.value
? {
@@ -808,13 +807,12 @@ provideContentManager({
isPackLocked,
isBusy: isInstanceBusy,
isBulkOperating,
getItemId: (item) => item.file_name,
contentTypeLabel: ref(formatMessage(messages.contentTypeProject)),
toggleEnabled: toggleDisableMod,
bulkEnableItems: (items) =>
Promise.all(items.map((item) => toggleDisableMod(item))).then(() => {}),
Promise.all(items.map((item) => _toggleDisableMod(item))).then(() => {}),
bulkDisableItems: (items) =>
Promise.all(items.map((item) => toggleDisableMod(item))).then(() => {}),
Promise.all(items.map((item) => _toggleDisableMod(item))).then(() => {}),
deleteItem: removeMod,
bulkDeleteItems: (items) => Promise.all(items.map((item) => removeMod(item))).then(() => {}),
refresh: () => initProjects('must_revalidate'),
@@ -827,19 +825,22 @@ provideContentManager({
viewModpackContent: handleModpackContent,
unlinkModpack: unpairProfile,
openSettings: props.openSettings,
switchVersion: handleSwitchVersion,
getOverflowOptions,
showContentHint,
dismissContentHint,
shareItems: handleShareItems,
mapToTableItem: (item) => ({
id: item.file_name,
id: item.id,
project: item.project ?? {
id: item.file_name,
slug: null,
title: item.file_name.replace('.disabled', ''),
icon_url: null,
},
projectLink: item.project?.id ? `/project/${item.project.id}` : undefined,
projectLink: item.project?.id
? { path: `/project/${item.project.id}`, query: { i: props.instance.path } }
: undefined,
version: item.version ?? {
id: item.file_name,
version_number: formatMessage(messages.unknownVersion),
@@ -847,7 +848,10 @@ provideContentManager({
},
versionLink:
item.project?.id && item.version?.id
? `/project/${item.project.id}/version/${item.version.id}`
? {
path: `/project/${item.project.id}/version/${item.version.id}`,
query: { i: props.instance.path },
}
: undefined,
owner: item.owner
? {
@@ -857,6 +861,7 @@ provideContentManager({
: undefined,
enabled: item.enabled,
}),
filterPersistKey: props.instance.path,
})
await initProjects()
@@ -1,13 +1,20 @@
import type { Labrinth } from '@modrinth/api-client'
import type { ContentInstallInstance, ContentItem } from '@modrinth/ui'
import type { ContentInstallInstance, ContentInstallProjectInfo, ContentItem } from '@modrinth/ui'
import { createContext } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { openUrl } from '@tauri-apps/plugin-opener'
import dayjs from 'dayjs'
import { nextTick, type Ref, ref } from 'vue'
import type { Router } from 'vue-router'
import { trackEvent } from '@/helpers/analytics'
import { get_project, get_project_v3_many, get_version_many } from '@/helpers/cache.js'
import {
get_organization,
get_project,
get_project_v3_many,
get_team,
get_version_many,
} from '@/helpers/cache.js'
import { create_profile_and_install as packInstall } from '@/helpers/pack'
import {
add_project_from_version,
@@ -19,6 +26,7 @@ import {
remove_project,
} from '@/helpers/profile.js'
import { get_game_versions } from '@/helpers/tags'
import type { GameInstance, InstanceLoader } from '@/helpers/types'
import {
findPreferredVersion,
installVersionDependencies,
@@ -30,13 +38,8 @@ interface ModalRef {
hide: () => void
}
interface InstallConfirmModalRef {
show: (
project: Labrinth.Projects.v2.Project,
version: string,
callback: (versionId?: string) => void,
createInstanceCallback: (profile: string) => void,
) => void
interface ModpackAlreadyInstalledModalRef {
show: (instanceName: string, instancePath: string) => void
}
interface IncompatibilityWarningModalRef {
@@ -73,6 +76,7 @@ export interface ContentInstallContext {
preferredLoader: Ref<string | null>
preferredGameVersion: Ref<string | null>
releaseGameVersions: Ref<Set<string>>
projectInfo: Ref<ContentInstallProjectInfo | null>
handleInstallToInstance: (instance: ContentInstallInstance) => Promise<void>
handleCreateAndInstall: (data: {
name: string
@@ -84,7 +88,9 @@ export interface ContentInstallContext {
handleNavigate: (instance: ContentInstallInstance) => void
handleCancel: () => void
setContentInstallModal: (ref: ModalRef) => void
setInstallConfirmModal: (ref: InstallConfirmModalRef) => void
setModpackAlreadyInstalledModal: (ref: ModpackAlreadyInstalledModalRef) => void
handleModpackDuplicateCreateAnyway: () => Promise<void>
handleModpackDuplicateGoToInstance: (instancePath: string) => void
setIncompatibilityWarningModal: (ref: IncompatibilityWarningModalRef) => void
install: (
projectId: string,
@@ -93,7 +99,7 @@ export interface ContentInstallContext {
source?: string,
callback?: (versionId?: string) => void,
createInstanceCallback?: (profile: string) => void,
hints?: { preferredLoader?: string; preferredGameVersion?: string },
hints?: { preferredLoader?: string; preferredGameVersion?: string; showProjectInfo?: boolean },
) => Promise<void>
installingItems: Ref<Map<string, ContentItem[]>>
}
@@ -116,6 +122,7 @@ export function createContentInstall(opts: {
const preferredGameVersion = ref<string | null>(null)
const releaseGameVersions = ref<Set<string>>(new Set())
const projectInfo = ref<ContentInstallProjectInfo | null>(null)
const installingItems = ref<Map<string, ContentItem[]>>(new Map())
function addInstallingItem(
@@ -131,12 +138,13 @@ export function createContentInstall(opts: {
) {
const primaryFile = version?.files?.find((f) => f.primary) ?? version?.files?.[0]
const placeholder: ContentItem = {
id: `__installing_${project.id}`,
file_name: `__installing_${project.id}`,
project: {
id: project.id,
slug: project.slug ?? null,
slug: project.slug ?? '',
title: project.title,
icon_url: project.icon_url ?? null,
icon_url: project.icon_url ?? undefined,
},
version: version
? {
@@ -174,18 +182,26 @@ export function createContentInstall(opts: {
}
let modalRef: ModalRef | null = null
let installConfirmModalRef: InstallConfirmModalRef | null = null
let modpackAlreadyInstalledModalRef: ModpackAlreadyInstalledModalRef | null = null
let incompatibilityWarningModalRef: IncompatibilityWarningModalRef | null = null
let currentProject: Labrinth.Projects.v2.Project | null = null
let currentVersions: Labrinth.Versions.v2.Version[] = []
let currentCallback: (versionId?: string) => void = () => {}
let profileMap: Record<string, GameInstance> = {}
let pendingModpackInstall: {
project: Labrinth.Projects.v2.Project
version: string
source: string
callback: (versionId?: string) => void
createInstanceCallback: (profile: string) => void
} | null = null
async function showModInstallModal(
project: Labrinth.Projects.v2.Project,
versions: Labrinth.Versions.v2.Version[],
onInstall: (versionId?: string) => void,
hints?: { preferredLoader?: string; preferredGameVersion?: string },
hints?: { preferredLoader?: string; preferredGameVersion?: string; showProjectInfo?: boolean },
) {
currentProject = project
currentVersions = versions
@@ -194,6 +210,58 @@ export function createContentInstall(opts: {
instances.value = []
defaultTab.value = 'existing'
if (hints?.showProjectInfo) {
projectInfo.value = {
title: project.title,
iconUrl: project.icon_url,
link: `/project/${project.slug ?? project.id}`,
}
if (project.organization) {
get_organization(project.organization)
.then((org: { id: string; slug: string; name: string; icon_url?: string }) => {
if (projectInfo.value) {
const orgSlug = org.slug ?? org.id
projectInfo.value = {
...projectInfo.value,
owner: {
name: org.name,
iconUrl: org.icon_url,
circle: false,
link: () => openUrl(`https://modrinth.com/organization/${orgSlug}`),
},
}
}
})
.catch(() => {})
} else if (project.team) {
get_team(project.team)
.then(
(
members: {
user: { id: string; username: string; avatar_url?: string }
is_owner: boolean
}[],
) => {
const owner = members.find((m) => m.is_owner)
if (owner && projectInfo.value) {
projectInfo.value = {
...projectInfo.value,
owner: {
name: owner.user.username,
iconUrl: owner.user.avatar_url,
circle: true,
link: () => openUrl(`https://modrinth.com/user/${owner.user.username}`),
},
}
}
},
)
.catch(() => {})
}
} else {
projectInfo.value = null
}
const loaderSet = new Set<string>()
const gameVersionSet = new Set<string>()
for (const v of versions) {
@@ -318,10 +386,10 @@ export function createContentInstall(opts: {
trackEvent('ProjectInstall', {
loader: profile.loader,
game_version: profile.game_version,
id: currentProject.id,
id: currentProject!.id,
version_id: version.id,
project_type: currentProject.project_type,
title: currentProject.title,
project_type: currentProject!.project_type,
title: currentProject!.title,
source: 'ProjectInstallModal',
})
currentCallback(version.id)
@@ -372,10 +440,10 @@ export function createContentInstall(opts: {
trackEvent('ProjectInstall', {
loader: data.loader,
game_version: data.gameVersion,
id: currentProject.id,
id: currentProject!.id,
version_id: version.id,
project_type: currentProject.project_type,
title: currentProject.title,
project_type: currentProject!.project_type,
title: currentProject!.title,
source: 'ProjectInstallModal',
})
@@ -402,35 +470,35 @@ export function createContentInstall(opts: {
source: string = 'unknown',
callback: (versionId?: string) => void = () => {},
createInstanceCallback: (profile: string) => void = () => {},
hints?: { preferredLoader?: string; preferredGameVersion?: string },
hints?: { preferredLoader?: string; preferredGameVersion?: string; showProjectInfo?: boolean },
) {
const project: Labrinth.Projects.v2.Project = await get_project(projectId, 'must_revalidate')
if (project.project_type === 'modpack') {
const version = versionId ?? project.versions[project.versions.length - 1]
const packs = await list()
const existingPack = packs.find((pack) => pack.linked_data?.project_id === project.id)
if (
packs.length === 0 ||
!packs.find((pack) => pack.linked_data?.project_id === project.id)
) {
await packInstall(
project.id,
version,
project.title,
project.icon_url,
createInstanceCallback,
)
trackEvent('PackInstall', {
id: project.id,
version_id: version,
title: project.title,
source,
})
callback(version)
} else {
installConfirmModalRef?.show(project, version, callback, createInstanceCallback)
if (existingPack) {
pendingModpackInstall = { project, version, source, callback, createInstanceCallback }
modpackAlreadyInstalledModalRef?.show(existingPack.name, existingPack.path)
return
}
await packInstall(
project.id,
version,
project.title,
project.icon_url,
createInstanceCallback,
)
trackEvent('PackInstall', {
id: project.id,
version_id: version,
title: project.title,
source,
})
callback(version)
} else if (instancePath) {
const [instanceOrNull, instanceProjects, versions] = await Promise.all([
get(instancePath),
@@ -508,6 +576,7 @@ export function createContentInstall(opts: {
preferredLoader,
preferredGameVersion,
releaseGameVersions,
projectInfo,
handleInstallToInstance,
handleCreateAndInstall,
handleNavigate,
@@ -515,8 +584,31 @@ export function createContentInstall(opts: {
setContentInstallModal(ref: ModalRef) {
modalRef = ref
},
setInstallConfirmModal(ref: InstallConfirmModalRef) {
installConfirmModalRef = ref
setModpackAlreadyInstalledModal(ref: ModpackAlreadyInstalledModalRef) {
modpackAlreadyInstalledModalRef = ref
},
async handleModpackDuplicateCreateAnyway() {
if (!pendingModpackInstall) return
const { project, version, source, callback, createInstanceCallback } = pendingModpackInstall
pendingModpackInstall = null
await packInstall(
project.id,
version,
project.title,
project.icon_url,
createInstanceCallback,
)
trackEvent('PackInstall', {
id: project.id,
version_id: version,
title: project.title,
source,
})
callback(version)
},
handleModpackDuplicateGoToInstance(instancePath: string) {
pendingModpackInstall = null
opts.router.push(`/instance/${encodeURIComponent(instancePath)}/`)
},
setIncompatibilityWarningModal(ref: IncompatibilityWarningModalRef) {
incompatibilityWarningModalRef = ref
@@ -0,0 +1,14 @@
import { createContext } from '@modrinth/ui'
import type { Ref } from 'vue'
import type { GameInstance } from '@/helpers/types'
export interface InstanceSettingsContext {
instance: GameInstance
offline?: boolean
isMinecraftServer: Ref<boolean>
onUnlinked: () => void
}
export const [injectInstanceSettings, provideInstanceSettings] =
createContext<InstanceSettingsContext>('InstanceSettingsModal', 'instanceSettings')
@@ -46,11 +46,24 @@ export interface ServerInstallContext {
showAddServerToInstanceModal: (serverName: string, serverAddress: string) => void
}
export const [injectServerInstall, provideServerInstall] = createContext<ServerInstallContext>(
let _serverInstallSingleton: ServerInstallContext | null = null
const [_rawInjectServerInstall, provideServerInstall] = createContext<ServerInstallContext>(
'root',
'serverInstall',
)
export { provideServerInstall }
export function injectServerInstall(): ServerInstallContext {
try {
return _rawInjectServerInstall()
} catch {
if (_serverInstallSingleton) return _serverInstallSingleton
throw new Error('ServerInstall context not available')
}
}
export function createServerInstall(opts: {
router: Router
handleError: (err: unknown) => void
@@ -345,7 +358,7 @@ export function createServerInstall(opts: {
}
}
return {
const context: ServerInstallContext = {
installingServerProjects,
startInstallingServer,
stopInstallingServer,
@@ -365,4 +378,7 @@ export function createServerInstall(opts: {
addServerToInstanceModalRef?.show(serverName, serverAddress)
},
}
_serverInstallSingleton = context
return context
}
@@ -1,18 +1,33 @@
import type { AbstractWebNotificationManager, CreationFlowContextValue } from '@modrinth/ui'
import { provide, useTemplateRef } from 'vue'
import type {
AbstractWebNotificationManager,
CreationFlowContextValue,
CreationFlowModal,
} from '@modrinth/ui'
import { provide, ref, useTemplateRef } from 'vue'
import type { ComponentExposed } from 'vue-component-type-helpers'
import { useRouter } from 'vue-router'
import type ModpackAlreadyInstalledModal from '@/components/ui/modal/ModpackAlreadyInstalledModal.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_project_versions, get_search_results } from '@/helpers/cache.js'
import { import_instance } from '@/helpers/import.js'
import { create_profile_and_install, create_profile_and_install_from_file } from '@/helpers/pack'
import { create, list } from '@/helpers/profile.js'
import type { InstanceLoader } from '@/helpers/types'
export function setupCreationModal(notificationManager: AbstractWebNotificationManager) {
const { handleError } = notificationManager
const router = useRouter()
const installationModal = useTemplateRef('installationModal')
const installationModal =
useTemplateRef<ComponentExposed<typeof CreationFlowModal>>('installationModal')
const modpackAlreadyInstalledModal = ref<InstanceType<typeof ModpackAlreadyInstalledModal>>()
function setModpackAlreadyInstalledModal(
modal: InstanceType<typeof ModpackAlreadyInstalledModal>,
) {
modpackAlreadyInstalledModal.value = modal
}
async function fetchExistingInstanceNames(): Promise<string[]> {
const instances = await list().catch(handleError)
@@ -23,10 +38,34 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
installationModal.value?.show()
})
async function handleCreate(config: CreationFlowContextValue) {
installationModal.value?.hide()
async function proceedWithModpackCreation(
projectId: string,
versionId: string,
name: string,
iconUrl?: string,
) {
await create_profile_and_install(projectId, versionId, name, iconUrl).catch(handleError)
trackEvent('InstanceCreate', { source: 'CreationModalModpack' })
}
async function handleCreate(config: CreationFlowContextValue) {
try {
if (config.modpackSelection.value) {
const { projectId, versionId, name, iconUrl } = config.modpackSelection.value
const instances = await list().catch(handleError)
const existingInstance = instances?.find((i) => i.linked_data?.project_id === projectId)
if (existingInstance) {
pendingModpackCreation.value = { projectId, versionId, name, iconUrl }
installationModal.value?.hide()
modpackAlreadyInstalledModal.value?.show(existingInstance.name, existingInstance.path)
return
}
}
installationModal.value?.hide()
if (config.isImportMode.value) {
for (const [launcherName, instanceSet] of Object.entries(
config.importSelectedInstances.value,
@@ -43,8 +82,7 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
if (config.modpackSelection.value) {
const { projectId, versionId, name, iconUrl } = config.modpackSelection.value
await create_profile_and_install(projectId, versionId, name, iconUrl).catch(handleError)
trackEvent('InstanceCreate', { source: 'CreationModalModpack' })
await proceedWithModpackCreation(projectId, versionId, name, iconUrl)
return
}
@@ -66,26 +104,40 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
await create(
name,
config.selectedGameVersion.value,
loader,
config.selectedGameVersion.value!,
loader as InstanceLoader,
loaderVersion,
iconPath,
false,
).catch(handleError)
trackEvent('InstanceCreate', {
profile_name: name,
game_version: config.selectedGameVersion.value,
loader,
loader_version: loaderVersion,
has_icon: !!iconPath,
source: 'CreationModal',
})
} catch (err) {
handleError(err)
handleError(err as Error)
}
}
const pendingModpackCreation = ref<{
projectId: string
versionId: string
name: string
iconUrl?: string
} | null>(null)
async function handleModpackDuplicateCreateAnyway() {
if (!pendingModpackCreation.value) return
const { projectId, versionId, name, iconUrl } = pendingModpackCreation.value
pendingModpackCreation.value = null
await proceedWithModpackCreation(projectId, versionId, name, iconUrl)
}
function handleModpackDuplicateGoToInstance(instancePath: string) {
pendingModpackCreation.value = null
router.push(`/instance/${encodeURIComponent(instancePath)}/`)
}
function handleBrowseModpacks() {
installationModal.value?.hide()
router.push('/browse/modpack')
@@ -113,5 +165,8 @@ export function setupCreationModal(notificationManager: AbstractWebNotificationM
handleBrowseModpacks,
searchModpacks,
getProjectVersions,
setModpackAlreadyInstalledModal,
handleModpackDuplicateCreateAnyway,
handleModpackDuplicateGoToInstance,
}
}
+1 -1
View File
@@ -115,7 +115,7 @@ export default defineNuxtConfig({
await import('./src/templates/docs/index.ts').then((m) => m.default),
)
const blogArticles = await import('@modrinth/blog').then((m) => m.articles)
const { getChangelog } = await import('@modrinth/utils')
const { getChangelog } = await import('@modrinth/blog')
nitroConfig.prerender = nitroConfig.prerender || {}
nitroConfig.prerender.routes = nitroConfig.prerender.routes || []
+1
View File
@@ -75,6 +75,7 @@
"semver": "^7.5.4",
"three": "^0.172.0",
"vue-confetti-explosion": "^1.0.2",
"vue-router": "*",
"vue-typed-virtual-list": "^1.0.10",
"vue3-ace-editor": "^2.2.4",
"vue3-apexcharts": "^1.5.2",
@@ -200,6 +200,7 @@ const developerModeCounter = ref(0)
const state = useGeneratedState()
function developerModeIncrement() {
developerModeCounter.value++
if (developerModeCounter.value >= 5) {
flags.value.developerMode = !flags.value.developerMode
developerModeCounter.value = 0
@@ -217,8 +218,6 @@ function developerModeIncrement() {
type: 'success',
})
}
} else {
developerModeCounter.value++
}
}
</script>
@@ -1,19 +1,39 @@
<script setup lang="ts">
import { CheckIcon, MailIcon } from '@modrinth/assets'
import { ButtonStyled } from '@modrinth/ui'
import { ref } from 'vue'
import { ButtonStyled, defineMessages, injectModrinthClient, useVIntl } from '@modrinth/ui'
import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { computed, ref } from 'vue'
import { useBaseFetch } from '~/composables/fetch.js'
const { formatMessage } = useVIntl()
const auth = await useAuth()
const messages = defineMessages({
tooltipSubscribe: {
id: 'ui.newsletter-button.tooltip',
defaultMessage: 'Subscribe to the Modrinth newsletter',
},
subscribe: {
id: 'ui.newsletter-button.subscribe',
defaultMessage: 'Subscribe',
},
subscribed: {
id: 'ui.newsletter-button.subscribed',
defaultMessage: 'Subscribed!',
},
})
const auth = (await useAuth()) as unknown as {
value: { user: { id: string; username: string; email: string; created: string } }
}
const client = injectModrinthClient()
const queryClient = useQueryClient()
const showSubscriptionConfirmation = ref(false)
const showSubscribeButton = useAsyncData(
async () => {
const { data: showSubscribeButton, isSuccess } = useQuery({
queryKey: computed(() => ['newsletter', 'subscribed', auth.value?.user?.id]),
queryFn: async () => {
if (auth.value?.user) {
try {
const { subscribed } = await useBaseFetch('auth/email/subscribe', {
method: 'GET',
})
const { subscribed } = await client.labrinth.auth_internal.getNewsletterStatus()
return !subscribed
} catch {
return true
@@ -22,36 +42,31 @@ const showSubscribeButton = useAsyncData(
return false
}
},
{ watch: [auth], server: false },
)
enabled: computed(() => !!auth.value?.user),
})
async function subscribe() {
try {
await useBaseFetch('auth/email/subscribe', {
method: 'POST',
})
await client.labrinth.auth_internal.subscribeNewsletter()
showSubscriptionConfirmation.value = true
} catch {
// Ignored
} finally {
setTimeout(() => {
showSubscriptionConfirmation.value = false
showSubscribeButton.status.value = 'success'
showSubscribeButton.data.value = false
queryClient.setQueryData(['newsletter', 'subscribed', auth.value?.user?.id], false)
}, 2500)
}
}
</script>
<template>
<ButtonStyled
v-if="showSubscribeButton.status.value === 'success' && showSubscribeButton.data.value"
color="brand"
type="outlined"
>
<button v-tooltip="`Subscribe to the Modrinth newsletter`" @click="subscribe">
<template v-if="!showSubscriptionConfirmation"> <MailIcon /> Subscribe </template>
<template v-else> <CheckIcon /> Subscribed! </template>
<ButtonStyled v-if="isSuccess && showSubscribeButton" color="brand" type="outlined">
<button v-tooltip="formatMessage(messages.tooltipSubscribe)" @click="subscribe">
<template v-if="!showSubscriptionConfirmation">
<MailIcon /> {{ formatMessage(messages.subscribe) }}
</template>
<template v-else> <CheckIcon /> {{ formatMessage(messages.subscribed) }} </template>
</button>
</ButtonStyled>
</template>
@@ -328,6 +328,7 @@ import {
Categories,
CopyCode,
DoubleIcon,
injectModrinthClient,
injectNotificationManager,
ProjectStatusBadge,
useFormatDateTime,
@@ -341,6 +342,7 @@ import { acceptTeamInvite, removeSelfFromTeam } from '~/helpers/teams'
import ThreadSummary from './thread/ThreadSummary.vue'
const client = injectModrinthClient()
const { addNotification } = injectNotificationManager()
const emit = defineEmits(['update:notifications'])
const formatRelativeTime = useRelativeTime()
@@ -407,7 +409,7 @@ async function read() {
? props.notification.grouped_notifs.map((notif) => notif.id)
: []),
]
const updateNotifs = await markAsRead(ids)
const updateNotifs = await markAsRead(client, ids)
const newNotifs = updateNotifs(props.notifications)
emit('update:notifications', newNotifs)
} catch (err) {
@@ -8,7 +8,7 @@
{{ analytics.error.value }}
</div>
</div>
<div v-else-if="!isInitialized || analytics.loading.value" class="universal-card">
<div v-else-if="analytics.loading.value" class="universal-card">
<h2>
<span class="label__title">Loading analytics...</span>
</h2>
@@ -315,6 +315,7 @@ import {
Card,
DropdownSelect,
useCompactNumber,
useDebugLogger,
useFormatMoney,
useFormatNumber,
} from '@modrinth/ui'
@@ -332,6 +333,7 @@ import {
intToRgba,
} from '~/utils/analytics.js'
const debug = useDebugLogger('ChartDisplay')
const formatNumber = useFormatNumber()
const { formatCompactNumber } = useCompactNumber()
const formatMoney = useFormatMoney()
@@ -339,6 +341,8 @@ const formatMoney = useFormatMoney()
const router = useNativeRouter()
const theme = useTheme()
debug('setup start', { server: import.meta.server, client: import.meta.client })
const props = withDefaults(
defineProps<{
projects?: any[]
@@ -357,7 +361,12 @@ const props = withDefaults(
},
)
const projects = ref(props.projects || [])
const projects = computed(() => props.projects || [])
debug('projects from props', {
count: projects.value.length,
ids: projects.value.map((p: any) => p.id),
})
// const selectedChart = ref('downloads')
const selectedChart = computed({
@@ -389,6 +398,13 @@ const tinyRevenueChart = ref()
const selectedDisplayProjects = ref(props.projects || [])
watch(
() => props.projects,
(newProjects) => {
selectedDisplayProjects.value = newProjects || []
},
)
const removeProjectFromDisplay = (id: string) => {
selectedDisplayProjects.value = selectedDisplayProjects.value.filter((p) => p.id !== id)
}
@@ -431,46 +447,47 @@ const isUsingProjectColors = computed({
},
})
const startDate = ref(dayjs().startOf('day'))
const endDate = ref(dayjs().endOf('day'))
const timeResolution = ref(30)
const isInitialized = ref(false)
const defaultRange = props.ranges.find(
(r) => r.getLabel([dayjs(), dayjs()]) === 'Previous 30 days',
)!
const initialDates = defaultRange.getDates(dayjs())
const internalRange: Ref<RangeObject> = ref(defaultRange)
const startDate = ref(initialDates.startDate)
const endDate = ref(initialDates.endDate)
const timeResolution = ref(defaultRange.timeResolution)
debug('default range initialized', {
range: defaultRange.getLabel([dayjs(), dayjs()]),
startDate: startDate.value.toISOString(),
endDate: endDate.value.toISOString(),
timeResolution: timeResolution.value,
})
onBeforeMount(() => {
// Load cached data and range from localStorage - cache.
debug('onBeforeMount')
if (import.meta.client) {
const rangeLabel = localStorage.getItem('analyticsSelectedRange')
debug('localStorage range', { rangeLabel })
if (rangeLabel) {
const range = props.ranges.find((r) => r.getLabel([dayjs(), dayjs()]) === rangeLabel)!
const range = props.ranges.find((r) => r.getLabel([dayjs(), dayjs()]) === rangeLabel)
if (range !== undefined) {
if (range) {
internalRange.value = range
const ranges = range.getDates(dayjs())
const dates = range.getDates(dayjs())
timeResolution.value = range.timeResolution
startDate.value = ranges.startDate
endDate.value = ranges.endDate
startDate.value = dates.startDate
endDate.value = dates.endDate
debug('range overridden from localStorage', {
startDate: dates.startDate.toISOString(),
endDate: dates.endDate.toISOString(),
timeResolution: range.timeResolution,
})
}
}
}
})
onMounted(() => {
if (internalRange.value === null) {
internalRange.value = props.ranges.find(
(r) => r.getLabel([dayjs(), dayjs()]) === 'Previous 30 days',
)!
}
const ranges = selectedRange.value.getDates(dayjs())
startDate.value = ranges.startDate
endDate.value = ranges.endDate
timeResolution.value = selectedRange.value.timeResolution
isInitialized.value = true
})
const internalRange: Ref<RangeObject> = ref(null as unknown as RangeObject)
const selectedRange = computed({
get: () => {
return internalRange.value
@@ -492,6 +509,7 @@ const selectedRange = computed({
},
})
debug('calling useFetchAllAnalytics')
const analytics = useFetchAllAnalytics(
resetCharts,
projects,
@@ -500,9 +518,15 @@ const analytics = useFetchAllAnalytics(
startDate,
endDate,
timeResolution,
isInitialized,
)
debug('awaiting analytics.fetch()')
await analytics.fetch()
debug('analytics.fetch() resolved', {
loading: analytics.loading.value,
error: analytics.error.value,
})
const formattedCategorySubtitle = computed(() => {
return (
selectedRange.value?.getLabel([dayjs(startDate.value), dayjs(endDate.value)]) ?? 'Loading...'
@@ -42,10 +42,18 @@
<script setup lang="ts">
import { MessageIcon } from '@modrinth/assets'
import { Admonition, ButtonStyled, defineMessages, useVIntl } from '@modrinth/ui'
import {
Admonition,
ButtonStyled,
defineMessages,
injectModrinthClient,
useVIntl,
} from '@modrinth/ui'
import { capitalizeString } from '@modrinth/utils'
import { useQuery } from '@tanstack/vue-query'
import { computed, watch } from 'vue'
const client = injectModrinthClient()
const { formatMessage } = useVIntl()
const messages = defineMessages({
@@ -97,35 +105,26 @@ const messages = defineMessages({
},
})
interface UserLimits {
current: number
max: number
}
const props = defineProps<{
type: 'project' | 'org' | 'collection'
}>()
const model = defineModel<boolean>()
const apiEndpoint = computed(() => {
switch (props.type) {
case 'project':
return 'limits/projects'
case 'org':
return 'limits/organizations'
case 'collection':
return 'limits/collections'
default:
return 'limits/projects'
}
const { data: limits } = useQuery({
queryKey: computed(() => ['limits', props.type]),
queryFn: () => {
switch (props.type) {
case 'org':
return client.labrinth.limits_v3.getOrganizationLimits()
case 'collection':
return client.labrinth.limits_v3.getCollectionLimits()
default:
return client.labrinth.limits_v3.getProjectLimits()
}
},
})
const { data: limits } = await useAsyncData<UserLimits | undefined>(
`limits-${props.type}`,
() => useBaseFetch(apiEndpoint.value, { apiVersion: 3 }) as Promise<UserLimits>,
)
const typeName = computed<{ singular: string; plural: string }>(() => {
switch (props.type) {
case 'project':
@@ -229,10 +229,6 @@ const messages = defineMessages({
id: 'create.project.create-project',
defaultMessage: 'Create project',
},
createServerProject: {
id: 'create.project.create-server-project',
defaultMessage: 'Create server',
},
visibilityPublic: {
id: 'create.project.visibility-public',
defaultMessage: 'Public',
@@ -107,6 +107,7 @@
</template>
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import {
ArrowLeftRightIcon,
ChevronRightIcon,
@@ -131,7 +132,6 @@ import {
getTaxThreshold,
getTaxThresholdActual,
type PaymentProvider,
type PayoutMethod,
provideWithdrawContext,
type WithdrawStage,
} from '@/providers/creator-withdraw.ts'
@@ -146,21 +146,9 @@ import MuralpayKycStage from './withdraw-stages/MuralpayKycStage.vue'
import TaxFormStage from './withdraw-stages/TaxFormStage.vue'
import TremendousDetailsStage from './withdraw-stages/TremendousDetailsStage.vue'
type FormCompletionStatus = 'unknown' | 'unrequested' | 'unsigned' | 'tin-mismatch' | 'complete'
interface UserBalanceResponse {
available: number
withdrawn_lifetime: number
withdrawn_ytd: number
pending: number
dates: Record<string, number>
requested_form_type: string | null
form_completion_status: FormCompletionStatus | null
}
const props = defineProps<{
balance: UserBalanceResponse | null
preloadedPaymentData?: { country: string; methods: PayoutMethod[] } | null
balance: Labrinth.Payout.v3.PayoutBalance | null | undefined
preloadedPaymentData?: { country: string; methods: Labrinth.Payout.v3.PayoutMethod[] } | null
}>()
const emit = defineEmits<{
@@ -66,6 +66,7 @@
</template>
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import {
ArrowDownIcon,
ArrowUpIcon,
@@ -89,31 +90,7 @@ import { Tooltip } from 'floating-vue'
import { useGeneratedState } from '~/composables/generated'
import { findRail } from '~/utils/muralpay-rails'
type PayoutStatus = 'in-transit' | 'cancelling' | 'cancelled' | 'success' | 'failed'
type PayoutMethodType = 'paypal' | 'venmo' | 'tremendous' | 'muralpay'
type PayoutSource = 'creator_rewards' | 'affilites'
type WithdrawalTransaction = {
type: 'withdrawal'
id: string
status: PayoutStatus
created: string
amount: number
fee?: number | null
method_type?: PayoutMethodType | null
method?: string
method_id?: string
method_address?: string | null
}
type PayoutAvailableTransaction = {
type: 'payout_available'
created: string
payout_source: PayoutSource
amount: number
}
type Transaction = WithdrawalTransaction | PayoutAvailableTransaction
type Transaction = Labrinth.Payout.v3.TransactionItem
const props = defineProps<{
transaction: Transaction
@@ -1,7 +1,8 @@
<template>
<div class="report">
<div v-if="report" class="report">
<div v-if="report.item_type === 'project'" class="item-info">
<nuxt-link
v-if="report.project"
:to="`/${$getProjectTypeForUrl(report.project.project_type, report.project.loaders)}/${
report.project.slug
}`"
@@ -38,27 +39,29 @@
</div>
</div>
<div v-else-if="report.item_type === 'version'" class="item-info">
<nuxt-link
:to="`/project/${report.project.slug}/version/${report.version.id}`"
class="iconified-link"
>
<div class="backed-svg" :class="{ raised: raised }">
<VersionIcon />
</div>
<span class="title">{{ report.version.name }}</span>
</nuxt-link>
of
<nuxt-link :to="`/project/${report.project.slug}`" class="iconified-stacked-link">
<Avatar :src="report.project.icon_url" size="xs" no-shadow :raised="raised" />
<div class="stacked">
<span class="title">{{ report.project.title }}</span>
<span>{{
formatProjectType(
getProjectTypeForUrl(report.project.project_type, report.project.loaders),
)
}}</span>
</div>
</nuxt-link>
<template v-if="report.version && report.project">
<nuxt-link
:to="`/project/${report.project.slug}/version/${report.version.id}`"
class="iconified-link"
>
<div class="backed-svg" :class="{ raised: raised }">
<VersionIcon />
</div>
<span class="title">{{ report.version.name }}</span>
</nuxt-link>
of
<nuxt-link :to="`/project/${report.project.slug}`" class="iconified-stacked-link">
<Avatar :src="report.project.icon_url" size="xs" no-shadow :raised="raised" />
<div class="stacked">
<span class="title">{{ report.project.title }}</span>
<span>{{
formatProjectType(
getProjectTypeForUrl(report.project.project_type, report.project.loaders),
)
}}</span>
</div>
</nuxt-link>
</template>
</div>
<div v-else class="item-info">
<div class="backed-svg" :class="{ raised: raised }">
@@ -79,7 +82,7 @@
:link="`/${moderation ? 'moderation' : 'dashboard'}/report/${report.id}`"
:auth="auth"
/>
<div class="reporter-info">
<div v-if="report.reporterUser" class="reporter-info">
<ReportIcon class="inline-svg" />
Reported by
<span v-if="auth.user.id === report.reporterUser.id">you</span>
@@ -9,7 +9,7 @@
<h2>Report details</h2>
<ReportInfo :report="report" :show-thread="false" :show-message="false" :auth="auth" />
</section>
<section class="universal-card">
<section v-if="report && thread" class="universal-card">
<h2>Messages</h2>
<ConversationThread
:thread="thread"
@@ -21,6 +21,10 @@
</div>
</template>
<script setup>
import { injectModrinthClient } from '@modrinth/ui'
import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { computed } from 'vue'
import Breadcrumbs from '~/components/ui/Breadcrumbs.vue'
import ReportInfo from '~/components/ui/report/ReportInfo.vue'
import ConversationThread from '~/components/ui/thread/ConversationThread.vue'
@@ -41,74 +45,87 @@ const props = defineProps({
},
})
const report = ref(null)
const client = injectModrinthClient()
const queryClient = useQueryClient()
await fetchReport().then((result) => {
report.value = result
// Fetch raw report
const { data: rawReport } = useQuery({
queryKey: computed(() => ['report', props.reportId]),
queryFn: () => client.labrinth.reports_v3.get(props.reportId),
})
const { data: rawThread } = await useAsyncData(`thread/${report.value.thread_id}`, () =>
useBaseFetch(`thread/${report.value.thread_id}`),
// Compute user IDs needed
const userIds = computed(() => {
if (!rawReport.value) return []
const ids = [rawReport.value.reporter]
if (rawReport.value.item_type === 'user') {
ids.push(rawReport.value.item_id)
}
return ids
})
// Fetch users
const { data: users } = useQuery({
queryKey: computed(() => ['users', userIds.value]),
queryFn: () => client.labrinth.users_v2.getMultiple(userIds.value),
enabled: computed(() => userIds.value.length > 0),
})
// Version ID if applicable
const versionId = computed(() =>
rawReport.value?.item_type === 'version' ? rawReport.value.item_id : null,
)
// Fetch version
const { data: version } = useQuery({
queryKey: computed(() => ['version', versionId.value]),
queryFn: () => client.labrinth.versions_v2.getVersion(versionId.value),
enabled: computed(() => !!versionId.value),
})
// Project ID
const projectId = computed(() => {
if (version.value) return version.value.project_id
if (rawReport.value?.item_type === 'project') return rawReport.value.item_id
return null
})
// Fetch project
const { data: project } = useQuery({
queryKey: computed(() => ['project', projectId.value]),
queryFn: () => client.labrinth.projects_v2.get(projectId.value),
enabled: computed(() => !!projectId.value),
})
// Assemble the full report object
const report = computed(() => {
if (!rawReport.value) return null
return {
...rawReport.value,
project: project.value ?? null,
version: version.value ?? null,
reporterUser: (users.value || []).find((user) => user.id === rawReport.value.reporter),
user:
rawReport.value.item_type === 'user'
? (users.value || []).find((user) => user.id === rawReport.value.item_id)
: undefined,
}
})
// Fetch thread
const { data: rawThread } = useQuery({
queryKey: computed(() => ['thread', report.value?.thread_id]),
queryFn: () => client.labrinth.threads_v3.getThread(report.value.thread_id),
enabled: computed(() => !!report.value?.thread_id),
})
const thread = computed(() =>
rawThread.value && report.value ? addReportMessage(rawThread.value, report.value) : null,
)
const thread = computed(() => addReportMessage(rawThread.value, report.value))
async function updateThread(newThread) {
rawThread.value = newThread
report.value = await fetchReport()
}
async function fetchReport() {
const { data: rawReport } = await useAsyncData(`report/${props.reportId}`, () =>
useBaseFetch(`report/${props.reportId}`),
)
rawReport.value.item_id = rawReport.value.item_id.replace(/"/g, '')
const userIds = []
userIds.push(rawReport.value.reporter)
if (rawReport.value.item_type === 'user') {
userIds.push(rawReport.value.item_id)
}
const versionId = rawReport.value.item_type === 'version' ? rawReport.value.item_id : null
let users = []
if (userIds.length > 0) {
const { data: usersVal } = await useAsyncData(`users?ids=${JSON.stringify(userIds)}`, () =>
useBaseFetch(`users?ids=${encodeURIComponent(JSON.stringify(userIds))}`),
)
users = usersVal.value
}
let version = null
if (versionId) {
const { data: versionVal } = await useAsyncData(`version/${versionId}`, () =>
useBaseFetch(`version/${versionId}`),
)
version = versionVal.value
}
const projectId = version
? version.project_id
: rawReport.value.item_type === 'project'
? rawReport.value.item_id
: null
let project = null
if (projectId) {
const { data: projectVal } = await useAsyncData(`project/${projectId}`, () =>
useBaseFetch(`project/${projectId}`),
)
project = projectVal.value
}
const reportData = rawReport.value
reportData.project = project
reportData.version = version
reportData.reporterUser = users.find((user) => user.id === rawReport.value.reporter)
if (rawReport.value.item_type === 'user') {
reportData.user = users.find((user) => user.id === rawReport.value.item_id)
}
return reportData
queryClient.setQueryData(['thread', report.value?.thread_id], newThread)
await queryClient.invalidateQueries({ queryKey: ['report', props.reportId] })
}
</script>
<style lang="scss" scoped>
@@ -21,14 +21,16 @@
:auth="auth"
class="universal-card recessed"
/>
<p v-if="reports.length === 0">You don't have any active reports.</p>
<p v-if="filteredReports.length === 0">You don't have any active reports.</p>
</template>
<script setup>
import { Chips } from '@modrinth/ui'
import { Chips, injectModrinthClient } from '@modrinth/ui'
import { useQuery } from '@tanstack/vue-query'
import { computed, ref } from 'vue'
import ReportInfo from '~/components/ui/report/ReportInfo.vue'
import { addReportMessage } from '~/helpers/threads.js'
import { asEncodedJsonArray, fetchSegmented } from '~/utils/fetch-helpers.ts'
import { fetchSegmentedWith } from '~/utils/fetch-helpers.ts'
const props = defineProps({
moderation: {
@@ -41,79 +43,113 @@ const props = defineProps({
},
})
const client = injectModrinthClient()
const viewMode = ref('open')
const reasonFilter = ref('All')
const reports = ref([])
const MAX_REPORTS = 1500
let { data: rawReports } = await useAsyncData('report', () =>
useBaseFetch(`report?count=${MAX_REPORTS}`),
)
rawReports = rawReports.value.map((report) => {
report.item_id = report.item_id.replace(/"/g, '')
return report
const { data: rawReportsData } = useQuery({
queryKey: ['reports', MAX_REPORTS],
queryFn: () => client.labrinth.reports_v3.list({ count: MAX_REPORTS }),
placeholderData: [],
})
const reporterUsers = rawReports.map((report) => report.reporter)
const reportedUsers = rawReports
.filter((report) => report.item_type === 'user')
.map((report) => report.item_id)
const versionReports = rawReports.filter((report) => report.item_type === 'version')
const versionIds = [...new Set(versionReports.map((report) => report.item_id))]
const userIds = [...new Set(reporterUsers.concat(reportedUsers))]
const threadIds = [
...new Set(rawReports.filter((report) => report.thread_id).map((report) => report.thread_id)),
]
const reasons = ['All', ...new Set(rawReports.map((report) => report.report_type))]
const rawReports = computed(() => rawReportsData.value)
const [{ data: users }, { data: versions }, { data: threads }] = await Promise.all([
await useAsyncData(`users?ids=${JSON.stringify(userIds)}`, () =>
fetchSegmented(userIds, (ids) => `users?ids=${asEncodedJsonArray(ids)}`),
),
await useAsyncData(`versions?ids=${JSON.stringify(versionIds)}`, () =>
fetchSegmented(versionIds, (ids) => `versions?ids=${asEncodedJsonArray(ids)}`),
),
await useAsyncData(`threads?ids=${JSON.stringify(threadIds)}`, () =>
fetchSegmented(threadIds, (ids) => `threads?ids=${asEncodedJsonArray(ids)}`),
const reporterUsers = computed(() => rawReports.value.map((report) => report.reporter))
const reportedUsers = computed(() =>
rawReports.value.filter((report) => report.item_type === 'user').map((report) => report.item_id),
)
const versionReports = computed(() =>
rawReports.value.filter((report) => report.item_type === 'version'),
)
const versionIds = computed(() => [
...new Set(versionReports.value.map((report) => report.item_id)),
])
const userIds = computed(() => [...new Set(reporterUsers.value.concat(reportedUsers.value))])
const threadIds = computed(() => [
...new Set(
rawReports.value.filter((report) => report.thread_id).map((report) => report.thread_id),
),
])
const reasons = computed(() => [
'All',
...new Set(rawReports.value.map((report) => report.report_type)),
])
const reportedProjects = rawReports
.filter((report) => report.item_type === 'project')
.map((report) => report.item_id)
const versionProjects = versions.value.map((version) => version.project_id)
const projectIds = [...new Set(reportedProjects.concat(versionProjects))]
const { data: projects } = await useAsyncData(`projects?ids=${JSON.stringify(projectIds)}`, () =>
fetchSegmented(projectIds, (ids) => `projects?ids=${asEncodedJsonArray(ids)}`),
)
reports.value = rawReports.map((report) => {
report.reporterUser = users.value.find((user) => user.id === report.reporter)
if (report.item_type === 'user') {
report.user = users.value.find((user) => user.id === report.item_id)
} else if (report.item_type === 'project') {
report.project = projects.value.find((project) => project.id === report.item_id)
} else if (report.item_type === 'version') {
report.version = versions.value.find((version) => version.id === report.item_id)
report.project = projects.value.find((project) => project.id === report.version.project_id)
}
if (report.thread_id) {
report.thread = addReportMessage(
threads.value.find((thread) => report.thread_id === thread.id),
report,
)
}
report.open = true
return report
const { data: users } = useQuery({
queryKey: computed(() => ['users', userIds.value]),
queryFn: () =>
fetchSegmentedWith(userIds.value, (ids) => client.labrinth.users_v2.getMultiple(ids)),
enabled: computed(() => userIds.value.length > 0),
placeholderData: [],
})
const { data: versions } = useQuery({
queryKey: computed(() => ['versions', versionIds.value]),
queryFn: () =>
fetchSegmentedWith(versionIds.value, (ids) => client.labrinth.versions_v2.getVersions(ids)),
enabled: computed(() => versionIds.value.length > 0),
placeholderData: [],
})
const { data: threads } = useQuery({
queryKey: computed(() => ['threads', threadIds.value]),
queryFn: () =>
fetchSegmentedWith(threadIds.value, (ids) => client.labrinth.threads_v3.getMultiple(ids)),
enabled: computed(() => threadIds.value.length > 0),
placeholderData: [],
})
const reportedProjects = computed(() =>
rawReports.value
.filter((report) => report.item_type === 'project')
.map((report) => report.item_id),
)
const versionProjects = computed(() => versions.value.map((version) => version.project_id))
const projectIds = computed(() => [
...new Set(reportedProjects.value.concat(versionProjects.value)),
])
const { data: projects } = useQuery({
queryKey: computed(() => ['projects', projectIds.value]),
queryFn: () =>
fetchSegmentedWith(projectIds.value, (ids) => client.labrinth.projects_v2.getMultiple(ids)),
enabled: computed(() => projectIds.value.length > 0),
placeholderData: [],
})
const userMap = computed(() => new Map(users.value.map((u) => [u.id, u])))
const versionMap = computed(() => new Map(versions.value.map((v) => [v.id, v])))
const projectMap = computed(() => new Map(projects.value.map((p) => [p.id, p])))
const threadMap = computed(() => new Map(threads.value.map((t) => [t.id, t])))
const reports = computed(() =>
rawReports.value.map((report) => {
const enrichedReport = { ...report }
enrichedReport.reporterUser = userMap.value.get(report.reporter)
if (report.item_type === 'user') {
enrichedReport.user = userMap.value.get(report.item_id)
} else if (report.item_type === 'project') {
enrichedReport.project = projectMap.value.get(report.item_id)
} else if (report.item_type === 'version') {
enrichedReport.version = versionMap.value.get(report.item_id)
enrichedReport.project = projectMap.value.get(enrichedReport.version?.project_id)
}
if (report.thread_id) {
const thread = threadMap.value.get(report.thread_id)
enrichedReport.thread = thread ? addReportMessage(thread, enrichedReport) : null
}
enrichedReport.open = true
return enrichedReport
}),
)
const filteredReports = computed(() =>
reports.value?.filter(
(x) =>
(props.moderation || x.reporterUser.id === props.auth.user.id) &&
(props.moderation || x.reporterUser?.id === props.auth.user.id) &&
(viewMode.value === 'open' ? x.open : !x.open) &&
(reasonFilter.value === 'All' || reasonFilter.value === x.report_type),
),
@@ -1,6 +1,13 @@
<script setup lang="ts">
import { type MessageDescriptor, useFormatPrice } from '@modrinth/ui'
import { ButtonStyled, defineMessage, defineMessages, ServersSpecs, useVIntl } from '@modrinth/ui'
import {
ButtonStyled,
commonMessages,
defineMessage,
defineMessages,
ServersSpecs,
useVIntl,
} from '@modrinth/ui'
const { formatMessage } = useVIntl()
const formatPrice = useFormatPrice()
@@ -37,10 +44,7 @@ const plans: Record<
buttonColor: 'blue',
accentText: 'text-blue',
accentBg: 'bg-bg-blue',
name: defineMessage({
id: 'servers.plan.small.name',
defaultMessage: 'Small',
}),
name: commonMessages.planSmallLabel,
description: defineMessage({
id: 'servers.plan.small.description',
defaultMessage: 'Perfect for 15 friends with a few light mods.',
@@ -51,10 +55,7 @@ const plans: Record<
buttonColor: 'green',
accentText: 'text-green',
accentBg: 'bg-bg-green',
name: defineMessage({
id: 'servers.plan.medium.name',
defaultMessage: 'Medium',
}),
name: commonMessages.planMediumLabel,
description: defineMessage({
id: 'servers.plan.medium.description',
defaultMessage: 'Great for 615 players and multiple mods.',
@@ -65,10 +66,7 @@ const plans: Record<
buttonColor: 'purple',
accentText: 'text-purple',
accentBg: 'bg-bg-purple',
name: defineMessage({
id: 'servers.plan.large.name',
defaultMessage: 'Large',
}),
name: commonMessages.planLargeLabel,
description: defineMessage({
id: 'servers.plan.large.description',
defaultMessage: 'Ideal for 1525 players, modpacks, or heavy modding.',
@@ -1,47 +1,15 @@
import type { Organization, Project, Report, User, Version } from '@modrinth/utils'
import type { AbstractModrinthClient, Labrinth } from '@modrinth/api-client'
type Thread = { id: string }
type Notification = Labrinth.Notifications.v2.Notification
export type PlatformNotificationAction = {
title: string
action_route: [string, string]
}
export type PlatformNotificationBody = {
project_id?: string
version_id?: string
report_id?: string
thread_id?: string
invited_by?: string
organization_id?: string
}
export type PlatformNotification = {
id: string
user_id: string
type: 'project_update' | 'team_invite' | 'status_change' | 'moderator_message'
title: string
text: string
link: string
read: boolean
created: string
actions: PlatformNotificationAction[]
body?: PlatformNotificationBody
export type PlatformNotification = Notification & {
extra_data?: Record<string, unknown>
grouped_notifs?: PlatformNotification[]
}
async function getBulk<T extends { id: string }>(
type: string,
ids: string[],
apiVersion = 2,
): Promise<T[]> {
if (!ids || ids.length === 0) {
return []
}
const url = `${type}?ids=${encodeURIComponent(JSON.stringify([...new Set(ids)]))}`
async function safeBulkFetch<T>(fn: () => Promise<T[]>): Promise<T[]> {
try {
const res = await useBaseFetch(url, { apiVersion })
const res = await fn()
return Array.isArray(res) ? res : []
} catch {
return []
@@ -49,6 +17,7 @@ async function getBulk<T extends { id: string }>(
}
export async function fetchExtraNotificationData(
client: AbstractModrinthClient,
notifications: PlatformNotification[],
): Promise<PlatformNotification[]> {
const bulk = {
@@ -72,7 +41,14 @@ export async function fetchExtraNotificationData(
}
}
const reports = (await getBulk<Report>('reports', bulk.reports)).filter(Boolean)
const reports = (
await safeBulkFetch(() =>
bulk.reports.length > 0
? client.labrinth.reports_v3.getMultiple([...new Set(bulk.reports)])
: Promise.resolve([]),
)
).filter(Boolean)
for (const r of reports) {
if (!r?.item_type) continue
if (r.item_type === 'project') bulk.projects.push(r.item_id)
@@ -80,16 +56,42 @@ export async function fetchExtraNotificationData(
else if (r.item_type === 'version') bulk.versions.push(r.item_id)
}
const versions = (await getBulk<Version>('versions', bulk.versions)).filter(Boolean)
const versions = (
await safeBulkFetch(() =>
bulk.versions.length > 0
? client.labrinth.versions_v2.getVersions([...new Set(bulk.versions)])
: Promise.resolve([]),
)
).filter(Boolean)
for (const v of versions) bulk.projects.push(v.project_id)
const [projects, threads, users, organizations] = await Promise.all([
getBulk<Project>('projects', bulk.projects),
getBulk<Thread>('threads', bulk.threads),
getBulk<User>('users', bulk.users),
getBulk<Organization>('organizations', bulk.organizations, 3),
safeBulkFetch(() =>
bulk.projects.length > 0
? client.labrinth.projects_v2.getMultiple([...new Set(bulk.projects)])
: Promise.resolve([]),
),
safeBulkFetch(() =>
bulk.threads.length > 0
? client.labrinth.threads_v3.getMultiple([...new Set(bulk.threads)])
: Promise.resolve([]),
),
safeBulkFetch(() =>
bulk.users.length > 0
? client.labrinth.users_v2.getMultiple([...new Set(bulk.users)])
: Promise.resolve([]),
),
safeBulkFetch(() =>
bulk.organizations.length > 0
? client.labrinth.organizations_v3.getMultiple([...new Set(bulk.organizations)])
: Promise.resolve([]),
),
])
type Report = Labrinth.Reports.v3.Report
type Version = Labrinth.Versions.v2.Version
for (const n of notifications) {
n.extra_data = {}
if (n.body) {
@@ -133,13 +135,13 @@ export function groupNotifications(notifications: PlatformNotification[]): Platf
const current = notifications[i]
const next = notifications[i + 1]
if (current.body && i < notifications.length - 1 && isSimilar(current, next)) {
current.grouped_notifs = [next]
const groupedNotif = { ...current, grouped_notifs: [next] }
let j = i + 2
while (j < notifications.length && isSimilar(current, notifications[j])) {
current.grouped_notifs.push(notifications[j])
groupedNotif.grouped_notifs.push(notifications[j])
j++
}
grouped.push(current)
grouped.push(groupedNotif)
i = j - 1
} else {
grouped.push(current)
@@ -153,11 +155,10 @@ function isSimilar(a: PlatformNotification, b: PlatformNotification | undefined)
}
export async function markAsRead(
client: AbstractModrinthClient,
ids: string[],
): Promise<(notifications: PlatformNotification[]) => PlatformNotification[]> {
await useBaseFetch(`notifications?ids=${JSON.stringify([...new Set(ids)])}`, {
method: 'PATCH',
})
await client.labrinth.notifications_v2.markMultipleAsRead(ids)
return (notifications: PlatformNotification[]) => {
const newNotifs = notifications ?? []
newNotifs.forEach((n) => {
+34 -10
View File
@@ -2,17 +2,31 @@ export function addReportMessage(thread, report) {
if (!thread || !report) {
return thread
}
if (
!thread.members.some((user) => {
return user.id === report.reporterUser.id
})
) {
thread.members.push(report.reporterUser)
const reporterId = report.reporterUser?.id ?? report.reporter
if (!reporterId) {
return thread
}
if (!thread.messages.some((message) => message.id === 'original')) {
thread.messages.push({
const members = Array.isArray(thread.members) ? [...thread.members] : []
const messages = Array.isArray(thread.messages) ? [...thread.messages] : []
let changed = false
if (
!members.some((user) => {
return user?.id === reporterId
}) &&
report.reporterUser
) {
members.push(report.reporterUser)
changed = true
}
if (!messages.some((message) => message?.id === 'original')) {
messages.push({
id: 'original',
author_id: report.reporterUser.id,
author_id: reporterId,
body: {
type: 'text',
body: report.body,
@@ -21,6 +35,16 @@ export function addReportMessage(thread, report) {
},
created: report.created,
})
changed = true
}
if (!changed) {
return thread
}
return {
...thread,
members,
messages,
}
return thread
}
+9 -5
View File
@@ -69,7 +69,7 @@
</NuxtLink>
</div>
<div
class="col-span-2 row-start-2 flex flex-wrap justify-center lg:col-span-1 lg:row-start-auto"
class="col-span-2 row-start-2 flex justify-center lg:col-span-1 lg:row-start-auto"
:class="{ 'gap-4': !flags.projectTypesPrimaryNav }"
>
<template v-if="flags.projectTypesPrimaryNav">
@@ -735,10 +735,12 @@ import {
commonMessages,
commonProjectTypeCategoryMessages,
defineMessages,
injectModrinthClient,
OverflowMenu,
useVIntl,
} from '@modrinth/ui'
import { isAdmin, isStaff, UserBadge } from '@modrinth/utils'
import { useQuery } from '@tanstack/vue-query'
import { getTaxThreshold } from '@/providers/creator-withdraw.ts'
import TextLogo from '~/components/brand/TextLogo.vue'
@@ -775,10 +777,12 @@ const config = useRuntimeConfig()
const route = useNativeRoute()
const router = useNativeRouter()
const link = config.public.siteUrl + route.path.replace(/\/+$/, '')
const client = injectModrinthClient()
const { data: payoutBalance } = await useAsyncData('payout/balance', () => {
if (!auth.value.user) return null
return useBaseFetch('payout/balance', { apiVersion: 3 })
const { data: payoutBalance } = useQuery({
queryKey: ['payout', 'balance'],
queryFn: () => client.labrinth.payout_v3.getBalance(),
enabled: computed(() => !!auth.value.user),
})
const showTaxComplianceBanner = computed(() => {
@@ -1140,7 +1144,7 @@ async function onKeyDown(event) {
rCount.value++
if (randomProjects.value.length < 3) {
randomProjects.value = await useBaseFetch('projects_random?count=50').catch((err) => {
randomProjects.value = await client.labrinth.projects_v2.getRandom(50).catch((err) => {
console.error(err)
return []
})
@@ -1331,15 +1331,6 @@
"servers.notice.id": {
"message": "ID"
},
"servers.plan.large.name": {
"message": "Velký"
},
"servers.plan.medium.name": {
"message": "Střední"
},
"servers.plan.small.name": {
"message": "Malý"
},
"settings.billing.payment_method.primary": {
"message": "Hlavní"
},
@@ -107,6 +107,9 @@
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.description": {
"message": "Modrinth App præsterer bedre end mange af de førende mod-håndteringsværktøjer og bruger kun 150 MB RAM!"
},
"app-marketing.features.performance.discord": {
"message": "Discord"
},
@@ -482,12 +485,24 @@
"create.project.create-project": {
"message": "Opret projekt"
},
"create.project.missing-fields-tooltip": {
"message": "Mangler informationer: {fields}"
},
"create.project.name-label": {
"message": "Navn"
},
"create.project.name-placeholder": {
"message": "Indtast projekt navn..."
},
"create.project.owner-description": {
"message": "Det projekt ejeren som dig selv eller en organisation du medlem af."
},
"create.project.owner-label": {
"message": "Ejer"
},
"create.project.server-project-title": {
"message": "Opretter et server projekt"
},
"create.project.summary-description": {
"message": "En sætning eller to som beskriver dit projekt."
},
@@ -500,6 +515,15 @@
"create.project.title": {
"message": "Opretter et projekt"
},
"create.project.type-label": {
"message": "Type"
},
"create.project.type-project": {
"message": "Projekt"
},
"create.project.type-server": {
"message": "Server"
},
"create.project.url-label": {
"message": "URL"
},
@@ -539,6 +563,15 @@
"dashboard.collections.button.create-new": {
"message": "Opret ny"
},
"dashboard.collections.empty.get-started-hint": {
"message": "Opret din første samling for at komme i gang!"
},
"dashboard.collections.empty.no-collections": {
"message": "Du har ikke nogle samlinger endnu"
},
"dashboard.collections.empty.no-match": {
"message": "Ingen samlinger passer din søgning"
},
"dashboard.collections.label.search-input": {
"message": "Søg dine samlinger"
},
@@ -956,6 +989,9 @@
"hosting-marketing.faq.ddos-protection": {
"message": "Har Modrinth Hosting servere DDoS beskyttelse?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Ja. Alle Modrinth servere kommer med DDoS beskyttelse, med op til 17 Tbps kapacitet i nogle lokationer."
},
"hosting-marketing.faq.heading": {
"message": "Ofte Spurgt Spørgsmål"
},
@@ -1061,6 +1097,9 @@
"hosting-marketing.know-what-you-need": {
"message": "Hvad har du præcis brug for?"
},
"hosting-marketing.medal.info": {
"message": "Prøv en gratis <orange>3 GB server</orange> i 5 dage drevet af <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Lær mere"
},
@@ -1112,6 +1151,24 @@
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Vælg imellem Vanilla, Fabric, Forge, Quilt og NeoForge. Hvis det er på Modrinth, det kan køre på din server."
},
"hosting.loader.failed-to-change-version": {
"message": "Fejlede i at ændre modpack version"
},
"hosting.loader.failed-to-load-versions": {
"message": "Fejlede i at indlæse versioner"
},
"hosting.loader.failed-to-reinstall": {
"message": "Fejlede i at geninstallere modpack"
},
"hosting.loader.failed-to-repair": {
"message": "Fejlede i at reparere server"
},
"hosting.loader.failed-to-save-settings": {
"message": "Fejlede i at gemme installation indstillinger"
},
"hosting.loader.failed-to-unlink": {
"message": "Fejlede i at unlink modpack"
},
"hosting.plan.out-of-stock": {
"message": "Ikke på lager"
},
@@ -2057,6 +2114,12 @@
"settings.sessions.unknown-platform": {
"message": "Ukendt platform"
},
"settings.sidebar.label.account": {
"message": "Konto"
},
"settings.sidebar.label.developer": {
"message": "Udvikler"
},
"ui.latest-news-row.latest-news": {
"message": "Seneste nyheder fra Modrinth"
},
+410 -14
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Projekt erstellen"
},
"create.project.create-server-project": {
"message": "Server erstellen"
},
"create.project.missing-fields-tooltip": {
"message": "Fehlende Felder: {fields}"
},
@@ -2858,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Ideal für 15 - 25 Spieler, Modpakete, oder umfrangreiches modding."
},
"servers.plan.large.name": {
"message": "Gross"
},
"servers.plan.medium.description": {
"message": "Geeignet für 6 - 15 Spieler und mehrere Mods."
},
"servers.plan.medium.name": {
"message": "Mittel"
},
"servers.plan.small.description": {
"message": "Perfekt für 1 - 5 Freunde mit ein par leichten Mods."
},
"servers.plan.small.name": {
"message": "Klein"
"settings.account.button.complete-setup": {
"message": "Einrichtung abschliessen"
},
"settings.account.data-export.action.download": {
"message": "Export herunterladen"
},
"settings.account.data-export.action.generate": {
"message": "Export generieren"
},
"settings.account.data-export.action.generating": {
"message": "Export wird generiert..."
},
"settings.account.data-export.description": {
"message": "Fordere eine Kopie aller deiner personenbezogenen Daten an, die du bei Modrinth hochgeladen hast. Dies kann einige Minuten dauern."
},
"settings.account.data-export.title": {
"message": "Datenexport"
},
"settings.account.delete.confirm.description": {
"message": "Dadurch werden **sofort alle deine Benutzerdaten und Follower gelöscht**. Deine Projekte werden dabei nicht gelöscht. Die Löschung deines Kontos kann nicht rückgängig gemacht werden.<br><br>Falls du Hilfe mit deinem Konto benötigst, wende dich bitte an den Support auf dem [Modrinth Discord](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Dieses Konto löschen"
},
"settings.account.delete.confirm.title": {
"message": "Bist du sicher, dass du deinen Account löschen willst?"
},
"settings.account.delete.section.action": {
"message": "Konto löschen"
},
"settings.account.delete.section.description": {
"message": "Sobald du dein Konto löschst, gibt es kein Zurück mehr. Durch das Löschen deines Kontos werden alle zugehörigen Daten ausser Projekte von unseren Servern entfernt."
},
"settings.account.delete.section.title": {
"message": "Konto löschen"
},
"settings.account.email.action.save": {
"message": "E-Mail speichern"
},
"settings.account.email.field.label": {
"message": "E-Mail-Adresse"
},
"settings.account.email.field.placeholder": {
"message": "Gib deine E-Mail-Adresse ein..."
},
"settings.account.email.modal.header.add": {
"message": "E-Mail hinzufügen"
},
"settings.account.email.modal.header.change": {
"message": "E-Mail ändern"
},
"settings.account.email.modal.notice": {
"message": "Deine Kontoinformationen werden nicht öffentlich angezeigt."
},
"settings.account.password.action.remove": {
"message": "Passwort entfernen"
},
"settings.account.password.action.save": {
"message": "Passwort speichern"
},
"settings.account.password.error.mismatch": {
"message": "Die eingegebenen Passwörter stimmen nicht überein!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Bitte gib dein Passwort ein, um fortzufahren."
},
"settings.account.password.field.confirm-current.label": {
"message": "Passwort bestätigen"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Passwort bestätigen"
},
"settings.account.password.field.confirm-new.label": {
"message": "Neues Passwort bestätigen"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Neues Passwort bestätigen"
},
"settings.account.password.field.new.label": {
"message": "Neues Passwort"
},
"settings.account.password.field.new.placeholder": {
"message": "Neues Passwort"
},
"settings.account.password.field.old.label": {
"message": "Altes Passwort"
},
"settings.account.password.field.old.placeholder": {
"message": "Altes Passwort"
},
"settings.account.password.modal.header.add": {
"message": "Passwort hinzufügen"
},
"settings.account.password.modal.header.change": {
"message": "Passwort ändern"
},
"settings.account.password.modal.header.remove": {
"message": "Passwort entfernen"
},
"settings.account.providers.action.add": {
"message": "Hinzufügen"
},
"settings.account.providers.modal.header": {
"message": "Authentifizierungsanbieter"
},
"settings.account.providers.table.actions": {
"message": "Aktionen"
},
"settings.account.providers.table.provider": {
"message": "Anbieter"
},
"settings.account.security.email.action.add": {
"message": "E-Mail hinzufügen"
},
"settings.account.security.email.action.change": {
"message": "E-Mail ändern"
},
"settings.account.security.email.description": {
"message": "Ändert die mit deinem Konto verknüpfte E-Mail."
},
"settings.account.security.email.title": {
"message": "E-Mail"
},
"settings.account.security.password.action.add": {
"message": "Passwort hinzufügen"
},
"settings.account.security.password.action.change": {
"message": "Passwort ändern"
},
"settings.account.security.password.description.change": {
"message": "Ändere das Passwort, mit dem du dich bei deinem Konto anmeldest."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Ändere oder lösche das Passwort, mit dem du dich bei deinem Konto anmeldest."
},
"settings.account.security.password.description.set": {
"message": "Lege ein permanentes Passwort für die Anmeldung bei deinem Konto fest."
},
"settings.account.security.password.title": {
"message": "Passwort"
},
"settings.account.security.providers.action.manage": {
"message": "Anbieter verwalten"
},
"settings.account.security.providers.description": {
"message": "Du kannst deinem Konto Anmeldemethoden hinzufügen oder entfernen, darunter GitHub, GitLab, Microsoft, Discord, Steam und Google."
},
"settings.account.security.providers.title": {
"message": "Authentifizierungsanbieter verwalten"
},
"settings.account.security.title": {
"message": "Kontosicherheit"
},
"settings.account.security.two-factor.action.remove": {
"message": "2FA entfernen"
},
"settings.account.security.two-factor.action.setup": {
"message": "2FA einrichten"
},
"settings.account.security.two-factor.description": {
"message": "Füge deinem Konto bei der Anmeldung eine zusätzliche Sicherheitsstufe hinzu."
},
"settings.account.security.two-factor.title": {
"message": "Zwei-Faktor-Authentifizierung"
},
"settings.account.two-factor.backup.intro": {
"message": "Lade diese Wiederherstellungscodes herunder und bewahre sie an einem sicheren Ort auf. Du kannst diese anstelle eines 2FA-Codes verwenden, solltest du jemals zugriff auf dein Gerät verlieren! Du solltest diese Codes wie deine Passwörter schützen."
},
"settings.account.two-factor.backup.single-use": {
"message": "Wiedererstellungscodes können nur einmal verwendet werden."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "Der eingegebene Code ist ungültig!"
},
"settings.account.two-factor.field.code.description": {
"message": "Bitte gib einen Zwei-Faktor-Code ein, um fortzufahren."
},
"settings.account.two-factor.field.code.label": {
"message": "Zwei-Faktor-Code eingeben"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Code eingeben..."
},
"settings.account.two-factor.setup.intro": {
"message": "Die Zwei-Faktor-Authentifizierung schützt dein Konto, indem es für die Anmeldung den Zugriff auf ein zweites Gerät erfordert."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Falls der QR-Code nicht gescannt werden kann, kannst du das Passwort manuell eingeben:"
},
"settings.account.two-factor.setup.scan": {
"message": "Scanne den QR-Code mit <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> oder einer anderen 2FA-App, um zu beginnen."
},
"settings.account.two-factor.verify.description": {
"message": "Gib den Einmalcode aus der Authentifizierungs-App ein, um den Zugriff zu bestätigen."
},
"settings.account.two-factor.verify.label": {
"message": "Code bestätigen"
},
"settings.applications.about": {
"message": "Über"
@@ -2954,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Anwendungen"
},
"settings.applications.modal.header": {
"message": "Anwendungsinformationen"
},
"settings.applications.notification.error.title": {
"message": "Ein Fehler ist aufgetreten"
},
"settings.applications.notification.icon-updated.description": {
"message": "Dein Anwendungsicon wurde aktualisiert."
},
@@ -2969,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "Speichere jetzt dein Geheimnis, da es nach dem verlassen dieser Seite versteckt wird!"
},
"settings.authorizations.about-this-app": {
"message": "Über diese Anwendung"
},
"settings.authorizations.by": {
"message": "von"
},
"settings.authorizations.description": {
"message": "Wenn du eine Anwendung mit deinem Modrinth-Konto autorisierst, gewährst du dieser Zugriff auf dein Konto. Du kannst den Zugriff auf dein Konto hier jederzeit verwalten und überprüfen."
},
"settings.authorizations.empty-state": {
"message": "Wir konnen aktuell deine autorisierten Anwendungen nicht anzeigen und arbeiten an einer lösung dafür. Bitte besuche diese Seite zu einem späteren Zeitpunkt erneut!"
},
"settings.authorizations.head-title": {
"message": "Autorisierungen"
},
"settings.authorizations.revoke.action": {
"message": "Widerrufen"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Dadurch wird der Anwendung der Zugriff auf dein Konto widerrufen. Du kannst sie später jederzeit erneut autorisieren."
},
"settings.authorizations.revoke.confirm.title": {
"message": "Möchtest du diese Anwendung wirklich widerrufen?"
},
"settings.billing.charges.description": {
"message": "Hier werden alle bisherigen Belastungen deines Modrinth-Kontos aufgeführt:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Medal Server-Testversion"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Läuft ab am {date}"
},
"settings.billing.interval.month": {
"message": "Monat"
},
"settings.billing.interval.monthly": {
"message": "monatlich"
},
"settings.billing.interval.year": {
"message": "Jahr"
},
"settings.billing.interval.yearly": {
"message": "jährlich"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Werbefreies Surfen auf modrinth.com und der Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Modrinth+ Abzeichen auf deinem Profil"
},
"settings.billing.midas.benefits.support": {
"message": "Unterstütze Modrinth und Ersteller direkt"
},
"settings.billing.midas.benefits.title": {
"message": "Vorteile"
},
"settings.billing.midas.save-per-year": {
"message": "Spare {amount}/Jahr, indem du auf jährliche Abrechnung umsteigst!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Du hast dein Abonnement gekündigt."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "Du behällst deine Vorteile bis zum ender der aktuellen Zahlungsperiode."
},
"settings.billing.midas.status.failed": {
"message": "Die Zahlung für dein Abonnement ist fehlgeschlagen. Bitte aktualisiere deine Zahlungsmethode."
},
"settings.billing.midas.status.open": {
"message": "Du hast derzeit folgende Abonnements:"
},
"settings.billing.midas.status.processing": {
"message": "Deine Zahlung wird bearbeitet. Vorteile werden aktiviert, sobald die Zahlung abgeschlossen ist."
},
"settings.billing.midas.upsell": {
"message": "Werde ein Abonnent von Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Abonnement kündigen"
},
@@ -2987,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "Bist du sicher, dass du diese Zahlungsmethode entfernen willst?"
},
"settings.billing.next": {
"message": "Nächstes:"
},
"settings.billing.or-yearly-save": {
"message": "Oder {price} / Jahr (spare {percent}%)!"
},
"settings.billing.payment_method.action.add": {
"message": "Zahlungsmethode hinzufügen"
},
@@ -3008,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Zahlungsmethoden"
},
"settings.billing.plan.title": {
"message": "{size} Plan"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} Geteilte CPUs (Spitzenlasten von bis zu {bursts} CPUs)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "Für dieses Abonnoment konnte kein verknüpfter Server gefunden werden. Dafür kann es verschiedene Gründe geben. Wenn du deinen Server gerade erst gekauft hast, ist dies normal. Es kann bis zu einer Stunde dauern, bist dein Server bereitgestellt ist. Falls du diesen Server bereits vor einiger Zeit erworben hast, wurde er wahrscheinlich inzwischen gesperrt. Sollte dies nicht das sein, was du erwartet hast, wende dich bitte an den Modrinth Support mit den folgenden Informationen:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "Server-ID: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "Stripe-ID: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} GB RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Ein Fehler ist bein erneuten abonnieren deines Modrinth Server aufgetreten."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Fehler beim erneuten Abonnieren"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Falls der Server momentan pausiert ist, kann es bis zu 10 Minuten dauern, bis ein weiterer Zahlungsversuch unternommen wird."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Anfrage zum erneuten Abonnieren übermittelt"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "Server-Abonnoment efolgreich erneuert"
},
"settings.billing.pyro.status.failed": {
"message": "Die Zahlung für dein Abonnement ist fehlgeschlagen. Bitte aktualisiere deine Zahlungsmethode und abonniere erneut."
},
"settings.billing.pyro.status.processing": {
"message": "Deine Zahlung wird bearbeitet. Dein Server wird aktiviert, sobald die Zahlung abgeschlossen ist."
},
"settings.billing.pyro.storage": {
"message": "{gb} GB SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} GB Swap"
},
"settings.billing.pyro_subscription.description": {
"message": "Verwalte deine Modrinth Server Abonnements."
},
"settings.billing.pyro_subscription.title": {
"message": "Modrinth Server Abonnements"
},
"settings.billing.renews": {
"message": "Wird erneuert am {date}"
},
"settings.billing.resubscribe": {
"message": "Erneut abonnieren"
},
"settings.billing.since": {
"message": "Seit dem {date}"
},
"settings.billing.subscribe": {
"message": "Abonnieren"
},
"settings.billing.subscription.description": {
"message": "Verwalte deine Modrinth Server Abonnements."
},
"settings.billing.subscription.title": {
"message": "Abonnements"
},
"settings.billing.switch.switching-to-interval": {
"message": "Wechsle auf {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Zu {interval} wechseln"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Monatliche Abrechnung kostet dich zusätzliche {amount} pro Jahr"
},
"settings.billing.switches-to-billing-on": {
"message": "Wechselt am {date} auf {interval} Abrechnung"
},
"settings.billing.update-method": {
"message": "Methode aktualisieren"
},
"settings.billing.upgrade": {
"message": "Aktualisieren"
},
"settings.display.banner.developer-mode.button": {
"message": "Entwicklermodus deaktivieren"
},
@@ -3032,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Funktionen umschalten"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "Entwicklermodus wurde deaktiviert"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Entwicklermodus deaktiviert"
},
"settings.display.project-list-layouts.datapack": {
"message": "Datenpakete-Seite"
},
@@ -3041,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Mods-Seite"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galerie"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Raster"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Zeilen"
},
"settings.display.project-list-layouts.modpack": {
"message": "Modpakete-Seite"
},
@@ -3101,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Farbschema"
},
"settings.head-title": {
"message": "Anzeigeeinstellungen"
},
"settings.pats.action.create": {
"message": "Erstelle einen PAT"
},
@@ -3161,6 +3536,9 @@
"settings.profile.description": {
"message": "Deine Profilinformationen sind auf Modrinth und über die <docs-link>Modrinth API</docs-link> öffentlich einsehbar."
},
"settings.profile.head-title": {
"message": "Profileinstellungen"
},
"settings.profile.profile-info": {
"message": "Profilinformationen"
},
@@ -3191,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Unbekannte Platform"
},
"settings.sidebar.label.account": {
"message": "Konto"
},
"settings.sidebar.label.developer": {
"message": "Entwickler"
},
"settings.sidebar.label.display": {
"message": "Anzeige"
},
"ui.latest-news-row.latest-news": {
"message": "Neuste Nachrichten von Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Alle Neuigkeiten anzeigen"
},
"ui.newsletter-button.subscribe": {
"message": "Abonnieren"
},
"ui.newsletter-button.subscribed": {
"message": "Abonniert!"
},
"ui.newsletter-button.tooltip": {
"message": "Abonniere den Modrinth Newsletter"
},
"version.environment.none.description": {
"message": "Die Umgebung für diese Version wurde nicht angegeben."
},
+410 -14
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Projekt erstellen"
},
"create.project.create-server-project": {
"message": "Server erstellen"
},
"create.project.missing-fields-tooltip": {
"message": "Fehlende Felder: {fields}"
},
@@ -2858,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Ideal für 1525 Spieler, Modpacks oder intensives Modding."
},
"servers.plan.large.name": {
"message": "Groß"
},
"servers.plan.medium.description": {
"message": "Geeignet für 615 Spieler und mehrere Mods."
},
"servers.plan.medium.name": {
"message": "Mittel"
},
"servers.plan.small.description": {
"message": "Perfekt für 15 Freunde mit ein paar kleinen Mods."
},
"servers.plan.small.name": {
"message": "Klein"
"settings.account.button.complete-setup": {
"message": "Einrichtung abschließen"
},
"settings.account.data-export.action.download": {
"message": "Export herunterladen"
},
"settings.account.data-export.action.generate": {
"message": "Export generieren"
},
"settings.account.data-export.action.generating": {
"message": "Export wird generiert..."
},
"settings.account.data-export.description": {
"message": "Fordere eine Kopie aller deiner personenbezogenen Daten an, die du bei Modrinth hochgeladen hast. Dies kann einige Minuten dauern."
},
"settings.account.data-export.title": {
"message": "Datenexport"
},
"settings.account.delete.confirm.description": {
"message": "Dadurch werden **sofort alle deine Benutzerdaten und Follower gelöscht**. Deine Projekte werden dabei nicht gelöscht. Die Löschung deines Kontos kann nicht rückgängig gemacht werden.<br><br>Falls du Hilfe mit deinem Konto benötigst, wende dich bitte an den Support auf dem [Modrinth Discord](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Dieses Konto löschen"
},
"settings.account.delete.confirm.title": {
"message": "Möchtest du dein Konto wirklich löschen?"
},
"settings.account.delete.section.action": {
"message": "Konto löschen"
},
"settings.account.delete.section.description": {
"message": "Sobald du dein Konto löschst, gibt es kein Zurück mehr. Durch das Löschen deines Kontos werden alle zugehörigen Daten außer Projekte von unseren Servern entfernt."
},
"settings.account.delete.section.title": {
"message": "Konto löschen"
},
"settings.account.email.action.save": {
"message": "E-Mail speichern"
},
"settings.account.email.field.label": {
"message": "E-Mail-Adresse"
},
"settings.account.email.field.placeholder": {
"message": "Gib deine E-Mail-Adresse ein..."
},
"settings.account.email.modal.header.add": {
"message": "E-Mail hinzufügen"
},
"settings.account.email.modal.header.change": {
"message": "E-Mail ändern"
},
"settings.account.email.modal.notice": {
"message": "Deine Kontoinformationen werden nicht öffentlich angezeigt."
},
"settings.account.password.action.remove": {
"message": "Passwort entfernen"
},
"settings.account.password.action.save": {
"message": "Passwort speichern"
},
"settings.account.password.error.mismatch": {
"message": "Die eingegebenen Passwörter stimmen nicht überein!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Bitte gib dein Passwort ein, um fortzufahren."
},
"settings.account.password.field.confirm-current.label": {
"message": "Passwort bestätigen"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Passwort bestätigen"
},
"settings.account.password.field.confirm-new.label": {
"message": "Neues Passwort bestätigen"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Neues Passwort bestätigen"
},
"settings.account.password.field.new.label": {
"message": "Neues Passwort"
},
"settings.account.password.field.new.placeholder": {
"message": "Neues Passwort"
},
"settings.account.password.field.old.label": {
"message": "Altes Passwort"
},
"settings.account.password.field.old.placeholder": {
"message": "Altes Passwort"
},
"settings.account.password.modal.header.add": {
"message": "Passwort hinzufügen"
},
"settings.account.password.modal.header.change": {
"message": "Passwort ändern"
},
"settings.account.password.modal.header.remove": {
"message": "Passwort entfernen"
},
"settings.account.providers.action.add": {
"message": "Hinzufügen"
},
"settings.account.providers.modal.header": {
"message": "Authentifizierungsanbieter"
},
"settings.account.providers.table.actions": {
"message": "Aktionen"
},
"settings.account.providers.table.provider": {
"message": "Anbieter"
},
"settings.account.security.email.action.add": {
"message": "E-Mail hinzufügen"
},
"settings.account.security.email.action.change": {
"message": "E-Mail ändern"
},
"settings.account.security.email.description": {
"message": "Ändert die mit deinem Konto verknüpfte E-Mail."
},
"settings.account.security.email.title": {
"message": "E-Mail"
},
"settings.account.security.password.action.add": {
"message": "Passwort hinzufügen"
},
"settings.account.security.password.action.change": {
"message": "Passwort ändern"
},
"settings.account.security.password.description.change": {
"message": "Ändere das Passwort, mit dem du dich bei deinem Konto anmeldest."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Ändere oder lösche das Passwort, mit dem du dich bei deinem Konto anmeldest."
},
"settings.account.security.password.description.set": {
"message": "Lege ein permanentes Passwort für die Anmeldung bei deinem Konto fest."
},
"settings.account.security.password.title": {
"message": "Passwort"
},
"settings.account.security.providers.action.manage": {
"message": "Anbieter verwalten"
},
"settings.account.security.providers.description": {
"message": "Du kannst deinem Konto Anmeldemethoden hinzufügen oder entfernen, darunter GitHub, GitLab, Microsoft, Discord, Steam und Google."
},
"settings.account.security.providers.title": {
"message": "Authentifizierungsanbieter verwalten"
},
"settings.account.security.title": {
"message": "Kontosicherheit"
},
"settings.account.security.two-factor.action.remove": {
"message": "2FA entfernen"
},
"settings.account.security.two-factor.action.setup": {
"message": "2FA einrichten"
},
"settings.account.security.two-factor.description": {
"message": "Füge deinem Konto bei der Anmeldung eine zusätzliche Sicherheitsstufe hinzu."
},
"settings.account.security.two-factor.title": {
"message": "Zwei-Faktor-Authentifizierung"
},
"settings.account.two-factor.backup.intro": {
"message": "Lade diese Wiederherstellungscodes herunter und bewahre sie an einem sicheren Ort auf. Du kannst diese anstelle eines 2FA-Codes verwenden, falls du jemals den Zugriff auf dein Gerät verlierst! Du solltest diese Codes genauso schützen wie dein Passwort."
},
"settings.account.two-factor.backup.single-use": {
"message": "Wiedererstellungscodes können nur einmal verwendet werden."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "Der eingegebene Code ist ungültig!"
},
"settings.account.two-factor.field.code.description": {
"message": "Bitte gib einen Zwei-Faktor-Code ein, um fortzufahren."
},
"settings.account.two-factor.field.code.label": {
"message": "Zwei-Faktor-Code eingeben"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Code eingeben..."
},
"settings.account.two-factor.setup.intro": {
"message": "Die Zwei-Faktor-Authentifizierung schützt dein Konto, indem sie für die Anmeldung den Zugriff auf ein zweites Gerät erfordert."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Falls der QR-Code nicht gescannt werden kann, kannst du das Passwort manuell eingeben:"
},
"settings.account.two-factor.setup.scan": {
"message": "Scanne den QR-Code mit <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> oder einer anderen 2FA-App, um zu beginnen."
},
"settings.account.two-factor.verify.description": {
"message": "Gib den Einmalcode aus dem Authentifikator ein, um den Zugriff zu bestätigen."
},
"settings.account.two-factor.verify.label": {
"message": "Code bestätigen"
},
"settings.applications.about": {
"message": "Über"
@@ -2954,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Anwendungen"
},
"settings.applications.modal.header": {
"message": "Anwendungsinformationen"
},
"settings.applications.notification.error.title": {
"message": "Ein Fehler ist aufgetreten"
},
"settings.applications.notification.icon-updated.description": {
"message": "Dein Anwendungsicon wurde aktualisiert."
},
@@ -2969,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "Speicher jetzt dein Secret, da es nach dem Verlassen dieser Seite nicht mehr sichtbar ist!"
},
"settings.authorizations.about-this-app": {
"message": "Über diese Anwendung"
},
"settings.authorizations.by": {
"message": "von"
},
"settings.authorizations.description": {
"message": "Wenn du eine Anwendung mit deinem Modrinth-Konto autorisierst, gewährst du dieser Zugriff auf dein Konto. Du kannst den Zugriff auf dein Konto hier jederzeit verwalten und überprüfen."
},
"settings.authorizations.empty-state": {
"message": "Wir können deine autorisierten Apps derzeit nicht anzeigen, wir arbeiten daran, das zu beheben. Bitte besuche diese Seite zu einem späteren Zeitpunkt erneut!"
},
"settings.authorizations.head-title": {
"message": "Autorisierungen"
},
"settings.authorizations.revoke.action": {
"message": "Widerrufen"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Dadurch wird den Zugriff der Anwendung auf dein Konto widerrufen. Du kannst sie später jederzeit erneut autorisieren."
},
"settings.authorizations.revoke.confirm.title": {
"message": "Möchtest du diese Anwendung wirklich widerrufen?"
},
"settings.billing.charges.description": {
"message": "Hier werden alle bisherigen Belastungen deines Modrinth-Kontos aufgeführt:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Medal Server-Testversion"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Läuft ab am {date}"
},
"settings.billing.interval.month": {
"message": "Monat"
},
"settings.billing.interval.monthly": {
"message": "monatlich"
},
"settings.billing.interval.year": {
"message": "Jahr"
},
"settings.billing.interval.yearly": {
"message": "jährlich"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Werbungsfreies Surfen auf modrinth.com und in Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Modrinth+ Abzeichen in deinem Profil"
},
"settings.billing.midas.benefits.support": {
"message": "Unterstütze Modrinth und Ersteller direkt"
},
"settings.billing.midas.benefits.title": {
"message": "Vorteile"
},
"settings.billing.midas.save-per-year": {
"message": "Spare {amount}/Jahr, indem du auf jährliche Abrechnung umsteigst!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Du hast dein Abonnement gekündigt."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "Du behältst deine Vorteile bis zum Ende des aktuellen Abrechnungszeitraums."
},
"settings.billing.midas.status.failed": {
"message": "Die Zahlung für dein Abonnement ist fehlgeschlagen. Bitte aktualisiere deine Zahlungsmethode."
},
"settings.billing.midas.status.open": {
"message": "Du hast derzeit folgende Abonnements:"
},
"settings.billing.midas.status.processing": {
"message": "Deine Zahlung wird bearbeitet. Vorteile werden aktiviert, sobald die Zahlung abgeschlossen ist."
},
"settings.billing.midas.upsell": {
"message": "Werde ein Abonnent von Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Abonnement kündigen"
},
@@ -2987,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "Möchtest du diese Zahlungsmethode wirklich entfernen?"
},
"settings.billing.next": {
"message": "Nächstes:"
},
"settings.billing.or-yearly-save": {
"message": "Oder {price} / Jahr (spare {percent}%)!"
},
"settings.billing.payment_method.action.add": {
"message": "Zahlungsmethode hinzufügen"
},
@@ -3008,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Zahlungsmethoden"
},
"settings.billing.plan.title": {
"message": "{size} Plan"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} Geteilte CPUs (Spitzenlasten von bis zu {bursts} CPUs)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "Für dieses Abonnement konnte kein verknüpfter Server gefunden werden. Dafür gibt es mehrere mögliche Gründe. Falls du deinen Server gerade erst gekauft hast, ist dies normal. Es kann bis zu einer Stunde dauern, bis dein Server bereitgestellt ist. Falls du diesen Server hingegen bereits vor einiger Zeit gekauft hast, wurde er wahrscheinlich seitdem gesperrt. Sollte dies nicht deinen Erwartungen entsprechen, wende dich bitte mit den folgenden Informationen an den Modrinth-Support:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "Server-ID: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "Stripe-ID: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} GB RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Beim erneuten Abonnieren deines Modrinth-Servers ist ein Fehler aufgetreten."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Fehler beim erneuten Abonnieren"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Falls der Server momentan pausiert ist, kann es bis zu 10 Minuten dauern, bis ein weiterer Zahlungsversuch unternommen wird."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Anfrage zum erneuten Abonnieren übermittelt"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "Server-Abonnement erfolgreich erneuert"
},
"settings.billing.pyro.status.failed": {
"message": "Die Zahlung für dein Abonnement ist fehlgeschlagen. Bitte aktualisiere deine Zahlungsmethode und abonniere erneut."
},
"settings.billing.pyro.status.processing": {
"message": "Deine Zahlung wird bearbeitet. Dein Server wird freigeschaltet, sobald die Zahlung abgeschlossen ist."
},
"settings.billing.pyro.storage": {
"message": "{gb} GB SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} GB Swap"
},
"settings.billing.pyro_subscription.description": {
"message": "Verwalte deine Modrinth Server-Abonnements."
},
"settings.billing.pyro_subscription.title": {
"message": "Modrinth Server-Abonnements"
},
"settings.billing.renews": {
"message": "Wird erneuert am {date}"
},
"settings.billing.resubscribe": {
"message": "Erneut abonnieren"
},
"settings.billing.since": {
"message": "Seit dem {date}"
},
"settings.billing.subscribe": {
"message": "Abonnieren"
},
"settings.billing.subscription.description": {
"message": "Verwalte deine Modrinth-Abonnements."
},
"settings.billing.subscription.title": {
"message": "Abonnements"
},
"settings.billing.switch.switching-to-interval": {
"message": "Wechsle auf {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Wechsle auf {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Monatliche Abrechnung kostet dich zusätzliche {amount} pro Jahr"
},
"settings.billing.switches-to-billing-on": {
"message": "Wechselt am {date} auf {interval} Abrechnung"
},
"settings.billing.update-method": {
"message": "Methode aktualisieren"
},
"settings.billing.upgrade": {
"message": "Verbessern"
},
"settings.display.banner.developer-mode.button": {
"message": "Entwicklermodus deaktivieren"
},
@@ -3032,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Funktionen umschalten"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "Entwicklermodus wurde deaktiviert"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Entwicklermodus deaktiviert"
},
"settings.display.project-list-layouts.datapack": {
"message": "Datenpakete-Seite"
},
@@ -3041,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Mods-Seite"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galerie"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Raster"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Zeilen"
},
"settings.display.project-list-layouts.modpack": {
"message": "Modpacks-Seite"
},
@@ -3101,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Farbschema"
},
"settings.head-title": {
"message": "Anzeigeeinstellungen"
},
"settings.pats.action.create": {
"message": "Erstelle ein PAT"
},
@@ -3161,6 +3536,9 @@
"settings.profile.description": {
"message": "Deine Profilinformationen sind auf Modrinth und über die <docs-link>Modrinth-API</docs-link> öffentlich einsehbar."
},
"settings.profile.head-title": {
"message": "Profileinstellungen"
},
"settings.profile.profile-info": {
"message": "Profilinformationen"
},
@@ -3191,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Unbekannte Plattform"
},
"settings.sidebar.label.account": {
"message": "Konto"
},
"settings.sidebar.label.developer": {
"message": "Entwickler"
},
"settings.sidebar.label.display": {
"message": "Anzeige"
},
"ui.latest-news-row.latest-news": {
"message": "Aktuelle Neuigkeiten von Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Alle Neuigkeiten ansehen"
},
"ui.newsletter-button.subscribe": {
"message": "Abonnieren"
},
"ui.newsletter-button.subscribed": {
"message": "Abonniert!"
},
"ui.newsletter-button.tooltip": {
"message": "Abonniere den Modrinth-Newsletter"
},
"version.environment.none.description": {
"message": "Die Umgebung für diese Version wurde nicht angegeben."
},
+410 -14
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Create project"
},
"create.project.create-server-project": {
"message": "Create server"
},
"create.project.missing-fields-tooltip": {
"message": "Missing fields: {fields}"
},
@@ -2858,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Ideal for 1525 players, modpacks, or heavy modding."
},
"servers.plan.large.name": {
"message": "Large"
},
"servers.plan.medium.description": {
"message": "Great for 615 players and multiple mods."
},
"servers.plan.medium.name": {
"message": "Medium"
},
"servers.plan.small.description": {
"message": "Perfect for 15 friends with a few light mods."
},
"servers.plan.small.name": {
"message": "Small"
"settings.account.button.complete-setup": {
"message": "Complete setup"
},
"settings.account.data-export.action.download": {
"message": "Download export"
},
"settings.account.data-export.action.generate": {
"message": "Generate export"
},
"settings.account.data-export.action.generating": {
"message": "Generating export..."
},
"settings.account.data-export.description": {
"message": "Request a copy of all your personal data you have uploaded to Modrinth. This may take several minutes to complete."
},
"settings.account.data-export.title": {
"message": "Data export"
},
"settings.account.delete.confirm.description": {
"message": "This will **immediately delete all of your user data and follows**. This will not delete your projects. Deleting your account cannot be reversed.<br><br>If you need help with your account, get support on the [Modrinth Discord](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Delete this account"
},
"settings.account.delete.confirm.title": {
"message": "Are you sure you want to delete your account?"
},
"settings.account.delete.section.action": {
"message": "Delete account"
},
"settings.account.delete.section.description": {
"message": "Once you delete your account, there is no going back. Deleting your account will remove all attached data, excluding projects, from our servers."
},
"settings.account.delete.section.title": {
"message": "Delete account"
},
"settings.account.email.action.save": {
"message": "Save email"
},
"settings.account.email.field.label": {
"message": "Email address"
},
"settings.account.email.field.placeholder": {
"message": "Enter your email address..."
},
"settings.account.email.modal.header.add": {
"message": "Add email"
},
"settings.account.email.modal.header.change": {
"message": "Change email"
},
"settings.account.email.modal.notice": {
"message": "Your account information is not displayed publicly."
},
"settings.account.password.action.remove": {
"message": "Remove password"
},
"settings.account.password.action.save": {
"message": "Save password"
},
"settings.account.password.error.mismatch": {
"message": "Input passwords do not match!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Please enter your password to proceed."
},
"settings.account.password.field.confirm-current.label": {
"message": "Confirm password"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Confirm password"
},
"settings.account.password.field.confirm-new.label": {
"message": "Confirm new password"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Confirm new password"
},
"settings.account.password.field.new.label": {
"message": "New password"
},
"settings.account.password.field.new.placeholder": {
"message": "New password"
},
"settings.account.password.field.old.label": {
"message": "Old password"
},
"settings.account.password.field.old.placeholder": {
"message": "Old password"
},
"settings.account.password.modal.header.add": {
"message": "Add password"
},
"settings.account.password.modal.header.change": {
"message": "Change password"
},
"settings.account.password.modal.header.remove": {
"message": "Remove password"
},
"settings.account.providers.action.add": {
"message": "Add"
},
"settings.account.providers.modal.header": {
"message": "Authentication providers"
},
"settings.account.providers.table.actions": {
"message": "Actions"
},
"settings.account.providers.table.provider": {
"message": "Provider"
},
"settings.account.security.email.action.add": {
"message": "Add email"
},
"settings.account.security.email.action.change": {
"message": "Change email"
},
"settings.account.security.email.description": {
"message": "Changes the email associated with your account."
},
"settings.account.security.email.title": {
"message": "Email"
},
"settings.account.security.password.action.add": {
"message": "Add password"
},
"settings.account.security.password.action.change": {
"message": "Change password"
},
"settings.account.security.password.description.change": {
"message": "Change the password used to login to your account."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Change or remove the password used to login to your account."
},
"settings.account.security.password.description.set": {
"message": "Set a permanent password to login to your account."
},
"settings.account.security.password.title": {
"message": "Password"
},
"settings.account.security.providers.action.manage": {
"message": "Manage providers"
},
"settings.account.security.providers.description": {
"message": "Add or remove sign-on methods from your account, including GitHub, GitLab, Microsoft, Discord, Steam, and Google."
},
"settings.account.security.providers.title": {
"message": "Manage authentication providers"
},
"settings.account.security.title": {
"message": "Account security"
},
"settings.account.security.two-factor.action.remove": {
"message": "Remove 2FA"
},
"settings.account.security.two-factor.action.setup": {
"message": "Setup 2FA"
},
"settings.account.security.two-factor.description": {
"message": "Add an additional layer of security to your account during login."
},
"settings.account.security.two-factor.title": {
"message": "Two-factor authentication"
},
"settings.account.two-factor.backup.intro": {
"message": "Download and save these back-up codes in a safe place. You can use these in-place of a 2FA code if you ever lose access to your device! You should protect these codes like your password."
},
"settings.account.two-factor.backup.single-use": {
"message": "Backup codes can only be used once."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "The code entered is incorrect!"
},
"settings.account.two-factor.field.code.description": {
"message": "Please enter a two-factor code to proceed."
},
"settings.account.two-factor.field.code.label": {
"message": "Enter two-factor code"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Enter code..."
},
"settings.account.two-factor.setup.intro": {
"message": "Two-factor authentication keeps your account secure by requiring access to a second device in order to sign in."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "If the QR code does not scan, you can manually enter the secret:"
},
"settings.account.two-factor.setup.scan": {
"message": "Scan the QR code with <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link>, or any other 2FA app to begin."
},
"settings.account.two-factor.verify.description": {
"message": "Enter the one-time code from authenticator to verify access."
},
"settings.account.two-factor.verify.label": {
"message": "Verify code"
},
"settings.applications.about": {
"message": "About"
@@ -2954,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Applications"
},
"settings.applications.modal.header": {
"message": "Application information"
},
"settings.applications.notification.error.title": {
"message": "An error occurred"
},
"settings.applications.notification.icon-updated.description": {
"message": "Your application icon has been updated."
},
@@ -2969,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "Save your secret now, it will be hidden after you leave this page!"
},
"settings.authorizations.about-this-app": {
"message": "About this app"
},
"settings.authorizations.by": {
"message": "by"
},
"settings.authorizations.description": {
"message": "When you authorize an application with your Modrinth account, you grant it access to your account. You can manage and review access to your account here at any time."
},
"settings.authorizations.empty-state": {
"message": "We currently can't display your authorized apps, we're working to fix this. Please visit this page at a later date!"
},
"settings.authorizations.head-title": {
"message": "Authorizations"
},
"settings.authorizations.revoke.action": {
"message": "Revoke"
},
"settings.authorizations.revoke.confirm.description": {
"message": "This will revoke the application's access to your account. You can always re-authorize it later."
},
"settings.authorizations.revoke.confirm.title": {
"message": "Are you sure you want to revoke this application?"
},
"settings.billing.charges.description": {
"message": "All of your past charges to your Modrinth account will be listed here:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Medal Server Trial"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Expires {date}"
},
"settings.billing.interval.month": {
"message": "month"
},
"settings.billing.interval.monthly": {
"message": "monthly"
},
"settings.billing.interval.year": {
"message": "year"
},
"settings.billing.interval.yearly": {
"message": "yearly"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Ad-free browsing on modrinth.com and Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Modrinth+ badge on your profile"
},
"settings.billing.midas.benefits.support": {
"message": "Support Modrinth and creators directly"
},
"settings.billing.midas.benefits.title": {
"message": "Benefits"
},
"settings.billing.midas.save-per-year": {
"message": "Save {amount}/year by switching to yearly billing!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "You've cancelled your subscription."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "You will retain your perks until the end of the current billing cycle."
},
"settings.billing.midas.status.failed": {
"message": "Your subscription payment failed. Please update your payment method."
},
"settings.billing.midas.status.open": {
"message": "You're currently subscribed to:"
},
"settings.billing.midas.status.processing": {
"message": "Your payment is being processed. Perks will activate once payment is complete."
},
"settings.billing.midas.upsell": {
"message": "Become a subscriber to Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Cancel subscription"
},
@@ -2987,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "Are you sure you want to remove this payment method?"
},
"settings.billing.next": {
"message": "Next:"
},
"settings.billing.or-yearly-save": {
"message": "Or {price} / year (save {percent}%)!"
},
"settings.billing.payment_method.action.add": {
"message": "Add payment method"
},
@@ -3008,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Payment methods"
},
"settings.billing.plan.title": {
"message": "{size} Plan"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} Shared CPUs (Bursts up to {bursts} CPUs)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "A linked server couldn't be found for this subscription. There are a few possible explanations for this. If you just purchased your server, this is normal. It could take up to an hour for your server to be provisioned. Otherwise, if you purchased this server a while ago, it has likely since been suspended. If this is not what you were expecting, please contact Modrinth Support with the following information:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "Server ID: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "Stripe ID: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} GB RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "An error occurred while resubscribing to your Modrinth server."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Error resubscribing"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "If the server is currently suspended, it may take up to 10 minutes for another charge attempt to be made."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Resubscription request submitted"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "Server subscription resubscribed successfully"
},
"settings.billing.pyro.status.failed": {
"message": "Your subscription payment failed. Please update your payment method, then resubscribe."
},
"settings.billing.pyro.status.processing": {
"message": "Your payment is being processed. Your server will activate once payment is complete."
},
"settings.billing.pyro.storage": {
"message": "{gb} GB SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} GB Swap"
},
"settings.billing.pyro_subscription.description": {
"message": "Manage your Modrinth Server subscriptions."
},
"settings.billing.pyro_subscription.title": {
"message": "Modrinth Server Subscriptions"
},
"settings.billing.renews": {
"message": "Renews {date}"
},
"settings.billing.resubscribe": {
"message": "Resubscribe"
},
"settings.billing.since": {
"message": "Since {date}"
},
"settings.billing.subscribe": {
"message": "Subscribe"
},
"settings.billing.subscription.description": {
"message": "Manage your Modrinth subscriptions."
},
"settings.billing.subscription.title": {
"message": "Subscriptions"
},
"settings.billing.switch.switching-to-interval": {
"message": "Switching to {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Switch to {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Monthly billing will cost you an additional {amount} per year"
},
"settings.billing.switches-to-billing-on": {
"message": "Switches to {interval} billing on {date}"
},
"settings.billing.update-method": {
"message": "Update method"
},
"settings.billing.upgrade": {
"message": "Upgrade"
},
"settings.display.banner.developer-mode.button": {
"message": "Deactivate developer mode"
},
@@ -3032,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Toggle features"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "Developer mode has been disabled"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Developer mode deactivated"
},
"settings.display.project-list-layouts.datapack": {
"message": "Data Packs page"
},
@@ -3041,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Mods page"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Gallery"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Grid"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Rows"
},
"settings.display.project-list-layouts.modpack": {
"message": "Modpacks page"
},
@@ -3101,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Color theme"
},
"settings.head-title": {
"message": "Display settings"
},
"settings.pats.action.create": {
"message": "Create a PAT"
},
@@ -3161,6 +3536,9 @@
"settings.profile.description": {
"message": "Your profile information is publicly viewable on Modrinth and through the <docs-link>Modrinth API</docs-link>."
},
"settings.profile.head-title": {
"message": "Profile settings"
},
"settings.profile.profile-info": {
"message": "Profile information"
},
@@ -3191,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Unknown platform"
},
"settings.sidebar.label.account": {
"message": "Account"
},
"settings.sidebar.label.developer": {
"message": "Developer"
},
"settings.sidebar.label.display": {
"message": "Display"
},
"ui.latest-news-row.latest-news": {
"message": "Latest news from Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "View all news"
},
"ui.newsletter-button.subscribe": {
"message": "Subscribe"
},
"ui.newsletter-button.subscribed": {
"message": "Subscribed!"
},
"ui.newsletter-button.tooltip": {
"message": "Subscribe to the Modrinth newsletter"
},
"version.environment.none.description": {
"message": "The environment for this version has not been specified."
},
+497 -14
View File
@@ -38,6 +38,9 @@
"app-marketing.download.options-title": {
"message": "Opciones de descarga"
},
"app-marketing.download.terms": {
"message": "Al descargar Modrinth App, tú aceptas nuestros <terms-link>Términos</terms-link> y <privacy-link>Política de privacidad</privacy-link>."
},
"app-marketing.download.title": {
"message": "Descargar la Modrinth App (Beta)"
},
@@ -104,6 +107,9 @@
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.description": {
"message": "La aplicación Modrinth funciona mejor que muchos de los principales gestores de mods, ¡usando solo 150 MB de RAM!"
},
"app-marketing.features.performance.discord": {
"message": "Discord"
},
@@ -386,6 +392,9 @@
"collection.label.no-projects": {
"message": "Aún no hay proyectos en la colección"
},
"collection.label.projects-count": {
"message": "{count, plural, =0 {Aún no hay proyectos} other {<stat>{count}</stat> {type}}}"
},
"collection.label.updated-at": {
"message": "Actualizado {ago}"
},
@@ -488,9 +497,6 @@
"create.project.create-project": {
"message": "Crear proyecto"
},
"create.project.create-server-project": {
"message": "Crear servidor"
},
"create.project.missing-fields-tooltip": {
"message": "Campos faltantes: {fields}"
},
@@ -569,6 +575,21 @@
"dashboard.collections.button.create-new": {
"message": "Crear nuevo"
},
"dashboard.collections.empty.get-started-hint": {
"message": "¡Crea tu primera colección para comenzar!"
},
"dashboard.collections.empty.no-collections": {
"message": "Aún no tienes ninguna colección"
},
"dashboard.collections.empty.no-match": {
"message": "Ninguna colección coincide con tu búsqueda"
},
"dashboard.collections.empty.no-match-hint": {
"message": "Intente ajustar sus filtros o términos de búsqueda."
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, one {proyecto} other {proyectos}}"
},
"dashboard.collections.label.search-input": {
"message": "Busca en tus colecciones"
},
@@ -644,6 +665,9 @@
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Una entidad comercial se refiere a una organización registrada, como una sociedad anónima, una sociedad colectiva o una sociedad de responsabilidad limitada."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "¿Vas a realizar la retirada como particular o como empresa?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Particular"
},
@@ -1115,6 +1139,9 @@
"hosting-marketing.faq.ddos-protection": {
"message": "¿Los servidores de Modrinth Hosting tendrán protección contra DDoS?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Sí. Todos los servidores de Modrinth Hosting vienen con protección DDoS, con hasta 17 Tbps de capacidad en algunas ubicaciones."
},
"hosting-marketing.faq.heading": {
"message": "Preguntas Frecuentes (FAQ)"
},
@@ -1220,6 +1247,9 @@
"hosting-marketing.know-what-you-need": {
"message": "¿Sabes exactamente lo que necesitas?"
},
"hosting-marketing.medal.info": {
"message": "Pruebe un <orange>servidor de 3 GB</orange> gratuito durante 5 días con <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Aprender más"
},
@@ -1271,6 +1301,39 @@
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Elige entre Vanilla, Fabric, Forge, Quilt y NeoForge. Si está en Modrinth, puede ejecutarse en tu servidor."
},
"hosting.loader.failed-to-change-version": {
"message": "No se pudo cambiar la versión del modpack"
},
"hosting.loader.failed-to-load-versions": {
"message": "No se pudieron cargar las versiones"
},
"hosting.loader.failed-to-reinstall": {
"message": "No se pudo reinstalar el modpack"
},
"hosting.loader.failed-to-repair": {
"message": "No se pudo reparar el servidor"
},
"hosting.loader.failed-to-save-settings": {
"message": "No se pudo guardar la configuración de instalación"
},
"hosting.loader.failed-to-unlink": {
"message": "No se pudo desvincular el modpack"
},
"hosting.loader.loader-version": {
"message": "{loader, select, null {Cargador} other {{loader}}} versión"
},
"hosting.loader.repair-started-text": {
"message": "La instalación de su servidor ha sido reparada."
},
"hosting.loader.repair-started-title": {
"message": "Reparación completada"
},
"hosting.loader.reset-server": {
"message": "Reiniciar servidor"
},
"hosting.loader.reset-server-description": {
"message": "Elimina todos los datos de su servidor, incluidos sus mundos, mods y archivos de configuración. Las copias de seguridad permanecerán y podrán restaurarse."
},
"hosting.plan.out-of-stock": {
"message": "Agotado"
},
@@ -1403,6 +1466,9 @@
"landing.section.for-players.label": {
"message": "Para jugadores"
},
"landing.section.for-players.tagline": {
"message": "Descubra más de {count, number} creaciones"
},
"landing.subheading": {
"message": "Descubre, juega y comparte contenido de Minecraft a través de nuestra plataforma de código abierto creada para la comunidad."
},
@@ -2003,6 +2069,9 @@
"profile.label.collection": {
"message": "Colección"
},
"profile.label.downloads": {
"message": "{count} {countPlural, plural, one {descarga} other {descargas}}"
},
"profile.label.joined": {
"message": "Se unió"
},
@@ -2021,6 +2090,9 @@
"profile.label.organizations": {
"message": "Organizaciones"
},
"profile.label.projects": {
"message": "{count} {countPlural, plural, one {proyecto} other {proyectos}}"
},
"profile.label.saving": {
"message": "Guardando..."
},
@@ -2741,6 +2813,18 @@
"search.filter.locked.server.sync": {
"message": "Sincronizar con el servidor"
},
"servers.busy.backup-creating": {
"message": "Creación de copia de seguridad en curso"
},
"servers.busy.backup-restoring": {
"message": "Restauración de copia de seguridad en curso"
},
"servers.busy.installing": {
"message": "El servidor se está instalando"
},
"servers.busy.syncing-content": {
"message": "Sincronización de contenido en progreso"
},
"servers.notice.actions": {
"message": "Acciones"
},
@@ -2771,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Ideal para 1525 jugadores, modpacks o uso intensivo de mods."
},
"servers.plan.large.name": {
"message": "Grande"
},
"servers.plan.medium.description": {
"message": "Ideal para 615 jugadores y múltiples mods."
},
"servers.plan.medium.name": {
"message": "Mediano"
},
"servers.plan.small.description": {
"message": "Perfecto para 15 amigos con algunos mods ligeros."
},
"servers.plan.small.name": {
"message": "Pequeño"
"settings.account.button.complete-setup": {
"message": "Configuración completa"
},
"settings.account.data-export.action.download": {
"message": "Descargar exportación"
},
"settings.account.data-export.action.generate": {
"message": "Generar exportación"
},
"settings.account.data-export.action.generating": {
"message": "Generando exportación..."
},
"settings.account.data-export.description": {
"message": "Solicita una copia de todos los datos personales que hayas subido a Modrinth. El proceso puede tardar varios minutos en completarse."
},
"settings.account.data-export.title": {
"message": "Exportación de datos"
},
"settings.account.delete.confirm.description": {
"message": "Esto **eliminará inmediatamente todos tus datos de usuario y tus seguidores**. No se eliminarán tus proyectos. La eliminación de tu cuenta es irreversible.<br><br>Si necesitas ayuda con tu cuenta, solicita asistencia en el [Discord de Modrinth](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Eliminar esta cuenta"
},
"settings.account.delete.confirm.title": {
"message": "¿Estás seguro de que quieres eliminar tu cuenta?"
},
"settings.account.delete.section.action": {
"message": "Eliminar cuenta"
},
"settings.account.delete.section.description": {
"message": "Una vez que elimines tu cuenta, no habrá vuelta atrás. Al eliminar tu cuenta, se borrarán de nuestros servidores todos los datos asociados, excepto los proyectos."
},
"settings.account.delete.section.title": {
"message": "Eliminar cuenta"
},
"settings.account.email.action.save": {
"message": "Guardar correo electrónico"
},
"settings.account.email.field.label": {
"message": "Correo electrónico"
},
"settings.account.email.field.placeholder": {
"message": "Introduce tu correo electrónico..."
},
"settings.account.email.modal.header.add": {
"message": "Añadir correo electrónico"
},
"settings.account.email.modal.header.change": {
"message": "Cambiar correo electrónico"
},
"settings.account.email.modal.notice": {
"message": "La información de tu cuenta no se muestra públicamente."
},
"settings.account.password.action.remove": {
"message": "Eliminar contraseña"
},
"settings.account.password.action.save": {
"message": "Guardar contraseña"
},
"settings.account.password.error.mismatch": {
"message": "¡Las contraseñas no coinciden!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Introduzca su contraseña para continuar."
},
"settings.account.password.field.confirm-current.label": {
"message": "Confirmar contraseña"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Confirmar contraseña"
},
"settings.account.password.field.confirm-new.label": {
"message": "Confirmar nueva contraseña"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Confirmar nueva contraseña"
},
"settings.account.password.field.new.label": {
"message": "Nueva contraseña"
},
"settings.account.password.field.new.placeholder": {
"message": "Nueva contraseña"
},
"settings.account.password.field.old.label": {
"message": "Antigua contraseña"
},
"settings.account.password.field.old.placeholder": {
"message": "Antigua contraseña"
},
"settings.account.password.modal.header.add": {
"message": "Añadir contraseña"
},
"settings.account.password.modal.header.change": {
"message": "Cambiar contraseña"
},
"settings.account.password.modal.header.remove": {
"message": "Eliminar contraseña"
},
"settings.account.providers.action.add": {
"message": "Añadir"
},
"settings.account.providers.modal.header": {
"message": "Proveedores de autenticación"
},
"settings.account.providers.table.actions": {
"message": "Acciones"
},
"settings.account.providers.table.provider": {
"message": "Proveedor"
},
"settings.account.security.email.action.add": {
"message": "Añadir correo electrónico"
},
"settings.account.security.email.action.change": {
"message": "Cambiar correo electrónico"
},
"settings.account.security.email.description": {
"message": "Cambia la dirección de correo electrónico asociada a tu cuenta."
},
"settings.account.security.email.title": {
"message": "Correo electrónico"
},
"settings.account.security.password.action.add": {
"message": "Añadir contraseña"
},
"settings.account.security.password.action.change": {
"message": "Cambiar contraseña"
},
"settings.account.security.password.description.change": {
"message": "Cambia la contraseña que utilizas para iniciar sesión en tu cuenta."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Cambia o elimina la contraseña que utilizas para iniciar sesión en tu cuenta."
},
"settings.account.security.password.description.set": {
"message": "Establece una contraseña permanente para iniciar sesión en tu cuenta."
},
"settings.account.security.password.title": {
"message": "Contraseña"
},
"settings.account.security.providers.action.manage": {
"message": "Gestionar proveedores"
},
"settings.account.security.providers.description": {
"message": "Añade o elimina métodos de inicio de sesión de tu cuenta, como GitHub, GitLab, Microsoft, Discord, Steam y Google."
},
"settings.account.security.providers.title": {
"message": "Gestionar proveedores de autenticación"
},
"settings.account.security.title": {
"message": "Seguridad de la cuenta"
},
"settings.account.security.two-factor.action.remove": {
"message": "Desactivar la autenticación de dos factores"
},
"settings.account.security.two-factor.action.setup": {
"message": "Configurar la autenticación de dos factores"
},
"settings.account.security.two-factor.description": {
"message": "Añade una capa adicional de seguridad a tu cuenta al iniciar sesión."
},
"settings.account.security.two-factor.title": {
"message": "Autenticación de dos factores"
},
"settings.account.two-factor.backup.intro": {
"message": "Descarga y guarda estos códigos de seguridad en un lugar seguro. ¡Puedes utilizarlos en lugar de un código de autenticación de dos factores si alguna vez pierdes el acceso a tu dispositivo! Debes proteger estos códigos igual que tu contraseña."
},
"settings.account.two-factor.backup.single-use": {
"message": "Los códigos de seguridad solo se pueden usar una vez."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "¡El código introducido es incorrecto!"
},
"settings.account.two-factor.field.code.description": {
"message": "Introduce el código de autenticación de dos factores para continuar."
},
"settings.account.two-factor.field.code.label": {
"message": "Introduce el código de dos factores"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Introduce el código..."
},
"settings.account.two-factor.setup.intro": {
"message": "La autenticación de dos factores protege tu cuenta, ya que exige el acceso a un segundo dispositivo para iniciar sesión."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Si no se puede escanear el código QR, puedes introducir el secreto manualmente:"
},
"settings.account.two-factor.setup.scan": {
"message": "Escanea el código QR con <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> o cualquier otra aplicación de autenticación de dos factores para empezar."
},
"settings.account.two-factor.verify.description": {
"message": "Introduce el código de un solo uso de la aplicación de autenticación para verificar el acceso."
},
"settings.account.two-factor.verify.label": {
"message": "Verificar código"
},
"settings.applications.about": {
"message": "Acerca de"
@@ -2867,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Aplicaciones"
},
"settings.applications.modal.header": {
"message": "Información de la aplicación"
},
"settings.applications.notification.error.title": {
"message": "Ha ocurrido un error"
},
"settings.applications.notification.icon-updated.description": {
"message": "El ícono de tu aplicación se ha actualizado."
},
@@ -2882,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "¡Guarda tu secreto ahora, se ocultará después de salir de esta página!"
},
"settings.authorizations.about-this-app": {
"message": "Acerca de esta aplicación"
},
"settings.authorizations.by": {
"message": "por"
},
"settings.authorizations.description": {
"message": "Cuando autorizas una aplicación con tu cuenta de Modrinth, le concedes acceso a tu cuenta. Puedes gestionar y revisar el acceso a tu cuenta aquí en cualquier momento."
},
"settings.authorizations.empty-state": {
"message": "Por el momento no podemos mostrar tus aplicaciones autorizadas, pero estamos trabajando para solucionar el problema. ¡Vuelve a visitar esta página más adelante!"
},
"settings.authorizations.head-title": {
"message": "Autorizaciones"
},
"settings.authorizations.revoke.action": {
"message": "Revocar"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Esto revocará el acceso de la aplicación a tu cuenta. Siempre podrás volver a autorizarla más adelante."
},
"settings.authorizations.revoke.confirm.title": {
"message": "¿Estás seguro de que quieres revocar esta solicitud?"
},
"settings.billing.charges.description": {
"message": "Aquí aparecerán todos los cargos anteriores de tu cuenta de Modrinth:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Versión de prueba de Medal Server"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Caduca el {date}"
},
"settings.billing.interval.month": {
"message": "mes"
},
"settings.billing.interval.monthly": {
"message": "mensual"
},
"settings.billing.interval.year": {
"message": "año"
},
"settings.billing.interval.yearly": {
"message": "anual"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Navegación sin anuncios en modrinth.com y Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Insignia de Modrinth+ en tu perfil"
},
"settings.billing.midas.benefits.support": {
"message": "Apoya directamente a Modrinth y a los creadores"
},
"settings.billing.midas.benefits.title": {
"message": "Beneficios"
},
"settings.billing.midas.save-per-year": {
"message": "¡Ahorra {amount} al año cambiando a la facturación anual!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Has cancelado tu suscripción."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "Conservarás tus ventajas hasta el final del ciclo de facturación actual."
},
"settings.billing.midas.status.failed": {
"message": "El pago de tu suscripción no se ha realizado correctamente. Actualiza tu método de pago."
},
"settings.billing.midas.status.open": {
"message": "Actualmente estás suscrito a:"
},
"settings.billing.midas.status.processing": {
"message": "Se está procesando tu pago. Las ventajas se activarán una vez que se haya completado el pago."
},
"settings.billing.midas.upsell": {
"message": "¡Suscríbete a Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Cancelar subscripción"
},
@@ -2900,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "¿Estás seguro de que quieres eliminar este método de pago?"
},
"settings.billing.next": {
"message": "Siguiente:"
},
"settings.billing.or-yearly-save": {
"message": "O {price} al año (¡ahorra un {percent}%!)"
},
"settings.billing.payment_method.action.add": {
"message": "Agregar método de pago"
},
@@ -2921,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Métodos de pago"
},
"settings.billing.plan.title": {
"message": "{size} Plan"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} CPU compartidas (Picos de hasta {bursts} CPUs)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "No se ha encontrado ningún servidor vinculado para esta suscripción. Hay varias explicaciones posibles para ello. Si acaba de adquirir su servidor, esto es normal. La configuración del servidor puede tardar hasta una hora. Por el contrario, si adquirió este servidor hace tiempo, es probable que haya sido suspendido desde entonces. Si esto no es lo que esperaba, póngase en contacto con el servicio de asistencia de Modrinth con la siguiente información:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "ID del servidor: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "ID de Stripe: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} GB de RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Se ha producido un error al volver a suscribirse a su servidor Modrinth."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Error al volver a suscribirse"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Si el servidor está actualmente suspendido, pueden pasar hasta 10 minutos antes de que se realice otro intento de cobro."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Solicitud de renovación enviada"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "La suscripción al servidor se ha renovado correctamente"
},
"settings.billing.pyro.status.failed": {
"message": "El pago de tu suscripción no se ha realizado correctamente. Actualiza tu método de pago y vuelve a suscribirte."
},
"settings.billing.pyro.status.processing": {
"message": "Se está procesando tu pago. Tu servidor se activará una vez que se haya completado el pago."
},
"settings.billing.pyro.storage": {
"message": "{gb} GB de SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} GB de intercambio"
},
"settings.billing.pyro_subscription.description": {
"message": "Gestiona tus suscripciones de Modrinth Servers."
},
"settings.billing.pyro_subscription.title": {
"message": "Suscripciones de Modrinth Servers"
},
"settings.billing.renews": {
"message": "Se renueva el {date}"
},
"settings.billing.resubscribe": {
"message": "Volver a suscribirse"
},
"settings.billing.since": {
"message": "Desde el {date}"
},
"settings.billing.subscribe": {
"message": "Suscríbete"
},
"settings.billing.subscription.description": {
"message": "Gestiona tus suscripciones de servidores Modrinth."
},
"settings.billing.subscription.title": {
"message": "Suscripciones"
},
"settings.billing.switch.switching-to-interval": {
"message": "Cambiando a {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Cambiar a {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "La facturación mensual te supondrá un coste adicional de {amount} al año"
},
"settings.billing.switches-to-billing-on": {
"message": "Pasará a la facturación por {interval} a partir del {date}"
},
"settings.billing.update-method": {
"message": "Actualizar método"
},
"settings.billing.upgrade": {
"message": "Mejorar"
},
"settings.display.banner.developer-mode.button": {
"message": "Desactivar modo desarrollador"
},
@@ -2945,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Activar/desactivar funciones"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "El modo de desarrollador se ha desactivado"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Modo de desarrollador desactivado"
},
"settings.display.project-list-layouts.datapack": {
"message": "Página de Data Packs"
},
@@ -2954,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Página de Mods"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galería"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Cuadrícula"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Filas"
},
"settings.display.project-list-layouts.modpack": {
"message": "Página de Modpacks"
},
@@ -3014,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Color de la interfaz"
},
"settings.head-title": {
"message": "Configuración de pantalla"
},
"settings.pats.action.create": {
"message": "Crear un PAT"
},
@@ -3074,6 +3536,9 @@
"settings.profile.description": {
"message": "La información de tu perfil es visible públicamente en Modrinth y mediante la <docs-link>API de Modrinth</docs-link>."
},
"settings.profile.head-title": {
"message": "Configuración del perfil"
},
"settings.profile.profile-info": {
"message": "Información del perfil"
},
@@ -3104,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Plataforma desconocida"
},
"settings.sidebar.label.account": {
"message": "Cuenta"
},
"settings.sidebar.label.developer": {
"message": "Desarrollador"
},
"settings.sidebar.label.display": {
"message": "Pantalla"
},
"ui.latest-news-row.latest-news": {
"message": "Últimas noticias de Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Ver todas las noticias"
},
"ui.newsletter-button.subscribe": {
"message": "Suscribir"
},
"ui.newsletter-button.subscribed": {
"message": "¡Suscrito!"
},
"ui.newsletter-button.tooltip": {
"message": "Suscríbete al boletín de noticias de Modrinth"
},
"version.environment.none.description": {
"message": "No se ha especificado el entorno para esta versión."
},
+524 -14
View File
@@ -38,6 +38,9 @@
"app-marketing.download.options-title": {
"message": "Opciones de descarga"
},
"app-marketing.download.terms": {
"message": "Al descargar Modrinth App, tú aceptas nuestros <terms-link>Términos</terms-link> y <privacy-link>Política de privacidad</privacy-link>."
},
"app-marketing.download.title": {
"message": "Descargar la aplicación Modrinth (Beta)"
},
@@ -104,6 +107,9 @@
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.description": {
"message": "La aplicación Modrinth funciona mejor que muchos de los principales gestores de mods, ¡usando solo 150 MB de RAM!"
},
"app-marketing.features.performance.discord": {
"message": "Discord"
},
@@ -386,6 +392,9 @@
"collection.label.no-projects": {
"message": "No hay proyectos en colección todavía"
},
"collection.label.projects-count": {
"message": "{count, plural, =0 {Aún no hay proyectos} other {<stat>{count}</stat> {type}}}"
},
"collection.label.updated-at": {
"message": "Actualizado hace {ago}"
},
@@ -488,8 +497,8 @@
"create.project.create-project": {
"message": "Crear proyecto"
},
"create.project.create-server-project": {
"message": "Crear servidor"
"create.project.missing-fields-tooltip": {
"message": "Campos faltantes: {fields}"
},
"create.project.name-label": {
"message": "Nombre"
@@ -497,6 +506,15 @@
"create.project.name-placeholder": {
"message": "Introduzca el nombre del proyecto..."
},
"create.project.owner-description": {
"message": "Establezca el propietario del proyecto como usted mismo o una organización de la que sea miembro."
},
"create.project.owner-label": {
"message": "Dueño"
},
"create.project.server-project-title": {
"message": "Creando un proyecto de servidor"
},
"create.project.summary-description": {
"message": "Una o dos frases que describan tu proyecto."
},
@@ -509,6 +527,15 @@
"create.project.title": {
"message": "Creando un proyecto"
},
"create.project.type-label": {
"message": "Tipo"
},
"create.project.type-project": {
"message": "Proyecto"
},
"create.project.type-server": {
"message": "Servidor"
},
"create.project.url-label": {
"message": "URL"
},
@@ -548,6 +575,21 @@
"dashboard.collections.button.create-new": {
"message": "Crear nuevo"
},
"dashboard.collections.empty.get-started-hint": {
"message": "¡Crea tu primera colección para comenzar!"
},
"dashboard.collections.empty.no-collections": {
"message": "Aún no tienes ninguna colección"
},
"dashboard.collections.empty.no-match": {
"message": "Ninguna colección coincide con tu búsqueda"
},
"dashboard.collections.empty.no-match-hint": {
"message": "Intente ajustar sus filtros o términos de búsqueda."
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, one {proyecto} other {proyectos}}"
},
"dashboard.collections.label.search-input": {
"message": "Buscar en tus colecciones"
},
@@ -623,6 +665,9 @@
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Una entidad comercial se refiere a una organización registrada, como una corporación, sociedad o LLC."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "¿Vas a realizar la retirada como particular o como empresa?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Persona física"
},
@@ -1094,6 +1139,9 @@
"hosting-marketing.faq.ddos-protection": {
"message": "¿Los servidores de Modrinth Hosting tienen protección DDoS?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Sí. Todos los servidores de Modrinth Hosting vienen con protección DDoS, con hasta 17 Tbps de capacidad en algunas ubicaciones."
},
"hosting-marketing.faq.heading": {
"message": "F.A.Q"
},
@@ -1199,6 +1247,9 @@
"hosting-marketing.know-what-you-need": {
"message": "¿Sabes exactamente lo que necesitas?"
},
"hosting-marketing.medal.info": {
"message": "Pruebe un <orange>servidor de 3 GB</orange> gratuito durante 5 días con <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Aprender más"
},
@@ -1250,6 +1301,39 @@
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Elige entre Vanilla, Fabric, Forge, Quilt y NeoForge. Si está en Modrinth, pueden ejecutarse en tu servidor."
},
"hosting.loader.failed-to-change-version": {
"message": "No se pudo cambiar la versión del modpack"
},
"hosting.loader.failed-to-load-versions": {
"message": "No se pudieron cargar las versiones"
},
"hosting.loader.failed-to-reinstall": {
"message": "No se pudo reinstalar el modpack"
},
"hosting.loader.failed-to-repair": {
"message": "No se pudo reparar el servidor"
},
"hosting.loader.failed-to-save-settings": {
"message": "No se pudo guardar la configuración de instalación"
},
"hosting.loader.failed-to-unlink": {
"message": "No se pudo desvincular el modpack"
},
"hosting.loader.loader-version": {
"message": "{loader, select, null {Cargador} other {{loader}}} versión"
},
"hosting.loader.repair-started-text": {
"message": "La instalación de su servidor ha sido reparada."
},
"hosting.loader.repair-started-title": {
"message": "Reparación completada"
},
"hosting.loader.reset-server": {
"message": "Reiniciar servidor"
},
"hosting.loader.reset-server-description": {
"message": "Elimina todos los datos de su servidor, incluidos sus mundos, mods y archivos de configuración. Las copias de seguridad permanecerán y podrán restaurarse."
},
"hosting.plan.out-of-stock": {
"message": "Agotado"
},
@@ -1382,6 +1466,9 @@
"landing.section.for-players.label": {
"message": "Para Jugadores"
},
"landing.section.for-players.tagline": {
"message": "Descubra más de {count, number} creaciones"
},
"landing.subheading": {
"message": "Descubre, juega y comparte contenido de Minecraft a través de nuestra plataforma de código abierto creada para la comunidad."
},
@@ -1778,6 +1865,9 @@
"muralpay.field.pix-phone": {
"message": "Número de telefono PIX"
},
"muralpay.field.random-key": {
"message": "Clave aleatoria"
},
"muralpay.field.routing-number": {
"message": "Número de ruta"
},
@@ -1850,6 +1940,9 @@
"muralpay.placeholder.enter-pix-email": {
"message": "Ingrese el email PIX"
},
"muralpay.placeholder.enter-random-key": {
"message": "Introducir clave aleatoria"
},
"muralpay.placeholder.enter-routing-number": {
"message": "Ingrese el número de ruta de 9 dígitos"
},
@@ -1976,6 +2069,9 @@
"profile.label.collection": {
"message": "Colección"
},
"profile.label.downloads": {
"message": "{count} {countPlural, plural, one {descarga} other {descargas}}"
},
"profile.label.joined": {
"message": "Se unió hace"
},
@@ -1994,6 +2090,9 @@
"profile.label.organizations": {
"message": "Organizaciones"
},
"profile.label.projects": {
"message": "{count} {countPlural, plural, one {proyecto} other {proyectos}}"
},
"profile.label.saving": {
"message": "Guardando..."
},
@@ -2714,6 +2813,18 @@
"search.filter.locked.server.sync": {
"message": "Sincronizar con el servidor"
},
"servers.busy.backup-creating": {
"message": "Creación de copia de seguridad en curso"
},
"servers.busy.backup-restoring": {
"message": "Restauración de copia de seguridad en curso"
},
"servers.busy.installing": {
"message": "El servidor se está instalando"
},
"servers.busy.syncing-content": {
"message": "Sincronización de contenido en progreso"
},
"servers.notice.actions": {
"message": "Acciones"
},
@@ -2744,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Ideal para 1525 jugadores, paquetes de mods o modding intensivo."
},
"servers.plan.large.name": {
"message": "Grande"
},
"servers.plan.medium.description": {
"message": "Ideal para 615 jugadores y múltiples mods."
},
"servers.plan.medium.name": {
"message": "Medio"
},
"servers.plan.small.description": {
"message": "Perfecto para 15 amigos con algunas modificaciones ligeras."
},
"servers.plan.small.name": {
"message": "Pequeño"
"settings.account.button.complete-setup": {
"message": "Configuración completa"
},
"settings.account.data-export.action.download": {
"message": "Descargar exportación"
},
"settings.account.data-export.action.generate": {
"message": "Generar exportación"
},
"settings.account.data-export.action.generating": {
"message": "Generando exportación..."
},
"settings.account.data-export.description": {
"message": "Solicita una copia de todos los datos personales que hayas subido a Modrinth. El proceso puede tardar varios minutos en completarse."
},
"settings.account.data-export.title": {
"message": "Exportación de datos"
},
"settings.account.delete.confirm.description": {
"message": "Esto **eliminará inmediatamente todos tus datos de usuario y tus seguidores**. No se eliminarán tus proyectos. La eliminación de tu cuenta es irreversible.<br><br>Si necesitas ayuda con tu cuenta, solicita asistencia en el [Discord de Modrinth](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Eliminar esta cuenta"
},
"settings.account.delete.confirm.title": {
"message": "¿Estás seguro de que quieres eliminar tu cuenta?"
},
"settings.account.delete.section.action": {
"message": "Eliminar cuenta"
},
"settings.account.delete.section.description": {
"message": "Una vez que elimines tu cuenta, no habrá vuelta atrás. Al eliminar tu cuenta, se borrarán de nuestros servidores todos los datos asociados, excepto los proyectos."
},
"settings.account.delete.section.title": {
"message": "Eliminar cuenta"
},
"settings.account.email.action.save": {
"message": "Guardar correo electrónico"
},
"settings.account.email.field.label": {
"message": "Correo electrónico"
},
"settings.account.email.field.placeholder": {
"message": "Introduce tu correo electrónico..."
},
"settings.account.email.modal.header.add": {
"message": "Añadir correo electrónico"
},
"settings.account.email.modal.header.change": {
"message": "Cambiar correo electrónico"
},
"settings.account.email.modal.notice": {
"message": "La información de tu cuenta no se muestra públicamente."
},
"settings.account.password.action.remove": {
"message": "Eliminar contraseña"
},
"settings.account.password.action.save": {
"message": "Guardar contraseña"
},
"settings.account.password.error.mismatch": {
"message": "¡Las contraseñas no coinciden!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Introduzca su contraseña para continuar."
},
"settings.account.password.field.confirm-current.label": {
"message": "Confirmar contraseña"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Confirmar contraseña"
},
"settings.account.password.field.confirm-new.label": {
"message": "Confirmar nueva contraseña"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Confirmar nueva contraseña"
},
"settings.account.password.field.new.label": {
"message": "Nueva contraseña"
},
"settings.account.password.field.new.placeholder": {
"message": "Nueva contraseña"
},
"settings.account.password.field.old.label": {
"message": "Antigua contraseña"
},
"settings.account.password.field.old.placeholder": {
"message": "Antigua contraseña"
},
"settings.account.password.modal.header.add": {
"message": "Añadir contraseña"
},
"settings.account.password.modal.header.change": {
"message": "Cambiar contraseña"
},
"settings.account.password.modal.header.remove": {
"message": "Eliminar contraseña"
},
"settings.account.providers.action.add": {
"message": "Añadir"
},
"settings.account.providers.modal.header": {
"message": "Proveedores de autenticación"
},
"settings.account.providers.table.actions": {
"message": "Acciones"
},
"settings.account.providers.table.provider": {
"message": "Proveedor"
},
"settings.account.security.email.action.add": {
"message": "Añadir correo electrónico"
},
"settings.account.security.email.action.change": {
"message": "Cambiar correo electrónico"
},
"settings.account.security.email.description": {
"message": "Cambia la dirección de correo electrónico asociada a tu cuenta."
},
"settings.account.security.email.title": {
"message": "Correo electrónico"
},
"settings.account.security.password.action.add": {
"message": "Añadir contraseña"
},
"settings.account.security.password.action.change": {
"message": "Cambiar contraseña"
},
"settings.account.security.password.description.change": {
"message": "Cambia la contraseña que utilizas para iniciar sesión en tu cuenta."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Cambia o elimina la contraseña que utilizas para iniciar sesión en tu cuenta."
},
"settings.account.security.password.description.set": {
"message": "Establece una contraseña permanente para iniciar sesión en tu cuenta."
},
"settings.account.security.password.title": {
"message": "Contraseña"
},
"settings.account.security.providers.action.manage": {
"message": "Gestionar proveedores"
},
"settings.account.security.providers.description": {
"message": "Añade o elimina métodos de inicio de sesión de tu cuenta, como GitHub, GitLab, Microsoft, Discord, Steam y Google."
},
"settings.account.security.providers.title": {
"message": "Gestionar proveedores de autenticación"
},
"settings.account.security.title": {
"message": "Seguridad de la cuenta"
},
"settings.account.security.two-factor.action.remove": {
"message": "Desactivar la autenticación de dos factores"
},
"settings.account.security.two-factor.action.setup": {
"message": "Configurar la autenticación de dos factores"
},
"settings.account.security.two-factor.description": {
"message": "Añade una capa adicional de seguridad a tu cuenta al iniciar sesión."
},
"settings.account.security.two-factor.title": {
"message": "Autenticación de dos factores"
},
"settings.account.two-factor.backup.intro": {
"message": "Descarga y guarda estos códigos de seguridad en un lugar seguro. ¡Puedes utilizarlos en lugar de un código de autenticación de dos factores si alguna vez pierdes el acceso a tu dispositivo! Debes proteger estos códigos igual que tu contraseña."
},
"settings.account.two-factor.backup.single-use": {
"message": "Los códigos de seguridad solo se pueden usar una vez."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "¡El código introducido es incorrecto!"
},
"settings.account.two-factor.field.code.description": {
"message": "Introduce el código de autenticación de dos factores para continuar."
},
"settings.account.two-factor.field.code.label": {
"message": "Introduce el código de dos factores"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Introduce el código..."
},
"settings.account.two-factor.setup.intro": {
"message": "La autenticación de dos factores protege tu cuenta, ya que exige el acceso a un segundo dispositivo para iniciar sesión."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Si no se puede escanear el código QR, puedes introducir el secreto manualmente:"
},
"settings.account.two-factor.setup.scan": {
"message": "Escanea el código QR con <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> o cualquier otra aplicación de autenticación de dos factores para empezar."
},
"settings.account.two-factor.verify.description": {
"message": "Introduce el código de un solo uso de la aplicación de autenticación para verificar el acceso."
},
"settings.account.two-factor.verify.label": {
"message": "Verificar código"
},
"settings.applications.about": {
"message": "Acerca de"
@@ -2838,14 +3138,14 @@
"message": "URL"
},
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
"message": "https://ejemplo.com"
},
"settings.applications.head-title": {
"message": "Aplicaciones"
},
"settings.applications.modal.header": {
"message": "Información de aplicación"
},
"settings.applications.notification.error.title": {
"message": "Se ha producido un error"
},
"settings.applications.notification.icon-updated.description": {
"message": "El icono de tu aplicación se ha actualizado."
},
@@ -2855,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "Guarda tu secreto ahora, ¡quedará oculto después de que salgas de esta página!"
},
"settings.authorizations.about-this-app": {
"message": "Acerca de esta aplicación"
},
"settings.authorizations.by": {
"message": "por"
},
"settings.authorizations.description": {
"message": "Cuando autorizas una aplicación con tu cuenta de Modrinth, le concedes acceso a tu cuenta. Puedes gestionar y revisar el acceso a tu cuenta aquí en cualquier momento."
},
"settings.authorizations.empty-state": {
"message": "Por el momento no podemos mostrar tus aplicaciones autorizadas, pero estamos trabajando para solucionar el problema. ¡Vuelve a visitar esta página más adelante!"
},
"settings.authorizations.head-title": {
"message": "Autorizaciones"
},
"settings.authorizations.revoke.action": {
"message": "Revocar"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Esto revocará el acceso de la aplicación a tu cuenta. Siempre podrás volver a autorizarla más adelante."
},
"settings.authorizations.revoke.confirm.title": {
"message": "¿Estás seguro de que quieres revocar esta solicitud?"
},
"settings.billing.charges.description": {
"message": "Aquí aparecerán todos los cargos anteriores de tu cuenta de Modrinth:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Versión de prueba de Medal Server"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Caduca el {date}"
},
"settings.billing.interval.month": {
"message": "mes"
},
"settings.billing.interval.monthly": {
"message": "mensual"
},
"settings.billing.interval.year": {
"message": "año"
},
"settings.billing.interval.yearly": {
"message": "anual"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Navegación sin anuncios en modrinth.com y Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Insignia de Modrinth+ en tu perfil"
},
"settings.billing.midas.benefits.support": {
"message": "Apoya directamente a Modrinth y a los creadores"
},
"settings.billing.midas.benefits.title": {
"message": "Beneficios"
},
"settings.billing.midas.save-per-year": {
"message": "¡Ahorra {amount} al año cambiando a la facturación anual!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Has cancelado tu suscripción."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "Conservarás tus ventajas hasta el final del ciclo de facturación actual."
},
"settings.billing.midas.status.failed": {
"message": "El pago de tu suscripción no se ha realizado correctamente. Actualiza tu método de pago."
},
"settings.billing.midas.status.open": {
"message": "Actualmente estás suscrito a:"
},
"settings.billing.midas.status.processing": {
"message": "Se está procesando tu pago. Las ventajas se activarán una vez que se haya completado el pago."
},
"settings.billing.midas.upsell": {
"message": "¡Suscríbete a Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Cancelar suscripción"
},
@@ -2873,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "¿Estás seguro de que deseas eliminar este método de pago?"
},
"settings.billing.next": {
"message": "Siguiente:"
},
"settings.billing.or-yearly-save": {
"message": "O {price} al año (¡ahorra un {percent}%!)"
},
"settings.billing.payment_method.action.add": {
"message": "Añadir método de pago"
},
@@ -2894,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Formas de pago"
},
"settings.billing.plan.title": {
"message": "{size} Plan"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} CPU compartidas (Picos de hasta {bursts} CPUs)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "No se ha encontrado ningún servidor vinculado para esta suscripción. Hay varias explicaciones posibles para ello. Si acaba de adquirir su servidor, esto es normal. La configuración del servidor puede tardar hasta una hora. Por el contrario, si adquirió este servidor hace tiempo, es probable que haya sido suspendido desde entonces. Si esto no es lo que esperaba, póngase en contacto con el servicio de asistencia de Modrinth con la siguiente información:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "ID del servidor: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "ID de Stripe: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} GB de RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Se ha producido un error al volver a suscribirse a su servidor Modrinth."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Error al volver a suscribirse"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Si el servidor está actualmente suspendido, pueden pasar hasta 10 minutos antes de que se realice otro intento de cobro."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Solicitud de renovación enviada"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "La suscripción al servidor se ha renovado correctamente"
},
"settings.billing.pyro.status.failed": {
"message": "El pago de tu suscripción no se ha realizado correctamente. Actualiza tu método de pago y vuelve a suscribirte."
},
"settings.billing.pyro.status.processing": {
"message": "Se está procesando tu pago. Tu servidor se activará una vez que se haya completado el pago."
},
"settings.billing.pyro.storage": {
"message": "{gb} GB de SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} GB de intercambio"
},
"settings.billing.pyro_subscription.description": {
"message": "Gestiona tus suscripciones a servidores de Modrinth."
},
"settings.billing.pyro_subscription.title": {
"message": "Suscripciones a servidores de Modrinth"
},
"settings.billing.renews": {
"message": "Se renueva el {date}"
},
"settings.billing.resubscribe": {
"message": "Volver a suscribirse"
},
"settings.billing.since": {
"message": "Desde el {date}"
},
"settings.billing.subscribe": {
"message": "Suscríbete"
},
"settings.billing.subscription.description": {
"message": "Gestiona tus suscripciones de Modrinth."
},
"settings.billing.subscription.title": {
"message": "Suscripciones"
},
"settings.billing.switch.switching-to-interval": {
"message": "Cambiando a {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Cambiar a {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "La facturación mensual te supondrá un coste adicional de {amount} al año"
},
"settings.billing.switches-to-billing-on": {
"message": "Pasará a la facturación por {interval} a partir del {date}"
},
"settings.billing.update-method": {
"message": "Actualizar método"
},
"settings.billing.upgrade": {
"message": "Mejorar"
},
"settings.display.banner.developer-mode.button": {
"message": "Desactivar modo desarrollador"
},
@@ -2918,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Alternar funciones"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "El modo de desarrollador se ha desactivado"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Modo de desarrollador desactivado"
},
"settings.display.project-list-layouts.datapack": {
"message": "Página de paquetes de datos"
},
@@ -2927,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Página de Mods"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galería"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Cuadrícula"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Filas"
},
"settings.display.project-list-layouts.modpack": {
"message": "Página de Modpacks"
},
@@ -2987,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Tema de color"
},
"settings.head-title": {
"message": "Configuración de pantalla"
},
"settings.pats.action.create": {
"message": "Crear un PAT"
},
@@ -3047,6 +3536,9 @@
"settings.profile.description": {
"message": "La información de tu perfil es visible públicamente en Modrinth y a través de la <docs-link>API de Modrinth</docs-link>."
},
"settings.profile.head-title": {
"message": "Configuración del perfil"
},
"settings.profile.profile-info": {
"message": "Información perfil"
},
@@ -3077,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Plataforma desconocida"
},
"settings.sidebar.label.account": {
"message": "Cuenta"
},
"settings.sidebar.label.developer": {
"message": "Desarrollador"
},
"settings.sidebar.label.display": {
"message": "Pantalla"
},
"ui.latest-news-row.latest-news": {
"message": "Últimas noticias de Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Ver todas las noticias"
},
"ui.newsletter-button.subscribe": {
"message": "Suscribir"
},
"ui.newsletter-button.subscribed": {
"message": "¡Suscrito!"
},
"ui.newsletter-button.tooltip": {
"message": "Suscríbete al boletín de noticias de Modrinth"
},
"version.environment.none.description": {
"message": "El entorno para esta versión no ha sido especificado."
},
+18 -9
View File
@@ -35,6 +35,9 @@
"app-marketing.download.options-title": {
"message": "Lataus vaihtoehdot"
},
"app-marketing.download.terms": {
"message": "Lataamalla Modrint sovelluksen, sinä hyväksyt meidän <terms-link>Ehdot</terms-link> Ja <privacy-link>Tietosuojakäytännöt</privacy-link>."
},
"app-marketing.download.title": {
"message": "Lataa Modrinth App (Beta)"
},
@@ -101,6 +104,9 @@
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.description": {
"message": "Modrinth App toimii paremmin kuin monet johtavat modinhallintaohjelmat ja käyttää vain 150 MT RAM-muistia!"
},
"app-marketing.features.performance.discord": {
"message": "Discord"
},
@@ -335,6 +341,9 @@
"collection.title": {
"message": "{name} - kokoelma"
},
"create.collection.collection-info": {
"message": "Sinun uusi kokoelma luodaan julkiseksi kokoelmaksi {count, plural, =0 {no projects} one {# project} other {# projects}}:lla. "
},
"dashboard.collections.button.create-new": {
"message": "Luo uusi"
},
@@ -347,6 +356,15 @@
"dashboard.creator-tax-form-modal.header": {
"message": "Vero lomake"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Vahvista lompakkosi osoite"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Matalammat maksut saatavilla"
},
"dashboard.revenue.processing": {
"message": "Prosessoidaan"
},
"error.collection.404.list_item.1": {
"message": "Saatoit kirjoittaa kokoelman URL osoitteen väärin."
},
@@ -707,15 +725,6 @@
"servers.notices.no-notices": {
"message": "Ei ilmoituksia"
},
"servers.plan.large.name": {
"message": "Suuri"
},
"servers.plan.medium.name": {
"message": "Keskikokoinen"
},
"servers.plan.small.name": {
"message": "Pieni"
},
"settings.billing.payment_method.action.primary": {
"message": "Tee ensisijaiseksi"
},
+12 -15
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Lumikha ng proyekto"
},
"create.project.create-server-project": {
"message": "Lumikha ng server"
},
"create.project.missing-fields-tooltip": {
"message": "Nakukulang na field: {fields}"
},
@@ -1304,6 +1301,9 @@
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Mapa-Vanilla, mapa-Fabric, mapa-Forge, mapa-Quilt o mapa-NeoForge ba ang pili mo. Kung ito'y nasa Modrinth, gagana ito sa server mo."
},
"hosting.loader.failed-to-unlink": {
"message": "Bigong ma-unlink ang modpack"
},
"hosting.plan.out-of-stock": {
"message": "Wala nang stock"
},
@@ -2813,21 +2813,12 @@
"servers.plan.large.description": {
"message": "Nakaaangkop sa 1525 manlalaro, modpack, o mabibigat na modding."
},
"servers.plan.large.name": {
"message": "Large"
},
"servers.plan.medium.description": {
"message": "Nakaaangkop sa 615 manlalaro at may karamihang mod."
},
"servers.plan.medium.name": {
"message": "Medium"
},
"servers.plan.small.description": {
"message": "Nakaaangkop sa 15 manlalaro na may iilang mod."
},
"servers.plan.small.name": {
"message": "Small"
},
"settings.applications.about": {
"message": "Tungkol"
},
@@ -2912,9 +2903,6 @@
"settings.applications.modal.header": {
"message": "Impormasyon ng aplikasyon"
},
"settings.applications.notification.error.title": {
"message": "Isang kamaliang naganap"
},
"settings.applications.notification.icon-updated.description": {
"message": "Ang ikono ng iyong aplikasyon ay na-update."
},
@@ -3152,6 +3140,15 @@
"ui.latest-news-row.view-all": {
"message": "Tingnan ang lahat ng balita"
},
"ui.newsletter-button.subscribe": {
"message": "Mag-subscribe"
},
"ui.newsletter-button.subscribed": {
"message": "Naka-subscribe!"
},
"ui.newsletter-button.tooltip": {
"message": "Mag-subscribe sa Modrinth newsletter"
},
"version.environment.none.description": {
"message": "Wala pang itinakdang environment para sa bersiyong ito."
},
+410 -14
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Créer un projet"
},
"create.project.create-server-project": {
"message": "Créer un serveur"
},
"create.project.missing-fields-tooltip": {
"message": "Champs manquants : {fields}"
},
@@ -2858,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Idéal pour 1525 joueurs, des modpacks, ou le modding intensif."
},
"servers.plan.large.name": {
"message": "Grand"
},
"servers.plan.medium.description": {
"message": "Parfait pour 615 joueurs et plusieurs mods."
},
"servers.plan.medium.name": {
"message": "Moyen"
},
"servers.plan.small.description": {
"message": "Parfait pour 15 amis et quelques mods légers."
},
"servers.plan.small.name": {
"message": "Petit"
"settings.account.button.complete-setup": {
"message": "Terminer la configuration"
},
"settings.account.data-export.action.download": {
"message": "Télécharger lexport"
},
"settings.account.data-export.action.generate": {
"message": "Générer lexport"
},
"settings.account.data-export.action.generating": {
"message": "Génération de lexport..."
},
"settings.account.data-export.description": {
"message": "Demandez une copie de toutes vos données personnelles que vous avez téléchargées sur Modrinth. Cette opération peut prendre plusieurs minutes."
},
"settings.account.data-export.title": {
"message": "Export des données"
},
"settings.account.delete.confirm.description": {
"message": "Cela supprimera **immédiatement tous vos projets et vos suivis**. La suppression de votre compte est irréversible.<br><br>Si vous avez besoin d'aide avec votre compte, contactez le serveur [Discord de Modrinth](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Supprimer ce compte"
},
"settings.account.delete.confirm.title": {
"message": "Êtes-vous sûr de vouloir supprimer votre compte ?"
},
"settings.account.delete.section.action": {
"message": "Supprimer le compte"
},
"settings.account.delete.section.description": {
"message": "Une fois votre compte supprimé, il ne sera plus possible de revenir en arrière. La suppression de votre compte effacera toutes les données associées de nos serveurs, à lexception des projets."
},
"settings.account.delete.section.title": {
"message": "Supprimer le compte"
},
"settings.account.email.action.save": {
"message": "Enregistrer l'e-mail"
},
"settings.account.email.field.label": {
"message": "Adresse e-mail"
},
"settings.account.email.field.placeholder": {
"message": "Entrez votre adresse e-mail..."
},
"settings.account.email.modal.header.add": {
"message": "Ajouter un e-mail"
},
"settings.account.email.modal.header.change": {
"message": "Modifier le-mail"
},
"settings.account.email.modal.notice": {
"message": "Les informations de votre compte ne sont pas affichées publiquement."
},
"settings.account.password.action.remove": {
"message": "Supprimer le mot de passe"
},
"settings.account.password.action.save": {
"message": "Enregistrer le mot de passe"
},
"settings.account.password.error.mismatch": {
"message": "Les mots de passe saisis ne correspondent pas!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Veuillez saisir votre mot de passe pour continuer."
},
"settings.account.password.field.confirm-current.label": {
"message": "Confirmer le mot de passe"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Confirmer le mot de passe"
},
"settings.account.password.field.confirm-new.label": {
"message": "Confirmer le nouveau mot de passe"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Confirmer le nouveau mot de passe"
},
"settings.account.password.field.new.label": {
"message": "Nouveau mot de passe"
},
"settings.account.password.field.new.placeholder": {
"message": "Nouveau mot de passe"
},
"settings.account.password.field.old.label": {
"message": "Ancien mot de passe"
},
"settings.account.password.field.old.placeholder": {
"message": "Ancien mot de passe"
},
"settings.account.password.modal.header.add": {
"message": "Ajouter un mot de passe"
},
"settings.account.password.modal.header.change": {
"message": "Modifier le mot de passe"
},
"settings.account.password.modal.header.remove": {
"message": "Supprimer le mot de passe"
},
"settings.account.providers.action.add": {
"message": "Ajouter"
},
"settings.account.providers.modal.header": {
"message": "Fournisseurs dauthentification"
},
"settings.account.providers.table.actions": {
"message": "Actions"
},
"settings.account.providers.table.provider": {
"message": "Fournisseur"
},
"settings.account.security.email.action.add": {
"message": "Ajouter un e-mail"
},
"settings.account.security.email.action.change": {
"message": "Modifier le-mail"
},
"settings.account.security.email.description": {
"message": "Modifie le-mail associé à votre compte."
},
"settings.account.security.email.title": {
"message": "E-mail"
},
"settings.account.security.password.action.add": {
"message": "Ajouter un mot de passe"
},
"settings.account.security.password.action.change": {
"message": "Modifier le mot de passe"
},
"settings.account.security.password.description.change": {
"message": "Modifie le mot de passe utilisé pour vous connecter à votre compte."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Modifier ou supprimer le mot de passe utilisé pour vous connecter à votre compte."
},
"settings.account.security.password.description.set": {
"message": "Définissez un mot de passe permanent pour vous connecter à votre compte."
},
"settings.account.security.password.title": {
"message": "Mot de passe"
},
"settings.account.security.providers.action.manage": {
"message": "Gérer les fournisseurs"
},
"settings.account.security.providers.description": {
"message": "Ajoutez ou supprimez des méthodes de connexion à votre compte, y compris GitHub, GitLab, Microsoft, Discord, Steam et Google."
},
"settings.account.security.providers.title": {
"message": "Gérer les fournisseurs dauthentification"
},
"settings.account.security.title": {
"message": "Compte et sécurité"
},
"settings.account.security.two-factor.action.remove": {
"message": "Supprimer la 2FA"
},
"settings.account.security.two-factor.action.setup": {
"message": "Configurer la 2FA"
},
"settings.account.security.two-factor.description": {
"message": "Ajoutez une couche de sécurité supplémentaire à votre compte lors de la connexion."
},
"settings.account.security.two-factor.title": {
"message": "Authentification à deux facteurs"
},
"settings.account.two-factor.backup.intro": {
"message": "Téléchargez et enregistrez ces codes de secours dans un endroit sûr. Vous pourrez les utiliser à la place dun code 2FA si vous perdez laccès à votre appareil ! Vous devez protéger ces codes comme votre mot de passe."
},
"settings.account.two-factor.backup.single-use": {
"message": "Les codes de secours ne peuvent être utilisés quune seule fois."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "Le code saisi est incorrect!"
},
"settings.account.two-factor.field.code.description": {
"message": "Veuillez saisir un code dauthentification à deux facteurs pour continuer."
},
"settings.account.two-factor.field.code.label": {
"message": "Saisir le code dauthentification à deux facteurs"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Saisir le code..."
},
"settings.account.two-factor.setup.intro": {
"message": "Lauthentification à deux facteurs protège votre compte en exigeant laccès à un second appareil pour vous connecter."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Si le code QR ne peut pas être scanné, vous pouvez saisir manuellement le secret :"
},
"settings.account.two-factor.setup.scan": {
"message": "Scannez le code QR avec <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> ou toute autre application 2FA pour commencer."
},
"settings.account.two-factor.verify.description": {
"message": "Saisissez le code à usage unique généré par votre application dauthentification pour vérifier laccès."
},
"settings.account.two-factor.verify.label": {
"message": "Vérifier le code"
},
"settings.applications.about": {
"message": "À propos"
@@ -2954,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Applications"
},
"settings.applications.modal.header": {
"message": "Information de l'application"
},
"settings.applications.notification.error.title": {
"message": "Une erreur est survenue"
},
"settings.applications.notification.icon-updated.description": {
"message": "L'icône de votre application a été mis à jour."
},
@@ -2969,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "Sauvegarder votre secret maintenant, il sera caché quand vous quitterez cette page !"
},
"settings.authorizations.about-this-app": {
"message": "À propos de cette application"
},
"settings.authorizations.by": {
"message": "par"
},
"settings.authorizations.description": {
"message": "Lorsque vous autorisez une application avec votre compte Modrinth, vous lui accordez laccès à votre compte. Vous pouvez gérer et consulter les accès à votre compte ici à tout moment."
},
"settings.authorizations.empty-state": {
"message": "Nous ne pouvons pas afficher vos applications autorisées pour le moment, nous travaillons à résoudre ce problème. Veuillez revenir sur cette page ultérieurement !"
},
"settings.authorizations.head-title": {
"message": "Autorisations"
},
"settings.authorizations.revoke.action": {
"message": "Révoquer"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Cela révoquera laccès de lapplication à votre compte. Vous pourrez toujours la réautoriser plus tard."
},
"settings.authorizations.revoke.confirm.title": {
"message": "Êtes-vous sûr de vouloir révoquer cette application?"
},
"settings.billing.charges.description": {
"message": "Toutes vos transactions passées sur votre compte Modrinth seront affichées ici :"
},
"settings.billing.charges.product.medal-trial": {
"message": "Essai du serveur Medal"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Hébergement Modrinth"
},
"settings.billing.expires": {
"message": "Expire le {date}"
},
"settings.billing.interval.month": {
"message": "mois"
},
"settings.billing.interval.monthly": {
"message": "mensuel"
},
"settings.billing.interval.year": {
"message": "an"
},
"settings.billing.interval.yearly": {
"message": "annuel"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Navigation sans publicité sur modrinth.com et Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Badge Modrinth+ sur votre profil"
},
"settings.billing.midas.benefits.support": {
"message": "Soutenez directement Modrinth et les créateurs"
},
"settings.billing.midas.benefits.title": {
"message": "Avantages"
},
"settings.billing.midas.save-per-year": {
"message": "Économisez {amount}/an en passant à la facturation annuelle !"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Vous avez annulé votre abonnement."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "Vous conserverez vos avantages jusqu’à la fin du cycle de facturation en cours."
},
"settings.billing.midas.status.failed": {
"message": "Le paiement de votre abonnement a échoué. Veuillez mettre à jour votre mode de paiement."
},
"settings.billing.midas.status.open": {
"message": "Vous êtes actuellement abonné à :"
},
"settings.billing.midas.status.processing": {
"message": "Votre paiement est en cours de traitement. Les avantages seront activés une fois le paiement terminé."
},
"settings.billing.midas.upsell": {
"message": "Devenez abonné à Modrinth Plus !"
},
"settings.billing.modal.cancel.action": {
"message": "Annuler labonnement"
},
@@ -2987,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "Êtes-vous sûr de vouloir supprimer ce mode de paiement ?"
},
"settings.billing.next": {
"message": "Suivant :"
},
"settings.billing.or-yearly-save": {
"message": "Ou {price} / an (économisez {percent}%) !"
},
"settings.billing.payment_method.action.add": {
"message": "Ajouter un mode de paiement"
},
@@ -3008,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Mode de paiement"
},
"settings.billing.plan.title": {
"message": "Plan {size}"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} CPU partagés (pics jusqu’à {bursts} CPU)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "Un serveur lié na pas pu être trouvé pour cet abonnement. Il y a plusieurs explications possibles. Si vous venez dacheter votre serveur, cest normal. Il peut prendre jusqu’à une heure pour que votre serveur soit provisionné. Sinon, si vous avez acheté ce serveur il y a un certain temps, il a probablement été suspendu depuis. Si ce nest pas ce à quoi vous vous attendiez, veuillez contacter le support Modrinth avec les informations suivantes :"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "ID du serveur : {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "ID Stripe : {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} Go de RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Une erreur est survenue lors de la tentative de réabonnement à votre serveur Modrinth."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Erreur lors du réabonnement"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Si le serveur est actuellement suspendu, une nouvelle tentative de paiement peut prendre jusqu’à 10 minutes."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Demande de réabonnement envoyée"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "Réabonnement au serveur effectué avec succès"
},
"settings.billing.pyro.status.failed": {
"message": "Votre paiement dabonnement a échoué. Veuillez mettre à jour votre moyen de paiement, puis vous réabonner."
},
"settings.billing.pyro.status.processing": {
"message": "Votre paiement est en cours de traitement. Votre serveur sera activé une fois le paiement finalisé."
},
"settings.billing.pyro.storage": {
"message": "{gb} Go de SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} Go de swap"
},
"settings.billing.pyro_subscription.description": {
"message": "Gérer vos abonnements au serveur Modrinth."
},
"settings.billing.pyro_subscription.title": {
"message": "Abonnements au serveur Modrinth"
},
"settings.billing.renews": {
"message": "Renouvellement le {date}"
},
"settings.billing.resubscribe": {
"message": "Se réabonner"
},
"settings.billing.since": {
"message": "Depuis {date}"
},
"settings.billing.subscribe": {
"message": "Sabonner"
},
"settings.billing.subscription.description": {
"message": "Gérer vos abonnements Modrinth."
},
"settings.billing.subscription.title": {
"message": "Abonnements"
},
"settings.billing.switch.switching-to-interval": {
"message": "Passage à {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Passer à {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "La facturation mensuelle vous coûtera un supplément de {amount} par an"
},
"settings.billing.switches-to-billing-on": {
"message": "Passe à une facturation {interval} le {date}"
},
"settings.billing.update-method": {
"message": "Mettre à jour le moyen de paiement"
},
"settings.billing.upgrade": {
"message": "Mettre à niveau"
},
"settings.display.banner.developer-mode.button": {
"message": "Désactiver le mode développeur"
},
@@ -3032,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Activer/désactiver les fonctionnalités"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "Le mode développeur a été désactivé"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Mode développeur désactivé"
},
"settings.display.project-list-layouts.datapack": {
"message": "Page des data packs"
},
@@ -3041,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Page des mods"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galerie"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Grille"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Lignes"
},
"settings.display.project-list-layouts.modpack": {
"message": "Page des modpacks"
},
@@ -3101,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Thème de couleur"
},
"settings.head-title": {
"message": "Paramètres daffichage"
},
"settings.pats.action.create": {
"message": "Créer un PAT"
},
@@ -3161,6 +3536,9 @@
"settings.profile.description": {
"message": "Votre information de profil est visible publiquement sur Modrinth et sur la <docs-link>Modrinth API</docs-link>."
},
"settings.profile.head-title": {
"message": "Paramètres du profil"
},
"settings.profile.profile-info": {
"message": "Information du profil"
},
@@ -3191,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Plateforme inconnue"
},
"settings.sidebar.label.account": {
"message": "Compte"
},
"settings.sidebar.label.developer": {
"message": "Développeur"
},
"settings.sidebar.label.display": {
"message": "Affichage"
},
"ui.latest-news-row.latest-news": {
"message": "Dernières nouveautés de Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Voir toutes les actualités"
},
"ui.newsletter-button.subscribe": {
"message": "S'abonner"
},
"ui.newsletter-button.subscribed": {
"message": "Abonné ! "
},
"ui.newsletter-button.tooltip": {
"message": "S'abonner au journal Modrinth"
},
"version.environment.none.description": {
"message": "L'environnement pour cette version n'a pas été spécifié."
},
@@ -485,9 +485,6 @@
"create.project.create-project": {
"message": "צור פרויקט"
},
"create.project.create-server-project": {
"message": "צור שרת"
},
"create.project.name-label": {
"message": "שם"
},
+126 -33
View File
@@ -258,10 +258,10 @@
"message": "Jelszavad visszaállítása"
},
"auth.sign-in.2fa.description": {
"message": "Kérlek ad meg a két-faktoros kódot hogy tovább menj."
"message": "Kérjük írja be a kétlépcsős hitelesítés kódját a folytatáshoz."
},
"auth.sign-in.2fa.label": {
"message": "Két-faktoros kód megadása"
"message": "Írja be a kétlépcsős hitelesítés kódját"
},
"auth.sign-in.2fa.placeholder": {
"message": "Kód beírása..."
@@ -456,13 +456,13 @@
"message": "szervezet"
},
"create.limit-alert.type-plural-collection": {
"message": "gyűjtemények"
"message": "gyűjtemény"
},
"create.limit-alert.type-plural-organization": {
"message": "szervezetek"
"message": "szervezet"
},
"create.limit-alert.type-plural-project": {
"message": "projektek"
"message": "projekt"
},
"create.limit-alert.type-project": {
"message": "projekt"
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Projekt létrehozása"
},
"create.project.create-server-project": {
"message": "Szerver létrehozása"
},
"create.project.missing-fields-tooltip": {
"message": "Hiányzó mezők: {fields}"
},
@@ -540,7 +537,7 @@
"message": "Szerver"
},
"create.project.url-label": {
"message": "URL"
"message": "Link"
},
"create.project.visibility-description": {
"message": "A projekt láthatósága jóváhagyása után."
@@ -578,6 +575,18 @@
"dashboard.collections.button.create-new": {
"message": "Új létrehozása"
},
"dashboard.collections.empty.get-started-hint": {
"message": "Készítsd el az első gyűjteményedet, és kezdj neki!"
},
"dashboard.collections.empty.no-collections": {
"message": "Még nincs gyűjteményed"
},
"dashboard.collections.empty.no-match": {
"message": "Egy gyűjtemény sem egyezik a kereséssel"
},
"dashboard.collections.empty.no-match-hint": {
"message": "Próbáld meg módosítani a szűrőket vagy a keresési kifejezéseket."
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, one {projekt} other {projektek}}"
},
@@ -603,7 +612,7 @@
"message": "A külföldi jogi személy olyan üzleti egységet jelent, amelyet az Egyesült Államokon kívül hoztak létre (például nem amerikai részvénytársaság, társulás vagy korlátolt felelősségű társaság LLC)."
},
"dashboard.creator-tax-form-modal.entity.foreign-entity": {
"message": "Idegen entitáns"
"message": "Külföldi szervezet"
},
"dashboard.creator-tax-form-modal.entity.private-individual": {
"message": "Magánszemély"
@@ -788,6 +797,9 @@
"dashboard.creator-withdraw-modal.tremendous-details.available-denominations-label": {
"message": "Elérhető címletek"
},
"dashboard.creator-withdraw-modal.tremendous-details.enter-amount-hint": {
"message": "Keress Ajándékkártyákat ez az ár körül."
},
"dashboard.creator-withdraw-modal.tremendous-details.enter-denomination-placeholder": {
"message": "Összeg megadása"
},
@@ -923,6 +935,9 @@
"dashboard.withdraw.error.email-verification.title": {
"message": "E-mail hítelesítés szükséges"
},
"dashboard.withdraw.error.insufficient-balance.title": {
"message": "Nincs elég vagyonod"
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Cím megerősítése sikertelen"
},
@@ -1131,7 +1146,7 @@
"message": "Egyéni link"
},
"hosting-marketing.included.custom-url.description": {
"message": "Ossza meg szerverét egy egyedi <contrast>modrinth.gg</contrast> linkkel."
"message": "Oszd meg a szerveredet egy egyedi <contrast>modrinth.gg</contrast> linkkel."
},
"hosting-marketing.included.description": {
"message": "Minden szerverhez tartozik egy sor olyan funkció, amelynek célja, hogy olyan tárhelyszolgáltatást nyújtson, amelyet csak a Modrinth tud nyújtani."
@@ -1397,6 +1412,9 @@
"layout.banner.add-email.description": {
"message": "Biztonsági okok miatt a Modrinthon kell egy e-mail cím a fiókodhoz."
},
"layout.banner.build-fail.description": {
"message": "A Modrinth felhasználói felületének jelenlegi telepítése nem tudta az API-ból lekérni az állapotadatokat. Ennek oka lehet egy szolgáltatáskimaradás vagy konfigurációs hiba. Kérünk, próbáld meg újra, amikor az API újra elérhetővé válik. Hibakódok: {errors}; Az API jelenlegi linkje: {url}"
},
"layout.banner.staging.title": {
"message": "A Modrinth színreviteli környezetét nézed"
},
@@ -1980,61 +1998,61 @@
"message": "Figyelmeztetés"
},
"project-type.collection.plural": {
"message": "Gyűjtemények"
"message": "Gyűjtemény"
},
"project-type.collection.singular": {
"message": "Gyűjtemény"
},
"project-type.datapack.plural": {
"message": "Adatcsomagok"
"message": "Adatcsomag"
},
"project-type.datapack.singular": {
"message": "Adatcsomag"
},
"project-type.minecraft_java_server.plural": {
"message": "Szerverek"
"message": "Szerver"
},
"project-type.minecraft_java_server.singular": {
"message": "Szerver"
},
"project-type.mod.plural": {
"message": "Modok"
"message": "Mod"
},
"project-type.mod.singular": {
"message": "Mod"
},
"project-type.modpack.plural": {
"message": "Modcsomagok"
"message": "Modcsomag"
},
"project-type.modpack.singular": {
"message": "Modpack"
},
"project-type.plugin.plural": {
"message": "Bővítmények"
"message": "Bővítmény"
},
"project-type.plugin.singular": {
"message": "Bővítmény"
},
"project-type.project.plural": {
"message": "Projektek"
"message": "Projekt"
},
"project-type.project.singular": {
"message": "Projekt"
},
"project-type.resourcepack.plural": {
"message": "Forráscsomagok"
"message": "Forráscsomag"
},
"project-type.resourcepack.singular": {
"message": "Forráscsomag"
},
"project-type.server.plural": {
"message": "Szerverek"
"message": "Szerver"
},
"project-type.server.singular": {
"message": "Szerver"
},
"project-type.shader.plural": {
"message": "Shaderek"
"message": "Shader"
},
"project-type.shader.singular": {
"message": "Shader"
@@ -2531,20 +2549,98 @@
"servers.plan.large.description": {
"message": "Ideális 1525 játékos számára, modcsomagokhoz vagy intenzív moddoláshoz."
},
"servers.plan.large.name": {
"message": "Nagy"
},
"servers.plan.medium.description": {
"message": "Nagyszerű 615 játékos számára, többféle moddal."
},
"servers.plan.medium.name": {
"message": "Közepes"
},
"servers.plan.small.description": {
"message": "Tökéletes 15 barát számára, néhány kisebb moddal."
},
"servers.plan.small.name": {
"message": "Kicsi"
"settings.account.delete.confirm.proceed": {
"message": "Fiók törlése"
},
"settings.account.delete.confirm.title": {
"message": "Biztosan törölni szeretnéd a fiókodat?"
},
"settings.account.delete.section.action": {
"message": "Fiók törlése"
},
"settings.account.delete.section.title": {
"message": "Fiók törlése"
},
"settings.account.email.action.save": {
"message": "E-mail mentése"
},
"settings.account.email.field.label": {
"message": "E-mail-cím"
},
"settings.account.email.field.placeholder": {
"message": "Írd ide az e-mail címedet..."
},
"settings.account.email.modal.header.add": {
"message": "E-mail hozzáadása"
},
"settings.account.email.modal.header.change": {
"message": "E-mail megváltoztatása"
},
"settings.account.password.action.save": {
"message": "Jelszó mentése"
},
"settings.account.password.error.mismatch": {
"message": "A megadott jelszavak nem egyeznek!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Írd be a jelszavadat a folytatáshoz."
},
"settings.account.password.field.confirm-current.label": {
"message": "Jelszó megerősítése"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Jelszó megerősítése"
},
"settings.account.password.field.confirm-new.label": {
"message": "Új jelszó megerősítése"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Új jelszó megerősítése"
},
"settings.account.password.field.new.label": {
"message": "Új jelszó"
},
"settings.account.password.field.new.placeholder": {
"message": "Új jelszó"
},
"settings.account.password.field.old.label": {
"message": "Régi jelszó"
},
"settings.account.password.field.old.placeholder": {
"message": "Régi jelszó"
},
"settings.account.password.modal.header.add": {
"message": "Jelszó létrehozása"
},
"settings.account.password.modal.header.change": {
"message": "Jelszó módosítása"
},
"settings.account.providers.action.add": {
"message": "Hozzáadás"
},
"settings.account.security.email.title": {
"message": "E-mail"
},
"settings.account.security.password.title": {
"message": "Jelszó"
},
"settings.account.security.two-factor.action.remove": {
"message": "A kétlépcsős hitelesítés kikapcsolása "
},
"settings.account.security.two-factor.action.setup": {
"message": "A kétlépcsős hitelesítés beállítása"
},
"settings.account.two-factor.backup.intro": {
"message": "Töltse le ezeket a biztonsági kódokat, és őrizze meg őket biztonságos helyen. Ha valaha is elveszítené a hozzáférését az eszközéhez, ezeket a kódokat használhatja a kétlépcsős hitelesítés kódja helyett! Ezeket a kódokat ugyanúgy óvnia kell, mint a jelszavát."
},
"settings.account.two-factor.setup.scan": {
"message": "Olvassa be a QR-kódot az <authy-link>Authy</authy-link>, a <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> vagy bármely más kétlépcsős hitelesítési alkalmazás segítségével a folyamat megkezdéséhez."
},
"settings.applications.about": {
"message": "Rólunk"
@@ -2616,7 +2712,7 @@
"message": "Hatáskörök"
},
"settings.applications.field.url": {
"message": "URL"
"message": "Link"
},
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
@@ -2624,9 +2720,6 @@
"settings.applications.modal.header": {
"message": "Alkamazás információ"
},
"settings.applications.notification.error.title": {
"message": "Hiba történt"
},
"settings.applications.notification.icon-updated.description": {
"message": "Az alkamazásod ikonja frissítve lett."
},
+51 -15
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Buat proyek"
},
"create.project.create-server-project": {
"message": "Buat server"
},
"create.project.missing-fields-tooltip": {
"message": "Bidang hilang: {fields}"
},
@@ -1304,6 +1301,39 @@
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Pilih antara Vanila, Fabric, Forge, Quilt, dan NeoForge. Bila ia ada di Modrinth, ia dapat dijalankan di server Anda."
},
"hosting.loader.failed-to-change-version": {
"message": "Gagal mengubah versi paket mod"
},
"hosting.loader.failed-to-load-versions": {
"message": "Gagal memuat versi"
},
"hosting.loader.failed-to-reinstall": {
"message": "Gagal memasang ulang paket mod"
},
"hosting.loader.failed-to-repair": {
"message": "Gagal memperbaiki server"
},
"hosting.loader.failed-to-save-settings": {
"message": "Gagal menyinpan pengaturan pemasangan"
},
"hosting.loader.failed-to-unlink": {
"message": "Gagal melepas tautan paket mod"
},
"hosting.loader.loader-version": {
"message": "Versi {loader, select, null {pemuat} other {{loader}}}"
},
"hosting.loader.repair-started-text": {
"message": "Pemasangan server Anda telah diperbaiki."
},
"hosting.loader.repair-started-title": {
"message": "Perbaikan selesai"
},
"hosting.loader.reset-server": {
"message": "Atur ulang server"
},
"hosting.loader.reset-server-description": {
"message": "Menghapus semua data pada server Anda, termasuk dunia, mod, dan berkas konfigurasi Anda. Cadangan akan tetap ada dan dapat dipulihkan."
},
"hosting.plan.out-of-stock": {
"message": "Habis"
},
@@ -2783,6 +2813,18 @@
"search.filter.locked.server.sync": {
"message": "Sinkronkan dengan server"
},
"servers.busy.backup-creating": {
"message": "Sedang membuat cadangan"
},
"servers.busy.backup-restoring": {
"message": "Sedang memulihkan cadangan"
},
"servers.busy.installing": {
"message": "Server sedang dipasang"
},
"servers.busy.syncing-content": {
"message": "Sedang menyingkronkan konten"
},
"servers.notice.actions": {
"message": "Tindakan"
},
@@ -2813,21 +2855,12 @@
"servers.plan.large.description": {
"message": "Cocok untuk 15—25 pemain, paket mod, atau yang penggunakan mod berat."
},
"servers.plan.large.name": {
"message": "Besar"
},
"servers.plan.medium.description": {
"message": "Cocok untuk 6—15 orang pemain dan yang menggunakan beberapa mod."
},
"servers.plan.medium.name": {
"message": "Sedang"
},
"servers.plan.small.description": {
"message": "Cocok untuk 1—5 orang teman dengan beberapa mod ringan."
},
"servers.plan.small.name": {
"message": "Kecil"
},
"settings.applications.about": {
"message": "Tentang"
},
@@ -2912,9 +2945,6 @@
"settings.applications.modal.header": {
"message": "Informasi aplikasi"
},
"settings.applications.notification.error.title": {
"message": "Terjadi kesalahan"
},
"settings.applications.notification.icon-updated.description": {
"message": "Ikon aplikasi Anda telah diperbarui."
},
@@ -3152,6 +3182,12 @@
"ui.latest-news-row.view-all": {
"message": "Lihat semua berita"
},
"ui.newsletter-button.subscribe": {
"message": "Berlangganan"
},
"ui.newsletter-button.subscribed": {
"message": "Sudah berlangganan!"
},
"version.environment.none.description": {
"message": "Lingkungan untuk versi ini belum ditentukan."
},
+438 -42
View File
@@ -36,25 +36,25 @@
"message": "Mac"
},
"app-marketing.download.options-title": {
"message": "Opzioni download"
"message": "Opzioni di download"
},
"app-marketing.download.terms": {
"message": "Scaricando Modrinth App, accetti i nostri <terms-link>termini d''uso</terms-link> e l''<privacy-link>informativa sulla privacy</privacy-link>."
},
"app-marketing.download.title": {
"message": "Scarica Modrinth App (Beta)"
"message": "Scarica Modrinth App (beta)"
},
"app-marketing.download.windows": {
"message": "Windows"
},
"app-marketing.features.follow.description": {
"message": "Memorizza i contenuti che ami e ricevi aggiornamenti con un clic."
"message": "Memorizza i contenuti che ami e rimani aggiornato con un clic."
},
"app-marketing.features.follow.title": {
"message": "Segui i progetti che ami"
},
"app-marketing.features.importing.description": {
"message": "Importa i tuoi profili preferiti dal launcher che usavi prima e parti con Modrinth App in pochi secondi!"
"message": "Importa i tuoi profili dal launcher che usavi prima e sarai pronto a usare Modrinth App in pochi secondi!"
},
"app-marketing.features.importing.gdlauncher-alt": {
"message": "GDLauncher"
@@ -63,7 +63,7 @@
"message": "MultiMC"
},
"app-marketing.features.importing.title": {
"message": "Importa profili"
"message": "Importa i tuoi profili"
},
"app-marketing.features.mod-management.actions": {
"message": "Azioni"
@@ -72,7 +72,7 @@
"message": "di {author}"
},
"app-marketing.features.mod-management.description": {
"message": "Modrinth facilita la gestione di tutte le tue mod in un posto solo. Puoi installarle, disinstallarle e aggiornarle con un solo clic."
"message": "Modrinth App facilita la gestione di tutte le mod che hai scaricato in un unico posto. Puoi installarle, disinstallarle e aggiornarle con un solo clic."
},
"app-marketing.features.mod-management.installed-mods": {
"message": "Mod installate"
@@ -84,7 +84,7 @@
"message": "Cerca mod"
},
"app-marketing.features.mod-management.title": {
"message": "Gestisci mod"
"message": "Gestisci le mod scaricate"
},
"app-marketing.features.mod-management.version": {
"message": "Versione"
@@ -93,7 +93,7 @@
"message": "Gioca con le tue mod, con o senza connessione a Internet."
},
"app-marketing.features.offline.title": {
"message": "Modalità offline"
"message": "Usala anche offline"
},
"app-marketing.features.open-source.description": {
"message": "Modrinth App è del tutto open source. Leggi il codice sorgente sul nostro <github-link>GitHub</github-link>!"
@@ -108,7 +108,7 @@
"message": "% CPU"
},
"app-marketing.features.performance.description": {
"message": "Modrinth App ha prestazioni migliori di molti dei principali gestori mod, utilizzando appena 150 MB di RAM!"
"message": "Modrinth App offre prestazioni migliori rispetto a molti dei principali gestori di mod, utilizzando appena 150 MB di RAM!"
},
"app-marketing.features.performance.discord": {
"message": "Discord"
@@ -147,31 +147,31 @@
"message": "Performante"
},
"app-marketing.features.play.description": {
"message": "Usa Modrinth App per scaricare e giocare con le tue mod e i tuoi pacchetti di mod preferiti."
"message": "Usa Modrinth App per scaricare e giocare con le tue mod e pacchetti preferiti."
},
"app-marketing.features.play.title": {
"message": "Gioca con le tue mod preferite"
},
"app-marketing.features.sharing.description": {
"message": "Trova e scegli tra le migliaia di mod e pacchetti presenti qui su Modrinth."
"message": "Cerca e scegli tra le migliaia di mod e pacchetti presenti qui su Modrinth."
},
"app-marketing.features.sharing.modpack": {
"message": "Pacchetto di mod"
"message": "Pacchetto"
},
"app-marketing.features.sharing.share-button": {
"message": "Condividi"
},
"app-marketing.features.sharing.title": {
"message": "Trova, crea e condividi"
"message": "Esplora, crea e condividi"
},
"app-marketing.features.unlike-any-launcher": {
"message": "Distinta dagli altri launcher"
},
"app-marketing.features.website.description": {
"message": "Modrinth App è integrata completamente con il sito, così puoi accedere a tutti i tuoi progetti preferiti dall'app!"
"message": "Modrinth App è integrata completamente con il sito, così puoi accedere a tutti i tuoi progetti preferiti direttamente dall'app!"
},
"app-marketing.features.website.title": {
"message": "Integrata col sito"
"message": "Integrata con il sito"
},
"app-marketing.features.youve-used-before": {
"message": "che tu abbia mai usato prima"
@@ -258,7 +258,7 @@
"message": "Reimposta la password"
},
"auth.sign-in.2fa.description": {
"message": "Inserisci un codice di autenticazione a due fattori per procedere."
"message": "Inserisci il codice 2FA per continuare."
},
"auth.sign-in.2fa.label": {
"message": "Inserisci un codice 2FA"
@@ -336,7 +336,7 @@
"message": "Ricevi novità riguardanti Modrinth"
},
"auth.welcome.description": {
"message": "Fai ora parte della grandiosa community di creatori ed esploratori che già costruiscono, aggiornano e stanno sul pezzo con le fantastiche mod."
"message": "Fai ora parte della grandiosa comunità di creatori ed esploratori che già costruiscono, aggiornano e stanno sul pezzo con le fantastiche mod."
},
"auth.welcome.label.tos": {
"message": "Creando un''account, hai accettato i <terms-link>termini d''utilizzo</terms-link> e l''<privacy-policy-link>informativa sulla privacy</privacy-policy-link> di Modrinth."
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Crea progetto"
},
"create.project.create-server-project": {
"message": "Crea server"
},
"create.project.missing-fields-tooltip": {
"message": "Campi mancanti: {fields}"
},
@@ -864,7 +861,7 @@
"message": "Clicca per sapere come Modrinth gestisce i tuoi guadagni."
},
"dashboard.revenue.estimated-with-date": {
"message": "Previsti per {date}"
"message": "Previsti per il {date}"
},
"dashboard.revenue.processing": {
"message": "In elaborazione"
@@ -1191,7 +1188,7 @@
"message": "Avvia il tuo server"
},
"hosting-marketing.hero.host-with-modrinth": {
"message": "Affidati a Modrinth Hosting per il tuo prossimo server"
"message": "Affida il tuo prossimo server a Modrinth Hosting"
},
"hosting-marketing.hero.hosting-description": {
"message": "Modrinth Hosting è il modo più facile per gestire il tuo server personale per Minecraft: Java Edition. Installa e gioca alle tue mod e pacchetti preferiti, tutto tramite la piattaforma Modrinth."
@@ -1473,7 +1470,7 @@
"message": "Scopri oltre {count, number} creazioni"
},
"landing.subheading": {
"message": "Scopri, gioca e condividi contenuti per Minecraft attraverso la nostra piattaforma open source creata per la community."
"message": "Scopri, gioca e condividi contenuti per Minecraft attraverso la nostra piattaforma open source creata per la comunità."
},
"layout.action.change-theme": {
"message": "Cambia tema"
@@ -1689,7 +1686,7 @@
"message": "Esplora"
},
"layout.nav.discover-content": {
"message": "Esplora contenuti"
"message": "Esplora i contenuti"
},
"layout.nav.feature-flags": {
"message": "Flag delle funzionalità"
@@ -2817,16 +2814,16 @@
"message": "Sincronizza col server"
},
"servers.busy.backup-creating": {
"message": "Creando il backup..."
"message": "È in corso la creazione di un backup"
},
"servers.busy.backup-restoring": {
"message": "Ripristinando il backup..."
"message": "È in corso il ripristino da un backup"
},
"servers.busy.installing": {
"message": "Installando il server..."
"message": "È in corso l'installazione del server"
},
"servers.busy.syncing-content": {
"message": "Sincronizzando i contenuti..."
"message": "È in corso la sincronizzazione dei contenuti"
},
"servers.notice.actions": {
"message": "Azioni"
@@ -2858,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Ideale per 1525 giocatori, pacchetti di mod o modding intenso."
},
"servers.plan.large.name": {
"message": "Grande"
},
"servers.plan.medium.description": {
"message": "Ottimo per 615 giocatori e più mod."
},
"servers.plan.medium.name": {
"message": "Medio"
},
"servers.plan.small.description": {
"message": "Perfetto per 15 giocatori e qualche mod leggera."
},
"servers.plan.small.name": {
"message": "Piccolo"
"settings.account.button.complete-setup": {
"message": "Completa la configurazione"
},
"settings.account.data-export.action.download": {
"message": "Scarica copia"
},
"settings.account.data-export.action.generate": {
"message": "Genera copia"
},
"settings.account.data-export.action.generating": {
"message": "Generando la copia..."
},
"settings.account.data-export.description": {
"message": "Richiedi una copia dei tuoi dati personali che hai caricato su Modrinth. L'operazione richiederà alcuni minuti."
},
"settings.account.data-export.title": {
"message": "Esporta i dati"
},
"settings.account.delete.confirm.description": {
"message": "Questo **eliminerà immediatamente tutti i tuoi dati utente**, ma non i tuoi progetti. Questa azione non può essere annullata.<br><br>Se hai bisogno di assistenza col tuo account, puoi ottenere supporto sul [server Discord di Modrinth](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Elimina questo account"
},
"settings.account.delete.confirm.title": {
"message": "Vuoi davvero eliminare il tuo account?"
},
"settings.account.delete.section.action": {
"message": "Elimina account"
},
"settings.account.delete.section.description": {
"message": "Una volta eliminato l'account, non si torna indietro. Proseguendo tutti i dati associati a esso, esclusi i progetti, verranno rimossi dai nostri server."
},
"settings.account.delete.section.title": {
"message": "Elimina account"
},
"settings.account.email.action.save": {
"message": "Salva email"
},
"settings.account.email.field.label": {
"message": "Indirizzo email"
},
"settings.account.email.field.placeholder": {
"message": "Inserisci il tuo indirizzo email..."
},
"settings.account.email.modal.header.add": {
"message": "Aggiungi email"
},
"settings.account.email.modal.header.change": {
"message": "Cambia email"
},
"settings.account.email.modal.notice": {
"message": "I dati del tuo account non sono visibili pubblicamente."
},
"settings.account.password.action.remove": {
"message": "Rimuovi password"
},
"settings.account.password.action.save": {
"message": "Salva password"
},
"settings.account.password.error.mismatch": {
"message": "Le password inserite non corrispondono!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Inserisci la tua password per continuare."
},
"settings.account.password.field.confirm-current.label": {
"message": "Conferma password"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Conferma password"
},
"settings.account.password.field.confirm-new.label": {
"message": "Conferma nuova password"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Conferma nuova password"
},
"settings.account.password.field.new.label": {
"message": "Nuova password"
},
"settings.account.password.field.new.placeholder": {
"message": "Nuova password"
},
"settings.account.password.field.old.label": {
"message": "Vecchia password"
},
"settings.account.password.field.old.placeholder": {
"message": "Vecchia password"
},
"settings.account.password.modal.header.add": {
"message": "Aggiungi password"
},
"settings.account.password.modal.header.change": {
"message": "Cambia password"
},
"settings.account.password.modal.header.remove": {
"message": "Rimuovi password"
},
"settings.account.providers.action.add": {
"message": "Aggiungi"
},
"settings.account.providers.modal.header": {
"message": "Fornitori per l'autenticazione"
},
"settings.account.providers.table.actions": {
"message": "Azioni"
},
"settings.account.providers.table.provider": {
"message": "Fornitore"
},
"settings.account.security.email.action.add": {
"message": "Aggiungi email"
},
"settings.account.security.email.action.change": {
"message": "Cambia email"
},
"settings.account.security.email.description": {
"message": "Cambia la email associata col tuo account."
},
"settings.account.security.email.title": {
"message": "Email"
},
"settings.account.security.password.action.add": {
"message": "Aggiungi password"
},
"settings.account.security.password.action.change": {
"message": "Cambia password"
},
"settings.account.security.password.description.change": {
"message": "Cambia la password usata per accedere al tuo account."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Cambia o rimuovi la password usata per accedere al tuo account."
},
"settings.account.security.password.description.set": {
"message": "Imposta una password permanente per accedere al tuo account."
},
"settings.account.security.password.title": {
"message": "Password"
},
"settings.account.security.providers.action.manage": {
"message": "Gestisci fornitori"
},
"settings.account.security.providers.description": {
"message": "Aggiungi o rimuovi metodi di accesso al tuo account, inclusi GitHub, GitLab, Microsoft, Discord, Steam e Google."
},
"settings.account.security.providers.title": {
"message": "Gestisci fornitori per l'autenticazione"
},
"settings.account.security.title": {
"message": "Sicurezza dell'account"
},
"settings.account.security.two-factor.action.remove": {
"message": "Rimuovi 2FA"
},
"settings.account.security.two-factor.action.setup": {
"message": "Configura 2FA"
},
"settings.account.security.two-factor.description": {
"message": "Aggiungi un livello di sicurezza aggiuntivo nell'accesso al tuo account."
},
"settings.account.security.two-factor.title": {
"message": "Autenticazione a due fattori"
},
"settings.account.two-factor.backup.intro": {
"message": "Scarica e salva questi codici di recupero in un posto sicuro. Puoi usarli al posto del codice 2FA se perdi l'accesso al tuo dispositivo! Dovresti proteggere questi codici come la tua password."
},
"settings.account.two-factor.backup.single-use": {
"message": "Ogni codice di recupero è utilizzabile solo una volta."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "Il codice inserito è sbagliato!"
},
"settings.account.two-factor.field.code.description": {
"message": "Inserisci il codice 2FA per continuare."
},
"settings.account.two-factor.field.code.label": {
"message": "Inserisci codice 2FA"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Inserisci codice..."
},
"settings.account.two-factor.setup.intro": {
"message": "L'autenticazione a due fattori (2FA) protegge il tuo account richiedendo un dispositivo secondario per effettuare l'accesso."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Se il codice QR non funziona, inserisci manualmente questa chiave:"
},
"settings.account.two-factor.setup.scan": {
"message": "Inizia scansionando il codice QR con <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> o qualsiasi altra app per il 2FA."
},
"settings.account.two-factor.verify.description": {
"message": "Inserisci il codice generato dall'app di autenticazione per confermare l'accesso."
},
"settings.account.two-factor.verify.label": {
"message": "Codice di verifica"
},
"settings.applications.about": {
"message": "Info"
@@ -2954,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Applicazioni"
},
"settings.applications.modal.header": {
"message": "Info sull'applicazione"
},
"settings.applications.notification.error.title": {
"message": "Si è verificato un errore"
},
"settings.applications.notification.icon-updated.description": {
"message": "L'icona della tua applicazione è stata aggiornata."
},
@@ -2969,11 +3155,95 @@
"settings.applications.secret.disclaimer": {
"message": "Segnati il secret ora, perché sarà nascosto appena lasci questa pagina!"
},
"settings.authorizations.about-this-app": {
"message": "Info sull'app"
},
"settings.authorizations.by": {
"message": "da"
},
"settings.authorizations.description": {
"message": "Quando autorizzi un'applicazione, le concedi l'accesso al tuo account Modrinth. Qui puoi gestirne e controllarne l'accesso in qualsiasi momento."
},
"settings.authorizations.empty-state": {
"message": "Al momento non riusciamo a mostrare le tue app autorizzate, stiamo lavorando per risolvere il problema. Ritorna più tardi!"
},
"settings.authorizations.head-title": {
"message": "Autorizzazioni"
},
"settings.authorizations.revoke.action": {
"message": "Revoca"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Questo revocherà l'accesso dell'app al tuo account. Potrai riautorizzarla in seguito."
},
"settings.authorizations.revoke.confirm.title": {
"message": "Vuoi davvero revocare questa applicazione?"
},
"settings.billing.charges.description": {
"message": "Tutti gli addebiti passati del tuo account Modrinth saranno mostrati qui:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Prova del server Medal"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Scade: {date}"
},
"settings.billing.interval.month": {
"message": "mese"
},
"settings.billing.interval.monthly": {
"message": "mensile"
},
"settings.billing.interval.year": {
"message": "anno"
},
"settings.billing.interval.yearly": {
"message": "annuale"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Niente pubblicità su modrinth.com e nella Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Distintivo Modrinth+ sul tuo profilo"
},
"settings.billing.midas.benefits.support": {
"message": "Supporta Modrinth e i creatori direttamente"
},
"settings.billing.midas.benefits.title": {
"message": "Benefici"
},
"settings.billing.midas.save-per-year": {
"message": "Risparmia {amount}/anno passando al piano annuale!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Hai annullato l'abbonamento."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "I vantaggi rimarranno attivi fino alla fine di questo ciclo di fatturazione."
},
"settings.billing.midas.status.failed": {
"message": "La transazione non è andata a buon fine. Aggiorna il tuo metodo di pagamento."
},
"settings.billing.midas.status.open": {
"message": "Abbonamento attuale:"
},
"settings.billing.midas.status.processing": {
"message": "La transazione è in fase di elaborazione. I vantaggi si attiveranno a fine operazione."
},
"settings.billing.midas.upsell": {
"message": "Abbonati a Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Annulla abbonamento"
},
"settings.billing.modal.cancel.description": {
"message": "Questo annullerà il tuo abbonamento. Manterrai i tuoi vantaggi fino alla fine del ciclo di fatturazione in corso."
"message": "Questo annullerà il tuo abbonamento. I vantaggi rimarranno attivi fino alla fine di questo ciclo di fatturazione."
},
"settings.billing.modal.cancel.title": {
"message": "Vuoi davvero annullare il tuo abbonamento?"
@@ -2987,11 +3257,17 @@
"settings.billing.modal.delete.title": {
"message": "Vuoi davvero rimuovere questo metodo di pagamento?"
},
"settings.billing.next": {
"message": "Poi:"
},
"settings.billing.or-yearly-save": {
"message": "O {price} / anno (risparmi il {percent}%!)"
},
"settings.billing.payment_method.action.add": {
"message": "Aggiungi un metodo di pagamento"
},
"settings.billing.payment_method.action.history": {
"message": "Vedi accrediti precedenti"
"message": "Vedi addebiti precedenti"
},
"settings.billing.payment_method.action.primary": {
"message": "Rendi primario"
@@ -3008,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Metodi di pagamento"
},
"settings.billing.plan.title": {
"message": "Piano: {size}"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} CPU condivise (Supercarica fino a {bursts} CPU)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "Non è stato trovato un server collegato a questo abbonamento. Ci sono alcune possibili spiegazioni: se lo hai appena acquistato, è normale, potrebbe volerci fino a un'ora prima che sia pronto all'uso. Altrimenti, il server potrebbe essere stato sospeso. Se questo non è ciò che ti aspettavi, contatta il supporto di Modrinth fornendo le seguenti informazioni:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "ID server: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "ID Stripe: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} GB di RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Si è verificato un errore nel riabbonamento del tuo server Modrinth."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Errore nel riabbonamento"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Se il server è in sospensione, un nuovo tentativo di addebito potrebbe richiedere fino a 10 minuti."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Richiesta di riabbonamento inviata"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "Riabbonamento al server effettuato con successo"
},
"settings.billing.pyro.status.failed": {
"message": "La transazione non è andata a buon fine. Aggiorna il tuo metodo di pagamento, poi riprova."
},
"settings.billing.pyro.status.processing": {
"message": "La transazione è in fase di elaborazione. Il tuo server si attiverà a fine operazione."
},
"settings.billing.pyro.storage": {
"message": "{gb} GB di SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} GB di swap"
},
"settings.billing.pyro_subscription.description": {
"message": "Gestisci i tuoi abbonamenti legati a Modrinth Servers."
},
"settings.billing.pyro_subscription.title": {
"message": "Abbonamenti Modrinth Servers"
},
"settings.billing.renews": {
"message": "Rinnovo: {date}"
},
"settings.billing.resubscribe": {
"message": "Riabbonati"
},
"settings.billing.since": {
"message": "Dal: {date}"
},
"settings.billing.subscribe": {
"message": "Abbonati"
},
"settings.billing.subscription.description": {
"message": "Gestisci i tuoi abbonamenti Modrinth."
},
"settings.billing.subscription.title": {
"message": "Abbonamenti"
},
"settings.billing.switch.switching-to-interval": {
"message": "Passando al piano {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Passa al piano {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Il piano mensile costerà {amount} in più all'anno"
},
"settings.billing.switches-to-billing-on": {
"message": "Passerà al piano {interval} il {date}"
},
"settings.billing.update-method": {
"message": "Aggiorna metodo"
},
"settings.billing.upgrade": {
"message": "Aggiorna"
},
"settings.display.banner.developer-mode.button": {
"message": "Disattiva modalità sviluppatore"
},
@@ -3032,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Altre funzionalità"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "La modalità sviluppatore è stata disabilitata"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Modalità sviluppatore disattivata"
},
"settings.display.project-list-layouts.datapack": {
"message": "Pagina dei pacchetti di dati"
},
@@ -3041,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Pagina delle mod"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galleria"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Griglia"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Righe"
},
"settings.display.project-list-layouts.modpack": {
"message": "Pagina dei pacchetti di mod"
},
@@ -3101,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Tema"
},
"settings.head-title": {
"message": "Impostazioni di visualizzazione"
},
"settings.pats.action.create": {
"message": "Crea un token"
},
@@ -3150,7 +3525,7 @@
"message": "Ultimo utilizzo {ago}"
},
"settings.pats.token.never-used": {
"message": "Mai utilizzato"
"message": "Mai usato"
},
"settings.profile.bio.description": {
"message": "Una breve descrizione per raccontare a tutti qualcosa di te."
@@ -3161,6 +3536,9 @@
"settings.profile.description": {
"message": "Le informazioni del tuo profilo sono visibili pubblicamente su Modrinth e tramite l''<docs-link>API di Modrinth</docs-link>."
},
"settings.profile.head-title": {
"message": "Impostazioni del profilo"
},
"settings.profile.profile-info": {
"message": "Informazioni del profilo"
},
@@ -3191,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Piattaforma sconosciuta"
},
"settings.sidebar.label.account": {
"message": "Account"
},
"settings.sidebar.label.developer": {
"message": "Sviluppo"
},
"settings.sidebar.label.display": {
"message": "Visualizzazione"
},
"ui.latest-news-row.latest-news": {
"message": "Novità da Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Leggi tutte le novità"
},
"ui.newsletter-button.subscribe": {
"message": "Iscriviti"
},
"ui.newsletter-button.subscribed": {
"message": "Iscritto!"
},
"ui.newsletter-button.tooltip": {
"message": "Iscriviti alla newsletter di Modrinth"
},
"version.environment.none.description": {
"message": "L'ambiente per questa versione non è stato specificato."
},
+261 -42
View File
@@ -9,7 +9,7 @@
"message": "ユーザーが見つかりませんでした"
},
"app-marketing.download.description": {
"message": "我々のデスクトップアプリはてのプラットフォームでご利用いただけますので、ご希望のバージョンをお選びください。"
"message": "我々のデスクトップアプリはすべてのプラットフォームでご利用いただけますので、ご希望のバージョンをお選びください。"
},
"app-marketing.download.download-appimage": {
"message": "AppImageをダウンロードする"
@@ -141,7 +141,7 @@
"message": "RAM"
},
"app-marketing.features.performance.small": {
"message": ""
"message": "小さい"
},
"app-marketing.features.performance.title": {
"message": "効率的"
@@ -168,7 +168,7 @@
"message": "他のランチャーと異なる点"
},
"app-marketing.features.website.description": {
"message": "Modrinth Appはウェブサイトと完全に統合されているため、あなたはお気に入りのプロジェクトにアプリからアクセスできます!"
"message": "Modrinth Appはウェブサイトと完全に統合されているため、あなたはすべてのお気に入りのプロジェクトにアプリからアクセスできます!"
},
"app-marketing.features.website.title": {
"message": "ウェブサイトとの統合"
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "プロジェクトを作成"
},
"create.project.create-server-project": {
"message": "サーバーを作成"
},
"create.project.missing-fields-tooltip": {
"message": "不足している項目: {fields}"
},
@@ -591,7 +588,7 @@
"message": "フィルターや検索語句を調整してみてください。"
},
"dashboard.collections.label.projects-count": {
"message": "{count}件のプロジェクト"
"message": "{count} {countPlural, plural, one {プロジェクト} other {プロジェクト}}"
},
"dashboard.collections.label.search-input": {
"message": "コレクションを検索"
@@ -1194,7 +1191,7 @@
"message": "Modrinth Hostingで次のサーバーをホストしよう"
},
"hosting-marketing.hero.hosting-description": {
"message": "Modrinth Hostingは、Minecraft: Java Editionサーバーを最も簡単にホストする方法です。お気に入りのModやModパックをModrinthプラットフォーム内で、シームレスにインストールしてプレイできます。"
"message": "Modrinth Hostingは、Minecraft: Java Editionサーバーを最も簡単にホストする方法です。お気に入りのModやModパックをすべてModrinthプラットフォーム内で、シームレスにインストールしてプレイできます。"
},
"hosting-marketing.included.advanced-networking": {
"message": "高度なネットワーク管理"
@@ -1212,7 +1209,7 @@
"message": "カスタムURL"
},
"hosting-marketing.included.custom-url.description": {
"message": "カスタム<contrast>modrinth.gg</contrast>URLでサーバーを共有できます。"
"message": "カスタム <contrast>modrinth.gg</contrast> URLでサーバーを共有できます。"
},
"hosting-marketing.included.description": {
"message": "全てのサーバーにはModrinthだけが提供できるホスティング体験を提供するために設計された一連の機能が含まれています。"
@@ -1725,7 +1722,7 @@
"message": "収益"
},
"layout.nav.saved-projects": {
"message": "プロジェクトを保存"
"message": "保存されたプロジェクト"
},
"layout.nav.search": {
"message": "検索"
@@ -2076,7 +2073,7 @@
"message": "{count}件のダウンロード"
},
"profile.label.joined": {
"message": "参加しました"
"message": "参加: "
},
"profile.label.no-collections": {
"message": "このユーザーのコレクションはありません!"
@@ -2310,10 +2307,10 @@
"message": "{title}は{gameVersion}の{platform}に対応していません"
},
"project.download.search-game-versions": {
"message": "ゲームバージョンを検索..."
"message": "ゲームバージョンを検索"
},
"project.download.search-game-versions-label": {
"message": "ゲームバージョンを検索..."
"message": "ゲームバージョンを検索"
},
"project.download.select-game-version": {
"message": "ゲームバージョンを選択"
@@ -2361,7 +2358,7 @@
"message": "ライセンステキストを取得できませんでした。"
},
"project.license.loading": {
"message": "ライセンスの文を読み込み中"
"message": "ライセンステキストを読み込み中"
},
"project.license.title": {
"message": "ライセンス"
@@ -2409,7 +2406,7 @@
"message": "。"
},
"project.settings.general.tagline.placeholder.1": {
"message": "。"
"message": "例: ゲームの進行システムをネザーを中心に据えるように大幅に変更する。"
},
"project.settings.general.tagline.placeholder.2": {
"message": "例: 着用可能な建設作業着を追加する。"
@@ -2421,7 +2418,7 @@
"message": "例:ネザーポータル同士の接続方法を改善する。"
},
"project.settings.general.tagline.placeholder.5": {
"message": "例:夜間に遭遇する通常のモブに、強力なボスバージョンを追加する。"
"message": "例:夜間に遭遇する通常のMobに、強力なボスバージョンを追加する。"
},
"project.settings.general.tagline.title": {
"message": "キャッチフレーズ"
@@ -2436,10 +2433,10 @@
"message": "プロジェクトダッシュボードを見る"
},
"project.stats.downloads-label": {
"message": "件のダウンロード{count, plural, one {} other {}}"
"message": "件のダウンロード"
},
"project.stats.followers-label": {
"message": "人のフォロワー{count, plural, one {} other {}}"
"message": "人のフォロワー"
},
"project.status.archived.message": {
"message": "{title} はアーカイブされました。作者がプロジェクトのアーカイブを解除しない限り、今後 {title} に更新はありません。"
@@ -2454,7 +2451,7 @@
"message": "この{item, select, project {プロジェクト} version {バージョン} user {ユーザー} other {コンテンツ}}に関するあなたの報告はすでに投稿されています。追記がある場合は、報告に詳細を追加できます。"
},
"report.back-to-item": {
"message": "{item, select, project {project} version {version} user {user} other {content}} に戻る"
"message": "{item, select, project {プロジェクト} version {バージョン} user {ユーザー} other {コンテンツ}}に戻る"
},
"report.body.description": {
"message": "可能で関連性がある場合は、リンクと画像を追加してください。空または不十分な報告は閉じられ、無視されます。"
@@ -2652,7 +2649,7 @@
"message": "PATの書き込み"
},
"scopes.payoutsRead.description": {
"message": "支払いを確認する"
"message": "支払いデータを確認する"
},
"scopes.payoutsRead.label": {
"message": "支払い額の確認"
@@ -2727,7 +2724,7 @@
"message": "セッションを削除する"
},
"scopes.sessionDelete.label": {
"message": "セッションを削除する"
"message": "セッションを削除"
},
"scopes.sessionRead.description": {
"message": "有効なセッションを読み取る"
@@ -2856,22 +2853,202 @@
"message": "お知らせはありません"
},
"servers.plan.large.description": {
"message": "15〜25人、Modパックや重いModを導入するのに最適です。"
},
"servers.plan.large.name": {
"message": "大"
"message": "15〜25人、Modパックや重いModを導入するのに最適。"
},
"servers.plan.medium.description": {
"message": "6〜15人のプレイヤーと複数のModに最適。"
},
"servers.plan.medium.name": {
"message": "標準"
},
"servers.plan.small.description": {
"message": "いくつかの軽量なModで1〜5人に最適。"
},
"servers.plan.small.name": {
"message": ""
"settings.account.button.complete-setup": {
"message": "セットアップを完了"
},
"settings.account.data-export.action.download": {
"message": "エクスポートをダウンロード"
},
"settings.account.data-export.action.generate": {
"message": "エクスポートを生成"
},
"settings.account.data-export.action.generating": {
"message": "エクスポートを生成中…"
},
"settings.account.data-export.description": {
"message": "Modrinthにアップロードされたあなたのすべての個人データのコピーをリクエストします。これには数分かかることがあります。"
},
"settings.account.data-export.title": {
"message": "データのエクスポート"
},
"settings.account.delete.confirm.description": {
"message": "これにより**即座にあなたのすべてのユーザーデータとフォローが削除されます**。プロジェクトは削除されません。アカウントの削除は取り消せません。<br><br>アカウントについてサポートが必要な場合は、[Modrinth Discord](https://discord.modrinth.com)にてご連絡ください。"
},
"settings.account.delete.confirm.proceed": {
"message": "このアカウントを削除"
},
"settings.account.delete.confirm.title": {
"message": "本当にアカウントを削除しますか?"
},
"settings.account.delete.section.action": {
"message": "アカウントを削除"
},
"settings.account.delete.section.description": {
"message": "一度アカウントを削除すると元に戻せません。アカウントを削除すると、プロジェクトを除くすべてのデータがModrinthのサーバーから削除されます。"
},
"settings.account.delete.section.title": {
"message": "アカウントを削除"
},
"settings.account.email.action.save": {
"message": "メールアドレスを保存"
},
"settings.account.email.field.label": {
"message": "メールアドレス"
},
"settings.account.email.field.placeholder": {
"message": "メールアドレスを入力…"
},
"settings.account.email.modal.header.add": {
"message": "メールアドレスを追加"
},
"settings.account.email.modal.header.change": {
"message": "メールアドレスを変更"
},
"settings.account.email.modal.notice": {
"message": "アカウントの情報は公開されません。"
},
"settings.account.password.action.remove": {
"message": "パスワードを削除"
},
"settings.account.password.action.save": {
"message": "パスワードを保存"
},
"settings.account.password.error.mismatch": {
"message": "入力されたパスワードが一致しません!"
},
"settings.account.password.field.confirm-current.description": {
"message": "続けるにはパスワードを入力してください。"
},
"settings.account.password.field.confirm-current.label": {
"message": "パスワードの確認"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "パスワードの確認"
},
"settings.account.password.field.confirm-new.label": {
"message": "新しいパスワードの確認"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "新しいパスワードの確認"
},
"settings.account.password.field.new.label": {
"message": "新しいパスワード"
},
"settings.account.password.field.new.placeholder": {
"message": "新しいパスワード"
},
"settings.account.password.field.old.label": {
"message": "古いパスワード"
},
"settings.account.password.field.old.placeholder": {
"message": "古いパスワード"
},
"settings.account.password.modal.header.add": {
"message": "パスワードを追加"
},
"settings.account.password.modal.header.change": {
"message": "パスワードを変更"
},
"settings.account.password.modal.header.remove": {
"message": "パスワードを削除"
},
"settings.account.providers.action.add": {
"message": "追加"
},
"settings.account.providers.modal.header": {
"message": "認証プロバイダ"
},
"settings.account.providers.table.actions": {
"message": "アクション"
},
"settings.account.providers.table.provider": {
"message": "プロバイダ"
},
"settings.account.security.email.action.add": {
"message": "メールアドレスを追加"
},
"settings.account.security.email.action.change": {
"message": "メールアドレスを変更"
},
"settings.account.security.email.description": {
"message": "アカウントに関連づけられたメールアドレスを変更します。"
},
"settings.account.security.email.title": {
"message": "メールドレス"
},
"settings.account.security.password.action.add": {
"message": "パスワードを追加"
},
"settings.account.security.password.action.change": {
"message": "パスワードを変更"
},
"settings.account.security.password.description.change": {
"message": "アカウントにログインするにはパスワードを変更してください。"
},
"settings.account.security.password.description.change-or-remove": {
"message": "アカウントにログインするにはパスワードを変更または削除してください。"
},
"settings.account.security.password.description.set": {
"message": "アカウントにログインするためのパスワードを設定してください。"
},
"settings.account.security.password.title": {
"message": "パスワード"
},
"settings.account.security.providers.action.manage": {
"message": "プロバイダを管理"
},
"settings.account.security.providers.description": {
"message": "GitHub、GitLab、Microsoft、Discord、Steam、Googleなどのログイン方法をアカウントに追加、または削除できます。"
},
"settings.account.security.providers.title": {
"message": "認証プロバイダを管理"
},
"settings.account.security.title": {
"message": "アカウントのセキュリティ"
},
"settings.account.security.two-factor.action.remove": {
"message": "2FAを削除"
},
"settings.account.security.two-factor.action.setup": {
"message": "2FAを設定"
},
"settings.account.security.two-factor.description": {
"message": "ログイン時のアカウントのセキュリティをさらに強化します。"
},
"settings.account.security.two-factor.title": {
"message": "2段階認証"
},
"settings.account.two-factor.backup.intro": {
"message": "バックアップコードをダウンロードし、安全な場所に保存してください。デバイスにアクセスできなくなった場合、2段階認証コードの代わりにこれらのコードを使用できます。パスワードと同様に、厳重に管理してください。"
},
"settings.account.two-factor.backup.single-use": {
"message": "バックアップコードは1回のみ使用可能です。"
},
"settings.account.two-factor.error.incorrect-code": {
"message": "入力されたコードが正しくありません。"
},
"settings.account.two-factor.field.code.description": {
"message": "続行するには二要素認証コードを入力してください。"
},
"settings.account.two-factor.field.code.label": {
"message": "二要素認証コードを入力"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "コードを入力…"
},
"settings.account.two-factor.setup.intro": {
"message": "2段階認証では、サインイン時にあなたの別のデバイスへのアクセスを求めることで、アカウントの安全性を高めます。"
},
"settings.account.two-factor.setup.manual-secret": {
"message": "QRコードが読み取れない場合は、コードを手動で入力してください:"
},
"settings.applications.about": {
"message": "概要"
@@ -2957,9 +3134,6 @@
"settings.applications.modal.header": {
"message": "アプリケーション情報"
},
"settings.applications.notification.error.title": {
"message": "エラーが発生しました"
},
"settings.applications.notification.icon-updated.description": {
"message": "アプリケーションのアイコンが更新されました。"
},
@@ -2987,6 +3161,12 @@
"settings.billing.modal.delete.title": {
"message": "このお支払い方法を削除してもよろしいですか?"
},
"settings.billing.next": {
"message": "次:"
},
"settings.billing.or-yearly-save": {
"message": "または{price} / 年 ({percent}%お得)"
},
"settings.billing.payment_method.action.add": {
"message": "支払い方法を追加する"
},
@@ -3003,11 +3183,41 @@
"message": "お支払い方法が設定されていません。"
},
"settings.billing.payment_method.primary": {
"message": "プライマリ"
"message": "メイン"
},
"settings.billing.payment_method.title": {
"message": "支払い方法"
},
"settings.billing.plan.title": {
"message": "{size}プラン"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared}個の共有されたCPU ({bursts}個のCPUに増加)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "このサブスクリプションに対応するサーバーが見つかりませんでした。これにはいくつか説明があります。あなたがサーバーを購入してすぐの場合、これは通常であり、サーバーが提供されるまで長くて1時間かかります。しばらく前にサーバーを購入していた場合はおそらくそれ以来サーバーが停止されています。これが期待したものではない場合は、以下の情報と共にModrinth Supportにお問い合わせください。"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "サーバーID: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "Stripe ID: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb}GB RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Modrinthサーバーの再登録中にエラーが発生しました。"
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "再登録エラー"
},
"settings.billing.pyro_subscription.description": {
"message": "Modrinth Server のサブスクリプションを管理する。"
},
@@ -3039,16 +3249,16 @@
"message": "このデバイスでプロジェクト一覧を表示する各ページのレイアウトをお選びください。"
},
"settings.display.project-list-layouts.mod": {
"message": ""
"message": "Modページ"
},
"settings.display.project-list-layouts.modpack": {
"message": "Modpacks"
"message": "Modパックページ"
},
"settings.display.project-list-layouts.plugin": {
"message": "Plugins"
"message": "プラグインページ"
},
"settings.display.project-list-layouts.resourcepack": {
"message": "Resource Packs"
"message": "リソースパックページ"
},
"settings.display.project-list-layouts.server": {
"message": "サーバーページ"
@@ -3060,13 +3270,13 @@
"message": "プロジェクト一覧のレイアウト"
},
"settings.display.project-list-layouts.user": {
"message": "ユーザープロフィール"
"message": "ユーザープロフィールページ"
},
"settings.display.project-list.layouts.collection": {
"message": "コレクション"
},
"settings.display.sidebar.advanced-rendering.description": {
"message": "ぼかし効果などの高度なレンダリングを有効にします。グラフィック アクセラレーションが使用できない場合は、パフォーマンスが低下する可能性があります。"
"message": "ぼかし効果などの高度なレンダリングを有効にします。グラフィックアクセラレーションが使用できない場合は、パフォーマンスが低下する可能性があります。"
},
"settings.display.sidebar.advanced-rendering.title": {
"message": "高度なレンダリング"
@@ -3117,7 +3327,7 @@
"message": "名前"
},
"settings.pats.modal.create.name.placeholder": {
"message": "PATの名前を入力..."
"message": "PATの名前を入力"
},
"settings.pats.modal.create.title": {
"message": "個人用アクセストークンを作成"
@@ -3197,6 +3407,15 @@
"ui.latest-news-row.view-all": {
"message": "すべてのニュースを見る"
},
"ui.newsletter-button.subscribe": {
"message": "登録"
},
"ui.newsletter-button.subscribed": {
"message": "登録しました!"
},
"ui.newsletter-button.tooltip": {
"message": "Modrinthのニュースレターに登録する"
},
"version.environment.none.description": {
"message": "このバージョンの環境設定は未指定です。"
},
@@ -3204,7 +3423,7 @@
"message": "環境設定が指定されていません"
},
"version.environment.unknown.description": {
"message": "環境: {environment} が認識されていません。"
"message": "環境: {environment}が認識されていません。"
},
"version.environment.unknown.title": {
"message": "不明な環境"
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "프로젝트 만들기"
},
"create.project.create-server-project": {
"message": "서버 생성"
},
"create.project.missing-fields-tooltip": {
"message": "누락된 필드: {fields}"
},
@@ -2813,21 +2810,12 @@
"servers.plan.large.description": {
"message": "15–25명의 플레이어, 모드팩 또는 무거운 모드에 적합합니다."
},
"servers.plan.large.name": {
"message": "대형"
},
"servers.plan.medium.description": {
"message": "6–15명의 플레이어와 여러 개의 모드에 적합합니다."
},
"servers.plan.medium.name": {
"message": "중형"
},
"servers.plan.small.description": {
"message": "1–5명의 친구와 적은 수의 가벼운 모드에 적합합니다."
},
"servers.plan.small.name": {
"message": "소형"
},
"settings.applications.about": {
"message": "앱 정보"
},
@@ -2912,9 +2900,6 @@
"settings.applications.modal.header": {
"message": "신청정보"
},
"settings.applications.notification.error.title": {
"message": "오류가 발생했습니다"
},
"settings.applications.notification.icon-updated.description": {
"message": "앱 아이콘이 업데이트되었습니다."
},
+420 -24
View File
@@ -366,7 +366,7 @@
"message": "Nyahikut projek"
},
"collection.delete-modal.description": {
"message": "Ini akan memadamkan koleksi ini selama-lamanya. Tindakan ini tidak boleh dibuat asal."
"message": "Ini akan memadamkan koleksi ini selama-lamanya. Tindakan ini tidak boleh dibatalkan."
},
"collection.delete-modal.title": {
"message": "Adakah anda pasti mahu memadamkan koleksi ini?"
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Cipta projek"
},
"create.project.create-server-project": {
"message": "Cipta sebuah pelayan"
},
"create.project.missing-fields-tooltip": {
"message": "Medan yang hilang: {fields}"
},
@@ -558,7 +555,7 @@
"message": "Cipta pautan afiliasi"
},
"dashboard.affiliate-links.error.title": {
"message": "Ralat semasa memuatkan pautan afiliasi"
"message": "Ralat semasa memuat pautan afiliasi"
},
"dashboard.affiliate-links.header": {
"message": "Pautan afiliasi anda"
@@ -684,7 +681,7 @@
"message": "Tidak dapat mengambil kaedah pembayaran yang tersedia. Sila cuba lagi kemudian."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Gagal memuatkan kaedah pembayaran"
"message": "Gagal memuat kaedah pembayaran"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Rantau"
@@ -1386,7 +1383,7 @@
"message": "Pengurusan Pasukan"
},
"landing.error.failedToLoadRandomProjects": {
"message": "Gagal memuatkan projek-projek rawak :("
"message": "Gagal memuat projek-projek rawak :("
},
"landing.feature.follow.description": {
"message": "Dapatkan makluman setiap kali projek kegemaran anda dikemas kini dan elakkan daripada ketinggalan."
@@ -2346,7 +2343,7 @@
"message": "Sila semak metadata persekitaran"
},
"project.error.loading": {
"message": "Ralat memuatkan data projek{message}"
"message": "Ralat semasa memuat data projek{message}"
},
"project.error.page-not-found": {
"message": "Halaman tidak dapat dijumpai"
@@ -2361,7 +2358,7 @@
"message": "Teks lesen tidak dapat diambil."
},
"project.license.loading": {
"message": "Sedang memuatkan teks lesen..."
"message": "Sedang memuat teks lesen..."
},
"project.license.title": {
"message": "Lesen"
@@ -2858,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Sesuai untuk 1525 pemain, pek mod atau pengubahsuaian yang berat."
},
"servers.plan.large.name": {
"message": "Besar"
},
"servers.plan.medium.description": {
"message": "Bagus untuk 615 pemain dan berbilang mod."
},
"servers.plan.medium.name": {
"message": "Sederhana"
},
"servers.plan.small.description": {
"message": "Sesuai untuk 15 rakan dengan beberapa mod ringan."
},
"servers.plan.small.name": {
"message": "Kecil"
"settings.account.button.complete-setup": {
"message": "Lengkapkan persediaan"
},
"settings.account.data-export.action.download": {
"message": "Muat turun eksport"
},
"settings.account.data-export.action.generate": {
"message": "Jana eksport"
},
"settings.account.data-export.action.generating": {
"message": "Sedang menjana eksport..."
},
"settings.account.data-export.description": {
"message": "Minta salinan semua data peribadi anda yang telah dimuat naik ke Modrinth. Ini mungkin mengambil masa beberapa minit untuk diselesaikan."
},
"settings.account.data-export.title": {
"message": "Pengeksportan data"
},
"settings.account.delete.confirm.description": {
"message": "Ini akan **dengan segera memadamkan semua projek** dan ikutan anda. Ini tidak akan memadamkan projek anda. Pemadaman akaun anda tidak boleh dibatalkan.<br><br>Jika anda memerlukan bantuan dengan akaun anda, dapatkan sokongan di [Discord Modrinth](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Padam akaun ini"
},
"settings.account.delete.confirm.title": {
"message": "Adakah anda pasti mahu memadamkan akaun anda?"
},
"settings.account.delete.section.action": {
"message": "Padam akaun"
},
"settings.account.delete.section.description": {
"message": "Setelah anda memadamkan akaun anda, tidak ada jalan untuk kembali. Pemadaman akaun anda akan menghapuskan semua data yang dilampirkan, kecuali projek, daripada pelayan kami."
},
"settings.account.delete.section.title": {
"message": "Padam akaun"
},
"settings.account.email.action.save": {
"message": "Simpan e-mel"
},
"settings.account.email.field.label": {
"message": "Alamat e-mel"
},
"settings.account.email.field.placeholder": {
"message": "Masukkan alamat e-mel anda..."
},
"settings.account.email.modal.header.add": {
"message": "Tambah e-mel"
},
"settings.account.email.modal.header.change": {
"message": "Tukar e-mel"
},
"settings.account.email.modal.notice": {
"message": "Maklumat akaun anda tidak dipaparkan secara terbuka."
},
"settings.account.password.action.remove": {
"message": "Alih keluar kata laluan"
},
"settings.account.password.action.save": {
"message": "Simpan kata laluan"
},
"settings.account.password.error.mismatch": {
"message": "Kata laluan input tidak sepadan!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Sila masukkan kata laluan anda untuk meneruskan."
},
"settings.account.password.field.confirm-current.label": {
"message": "Sahkan kata laluan"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Sahkan kata laluan"
},
"settings.account.password.field.confirm-new.label": {
"message": "Sahkan kata laluan baharu"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Sahkan kata laluan baharu"
},
"settings.account.password.field.new.label": {
"message": "Kata laluan baharu"
},
"settings.account.password.field.new.placeholder": {
"message": "Kata laluan baharu"
},
"settings.account.password.field.old.label": {
"message": "Kata laluan lama"
},
"settings.account.password.field.old.placeholder": {
"message": "Kata laluan lama"
},
"settings.account.password.modal.header.add": {
"message": "Tambah kata laluan"
},
"settings.account.password.modal.header.change": {
"message": "Tukar kata laluan"
},
"settings.account.password.modal.header.remove": {
"message": "Alih keluar kata laluan"
},
"settings.account.providers.action.add": {
"message": "Tambah"
},
"settings.account.providers.modal.header": {
"message": "Penyedia pengesahan"
},
"settings.account.providers.table.actions": {
"message": "Tindakan"
},
"settings.account.providers.table.provider": {
"message": "Penyedia"
},
"settings.account.security.email.action.add": {
"message": "Tambah e-mel"
},
"settings.account.security.email.action.change": {
"message": "Tukar e-mel"
},
"settings.account.security.email.description": {
"message": "Tukar e-mel yang dikaitkan dengan akaun anda."
},
"settings.account.security.email.title": {
"message": "E-mel"
},
"settings.account.security.password.action.add": {
"message": "Tambah kata laluan"
},
"settings.account.security.password.action.change": {
"message": "Tukar kata laluan"
},
"settings.account.security.password.description.change": {
"message": "Tukar kata laluan yang digunakan untuk log masuk ke akaun anda."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Tukar atau alih keluar kata laluan yang digunakan untuk log masuk ke akaun anda."
},
"settings.account.security.password.description.set": {
"message": "Tetapkan kata laluan kekal untuk log masuk ke akaun anda."
},
"settings.account.security.password.title": {
"message": "Kata laluan"
},
"settings.account.security.providers.action.manage": {
"message": "Urus penyedia"
},
"settings.account.security.providers.description": {
"message": "Tambah atau alih keluar kaedah daftar masuk daripada akaun anda, termasuk GitHub, GitLab, Microsoft, Discord, Steam dan Google."
},
"settings.account.security.providers.title": {
"message": "Urus penyedia pengesahan"
},
"settings.account.security.title": {
"message": "Keselamatan akaun"
},
"settings.account.security.two-factor.action.remove": {
"message": "Alih keluar 2FA"
},
"settings.account.security.two-factor.action.setup": {
"message": "Sediakan 2FA"
},
"settings.account.security.two-factor.description": {
"message": "Tambahkan lapisan keselamatan tambahan pada akaun anda semasa log masuk."
},
"settings.account.security.two-factor.title": {
"message": "Pengesahan dua faktor (2FA)"
},
"settings.account.two-factor.backup.intro": {
"message": "Muat turun dan simpan kod sandaran ini di tempat yang selamat. Anda boleh menggunakannya sebagai ganti kod 2FA jika anda kehilangan akses kepada peranti anda! Anda harus melindungi kod ini seperti kata laluan anda."
},
"settings.account.two-factor.backup.single-use": {
"message": "Kod sandaran hanya boleh digunakan sekali sahaja."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "Kod yang dimasukkan salah!"
},
"settings.account.two-factor.field.code.description": {
"message": "Sila masukkan kod dua faktor untuk meneruskan."
},
"settings.account.two-factor.field.code.label": {
"message": "Masukkan kod dua faktor"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Masukkan kod..."
},
"settings.account.two-factor.setup.intro": {
"message": "Pengesahan dua faktor memastikan akaun anda selamat dengan memerlukan akses kepada peranti kedua untuk log masuk."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Jika kod QR tidak dapat diimbas, anda boleh memasukkan rahsia secara manual:"
},
"settings.account.two-factor.setup.scan": {
"message": "Imbas kod QR dengan <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> atau mana-mana aplikasi 2FA lain untuk mulakan."
},
"settings.account.two-factor.verify.description": {
"message": "Masukkan kod sekali pakai daripada pengesah untuk mengesahkan akses."
},
"settings.account.two-factor.verify.label": {
"message": "Sahkan kod"
},
"settings.applications.about": {
"message": "Tentang"
@@ -2954,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Aplikasi"
},
"settings.applications.modal.header": {
"message": "Maklumat aplikasi"
},
"settings.applications.notification.error.title": {
"message": "Sebuah ralat telah berlaku"
},
"settings.applications.notification.icon-updated.description": {
"message": "Ikon aplikasi anda telah dikemas kini."
},
@@ -2969,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "Simpan secret anda sekarang, ia akan disembunyikan selepas anda meninggalkan laman ini!"
},
"settings.authorizations.about-this-app": {
"message": "Mengenai aplikasi ini"
},
"settings.authorizations.by": {
"message": "oleh"
},
"settings.authorizations.description": {
"message": "Apabila anda membenarkan aplikasi ini dengan akaun Modrinth anda, anda memberikannya akses kepada akaun anda. Anda boleh mengurus dan menyemak akses kepada akaun anda di sini pada bila-bila masa."
},
"settings.authorizations.empty-state": {
"message": "Kami tidak dapat memaparkan aplikasi yang dibenarkan oleh anda pada masa ini, kami sedang berusaha untuk memperbaikinya. Sila kunjungi halaman ini pada tarikh yang akan datang!"
},
"settings.authorizations.head-title": {
"message": "Kebenaran"
},
"settings.authorizations.revoke.action": {
"message": "Batalkan"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Ini akan membatalkan akses aplikasi ini ke akaun anda. Anda sentiasa boleh membenarkannya semula kemudian."
},
"settings.authorizations.revoke.confirm.title": {
"message": "Adakah anda pasti mahu membatalkan aplikasi ini?"
},
"settings.billing.charges.description": {
"message": "Semua caj anda ke akaun Modrinth anda yang lepas akan disenaraikan di sini:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Percubaan Pelayan Medal"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Akan tamat tempoh {date}"
},
"settings.billing.interval.month": {
"message": "bulan"
},
"settings.billing.interval.monthly": {
"message": "bulanan"
},
"settings.billing.interval.year": {
"message": "tahun"
},
"settings.billing.interval.yearly": {
"message": "tahunan"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Pelayaran bebas iklan di modrinth.com dan Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Lencana Modrinth+ pada profil anda"
},
"settings.billing.midas.benefits.support": {
"message": "Sokong Modrinth dan pencipta secara langsung"
},
"settings.billing.midas.benefits.title": {
"message": "Faedah"
},
"settings.billing.midas.save-per-year": {
"message": "Jimat {amount}/tahun dengan bertukar kepada pengebilan tahunan!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Anda telah membatalkan langganan anda."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "Anda akan mengekalkan faedah anda sehingga akhir kitaran pengebilan semasa."
},
"settings.billing.midas.status.failed": {
"message": "Pembayaran langganan anda gagal. Sila kemas kini kaedah pembayaran anda."
},
"settings.billing.midas.status.open": {
"message": "Anda sedang melanggan:"
},
"settings.billing.midas.status.processing": {
"message": "Pembayaran anda sedang diproses. Manfaat akan diaktifkan setelah pembayaran selesai."
},
"settings.billing.midas.upsell": {
"message": "Jadilah pelanggan Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Batalkan langganan"
},
@@ -2987,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "Adakah anda pasti mahu mengalih keluar kaedah pembayaran ini?"
},
"settings.billing.next": {
"message": "Seterusnya:"
},
"settings.billing.or-yearly-save": {
"message": "Atau {price} / tahun (jimat {percent}%)!"
},
"settings.billing.payment_method.action.add": {
"message": "Tambah kaedah pembayaran"
},
@@ -2997,7 +3273,7 @@
"message": "Jadikan utama"
},
"settings.billing.payment_method.card_expiry": {
"message": "Luput {month}/{year}"
"message": "Tamat tempoh {month}/{year}"
},
"settings.billing.payment_method.none": {
"message": "Anda belum menambah sebarang kaedah pembayaran."
@@ -3008,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Kaedah pembayaran"
},
"settings.billing.plan.title": {
"message": "Pelan {size}"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} CPU Kongsi (Boleh memecut sehingga {bursts} CPU)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "Pelayan yang dipautkan tidak dapat ditemui untuk langganan ini. Terdapat beberapa kemungkinan untuk menjelaskan perkara ini. Jika anda baru sahaja membeli pelayan anda, ini adalah perkara biasa. Ia mungkin mengambil masa sehingga sejam untuk pelayan anda disediakan. Jika tidak, jika anda membeli pelayan ini beberapa ketika dahulu, ia mungkin telah digantung. Jika ini bukan yang anda jangkakan, sila hubungi Sokongan Modrinth dengan maklumat berikut:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "ID Pelayan: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "ID Stripe: {id}"
},
"settings.billing.pyro.ram": {
"message": "RAM {gb} GB"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Sebuah ralat telah berlaku semasa melanggan semula pelayan Modrinth anda."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Ralat semasa melanggan semula"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Jika pelayan sedang digantung, percubaan pengecasan lain mungkin mengambil masa sehingga 10 minit."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Permintaan langganan semula telah dihantar"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "Langganan pelayan berjaya dilanggan semula"
},
"settings.billing.pyro.status.failed": {
"message": "Pembayaran langganan anda gagal. Sila kemas kini kaedah pembayaran anda, kemudian langgan semula."
},
"settings.billing.pyro.status.processing": {
"message": "Pembayaran anda sedang diproses. Pelayan anda akan diaktifkan setelah pembayaran selesai."
},
"settings.billing.pyro.storage": {
"message": "SSD {gb} GB"
},
"settings.billing.pyro.swap": {
"message": "Swap {gb} GB"
},
"settings.billing.pyro_subscription.description": {
"message": "Urus langganan Modrinth Servers anda."
},
"settings.billing.pyro_subscription.title": {
"message": "Langganan Modrinth Servers"
},
"settings.billing.renews": {
"message": "Diperbaharui {date}"
},
"settings.billing.resubscribe": {
"message": "Langgan semula"
},
"settings.billing.since": {
"message": "Sejak {date}"
},
"settings.billing.subscribe": {
"message": "Langgan"
},
"settings.billing.subscription.description": {
"message": "Urus langganan Modrinth anda."
},
"settings.billing.subscription.title": {
"message": "Langganan"
},
"settings.billing.switch.switching-to-interval": {
"message": "Bertukar ke {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Tukar ke {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Bil bulanan akan dikenakan bayaran tambahan sebanyak {amount} setahun"
},
"settings.billing.switches-to-billing-on": {
"message": "Akan beralih kepada pengebilan {interval} pada {date}"
},
"settings.billing.update-method": {
"message": "Kaedah kemas kini"
},
"settings.billing.upgrade": {
"message": "Naik Taraf"
},
"settings.display.banner.developer-mode.button": {
"message": "Nyahaktifkan mod pembangun"
},
@@ -3032,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Togol ciri-ciri"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "Mod pembangun telah dinyahdayakan"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Mod pembangun dinyahaktifkan"
},
"settings.display.project-list-layouts.datapack": {
"message": "Halaman Pek Data"
},
@@ -3041,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Halaman Mod"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galeri"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Grid"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Barisan"
},
"settings.display.project-list-layouts.modpack": {
"message": "Halaman Pek Mod"
},
@@ -3101,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Tema warna"
},
"settings.head-title": {
"message": "Tetapan paparan"
},
"settings.pats.action.create": {
"message": "Cipta PAT"
},
@@ -3111,7 +3486,7 @@
"message": "Cipta PAT"
},
"settings.pats.modal.create.expires.label": {
"message": "Luput"
"message": "Tamat tempoh"
},
"settings.pats.modal.create.name.label": {
"message": "Nama"
@@ -3141,10 +3516,10 @@
"message": "Batalkan token"
},
"settings.pats.token.expired-ago": {
"message": "Telah luput {ago}"
"message": "Telah tamat tempoh {ago}"
},
"settings.pats.token.expires-in": {
"message": "Akan luput dalam {inTime}"
"message": "Akan tamat tempoh {inTime}"
},
"settings.pats.token.last-used": {
"message": "Kali terakhir digunakan {ago}"
@@ -3161,6 +3536,9 @@
"settings.profile.description": {
"message": "Maklumat profil anda boleh dilihat secara terbuka pada Modrinth dan melalui <docs-link>API Modrinth</docs-link>."
},
"settings.profile.head-title": {
"message": "Tetapan profil"
},
"settings.profile.profile-info": {
"message": "Maklumat profil"
},
@@ -3191,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Platform tidak diketahui"
},
"settings.sidebar.label.account": {
"message": "Akaun"
},
"settings.sidebar.label.developer": {
"message": "Pembangun"
},
"settings.sidebar.label.display": {
"message": "Paparan"
},
"ui.latest-news-row.latest-news": {
"message": "Berita terkini dari Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Lihat semua berita"
},
"ui.newsletter-button.subscribe": {
"message": "Langgan"
},
"ui.newsletter-button.subscribed": {
"message": "Sudah melanggan!"
},
"ui.newsletter-button.tooltip": {
"message": "Langgan surat berita Modrinth"
},
"version.environment.none.description": {
"message": "Persekitaran untuk versi ini belum dinyatakan."
},
+38 -14
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Project aanmaken"
},
"create.project.create-server-project": {
"message": "Maak server"
},
"create.project.missing-fields-tooltip": {
"message": "Missende velden: {fields}"
},
@@ -2816,20 +2813,50 @@
"servers.plan.large.description": {
"message": "Ideaal voor 15-25 spelers, modpacks of zwaar modificeren"
},
"servers.plan.large.name": {
"message": "Groot"
},
"servers.plan.medium.description": {
"message": "Goed voor 6-15 spelers en meerdere mods"
},
"servers.plan.medium.name": {
"message": "Medium"
},
"servers.plan.small.description": {
"message": "Perfect voor 1-5 vrienden en een paar lichte mods"
},
"servers.plan.small.name": {
"message": "Klein"
"settings.account.password.action.remove": {
"message": "Wachtwoord verwijderen"
},
"settings.account.password.action.save": {
"message": "Wachtwoord opslaan"
},
"settings.account.password.field.new.label": {
"message": "Nieuw wachtwoord"
},
"settings.account.password.field.new.placeholder": {
"message": "Nieww wachtwoord"
},
"settings.account.password.field.old.label": {
"message": "Oud wachtwoord"
},
"settings.account.password.field.old.placeholder": {
"message": "Oud wachtwoord"
},
"settings.account.password.modal.header.add": {
"message": "Wachtwoord toevoegen"
},
"settings.account.password.modal.header.change": {
"message": "Wachtwoord veranderen"
},
"settings.account.password.modal.header.remove": {
"message": "Wachtwoord verwijderen"
},
"settings.account.providers.action.add": {
"message": "Toevoegen"
},
"settings.account.providers.table.actions": {
"message": "Acties"
},
"settings.account.security.password.action.add": {
"message": "Wachtwoord toevoegen"
},
"settings.account.security.password.title": {
"message": "Wachtwoord"
},
"settings.applications.about": {
"message": "Over"
@@ -2915,9 +2942,6 @@
"settings.applications.modal.header": {
"message": "Project informatie"
},
"settings.applications.notification.error.title": {
"message": "Er is een fout opgetreden"
},
"settings.applications.notification.icon-updated.description": {
"message": "Het icoon van jouw project is bijgewerkt."
},
@@ -2720,21 +2720,12 @@
"servers.plan.large.description": {
"message": "Ideelt for 15 - 25 spillere, modpacks eller tung modding."
},
"servers.plan.large.name": {
"message": "Stor"
},
"servers.plan.medium.description": {
"message": "Flott for 6 - 15 spillere og flere mods."
},
"servers.plan.medium.name": {
"message": "Medium"
},
"servers.plan.small.description": {
"message": "Perfekt for 1 - 5 venner med noen få lette mods."
},
"servers.plan.small.name": {
"message": "Lite"
},
"settings.applications.about": {
"message": "Om"
},
@@ -2813,9 +2804,6 @@
"settings.applications.modal.header": {
"message": "Applikasjonsinformasjon"
},
"settings.applications.notification.error.title": {
"message": "Det har oppstått en feil"
},
"settings.applications.notification.icon-updated.description": {
"message": "Applikasjonsikonet ditt har blitt oppdatert."
},
+17 -14
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Utwórz projekt"
},
"create.project.create-server-project": {
"message": "Utwórz serwer"
},
"create.project.missing-fields-tooltip": {
"message": "Brakujące pola: {fields}"
},
@@ -2813,20 +2810,29 @@
"servers.plan.large.description": {
"message": "Idealny dla 1525 graczy, paczek modów lub dużej ilości modów."
},
"servers.plan.large.name": {
"message": "Duży"
},
"servers.plan.medium.description": {
"message": "Świetny wybór dla 615 graczy i wielu modów."
},
"servers.plan.medium.name": {
"message": "Średni"
},
"servers.plan.small.description": {
"message": "Idealny dla 15 przyjaciół z kilkoma lekkimi modami."
},
"servers.plan.small.name": {
"message": "Mały"
"settings.account.password.field.confirm-current.label": {
"message": "Potwierdź hasło"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Potwierdź hasło"
},
"settings.account.password.field.confirm-new.label": {
"message": "Potwierdź nowe hasło"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Potwierdź nowe hasło"
},
"settings.account.password.field.new.label": {
"message": "Nowe hasło"
},
"settings.account.password.field.new.placeholder": {
"message": "Nowe hasło"
},
"settings.applications.about": {
"message": "O nas"
@@ -2912,9 +2918,6 @@
"settings.applications.modal.header": {
"message": "Informacje o aplikacje"
},
"settings.applications.notification.error.title": {
"message": "Wystąpił błąd"
},
"settings.applications.notification.icon-updated.description": {
"message": "Ikona twej aplikacji została zaktualizowana."
},
+411 -15
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Criar projeto"
},
"create.project.create-server-project": {
"message": "Criar servidor"
},
"create.project.missing-fields-tooltip": {
"message": "Campos ausentes: {fields}"
},
@@ -1302,7 +1299,7 @@
"message": "Todos os seus mods favoritos"
},
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Escolha entre Vanilla, Fabric, Forge, Quilt e NeoForge. Se estiver no Modrinth, pode ser executado no seu servidor."
"message": "Escolha entre Jogo padrão, Fabric, Forge, Quilt e NeoForge. Se estiver no Modrinth, pode ser executado no seu servidor."
},
"hosting.loader.failed-to-change-version": {
"message": "Falha ao alterar a versão do pacote de mods"
@@ -2858,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Ideal para 1525 jogadores, pacotes de mods ou mods pesados."
},
"servers.plan.large.name": {
"message": "Grande"
},
"servers.plan.medium.description": {
"message": "Bom para 615 jogadores e vários mods."
},
"servers.plan.medium.name": {
"message": "Médio"
},
"servers.plan.small.description": {
"message": "Perfeito para 15 amigos e alguns mods leves."
},
"servers.plan.small.name": {
"message": "Pequeno"
"settings.account.button.complete-setup": {
"message": "Terminar configuração"
},
"settings.account.data-export.action.download": {
"message": "Baixar exportação"
},
"settings.account.data-export.action.generate": {
"message": "Gerar exportação"
},
"settings.account.data-export.action.generating": {
"message": "Gerando exportação..."
},
"settings.account.data-export.description": {
"message": "Solicite uma cópia de todos os seus dados pessoais que você enviou para o Modrinth. Isso pode levar vários minutos para ser concluído."
},
"settings.account.data-export.title": {
"message": "Exportação de dados"
},
"settings.account.delete.confirm.description": {
"message": "Isso irá **excluir imediatamente todos os seus dados de usuário e seguidores**. Isso não excluirá seus projetos. A exclusão da sua conta não pode ser desfeita.<br><br>Se você precisar de ajuda com sua conta, obtenha suporte no [Discord do Modrinth](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Excluir esta conta"
},
"settings.account.delete.confirm.title": {
"message": "Você tem certeza que deseja excluir sua conta?"
},
"settings.account.delete.section.action": {
"message": "Excluir conta"
},
"settings.account.delete.section.description": {
"message": "Depois de excluir sua conta, não tem pé atrás. Excluir sua conta irá remover todos os seus dados anexados, excluindo projetos, de nossos servidores."
},
"settings.account.delete.section.title": {
"message": "Excluir conta"
},
"settings.account.email.action.save": {
"message": "Salvar e-mail"
},
"settings.account.email.field.label": {
"message": "Endereço de e-mail"
},
"settings.account.email.field.placeholder": {
"message": "Digitar seu endereço de e-mail..."
},
"settings.account.email.modal.header.add": {
"message": "Adicionar e-mail"
},
"settings.account.email.modal.header.change": {
"message": "Alterar e-mail"
},
"settings.account.email.modal.notice": {
"message": "As informações da sua conta não são exibidas publicamente."
},
"settings.account.password.action.remove": {
"message": "Remover senha"
},
"settings.account.password.action.save": {
"message": "Salvar senha"
},
"settings.account.password.error.mismatch": {
"message": "As senhas digitadas não coincidem!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Por favor, insira sua senha para prosseguir."
},
"settings.account.password.field.confirm-current.label": {
"message": "Confirmar senha"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Confirmar senha"
},
"settings.account.password.field.confirm-new.label": {
"message": "Confirmar nova senha"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Confirmar nova senha"
},
"settings.account.password.field.new.label": {
"message": "Nova senha"
},
"settings.account.password.field.new.placeholder": {
"message": "Nova senha"
},
"settings.account.password.field.old.label": {
"message": "Senha antiga"
},
"settings.account.password.field.old.placeholder": {
"message": "Senha antiga"
},
"settings.account.password.modal.header.add": {
"message": "Adicionar senha"
},
"settings.account.password.modal.header.change": {
"message": "Alterar senha"
},
"settings.account.password.modal.header.remove": {
"message": "Remover senha"
},
"settings.account.providers.action.add": {
"message": "Adicionar"
},
"settings.account.providers.modal.header": {
"message": "Provedores de autenticação"
},
"settings.account.providers.table.actions": {
"message": "Ações"
},
"settings.account.providers.table.provider": {
"message": "Provedor"
},
"settings.account.security.email.action.add": {
"message": "Adicionar e-mail"
},
"settings.account.security.email.action.change": {
"message": "Alterar e-mail"
},
"settings.account.security.email.description": {
"message": "Altera o endereço de e-mail associado à sua conta."
},
"settings.account.security.email.title": {
"message": "E-mail"
},
"settings.account.security.password.action.add": {
"message": "Adicionar senha"
},
"settings.account.security.password.action.change": {
"message": "Alterar senha"
},
"settings.account.security.password.description.change": {
"message": "Altere a senha usada para acessar sua conta."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Altere ou remova a senha usada para acessar sua conta."
},
"settings.account.security.password.description.set": {
"message": "Defina uma senha permanente para acessar sua conta."
},
"settings.account.security.password.title": {
"message": "Senha"
},
"settings.account.security.providers.action.manage": {
"message": "Gerenciar provedores"
},
"settings.account.security.providers.description": {
"message": "Adicione ou remova métodos de login da sua conta, incluindo GitHub, GitLab, Microsoft, Discord, Steam e Google."
},
"settings.account.security.providers.title": {
"message": "Provedores de autenticação"
},
"settings.account.security.title": {
"message": "Segurança da conta"
},
"settings.account.security.two-factor.action.remove": {
"message": "Remover 2FA"
},
"settings.account.security.two-factor.action.setup": {
"message": "Configurar 2FA"
},
"settings.account.security.two-factor.description": {
"message": "Adicione uma camada extra de segurança à sua conta durante o login."
},
"settings.account.security.two-factor.title": {
"message": "Autenticação de dois fatores"
},
"settings.account.two-factor.backup.intro": {
"message": "Baixe e salve estes códigos de recuperação em um local seguro. Você pode usá-los no lugar de um código de autenticação em dois fatores caso perca o acesso ao seu dispositivo! Você deve proteger esses códigos como protegeria sua senha."
},
"settings.account.two-factor.backup.single-use": {
"message": "Os códigos de recuperação só podem ser usados uma vez."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "O código inserido está incorreto!"
},
"settings.account.two-factor.field.code.description": {
"message": "Insira o código de dois fatores para prosseguir."
},
"settings.account.two-factor.field.code.label": {
"message": "Insira o código de dois fatores"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Insira o código..."
},
"settings.account.two-factor.setup.intro": {
"message": "A autenticação de dois fatores mantém sua conta segura, exigindo o acesso a um segundo dispositivo para efetuar o login."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Se o código QR não for lido, você pode inserir a senha manualmente:"
},
"settings.account.two-factor.setup.scan": {
"message": "Escaneie o código QR com <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> ou qualquer outro aplicativo de autenticação em dois fatores para começar."
},
"settings.account.two-factor.verify.description": {
"message": "Insira o código único do autenticador para verificar o acesso."
},
"settings.account.two-factor.verify.label": {
"message": "Verifique o código"
},
"settings.applications.about": {
"message": "Sobre"
@@ -2954,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Aplicativos"
},
"settings.applications.modal.header": {
"message": "Informações do aplicativo"
},
"settings.applications.notification.error.title": {
"message": "Ocorreu um erro"
},
"settings.applications.notification.icon-updated.description": {
"message": "O ícone do seu aplicativo foi atualizado."
},
@@ -2969,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "Salve o seu secret agora, ele ficará oculto depois que você sair desta página!"
},
"settings.authorizations.about-this-app": {
"message": "Sobre este aplicativo"
},
"settings.authorizations.by": {
"message": "por"
},
"settings.authorizations.description": {
"message": "Ao autorizar um aplicativo com sua conta do Modrinth, você concede acesso à sua conta. Você pode gerenciar e revisar o acesso à sua conta aqui a qualquer momento."
},
"settings.authorizations.empty-state": {
"message": "No momento, não podemos exibir seus aplicativos autorizados. Estamos trabalhando para corrigir isso. Visite esta página novamente mais tarde!"
},
"settings.authorizations.head-title": {
"message": "Autorizações"
},
"settings.authorizations.revoke.action": {
"message": "Revogar"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Isso revogará o acesso do aplicativo à sua conta. Você sempre poderá autorizá-lo novamente mais tarde."
},
"settings.authorizations.revoke.confirm.title": {
"message": "Tem certeza de que deseja revogar este aplicativo?"
},
"settings.billing.charges.description": {
"message": "Todas as suas cobranças anteriores na sua conta Modrinth serão listadas aqui:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Teste do servidor Medal"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Expira em {date}"
},
"settings.billing.interval.month": {
"message": "mês"
},
"settings.billing.interval.monthly": {
"message": "mensal"
},
"settings.billing.interval.year": {
"message": "ano"
},
"settings.billing.interval.yearly": {
"message": "anual"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Navegação sem anúncios em modrinth.com e no Modrinth App"
},
"settings.billing.midas.benefits.badge": {
"message": "Distintivo Modrinth+ no seu perfil"
},
"settings.billing.midas.benefits.support": {
"message": "Apoie o Modrinth e seus criadores diretamente"
},
"settings.billing.midas.benefits.title": {
"message": "Benefícios"
},
"settings.billing.midas.save-per-year": {
"message": "Economize {amount}/ano mudando para a fatura anual!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Você cancelou sua assinatura."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "Você manterá seus benefícios até o final do ciclo de faturamento atual."
},
"settings.billing.midas.status.failed": {
"message": "O pagamento da sua assinatura falhou. Por favor, atualize sua forma de pagamento."
},
"settings.billing.midas.status.open": {
"message": "Você está inscrito(a) em:"
},
"settings.billing.midas.status.processing": {
"message": "Seu pagamento está sendo processado. Os benefícios serão ativados assim que o pagamento for concluído."
},
"settings.billing.midas.upsell": {
"message": "Torne-se assinante do Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Cancelar assinatura"
},
@@ -2987,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "Tem certeza de que deseja remover este método de pagamento?"
},
"settings.billing.next": {
"message": "Próximo:"
},
"settings.billing.or-yearly-save": {
"message": "Ou {price} / ano (economize {percent}%)!"
},
"settings.billing.payment_method.action.add": {
"message": "Adicionar método de pagamento"
},
@@ -3008,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Métodos de pagamento"
},
"settings.billing.plan.title": {
"message": "Plano {size}"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} CPUs compartilhadas (picos de até {bursts} CPUs)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "Não foi possível encontrar um servidor vinculado para esta assinatura. Existem algumas possíveis explicações para isso. Se você acabou de comprar seu servidor, isso é normal. Pode levar até uma hora para que ele seja provisionado. Caso contrário, se você comprou esse servidor há algum tempo, é provável que ele tenha sido suspenso. Se isso não era o esperado, entre em contato com o suporte do Modrinth com as seguintes informações:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "ID do servidor: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "Stripe ID: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} GB de RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Ocorreu um erro ao se reinscrever no seu Modrinth server."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Erro ao reativar a assinatura"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Se o servidor estiver suspenso, pode levar até 10 minutos para que outra tentativa de cobrança seja feita."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Solicitação de reativação enviada"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "Assinatura do servidor reativada com sucesso"
},
"settings.billing.pyro.status.failed": {
"message": "O pagamento da sua assinatura falhou. Por favor, atualize sua forma de pagamento, e tente assinar novamente."
},
"settings.billing.pyro.status.processing": {
"message": "Seu pagamento está sendo processado. O seu servidor será ativado assim que o pagamento for concluído."
},
"settings.billing.pyro.storage": {
"message": "{gb} GB de SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} GB de Swap"
},
"settings.billing.pyro_subscription.description": {
"message": "Gerencie suas assinaturas do Modrinth Servers."
},
"settings.billing.pyro_subscription.title": {
"message": "Assinaturas do Modrinth Servers"
},
"settings.billing.renews": {
"message": "Renova {date}"
},
"settings.billing.resubscribe": {
"message": "Reativar assinatura"
},
"settings.billing.since": {
"message": "Desde {date}"
},
"settings.billing.subscribe": {
"message": "Assinar"
},
"settings.billing.subscription.description": {
"message": "Gerencie suas assinaturas do Modrinth."
},
"settings.billing.subscription.title": {
"message": "Assinaturas"
},
"settings.billing.switch.switching-to-interval": {
"message": "Trocando para {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Trocar para {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "A cobrança mensal terá um custo adicional de {amount} por ano"
},
"settings.billing.switches-to-billing-on": {
"message": "Muda para cobrança {interval} em {date}"
},
"settings.billing.update-method": {
"message": "Atualizar método"
},
"settings.billing.upgrade": {
"message": "Atualizar"
},
"settings.display.banner.developer-mode.button": {
"message": "Desativar modo desenvolvedor"
},
@@ -3032,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Alternar recursos"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "O modo de desenvolvedor foi desativado"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Modo de desenvolvedor desativado"
},
"settings.display.project-list-layouts.datapack": {
"message": "Página dos pacotes de dados"
},
@@ -3041,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Página dos mods"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galeria"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Grade"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Linhas"
},
"settings.display.project-list-layouts.modpack": {
"message": "Página dos pacotes de mods"
},
@@ -3101,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Tema"
},
"settings.head-title": {
"message": "Configurações de exibição"
},
"settings.pats.action.create": {
"message": "Criar um TAP"
},
@@ -3161,6 +3536,9 @@
"settings.profile.description": {
"message": "As informações do seu perfil são visíveis publicamente no Modrinth e por meio da <docs-link>API do Modrinth</docs-link>."
},
"settings.profile.head-title": {
"message": "Configurações de perfil"
},
"settings.profile.profile-info": {
"message": "Informação do perfil"
},
@@ -3191,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Plataforma desconhecida"
},
"settings.sidebar.label.account": {
"message": "Conta"
},
"settings.sidebar.label.developer": {
"message": "Desenvolvedor"
},
"settings.sidebar.label.display": {
"message": "Mostrar"
},
"ui.latest-news-row.latest-news": {
"message": "Notícias recentes do Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Ver todas as notícias"
},
"ui.newsletter-button.subscribe": {
"message": "Inscrever"
},
"ui.newsletter-button.subscribed": {
"message": "Inscrito!"
},
"ui.newsletter-button.tooltip": {
"message": "Inscreva-se no boletim informativo do Modrinth"
},
"version.environment.none.description": {
"message": "O ambiente para esta versão não foi especificado."
},
+9 -12
View File
@@ -506,6 +506,15 @@
"create.project.title": {
"message": "Criar um projeto"
},
"create.project.type-label": {
"message": "Tipo"
},
"create.project.type-project": {
"message": "Projeto"
},
"create.project.type-server": {
"message": "Servidor"
},
"create.project.url-label": {
"message": "URL"
},
@@ -2720,21 +2729,12 @@
"servers.plan.large.description": {
"message": "Ideal para 15 a 25 jogadores, modpacks ou muitos mods."
},
"servers.plan.large.name": {
"message": "Grande"
},
"servers.plan.medium.description": {
"message": "Ótimo para 6 a 15 jogadores e vários mods."
},
"servers.plan.medium.name": {
"message": "Médio"
},
"servers.plan.small.description": {
"message": "Perfeito para 1 a 5 amigos com alguns mods leves."
},
"servers.plan.small.name": {
"message": "Pequeno"
},
"settings.applications.about": {
"message": "Sobre"
},
@@ -2813,9 +2813,6 @@
"settings.applications.modal.header": {
"message": "Informação da Aplicação"
},
"settings.applications.notification.error.title": {
"message": "Ocorreu um erro"
},
"settings.applications.notification.icon-updated.description": {
"message": "O ícone da tua aplicação foi atualizado."
},
@@ -1997,21 +1997,12 @@
"servers.plan.large.description": {
"message": "Ideal pentru 1525 de jucători, pachete de moduri sau moduri complexe."
},
"servers.plan.large.name": {
"message": "Larg"
},
"servers.plan.medium.description": {
"message": "Bun pentru 615 jucători și multiple moduri."
},
"servers.plan.medium.name": {
"message": "Mediu"
},
"servers.plan.small.description": {
"message": "Perfect pentru 15 prieteni cu câteva moduri ușoare."
},
"servers.plan.small.name": {
"message": "Mic"
},
"settings.applications.about": {
"message": "Despre"
},
+422 -17
View File
@@ -258,7 +258,7 @@
"message": "Сброс пароля"
},
"auth.sign-in.2fa.description": {
"message": "Введите код двухфакторной аутентификации."
"message": "Введите код подтверждения из приложения."
},
"auth.sign-in.2fa.label": {
"message": "Двухфакторная аутентификация"
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Создать проект"
},
"create.project.create-server-project": {
"message": "Создать сервер"
},
"create.project.missing-fields-tooltip": {
"message": "Не заполнены поля: {fields}"
},
@@ -660,7 +657,7 @@
"message": "Чистая сумма"
},
"dashboard.creator-withdraw-modal.fee-breakdown-usd-equivalent": {
"message": "Доллар США"
"message": "Долларов США"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Юридическое лицо"
@@ -1322,12 +1319,21 @@
"hosting.loader.failed-to-unlink": {
"message": "Не удалось отвязать набор модов"
},
"hosting.loader.loader-version": {
"message": "{loader, select, null {Версия загрузчика} other {Версия {loader}}}"
},
"hosting.loader.repair-started-text": {
"message": "Установка вашего сервера была восстановлена."
},
"hosting.loader.repair-started-title": {
"message": "Восстановление завершено"
},
"hosting.loader.reset-server": {
"message": "Сбросить сервер"
},
"hosting.loader.reset-server-description": {
"message": "Удаляет все данные сервера, включая миры, моды и файлы настроек. Резервные копии останутся и их можно будет восстановить."
},
"hosting.plan.out-of-stock": {
"message": "Нет в наличии"
},
@@ -2241,7 +2247,7 @@
"message": "Создать сервер"
},
"project.actions.dont-show-again": {
"message": "Больше не показывать"
"message": "Больше не показывать"
},
"project.actions.review-project": {
"message": "Проверить проект"
@@ -2849,20 +2855,209 @@
"servers.plan.large.description": {
"message": "Подходит для 15–25 игроков, сборок, либо требовательных модов."
},
"servers.plan.large.name": {
"message": "Большой"
},
"servers.plan.medium.description": {
"message": "Подходит для 6–15 игроков и нескольких модов."
},
"servers.plan.medium.name": {
"message": "Средний"
},
"servers.plan.small.description": {
"message": "Подходит для 1–5 игроков и нескольких лёгких модов."
},
"servers.plan.small.name": {
"message": "Малый"
"settings.account.button.complete-setup": {
"message": "Завершить настройку"
},
"settings.account.data-export.action.download": {
"message": "Скачать экспорт"
},
"settings.account.data-export.action.generate": {
"message": "Сгенерировать экспорт"
},
"settings.account.data-export.action.generating": {
"message": "Генерация экспорта..."
},
"settings.account.data-export.description": {
"message": "Запросите закодировать ваших персональных данных, загузине в Modrinth. Этот процесс может отнять несколько минут."
},
"settings.account.data-export.title": {
"message": "Экспортирование данных"
},
"settings.account.delete.confirm.description": {
"message": "Этот процесс **немедленно удалит все ваши пользовательские данные и следования**. Ваши проекты не будут удалённы.<br><br>. Если вам нужна помощь с вашей учетной записью, обратитесь за поддержкой в ​​[Discord сервер Modrinth-а](https://discord.modrinth.com)."
},
"settings.account.delete.confirm.proceed": {
"message": "Удалить этот аккаунт"
},
"settings.account.delete.confirm.title": {
"message": "Вы уверены, что вы хотите удалить ваш аккаунт?"
},
"settings.account.delete.section.action": {
"message": "Удалить аккаунт"
},
"settings.account.delete.section.description": {
"message": "После удаления аккаунта пути назад нет. Удаление ваших аккаунта приведет к удалению всех связанных с ней данных, за исключением проектов, с наших серверов."
},
"settings.account.delete.section.title": {
"message": "Удалить аккаунт"
},
"settings.account.email.action.save": {
"message": "Сохранить электронную почту"
},
"settings.account.email.field.label": {
"message": "Адрес электронной почты"
},
"settings.account.email.field.placeholder": {
"message": "Введите ваш адрес электронной почты..."
},
"settings.account.email.modal.header.add": {
"message": "Добавить электронную почту"
},
"settings.account.email.modal.header.change": {
"message": "Сменить электронную почту"
},
"settings.account.email.modal.notice": {
"message": "Информация о вашем аккаунте не показывается публично."
},
"settings.account.password.action.remove": {
"message": "Удалить пароль"
},
"settings.account.password.action.save": {
"message": "Сохранить пароль"
},
"settings.account.password.error.mismatch": {
"message": "Введённые пароли не совпадают!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Пожалуйста, введите ваш пароль, чтобы продолжить."
},
"settings.account.password.field.confirm-current.label": {
"message": "Подтвердить пароль"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Подтвердить пароль"
},
"settings.account.password.field.confirm-new.label": {
"message": "Подтвердить новый пароль"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Подтвердить новый пароль"
},
"settings.account.password.field.new.label": {
"message": "Новый пароль"
},
"settings.account.password.field.new.placeholder": {
"message": "Новый пароль"
},
"settings.account.password.field.old.label": {
"message": "Прошлый пароль"
},
"settings.account.password.field.old.placeholder": {
"message": "Прошлый пароль"
},
"settings.account.password.modal.header.add": {
"message": "Добавить пароль"
},
"settings.account.password.modal.header.change": {
"message": "Сменить пароль"
},
"settings.account.password.modal.header.remove": {
"message": "Удалить пароль"
},
"settings.account.providers.action.add": {
"message": "Добавить"
},
"settings.account.providers.modal.header": {
"message": "Сервисы входа"
},
"settings.account.providers.table.actions": {
"message": "Действия"
},
"settings.account.providers.table.provider": {
"message": "Сервис"
},
"settings.account.security.email.action.add": {
"message": "Добавить электронную почту"
},
"settings.account.security.email.action.change": {
"message": "Сменить электронную почту"
},
"settings.account.security.email.description": {
"message": "Изменяет электронную почту связанную с вашим аккаунтом."
},
"settings.account.security.email.title": {
"message": "Электронная почта"
},
"settings.account.security.password.action.add": {
"message": "Добавить пароль"
},
"settings.account.security.password.action.change": {
"message": "Сменить пароль"
},
"settings.account.security.password.description.change": {
"message": "Смените пароль, использовавшийся для входа в ваш аккаунт."
},
"settings.account.security.password.description.change-or-remove": {
"message": "Смените пароль или удалите, использовавшийся для входа в ваш аккаунт."
},
"settings.account.security.password.description.set": {
"message": "Поставьте постоянный пароль, чтобы войти в ваш аккаунт."
},
"settings.account.security.password.title": {
"message": "Пароль"
},
"settings.account.security.providers.action.manage": {
"message": "Настроить сервисы"
},
"settings.account.security.providers.description": {
"message": "Привяжите или отвяжите сторонние сервисы входа: GitHub, GitLab, Microsoft, Discord, Steam и Google."
},
"settings.account.security.providers.title": {
"message": "Вход через сторонние сервисы"
},
"settings.account.security.title": {
"message": "Безопасность аккаунта"
},
"settings.account.security.two-factor.action.remove": {
"message": "Отвязать аутентификатор"
},
"settings.account.security.two-factor.action.setup": {
"message": "Привязать аутентификатор"
},
"settings.account.security.two-factor.description": {
"message": "Добавьте ещё один уровень безопасности аккаунта при входе."
},
"settings.account.security.two-factor.title": {
"message": "Двухфакторная аутентификация"
},
"settings.account.two-factor.backup.intro": {
"message": "Сохраните резервные коды в надёжном месте. Используйте любой из них как код подтверждения, если потеряете доступ к устройству. Берегите их как свой пароль."
},
"settings.account.two-factor.backup.single-use": {
"message": "Резервные коды одноразовые."
},
"settings.account.two-factor.error.incorrect-code": {
"message": "Введённый код неверный!"
},
"settings.account.two-factor.field.code.description": {
"message": "Введите код подтверждения из приложения."
},
"settings.account.two-factor.field.code.label": {
"message": "Код подтверждения"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Введите код..."
},
"settings.account.two-factor.setup.intro": {
"message": "Двухфакторная аутентификация защищает аккаунт, требуя доступ ко второму устройству при входе в систему."
},
"settings.account.two-factor.setup.manual-secret": {
"message": "Если код не сканируется, введите ключ вручную:"
},
"settings.account.two-factor.setup.scan": {
"message": "Отсканируйте QR‑код через <authy-link>Authy</authy-link>, <microsoft-authenticator-link>Microsoft Authenticator</microsoft-authenticator-link> или любое другое приложение для генерации кодов, чтобы начать настройку."
},
"settings.account.two-factor.verify.description": {
"message": "Введите одноразовый код подтверждения из приложения."
},
"settings.account.two-factor.verify.label": {
"message": "Код подтверждения"
},
"settings.applications.about": {
"message": "Сведения"
@@ -2945,12 +3140,12 @@
"settings.applications.field.url.placeholder": {
"message": "https://example.com"
},
"settings.applications.head-title": {
"message": "Приложения"
},
"settings.applications.modal.header": {
"message": "Информация о приложении"
},
"settings.applications.notification.error.title": {
"message": "Произошла ошибка"
},
"settings.applications.notification.icon-updated.description": {
"message": "Иконка приложения обновлена."
},
@@ -2960,6 +3155,90 @@
"settings.applications.secret.disclaimer": {
"message": "Сохраните секретный ключ. Он исчезнет после выхода со страницы!"
},
"settings.authorizations.about-this-app": {
"message": "Об этом приложении"
},
"settings.authorizations.by": {
"message": "от"
},
"settings.authorizations.description": {
"message": "Когда вы авторизуете приложение с помощью своего Modrinth аккаунта, вы предоставляете ему доступ для действий от вашего имени. Вы можете управлять доступом своего аккаунта и просматривать его здесь в любое время."
},
"settings.authorizations.empty-state": {
"message": "Извините, в данный момент мы не можем отобразить ваши авторизованные приложения. Мы работаем над устранением этой проблемы. Пожалуйста, посетите эту страницу позже!"
},
"settings.authorizations.head-title": {
"message": "Авторизации"
},
"settings.authorizations.revoke.action": {
"message": "Отменить"
},
"settings.authorizations.revoke.confirm.description": {
"message": "Это операция отменить доступ приложения к вашему аккаунту. Вы всегда сможете авторизовать его позже."
},
"settings.authorizations.revoke.confirm.title": {
"message": "Вы уверены, что хотите изменить доступ?"
},
"settings.billing.charges.description": {
"message": "Здесь будут перечислены все ваши прошлые платежи в аккаунте Modrinth:"
},
"settings.billing.charges.product.medal-trial": {
"message": "Пробный период Medal Server"
},
"settings.billing.charges.product.midas": {
"message": "Modrinth Plus"
},
"settings.billing.charges.product.pyro": {
"message": "Modrinth Hosting"
},
"settings.billing.expires": {
"message": "Истечёт через {date}"
},
"settings.billing.interval.month": {
"message": "месяц"
},
"settings.billing.interval.monthly": {
"message": "ежемесячный"
},
"settings.billing.interval.year": {
"message": "год"
},
"settings.billing.interval.yearly": {
"message": "годовой"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Поиск на modrinth.com и Modrinth App без рекламы"
},
"settings.billing.midas.benefits.badge": {
"message": "Значок Modrinth+ в вашем профиле"
},
"settings.billing.midas.benefits.support": {
"message": "Поддержать Modrinth и создателей напрямую"
},
"settings.billing.midas.benefits.title": {
"message": "Преимущества"
},
"settings.billing.midas.save-per-year": {
"message": "Сэкономьте {amount} / год, перейдя на годовую оплату!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Вы отменили вашу подписку."
},
"settings.billing.midas.status.cancelled.line2": {
"message": "Ваши привилегии сохранятся до конца текущего расчетного периода."
},
"settings.billing.midas.status.failed": {
"message": "Оплата подписки не удалась. Пожалуйста, обновите способ оплаты."
},
"settings.billing.midas.status.open": {
"message": "На данный момент вы подписаны на:"
},
"settings.billing.midas.status.processing": {
"message": "Ваш платеж обрабатывается. Привилегии будут активированы после завершения платежа."
},
"settings.billing.midas.upsell": {
"message": "Станьте подписчиком Modrinth Plus!"
},
"settings.billing.modal.cancel.action": {
"message": "Отменить подписку"
},
@@ -2978,6 +3257,12 @@
"settings.billing.modal.delete.title": {
"message": "Вы действительно хотите удалить этот способ оплаты?"
},
"settings.billing.next": {
"message": "Далее:"
},
"settings.billing.or-yearly-save": {
"message": "Или {price} / год (скидка {percent}%)!"
},
"settings.billing.payment_method.action.add": {
"message": "Добавить способ оплаты"
},
@@ -2999,18 +3284,99 @@
"settings.billing.payment_method.title": {
"message": "Способы оплаты"
},
"settings.billing.plan.title": {
"message": "{size} план"
},
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} общих ЦП (увеличение до {bursts} ЦП)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "Для этой подписки не удалось найти связанный сервер. Этому есть несколько возможных объяснений. Если вы только что приобрели сервер, это нормально. Подготовка сервера может занять до часа. В противном случае, если вы приобрели этот сервер некоторое время назад, он, вероятно, уже приостановлен. Если это не то, чего вы ожидали, пожалуйста, свяжитесь со службой поддержки Modrinth, предоставив следующую информацию:"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "ID сервера: {id}"
},
"settings.billing.pyro.linked-server.stripe-id": {
"message": "Stripe ID: {id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} ГБ RAM"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Произошла ошибка при повторной подписке Modrinth server."
},
"settings.billing.pyro.resubscribe.error.title": {
"message": "Ошибка при повторной подписке"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Если сервер в данный момент приостановлен, повторная попытка списания средств может занять до 10 минут."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Запрос на повторную подписку отправлен"
},
"settings.billing.pyro.resubscribe.success.text": {
"message": "Подписка на сервер успешно продлена"
},
"settings.billing.pyro.status.failed": {
"message": "Оплата подписки не удалась. Пожалуйста, обновите способ оплаты."
},
"settings.billing.pyro.status.processing": {
"message": "Ваш платеж обрабатывается. Ваш сервер будет активирован после завершения платежа."
},
"settings.billing.pyro.storage": {
"message": "{gb} ГБ SSD"
},
"settings.billing.pyro.swap": {
"message": "{gb} ГБ файла подкачки"
},
"settings.billing.pyro_subscription.description": {
"message": "Управляйте своими подписками на Modrinth Servers."
},
"settings.billing.pyro_subscription.title": {
"message": "Подписки на Modrinth Servers"
},
"settings.billing.renews": {
"message": "Продлевает {date}"
},
"settings.billing.resubscribe": {
"message": "Переподписаться"
},
"settings.billing.since": {
"message": "С {date}"
},
"settings.billing.subscribe": {
"message": "Подписаться"
},
"settings.billing.subscription.description": {
"message": "Управляйте своими подписками на Modrinth."
},
"settings.billing.subscription.title": {
"message": "Подписки"
},
"settings.billing.switch.switching-to-interval": {
"message": "Переключение на {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Переключите на {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Ежемесячная оплата обойдется вам дополнительно {amount} на год"
},
"settings.billing.switches-to-billing-on": {
"message": "Переход на оплату по {interval} на {date}"
},
"settings.billing.update-method": {
"message": "Обновить способ"
},
"settings.billing.upgrade": {
"message": "Обновиться"
},
"settings.display.banner.developer-mode.button": {
"message": "Отключить режим разработчика"
},
@@ -3023,6 +3389,12 @@
"settings.display.flags.title": {
"message": "Переключение функций"
},
"settings.display.notification.developer-mode-deactivated.text": {
"message": "Режим разработчика отключен"
},
"settings.display.notification.developer-mode-deactivated.title": {
"message": "Режим разработчика отключен"
},
"settings.display.project-list-layouts.datapack": {
"message": "Страница наборов данных"
},
@@ -3032,6 +3404,15 @@
"settings.display.project-list-layouts.mod": {
"message": "Страница модов"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Галерея"
},
"settings.display.project-list-layouts.mode.grid": {
"message": "Сетка"
},
"settings.display.project-list-layouts.mode.rows": {
"message": "Список"
},
"settings.display.project-list-layouts.modpack": {
"message": "Страница сборок"
},
@@ -3092,6 +3473,9 @@
"settings.display.theme.title": {
"message": "Тема"
},
"settings.head-title": {
"message": "Настройки отображения"
},
"settings.pats.action.create": {
"message": "Создать токен доступа"
},
@@ -3152,6 +3536,9 @@
"settings.profile.description": {
"message": "Информация в вашем профиле доступна публично на Modrinth и через <docs-link>API Modrinth</docs-link>."
},
"settings.profile.head-title": {
"message": "Настройки профиля"
},
"settings.profile.profile-info": {
"message": "Информация в профиле"
},
@@ -3182,12 +3569,30 @@
"settings.sessions.unknown-platform": {
"message": "Неизвестная платформа"
},
"settings.sidebar.label.account": {
"message": "Аккаунт"
},
"settings.sidebar.label.developer": {
"message": "Разработка"
},
"settings.sidebar.label.display": {
"message": "Отображение"
},
"ui.latest-news-row.latest-news": {
"message": "Последние новости от Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "Посмотреть все новости"
},
"ui.newsletter-button.subscribe": {
"message": "Подписаться"
},
"ui.newsletter-button.subscribed": {
"message": "Вы подписаны!"
},
"ui.newsletter-button.tooltip": {
"message": "Подписаться на рассылку от Modrinth"
},
"version.environment.none.description": {
"message": "Среда для этой версии не указана."
},
@@ -965,21 +965,12 @@
"servers.plan.large.description": {
"message": "Idealno za 1525 igrača, modpackove ili intenzivno modovanje."
},
"servers.plan.large.name": {
"message": "Veliki"
},
"servers.plan.medium.description": {
"message": "Odlično za 615 igrača i više modova."
},
"servers.plan.medium.name": {
"message": "Srednje"
},
"servers.plan.small.description": {
"message": "Savršeno za 15 prijatelja sa nekoliko lakih modova."
},
"servers.plan.small.name": {
"message": "Mali"
},
"settings.billing.modal.cancel.action": {
"message": "Otkaži pretplatu"
},
+64 -13
View File
@@ -497,9 +497,6 @@
"create.project.create-project": {
"message": "Skapa projekt"
},
"create.project.create-server-project": {
"message": "Skapa server"
},
"create.project.missing-fields-tooltip": {
"message": "Saknade fält: {fields}"
},
@@ -578,6 +575,21 @@
"dashboard.collections.button.create-new": {
"message": "Skapa ny"
},
"dashboard.collections.empty.get-started-hint": {
"message": "Skapa din första samling för att komma igång!"
},
"dashboard.collections.empty.no-collections": {
"message": "Du har inga samlingar än"
},
"dashboard.collections.empty.no-match": {
"message": "Inga samlingar matchar din sökning"
},
"dashboard.collections.empty.no-match-hint": {
"message": "Prova att ändra dina filter eller sökord."
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, one {projekt} other {projekt}}"
},
"dashboard.collections.label.search-input": {
"message": "Sök i dina samlingar"
},
@@ -653,6 +665,9 @@
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "En affärsenhet är en registrerad organisation såsom ett aktiebolag, ett handelsbolag eller ett LLC-bolag."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "Tar du ut pengar som en privatperson eller företag?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Privat individ"
},
@@ -881,9 +896,33 @@
"dashboard.withdraw.completion.wallet": {
"message": "Saldo"
},
"dashboard.withdraw.error.insufficient-balance.title": {
"message": "Otillräcklig saldo"
},
"dashboard.withdraw.error.invalid-address.text": {
"message": "Adressen som du angett kunde inte verifieras. Kontrollera dina adressdetaljer."
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Adressverifiering misslyckades"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": "Bankkonto-detaljerna som du angett är ogiltiga. Vänligen verifiera din information."
},
"dashboard.withdraw.error.invalid-bank.title": {
"message": "Ogiltiga bankuppgifter"
},
"dashboard.withdraw.error.invalid-wallet.text": {
"message": "Kryptoplånboks-adressen som du angett är ogiltig. Dubbelkolla och försök igen."
},
"dashboard.withdraw.error.invalid-wallet.title": {
"message": "Ogiltig plånboksadress"
},
"dashboard.withdraw.error.minimum-not-met.text": {
"message": "Utdragningsbeloppet (efter avgifterna) möter inte minimikravet. Vänligen höj utdragningsbeloppet."
},
"dashboard.withdraw.error.minimum-not-met.title": {
"message": "Belopp för lågt"
},
"error.collection.404.list_item.1": {
"message": "Du kan ha skrivit fel på samlingens URL."
},
@@ -905,6 +944,12 @@
"error.generic.404.title": {
"message": "Sidan hittades inte"
},
"error.generic.451.subtitle": {
"message": "Sidan har blockerats av juridiska skäl, såsom statlig censur eller pågående rättsliga förfaranden."
},
"error.generic.451.title": {
"message": "Innehåll otillgängligt av juridiska skäl"
},
"error.generic.default.list_item.1": {
"message": "Se om Modrinth är nere på vår <status-link>statussida</status-link>."
},
@@ -1010,6 +1055,9 @@
"hosting-marketing.faq.ddos-protection": {
"message": "Har Modrinth Hostings servrar DDoS-skydd?"
},
"hosting-marketing.faq.ddos-protection.answer": {
"message": "Ja. Alla Modrinth Hosting servrar medföljer DDoS-skydd, med upp till 17 Tbps kapacitet på vissa ställen."
},
"hosting-marketing.faq.heading": {
"message": "Vanliga frågor"
},
@@ -1019,6 +1067,9 @@
"hosting-marketing.faq.how-fast.answer.one": {
"message": "Modrinth Hostings servrar bygger på väldigt modern högpresterande hårdvara, men att säga exakt hur det kommer påverka hur din server kör är svårt, då det finns många olika faktorer som påverkar det, som moddarna, datapaketen, pluginsen som du kör på din server och även beteendet av dina spelare."
},
"hosting-marketing.faq.how-fast.answer.two": {
"message": "Flesta prestandaproblem som kommer upp är ofta på grund av en ej-optimerad modpack, mod, datapack, eller plugin som får servern att lagga. Eftersom våra servrar är av väldigt hög kvalitet, så borde du inte inträffa många problem om du väljer en lämplig plan för innehållet som du har på servern."
},
"hosting-marketing.faq.increase-storage": {
"message": "Kan jag öka mängden lagring på min server?"
},
@@ -1073,6 +1124,9 @@
"hosting-marketing.included.custom-url.description": {
"message": "Dela din server med en anpassad <contrast>modrinth.gg</contrast> URL."
},
"hosting-marketing.included.file-manager": {
"message": "Filhanterare som är lätt att använda"
},
"hosting-marketing.included.file-manager.description": {
"message": "Sök, hantera, redigera och ladda upp filer direkt till din server med lätthet."
},
@@ -1103,6 +1157,9 @@
"hosting-marketing.know-what-you-need": {
"message": "Vet du exakt vad du behöver?"
},
"hosting-marketing.medal.info": {
"message": "Prova på en gratis <orange>3 GB server</orange> i 5 dagar drivet av <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Läs mer"
},
@@ -1143,7 +1200,7 @@
"message": "Spela där dina moddar finns"
},
"hosting-marketing.why.where-mods-are.description": {
"message": "Modrinth Hosting integrerar mod- och modpack-installationsprocessen sömlöst i din server."
"message": "Modrinth Hosting integrerar mod- och modpaket-installationsprocessen sömlöst i din server."
},
"hosting-marketing.why.why-modrinth-hosting": {
"message": "Varför Modrinth Hosting?"
@@ -1154,6 +1211,9 @@
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Välja mellan Vanilla, Fabric, Forge; Quilt och NeoForge. Om det finns på Modrinth så kan din server köra det."
},
"hosting.loader.failed-to-change-version": {
"message": "Misslyckades med att ändra version på modpaketet"
},
"hosting.plan.out-of-stock": {
"message": "Ej i lager"
},
@@ -2366,18 +2426,12 @@
"servers.plan.large.description": {
"message": "Ideal för 1525 spelare, modpaket, eller tungt moddande."
},
"servers.plan.large.name": {
"message": "Stor"
},
"servers.plan.medium.description": {
"message": "Bra för 615 spelare och flera moddar."
},
"servers.plan.small.description": {
"message": "Perfekt för 15 vänner med några få lätta moddar."
},
"servers.plan.small.name": {
"message": "Liten"
},
"settings.applications.about": {
"message": "Om"
},
@@ -2432,9 +2486,6 @@
"settings.applications.field.url.placeholder": {
"message": "https://exempel.se"
},
"settings.applications.notification.error.title": {
"message": "Ett fel inträffade"
},
"settings.applications.notification.icon-updated.description": {
"message": "Ditt applikations ikon har blivit uppdaterad."
},
+150 -15
View File
@@ -488,9 +488,6 @@
"create.project.create-project": {
"message": "Proje oluştur"
},
"create.project.create-server-project": {
"message": "Sunucu oluştur"
},
"create.project.missing-fields-tooltip": {
"message": "Eksik alanlar:{fields}"
},
@@ -569,6 +566,12 @@
"dashboard.collections.button.create-new": {
"message": "Yeni oluştur"
},
"dashboard.collections.empty.get-started-hint": {
"message": "Başlamak için ilk koleksiyonunu oluştur!"
},
"dashboard.collections.empty.no-collections": {
"message": "Henüz koleksiyonun yok"
},
"dashboard.collections.label.search-input": {
"message": "Koleksiyonlarında ara"
},
@@ -1271,6 +1274,21 @@
"hosting-marketing.why.your-favorite-mods.description": {
"message": "Vanilla, Fabric, Forge, Quilt ve NeoForge arasından seçin. Modrinth'de varsa sunucunuzda çalışır."
},
"hosting.loader.failed-to-change-version": {
"message": "Modpaketi sürümü değiştirilemedi"
},
"hosting.loader.failed-to-load-versions": {
"message": "Sürümler yüklenemedi"
},
"hosting.loader.failed-to-repair": {
"message": "Sunucu tamiri başarısız oldu"
},
"hosting.loader.repair-started-title": {
"message": "Tamir tamamlandı"
},
"hosting.loader.reset-server": {
"message": "Sunucuyu sıfırla"
},
"hosting.plan.out-of-stock": {
"message": "Stokta yok"
},
@@ -2271,7 +2289,7 @@
"message": "Lütfen ortam meta verisini inceleyin"
},
"project.error.loading": {
"message": "Proje verisi yüklenemedi{message}"
"message": "Proje verisi yüklenirken hata{message}"
},
"project.error.page-not-found": {
"message": "Sayfa bulunamadı"
@@ -2771,20 +2789,95 @@
"servers.plan.large.description": {
"message": "1525 oyuncu, mod paketleri veya ağır modlu sunucu için ideal."
},
"servers.plan.large.name": {
"message": "Büyük"
},
"servers.plan.medium.description": {
"message": "615 oyuncu ve birden fazla mod için iyi."
},
"servers.plan.medium.name": {
"message": "Orta"
},
"servers.plan.small.description": {
"message": "15 arkadaş ve birkaç hafif mod için mükemmel."
},
"servers.plan.small.name": {
"message": "Küçük"
"settings.account.password.error.mismatch": {
"message": "Parolalar uyuşmuyor!"
},
"settings.account.password.field.confirm-current.description": {
"message": "Devam etmek için lütfen şifrenizi girin."
},
"settings.account.password.field.confirm-current.label": {
"message": "Parolayı onayla"
},
"settings.account.password.field.confirm-current.placeholder": {
"message": "Parolayı onayla"
},
"settings.account.password.field.confirm-new.label": {
"message": "Yeni parolayı onayla"
},
"settings.account.password.field.confirm-new.placeholder": {
"message": "Yeni parolayı onayla"
},
"settings.account.password.field.new.label": {
"message": "Yeni parola"
},
"settings.account.password.field.new.placeholder": {
"message": "Yeni parola"
},
"settings.account.password.field.old.label": {
"message": "Eski parola"
},
"settings.account.password.field.old.placeholder": {
"message": "Eski parola"
},
"settings.account.password.modal.header.add": {
"message": "Parola ekle"
},
"settings.account.password.modal.header.change": {
"message": "Parolayı değiştir"
},
"settings.account.password.modal.header.remove": {
"message": "Parolayı kaldır"
},
"settings.account.providers.action.add": {
"message": "Ekle"
},
"settings.account.providers.table.provider": {
"message": "Sağlayıcı"
},
"settings.account.security.email.action.add": {
"message": "Eposta ekle"
},
"settings.account.security.email.action.change": {
"message": "Eposta değiştir"
},
"settings.account.security.email.title": {
"message": "Eposta"
},
"settings.account.security.password.action.add": {
"message": "Parola ekle"
},
"settings.account.security.password.action.change": {
"message": "Parolayı değiştir"
},
"settings.account.security.password.title": {
"message": "Parola"
},
"settings.account.security.title": {
"message": "Hesap güvenliği"
},
"settings.account.security.two-factor.action.remove": {
"message": "İki aşamalı doğrulamayı kaldır"
},
"settings.account.security.two-factor.action.setup": {
"message": "İki aşamalı doğrulama kur"
},
"settings.account.security.two-factor.title": {
"message": "İki aşamalı doğrulama"
},
"settings.account.two-factor.error.incorrect-code": {
"message": "Girilen kod yanlış!"
},
"settings.account.two-factor.field.code.placeholder": {
"message": "Kodu girin..."
},
"settings.account.two-factor.verify.label": {
"message": "Kodu onayla"
},
"settings.applications.about": {
"message": "Hakkında"
@@ -2870,9 +2963,6 @@
"settings.applications.modal.header": {
"message": "Proje bilgileri"
},
"settings.applications.notification.error.title": {
"message": "Bir hata oluştu"
},
"settings.applications.notification.icon-updated.description": {
"message": "Uygulamanızın simgesi güncellendi."
},
@@ -2882,6 +2972,12 @@
"settings.applications.secret.disclaimer": {
"message": "Gizli anahtar sadece bir kez gösterilir. Pencereyi kapadığınızda kaybolacaktır. Güvenliğiniz için paylaşmayın!"
},
"settings.authorizations.about-this-app": {
"message": "Bu uygulama hakkında"
},
"settings.authorizations.by": {
"message": "tarafından"
},
"settings.billing.modal.cancel.action": {
"message": "Aboneliği iptal et"
},
@@ -2921,18 +3017,36 @@
"settings.billing.payment_method.title": {
"message": "Ödeme yöntemleri"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "Sunucu Kimliği:{id}"
},
"settings.billing.pyro.ram": {
"message": "{gb} GB RAM"
},
"settings.billing.pyro.status.processing": {
"message": "Ödemeniz işleniyor. Sunucunuz ödeme tamamlandığında aktifleşecektir."
},
"settings.billing.pyro.storage": {
"message": "{gb} GB RAM"
},
"settings.billing.pyro_subscription.description": {
"message": "Modrinth Sunucu aboneliklerini yönet."
},
"settings.billing.pyro_subscription.title": {
"message": "Modrinth Sunucu Abonelikleri"
},
"settings.billing.subscribe": {
"message": "Abone ol"
},
"settings.billing.subscription.description": {
"message": "Modrinth aboneliklerinizi yönetin."
},
"settings.billing.subscription.title": {
"message": "Abonelikler"
},
"settings.billing.upgrade": {
"message": "Güncelle"
},
"settings.display.banner.developer-mode.button": {
"message": "Geliştiri modunu devre dışı bırak"
},
@@ -2954,6 +3068,9 @@
"settings.display.project-list-layouts.mod": {
"message": "Modlar sayfası"
},
"settings.display.project-list-layouts.mode.gallery": {
"message": "Galeri"
},
"settings.display.project-list-layouts.modpack": {
"message": "Mod paketleri sayfası"
},
@@ -3014,6 +3131,9 @@
"settings.display.theme.title": {
"message": "Renk teması"
},
"settings.head-title": {
"message": "Görüntü Ayarları"
},
"settings.pats.action.create": {
"message": "Bir PAT yarat"
},
@@ -3071,6 +3191,9 @@
"settings.profile.description": {
"message": "Profil bilgin Modrinth'te ve <docs-link>Modrinth API</docs-link> herkese açık görüntülenebilir."
},
"settings.profile.head-title": {
"message": "Profil Ayarları"
},
"settings.profile.profile-info": {
"message": "Profil bilgisi"
},
@@ -3101,12 +3224,24 @@
"settings.sessions.unknown-platform": {
"message": "Bilinmeyen platform"
},
"settings.sidebar.label.account": {
"message": "Hesap"
},
"settings.sidebar.label.developer": {
"message": "Geliştirici"
},
"ui.latest-news-row.latest-news": {
"message": "Modrinth'ten haberler"
},
"ui.latest-news-row.view-all": {
"message": "Bütün haberleri gör"
},
"ui.newsletter-button.subscribe": {
"message": "Abone ol"
},
"ui.newsletter-button.subscribed": {
"message": "Abone Olundu!"
},
"version.environment.none.description": {
"message": "Bu sürüm için ortam belirtilmemiş."
},

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