Compare commits

...
Author SHA1 Message Date
aecsocket 58cbdaccc5 fixes 2026-05-29 19:33:09 +01:00
aecsocket 991d5e2e5b Filter out invalid loaders, fix query bug 2026-05-29 19:20:23 +01:00
aecsocket 333bf8d77f should fix bucketing query bug 2026-05-29 19:20:09 +01:00
Calum H.andGitHub f49951084e fix: prev message invalid treat as changed (#6236) 2026-05-29 16:19:58 +00:00
Calum H.andGitHub 047b8c3bf7 fix: i18n string problems (#6131)
* fix: apply non-json i18n fixes

* fix: pruning

* fix: prepr

* fix: run.mjs

* fix: lint
2026-05-29 15:55:39 +00:00
Calum H.andGitHub 5c1ffd9ff2 fix: resubmit i18n bug (#6218) 2026-05-29 12:17:08 +00:00
Calum H.andGitHub 670b3c17b6 feat: use split up backup cancel endpoints (#6217) 2026-05-29 12:16:57 +00:00
Prospector ec7c538888 changelog 2026-05-28 18:45:43 -07:00
Prospector b88341e3a8 fix: clean up user page, add verification on modrinth user, fix collection sidebar width 2026-05-28 18:44:25 -07:00
Truman GaoandGitHub 2048d8008a fix: sign in buttons showing in mobile navbar when hidden (#6232) 2026-05-29 01:18:20 +00:00
aecsocketandGitHub 527f2f800b Analytics faceting return count, improve performance (#6229) 2026-05-28 17:58:19 +00:00
SychicandGitHub c7d3229fd3 fix(frontend): incorrect values prop name (#6224) 2026-05-28 16:54:51 +00:00
aecsocketandGitHub ec49a3b051 Move all-projects route to specific user scope (#6220)
* Move all-projects route to specific user scope

* ci

* ci flaky test

* fmt
2026-05-28 14:41:57 +00:00
Calum H.andGitHub cf1d948030 fix: desync on flush (#6223) 2026-05-27 23:22:09 +00:00
fe8fa4b6f7 feat: changelog app 0.14.0 (#6222)
* feat: changelog app 0.14.0

* fix: changelog

* Update packages/blog/changelog.ts

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

* Update packages/blog/changelog.ts

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

---------

Signed-off-by: Calum H. <hendersoncal117@gmail.com>
Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com>
2026-05-27 22:47:28 +00:00
Modrinth BotandGitHub 2c62cf1d12 New translations from Crowdin (main) (#6203) 2026-05-27 22:28:26 +00:00
Calum H.andGitHub 84b91f32f8 fix: skins QA problems + flow change (#6216)
* fix: skins backend bugs + apply flow

* fix: caching structure

* feat: collapse already duplicated skins + fix moj api spam

* fix: doc

* fix: flatten migrations

* feat: remove default cape/cape override concept

* fix: fmt + lint

* feat: remove SelectCapeModal for inline cape list

* feat: qa

* feat: virtualisation of skins sections + fix texture/model cache

* fix: lint

* fix: virt bugs + renderer fixes

* fix: qa bugs

* fix: doc

* fix: re-add click impulse anim from prototypes + re-add interact anim length cap

* fix: regressions

* devex: split up SkinPreviewrenderer

* fix: lint

* fix: introduce dynamic mode in virtual-scroll.ts

* feat: qa

* fix: nametag bug + remove minecon skin pack suffix

* feat: pain (literally)

* feat: user agent on moj reqs

* feat: impl per account flush queue for operations

* fix: breadcrumb

* chore: i18n pass

* fix: lint + prep + check

* fix: misalignments
2026-05-27 22:22:24 +00:00
aecsocketandGitHub 64edf2ddeb Improve analytics performance, analytics faceting (#6180)
* fix uri too long

* all projects route for user

* analytics facet fetching

* cache download source regexes

* filtering

* prepare

* Split up analytics metrics into separate modules

* prepare

* fix ci
2026-05-27 00:01:13 +00:00
aecsocketandGitHub 2f248027d6 Also run Daedalus manifest uploads when there's a new game version (#6213) 2026-05-26 21:55:54 +00:00
ThatGravyBoatandGitHub f96520638b feat: Add user-images.githubusercontent.com in allowedHostnames (#6210)
feat: Allow user-images.githubusercontent.com in descriptions
2026-05-26 14:52:35 +00:00
Prospector 9e5d29ced6 hotfix 2026-05-24 12:14:13 -07:00
Prospector 3e15d0b287 changelog 2026-05-24 10:46:35 -07:00
ProspectorandGitHub bcce7e28fd fix: guard against non-strings when decorating download urls (#6194) 2026-05-24 10:42:27 -07:00
ProspectorandGitHub 3889d0f5ec fix: simplify preview banner translation key (#6192) 2026-05-24 10:39:39 -07:00
ProspectorandGitHub 6f44c5b039 feat: add 2 second auto close on skipped notifications (#6191) 2026-05-24 10:39:27 -07:00
Modrinth BotandGitHub ea967845d9 New translations from Crowdin (main) (#6193) 2026-05-24 17:25:25 +00:00
Prospector a6967cf9cb changelog 2026-05-24 09:26:36 -07:00
ProspectorandGitHub 5bf92863b0 fix: spanish locale (#6189) 2026-05-24 09:21:14 -07:00
Prospector 71b6ecc10c fix changelog... 2026-05-23 23:26:34 -07:00
Prospector ed28bc7551 remove april fools redirect 2026-05-23 22:03:59 -07:00
Prospector 3e4197db7c changelog 2026-05-23 22:02:49 -07:00
ProspectorandGitHub e12230ff59 feat: update default memory from 2GB to 4GB (#6172)
* feat: update default memory from 2GB to 4GB

* prepr
2026-05-23 21:26:51 -07:00
ProspectorandGitHub aeb9f5a075 fix: invalid auth cookie causing page not to load (#6186) 2026-05-23 21:26:13 -07:00
Calum H.andGitHub 8b17441f40 feat: compact logs if they have logspam to prevent app crashing (#6181)
* feat: compact logs if they have logspam to prevent app crashing

* fix: lint
2026-05-23 18:22:15 +00:00
f9d47e8edc feat: Add new "Enabled" sorting button next to "Disabled" (#6000)
* feat: Added new "Enabled" sorting button next to "Disabled"

* Updated when filter buttons show

- When all mods are disabled, only "Disabled" shows
- When all mods are enabled, only "Enabled" shows
- When there disabled and enabled mods, then only both buttons show.

* Updated when filter buttons show

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-05-23 16:12:14 +00:00
a58bc3dc21 feat: java installation ui improvements (#5731)
* Clean impl of java installation ui improvements

* Migrate composable to ts

* Migrate to ButtonStyled, fix coloring

* Fix lint

* Fix clearing java path not refreshing state

* fix: use Table component + install btn disabled state tooltip

---------

Signed-off-by: Arthur <creeperkatze.dev@gmail.com>
Signed-off-by: Arthur <contact@creeperkatze.dev>
Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
Co-authored-by: Calum H. <calum@modrinth.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
2026-05-23 14:46:12 +00:00
ProspectorandGitHub 1e46444fb0 fix: checklist forcing redirects (#6173) 2026-05-22 15:53:22 -07:00
ProspectorandGitHub 1511e55597 fix: skip reviewed projects in queue (#6171) 2026-05-22 14:54:50 -07:00
aecsocketandGitHub 5727e156ed Fetch project analytics events on analytics get (#6143)
* Fetch project analytics events

* fix

* post-query ua bucketing

* fmt
2026-05-22 18:32:33 +00:00
Calum H.andGitHub 657186398d fix: remove broken roadmap reference (#6165)
Signed-off-by: Calum H. <calum@modrinth.com>
2026-05-22 18:10:01 +00:00
Michael H. 3ab2273782 chore: prepr 2026-05-22 19:58:11 +02:00
ProspectorandGitHub 893ec00fc6 feat: add external dep sorting to moderation queue (#6161)
* feat: add external dep sorting to moderation queue

* prepr
2026-05-21 16:40:13 -07:00
Prospector aa7dd1d210 web 2026-05-21 16:23:30 -07:00
Calum H.andGitHub f8733b0488 feat: changelog 21st may 2026 (#6158)
* feat: changelog 21st may 2026

* fix: changelog
2026-05-21 22:27:14 +00:00
Calum H.andGitHub d077d44540 fix: content tab uniqueness regression (#6156)
* fix: content tab uniqueness regression

Closes: #6154

* fix: further regressions

* fix: lint

* fix: lint
2026-05-21 22:03:35 +00:00
aecsocketandGitHub 4e1a61d8b6 Adjust window occlusion threshold (#6157) 2026-05-21 21:48:39 +00:00
aecsocketandGitHub 71dee4de40 Add modpacks with external files filter to moderation queue (#6155)
* simplify query

* make it a tristate

* external deps count
2026-05-21 20:21:54 +00:00
SychicandGitHub f74fad0cae fix: typo in version changelog (#6153) 2026-05-21 19:38:11 +00:00
Truman GaoandGitHub 07e81ac036 fix: project embeds (#6152)
* fix: project embeds

* remove: params.id
2026-05-21 17:02:53 +00:00
Calum H.andGitHub 6e7835fb35 feat: implement kryos upload sessions (#6145)
* feat: implement upload sessions

* fix: files not scoped

* feat: hide staging files folder and proper cancel feedback

* fix: lint
2026-05-21 16:49:48 +00:00
310 changed files with 14378 additions and 10290 deletions
@@ -9,8 +9,6 @@ body:
options:
- label: I checked the [existing issues](https://github.com/modrinth/code/issues?q=is%3Aissue) for duplicate feature requests
required: true
- label: I have checked that this feature request is not on our [roadmap](https://roadmap.modrinth.com)
required: true
- type: dropdown
id: projects
attributes:
+14
View File
@@ -56,6 +56,17 @@ jobs:
ref: ${{ github.ref }}
token: ${{ secrets.CROWDIN_GH_TOKEN }}
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Enable Corepack
run: corepack enable
- name: Install script dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Configure Git author
id: git-author
uses: MarcoIeni/git-config@59144859caf016f8b817a2ac9b051578729173c4 # v0.1.2
@@ -95,6 +106,9 @@ jobs:
shell: bash
run: sudo chown -R $USER:$USER .
- name: Prune stale ICU translations
run: pnpm scripts i18n-icu-contract prune-local
- name: Create Pull Request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
+22 -1
View File
@@ -4,11 +4,14 @@ on:
push:
branches: ['main']
paths:
- '.github/workflows/i18n.push.yml'
- '.github/workflows/i18n-push.yml'
- 'apps/*/src/locales/en-US/**'
- 'apps/*/locales/en-US/**'
- 'packages/*/src/locales/en-US/**'
- 'packages/*/locales/en-US/**'
- 'scripts/i18n-icu-contract.ts'
- 'package.json'
- 'pnpm-lock.yaml'
- 'crowdin.yml'
workflow_dispatch:
@@ -56,6 +59,18 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.ref }}
fetch-depth: 2
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Enable Corepack
run: corepack enable
- name: Install script dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Query branch name
id: branch-name
@@ -79,3 +94,9 @@ jobs:
env:
CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
- name: Clear stale ICU translations in Crowdin
run: pnpm scripts i18n-icu-contract clear-crowdin-changed --base-ref HEAD^ --crowdin-branch "[${{ github.repository_owner }}.${{ github.event.repository.name }}] ${{ steps.branch-name.outputs.safe_branch_name }}"
env:
CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
+2 -1
View File
@@ -204,4 +204,5 @@ jobs:
- name: Verify intl:extract has been run
run: |
pnpm turbo run intl:extract --force
git diff --exit-code --color */*/src/locales/en-US/index.json
pnpm scripts i18n-icu-contract prune-local --check
git diff --exit-code --color */*/src/locales/*/index.json
+1
View File
@@ -10,6 +10,7 @@
"lint": "eslint . && prettier --check .",
"fix": "eslint . --fix && prettier --write .",
"intl:extract": "formatjs extract \"src/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" --ignore \"**/*.d.ts\" --ignore node_modules --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
"intl:prune-local": "pnpm -w scripts i18n-icu-contract prune-local --scope apps/app-frontend",
"test": "vue-tsc --noEmit"
},
"dependencies": {
+3 -1
View File
@@ -330,6 +330,7 @@ async function setupApp() {
locale,
telemetry,
collapsed_navigation,
hide_nametag_skins_page,
advanced_rendering,
onboarded,
default_page,
@@ -360,6 +361,7 @@ async function setupApp() {
themeStore.setThemeState(theme)
themeStore.collapsedNavigation = collapsed_navigation
themeStore.advancedRendering = advanced_rendering
themeStore.hideNametagSkinsPage = hide_nametag_skins_page
themeStore.toggleSidebar = toggle_sidebar
themeStore.devMode = developer_mode
themeStore.featureFlags = feature_flags
@@ -1227,7 +1229,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
>
<CompassIcon />
</NavButton>
<NavButton v-tooltip.right="'Skins (Beta)'" to="/skins">
<NavButton v-tooltip.right="'Skin selector'" to="/skins">
<ChangeSkinIcon />
</NavButton>
<NavButton
@@ -150,7 +150,10 @@ async function refreshValues() {
if (equippedSkin.value) {
try {
const headUrl = await getPlayerHeadUrl(equippedSkin.value)
headUrlCache.value.set(equippedSkin.value.texture_key, headUrl)
headUrlCache.value = new Map(headUrlCache.value).set(
equippedSkin.value.texture_key,
headUrl,
)
} catch (error) {
console.warn('Failed to get head render for equipped skin:', error)
}
@@ -160,12 +163,24 @@ async function refreshValues() {
}
}
async function setEquippedSkin(skin: Skin) {
equippedSkin.value = skin
try {
const headUrl = await getPlayerHeadUrl(skin)
headUrlCache.value = new Map(headUrlCache.value).set(skin.texture_key, headUrl)
} catch (error) {
console.warn('Failed to get head render for equipped skin:', error)
}
}
function setLoginDisabled(value: boolean) {
loginDisabled.value = value
}
defineExpose({
refreshValues,
setEquippedSkin,
setLoginDisabled,
loginDisabled,
})
@@ -1,35 +1,33 @@
<template>
<ModalWrapper ref="detectJavaModal" header="Select java version" :show-ad-on-close="false">
<div class="auto-detect-modal">
<div class="table">
<div class="table-row table-head">
<div class="table-cell table-text">Version</div>
<div class="table-cell table-text">Path</div>
<div class="table-cell table-text">Actions</div>
</div>
<div v-for="javaInstall in chosenInstallOptions" :key="javaInstall.path" class="table-row">
<div class="table-cell table-text">
<span>{{ javaInstall.version }}</span>
</div>
<div v-tooltip="javaInstall.path" class="table-cell table-text">
<span>{{ javaInstall.path }}</span>
</div>
<div class="table-cell table-text manage">
<ButtonStyled v-if="currentSelected.path === javaInstall.path">
<button disabled><CheckIcon /> Selected</button>
<div class="flex flex-col gap-4">
<Table :columns="javaInstallColumns" :data="chosenInstallOptions" row-key="path">
<template #cell-version="{ value }">
<span class="font-semibold text-primary">{{ value }}</span>
</template>
<template #cell-path="{ value }">
<span v-tooltip="value" class="block truncate font-mono text-xs">{{ value }}</span>
</template>
<template #cell-actions="{ row }">
<div class="flex items-center justify-end">
<ButtonStyled v-if="currentSelected.path === row.path">
<button class="!shadow-none" disabled><CheckIcon /> Selected</button>
</ButtonStyled>
<ButtonStyled v-else>
<button @click="setJavaInstall(javaInstall)"><PlusIcon /> Select</button>
<button class="!shadow-none" @click="setJavaInstall(row)"><PlusIcon /> Select</button>
</ButtonStyled>
</div>
</div>
<div v-if="chosenInstallOptions.length === 0" class="table-row entire-row">
<div class="table-cell table-text">No java installations found!</div>
</div>
</div>
<div class="input-group push-right">
</template>
<template #empty-state>
<div class="p-4 text-secondary">No java installations found!</div>
</template>
</Table>
<div class="flex justify-end">
<ButtonStyled type="outlined">
<button @click="$refs.detectJavaModal.hide()">
<button
class="!shadow-none !border-surface-4 !border"
@click="$refs.detectJavaModal.hide()"
>
<XIcon />
Cancel
</button>
@@ -40,7 +38,7 @@
</template>
<script setup>
import { CheckIcon, PlusIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, injectNotificationManager } from '@modrinth/ui'
import { ButtonStyled, injectNotificationManager, Table } from '@modrinth/ui'
import { ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
@@ -52,6 +50,11 @@ const { handleError } = injectNotificationManager()
const chosenInstallOptions = ref([])
const detectJavaModal = ref(null)
const currentSelected = ref({})
const javaInstallColumns = [
{ key: 'version', label: 'Version', width: '9rem' },
{ key: 'path', label: 'Path' },
{ key: 'actions', label: 'Actions', align: 'right', width: '10rem' },
]
defineExpose({
show: async (version, currentSelectedJava) => {
@@ -77,25 +80,3 @@ function setJavaInstall(javaInstall) {
})
}
</script>
<style lang="scss" scoped>
.auto-detect-modal {
.table {
.table-row {
grid-template-columns: 1fr 4fr min-content;
}
span {
display: inherit;
align-items: center;
justify-content: center;
}
padding: 0.5rem;
}
}
.manage {
display: flex;
gap: 0.5rem;
}
</style>
@@ -1,85 +1,104 @@
<template>
<JavaDetectionModal ref="detectJavaModal" @submit="(val) => emit('update:modelValue', val)" />
<div class="toggle-setting" :class="{ compact }">
<StyledInput
autocomplete="off"
:disabled="props.disabled"
:model-value="props.modelValue ? props.modelValue.path : ''"
:placeholder="placeholder ?? '/path/to/java'"
wrapper-class="installation-input"
@update:model-value="
(val) => {
emit('update:modelValue', {
...props.modelValue,
path: val,
})
}
"
/>
<div :id="props.id" class="toggle-setting" :class="{ compact }">
<div class="input-with-status">
<StyledInput
autocomplete="off"
:disabled="props.disabled"
:model-value="props.modelValue ? props.modelValue.path : ''"
:placeholder="placeholder ?? '/path/to/java'"
wrapper-class="installation-input"
@update:model-value="
(val) => {
emit('update:modelValue', {
...props.modelValue,
path: val,
})
}
"
/>
<ButtonStyled
:color="
!hoveringTest && !testingJava
? testingJavaSuccess === true
? 'green'
: 'red'
: 'standard'
"
color-fill="text"
>
<button
class="!shadow-none"
:disabled="testingJava || props.disabled"
@click="runTest(props.modelValue?.path)"
@mouseenter="!props.disabled && (hoveringTest = true)"
@mouseleave="hoveringTest = false"
>
<SpinnerIcon v-if="testingJava" class="animate-spin h-4 w-4" />
<CheckCircleIcon
v-else-if="testingJavaSuccess === true && !hoveringTest"
class="h-4 w-4"
/>
<XCircleIcon v-else-if="testingJavaSuccess !== true && !hoveringTest" class="h-4 w-4" />
<RefreshCwIcon v-else-if="!props.disabled" class="h-4 w-4" />
</button>
</ButtonStyled>
</div>
<span class="installation-buttons">
<ButtonStyled v-if="props.version">
<button :disabled="props.disabled || installingJava" @click="reinstallJava">
<button
v-tooltip="testingJavaSuccess === true ? 'Already installed' : undefined"
class="!shadow-none"
:disabled="props.disabled || installingJava || testingJavaSuccess === true"
@click="reinstallJava"
>
<DownloadIcon />
{{ installingJava ? 'Installing...' : 'Install recommended' }}
</button>
</ButtonStyled>
<ButtonStyled>
<button :disabled="props.disabled" @click="autoDetect">
<button class="!shadow-none" :disabled="props.disabled" @click="autoDetect">
<SearchIcon />
Detect
</button>
</ButtonStyled>
<ButtonStyled>
<button :disabled="props.disabled" @click="handleJavaFileInput()">
<button class="!shadow-none" :disabled="props.disabled" @click="handleJavaFileInput()">
<FolderSearchIcon />
Browse
</button>
</ButtonStyled>
<ButtonStyled v-if="testingJava">
<button disabled>Testing...</button>
</ButtonStyled>
<ButtonStyled v-else-if="testingJavaSuccess === true">
<button disabled>
<CheckIcon />
Success
</button>
</ButtonStyled>
<ButtonStyled v-else-if="testingJavaSuccess === false">
<button disabled>
<XIcon />
Failed
</button>
</ButtonStyled>
<ButtonStyled v-else>
<button :disabled="props.disabled" @click="testJava">
<PlayIcon />
Test
</button>
</ButtonStyled>
</span>
</div>
</template>
<script setup>
import {
CheckIcon,
CheckCircleIcon,
DownloadIcon,
FolderSearchIcon,
PlayIcon,
RefreshCwIcon,
SearchIcon,
XIcon,
SpinnerIcon,
XCircleIcon,
} from '@modrinth/assets'
import { ButtonStyled, injectNotificationManager, StyledInput } from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { ref } from 'vue'
import { ref, watch } from 'vue'
import JavaDetectionModal from '@/components/ui/JavaDetectionModal.vue'
import useJavaTest from '@/composables/useJavaTest'
import { trackEvent } from '@/helpers/analytics'
import { auto_install_java, find_filtered_jres, get_jre, test_jre } from '@/helpers/jre.js'
import { auto_install_java, find_filtered_jres, get_jre } from '@/helpers/jre.js'
const { handleError } = injectNotificationManager()
const props = defineProps({
id: {
type: String,
required: false,
default: null,
},
version: {
type: Number,
required: false,
@@ -110,29 +129,36 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue'])
const testingJava = ref(false)
const testingJavaSuccess = ref(null)
const {
testingJava,
javaTestResult: testingJavaSuccess,
testJavaInstallationDebounced,
testJavaInstallation,
} = useJavaTest()
const installingJava = ref(false)
const hoveringTest = ref(false)
let hasInitialized = false
async function testJava() {
testingJava.value = true
testingJavaSuccess.value = await test_jre(
props.modelValue ? props.modelValue.path : '',
props.version,
)
testingJava.value = false
trackEvent('JavaTest', {
path: props.modelValue ? props.modelValue.path : '',
success: testingJavaSuccess.value,
})
setTimeout(() => {
testingJavaSuccess.value = null
}, 2000)
async function runTest(path) {
await testJavaInstallation(path, props.version, true)
}
watch(
() => props.modelValue?.path,
(newPath) => {
if (newPath) {
if (!hasInitialized) {
testJavaInstallation(newPath, props.version, false)
hasInitialized = true
} else {
testJavaInstallationDebounced(newPath, props.version)
}
}
},
{ immediate: true },
)
async function handleJavaFileInput() {
const filePath = await open()
@@ -142,6 +168,7 @@ async function handleJavaFileInput() {
result = {
path: filePath.path ?? filePath,
version: props.version.toString(),
parsed_version: props.version,
architecture: 'x86',
}
}
@@ -175,6 +202,7 @@ async function reinstallJava() {
result = {
path: path,
version: props.version.toString(),
parsed_version: props.version,
architecture: 'x86',
}
}
@@ -186,13 +214,23 @@ async function reinstallJava() {
emit('update:modelValue', result)
installingJava.value = false
runTest(result.path)
}
</script>
<style lang="scss" scoped>
.input-with-status {
display: flex;
flex-direction: row;
align-items: center;
gap: 0.5rem;
width: 100%;
min-width: 0;
}
.installation-input {
width: 100% !important;
flex-grow: 1;
flex: 1 1 0;
min-width: 0;
}
.toggle-setting {
@@ -215,12 +253,4 @@ async function reinstallJava() {
gap: 0.5rem;
margin: 0;
}
.test-success {
color: var(--color-green);
}
.test-fail {
color: var(--color-red);
}
</style>
@@ -1,6 +1,15 @@
<script setup lang="ts">
import { CheckCircleIcon, XCircleIcon } from '@modrinth/assets'
import {
CheckCircleIcon,
CoffeeIcon,
FolderSearchIcon,
RefreshCwIcon,
SearchIcon,
SpinnerIcon,
XCircleIcon,
} from '@modrinth/assets'
import {
ButtonStyled,
Checkbox,
defineMessages,
injectNotificationManager,
@@ -8,9 +17,11 @@ import {
StyledInput,
useVIntl,
} from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { computed, readonly, ref, watch } from 'vue'
import JavaSelector from '@/components/ui/JavaSelector.vue'
import JavaDetectionModal from '@/components/ui/JavaDetectionModal.vue'
import useJavaTest from '@/composables/useJavaTest'
import useMemorySlider from '@/composables/useMemorySlider'
import { edit, get_optimal_jre_key } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
@@ -25,9 +36,54 @@ const { instance } = injectInstanceSettings()
const globalSettings = (await get().catch(handleError)) as unknown as AppSettings
const overrideJavaInstall = ref(!!instance.value.java_path)
const optimalJava = readonly(await get_optimal_jre_key(instance.value.path).catch(handleError))
const javaInstall = ref({ path: optimalJava.path ?? instance.value.java_path })
const overrideJavaInstall = ref(!!instance.value.java_path)
const javaPath = ref(instance.value.java_path ?? optimalJava?.path ?? '')
const activePath = computed(() =>
overrideJavaInstall.value ? javaPath.value : (optimalJava?.path ?? ''),
)
watch(overrideJavaInstall, (enabled) => {
if (enabled && !javaPath.value) {
javaPath.value = optimalJava?.path ?? ''
}
})
const { testingJava, javaTestResult, testJavaInstallationDebounced, testJavaInstallation } =
useJavaTest()
const hoveringTest = ref(false)
let hasInitialized = false
watch(
activePath,
(newPath) => {
if (newPath && optimalJava?.parsed_version) {
if (!hasInitialized) {
testJavaInstallation(newPath, optimalJava?.parsed_version, false)
hasInitialized = true
} else {
testJavaInstallationDebounced(newPath, optimalJava?.parsed_version)
}
}
},
{ immediate: true },
)
const javaDetectionModal = ref<{ show: (version: number, current: object) => void } | null>(null)
async function handleBrowseJava() {
const result = await open({ multiple: false })
if (result) {
javaPath.value = result
}
}
function handleDetectJava() {
javaDetectionModal.value?.show(optimalJava?.parsed_version, { path: javaPath.value })
}
const overrideJavaArgs = ref((instance.value.extra_launch_args?.length ?? 0) > 0)
const javaArgs = ref(
@@ -51,8 +107,8 @@ const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) a
const editProfileObject = computed(() => {
return {
java_path:
overrideJavaInstall.value && javaInstall.value.path !== ''
? javaInstall.value.path.replace('java.exe', 'javaw.exe')
overrideJavaInstall.value && javaPath.value
? javaPath.value.replace('java.exe', 'javaw.exe')
: null,
extra_launch_args: overrideJavaArgs.value
? javaArgs.value.trim().split(/\s+/).filter(Boolean)
@@ -71,7 +127,7 @@ const editProfileObject = computed(() => {
watch(
[
overrideJavaInstall,
javaInstall,
javaPath,
overrideJavaArgs,
javaArgs,
overrideEnvVars,
@@ -90,17 +146,45 @@ const messages = defineMessages({
id: 'instance.settings.tabs.java.java-installation',
defaultMessage: 'Java installation',
},
customJavaInstallation: {
id: 'instance.settings.tabs.java.custom-java-installation',
defaultMessage: 'Custom Java installation',
},
javaPathPlaceholder: {
id: 'instance.settings.tabs.java.java-path-placeholder',
defaultMessage: '/path/to/java',
},
javaMemory: {
id: 'instance.settings.tabs.java.java-memory',
defaultMessage: 'Memory allocated',
},
customMemoryAllocation: {
id: 'instance.settings.tabs.java.custom-memory-allocation',
defaultMessage: 'Custom memory allocation',
},
javaArguments: {
id: 'instance.settings.tabs.java.java-arguments',
defaultMessage: 'Java arguments',
},
customJavaArguments: {
id: 'instance.settings.tabs.java.custom-java-arguments',
defaultMessage: 'Custom Java arguments',
},
enterJavaArguments: {
id: 'instance.settings.tabs.java.enter-java-arguments',
defaultMessage: 'Enter Java arguments...',
},
javaEnvironmentVariables: {
id: 'instance.settings.tabs.java.environment-variables',
defaultMessage: 'Environment variables',
},
javaMemory: {
id: 'instance.settings.tabs.java.java-memory',
defaultMessage: 'Memory allocated',
customEnvironmentVariables: {
id: 'instance.settings.tabs.java.custom-environment-variables',
defaultMessage: 'Custom environment variables',
},
enterEnvironmentVariables: {
id: 'instance.settings.tabs.java.enter-environment-variables',
defaultMessage: 'Enter environmental variables...',
},
hooks: {
id: 'instance.settings.tabs.java.hooks',
@@ -111,43 +195,86 @@ const messages = defineMessages({
<template>
<div>
<h2 id="project-name" class="m-0 mb-2.5 text-lg font-semibold text-contrast block">
<JavaDetectionModal ref="javaDetectionModal" @submit="(val) => (javaPath = val.path)" />
<h2 class="m-0 mb-2 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.javaInstallation) }}
</h2>
<Checkbox v-model="overrideJavaInstall" label="Custom Java installation" class="mb-2.5" />
<template v-if="!overrideJavaInstall">
<div class="flex my-2 items-center gap-2 font-semibold">
<template v-if="javaInstall">
<CheckCircleIcon class="text-brand-green h-4 w-4" />
<span>Using default Java {{ optimalJava.major_version }} installation:</span>
</template>
<template v-else-if="optimalJava">
<XCircleIcon class="text-brand-red h-5 w-5" />
<span
>Could not find a default Java {{ optimalJava.major_version }} installation. Please set
one below:</span
<Checkbox
v-model="overrideJavaInstall"
:label="formatMessage(messages.customJavaInstallation)"
class="mb-2"
/>
<div class="flex gap-4 p-4 bg-bg rounded-2xl">
<div class="flex gap-3 items-start flex-1 min-w-0">
<div
class="w-10 h-10 flex items-center justify-center rounded-full bg-button-bg border-solid border-[1px] border-button-border p-2 mt-1 shrink-0 [&_svg]:h-full [&_svg]:w-full"
>
<CoffeeIcon />
</div>
<div class="flex flex-col gap-2 flex-1 min-w-0">
<span class="font-semibold leading-none mt-2"
>Java {{ optimalJava?.parsed_version }}</span
>
</template>
<template v-else>
<XCircleIcon class="text-brand-red h-5 w-5" />
<span
>Could not automatically determine a Java installation to use. Please set one
below:</span
>
</template>
<div class="flex gap-2 items-center">
<StyledInput
:model-value="activePath"
:disabled="!overrideJavaInstall"
autocomplete="off"
:placeholder="formatMessage(messages.javaPathPlaceholder)"
wrapper-class="flex-1 min-w-0"
@update:model-value="(val) => (javaPath = String(val))"
/>
<ButtonStyled
:color="
!hoveringTest && !testingJava
? javaTestResult === true
? 'green'
: 'red'
: 'standard'
"
color-fill="text"
>
<button
:disabled="!overrideJavaInstall || testingJava"
@click="testJavaInstallation(activePath, optimalJava?.parsed_version, true)"
@mouseenter="overrideJavaInstall && (hoveringTest = true)"
@mouseleave="hoveringTest = false"
>
<SpinnerIcon v-if="testingJava" class="animate-spin h-4 w-4" />
<CheckCircleIcon
v-else-if="javaTestResult === true && !hoveringTest"
class="h-4 w-4"
/>
<XCircleIcon v-else-if="javaTestResult !== true && !hoveringTest" class="h-4 w-4" />
<RefreshCwIcon v-else-if="overrideJavaInstall" class="h-4 w-4" />
</button>
</ButtonStyled>
</div>
<div v-if="overrideJavaInstall" class="flex gap-2">
<ButtonStyled>
<button @click="handleDetectJava">
<SearchIcon />
Detect
</button>
</ButtonStyled>
<ButtonStyled>
<button @click="handleBrowseJava">
<FolderSearchIcon />
Browse
</button>
</ButtonStyled>
</div>
</div>
</div>
<div
v-if="javaInstall && !overrideJavaInstall"
class="p-4 bg-bg rounded-xl text-xs text-secondary leading-none font-mono"
>
{{ javaInstall.path }}
</div>
</template>
<JavaSelector v-if="overrideJavaInstall || !javaInstall" v-model="javaInstall" />
<h2 id="project-name" class="mt-6 mb-2.5 text-lg font-semibold text-contrast block">
</div>
<h2 class="mt-4 mb-1 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.javaMemory) }}
</h2>
<Checkbox v-model="overrideMemorySettings" label="Custom memory allocation" class="mb-2.5" />
<Checkbox
v-model="overrideMemorySettings"
:label="formatMessage(messages.customMemoryAllocation)"
class="mb-2"
/>
<Slider
id="max-memory"
v-model="memory.maximum"
@@ -159,28 +286,36 @@ const messages = defineMessages({
:snap-range="512"
unit="MB"
/>
<h2 id="project-name" class="mt-6 mb-2.5 text-lg font-semibold text-contrast block">
<h2 class="mt-4 mb-1 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.javaArguments) }}
</h2>
<Checkbox v-model="overrideJavaArgs" label="Custom java arguments" class="my-2" />
<Checkbox
v-model="overrideJavaArgs"
:label="formatMessage(messages.customJavaArguments)"
class="my-2"
/>
<StyledInput
id="java-args"
v-model="javaArgs"
autocomplete="off"
:disabled="!overrideJavaArgs"
placeholder="Enter java arguments..."
:placeholder="formatMessage(messages.enterJavaArguments)"
wrapper-class="w-full"
/>
<h2 id="project-name" class="mt-6 mb-2.5 text-lg font-semibold text-contrast block">
<h2 class="mt-4 mb-1 text-lg font-extrabold text-contrast block">
{{ formatMessage(messages.javaEnvironmentVariables) }}
</h2>
<Checkbox v-model="overrideEnvVars" label="Custom environment variables" class="mb-2.5" />
<Checkbox
v-model="overrideEnvVars"
:label="formatMessage(messages.customEnvironmentVariables)"
class="mb-2"
/>
<StyledInput
id="env-vars"
v-model="envVars"
autocomplete="off"
:disabled="!overrideEnvVars"
placeholder="Enter environmental variables..."
:placeholder="formatMessage(messages.enterEnvironmentVariables)"
wrapper-class="w-full"
/>
</div>
@@ -160,7 +160,16 @@ watch(
</h2>
<p class="m-0 mt-1">{{ formatMessage(messages.hideNametagDescription) }}</p>
</div>
<Toggle id="hide-nametag-skins-page" v-model="settings.hide_nametag_skins_page" />
<Toggle
id="hide-nametag-skins-page"
:model-value="themeStore.hideNametagSkinsPage"
@update:model-value="
(e) => {
themeStore.hideNametagSkinsPage = !!e
settings.hide_nametag_skins_page = themeStore.hideNametagSkinsPage
}
"
/>
</div>
<div v-if="os !== 'MacOS'" class="mt-6 flex items-center justify-between gap-4">
@@ -1,149 +1,242 @@
<template>
<UploadSkinModal ref="uploadModal" />
<ModalWrapper ref="modal" @on-hide="resetState">
<NewModal ref="modal" :on-hide="handleModalHide">
<template #title>
<span class="text-lg font-extrabold text-contrast">
{{ mode === 'edit' ? 'Editing skin' : 'Adding a skin' }}
{{ formatMessage(mode === 'edit' ? messages.editSkinTitle : messages.addSkinTitle) }}
</span>
</template>
<div class="flex flex-col md:flex-row gap-6">
<div class="max-h-[25rem] w-[16rem] min-w-[16rem] overflow-hidden relative">
<div class="absolute top-[-4rem] left-0 h-[32rem] w-[16rem] flex-shrink-0">
<SkinPreviewRenderer
:variant="variant"
:texture-src="previewSkin || ''"
:cape-src="selectedCapeTexture"
:scale="1.4"
:fov="50"
:initial-rotation="Math.PI / 8"
class="h-full w-full"
/>
</div>
<div class="h-[25rem] w-[16rem] min-w-[16rem] flex-shrink-0 md:self-center">
<SkinPreviewRenderer
:variant="variant"
:texture-src="previewSkin || ''"
:cape-src="selectedCapeTexture"
framing="modal"
:initial-rotation="Math.PI / 8"
class="h-full w-full"
/>
</div>
<div class="flex flex-col gap-4 w-full min-h-[20rem]">
<section>
<h2 class="text-base font-semibold mb-2">Texture</h2>
<section v-if="mode === 'edit' && canEditTextureAndModel">
<h2 class="text-base font-semibold mb-2">{{ formatMessage(messages.textureSection) }}</h2>
<ButtonStyled>
<button @click="openUploadSkinModal"><UploadIcon /> Replace texture</button>
<button class="!shadow-none" @click="openTextureFileBrowser">
<UploadIcon /> {{ formatMessage(messages.replaceTextureButton) }}
</button>
</ButtonStyled>
<input
ref="textureFileInput"
type="file"
accept="image/png"
class="hidden"
@change="onTextureFileInputChange"
/>
</section>
<section>
<h2 class="text-base font-semibold mb-2">Arm style</h2>
<section v-if="canEditTextureAndModel">
<h2 class="text-base font-semibold mb-2">
{{ formatMessage(messages.armStyleSection) }}
</h2>
<RadioButtons v-model="variant" :items="['CLASSIC', 'SLIM']">
<template #default="{ item }">
{{ item === 'CLASSIC' ? 'Wide' : 'Slim' }}
{{
formatMessage(item === 'CLASSIC' ? messages.wideArmStyle : messages.slimArmStyle)
}}
</template>
</RadioButtons>
</section>
<section>
<h2 class="text-base font-semibold mb-2">Cape</h2>
<div class="flex gap-2">
<CapeButton
v-if="defaultCape"
:id="defaultCape.id"
:texture="defaultCape.texture"
:name="undefined"
:selected="!selectedCape"
faded
@select="selectCape(undefined)"
<h2 class="text-base font-semibold mb-2">{{ formatMessage(messages.capeSection) }}</h2>
<div class="relative w-fit max-w-full">
<Transition
enter-active-class="transition-all duration-200 ease-out"
enter-from-class="opacity-0 max-h-0"
enter-to-class="opacity-100 max-h-6"
leave-active-class="transition-all duration-200 ease-in"
leave-from-class="opacity-100 max-h-6"
leave-to-class="opacity-0 max-h-0"
>
<span>Use default cape</span>
</CapeButton>
<CapeLikeTextButton v-else :highlighted="!selectedCape" @click="selectCape(undefined)">
<span>Use default cape</span>
</CapeLikeTextButton>
<div
v-if="showCapeTopFade"
class="pointer-events-none absolute left-0 right-0 top-0 z-10 h-6 bg-gradient-to-b from-bg-raised to-transparent"
/>
</Transition>
<CapeButton
v-for="cape in visibleCapeList"
:id="cape.id"
:key="cape.id"
:texture="cape.texture"
:name="cape.name || 'Cape'"
:selected="selectedCape?.id === cape.id"
@select="selectCape(cape)"
/>
<CapeLikeTextButton
v-if="(capes?.length ?? 0) > 2"
tooltip="View more capes"
@mouseup="openSelectCapeModal"
<div
ref="capeListRef"
class="grid grid-cols-[repeat(4,max-content)] auto-rows-max gap-2 overflow-y-auto pr-1"
:style="{ maxHeight: capeListMaxHeight }"
@scroll="checkCapeScrollState"
>
<template #icon><ChevronRightIcon /></template>
<span>More</span>
</CapeLikeTextButton>
<CapeLikeTextButton
:tooltip="formatMessage(messages.noCapeTooltip)"
:highlighted="!selectedCape"
@click="selectCape(undefined)"
>
<template #icon><XIcon /></template>
<span>{{ formatMessage(messages.noneCapeOption) }}</span>
</CapeLikeTextButton>
<CapeButton
v-for="cape in sortedCapes"
:id="cape.id"
:key="cape.id"
:texture="cape.texture"
:name="cape.name || formatMessage(messages.capeFallbackName)"
:selected="selectedCape?.id === cape.id"
@select="selectCape(cape)"
/>
</div>
<Transition
enter-active-class="transition-all duration-200 ease-out"
enter-from-class="opacity-0 max-h-0"
enter-to-class="opacity-100 max-h-6"
leave-active-class="transition-all duration-200 ease-in"
leave-from-class="opacity-100 max-h-6"
leave-to-class="opacity-0 max-h-0"
>
<div
v-if="showCapeBottomFade"
class="pointer-events-none absolute bottom-0 left-0 right-0 z-10 h-6 bg-gradient-to-t from-bg-raised to-transparent"
/>
</Transition>
</div>
</section>
</div>
</div>
<div class="flex gap-2 mt-12">
<ButtonStyled color="brand">
<button v-tooltip="saveTooltip" :disabled="disableSave || isSaving" @click="save">
<SpinnerIcon v-if="isSaving" class="animate-spin" />
<CheckIcon v-else-if="mode === 'new'" />
<SaveIcon v-else />
{{ mode === 'new' ? 'Add skin' : 'Save skin' }}
</button>
</ButtonStyled>
<ButtonStyled type="outlined">
<button :disabled="isSaving" @click="hide"><XIcon />Cancel</button>
</ButtonStyled>
</div>
</ModalWrapper>
<SelectCapeModal
ref="selectCapeModal"
:capes="capes || []"
@select="handleCapeSelected"
@cancel="handleCapeCancel"
/>
<template #actions>
<div class="flex gap-2 justify-end">
<ButtonStyled type="outlined">
<button :disabled="isSaving" @click="hide">
<XIcon />{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand">
<button v-tooltip="saveTooltip" :disabled="disableSave || isSaving" @click="save">
<SpinnerIcon v-if="isSaving" class="animate-spin" />
<CheckIcon v-else-if="mode === 'new'" />
<SaveIcon v-else />
{{ formatMessage(mode === 'new' ? messages.addSkinButton : messages.saveSkinButton) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
</template>
<script setup lang="ts">
import {
CheckIcon,
ChevronRightIcon,
SaveIcon,
SpinnerIcon,
UploadIcon,
XIcon,
} from '@modrinth/assets'
import { CheckIcon, SaveIcon, SpinnerIcon, UploadIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
CapeButton,
CapeLikeTextButton,
commonMessages,
defineMessages,
injectNotificationManager,
NewModal,
RadioButtons,
SkinPreviewRenderer,
useScrollIndicator,
useVIntl,
} from '@modrinth/ui'
import { computed, ref, useTemplateRef, watch } from 'vue'
import { arrayBufferToBase64 } from '@modrinth/utils'
import { computed, nextTick, ref, useTemplateRef, watch } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import SelectCapeModal from '@/components/ui/skin/SelectCapeModal.vue'
import UploadSkinModal from '@/components/ui/skin/UploadSkinModal.vue'
import {
add_and_equip_custom_skin,
type Cape,
determineModelType,
equip_skin,
get_normalized_skin_texture,
remove_custom_skin,
normalize_skin_texture,
save_custom_skin,
type Skin,
type SkinModel,
type SkinTextureUrl,
unequip_skin,
} from '@/helpers/skins.ts'
const CAPE_LIST_MAX_HEIGHT = 334
const messages = defineMessages({
editSkinTitle: {
id: 'app.skins.modal.edit-title',
defaultMessage: 'Editing skin',
},
addSkinTitle: {
id: 'app.skins.modal.add-title',
defaultMessage: 'Adding a skin',
},
textureSection: {
id: 'app.skins.modal.texture-section',
defaultMessage: 'Texture',
},
replaceTextureButton: {
id: 'app.skins.modal.replace-texture-button',
defaultMessage: 'Replace texture',
},
armStyleSection: {
id: 'app.skins.modal.arm-style-section',
defaultMessage: 'Arm style',
},
wideArmStyle: {
id: 'app.skins.modal.arm-style-wide',
defaultMessage: 'Wide',
},
slimArmStyle: {
id: 'app.skins.modal.arm-style-slim',
defaultMessage: 'Slim',
},
capeSection: {
id: 'app.skins.modal.cape-section',
defaultMessage: 'Cape',
},
noCapeTooltip: {
id: 'app.skins.modal.no-cape-tooltip',
defaultMessage: 'No cape',
},
noneCapeOption: {
id: 'app.skins.modal.none-cape-option',
defaultMessage: 'None',
},
capeFallbackName: {
id: 'app.skins.modal.cape-fallback-name',
defaultMessage: 'Cape',
},
savingTooltip: {
id: 'app.skins.modal.saving-tooltip',
defaultMessage: 'Saving...',
},
uploadSkinFirstTooltip: {
id: 'app.skins.modal.upload-skin-first-tooltip',
defaultMessage: 'Upload a skin first!',
},
makeEditFirstTooltip: {
id: 'app.skins.modal.make-edit-first-tooltip',
defaultMessage: 'Make an edit to the skin first!',
},
addSkinButton: {
id: 'app.skins.modal.add-skin-button',
defaultMessage: 'Add skin',
},
saveSkinButton: {
id: 'app.skins.modal.save-skin-button',
defaultMessage: 'Save skin',
},
})
const { formatMessage } = useVIntl()
const { handleError } = injectNotificationManager()
const modal = useTemplateRef('modal')
const selectCapeModal = useTemplateRef('selectCapeModal')
const textureFileInput = useTemplateRef<HTMLInputElement>('textureFileInput')
const capeListRef = ref<HTMLElement | null>(null)
const capeListMaxHeight = ref(`${CAPE_LIST_MAX_HEIGHT}px`)
const mode = ref<'new' | 'edit'>('new')
const currentSkin = ref<Skin | null>(null)
const shouldRestoreModal = ref(false)
const isSaving = ref(false)
const uploadedTextureUrl = ref<SkinTextureUrl | null>(null)
@@ -151,10 +244,49 @@ const previewSkin = ref<string>('')
const variant = ref<SkinModel>('CLASSIC')
const selectedCape = ref<Cape | undefined>(undefined)
const props = defineProps<{ capes?: Cape[]; defaultCape?: Cape }>()
const props = defineProps<{ capes?: Cape[] }>()
const selectedCapeTexture = computed(() => selectedCape.value?.texture)
const visibleCapeList = ref<Cape[]>([])
const canEditTextureAndModel = computed(() => currentSkin.value?.source !== 'default')
const {
showTopFade: showCapeTopFade,
showBottomFade: showCapeBottomFade,
checkScrollState: checkCapeScrollState,
forceCheck: forceCapeScrollCheck,
} = useScrollIndicator(capeListRef)
let capeListLayoutFrame: number | null = null
function updateCapeListLayout() {
const capeList = capeListRef.value
const modalContent = capeList?.closest('[data-modal-content]') as HTMLElement | null
if (!capeList || !modalContent) {
capeListMaxHeight.value = `${CAPE_LIST_MAX_HEIGHT}px`
forceCapeScrollCheck()
return
}
const availableHeight =
modalContent.getBoundingClientRect().bottom - capeList.getBoundingClientRect().top
capeListMaxHeight.value = `${Math.min(
CAPE_LIST_MAX_HEIGHT,
Math.max(0, Math.floor(availableHeight)),
)}px`
nextTick(() => forceCapeScrollCheck())
}
function refreshCapeListLayout() {
if (capeListLayoutFrame !== null) {
cancelAnimationFrame(capeListLayoutFrame)
}
capeListLayoutFrame = requestAnimationFrame(() => {
capeListLayoutFrame = null
updateCapeListLayout()
})
}
const sortedCapes = computed(() => {
return [...(props.capes || [])].sort((a, b) => {
@@ -164,32 +296,6 @@ const sortedCapes = computed(() => {
})
})
function initVisibleCapeList() {
if (!props.capes || props.capes.length === 0) {
visibleCapeList.value = []
return
}
if (visibleCapeList.value.length === 0) {
if (selectedCape.value) {
const otherCape = getSortedCapeExcluding(selectedCape.value.id)
visibleCapeList.value = otherCape ? [selectedCape.value, otherCape] : [selectedCape.value]
} else {
visibleCapeList.value = getSortedCapes(2)
}
}
}
function getSortedCapes(count: number): Cape[] {
if (!sortedCapes.value || sortedCapes.value.length === 0) return []
return sortedCapes.value.slice(0, count)
}
function getSortedCapeExcluding(excludeId: string): Cape | undefined {
if (!sortedCapes.value || sortedCapes.value.length <= 1) return undefined
return sortedCapes.value.find((cape) => cape.id !== excludeId)
}
async function loadPreviewSkin() {
if (uploadedTextureUrl.value) {
previewSkin.value = uploadedTextureUrl.value.normalized
@@ -221,9 +327,13 @@ const disableSave = computed(
)
const saveTooltip = computed(() => {
if (isSaving.value) return 'Saving...'
if (mode.value === 'new' && !uploadedTextureUrl.value) return 'Upload a skin first!'
if (mode.value === 'edit' && !hasEdits.value) return 'Make an edit to the skin first!'
if (isSaving.value) return formatMessage(messages.savingTooltip)
if (mode.value === 'new' && !uploadedTextureUrl.value) {
return formatMessage(messages.uploadSkinFirstTooltip)
}
if (mode.value === 'edit' && !hasEdits.value) {
return formatMessage(messages.makeEditFirstTooltip)
}
return undefined
})
@@ -234,11 +344,13 @@ function resetState() {
previewSkin.value = ''
variant.value = 'CLASSIC'
selectedCape.value = undefined
visibleCapeList.value = []
shouldRestoreModal.value = false
isSaving.value = false
}
function handleModalHide() {
setTimeout(() => resetState(), 250)
}
async function show(e: MouseEvent, skin?: Skin) {
mode.value = skin ? 'edit' : 'new'
currentSkin.value = skin ?? null
@@ -249,12 +361,11 @@ async function show(e: MouseEvent, skin?: Skin) {
variant.value = 'CLASSIC'
selectedCape.value = undefined
}
visibleCapeList.value = []
initVisibleCapeList()
await loadPreviewSkin()
modal.value?.show(e)
nextTick(() => refreshCapeListLayout())
}
async function showNew(e: MouseEvent, skinTextureUrl: SkinTextureUrl) {
@@ -263,98 +374,54 @@ async function showNew(e: MouseEvent, skinTextureUrl: SkinTextureUrl) {
uploadedTextureUrl.value = skinTextureUrl
variant.value = await determineModelType(skinTextureUrl.original)
selectedCape.value = undefined
visibleCapeList.value = []
initVisibleCapeList()
await loadPreviewSkin()
modal.value?.show(e)
nextTick(() => refreshCapeListLayout())
}
async function restoreWithNewTexture(skinTextureUrl: SkinTextureUrl) {
async function setUploadedTexture(skinTextureUrl: SkinTextureUrl) {
uploadedTextureUrl.value = skinTextureUrl
await loadPreviewSkin()
if (shouldRestoreModal.value) {
setTimeout(() => {
modal.value?.show()
shouldRestoreModal.value = false
}, 0)
}
nextTick(() => refreshCapeListLayout())
}
function hide() {
modal.value?.hide()
setTimeout(() => resetState(), 250)
}
function selectCape(cape: Cape | undefined) {
if (cape && selectedCape.value?.id !== cape.id) {
const isInVisibleList = visibleCapeList.value.some((c) => c.id === cape.id)
if (!isInVisibleList && visibleCapeList.value.length > 0) {
visibleCapeList.value.splice(0, 1, cape)
if (visibleCapeList.value.length > 1 && visibleCapeList.value[1].id === cape.id) {
const otherCape = getSortedCapeExcluding(cape.id)
if (otherCape) {
visibleCapeList.value.splice(1, 1, otherCape)
}
}
}
}
selectedCape.value = cape
}
function handleCapeSelected(cape: Cape | undefined) {
selectCape(cape)
function openTextureFileBrowser() {
textureFileInput.value?.click()
}
if (shouldRestoreModal.value) {
setTimeout(() => {
modal.value?.show()
shouldRestoreModal.value = false
}, 0)
async function onTextureFileInputChange(e: Event) {
const files = (e.target as HTMLInputElement).files
const file = files?.[0]
if (!file) {
return
}
}
function handleCapeCancel() {
if (shouldRestoreModal.value) {
setTimeout(() => {
modal.value?.show()
shouldRestoreModal.value = false
}, 0)
}
}
function openSelectCapeModal(e: MouseEvent) {
if (!selectCapeModal.value) return
shouldRestoreModal.value = true
modal.value?.hide()
setTimeout(() => {
selectCapeModal.value?.show(
e,
currentSkin.value?.texture_key,
selectedCape.value,
previewSkin.value,
variant.value,
)
}, 0)
}
function openUploadSkinModal(e: MouseEvent) {
shouldRestoreModal.value = true
modal.value?.hide()
emit('open-upload-modal', e)
}
function restoreModal() {
if (shouldRestoreModal.value) {
setTimeout(() => {
const fakeEvent = new MouseEvent('click')
modal.value?.show(fakeEvent)
shouldRestoreModal.value = false
}, 500)
try {
const originalSkinTexUrl = `data:image/png;base64,${arrayBufferToBase64(
await file.arrayBuffer(),
)}`
const skinTextureNormalized = await normalize_skin_texture(originalSkinTexUrl)
await setUploadedTexture({
original: originalSkinTexUrl,
normalized: `data:image/png;base64,${arrayBufferToBase64(skinTextureNormalized)}`,
})
} catch (error) {
handleError(error)
} finally {
if (textureFileInput.value) {
textureFileInput.value.value = ''
}
}
}
@@ -370,17 +437,32 @@ async function save() {
textureUrl = currentSkin.value!.texture
}
await unequip_skin()
const bytes: Uint8Array = new Uint8Array(await (await fetch(textureUrl)).arrayBuffer())
if (mode.value === 'new') {
await add_and_equip_custom_skin(bytes, variant.value, selectedCape.value)
emit('saved')
const addedSkin = await add_and_equip_custom_skin(bytes, variant.value, selectedCape.value)
emit('saved', {
applied: true,
skin: addedSkin,
})
} else {
await add_and_equip_custom_skin(bytes, variant.value, selectedCape.value)
await remove_custom_skin(currentSkin.value!)
emit('saved')
const updatedSkin = await save_custom_skin(
currentSkin.value!,
bytes,
variant.value,
selectedCape.value,
!!uploadedTextureUrl.value && textureUrl !== currentSkin.value?.texture,
)
if (currentSkin.value?.is_equipped) {
await equip_skin(updatedSkin)
}
emit('saved', {
applied: !!currentSkin.value?.is_equipped,
skin: updatedSkin,
previousSkin: currentSkin.value!,
})
}
hide()
@@ -393,28 +475,53 @@ async function save() {
watch([uploadedTextureUrl, currentSkin], async () => {
await loadPreviewSkin()
refreshCapeListLayout()
})
watch(
() => props.capes,
() => {
initVisibleCapeList()
nextTick(() => refreshCapeListLayout())
},
{ immediate: true },
)
watch(
capeListRef,
(capeList, _, onCleanup) => {
if (!capeList) return
const modalContent = capeList.closest('[data-modal-content]')
const resizeObserver = new ResizeObserver(() => refreshCapeListLayout())
if (modalContent instanceof HTMLElement) {
resizeObserver.observe(modalContent)
}
window.addEventListener('resize', refreshCapeListLayout, { passive: true })
refreshCapeListLayout()
onCleanup(() => {
resizeObserver.disconnect()
window.removeEventListener('resize', refreshCapeListLayout)
if (capeListLayoutFrame !== null) {
cancelAnimationFrame(capeListLayoutFrame)
capeListLayoutFrame = null
}
})
},
{ flush: 'post' },
)
const emit = defineEmits<{
(event: 'saved'): void
(event: 'saved', options: { applied: boolean; skin?: Skin; previousSkin?: Skin }): void
(event: 'deleted', skin: Skin): void
(event: 'open-upload-modal', mouseEvent: MouseEvent): void
}>()
defineExpose({
show,
showNew,
restoreWithNewTexture,
hide,
shouldRestoreModal,
restoreModal,
})
</script>
@@ -1,141 +0,0 @@
<script setup lang="ts">
import { CheckIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
CapeButton,
CapeLikeTextButton,
ScrollablePanel,
SkinPreviewRenderer,
} from '@modrinth/ui'
import { computed, ref, useTemplateRef } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import type { Cape, SkinModel } from '@/helpers/skins.ts'
const modal = useTemplateRef('modal')
const emit = defineEmits<{
(e: 'select', cape: Cape | undefined): void
(e: 'cancel'): void
}>()
const props = defineProps<{
capes: Cape[]
}>()
const sortedCapes = computed(() => {
return [...props.capes].sort((a, b) => {
const nameA = (a.name || '').toLowerCase()
const nameB = (b.name || '').toLowerCase()
return nameA.localeCompare(nameB)
})
})
const currentSkinId = ref<string | undefined>()
const currentSkinTexture = ref<string | undefined>()
const currentSkinVariant = ref<SkinModel>('CLASSIC')
const currentCapeTexture = computed<string | undefined>(() => currentCape.value?.texture)
const currentCape = ref<Cape | undefined>()
function show(
e: MouseEvent,
skinId?: string,
selected?: Cape,
skinTexture?: string,
variant?: SkinModel,
) {
currentSkinId.value = skinId
currentSkinTexture.value = skinTexture
currentSkinVariant.value = variant || 'CLASSIC'
currentCape.value = selected
modal.value?.show(e)
}
function select() {
emit('select', currentCape.value)
hide()
}
function hide() {
modal.value?.hide()
emit('cancel')
}
function updateSelectedCape(cape: Cape | undefined) {
currentCape.value = cape
}
function onModalHide() {
emit('cancel')
}
defineExpose({
show,
hide,
})
</script>
<template>
<ModalWrapper ref="modal" @on-hide="onModalHide">
<template #title>
<div class="flex flex-col">
<span class="text-lg font-extrabold text-heading">Change cape</span>
</div>
</template>
<div class="flex flex-col md:flex-row gap-6">
<div class="max-h-[25rem] h-[25rem] w-[16rem] min-w-[16rem] overflow-hidden relative">
<div class="absolute top-[-4rem] left-0 h-[32rem] w-[16rem] flex-shrink-0">
<SkinPreviewRenderer
v-if="currentSkinTexture"
:cape-src="currentCapeTexture"
:texture-src="currentSkinTexture"
:variant="currentSkinVariant"
:scale="1.4"
:fov="50"
:initial-rotation="Math.PI + Math.PI / 8"
class="h-full w-full"
/>
</div>
</div>
<div class="flex flex-col gap-4 w-full my-auto">
<ScrollablePanel class="max-h-[20rem] max-w-[30rem] mb-5 h-full">
<div class="flex flex-wrap gap-2 justify-center content-start overflow-y-auto h-full">
<CapeLikeTextButton
tooltip="No Cape"
:highlighted="!currentCape"
@click="updateSelectedCape(undefined)"
>
<template #icon>
<XIcon />
</template>
<span>None</span>
</CapeLikeTextButton>
<CapeButton
v-for="cape in sortedCapes"
:id="cape.id"
:key="cape.id"
:name="cape.name"
:texture="cape.texture"
:selected="currentCape?.id === cape.id"
@select="updateSelectedCape(cape)"
/>
</div>
</ScrollablePanel>
</div>
</div>
<div class="flex gap-2 items-center">
<ButtonStyled color="brand">
<button @click="select">
<CheckIcon />
Select
</button>
</ButtonStyled>
<ButtonStyled>
<button @click="hide">
<XIcon />
Cancel
</button>
</ButtonStyled>
</div>
</ModalWrapper>
</template>
@@ -1,141 +0,0 @@
<template>
<ModalWrapper ref="modal" @on-hide="hide(true)">
<template #title>
<span class="text-lg font-extrabold text-contrast"> Upload skin texture </span>
</template>
<div class="relative">
<div
class="border-2 border-dashed border-highlight-gray rounded-xl h-[173px] flex flex-col items-center justify-center p-8 cursor-pointer bg-button-bg hover:bg-button-hover transition-colors relative"
@click="triggerFileInput"
>
<p class="mx-auto mb-0 text-primary font-bold text-lg text-center flex items-center gap-2">
<UploadIcon /> Select skin texture file
</p>
<p class="mx-auto mt-0 text-secondary text-sm text-center">
Drag and drop or click here to browse
</p>
<input
ref="fileInput"
type="file"
accept="image/png"
class="hidden"
@change="handleInputFileChange"
/>
</div>
</div>
</ModalWrapper>
</template>
<script setup lang="ts">
import { UploadIcon } from '@modrinth/assets'
import { injectNotificationManager } from '@modrinth/ui'
import { getCurrentWebview } from '@tauri-apps/api/webview'
import { onBeforeUnmount, ref, watch } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { get_dragged_skin_data } from '@/helpers/skins'
const { addNotification } = injectNotificationManager()
const modal = ref()
const fileInput = ref<HTMLInputElement>()
const unlisten = ref<() => void>()
const modalVisible = ref(false)
const emit = defineEmits<{
(e: 'uploaded', data: ArrayBuffer): void
(e: 'canceled'): void
}>()
function show(e?: MouseEvent) {
modal.value?.show(e)
modalVisible.value = true
setupDragDropListener()
}
function hide(emitCanceled = false) {
modal.value?.hide()
modalVisible.value = false
cleanupDragDropListener()
resetState()
if (emitCanceled) {
emit('canceled')
}
}
function resetState() {
if (fileInput.value) fileInput.value.value = ''
}
function triggerFileInput() {
fileInput.value?.click()
}
async function handleInputFileChange(e: Event) {
const files = (e.target as HTMLInputElement).files
if (!files || files.length === 0) {
return
}
const file = files[0]
const buffer = await file.arrayBuffer()
await processData(buffer)
}
async function setupDragDropListener() {
try {
if (modalVisible.value) {
await cleanupDragDropListener()
unlisten.value = await getCurrentWebview().onDragDropEvent(async (event) => {
if (event.payload.type !== 'drop') {
return
}
if (!event.payload.paths || event.payload.paths.length === 0) {
return
}
const filePath = event.payload.paths[0]
try {
const data = await get_dragged_skin_data(filePath)
await processData(data.buffer)
} catch (error) {
addNotification({
title: 'Error processing file',
text: error instanceof Error ? error.message : 'Failed to read the dropped file.',
type: 'error',
})
}
})
}
} catch (error) {
console.error('Failed to set up drag and drop listener:', error)
}
}
async function cleanupDragDropListener() {
if (unlisten.value) {
unlisten.value()
unlisten.value = undefined
}
}
async function processData(buffer: ArrayBuffer) {
emit('uploaded', buffer)
hide()
}
watch(modalVisible, (isVisible) => {
if (isVisible) {
setupDragDropListener()
} else {
cleanupDragDropListener()
}
})
onBeforeUnmount(() => {
cleanupDragDropListener()
})
defineExpose({ show, hide })
</script>
@@ -0,0 +1,410 @@
<script setup lang="ts">
import { DropdownIcon, EditIcon, PlusIcon, TrashIcon } from '@modrinth/assets'
import {
Accordion,
ButtonStyled,
commonMessages,
defineMessages,
SkinButton,
SkinLikeTextButton,
useScrollViewport,
useVIntl,
} from '@modrinth/ui'
import { useElementSize, useWindowSize } from '@vueuse/core'
import { computed, nextTick, onUnmounted, ref, useTemplateRef, watch } from 'vue'
import type { RenderResult } from '@/helpers/rendering/batch-skin-renderer.ts'
import type { Skin } from '@/helpers/skins.ts'
type SkinSectionKind = 'saved' | 'default'
type SkinLikeTextButtonExpose = {
getRootElement: () => HTMLElement | null | undefined
}
type AddSkinButtonRef = SkinLikeTextButtonExpose | SkinLikeTextButtonExpose[]
interface DefaultSkinSection {
title: string
skins: Skin[]
}
interface SkinSection {
key: string
title: string
kind: SkinSectionKind
skins: Skin[]
}
interface VirtualSkinSection {
section: SkinSection
top: number
index: number
}
const SKIN_CARD_ASPECT_WIDTH = 31
const SKIN_CARD_ASPECT_HEIGHT = 40
const SKIN_GRID_GAP = 12
const SKIN_SECTION_FIRST_SPACING = 4
const SKIN_SECTION_SPACING = 24
const SKIN_SECTION_HEADER_HEIGHT = 28
const SKIN_SECTION_CONTENT_SPACING = 8
const SKIN_SECTION_OVERSCAN = 900
const FALLBACK_CARD_WIDTH = 220
const messages = defineMessages({
savedSkinsSection: {
id: 'app.skins.section.saved-skins',
defaultMessage: 'Saved skins',
},
addSkinButton: {
id: 'app.skins.add-button',
defaultMessage: 'Add skin',
},
dragAndDropSubtitle: {
id: 'app.skins.add-button.drag-and-drop',
defaultMessage: 'Drag and drop',
},
editSkinButton: {
id: 'app.skins.edit-button',
defaultMessage: 'Edit skin',
},
deleteSkinButton: {
id: 'app.skins.delete-button',
defaultMessage: 'Delete skin',
},
})
const props = defineProps<{
savedSkins: Skin[]
defaultSkinSections: DefaultSkinSection[]
getBakedSkinTextures: (skin: Skin) => RenderResult | undefined
isSkinSelected: (skin: Skin) => boolean
isSkinActive: (skin: Skin) => boolean
isAddSkinButtonDragActive: boolean
}>()
const emit = defineEmits<{
select: [skin: Skin]
edit: [skin: Skin, event: MouseEvent]
delete: [skin: Skin]
'add-skin': []
'add-skin-dragenter': [event: DragEvent]
'add-skin-dragover': [event: DragEvent]
'add-skin-dragleave': [event: DragEvent]
'add-skin-drop': [event: DragEvent]
}>()
const addSkinButton = useTemplateRef<AddSkinButtonRef>('addSkinButton')
const { formatMessage } = useVIntl()
const { listContainer, relativeScrollTop, scrollContainer, viewportHeight } = useScrollViewport()
const openSectionKeys = ref<Set<string>>(new Set())
const hasSettledInitialLayout = ref(false)
const knownSectionKeys = new Set<string>()
let enableLayoutTransitionsFrame: number | null = null
let isEnableLayoutTransitionsScheduled = false
let isUnmounted = false
const { width: listWidth } = useElementSize(listContainer)
const { width: windowWidth } = useWindowSize()
const columnCount = computed(() => {
if (windowWidth.value >= 2050) {
return 6
}
if (windowWidth.value >= 1750) {
return 5
}
if (windowWidth.value >= 1300) {
return 4
}
return 3
})
const cardWidth = computed(() => {
if (listWidth.value <= 0) {
return FALLBACK_CARD_WIDTH
}
const gapsWidth = (columnCount.value - 1) * SKIN_GRID_GAP
return Math.max(0, (listWidth.value - gapsWidth) / columnCount.value)
})
const cardHeight = computed(
() => (cardWidth.value * SKIN_CARD_ASPECT_HEIGHT) / SKIN_CARD_ASPECT_WIDTH,
)
const sections = computed<SkinSection[]>(() => [
{
key: 'saved-skins',
title: formatMessage(messages.savedSkinsSection),
kind: 'saved',
skins: props.savedSkins,
},
...props.defaultSkinSections.map((section) => ({
key: defaultSkinSectionKey(section.title),
title: section.title,
kind: 'default' as const,
skins: section.skins,
})),
])
const sectionLayouts = computed(() => {
const layouts: Array<{ section: SkinSection; top: number; height: number; index: number }> = []
let top = 0
sections.value.forEach((section, index) => {
const height = getSectionHeightEstimate(section, index)
layouts.push({ section, top, height, index })
top += height
})
return layouts
})
const totalHeight = computed(() => {
const lastSection = sectionLayouts.value[sectionLayouts.value.length - 1]
return lastSection ? lastSection.top + lastSection.height : 0
})
const visibleSections = computed<VirtualSkinSection[]>(() => {
if (!listContainer.value || !scrollContainer.value) {
return sectionLayouts.value.slice(0, 4)
}
const viewportStart = Math.max(0, relativeScrollTop.value - SKIN_SECTION_OVERSCAN)
const viewportEnd = relativeScrollTop.value + viewportHeight.value + SKIN_SECTION_OVERSCAN
return sectionLayouts.value
.filter((layout) => layout.top + layout.height >= viewportStart && layout.top <= viewportEnd)
.map(({ section, top, index }) => ({ section, top, index }))
})
watch(
sections,
(nextSections) => {
const sectionKeys = new Set(nextSections.map((section) => section.key))
const openKeys = new Set(openSectionKeys.value)
for (const section of nextSections) {
if (!knownSectionKeys.has(section.key)) {
knownSectionKeys.add(section.key)
openKeys.add(section.key)
}
}
for (const key of knownSectionKeys) {
if (!sectionKeys.has(key)) {
knownSectionKeys.delete(key)
openKeys.delete(key)
}
}
openSectionKeys.value = openKeys
},
{ immediate: true },
)
watch(
listWidth,
(width) => {
if (
typeof window === 'undefined' ||
width <= 0 ||
hasSettledInitialLayout.value ||
isEnableLayoutTransitionsScheduled
) {
return
}
isEnableLayoutTransitionsScheduled = true
void nextTick(() => {
if (isUnmounted) return
enableLayoutTransitionsFrame = window.requestAnimationFrame(() => {
if (isUnmounted) return
enableLayoutTransitionsFrame = window.requestAnimationFrame(() => {
if (isUnmounted) return
hasSettledInitialLayout.value = true
enableLayoutTransitionsFrame = null
isEnableLayoutTransitionsScheduled = false
})
})
})
},
{ immediate: true },
)
onUnmounted(() => {
isUnmounted = true
if (enableLayoutTransitionsFrame !== null) {
window.cancelAnimationFrame(enableLayoutTransitionsFrame)
}
})
function defaultSkinSectionKey(title: string) {
return `default-skins-${title}`
}
function skinKey(skin: Skin, prefix: string) {
return `${prefix}-${skin.source}-${skin.texture_key}-${skin.variant}-${skin.cape_id ?? 'no-cape'}`
}
function isSectionOpen(key: string) {
return openSectionKeys.value.has(key)
}
function setSectionOpen(key: string, open: boolean) {
const openKeys = new Set(openSectionKeys.value)
if (open) {
openKeys.add(key)
} else {
openKeys.delete(key)
}
openSectionKeys.value = openKeys
}
function getSectionHeightEstimate(section: SkinSection, index: number) {
const spacing = index === 0 ? SKIN_SECTION_FIRST_SPACING : SKIN_SECTION_SPACING
if (!isSectionOpen(section.key)) {
return spacing + SKIN_SECTION_HEADER_HEIGHT
}
const cardCount = section.kind === 'saved' ? section.skins.length + 1 : section.skins.length
const rowCount = Math.ceil(cardCount / columnCount.value)
const gridHeight = rowCount * cardHeight.value + Math.max(0, rowCount - 1) * SKIN_GRID_GAP
return spacing + SKIN_SECTION_HEADER_HEIGHT + SKIN_SECTION_CONTENT_SPACING + gridHeight
}
function getAddSkinButtonElement() {
const button = Array.isArray(addSkinButton.value)
? addSkinButton.value.find((candidate) => candidate.getRootElement())
: addSkinButton.value
return button?.getRootElement()
}
defineExpose({ getAddSkinButtonElement })
</script>
<template>
<div
ref="listContainer"
class="relative w-full"
:style="{ height: `${totalHeight}px`, overflowAnchor: 'none' }"
>
<div
v-for="{ section, top, index } in visibleSections"
:key="section.key"
class="absolute inset-x-0"
:class="[
index === 0 ? 'pt-1' : 'pt-6',
hasSettledInitialLayout
? 'transition-transform duration-300 ease-in-out will-change-transform motion-reduce:transition-none'
: '',
]"
:style="{ transform: `translateY(${top}px)` }"
>
<Accordion
button-class="group flex w-full items-center gap-[6px] bg-transparent m-0 p-0 border-none cursor-pointer text-left"
content-class="pt-2"
:open-by-default="isSectionOpen(section.key)"
@on-open="setSectionOpen(section.key, true)"
@on-close="setSectionOpen(section.key, false)"
>
<template #title>
{{ section.title }}
</template>
<template #button="{ open }">
<DropdownIcon
class="size-6 shrink-0 text-primary transition-transform duration-300"
:class="{ 'rotate-180': open }"
/>
<span class="min-w-0 text-xl font-semibold leading-7 text-primary">
{{ section.title }}
</span>
</template>
<div
v-if="section.kind === 'saved'"
class="grid w-full grid-cols-3 gap-3 min-[1300px]:grid-cols-4 min-[1750px]:grid-cols-5 min-[2050px]:grid-cols-6"
>
<SkinLikeTextButton
ref="addSkinButton"
class="aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
dropzone
:drag-active="isAddSkinButtonDragActive"
@click="emit('add-skin')"
@dragenter="emit('add-skin-dragenter', $event)"
@dragover="emit('add-skin-dragover', $event)"
@dragleave="emit('add-skin-dragleave', $event)"
@drop="emit('add-skin-drop', $event)"
>
<template #icon>
<PlusIcon class="size-8" />
</template>
{{ formatMessage(messages.addSkinButton) }}
<template #subtitle>{{ formatMessage(messages.dragAndDropSubtitle) }}</template>
</SkinLikeTextButton>
<SkinButton
v-for="skin in section.skins"
:key="skinKey(skin, 'saved-skin')"
class="aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
:backward-image-src="getBakedSkinTextures(skin)?.backwards"
:selected="isSkinSelected(skin)"
:active="isSkinActive(skin)"
@select="emit('select', skin)"
>
<template #overlay-buttons>
<ButtonStyled color="brand">
<button
:aria-label="formatMessage(messages.editSkinButton)"
class="pointer-events-auto"
@click.stop="(event: MouseEvent) => emit('edit', skin, event)"
>
<EditIcon /> {{ formatMessage(commonMessages.editButton) }}
</button>
</ButtonStyled>
<ButtonStyled v-show="!skin.is_equipped" circular color="red">
<button
v-tooltip="formatMessage(messages.deleteSkinButton)"
:aria-label="formatMessage(messages.deleteSkinButton)"
class="!rounded-[100%] pointer-events-auto"
@click.stop="emit('delete', skin)"
>
<TrashIcon />
</button>
</ButtonStyled>
</template>
</SkinButton>
</div>
<div
v-else
class="grid w-full grid-cols-3 gap-3 min-[1300px]:grid-cols-4 min-[1750px]:grid-cols-5 min-[2050px]:grid-cols-6"
>
<SkinButton
v-for="skin in section.skins"
:key="skinKey(skin, section.key)"
class="aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
:backward-image-src="getBakedSkinTextures(skin)?.backwards"
:selected="isSkinSelected(skin)"
:active="isSkinActive(skin)"
:tooltip="skin.name"
@select="emit('select', skin)"
/>
</div>
</Accordion>
</div>
</div>
</template>
@@ -244,7 +244,7 @@ const messages = defineMessages({
</TagItem>
<div
v-if="world.type === 'singleplayer'"
class="text-sm text-secondary flex items-center gap-1 font-semibold"
class="text-sm text-secondary flex items-center gap-1 font-semibold flex-nowrap whitespace-nowrap"
>
<UserIcon
aria-hidden="true"
@@ -8,7 +8,7 @@ interface LogEntry {
filename: string
name?: string
log_type: string
stdout?: string
output?: string | null
age?: number
live?: boolean
}
@@ -50,12 +50,12 @@ async function getHistoricalLogs(profilePathId: string, instancePath: string): P
const entry = getOrCreate(profilePathId)
if (entry.logList) return entry.logList
const logs: LogEntry[] = await get_logs(instancePath, false)
const logs: LogEntry[] = await get_logs(instancePath, true)
entry.logList = logs
for (const log of logs) {
if (log.stdout && log.stdout !== '') {
entry.historicalCache.set(log.filename, log.stdout)
if (log.output) {
entry.historicalCache.set(log.filename, log.output)
}
}
@@ -0,0 +1,52 @@
import { ref } from 'vue'
import { trackEvent } from '@/helpers/analytics'
import { test_jre } from '@/helpers/jre.js'
export default function useJavaTest() {
const testingJava = ref(false)
const javaTestResult = ref<boolean | null>(null)
let testDebounceTimer: ReturnType<typeof setTimeout> | null = null
async function runJavaTest(path: string, version: number, track = true) {
if (testDebounceTimer) {
clearTimeout(testDebounceTimer)
testDebounceTimer = null
}
if (!path) {
javaTestResult.value = null
return
}
testingJava.value = true
try {
javaTestResult.value = await test_jre(path, version)
} catch {
javaTestResult.value = false
}
testingJava.value = false
if (track) {
trackEvent('JavaTest', { path, success: javaTestResult.value })
}
}
function testJavaInstallationDebounced(path: string, version: number, delay = 600) {
if (testDebounceTimer) clearTimeout(testDebounceTimer)
if (!path) {
javaTestResult.value = null
return
}
testDebounceTimer = setTimeout(() => runJavaTest(path, version, false), delay)
}
async function testJavaInstallation(path: string, version: number, track = false) {
await runJavaTest(path, version, track)
}
return {
testingJava,
javaTestResult,
testJavaInstallationDebounced,
testJavaInstallation,
}
}
+2 -3
View File
@@ -6,12 +6,11 @@
import { invoke } from '@tauri-apps/api/core'
/*
A log is a struct containing the filename string, stdout, and stderr, as follows:
A log is a struct containing the filename string and optional output, as follows:
pub struct Logs {
pub filename: String,
pub stdout: String,
pub stderr: String,
pub output: Option<String>,
}
*/
+8 -1
View File
@@ -147,9 +147,16 @@ export async function get_mod_full_path(path: string, projectPath: string): Prom
return await invoke('plugin:profile|profile_get_mod_full_path', { path, projectPath })
}
export interface JavaVersion {
parsed_version: number
version: string
architecture: string
path: string
}
// Get optimal java version from profile
// Returns a java version
export async function get_optimal_jre_key(path: string): Promise<string | null> {
export async function get_optimal_jre_key(path: string): Promise<JavaVersion | null> {
return await invoke('plugin:profile|profile_get_optimal_jre_key', { path })
}
@@ -3,9 +3,8 @@ import {
applyCapeTexture,
createTransparentTexture,
disposeCaches,
loadTexture,
setupSkinModel,
} from '@modrinth/utils'
} from '@modrinth/ui'
import * as THREE from 'three'
import { reactive } from 'vue'
@@ -29,6 +28,7 @@ class BatchSkinRenderer {
private scene: THREE.Scene | null = null
private camera: THREE.PerspectiveCamera | null = null
private currentModel: THREE.Group | null = null
private transparentTexture: THREE.Texture | null = null
private readonly width: number
private readonly height: number
@@ -52,6 +52,7 @@ class BatchSkinRenderer {
})
this.renderer.outputColorSpace = THREE.SRGBColorSpace
this.renderer.shadowMap.enabled = false
this.renderer.toneMapping = THREE.NoToneMapping
this.renderer.toneMappingExposure = 10.0
this.renderer.setClearColor(0x000000, 0)
@@ -62,7 +63,7 @@ class BatchSkinRenderer {
const ambientLight = new THREE.AmbientLight(0xffffff, 2)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2)
directionalLight.castShadow = true
directionalLight.castShadow = false
directionalLight.position.set(2, 4, 3)
this.scene.add(ambientLight)
this.scene.add(directionalLight)
@@ -112,9 +113,19 @@ class BatchSkinRenderer {
this.renderer.render(this.scene, this.camera)
const dataUrl = this.renderer.domElement.toDataURL('image/webp', 0.9)
const response = await fetch(dataUrl)
return await response.blob()
return await new Promise<Blob>((resolve, reject) => {
this.renderer!.domElement.toBlob(
(blob) => {
if (blob) {
resolve(blob)
} else {
reject(new Error('Failed to create blob from rendered canvas'))
}
},
'image/webp',
0.9,
)
})
}
private async setupModel(modelUrl: string, textureUrl: string, capeUrl?: string): Promise<void> {
@@ -122,14 +133,10 @@ class BatchSkinRenderer {
throw new Error('Renderer not initialized')
}
const { model } = await setupSkinModel(modelUrl, textureUrl)
const { model } = await setupSkinModel(modelUrl, textureUrl, capeUrl)
if (capeUrl) {
const capeTexture = await loadTexture(capeUrl)
applyCapeTexture(model, capeTexture)
} else {
const transparentTexture = createTransparentTexture()
applyCapeTexture(model, null, transparentTexture)
if (!capeUrl) {
applyCapeTexture(model, null, this.getTransparentTexture())
}
const group = new THREE.Group()
@@ -141,39 +148,38 @@ class BatchSkinRenderer {
this.currentModel = group
}
private clearScene(): void {
if (!this.scene) return
while (this.scene.children.length > 0) {
const child = this.scene.children[0]
this.scene.remove(child)
if (child instanceof THREE.Mesh) {
if (child.geometry) child.geometry.dispose()
if (child.material) {
if (Array.isArray(child.material)) {
child.material.forEach((material) => material.dispose())
} else {
child.material.dispose()
}
}
}
private getTransparentTexture(): THREE.Texture {
if (!this.transparentTexture) {
this.transparentTexture = createTransparentTexture()
}
const ambientLight = new THREE.AmbientLight(0xffffff, 2)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2)
directionalLight.castShadow = true
directionalLight.position.set(2, 4, 3)
this.scene.add(ambientLight)
this.scene.add(directionalLight)
return this.transparentTexture
}
private clearScene(): void {
if (!this.scene || !this.currentModel) return
this.scene.remove(this.currentModel)
this.currentModel.clear()
this.currentModel = null
}
public dispose(): void {
this.clearScene()
if (this.transparentTexture) {
this.transparentTexture.dispose()
this.transparentTexture = null
}
if (this.renderer) {
this.renderer.dispose()
}
this.renderer = null
this.scene = null
this.camera = null
disposeCaches()
}
}
@@ -194,6 +200,9 @@ export const headBlobUrlMap = reactive(new Map<string, string>())
const DEBUG_MODE = false
let sharedRenderer: BatchSkinRenderer | null = null
let latestPreviewGeneration = 0
let previewGenerationQueue: Promise<void> = Promise.resolve()
function getSharedRenderer(): BatchSkinRenderer {
if (!sharedRenderer) {
sharedRenderer = new BatchSkinRenderer()
@@ -356,7 +365,27 @@ export async function getPlayerHeadUrl(skin: Skin): Promise<string> {
return await generateHeadRender(skin)
}
export async function generateSkinPreviews(skins: Skin[], capes: Cape[]): Promise<void> {
export function generateSkinPreviews(skins: Skin[], capes: Cape[]): Promise<void> {
const generation = ++latestPreviewGeneration
const skinsSnapshot = [...skins]
const capesSnapshot = [...capes]
const generationPromise = previewGenerationQueue.then(() =>
generateSkinPreviewsForGeneration(skinsSnapshot, capesSnapshot, generation),
)
previewGenerationQueue = generationPromise.catch(() => {})
return generationPromise
}
async function generateSkinPreviewsForGeneration(
skins: Skin[],
capes: Cape[],
generation: number,
): Promise<void> {
const isCurrentGeneration = () => generation === latestPreviewGeneration
try {
const skinKeys = skins.map(
(skin) => `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`,
@@ -368,6 +397,8 @@ export async function generateSkinPreviews(skins: Skin[], capes: Cape[]): Promis
headStorage.batchRetrieve(headKeys),
])
if (!isCurrentGeneration()) return
for (let i = 0; i < skins.length; i++) {
const skinKey = skinKeys[i]
const headKey = headKeys[i]
@@ -388,6 +419,8 @@ export async function generateSkinPreviews(skins: Skin[], capes: Cape[]): Promis
}
for (const skin of skins) {
if (!isCurrentGeneration()) return
const key = `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`
if (skinBlobUrlMap.has(key)) {
@@ -419,6 +452,8 @@ export async function generateSkinPreviews(skins: Skin[], capes: Cape[]): Promis
cape?.texture,
)
if (!isCurrentGeneration()) return
const renderResult: RenderResult = {
forwards: URL.createObjectURL(rawRenderResult.forwards),
backwards: URL.createObjectURL(rawRenderResult.backwards),
@@ -439,9 +474,12 @@ export async function generateSkinPreviews(skins: Skin[], capes: Cape[]): Promis
}
} finally {
disposeSharedRenderer()
await cleanupUnusedPreviews(skins)
await skinPreviewStorage.debugCalculateStorage()
await headStorage.debugCalculateStorage()
if (isCurrentGeneration()) {
await cleanupUnusedPreviews(skins)
await skinPreviewStorage.debugCalculateStorage()
await headStorage.debugCalculateStorage()
}
}
}
+30 -10
View File
@@ -5,7 +5,6 @@ export interface Cape {
id: string
name: string
texture: string
is_default: boolean
is_equipped: boolean
}
@@ -15,6 +14,7 @@ export type SkinSource = 'default' | 'custom_external' | 'custom'
export interface Skin {
texture_key: string
name?: string
section?: string
variant: SkinModel
cape_id?: string
texture: string
@@ -121,17 +121,11 @@ export async function get_available_skins(): Promise<Skin[]> {
export async function add_and_equip_custom_skin(
textureBlob: Uint8Array,
variant: SkinModel,
capeOverride?: Cape,
): Promise<void> {
await invoke('plugin:minecraft-skins|add_and_equip_custom_skin', {
cape?: Cape,
): Promise<Skin> {
return await invoke('plugin:minecraft-skins|add_and_equip_custom_skin', {
textureBlob,
variant,
capeOverride,
})
}
export async function set_default_cape(cape?: Cape): Promise<void> {
await invoke('plugin:minecraft-skins|set_default_cape', {
cape,
})
}
@@ -148,6 +142,22 @@ export async function remove_custom_skin(skin: Skin): Promise<void> {
})
}
export async function save_custom_skin(
skin: Skin,
textureBlob: Uint8Array,
variant: SkinModel,
cape: Cape | undefined,
replaceTexture: boolean,
): Promise<Skin> {
return await invoke('plugin:minecraft-skins|save_custom_skin', {
skin,
textureBlob,
variant,
cape,
replaceTexture,
})
}
export async function get_normalized_skin_texture(skin: Skin): Promise<string> {
const data = await normalize_skin_texture(skin.texture)
const base64 = arrayBufferToBase64(data)
@@ -162,6 +172,16 @@ export async function unequip_skin(): Promise<void> {
await invoke('plugin:minecraft-skins|unequip_skin')
}
export async function flush_pending_skin_change(): Promise<void> {
await invoke('plugin:minecraft-skins|flush_pending_skin_change')
}
export async function flush_pending_skin_change_for_profile(profileId: string): Promise<void> {
await invoke('plugin:minecraft-skins|flush_pending_skin_change_for_profile', {
profileId,
})
}
export async function get_dragged_skin_data(path: string): Promise<Uint8Array> {
const data = await invoke('plugin:minecraft-skins|get_dragged_skin_data', { path })
return new Uint8Array(data)
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "Procházet servery"
},
"app.instance.worlds.delete-world-description": {
"message": "\"{name}\" bude **navždy smazáno** a nebude způsob, jak to obnovit."
},
"app.instance.worlds.delete-world-title": {
"message": "Opravdu si jsi jistý, že chceš navždy smazat tenhle svět?"
},
@@ -248,9 +245,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "Žádné servery nebo světy nebyly přidány"
},
"app.instance.worlds.remove-server-description": {
"message": "„{name}“ bude odstraněn z tvého seznamu, včetně hry, a nebude žádný způsob, jak ho obnovit."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "'{name}' ({address}) bude odstraněn z vašeho seznamu, a to i ve hře, a nebude možné jej obnovit."
},
@@ -302,6 +296,9 @@
"app.project.install-button.already-installed": {
"message": "Tento projekt je již nainstalován"
},
"app.project.install-context.back-to-browse": {
"message": "Zpět na Prozkoumat"
},
"app.project.install-context.install-content-to-instance": {
"message": "Nainstalovat obsah do instnce"
},
@@ -440,9 +437,6 @@
"friends.heading.pending": {
"message": "Čeká na vyřízení"
},
"friends.no-friends-match": {
"message": "Žádní přátelé neodpovídají '{query}''"
},
"friends.search-friends-placeholder": {
"message": "Hledat přátele..."
},
@@ -104,6 +104,12 @@
"app.browse.discover-servers": {
"message": "Opdag servere"
},
"app.browse.project-type.modpacks": {
"message": "Modpacks"
},
"app.creation-modal.installing-modpack.description": {
"message": "{fileName}"
},
"app.export-modal.description-placeholder": {
"message": "Indtast modpack beskrivelse..."
},
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "Server durchsuchen"
},
"app.instance.worlds.delete-world-description": {
"message": "„{name}“ wird **endgültig gelöscht**, und es gibt keine Möglichkeit, sie wiederherzustellen."
},
"app.instance.worlds.delete-world-title": {
"message": "Möchtest du diese Welt wirklich endgültig löschen?"
},
@@ -248,12 +245,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "Keine Server oder Welten hinzugefügt"
},
"app.instance.worlds.remove-server-description": {
"message": "„{name}“ wird aus deiner Liste entfernt, auch im Spiel, und es gibt keine Möglichkeit, ihn wiederherzustellen."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "„{name}“ ({address}) wird aus deiner Liste entfernt, inklusive im Spiel, und es gibt keine Möglichkeit, ihn wiederherzustellen."
},
"app.instance.worlds.remove-server-title": {
"message": "Möchtest du {name} wirklich entfernen?"
},
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "Server durchsuchen"
},
"app.instance.worlds.delete-world-description": {
"message": "„{name}“ wird **endgültig gelöscht**, und es gibt keine Möglichkeit, sie wiederherzustellen."
},
"app.instance.worlds.delete-world-title": {
"message": "Möchtest du diese Welt wirklich endgültig löschen?"
},
@@ -248,12 +245,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "Keine Server oder Welten hinzugefügt"
},
"app.instance.worlds.remove-server-description": {
"message": "„{name}“ wird aus deiner Liste entfernt, auch im Spiel, und es gibt keine Möglichkeit, ihn wiederherzustellen."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "„{name}“ ({address}) wird aus deiner Liste entfernt, inklusive im Spiel, und es gibt keine Möglichkeit, ihn wiederherzustellen."
},
"app.instance.worlds.remove-server-title": {
"message": "Möchtest du {name} wirklich entfernen?"
},
@@ -332,6 +332,138 @@
"app.settings.tabs.resource-management": {
"message": "Resource management"
},
"app.skins.add-button": {
"message": "Add skin"
},
"app.skins.add-button.drag-and-drop": {
"message": "Drag and drop"
},
"app.skins.apply-button": {
"message": "Apply"
},
"app.skins.delete-button": {
"message": "Delete skin"
},
"app.skins.delete-modal.description": {
"message": "This will permanently delete the selected skin. This action cannot be undone."
},
"app.skins.delete-modal.title": {
"message": "Are you sure you want to delete this skin?"
},
"app.skins.dropped-file-error.text": {
"message": "Failed to read the dropped file."
},
"app.skins.dropped-file-error.title": {
"message": "Error processing file"
},
"app.skins.edit-button": {
"message": "Edit skin"
},
"app.skins.modal.add-skin-button": {
"message": "Add skin"
},
"app.skins.modal.add-title": {
"message": "Adding a skin"
},
"app.skins.modal.arm-style-section": {
"message": "Arm style"
},
"app.skins.modal.arm-style-slim": {
"message": "Slim"
},
"app.skins.modal.arm-style-wide": {
"message": "Wide"
},
"app.skins.modal.cape-fallback-name": {
"message": "Cape"
},
"app.skins.modal.cape-section": {
"message": "Cape"
},
"app.skins.modal.edit-title": {
"message": "Editing skin"
},
"app.skins.modal.make-edit-first-tooltip": {
"message": "Make an edit to the skin first!"
},
"app.skins.modal.no-cape-tooltip": {
"message": "No cape"
},
"app.skins.modal.none-cape-option": {
"message": "None"
},
"app.skins.modal.replace-texture-button": {
"message": "Replace texture"
},
"app.skins.modal.save-skin-button": {
"message": "Save skin"
},
"app.skins.modal.saving-tooltip": {
"message": "Saving..."
},
"app.skins.modal.texture-section": {
"message": "Texture"
},
"app.skins.modal.upload-skin-first-tooltip": {
"message": "Upload a skin first!"
},
"app.skins.preview.edit-button": {
"message": "Edit skin"
},
"app.skins.previewing-badge": {
"message": "Previewing"
},
"app.skins.rate-limit.text": {
"message": "You're changing your skin too frequently. Mojang's servers have temporarily blocked further requests. Please wait a moment before trying again."
},
"app.skins.rate-limit.title": {
"message": "Slow down!"
},
"app.skins.section.builders-and-biomes": {
"message": "Builders & Biomes"
},
"app.skins.section.chase-the-skies": {
"message": "Chase the Skies"
},
"app.skins.section.default-skins": {
"message": "Default skins"
},
"app.skins.section.minecon-earth-2017": {
"message": "MINECON Earth 2017"
},
"app.skins.section.mounts-of-mayhem": {
"message": "Mounts of Mayhem"
},
"app.skins.section.saved-skins": {
"message": "Saved skins"
},
"app.skins.section.striding-hero": {
"message": "Striding Hero"
},
"app.skins.section.the-copper-age": {
"message": "The Copper Age"
},
"app.skins.section.the-garden-awakens": {
"message": "The Garden Awakens"
},
"app.skins.section.tiny-takeover": {
"message": "Tiny Takeover"
},
"app.skins.sign-in.button": {
"message": "Sign In"
},
"app.skins.sign-in.description": {
"message": "Please sign into your Minecraft account to use the skin management features of the Modrinth app."
},
"app.skins.sign-in.rinthbot-alt": {
"message": "Excited Modrinth Bot"
},
"app.skins.sign-in.title": {
"message": "Please sign in"
},
"app.skins.title": {
"message": "Skin selector"
},
"app.update-popup.body": {
"message": "Modrinth App v{version} is ready to install! Reload to update now, or automatically when you close Modrinth App."
},
@@ -611,6 +743,24 @@
"instance.settings.tabs.java": {
"message": "Java and memory"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Custom environment variables"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Custom Java arguments"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Custom Java installation"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Custom memory allocation"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Enter environmental variables..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Enter Java arguments..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Environment variables"
},
@@ -626,6 +776,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Memory allocated"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/path/to/java"
},
"instance.settings.tabs.window": {
"message": "Window"
},
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "Explorar servidores"
},
"app.instance.worlds.delete-world-description": {
"message": "\"{name}\" se **eliminará permanentemente** y no habrá forma de recuperarlo."
},
"app.instance.worlds.delete-world-title": {
"message": "¿Estás seguro de que quieres eliminar este mundo de forma permanente?"
},
@@ -248,12 +245,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "No hay servidores ni mundos añadidos"
},
"app.instance.worlds.remove-server-description": {
"message": "\"{name}\" se eliminará de tu lista, también dentro del juego, y no podrás recuperarlo."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "\"{name}\" ({address}) se eliminará de tu lista, también dentro del juego, y no podrás recuperarlo."
},
"app.instance.worlds.remove-server-title": {
"message": "¿Estás seguro de que quieres eliminar {name}?"
},
@@ -611,6 +602,24 @@
"instance.settings.tabs.java": {
"message": "Java y memoria"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Variables de entorno personalizadas"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Argumentos personalizados de Java"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Instalación personalizada de Java"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Asignación de memoria personalizada"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Introduce las variables de entorno..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Introduce los argumentos de Java..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Variables de entorno"
},
@@ -626,6 +635,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Memoria asignada"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/ruta/a/java"
},
"instance.settings.tabs.window": {
"message": "Ventana"
},
+74 -8
View File
@@ -21,7 +21,7 @@
"message": "Instancia principal"
},
"app.action-bar.show-more-running-instances": {
"message": "Mostrar mas instancias en ejecución"
"message": "Mostrar más instancias en ejecución"
},
"app.action-bar.stop-instance": {
"message": "Finalizar instancia"
@@ -48,7 +48,7 @@
"message": "Tema de color"
},
"app.appearance-settings.default-landing-page.description": {
"message": "Cambia la página en la que el launcher se abre en."
"message": "Cambia la página en la que el lanzador inicia."
},
"app.appearance-settings.default-landing-page.home": {
"message": "Inicio"
@@ -72,13 +72,13 @@
"message": "Vuelve a jugar tus mundos"
},
"app.appearance-settings.minimize-launcher.description": {
"message": "Minimiza el launcher cuando un proceso de Minecraft empieza."
"message": "Minimiza el lanzador cuando un proceso de Minecraft empieza."
},
"app.appearance-settings.minimize-launcher.title": {
"message": "Minimiza el launcher"
"message": "Minimiza el lanzador"
},
"app.appearance-settings.native-decorations.description": {
"message": "Usa los sistemas de frame de Windows (se requiere resetear la aplicación)."
"message": "Usa los sistemas de marco de Windows (se requiere resetear la aplicación)."
},
"app.appearance-settings.native-decorations.title": {
"message": "Decoraciones nativas"
@@ -93,10 +93,10 @@
"message": "Alternar barra lateral"
},
"app.appearance-settings.unknown-pack-warning.description": {
"message": "Si intentas instalar un archivo de paquete de Modrinth (.mrpack) que no esté alojado en Modrinth, te advertiremos de los riesgos antes de instalarlo."
"message": "Si intentas instalar un archivo de paquete de Modrinth (.mrpack) que no esté alojado en Modrinth, debes comprender los riesgos que esto conlleva antes de instalarlo."
},
"app.appearance-settings.unknown-pack-warning.title": {
"message": "Adviérteme antes de instalarme modpacks desconocidos"
"message": "Advertir antes de instalarme paquetes de mods desconocidos"
},
"app.auth-servers.unreachable.body": {
"message": "Los servidores de autenticación de Minecraft pueden no estar funcionando en este momento. Verifica tu conexión a internet e inténtalo de nuevo más tarde."
@@ -104,6 +104,12 @@
"app.auth-servers.unreachable.header": {
"message": "No se puede conectar con los servidores de autenticación"
},
"app.browse.add-servers-to-instance": {
"message": "Añadir servidor a instancia"
},
"app.browse.add-to-an-instance": {
"message": "Añadir a una instancia"
},
"app.browse.add-to-instance": {
"message": "Añadir a la instancia"
},
@@ -116,6 +122,9 @@
"app.browse.already-added": {
"message": "Ya está añadido"
},
"app.browse.back-to-instance": {
"message": "Volver a la instancia"
},
"app.browse.discover-content": {
"message": "Descubrir contenido"
},
@@ -126,7 +135,10 @@
"message": "Ocultar servidores ya añadidos"
},
"app.browse.project-type.modpacks": {
"message": "Modpacks"
"message": "Paquetes de Mods"
},
"app.browse.server-instance-content-warning": {
"message": "Añadir contenido puede comprometer la compatibilidad a la hora de unirse a un servidor. Cualquier contenido añadido se perderá cuando actualices la instancia del servidor."
},
"app.browse.server.installing": {
"message": "Instalando"
@@ -146,12 +158,18 @@
"app.export-modal.header": {
"message": "Exportar modpack"
},
"app.export-modal.include-file-accessibility-label": {
"message": "¿Incluir \"{file}\"?"
},
"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": "Configura que archivos se incluirán en esta instancia"
},
"app.export-modal.version-number-label": {
"message": "Número de versión"
},
@@ -281,6 +299,15 @@
"app.modal.update-to-play.update-required-description": {
"message": "Una actualización es requerida para jugar {name}. Por favor actualízala a la versión más reciente para ejecutar el juego."
},
"app.project.install-button.already-installed": {
"message": "El proyecto ya está instalado"
},
"app.project.install-context.back-to-browse": {
"message": "Volver a descubrir"
},
"app.project.install-context.install-content-to-instance": {
"message": "Instalar contenido"
},
"app.settings.developer-mode-enabled": {
"message": "Modo desarrollador activado."
},
@@ -584,6 +611,24 @@
"instance.settings.tabs.java": {
"message": "Java y memoria"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Variables de entorno personalizadas"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Argumentos personalizados de Java"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Instalación personalizada de Java"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Asignación de memoria personalizada"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Introduce las variables de entorno..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Introduce los argumentos de Java..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Variables de entorno"
},
@@ -599,6 +644,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Memoria asignada"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/ruta/a/java"
},
"instance.settings.tabs.window": {
"message": "Ventana"
},
@@ -671,6 +719,24 @@
"instance.worlds.world_in_use": {
"message": "El mundo está en uso"
},
"minecraft-account.add-account": {
"message": "Añadir cuenta"
},
"minecraft-account.label": {
"message": "Cuenta de Minecraft"
},
"minecraft-account.not-signed-in": {
"message": "Registrarse"
},
"minecraft-account.remove-account": {
"message": "Eliminar cuenta"
},
"minecraft-account.select-account": {
"message": "Seleccionar cuenta"
},
"minecraft-account.sign-in": {
"message": "Registrarse en Minecraft"
},
"search.filter.locked.instance": {
"message": "Proporcionado por la instancia"
},
@@ -1,10 +1,115 @@
{
"app.action-bar.downloading-java": {
"message": "Ladataan Java-versiota {version}"
},
"app.action-bar.downloads": {
"message": "Lataukset"
},
"app.action-bar.hide-more-running-instances": {
"message": "Piilota enemmän käynnissä olevia instansseja"
},
"app.action-bar.make-primary-instance": {
"message": "Aseta ensisijaiseksi instanssiksi"
},
"app.action-bar.no-instances-running": {
"message": "Ei instansseja käynnissä"
},
"app.action-bar.offline": {
"message": "Offline-tilassa"
},
"app.action-bar.primary-instance": {
"message": "Ensisijainen instanssi"
},
"app.action-bar.show-more-running-instances": {
"message": "Näytä enemmän käynnissä olevia instansseja"
},
"app.action-bar.stop-instance": {
"message": "Pysäytä instanssi"
},
"app.action-bar.view-active-downloads": {
"message": "Näytä aktiiviset lataukset"
},
"app.action-bar.view-instance": {
"message": "Katso intanssia"
},
"app.action-bar.view-logs": {
"message": "Katso lokeja"
},
"app.appearance-settings.advanced-rendering.description": {
"message": "Mahdollistaa edistyneen renderöinnin, kuten sumennus efektit, jotka voivat aiheuttaa suorituskykyongelmia ilman laitteistokiihdytettyä renderöintiä."
},
"app.appearance-settings.advanced-rendering.title": {
"message": "Edistynyt renderointi"
},
"app.appearance-settings.color-theme.description": {
"message": "Valitse haluamasi väriteema Modrinth Appille."
},
"app.appearance-settings.color-theme.title": {
"message": "Väriteema"
},
"app.appearance-settings.default-landing-page.description": {
"message": "Muuta sivua mille laukaisin avautuu."
},
"app.appearance-settings.default-landing-page.home": {
"message": "Koti"
},
"app.appearance-settings.default-landing-page.library": {
"message": "Kirjasto"
},
"app.appearance-settings.default-landing-page.title": {
"message": "Oletus laskeutumissivu"
},
"app.appearance-settings.hide-nametag.description": {
"message": "Kytkee pois päältä nimikyltin pelaajasi päällä skinit sivulla."
},
"app.appearance-settings.hide-nametag.title": {
"message": "Piilota nimikyltti"
},
"app.appearance-settings.jump-back-into-worlds.description": {
"message": "Sisällyttää viimeaikaiset maailmat \"Hyppää takaisin sisään\" osiossa Koti sivulla."
},
"app.appearance-settings.jump-back-into-worlds.title": {
"message": "Hyppää takaisin sisään maailmoihin"
},
"app.appearance-settings.minimize-launcher.description": {
"message": "Pienennä laukaisin kun Minecraft prosessi käynnistyy."
},
"app.appearance-settings.minimize-launcher.title": {
"message": "Piilota käynnistysohjelma"
},
"app.appearance-settings.native-decorations.description": {
"message": "Käytä järjestelmän ikkuna kehystä (Vaatii sovelluksen uudelleen käynnistämisen)."
},
"app.appearance-settings.native-decorations.title": {
"message": "Natiivit koristukset"
},
"app.appearance-settings.select-option": {
"message": "Valitse vaihtoehto"
},
"app.appearance-settings.toggle-sidebar.description": {
"message": "Laittaa päälle mahdollisuuden kytkeä sivupalkkia."
},
"app.appearance-settings.toggle-sidebar.title": {
"message": "Kytke sivupalkki"
},
"app.appearance-settings.unknown-pack-warning.description": {
"message": "Jos yrität asentaa Modrinth-pakettitiedoston (.mrpack), jota ei ole isännöity Modrinthissä, varmistamme, että ymmärrät riskit ennen asennusta."
},
"app.appearance-settings.unknown-pack-warning.title": {
"message": "Varoita minua ennen tuntemattomien modipakettien asentamista"
},
"app.auth-servers.unreachable.body": {
"message": "Minecraftin todennuspalvelimet eivät ehkä ole tällä hetkellä tavoitettavissa. Tarkista internetyhteytesi ja yritä myöhemmin uudelleen."
},
"app.auth-servers.unreachable.header": {
"message": "Todennuspalvelimiin ei saada yhteyttä"
},
"app.browse.add-servers-to-instance": {
"message": "Lisää palvelin instanssiin"
},
"app.browse.add-to-an-instance": {
"message": "Lisää instanssiin"
},
"app.browse.add-to-instance": {
"message": "Lisää instanssiin"
},
@@ -17,12 +122,33 @@
"app.browse.already-added": {
"message": "On jo asennettu"
},
"app.browse.back-to-instance": {
"message": "Takaisin instanssiin"
},
"app.browse.discover-content": {
"message": "Löydä sisältöä"
},
"app.browse.discover-servers": {
"message": "Löydä palvelimia"
},
"app.browse.hide-added-servers": {
"message": "Piilota lisätyt palvelimet"
},
"app.browse.project-type.modpacks": {
"message": "Modipaketit"
},
"app.browse.server-instance-content-warning": {
"message": "Sisällön lisääminen voi rikkoa yhteensopivuuden palvelimelle liittyessä. Kaikki lisätty sisältö katoaa myös kun päivität palvelin instanssin sisällön."
},
"app.browse.server.installing": {
"message": "Asennetaan"
},
"app.creation-modal.installing-modpack.description": {
"message": "{fileName}"
},
"app.creation-modal.installing-modpack.title": {
"message": "Asennetaan modipakettia..."
},
"app.export-modal.description-placeholder": {
"message": "Lisää modipaketin kuvaus..."
},
@@ -32,12 +158,18 @@
"app.export-modal.header": {
"message": "Vie modipaketti"
},
"app.export-modal.include-file-accessibility-label": {
"message": "Sisällytä \"{file}\"?"
},
"app.export-modal.modpack-name-label": {
"message": "Modipaketin nimi"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Modipaketin nimi"
},
"app.export-modal.select-files-label": {
"message": "Muuta mitkä tiedostot sisältyvät tähän vientiin"
},
"app.export-modal.version-number-label": {
"message": "Versio numero"
},
@@ -80,6 +212,9 @@
"app.instance.mods.share-text": {
"message": "Tsekkaa projektit joita käytän minun modipaketissani!"
},
"app.instance.mods.share-title": {
"message": "Jaetaan modipaketti sisältöä"
},
"app.instance.mods.successfully-uploaded": {
"message": "Onnistuneesti ladattu"
},
@@ -164,6 +299,15 @@
"app.modal.update-to-play.update-required-description": {
"message": "Pävitys vaaditaan pelataksesi {name}. Päivitä viimeisimpään versioon pelataksesi."
},
"app.project.install-button.already-installed": {
"message": "Tämä projekti on jo asennettu"
},
"app.project.install-context.back-to-browse": {
"message": "Takaisin sisällön löytöön"
},
"app.project.install-context.install-content-to-instance": {
"message": "Asenna sisältöä instanssiin"
},
"app.settings.developer-mode-enabled": {
"message": "Kehittäjätila käytössä."
},
@@ -467,6 +611,24 @@
"instance.settings.tabs.java": {
"message": "Java ja muisti"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Mukautetut ympäristö muuttujat"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Mukautetut Java argumentit"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Mukautettu Java asennus"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Mukautettu muistin allokointi"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Syötä ympäristö muuttujat..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Syötä Java argumentit..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Ympäristö muuttujat"
},
@@ -482,6 +644,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Muisti allokoitu"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/javaan/johtava/polku/"
},
"instance.settings.tabs.window": {
"message": "Ikkuna"
},
@@ -554,6 +719,24 @@
"instance.worlds.world_in_use": {
"message": "Maailma on käytössä"
},
"minecraft-account.add-account": {
"message": "Lisää tili"
},
"minecraft-account.label": {
"message": "Minecraft tili"
},
"minecraft-account.not-signed-in": {
"message": "Ei kirjautuneena sisään"
},
"minecraft-account.remove-account": {
"message": "Poista tili"
},
"minecraft-account.select-account": {
"message": "Valitse tili"
},
"minecraft-account.sign-in": {
"message": "Kirjaudu sisään Minecraftiin"
},
"search.filter.locked.instance": {
"message": "Annettu instanssin toimesta"
},
@@ -577,5 +760,26 @@
},
"search.filter.locked.server-loader.title": {
"message": "Modialusta on palvelimen tarjoama"
},
"unknown-pack-warning-modal.body": {
"message": "Tiedosto tarkistetaan vain jos se on ladattu Modrinthiin, riippumatta tiedoston muodosta (mukaanlukien .mrpack)."
},
"unknown-pack-warning-modal.dont-show-again": {
"message": "Älä näytä tätä varoitusta uudestaan"
},
"unknown-pack-warning-modal.header": {
"message": "Vahvista asennus"
},
"unknown-pack-warning-modal.install-anyway": {
"message": "Asenna jokatapauksessa"
},
"unknown-pack-warning-modal.malware-statement": {
"message": "Haittaohjelmia levitetään usein modipaketti tiedostojen kautta jakamalla niitä alustoilla kuten Discordissa."
},
"unknown-pack-warning-modal.warning.body": {
"message": "Emme löytäneet tätä tiedostoa Modrinthista. Suosittelemme vahvasti että asennat tiedostoja vain lähteistä joihin luotat."
},
"unknown-pack-warning-modal.warning.title": {
"message": "Tuntematon tiedosto varoitus"
}
}
@@ -729,7 +729,7 @@
"message": "Kumpirmahin ang installation"
},
"unknown-pack-warning-modal.install-anyway": {
"message": "I-install parin"
"message": "I-install pa rin"
},
"unknown-pack-warning-modal.malware-statement": {
"message": "Ang malware ay madalas naidadala sa mga modpack files sa pamamagitan ng pag-bigay ng mga ito sa mga platforms kagaya ng Discord."
+18 -12
View File
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "Parcourir des serveurs"
},
"app.instance.worlds.delete-world-description": {
"message": "« {name} » sera supprimé **pour toujours**, et il sera impossible de le récupérer."
},
"app.instance.worlds.delete-world-title": {
"message": "Êtes-vous sûr·e de vouloir supprimer ce monde pour toujours ?"
},
@@ -248,12 +245,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "Aucun serveur ou monde ajoutés"
},
"app.instance.worlds.remove-server-description": {
"message": "« {name} » sera retiré de votre liste, y compris en jeu, et il sera impossible de le récupérer."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "« {name} » ({address}) sera retiré de votre liste, y compris en jeu, et il sera impossible de le récupérer."
},
"app.instance.worlds.remove-server-title": {
"message": "Êtes-vous sûr·e de vouloir retirer {name} ?"
},
@@ -389,9 +380,6 @@
"app.world.world-item.offline": {
"message": "Hors ligne"
},
"app.world.world-item.players-online": {
"message": "{count, plural, =0 {Personne en ligne} one {# est en ligne} other {# sont en ligne}}"
},
"friends.action.add-friend": {
"message": "Ajouter un ami"
},
@@ -611,6 +599,24 @@
"instance.settings.tabs.java": {
"message": "Java et mémoire"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Variables d'environnement personnalisé"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Arguments Java personnalisée"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Installation Java personnalisée"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Allocation de mémoire personnalisée"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Entrer une variable d'environnement..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Entrer un argument Java..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Variables d'environnement"
},
@@ -254,9 +254,6 @@
"friends.action.add-friend": {
"message": "הוספת חבר"
},
"friends.action.view-friend-requests": {
"message": "{count, plural, one {בקשת חברות אחת} other {# בקשות חברות}}"
},
"friends.add-friend.submit": {
"message": "שליחת בקשת חברות"
},
@@ -272,9 +272,6 @@
"app.modal.install-to-play.install-button": {
"message": "Telepítés"
},
"app.modal.install-to-play.mod-count": {
"message": "{count} mod"
},
"app.modal.install-to-play.required-modpack": {
"message": "Szükséges modcsomag"
},
@@ -395,9 +392,6 @@
"friends.action.add-friend": {
"message": "Barát hozzáadása"
},
"friends.action.view-friend-requests": {
"message": "{count} barát {count, plural, other {kérelem}}"
},
"friends.add-friend.submit": {
"message": "Barátkérelem elküldése"
},
+36 -6
View File
@@ -71,6 +71,9 @@
"app.appearance-settings.select-option": {
"message": "Pilih opsi"
},
"app.appearance-settings.unknown-pack-warning.title": {
"message": "Peringatkan saya sebelum memasang paket mod tidak dikenal"
},
"app.auth-servers.unreachable.body": {
"message": "Server autentikasi Minecraft mungkin sedang tidak tersedia saat ini. Periksa koneksi internet Anda dan coba lagi nanti."
},
@@ -242,9 +245,6 @@
"app.modal.install-to-play.install-button": {
"message": "Pasang"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, other {# mod}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Paket mod yang diperlukan"
},
@@ -269,6 +269,9 @@
"app.modal.update-to-play.update-required-description": {
"message": "{name} perlu diperbarui sebelum dimainkan. Mohon perbarui ke versi terkini untuk meluncurkan permainan."
},
"app.project.install-context.install-content-to-instance": {
"message": "Pasang konten ke instans"
},
"app.settings.developer-mode-enabled": {
"message": "Mode pengembang dihidupkan."
},
@@ -356,9 +359,6 @@
"friends.action.add-friend": {
"message": "Tambah teman"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural, other {permintaan}} teman"
},
"friends.add-friend.submit": {
"message": "Kirim permintaan teman"
},
@@ -659,6 +659,21 @@
"instance.worlds.world_in_use": {
"message": "Dunia sedang dimainkan"
},
"minecraft-account.add-account": {
"message": "Tambah akun"
},
"minecraft-account.label": {
"message": "Akun Minecraft"
},
"minecraft-account.not-signed-in": {
"message": "Tidak masuk"
},
"minecraft-account.remove-account": {
"message": "Hapus akun"
},
"minecraft-account.select-account": {
"message": "Pilih akun"
},
"search.filter.locked.instance": {
"message": "Disediakan oleh instans"
},
@@ -682,5 +697,20 @@
},
"search.filter.locked.server-loader.title": {
"message": "Pemuat disediakan oleh server"
},
"unknown-pack-warning-modal.dont-show-again": {
"message": "Jangan tampilkan peringatan ini lagi"
},
"unknown-pack-warning-modal.header": {
"message": "Konfirmasi pemasangan"
},
"unknown-pack-warning-modal.install-anyway": {
"message": "Tetap pasang"
},
"unknown-pack-warning-modal.warning.body": {
"message": "Kami tidak dapat menemukan berkas ini di Modrinth. Kami sangat menyarankan Anda untuk hanya memasang berkas dari sumber-sumber terpercaya."
},
"unknown-pack-warning-modal.warning.title": {
"message": "Peringatan berkas tidak dikenal"
}
}
+22 -13
View File
@@ -84,7 +84,7 @@
"message": "Decorazioni native"
},
"app.appearance-settings.select-option": {
"message": "Scegli una pagina"
"message": "Seleziona"
},
"app.appearance-settings.toggle-sidebar.description": {
"message": "Scegli se mostrare o nascondere la barra laterale."
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "Esplora i server"
},
"app.instance.worlds.delete-world-description": {
"message": "\"{name}\" verrà **eliminato permanentemente** e non ci sarà modo di recuperarlo."
},
"app.instance.worlds.delete-world-title": {
"message": "Vuoi davvero eliminare questo mondo per sempre?"
},
@@ -248,12 +245,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "Nessun server o mondo aggiunto"
},
"app.instance.worlds.remove-server-description": {
"message": "\"{name}\" sarà rimosso dalla tua lista, inclusa quella nel gioco, e non ci sarà modo di recuperarlo."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "\"{name}\" ({address}) sarà rimosso dalla tua lista, inclusa quella nel gioco, e non ci sarà modo di recuperarlo."
},
"app.instance.worlds.remove-server-title": {
"message": "Vuoi davvero rimuovere {name}?"
},
@@ -272,9 +263,6 @@
"app.modal.install-to-play.install-button": {
"message": "Installa"
},
"app.modal.install-to-play.mod-count": {
"message": "{count} mod"
},
"app.modal.install-to-play.required-modpack": {
"message": "Pacchetto di mod richiesto"
},
@@ -611,6 +599,24 @@
"instance.settings.tabs.java": {
"message": "Java e memoria"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Variabili d'ambiente"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Argomenti JVM"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Eseguibile di Java"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Memoria allocata"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Inserisci le variabili d'ambiente..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Inserisci gli argomenti JVM..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Variabili d'ambiente"
},
@@ -626,6 +632,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Memoria allocata"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/percorso/di/java"
},
"instance.settings.tabs.window": {
"message": "Finestra"
},
@@ -254,9 +254,6 @@
"app.modal.install-to-play.install-button": {
"message": "インストール"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, other {#個のMod}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "必須のModパック"
},
@@ -368,9 +365,6 @@
"friends.action.add-friend": {
"message": "フレンドを追加"
},
"friends.action.view-friend-requests": {
"message": "{count}件の友達リクエスト"
},
"friends.add-friend.submit": {
"message": "フレンド申請を送信"
},
+24 -6
View File
@@ -24,7 +24,7 @@
"message": "실행 중인 인스턴스 보이기"
},
"app.action-bar.stop-instance": {
"message": "인스턴스 중지"
"message": "인스턴스 멈추기"
},
"app.action-bar.view-active-downloads": {
"message": "다운로드 목록 보기"
@@ -192,10 +192,10 @@
"message": "이 모드팩은 이미 <bold>{instanceName}</bold> 인스턴스에 설치되어 있습니다. 정말로 복제하시겠습니까?"
},
"app.instance.modpack-already-installed.create": {
"message": "생성"
"message": "만들기"
},
"app.instance.modpack-already-installed.header": {
"message": "모드팩 이미 설치"
"message": "이미 설치된 모드팩"
},
"app.instance.modpack-already-installed.instance": {
"message": "인스턴스"
@@ -395,9 +395,6 @@
"friends.action.add-friend": {
"message": "친구 추가"
},
"friends.action.view-friend-requests": {
"message": "{count}건의 친구 요청"
},
"friends.add-friend.submit": {
"message": "친구 요청 보내기"
},
@@ -611,6 +608,24 @@
"instance.settings.tabs.java": {
"message": "Java 및 메모리"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "사용자 지정 환경 변수"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "사용자 지정 Java 매개변수"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "사용자 지정 Java 설치"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "사용자 지정 메모리 할당"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "환경 변수를 입력하세요..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Java 인수를 입력하세요..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "환경 변수"
},
@@ -626,6 +641,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "할당된 메모리"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/path/to/java"
},
"instance.settings.tabs.window": {
"message": "창"
},
@@ -272,9 +272,6 @@
"app.modal.install-to-play.install-button": {
"message": "Pasang"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, other {# mod}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Pek mod yang diperlukan"
},
@@ -392,9 +389,6 @@
"friends.action.add-friend": {
"message": "Tambah rakan"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural, other {permintaan}} rakan"
},
"friends.add-friend.submit": {
"message": "Hantar permintaan rakan"
},
@@ -189,7 +189,7 @@
"message": "Verwijder instantie"
},
"app.instance.modpack-already-installed.body": {
"message": "Deze modpakket is al in de <bold>{instanceName}<bold> instantie geïnstalleerd. Ben je zeker dat je het geen wil dupliceren?"
"message": "Deze modpakket is al in de <bold>{instanceName}</bold> instantie geïnstalleerd. Ben je zeker dat je het geen wil dupliceren?"
},
"app.instance.modpack-already-installed.create": {
"message": "Maak"
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "Zoek servers"
},
"app.instance.worlds.delete-world-description": {
"message": "{name} Zal **permanent verwijderd** worden en kan niet hersteld worden."
},
"app.instance.worlds.delete-world-title": {
"message": "Weet je zeker dat je deze wereld definitief wilt verwijderen?"
},
@@ -257,9 +254,6 @@
"app.instance.worlds.remove-server-title": {
"message": "Ben je zeker dat je {name} wil verwijderen?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Zoek werelden"
},
"app.instance.worlds.this-server": {
"message": "deze server"
},
@@ -206,9 +206,6 @@
"app.instance.mods.project-was-added": {
"message": "Dodano \"{name}\""
},
"app.instance.mods.projects-were-added": {
"message": "Dodano {count} {count, plural, one {projekt} few {projekty} other {projektów}}"
},
"app.instance.mods.share-text": {
"message": "Sprawdź projekty, które używam w mojej paczce modów!"
},
@@ -272,9 +269,6 @@
"app.modal.install-to-play.install-button": {
"message": "Zainstaluj"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# mod} few {# mody} other {# modów}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Wymagana paczka modów"
},
@@ -395,9 +389,6 @@
"friends.action.add-friend": {
"message": "Dodaj znajomego"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural, one {zaproszenie} few {zaproszenia} other {zaproszeń}} do znajomych"
},
"friends.add-friend.submit": {
"message": "Wyślij zaproszenie"
},
+21 -6
View File
@@ -272,9 +272,6 @@
"app.modal.install-to-play.install-button": {
"message": "Instalar"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, =0 {Nenhum mod} one {# mod} other {# mods}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Pacote de mods necessário"
},
@@ -395,9 +392,6 @@
"friends.action.add-friend": {
"message": "Adicionar um amigo"
},
"friends.action.view-friend-requests": {
"message": "{count, plural, =0 {Nenhuma solicitação de amizade} one {{count} solicitação de amizade} other {{count} solicitações de amizade}}"
},
"friends.add-friend.submit": {
"message": "Enviar amizade"
},
@@ -611,6 +605,24 @@
"instance.settings.tabs.java": {
"message": "Java e memória"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Variáveis de ambiente personalizadas"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Argumentos Java personalizados"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Instalação personalizada do Java"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Alocação de memória personalizada"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Insira as variáveis de ambiente..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Insira os argumentos Java..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Variáveis de ambiente"
},
@@ -626,6 +638,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Memória alocada"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/caminho/ao/java"
},
"instance.settings.tabs.window": {
"message": "Janela"
},
@@ -149,9 +149,6 @@
"app.instance.worlds.browse-servers": {
"message": "Procurar servidores"
},
"app.instance.worlds.delete-world-description": {
"message": "\"{name}\" vai ser **apagado permanentemente**, e não haverá maneira de o recuperar."
},
"app.instance.worlds.delete-world-title": {
"message": "Tens a certeza que queres apagar permanentemente este mundo?"
},
@@ -173,12 +170,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "Sem servidores ou mundos adicionados"
},
"app.instance.worlds.remove-server-description": {
"message": "\"{name}\" vai ser removido da tua lista, incluindo dentro do jogo, e não haverá maneira de o recuperar."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "\"{name}\" ({address}) vai ser removido da tua lista, incluindo dentro do jogo, e não haverá maneira de o recuperar."
},
"app.instance.worlds.remove-server-title": {
"message": "Tens a certeza que queres remover {name}?"
},
+23 -26
View File
@@ -206,9 +206,6 @@
"app.instance.mods.project-was-added": {
"message": "«{name}» добавлен"
},
"app.instance.mods.projects-were-added": {
"message": "{count, plural, one {Добавлен # проект} few {Добавлено # проекта} other {Добавлено # проектов}}"
},
"app.instance.mods.share-text": {
"message": "Что в моей сборке:"
},
@@ -224,9 +221,6 @@
"app.instance.worlds.browse-servers": {
"message": "Найти серверы"
},
"app.instance.worlds.delete-world-description": {
"message": "«{name}» будет **удалён навсегда**. Его невозможно восстановить."
},
"app.instance.worlds.delete-world-title": {
"message": "Вы действительно хотите удалить этот мир?"
},
@@ -248,18 +242,9 @@
"app.instance.worlds.no-worlds-heading": {
"message": "Нет серверов и миров"
},
"app.instance.worlds.remove-server-description": {
"message": "«{name}» будет удалён из списка — в том числе в игре. Его невозможно восстановить."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "«{name}» ({address}) будет удалён из списка — в том числе в игре. Его невозможно восстановить."
},
"app.instance.worlds.remove-server-title": {
"message": "Вы действительно хотите удалить {name}?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "Поиск по {count, plural, one {# миру} other {# мирам}}..."
},
"app.instance.worlds.this-server": {
"message": "этот сервер"
},
@@ -272,9 +257,6 @@
"app.modal.install-to-play.install-button": {
"message": "Установить"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# мод} few {# мода} other {# модов}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Необходимая сборка"
},
@@ -360,7 +342,7 @@
"message": "Доступно обновление"
},
"app.update.complete-toast.text": {
"message": "Нажмите здесь, чтобы посмотреть изменения."
"message": "Нажмите, чтобы посмотреть список изменений."
},
"app.update.complete-toast.title": {
"message": "Версия {version} успешно установлена!"
@@ -395,9 +377,6 @@
"friends.action.add-friend": {
"message": "Добавить в друзья"
},
"friends.action.view-friend-requests": {
"message": "{count} {count, plural, one {запрос} few {запроса} other {запросов}} дружбы"
},
"friends.add-friend.submit": {
"message": "Отправить запрос дружбы"
},
@@ -491,9 +470,6 @@
"instance.edit-world.title": {
"message": "Настройка мира"
},
"instance.files.adding-files": {
"message": "Добавление файлов ({completed, number}/{total, number})"
},
"instance.files.save-as": {
"message": "Сохранить как..."
},
@@ -611,6 +587,24 @@
"instance.settings.tabs.java": {
"message": "Java и память"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Пользовательские настройки запуска"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Пользовательские аргументы Java"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Пользовательская установка Java"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Пользовательский объём памяти"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Введите дополнительные параметры системы..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Введите аргументы Java..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Переменные среды"
},
@@ -626,6 +620,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Выделенная память"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/path/to/java"
},
"instance.settings.tabs.window": {
"message": "Окно"
},
@@ -741,7 +738,7 @@
"message": "Загрузчик управляется сервером"
},
"unknown-pack-warning-modal.body": {
"message": "Файлы любого формата проверены на безопасность, если они загружены на Modrinth (в том числе файлы .mrpack)."
"message": "Файл проверяется только в том случае, если он загружен на Modrinth, независимо от его формата (включая .mrpack)."
},
"unknown-pack-warning-modal.dont-show-again": {
"message": "Больше не предупреждать"
@@ -260,9 +260,6 @@
"app.modal.install-to-play.install-button": {
"message": "ติดตั้ง"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, other {# ม็อด}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "มอดแพ็กที่จำเป็น"
},
@@ -374,9 +371,6 @@
"friends.action.add-friend": {
"message": "เพิ่มเพื่อน"
},
"friends.action.view-friend-requests": {
"message": "คำขอเป็นเพื่อน {count} {count, plural, other {คน}}"
},
"friends.add-friend.submit": {
"message": "ส่งคำขอเป็นเพื่อน"
},
@@ -368,9 +368,6 @@
"friends.action.add-friend": {
"message": "Bir arkadaş ekle"
},
"friends.action.view-friend-requests": {
"message": "{count} arkadaşlık isteği"
},
"friends.add-friend.submit": {
"message": "Arkadaşlık isteği gönder"
},
+23 -17
View File
@@ -168,7 +168,7 @@
"message": "Назва збірки"
},
"app.export-modal.select-files-label": {
"message": "Змінити які файли додані до експорту"
"message": "Змініть файли, які додані до експорту"
},
"app.export-modal.version-number-label": {
"message": "Номер версії"
@@ -222,10 +222,7 @@
"message": "Додати сервер"
},
"app.instance.worlds.browse-servers": {
"message": "Переглянути сервера"
},
"app.instance.worlds.delete-world-description": {
"message": "«{name}» буде **назавжди видалено** й у вас не буде можливости відновлення."
"message": "Переглянути сервери"
},
"app.instance.worlds.delete-world-title": {
"message": "Ви впевнені, що хочете назавжди видалити цей світ?"
@@ -248,12 +245,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "Сервера або світи не додано"
},
"app.instance.worlds.remove-server-description": {
"message": "«{name}» буде видалено з вашого списку, включно в грі, і без можливости відновлення."
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "«{name}» ({address}) буде видалено з вашого списку, включно в грі, і без можливости відновлення."
},
"app.instance.worlds.remove-server-title": {
"message": "Ви впевнені, що хочете видалити «{name}»?"
},
@@ -272,9 +263,6 @@
"app.modal.install-to-play.install-button": {
"message": "Установити"
},
"app.modal.install-to-play.mod-count": {
"message": "{count, plural, one {# мод} few {# мода} other {# модів}}"
},
"app.modal.install-to-play.required-modpack": {
"message": "Потрібна збірка"
},
@@ -395,9 +383,6 @@
"friends.action.add-friend": {
"message": "Додати друга"
},
"friends.action.view-friend-requests": {
"message": "{count} запит{count, plural, one { у} few {и в} many {ів у} other {у в}} друзі"
},
"friends.add-friend.submit": {
"message": "Надіслати запит у друзі"
},
@@ -611,6 +596,24 @@
"instance.settings.tabs.java": {
"message": "Java та пам’ять"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Власні змінні середовища"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Власні аргументи Java"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Власна інсталяція Java"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Власний розподіл пам'яті"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Уведіть змінні середовища…"
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Уведіть аргументи Java…"
},
"instance.settings.tabs.java.environment-variables": {
"message": "Змінні середовища"
},
@@ -626,6 +629,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Виділена пам’ять"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/шлях/до/java"
},
"instance.settings.tabs.window": {
"message": "Вікно"
},
@@ -1,10 +1,115 @@
{
"app.action-bar.downloading-java": {
"message": "Đang tải xuống Java {version}"
},
"app.action-bar.downloads": {
"message": "Tải xuống"
},
"app.action-bar.hide-more-running-instances": {
"message": "Đóng các phiên bản đang chạy"
},
"app.action-bar.make-primary-instance": {
"message": "Đặt làm bản instance chính"
},
"app.action-bar.no-instances-running": {
"message": "Không có phiên bản nào đang chạy"
},
"app.action-bar.offline": {
"message": "Ngoại tuyến"
},
"app.action-bar.primary-instance": {
"message": "Bản instance chính"
},
"app.action-bar.show-more-running-instances": {
"message": "Hiện thêm các phiên bản đang chạy"
},
"app.action-bar.stop-instance": {
"message": "Dừng instance"
},
"app.action-bar.view-active-downloads": {
"message": "Xem các lượt tải xuống"
},
"app.action-bar.view-instance": {
"message": "Xem phiên bản"
},
"app.action-bar.view-logs": {
"message": "Xem logs"
},
"app.appearance-settings.advanced-rendering.description": {
"message": "Kích hoạt các tính năng dựng hình nâng cao như hiệu ứng làm mờ, có thể gây giảm hiệu năng nếu không có chế độ tăng tốc phần cứng."
},
"app.appearance-settings.advanced-rendering.title": {
"message": "Dựng hình nâng cao"
},
"app.appearance-settings.color-theme.description": {
"message": "Chọn màu nền ưu thích của bạn cho Modrinth App."
},
"app.appearance-settings.color-theme.title": {
"message": "Màu chủ đề"
},
"app.appearance-settings.default-landing-page.description": {
"message": "Thay đổi trang hiển thị khi khởi chạy launcher."
},
"app.appearance-settings.default-landing-page.home": {
"message": "Trang chủ"
},
"app.appearance-settings.default-landing-page.library": {
"message": "Thư viện"
},
"app.appearance-settings.default-landing-page.title": {
"message": "Trang mặc định"
},
"app.appearance-settings.hide-nametag.description": {
"message": "Tắt hiển thị thẻ tên phía trên người chơi ở trang skin."
},
"app.appearance-settings.hide-nametag.title": {
"message": "Ẩn thẻ tên"
},
"app.appearance-settings.jump-back-into-worlds.description": {
"message": "Hiển thị các thế giới gần đây trong mục \"Tiếp tục chơi\" ở Trang chủ."
},
"app.appearance-settings.jump-back-into-worlds.title": {
"message": "Tiếp tục chơi"
},
"app.appearance-settings.minimize-launcher.description": {
"message": "Thu nhỏ launcher khi game Minecraft bắt đầu chạy."
},
"app.appearance-settings.minimize-launcher.title": {
"message": "Thu nhỏ launcher"
},
"app.appearance-settings.native-decorations.description": {
"message": "Sử dụng khung cửa sổ hệ thống (yêu cầu khởi động lại ứng dụng)."
},
"app.appearance-settings.native-decorations.title": {
"message": "Giao diện cửa sổ hệ thống"
},
"app.appearance-settings.select-option": {
"message": "Chọn một tuỳ chọn"
},
"app.appearance-settings.toggle-sidebar.description": {
"message": "Bật tính năng ẩn hiển thị thanh menu bên."
},
"app.appearance-settings.toggle-sidebar.title": {
"message": "Ẩn/hiện thanh bên"
},
"app.appearance-settings.unknown-pack-warning.description": {
"message": "Nếu bạn cố gắng cài đặt tệp Modrinth Pack (.mrpack) không được lưu trữ trên máy chủ Modrinth, chúng tôi sẽ đảm bảo bạn hiểu rõ các rủi ro trước khi cài đặt."
},
"app.appearance-settings.unknown-pack-warning.title": {
"message": "Cảnh báo tôi trước khi cài đặt các modpacks không rõ nguồn gốc"
},
"app.auth-servers.unreachable.body": {
"message": "Máy chủ xác thực của Minecraft có thể đang bị sập. Hãy kiểm tra kết nối Internet của bạn và thử lại sau."
},
"app.auth-servers.unreachable.header": {
"message": "Không thể kết nối đến máy chủ xác thực"
},
"app.browse.add-servers-to-instance": {
"message": "Thêm máy chủ vào phiên bản"
},
"app.browse.add-to-an-instance": {
"message": "Thêm vào phiên bản"
},
"app.browse.add-to-instance": {
"message": "Thêm vào hồ sơ"
},
@@ -17,12 +122,33 @@
"app.browse.already-added": {
"message": "Đã được thêm"
},
"app.browse.back-to-instance": {
"message": "Quay lại phiên bản"
},
"app.browse.discover-content": {
"message": "Khám phá nội dung"
},
"app.browse.discover-servers": {
"message": "Khám phá máy chủ"
},
"app.browse.hide-added-servers": {
"message": "Ẩn các server đã thêm"
},
"app.browse.project-type.modpacks": {
"message": "Modpack"
},
"app.browse.server-instance-content-warning": {
"message": "Thêm nội dung có thể gây lỗi tương thích khi tham gia máy chủ. Bất kỳ nội dung nào được thêm vào cũng sẽ bị mất khi bạn cập nhật nội dung của phiên bản máy chủ."
},
"app.browse.server.installing": {
"message": "Đang cài đặt"
},
"app.creation-modal.installing-modpack.description": {
"message": "{fileName}"
},
"app.creation-modal.installing-modpack.title": {
"message": "Đang cài đặt modpack..."
},
"app.export-modal.description-placeholder": {
"message": "Thêm miêu tả cho gói modpack..."
},
@@ -32,12 +158,18 @@
"app.export-modal.header": {
"message": "Xuất modpack"
},
"app.export-modal.include-file-accessibility-label": {
"message": "Bao gồm \"{file}\"?"
},
"app.export-modal.modpack-name-label": {
"message": "Tên modpack"
},
"app.export-modal.modpack-name-placeholder": {
"message": "Tên modpack"
},
"app.export-modal.select-files-label": {
"message": "Cấu hình các tệp nào được bao gồm trong quá trình xuất phiên bản này"
},
"app.export-modal.version-number-label": {
"message": "Phiên bản"
},
@@ -167,6 +299,15 @@
"app.modal.update-to-play.update-required-description": {
"message": "Bạn cần cập nhật {name} để có thể chơi. Vui lòng cập nhật lên bản mới nhất để khởi chạy trò chơi."
},
"app.project.install-button.already-installed": {
"message": "Dự án này đã được cài đặt"
},
"app.project.install-context.back-to-browse": {
"message": "Quay lại trang Khám Phá"
},
"app.project.install-context.install-content-to-instance": {
"message": "Cài đặt nội dung vào phiên bản"
},
"app.settings.developer-mode-enabled": {
"message": "Chế độ nhà phát triển đã được bật."
},
@@ -470,6 +611,24 @@
"instance.settings.tabs.java": {
"message": "Java và bộ nhớ"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "Tùy chọn biến môi trường"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "Tùy chỉnh tham số Java"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "Tùy chỉnh phiên bản cài đặt Java"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "Tùy chỉnh phân bổ bộ nhớ"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "Nhập biến môi trường..."
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "Nhập tham số Java..."
},
"instance.settings.tabs.java.environment-variables": {
"message": "Biến môi trường"
},
@@ -485,6 +644,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "Bộ nhớ phân bổ"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/đường_dẫn/tới/java"
},
"instance.settings.tabs.window": {
"message": "Cửa sổ"
},
@@ -557,6 +719,24 @@
"instance.worlds.world_in_use": {
"message": "Thế giới đang mở"
},
"minecraft-account.add-account": {
"message": "Thêm tài khoản"
},
"minecraft-account.label": {
"message": "Tài khoản Minecraft"
},
"minecraft-account.not-signed-in": {
"message": "Chưa đăng nhập"
},
"minecraft-account.remove-account": {
"message": "Xoá tài khoản"
},
"minecraft-account.select-account": {
"message": "Chọn tài khoản"
},
"minecraft-account.sign-in": {
"message": "Đăng nhập vào Minecraft"
},
"search.filter.locked.instance": {
"message": "Được cung cấp bởi phiên bản"
},
@@ -580,5 +760,26 @@
},
"search.filter.locked.server-loader.title": {
"message": "Loader được cung cấp bởi máy chủ"
},
"unknown-pack-warning-modal.body": {
"message": "Tệp chỉ được xem xét nếu nó được tải lên Modrinth, bất kể định dạng tệp của nó là gì (bao gồm cả .mrpack)."
},
"unknown-pack-warning-modal.dont-show-again": {
"message": "Đừng hiển thị cảnh báo này nữa"
},
"unknown-pack-warning-modal.header": {
"message": "Xác nhận cài đặt"
},
"unknown-pack-warning-modal.install-anyway": {
"message": "Tiếp tục cài đặt"
},
"unknown-pack-warning-modal.malware-statement": {
"message": "Phần mềm độc hại thường được phát tán thông qua các tệp modpack bằng cách chia sẻ chúng trên các nền tảng như Discord."
},
"unknown-pack-warning-modal.warning.body": {
"message": "Chúng tôi không tìm thấy tập tin này trên Modrinth. Chúng tôi đặc biệt khuyên bạn chỉ nên cài đặt các tập tin từ các nguồn đáng tin cậy."
},
"unknown-pack-warning-modal.warning.title": {
"message": "Cảnh báo tệp không xác định"
}
}
+1 -16
View File
@@ -63,7 +63,7 @@
"message": "在皮肤页面中禁用你玩家头顶上的名牌。"
},
"app.appearance-settings.hide-nametag.title": {
"message": "隐藏名"
"message": "隐藏名称标签"
},
"app.appearance-settings.jump-back-into-worlds.description": {
"message": "在主页的“快速回到”部分包含最近的世界。"
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "浏览服务器"
},
"app.instance.worlds.delete-world-description": {
"message": "“{name}”将被**永久删除**,并且无法恢复。"
},
"app.instance.worlds.delete-world-title": {
"message": "你确定要永久删除这个世界吗?"
},
@@ -248,12 +245,6 @@
"app.instance.worlds.no-worlds-heading": {
"message": "未添加服务器或世界"
},
"app.instance.worlds.remove-server-description": {
"message": "将从你的列表中删除“{name}”,包括游戏内,并且无法恢复。"
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "将从你的列表中删除“{name}”({address}),包括游戏内,并且无法恢复。"
},
"app.instance.worlds.remove-server-title": {
"message": "你确定要删除 {name} 吗?"
},
@@ -272,9 +263,6 @@
"app.modal.install-to-play.install-button": {
"message": "安装"
},
"app.modal.install-to-play.mod-count": {
"message": "{count} 个模组"
},
"app.modal.install-to-play.required-modpack": {
"message": "需求整合包"
},
@@ -395,9 +383,6 @@
"friends.action.add-friend": {
"message": "添加好友"
},
"friends.action.view-friend-requests": {
"message": "{count} 个好友请求"
},
"friends.add-friend.submit": {
"message": "发送好友请求"
},
+27 -18
View File
@@ -147,10 +147,10 @@
"message": "{fileName}"
},
"app.creation-modal.installing-modpack.title": {
"message": "正在安裝模組包..."
"message": "正在安裝模組包……"
},
"app.export-modal.description-placeholder": {
"message": "輸入模組包描述..."
"message": "輸入模組包描述……"
},
"app.export-modal.export-button": {
"message": "匯出"
@@ -224,9 +224,6 @@
"app.instance.worlds.browse-servers": {
"message": "瀏覽伺服器"
},
"app.instance.worlds.delete-world-description": {
"message": "「{name}」將**永久刪除**,且無法還原。"
},
"app.instance.worlds.delete-world-title": {
"message": "確定要永久刪除這個世界嗎?"
},
@@ -248,17 +245,11 @@
"app.instance.worlds.no-worlds-heading": {
"message": "未新增任何伺服器或世界"
},
"app.instance.worlds.remove-server-description": {
"message": "「{name}」將從你的清單中移除(包含遊戲內),且無法還原。"
},
"app.instance.worlds.remove-server-description-with-address": {
"message": "「{name}」({address}) 將從你的清單中移除(包含遊戲內),且無法還原。"
},
"app.instance.worlds.remove-server-title": {
"message": "確定要移除「{name}」嗎?"
},
"app.instance.worlds.search-worlds-placeholder": {
"message": "搜尋 {count} 個世界..."
"message": "搜尋 {count} 個世界……"
},
"app.instance.worlds.this-server": {
"message": "這個伺服器"
@@ -272,9 +263,6 @@
"app.modal.install-to-play.install-button": {
"message": "安裝"
},
"app.modal.install-to-play.mod-count": {
"message": "{count} 個模組"
},
"app.modal.install-to-play.required-modpack": {
"message": "所需模組包"
},
@@ -302,6 +290,9 @@
"app.project.install-button.already-installed": {
"message": "這個專案已安裝"
},
"app.project.install-context.back-to-browse": {
"message": "返回瀏覽"
},
"app.project.install-context.install-content-to-instance": {
"message": "將內容安裝至實例"
},
@@ -392,9 +383,6 @@
"friends.action.add-friend": {
"message": "新增好友"
},
"friends.action.view-friend-requests": {
"message": "{count} 個好友邀請"
},
"friends.add-friend.submit": {
"message": "送出好友邀請"
},
@@ -608,6 +596,24 @@
"instance.settings.tabs.java": {
"message": "Java 和記憶體"
},
"instance.settings.tabs.java.custom-environment-variables": {
"message": "自訂環境變數"
},
"instance.settings.tabs.java.custom-java-arguments": {
"message": "自訂 Java 參數"
},
"instance.settings.tabs.java.custom-java-installation": {
"message": "自訂 Java 安裝"
},
"instance.settings.tabs.java.custom-memory-allocation": {
"message": "自訂記憶體分配"
},
"instance.settings.tabs.java.enter-environment-variables": {
"message": "輸入環境變數……"
},
"instance.settings.tabs.java.enter-java-arguments": {
"message": "輸入 Java 參數……"
},
"instance.settings.tabs.java.environment-variables": {
"message": "環境變數"
},
@@ -623,6 +629,9 @@
"instance.settings.tabs.java.java-memory": {
"message": "記憶體配置"
},
"instance.settings.tabs.java.java-path-placeholder": {
"message": "/path/to/java"
},
"instance.settings.tabs.window": {
"message": "視窗"
},
File diff suppressed because it is too large Load Diff
@@ -77,7 +77,7 @@ function buildLogList(rawLogs) {
log.filename !== 'latest_stdout.log' &&
log.filename !== 'latest_stdout' &&
log.filename !== 'launcher_log.txt' &&
log.stdout !== '' &&
(log.output == null || log.output !== '') &&
(log.filename.includes('.log') || log.filename.endsWith('.txt')),
)
.map((log) => ({
+14 -5
View File
@@ -230,8 +230,12 @@ function fileNameFromPath(path: string) {
return path.split('/').pop() ?? path
}
function getContentItemId(item: ContentItem | null | undefined) {
return item?.file_path ?? item?.file_name ?? item?.id ?? ''
}
function getContentOperationKeys(item: ContentItem) {
return [item.id, item.file_path, item.file_name, item.project?.id, item.version?.id].filter(
return [getContentItemId(item), item.file_path, item.file_name].filter(
(key): key is string => !!key,
)
}
@@ -478,10 +482,11 @@ async function switchProjectVersion(mod: ContentItem, version: Labrinth.Versions
}
async function handleUpdate(id: string) {
const item = projects.value.find((p) => p.id === id)
const item = projects.value.find((p) => getContentItemId(p) === id)
if (!item?.has_update || !item.project?.id || !item.version?.id) return
const requestId = beginUpdateRequest()
const itemId = getContentItemId(item)
debug('handleUpdate triggered', {
fileName: item.file_name,
@@ -542,7 +547,8 @@ async function handleUpdate(id: string) {
return handleError(e)
})) as Labrinth.Versions.v2.Version[] | null
if (!isActiveUpdateRequest(requestId) || updatingProject.value?.id !== item.id) return
if (!isActiveUpdateRequest(requestId) || getContentItemId(updatingProject.value) !== itemId)
return
loadingVersions.value = false
@@ -595,6 +601,7 @@ async function handleSwitchVersion(item: ContentItem) {
if (!item.project?.id || !item.version?.id) return
const requestId = beginUpdateRequest()
const itemId = getContentItemId(item)
updatingModpack.value = false
updatingProject.value = item
@@ -610,7 +617,8 @@ async function handleSwitchVersion(item: ContentItem) {
return handleError(e)
})) as Labrinth.Versions.v2.Version[] | null
if (!isActiveUpdateRequest(requestId) || updatingProject.value?.id !== item.id) return
if (!isActiveUpdateRequest(requestId) || getContentItemId(updatingProject.value) !== itemId)
return
loadingVersions.value = false
@@ -1055,8 +1063,9 @@ provideContentManager({
showContentHint,
dismissContentHint,
shareItems: handleShareItems,
getItemId: getContentItemId,
mapToTableItem: (item: ContentItem) => ({
id: item.id,
id: getContentItemId(item),
project: item.project ?? {
id: item.file_name,
slug: null,
+2 -2
View File
@@ -86,10 +86,10 @@ export default new createRouter({
},
{
path: '/skins',
name: 'Skins',
name: 'Skin selector',
component: Pages.Skins,
meta: {
breadcrumb: [{ name: 'Skins' }],
breadcrumb: [{ name: 'Skin selector' }],
},
},
{
+2
View File
@@ -21,6 +21,7 @@ export type ColorTheme = (typeof THEME_OPTIONS)[number]
export type ThemeStore = {
selectedTheme: ColorTheme
advancedRendering: boolean
hideNametagSkinsPage: boolean
toggleSidebar: boolean
devMode: boolean
@@ -30,6 +31,7 @@ export type ThemeStore = {
export const DEFAULT_THEME_STORE: ThemeStore = {
selectedTheme: 'dark',
advancedRendering: true,
hideNametagSkinsPage: false,
toggleSidebar: false,
devMode: false,
+3 -1
View File
@@ -114,10 +114,12 @@ fn main() {
"get_available_capes",
"get_available_skins",
"add_and_equip_custom_skin",
"set_default_cape",
"equip_skin",
"remove_custom_skin",
"save_custom_skin",
"unequip_skin",
"flush_pending_skin_change",
"flush_pending_skin_change_for_profile",
"normalize_skin_texture",
"get_dragged_skin_data",
])
+1 -1
View File
@@ -18,7 +18,7 @@ pub struct AdsState {
const AD_LINK: &str = "https://modrinth.com/wrapper/app-ads-cookie";
#[cfg(any(windows, target_os = "macos"))]
pub(super) const OCCLUDED_AREA_THRESHOLD: f64 = 1.0;
pub(super) const OCCLUDED_AREA_THRESHOLD: f64 = 0.5;
#[cfg(not(target_os = "linux"))]
const ADS_USER_AGENT: &str = concat!(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ",
+51 -17
View File
@@ -11,10 +11,12 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
get_available_capes,
get_available_skins,
add_and_equip_custom_skin,
set_default_cape,
equip_skin,
remove_custom_skin,
save_custom_skin,
unequip_skin,
flush_pending_skin_change,
flush_pending_skin_change_for_profile,
normalize_skin_texture,
get_dragged_skin_data,
])
@@ -37,29 +39,19 @@ pub async fn get_available_skins() -> Result<Vec<Skin>> {
Ok(minecraft_skins::get_available_skins().await?)
}
/// `invoke('plugin:minecraft-skins|add_and_equip_custom_skin', texture_blob, variant, cape_override)`
/// `invoke('plugin:minecraft-skins|add_and_equip_custom_skin', texture_blob, variant, cape)`
///
/// See also: [minecraft_skins::add_and_equip_custom_skin]
#[tauri::command]
pub async fn add_and_equip_custom_skin(
texture_blob: Bytes,
variant: MinecraftSkinVariant,
cape_override: Option<Cape>,
) -> Result<()> {
Ok(minecraft_skins::add_and_equip_custom_skin(
texture_blob,
variant,
cape_override,
cape: Option<Cape>,
) -> Result<Skin> {
Ok(
minecraft_skins::add_and_equip_custom_skin(texture_blob, variant, cape)
.await?,
)
.await?)
}
/// `invoke('plugin:minecraft-skins|set_default_cape', cape)`
///
/// See also: [minecraft_skins::set_default_cape]
#[tauri::command]
pub async fn set_default_cape(cape: Option<Cape>) -> Result<()> {
Ok(minecraft_skins::set_default_cape(cape).await?)
}
/// `invoke('plugin:minecraft-skins|equip_skin', skin)`
@@ -78,6 +70,27 @@ pub async fn remove_custom_skin(skin: Skin) -> Result<()> {
Ok(minecraft_skins::remove_custom_skin(skin).await?)
}
/// `invoke('plugin:minecraft-skins|save_custom_skin', skin, texture_blob, variant, cape, replace_texture)`
///
/// See also: [minecraft_skins::save_custom_skin]
#[tauri::command]
pub async fn save_custom_skin(
skin: Skin,
texture_blob: Bytes,
variant: MinecraftSkinVariant,
cape: Option<Cape>,
replace_texture: bool,
) -> Result<Skin> {
Ok(minecraft_skins::save_custom_skin(
skin,
texture_blob,
variant,
cape,
replace_texture,
)
.await?)
}
/// `invoke('plugin:minecraft-skins|unequip_skin')`
///
/// See also: [minecraft_skins::unequip_skin]
@@ -86,6 +99,27 @@ pub async fn unequip_skin() -> Result<()> {
Ok(minecraft_skins::unequip_skin().await?)
}
/// `invoke('plugin:minecraft-skins|flush_pending_skin_change')`
///
/// See also: [minecraft_skins::flush_pending_skin_change]
#[tauri::command]
pub async fn flush_pending_skin_change() -> Result<()> {
Ok(minecraft_skins::flush_pending_skin_change().await?)
}
/// `invoke('plugin:minecraft-skins|flush_pending_skin_change_for_profile', profile_id)`
///
/// See also: [minecraft_skins::flush_pending_skin_change_for_profile]
#[tauri::command]
pub async fn flush_pending_skin_change_for_profile(
profile_id: uuid::Uuid,
) -> Result<()> {
Ok(
minecraft_skins::flush_pending_skin_change_for_profile(profile_id)
.await?,
)
}
/// `invoke('plugin:minecraft-skins|normalize_skin_texture')`
///
/// See also: [minecraft_skins::normalize_skin_texture]
+12 -2
View File
@@ -270,10 +270,20 @@ fn main() {
Ok(app) => {
app.run(|app, event| {
#[cfg(not(any(feature = "updater", target_os = "macos")))]
drop((app, event));
let _ = app;
if matches!(&event, tauri::RunEvent::ExitRequested { .. })
&& let Err(error) = tauri::async_runtime::block_on(
theseus::minecraft_skins::flush_pending_skin_change(),
)
{
tracing::warn!(
"Failed to flush pending Minecraft skin change before exit: {error}"
);
}
#[cfg(feature = "updater")]
if matches!(event, tauri::RunEvent::Exit) {
if matches!(&event, tauri::RunEvent::Exit) {
let update_data = app.state::<PendingUpdateData>().inner();
let should_restart = State::get_if_initialized()
.map(|s| {
+53 -36
View File
@@ -65,49 +65,65 @@ async fn fetch(
)
.await?;
// We check Modrinth's fabric version manifest and compare if the fabric version exists in Modrinth's database
// We also check intermediary versions that are newly added to query
let (fetch_fabric_versions, fetch_intermediary_versions) =
if let Some(modrinth_manifest) = modrinth_manifest {
let (mut fetch_versions, mut fetch_intermediary_versions) =
(Vec::new(), Vec::new());
// We check Modrinth's manifest to find newly added loader versions,
// intermediary/mapping artifacts, and game versions.
let (
fetch_fabric_versions,
fetch_intermediary_versions,
has_new_game_versions,
) = if let Some(modrinth_manifest) = modrinth_manifest {
let (mut fetch_versions, mut fetch_intermediary_versions) =
(Vec::new(), Vec::new());
for version in &fabric_manifest.loader {
if !modrinth_manifest
.game_versions
.iter()
.any(|x| x.loaders.iter().any(|x| x.id == version.version))
&& !skip_versions.contains(&&*version.version)
{
fetch_versions.push(version);
}
for version in &fabric_manifest.loader {
if !modrinth_manifest
.game_versions
.iter()
.any(|x| x.loaders.iter().any(|x| x.id == version.version))
&& !skip_versions.contains(&&*version.version)
{
fetch_versions.push(version);
}
}
for version in &fabric_manifest.intermediary {
if !modrinth_manifest
for version in &fabric_manifest.intermediary {
if !modrinth_manifest
.game_versions
.iter()
.any(|x| x.id == version.version)
&& fabric_manifest
.game
.iter()
.any(|x| x.version == version.version)
{
fetch_intermediary_versions.push(version);
}
}
let has_new_game_versions =
fabric_manifest.game.iter().any(|version| {
!modrinth_manifest
.game_versions
.iter()
.any(|x| x.id == version.version)
&& fabric_manifest
.game
.iter()
.any(|x| x.version == version.version)
{
fetch_intermediary_versions.push(version);
}
}
});
(fetch_versions, fetch_intermediary_versions)
} else {
(
fabric_manifest
.loader
.iter()
.filter(|x| !skip_versions.contains(&&*x.version))
.collect(),
fabric_manifest.intermediary.iter().collect(),
)
};
(
fetch_versions,
fetch_intermediary_versions,
has_new_game_versions,
)
} else {
(
fabric_manifest
.loader
.iter()
.filter(|x| !skip_versions.contains(&&*x.version))
.collect(),
fabric_manifest.intermediary.iter().collect(),
true,
)
};
const DUMMY_GAME_VERSION: &str = "1.21";
@@ -216,6 +232,7 @@ async fn fetch(
if !fetch_fabric_versions.is_empty()
|| !fetch_intermediary_versions.is_empty()
|| has_new_game_versions
{
let fabric_manifest_path =
format!("{mod_loader}/v{format_version}/manifest.json",);
+1
View File
@@ -11,6 +11,7 @@
"lint": "eslint . && prettier --check .",
"fix": "eslint . --fix && prettier --write .",
"intl:extract": "formatjs extract \"src/{components,composables,layouts,middleware,modules,pages,plugins,utils}/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" \"src/error.vue\" --ignore \"**/*.d.ts\" --ignore node_modules --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
"intl:prune-local": "pnpm -w scripts i18n-icu-contract prune-local --scope apps/frontend",
"cf-deploy": "pnpm run build && wrangler deploy --env staging",
"cf-dev": "pnpm run build && wrangler dev --env staging",
"cf-typegen": "wrangler types"
@@ -5,7 +5,6 @@ import {
commonMessages,
defineMessages,
IntlFormatted,
normalizeChildren,
PagewideBanner,
useVIntl,
} from '@modrinth/ui'
@@ -22,7 +21,7 @@ const messages = defineMessages({
},
description: {
id: 'layout.banner.preview.description',
defaultMessage: `If you meant to access the official Modrinth website, visit {url}. This preview deploy is used by Modrinth staff for testing purposes. It was built using <branch-link>{owner}/{branch}</branch-link> @ {commit}.`,
defaultMessage: `If you meant to access the official Modrinth website, visit {url}. This preview deploy is used by Modrinth staff for testing purposes. It was built using {ref}.`,
},
})
@@ -41,30 +40,22 @@ const url = computed(() => `https://modrinth.com${route.fullPath}`)
</template>
<template #description>
<span>
<IntlFormatted
:message-id="messages.description"
:values="{
owner: config.public.owner,
branch: config.public.branch,
}"
>
<IntlFormatted :message-id="messages.description">
<template #url>
<a :href="url" target="_blank" rel="noopener" class="text-link">
{{ url }}
</a>
</template>
<template #branch-link="{ children }">
<template #ref>
<a
:href="`https://github.com/${config.public.owner}/code/tree/${config.public.branch}`"
target="_blank"
rel="noopener"
class="hover:underline"
>
<component :is="() => normalizeChildren(children)" />
{{ config.public.owner }} / {{ config.public.branch }}
</a>
</template>
<template #commit>
<span v-if="config.public.hash === 'unknown'">unknown</span>
@ <span v-if="config.public.hash === 'unknown'">unknown</span>
<a
v-else
:href="`https://github.com/${config.public.owner}/code/commit/${config.public.hash}`"
@@ -46,7 +46,7 @@
/>
</div>
<div class="flex flex-col gap-2">
<span class="font-semibold text-contrast"> Version changlog </span>
<span class="font-semibold text-contrast"> Version changelog </span>
<div class="w-full">
<MarkdownEditor
@@ -48,6 +48,16 @@
<span class="text-sm text-secondary">Requesting</span>
<Badge :type="queueEntry.project.requested_status" class="text-sm" />
</div>
<div
v-if="showExternalDependencies"
v-tooltip="'External dependencies'"
class="flex items-center gap-1 rounded-full border border-solid border-surface-5 bg-surface-4 px-2.5 py-1"
>
<FileIcon aria-hidden="true" class="size-4 text-secondary" />
<span class="text-sm font-medium text-secondary">
{{ queueEntry.external_dependencies_count }}
</span>
</div>
</div>
<div v-if="queueEntry.ownership?.kind === 'user'">
<NuxtLink
@@ -119,7 +129,7 @@
</template>
<script setup lang="ts">
import { ClipboardCopyIcon, LinkIcon, ScaleIcon } from '@modrinth/assets'
import { ClipboardCopyIcon, FileIcon, LinkIcon, ScaleIcon } from '@modrinth/assets'
import {
Avatar,
Badge,
@@ -151,6 +161,7 @@ const formatDateTimeFull = useFormatDateTime({
const props = defineProps<{
queueEntry: ModerationProject
showExternalDependencies?: boolean
}>()
const emit = defineEmits<{
@@ -701,11 +701,11 @@ async function navigateToNextUnlockedProject(): Promise<boolean> {
// Quick re-check if close to expiry (last 5 seconds of TTL)
if (now - next.validatedAt > PREFETCH_STALE_MS - 5000) {
const recheck = await moderationQueue.checkLock(next.projectId)
if (recheck.locked && !recheck.expired) {
// Project got locked, remove from queue and try next
const recheckResults = await batchCheckQueueCandidates([next.projectId])
const recheck = recheckResults.get(next.projectId)
if (!isEligibleQueueCandidate(recheck)) {
prefetchQueue.value.shift()
return navigateToNextUnlockedProject() // Recurse to try next
return navigateToNextUnlockedProject()
}
}
@@ -717,33 +717,14 @@ async function navigateToNextUnlockedProject(): Promise<boolean> {
next.skippedIds.map((id) => moderationQueue.completeCurrentProject(id, 'skipped')),
)
if (next.skippedIds.length > 0) {
addNotification({
title: 'Skipped locked projects',
text: `Skipped ${next.skippedIds.length} project(s) being moderated by others.`,
type: 'info',
})
}
notifySkippedQueueProjects(next.skippedIds.length)
// Trigger prefetch replenishment in background (don't await)
maintainPrefetchQueue()
// Navigate to canonical URL if we have metadata (avoids middleware redirect)
if (next.slug && next.projectType) {
const urlType = getProjectTypeForUrlShorthand(next.projectType, [], tags.value)
navigateTo({
path: `/${urlType}/${next.slug}`,
state: { showChecklist: true },
})
} else {
// Fallback: use project ID (will trigger middleware redirect)
navigateTo({
name: 'type-project',
params: { type: 'project', project: next.projectId },
state: { showChecklist: true },
})
}
navigateToQueueProject(
{ slug: next.slug, projectType: next.projectType, locked: false, isProcessing: true },
next.projectId,
)
return true
}
@@ -869,53 +850,108 @@ function reviewAnyway() {
maintainPrefetchQueue()
}
// Batch check locks and fetch project metadata in parallel
interface LockCheckResult {
// Batch check locks, processing status, and fetch project metadata in parallel
interface QueueCandidateCheck {
locked: boolean
expired?: boolean
isOwnLock?: boolean
slug?: string
projectType?: string
status?: string
isProcessing: boolean
}
async function batchCheckLocksWithMetadata(
function isEligibleQueueCandidate(result: QueueCandidateCheck | undefined): boolean {
if (!result?.isProcessing) return false
return !result.locked || !!result.expired || !!result.isOwnLock
}
function notifySkippedQueueProjects(count: number) {
if (count <= 0) return
addNotification({
title: 'Skipped projects',
text: `Skipped ${count} project(s) already moderated or locked by others.`,
type: 'info',
autoCloseMs: 2000,
})
}
function navigateToQueueProject(result: QueueCandidateCheck, projectId: string) {
if (result.slug && result.projectType) {
const urlType = getProjectTypeForUrlShorthand(result.projectType, [], tags.value)
navigateTo({
path: `/${urlType}/${result.slug}`,
state: { showChecklist: true },
})
} else {
navigateTo({
name: 'type-project',
params: { type: 'project', project: projectId },
state: { showChecklist: true },
})
}
}
async function batchCheckQueueCandidates(
projectIds: string[],
): Promise<Map<string, LockCheckResult>> {
const results = new Map<string, LockCheckResult>()
): Promise<Map<string, QueueCandidateCheck>> {
const results = new Map<string, QueueCandidateCheck>()
// Check locks and fetch minimal project data in parallel
const checks = await Promise.allSettled(
projectIds.map(async (id) => {
// Parallel: check lock AND fetch project metadata
const [lockResponse, projectData] = await Promise.all([
moderationQueue.checkLock(id),
useBaseFetch(`project/${id}`, { method: 'GET' }).catch(() => null),
])
const status = (projectData as { status?: string } | null)?.status
return {
id,
locked: lockResponse.locked,
expired: lockResponse.expired,
isOwnLock: lockResponse.is_own_lock,
slug: (projectData as { slug?: string })?.slug,
projectType: (projectData as { project_type?: string })?.project_type,
slug: (projectData as { slug?: string } | null)?.slug,
projectType: (projectData as { project_type?: string } | null)?.project_type,
status,
isProcessing: projectData === null ? true : status === 'processing',
}
}),
)
// Use forEach with index to avoid indexOf bug on PromiseSettledResult
checks.forEach((result, index) => {
if (result.status === 'fulfilled') {
results.set(result.value.id, result.value)
} else {
// On error, mark as needing fallback (no metadata)
results.set(projectIds[index], { locked: false })
results.set(projectIds[index], { locked: false, isProcessing: true })
}
})
return results
}
async function findNextEligibleQueueProject(candidateIds: string[]) {
const skippedIds: string[] = []
let checkedCount = 0
while (checkedCount < candidateIds.length) {
const batch = candidateIds.slice(checkedCount, checkedCount + PREFETCH_BATCH_SIZE)
checkedCount += batch.length
const results = await batchCheckQueueCandidates(batch)
for (const id of batch) {
const result = results.get(id)
if (isEligibleQueueCandidate(result)) {
return { projectId: id, result: result!, skippedIds: [...skippedIds] }
}
skippedIds.push(id)
}
}
return null
}
// Maintain a queue of prefetched unlocked projects for instant navigation
async function maintainPrefetchQueue() {
if (isPrefetching.value) return
@@ -947,13 +983,10 @@ async function maintainPrefetchQueue() {
const remainingItems =
currentIndex >= 0 ? queueItems.slice(currentIndex + 1) : queueItems.slice(1)
const candidateIds = remainingItems
.filter((id) => !prefetchedIds.has(id))
.slice(0, PREFETCH_BATCH_SIZE * 2) // Check up to 10 candidates
const candidateIds = remainingItems.filter((id) => !prefetchedIds.has(id))
if (candidateIds.length === 0) return
// 5. Batch check locks AND fetch metadata in parallel
const skippedIds: string[] = []
let checkedCount = 0
@@ -964,31 +997,18 @@ async function maintainPrefetchQueue() {
const batch = candidateIds.slice(checkedCount, checkedCount + PREFETCH_BATCH_SIZE)
checkedCount += batch.length
const results = await batchCheckLocksWithMetadata(batch)
const results = await batchCheckQueueCandidates(batch)
for (const id of batch) {
const result = results.get(id)
// Treat as unlocked if: not locked, OR expired, OR it's our own lock
if (!result?.locked || result?.expired || result?.isOwnLock) {
// Found unlocked project with metadata
if (result?.slug && result?.projectType) {
prefetchQueue.value.push({
projectId: id,
slug: result.slug,
projectType: result.projectType,
validatedAt: Date.now(),
skippedIds: [...skippedIds],
})
} else {
// No metadata - still add but will need fallback navigation
prefetchQueue.value.push({
projectId: id,
slug: '', // Empty = use fallback
projectType: '',
validatedAt: Date.now(),
skippedIds: [...skippedIds],
})
}
if (isEligibleQueueCandidate(result)) {
prefetchQueue.value.push({
projectId: id,
slug: result?.slug ?? '',
projectType: result?.projectType ?? '',
validatedAt: Date.now(),
skippedIds: [...skippedIds],
})
if (prefetchQueue.value.length >= PREFETCH_TARGET_COUNT) break
} else {
@@ -1004,8 +1024,6 @@ async function maintainPrefetchQueue() {
// Debounced prefetch to prevent spam from rapid stage changes
const debouncedPrefetch = useDebounceFn(maintainPrefetchQueue, 300)
const MAX_SKIP_ATTEMPTS = 10
async function skipToNextProject() {
// Skip the current project
const currentProjectId = projectV2.value?.id
@@ -1029,60 +1047,28 @@ async function skipToNextProject() {
debug('[skipToNextProject] No prefetch, entering fallback with batch checking')
// Fallback: batch check remaining projects with metadata (excluding current)
const remainingIds: string[] = []
const queueItems = moderationQueue.currentQueue.items
// Build list of remaining projects, excluding current
for (const id of queueItems) {
if (id === currentProjectId) continue
if (remainingIds.length >= MAX_SKIP_ATTEMPTS) break
remainingIds.push(id)
}
const remainingIds = moderationQueue.currentQueue.items.filter((id) => id !== currentProjectId)
if (remainingIds.length > 0) {
const results = await batchCheckLocksWithMetadata(remainingIds)
const next = await findNextEligibleQueueProject(remainingIds)
let skippedCount = 0
for (const id of remainingIds) {
const result = results.get(id)
// Treat as unlocked if: not locked, OR expired, OR it's our own lock
if (!result?.locked || result?.expired || result?.isOwnLock) {
// Found unlocked - skip the locked ones before it
if (skippedCount > 0) {
addNotification({
title: 'Skipped locked projects',
text: `Skipped ${skippedCount} project(s) being moderated by others.`,
type: 'info',
})
}
// Navigate to canonical URL if we have metadata
if (result?.slug && result?.projectType) {
const urlType = getProjectTypeForUrlShorthand(result.projectType, [], tags.value)
navigateTo({
path: `/${urlType}/${result.slug}`,
state: { showChecklist: true },
})
} else {
// Fallback: use project ID
navigateTo({
name: 'type-project',
params: { type: 'project', project: id },
state: { showChecklist: true },
})
}
return
}
await moderationQueue.completeCurrentProject(id, 'skipped')
skippedCount++
if (next) {
await Promise.all(
next.skippedIds.map((id) => moderationQueue.completeCurrentProject(id, 'skipped')),
)
notifySkippedQueueProjects(next.skippedIds.length)
navigateToQueueProject(next.result, next.projectId)
return
}
// All checked were locked
debug('[skipToNextProject] All projects were locked, skippedCount:', skippedCount)
await Promise.all(
remainingIds.map((id) => moderationQueue.completeCurrentProject(id, 'skipped')),
)
debug('[skipToNextProject] No eligible projects in queue')
addNotification({
title: 'All projects locked',
text: 'All remaining projects are currently being moderated by others.',
title: 'No projects available',
text: 'All remaining projects are already moderated or locked by others.',
type: 'warning',
})
}
@@ -1298,32 +1284,16 @@ onMounted(async () => {
document.addEventListener('visibilitychange', handleVisibilityChange)
notifications.setNotificationLocation('left')
// Check if project has already been reviewed (not in processing status)
if (projectV2.value.status !== 'processing') {
alreadyReviewed.value = true
return
}
// Try to acquire lock
const result = await moderationQueue.acquireLock(projectV2.value.id)
if (result.success) {
handleLockAcquired()
} else if (result.locked_by) {
// Actually locked by another moderator
// In queue mode with more projects - auto-skip to next project
if (moderationQueue.isQueueMode && moderationQueue.queueLength > 1) {
addNotification({
title: 'Project locked',
text: `Skipped project locked by @${result.locked_by.username}.`,
type: 'info',
})
// skipToNextProject already calls completeCurrentProject
await skipToNextProject()
return
}
// Single project mode or last in queue - show locked UI
lockStatus.value = {
locked: true,
lockedBy: result.locked_by,
@@ -2085,72 +2055,36 @@ async function endChecklist(status?: string) {
})
}
} else {
// Use prefetched data if available for instant navigation
if (!(await navigateToNextUnlockedProject())) {
// Fallback: batch check remaining projects with metadata
const remainingIds: string[] = []
const currentProjectId = projectV2.value?.id
const queueItems = moderationQueue.currentQueue.items
const remainingIds = moderationQueue.currentQueue.items.filter(
(id) => id !== currentProjectId,
)
// Build list of remaining projects, excluding current
for (const id of queueItems) {
if (id === currentProjectId) continue
if (remainingIds.length >= MAX_SKIP_ATTEMPTS) break
remainingIds.push(id)
}
let foundUnlocked = false
let foundEligible = false
if (remainingIds.length > 0) {
const results = await batchCheckLocksWithMetadata(remainingIds)
const next = await findNextEligibleQueueProject(remainingIds)
let skippedCount = 0
for (const id of remainingIds) {
const result = results.get(id)
// Treat as unlocked if: not locked, OR expired, OR it's our own lock
if (!result?.locked || result?.expired || result?.isOwnLock) {
// Found unlocked - skip the locked ones before it
if (skippedCount > 0) {
addNotification({
title: 'Skipped locked projects',
text: `Skipped ${skippedCount} project(s) being moderated by others.`,
type: 'info',
})
}
// Navigate to canonical URL if we have metadata
if (result?.slug && result?.projectType) {
const urlType = getProjectTypeForUrlShorthand(result.projectType, [], tags.value)
navigateTo({
path: `/${urlType}/${result.slug}`,
state: { showChecklist: true },
})
} else {
// Fallback: use project ID
navigateTo({
name: 'type-project',
params: { type: 'project', project: id },
state: { showChecklist: true },
})
}
foundUnlocked = true
break
}
await moderationQueue.completeCurrentProject(id, 'skipped')
skippedCount++
}
// If no unlocked projects found, show notification
if (!foundUnlocked && skippedCount > 0) {
if (next) {
await Promise.all(
next.skippedIds.map((id) => moderationQueue.completeCurrentProject(id, 'skipped')),
)
notifySkippedQueueProjects(next.skippedIds.length)
navigateToQueueProject(next.result, next.projectId)
foundEligible = true
} else {
await Promise.all(
remainingIds.map((id) => moderationQueue.completeCurrentProject(id, 'skipped')),
)
addNotification({
title: 'All projects locked',
text: 'All remaining projects are currently being moderated by others.',
title: 'No projects available',
text: 'All remaining projects are already moderated or locked by others.',
type: 'warning',
})
}
}
// If no unlocked projects found, go back to moderation queue
if (!foundUnlocked) {
if (!foundEligible) {
await navigateTo({
name: 'moderation',
})
@@ -27,6 +27,11 @@ const messages = defineMessages({
id: 'hosting.plan.select-plan',
defaultMessage: 'Select plan',
},
billedInterval: {
id: 'servers.purchase.step.plan.billed',
defaultMessage:
'billed {interval, select, monthly {monthly} quarterly {quarterly} yearly {yearly} other {{interval}}}',
},
})
const plans: Record<
@@ -132,7 +137,9 @@ const billingMonths = computed(() => {
<span class="m-0 text-2xl font-bold text-contrast">
{{ formatPrice(price / billingMonths, currency, true) }}
<span class="text-lg font-semibold text-secondary">
/ month<template v-if="interval !== 'monthly'">, billed {{ interval }}</template>
/ month<template v-if="interval !== 'monthly'"
>, {{ formatMessage(messages.billedInterval, { interval }) }}</template
>
</span>
</span>
<p class="m-0 max-w-[18rem]">{{ formatMessage(plans[plan].description) }}</p>
@@ -14,7 +14,7 @@
<p class="m-0">
<IntlFormatted
:message-id="messages.resubmitModalDescription"
:message-values="{ projectTitle: project.title }"
:values="{ projectTitle: project.title }"
>
<template #project-title="{ children }">
<span class="font-semibold text-contrast">
+38 -19
View File
@@ -1,3 +1,10 @@
function normalizeAuthToken(value) {
if (typeof value === 'string') {
return value
}
return ''
}
export const useAuth = async (oldToken = null) => {
const auth = useState('auth', () => ({
user: null,
@@ -32,27 +39,35 @@ export const initAuth = async (oldToken = null) => {
})
if (oldToken) {
authCookie.value = oldToken
const normalized = normalizeAuthToken(oldToken)
if (normalized) {
authCookie.value = normalized
}
}
if (route.query.code && !route.fullPath.includes('new_account=true')) {
authCookie.value = route.query.code
const oauthCode = normalizeAuthToken(route.query.code)
if (oauthCode && !route.fullPath.includes('new_account=true')) {
authCookie.value = oauthCode
}
if (route.fullPath.includes('new_account=true') && route.path !== '/auth/welcome') {
const redirect = route.path.startsWith('/auth/') ? null : route.fullPath
await navigateTo(
`/auth/welcome?authToken=${route.query.code}${
`/auth/welcome?authToken=${oauthCode}${
redirect ? `&redirect=${encodeURIComponent(redirect)}` : ''
}`,
)
}
if (authCookie.value) {
auth.token = authCookie.value
const tokenStr = normalizeAuthToken(authCookie.value)
if (!auth.token || !auth.token.startsWith('mra_')) {
if (authCookie.value != null && tokenStr === '') {
authCookie.value = null
} else if (tokenStr) {
auth.token = tokenStr
if (!auth.token.startsWith('mra_')) {
return auth
}
@@ -71,7 +86,7 @@ export const initAuth = async (oldToken = null) => {
}
}
if (!auth.user && auth.token) {
if (!auth.user && auth.token && typeof auth.token === 'string') {
try {
const session = await useBaseFetch(
'session/refresh',
@@ -84,18 +99,22 @@ export const initAuth = async (oldToken = null) => {
true,
)
auth.token = session.session
authCookie.value = auth.token
auth.user = await useBaseFetch(
'user',
{
headers: {
Authorization: auth.token,
auth.token = normalizeAuthToken(session.session)
if (auth.token) {
authCookie.value = auth.token
auth.user = await useBaseFetch(
'user',
{
headers: {
Authorization: auth.token,
},
},
},
true,
)
true,
)
} else {
authCookie.value = null
auth.token = ''
}
} catch {
authCookie.value = null
}
+4 -4
View File
@@ -199,7 +199,7 @@ export const scopeMessages = defineMessages({
},
patCreateDescription: {
id: 'scopes.patCreate.description',
defaultMessage: 'Create personal API tokens',
defaultMessage: 'Create personal access tokens',
},
patReadLabel: {
id: 'scopes.patRead.label',
@@ -207,7 +207,7 @@ export const scopeMessages = defineMessages({
},
patReadDescription: {
id: 'scopes.patRead.description',
defaultMessage: 'View created API tokens',
defaultMessage: 'View created personal access tokens',
},
patWriteLabel: {
id: 'scopes.patWrite.label',
@@ -215,7 +215,7 @@ export const scopeMessages = defineMessages({
},
patWriteDescription: {
id: 'scopes.patWrite.description',
defaultMessage: 'Edit personal API tokens',
defaultMessage: 'Edit personal access tokens',
},
patDeleteLabel: {
id: 'scopes.patDelete.label',
@@ -223,7 +223,7 @@ export const scopeMessages = defineMessages({
},
patDeleteDescription: {
id: 'scopes.patDelete.description',
defaultMessage: 'Delete your personal API tokens',
defaultMessage: 'Delete your personal access tokens',
},
sessionReadLabel: {
id: 'scopes.sessionRead.label',
@@ -61,7 +61,7 @@ export interface UseServerInstallContentOptions {
const messages = defineMessages({
unsupportedContentType: {
id: 'discover.install.error.unsupported-content-type',
defaultMessage: 'This content type cannot be installed to a server from browse.',
defaultMessage: 'This content type cannot be installed to a server from Discover.',
},
noServerWorld: {
id: 'discover.install.error.no-server-world',
@@ -63,7 +63,11 @@ export function useCdnDownloadContext() {
})
function createProjectDownloadUrl(originalUrl: string, context?: DownloadContext): string {
if (!originalUrl.startsWith('https://cdn.modrinth.com')) {
if (
typeof originalUrl !== 'string' ||
!originalUrl ||
!originalUrl.startsWith('https://cdn.modrinth.com')
) {
return originalUrl
}
+4 -1
View File
@@ -199,17 +199,20 @@ export type ModerationOwnership = ModerationOwnershipUser | ModerationOwnershipO
export interface ProjectWithOwnership {
ownership: ModerationOwnership
external_dependencies_count: number
[key: string]: any
}
export interface ModerationProject {
project: any
ownership: ModerationOwnership | null
external_dependencies_count: number
}
export function toModerationProjects(projects: ProjectWithOwnership[]): ModerationProject[] {
return projects.map(({ ownership, ...project }) => ({
return projects.map(({ ownership, external_dependencies_count, ...project }) => ({
project,
ownership: ownership ?? null,
external_dependencies_count: external_dependencies_count,
}))
}
+10
View File
@@ -1386,7 +1386,11 @@ const { cycle: changeTheme } = useTheme()
&-mobile {
.account-container {
opacity: 0;
padding-bottom: 0;
pointer-events: none;
transition: opacity 0.15s ease-in-out;
visibility: hidden;
.account-button {
padding: var(--spacing-card-md);
@@ -1409,6 +1413,12 @@ const { cycle: changeTheme } = useTheme()
&.expanded {
transform: translateY(0);
box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.3);
.account-container {
opacity: 1;
pointer-events: auto;
visibility: visible;
}
}
}
}
+1 -7
View File
@@ -410,9 +410,6 @@
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "الملفات التكميلية تستخدم لدعم الموارد مثل كود المصدر، وليس للإصدارات أو الأنواع البديلة."
},
"create.collection.collection-info": {
"message": "سيتم إنشاء مجموعتك الجديدة كمجموعة عامة تحتوي على {count, plural,\n one {# مشروع}\n other {# مشاريع}\n}."
},
"create.collection.create-collection": {
"message": "إنشاء مجموعة"
},
@@ -902,9 +899,6 @@
"dashboard.revenue.stats.withdrawn": {
"message": "تم سحبه "
},
"dashboard.revenue.tos": {
"message": "بتحميل المشاريع إلى مودرينث وسحب الأموال من حسابك، فإنك توافق على <terms-link> المكافآت. تعرّف على المزيد حول </info-link> برنامج المكافآت. "
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "قم بالتنزيل كملف CSV "
},
@@ -942,7 +936,7 @@
"message": "موعد"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "ستتلقى رسالة بريد إلكتروني في <b>{email}<b> مع تعليمات لاسترداد المبلغ المسحوب. "
"message": "ستتلقى رسالة بريد إلكتروني في <b>{email}</b> مع تعليمات لاسترداد المبلغ المسحوب. "
},
"dashboard.withdraw.completion.exchange-rate": {
"message": "سعر الصرف "
+156 -12
View File
@@ -107,6 +107,9 @@
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.description": {
"message": "Aplikace Modrinth je výkonnější než mnoho předních správců modů a využívá pouze 150MB paměti RAM!"
},
"app-marketing.features.performance.discord": {
"message": "Discord"
},
@@ -401,12 +404,51 @@
"collection.title": {
"message": "{name} - Kolekce"
},
"conversation-thread.action.add-private-note": {
"message": "Přidat soukromou poznámku"
},
"conversation-thread.action.close-thread": {
"message": "Uzavřít vlákno"
},
"conversation-thread.action.close-with-reply": {
"message": "Uzavřít s odpovědí"
},
"conversation-thread.action.reject": {
"message": "Zamítnout"
},
"conversation-thread.action.reject-with-reply": {
"message": "Zamítnout s odpovědí"
},
"conversation-thread.action.reopen-thread": {
"message": "Znovuotevřít vlákno"
},
"conversation-thread.action.reply": {
"message": "Odpovědět"
},
"conversation-thread.action.reply-to-thread": {
"message": "Odpovědět vláknu"
},
"conversation-thread.action.send": {
"message": "Odeslat"
},
"conversation-thread.action.send-to-review": {
"message": "Odeslat ke kontrole"
},
"conversation-thread.action.send-to-review-with-reply": {
"message": "Odeslat ke kontrole s odpovědí"
},
"conversation-thread.reply-editor.placeholder.reply": {
"message": "Odpovědět vláknu..."
},
"conversation-thread.reply-editor.placeholder.send": {
"message": "Odeslat zprávu..."
},
"conversation-thread.reply-modal.header": {
"message": "Odpovědět vláknu"
},
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "Doplňkové soubory slouží jako podpůrné materiály (např. zdrojový kód), ne jako alternativní verze či varianty."
},
"create.collection.collection-info": {
"message": "Tvá nová kolekce bude vytvořena jako veřejná a bude obsahovat {count, plural, =0 {žádné projekty} one {# projekt} few {# projekty} other {# projektů}}."
},
"create.collection.create-collection": {
"message": "Vytvořit kolekci"
},
@@ -497,6 +539,9 @@
"create.project.name-placeholder": {
"message": "Zadejte název projektu..."
},
"create.project.owner-label": {
"message": "Vlastník"
},
"create.project.summary-description": {
"message": "Popiště vaši organizace dvěma nebo jednou větou."
},
@@ -548,9 +593,18 @@
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "Jste si jistý, že chcete zrušit svůj affiliate odkaz „{title}“?"
},
"dashboard.analytics.total-downloads": {
"message": "Celková stažení"
},
"dashboard.analytics.total-followers": {
"message": "Celkoví sledující"
},
"dashboard.collections.button.create-new": {
"message": "Vytvořit novou"
},
"dashboard.collections.empty.get-started-hint": {
"message": "Vytvořte svou první kolekci a začněte!"
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, one {project} other {projects}}"
},
@@ -560,6 +614,15 @@
"dashboard.collections.long-title": {
"message": "Vaše kolekce"
},
"dashboard.collections.sort.name-ascending": {
"message": "Jméno (A-Z)"
},
"dashboard.collections.sort.recently-created": {
"message": "Nedávno vytvořeno"
},
"dashboard.collections.sort.recently-updated": {
"message": "Nedávno aktualizováno"
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Hotovo! 🎉"
},
@@ -575,9 +638,18 @@
"dashboard.creator-withdraw-modal.details-label": {
"message": "Detaily"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Množství"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Poplatek"
},
"dashboard.creator-withdraw-modal.fee-breakdown-gift-card-value": {
"message": "Hodnota dárkové karty"
},
"dashboard.creator-withdraw-modal.fee-breakdown-usd-equivalent": {
"message": "Ekvivalent americkému dolaru"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Zvolte vaši zemi"
},
@@ -626,9 +698,18 @@
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": ""
},
"dashboard.creator-withdraw-modal.tremendous-details.enter-denomination-placeholder": {
"message": "Zadejte množství"
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Platební metoda"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Odměna"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder": {
"message": "Vyberte odměnu"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Odměny"
},
@@ -638,9 +719,57 @@
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "Vyčerpali jste svůj limit pro výběr <b>{withdrawLimit}</b>. Pro vyšší výběr musíte vyplnit daňový formulář."
},
"dashboard.organizations.button.create": {
"message": "Vytvořit organizaci"
},
"dashboard.organizations.empty.cta": {
"message": "Vytvořte organizaci!"
},
"dashboard.organizations.error.fetch": {
"message": "Nepodařilo se načíst organizace"
},
"dashboard.overview.notifications.button.mark-all-as-read": {
"message": "Označit vše jako přečtené"
},
"dashboard.overview.notifications.button.view-history": {
"message": "Ukázat historii"
},
"dashboard.overview.notifications.history.label": {
"message": "Historie"
},
"dashboard.overview.notifications.history.title": {
"message": "Historie oznámení"
},
"dashboard.overview.notifications.loading": {
"message": "Načítání oznámení..."
},
"dashboard.projects.head-title": {
"message": "Projekty"
},
"dashboard.projects.links.discord-invite.label": {
"message": "Discord pozvánka"
},
"dashboard.projects.links.placeholder.valid-url": {
"message": "Zadejte platnou URL"
},
"dashboard.projects.sort.option.name": {
"message": "Jméno"
},
"dashboard.projects.sort.option.status": {
"message": "Stav"
},
"dashboard.projects.table.name": {
"message": "Jméno"
},
"dashboard.projects.table.status": {
"message": "Stav"
},
"dashboard.revenue.available-now": {
"message": "K dispozici nyní"
},
"dashboard.revenue.balance": {
"message": "Zůstatek"
},
"dashboard.revenue.estimated-with-date": {
"message": "Odhadováno {date}"
},
@@ -650,18 +779,39 @@
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Stáhnout jako CSV"
},
"dashboard.sidebar.label.creators": {
"message": "Tvůrci"
},
"dashboard.sidebar.label.notifications": {
"message": "Oznámení"
},
"dashboard.sidebar.label.organizations": {
"message": "Organizace"
},
"dashboard.sidebar.label.projects": {
"message": "Projekty"
},
"dashboard.withdraw.completion.account": {
"message": "Účet"
},
"dashboard.withdraw.completion.amount": {
"message": "Množství"
},
"dashboard.withdraw.completion.date": {
"message": "Datum"
},
"dashboard.withdraw.completion.fee": {
"message": "Poplatek"
},
"dashboard.withdraw.completion.transactions-button": {
"message": "Transakce"
},
"dashboard.withdraw.completion.wallet": {
"message": "Peněženka"
},
"discover.install.back-to-server": {
"message": "Zpět na server"
},
"error.collection.404.list_item.1": {
"message": "Možná jste zadali URL adresu kolekce špatně."
},
@@ -752,6 +902,9 @@
"frog.title": {
"message": "Žába"
},
"hosting-marketing.included.custom-url": {
"message": "Vlastní URL"
},
"landing.creator.feature.monetization.title": {
"message": "Monetizace"
},
@@ -1055,9 +1208,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Stáhněte si projekty od {username} na Modrinthu"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> sledující projektu} few {<stat>{count}</stat> sledující projektu} other {<stat>{count}</stat> sledujících projektu}}"
},
"profile.user-id": {
"message": "ID uživatele: {id}"
},
@@ -1202,12 +1352,6 @@
"project.settings.title": {
"message": "Nastavení"
},
"project.stats.downloads-label": {
"message": "stažení{count, plural, one {} few {} many {} other {}}"
},
"project.stats.followers-label": {
"message": "sledující{count, plural, one {} few {} other{ch}}"
},
"project.versions.title": {
"message": "Verze"
},
@@ -1013,9 +1013,6 @@
"hosting-marketing.faq.location": {
"message": "Hvor er Modrinth Hosting servere placeret? Kan jeg vælge et område?"
},
"hosting-marketing.faq.location.answer": {
"message": "Vi har servere tilgængelig i Nord Amerika, Europa, og Sydøst Asien på nuværende tidspunkt som du kan vælge imellem under købet. Flere områder kommer i fremtiden! Hvis du gerne vil skifte til dit område, venligst kontakt support."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Hvilken Minecraft version og loaders kan blive brugt?"
},
@@ -1934,21 +1931,12 @@
"report.already-reported": {
"message": "Du har allerede rapporteret {title}"
},
"report.already-reported-description": {
"message": "Du har allerede en åben anmeldelse for {item, select, project {dette projekt} version {denne version} user {denne bruger} other {dette indhold}}. Du kan tilføje flere detaljer til denne anmeldse hvis du har mere information at tilføje."
},
"report.back-to-item": {
"message": "Tilbage til {item, select, project {projekt} version {version} user {bruger} other {indhold}}"
},
"report.body.description": {
"message": "Inkluder links og billeder hvis muligt og relevant. Tomme eller upræcise rapporter vil blive lukket eller ignoreret."
},
"report.body.title": {
"message": "Venligst tilføj mere information omkring din anmeldelse"
},
"report.could-not-find": {
"message": "Kunne ikke finde {item, select, project {projekt} version {version} user {bruger} other {indhold}}"
},
"report.for.violation.description": {
"message": "Eksempler inkluderer ondsindet, spam, stødende, vildledende, misvisende og ulovligt indhold."
},
@@ -1964,15 +1952,9 @@
"report.please-report": {
"message": "Venligst anmeld:"
},
"report.question.content-id": {
"message": "Hvad er IDet på {item, select, project {projektet} version {versionen} user {brugeren} other {indholdet}}?"
},
"report.question.content-type": {
"message": "Hvilket form for indhold anmelder du?"
},
"report.question.report-reason": {
"message": "Hvilke af Modrinths regler bryder {item, select, project {projektet} version {versionen} user {brugeren} other {indholdet}}?"
},
"report.submit": {
"message": "Indsend anmeldelse"
},
@@ -1295,15 +1295,6 @@
"discover.install.heading.reset-modpack": {
"message": "Modpack zum installieren nach dem Reset auswählen"
},
"discover.seo.description": {
"message": "Suche und durchstöbere tausende von Minecraft {projectType, select, mod {Mods} modpack {Modpacks} resourcepack {Ressourcenpakete} shader {Shader} plugin {Plugins} datapack {Datenpakete} other {Projekte}} auf Modrinth sofortigen, genauen Suchergebnissen. Unsere Filter helfen dir beim schnellen finden der besten Minecraft {projectType, select, mod {Mods} modpack {Modpacks} resourcepack {Ressourcenpakete} shader {Shader} plugin {Plugins} datapack {Datenpakete} other {Projekte}}."
},
"discover.seo.title": {
"message": "Durchsuche {projectType, select, mod {Mods} modpack {Modpacks} resourcepack {Ressourcenpakete} shader {Shader} plugin {Plugins} datapack {Datenpakete} other {Projekte}}"
},
"discover.seo.title-with-query": {
"message": "Durchsuche {projectType, select, mod {Mods} modpack {Modpacks} resourcepack {Ressourcenpakete} shader {Shader} plugin {Plugins} datapack {Datenpakete} other {Projekte}} | {query}"
},
"error.collection.404.list_item.1": {
"message": "Du hast eventuell die Kollektions-URL falsch geschrieben."
},
@@ -1469,9 +1460,6 @@
"hosting-marketing.faq.location": {
"message": "Wo befinden sich Server von Modrinth Hosting? Kann ich eine Region auswählen?"
},
"hosting-marketing.faq.location.answer": {
"message": "Derzeit sind Server in Nordamerika, Europa und Südostasien verfügbar, die du beim Kauf auswählen kannst. Weitere Regionen werden in Zukunft dazukommen! Falls du deine Region wechseln möchtest, wende dich bitte an den Support."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Welche Minecraft-Versionen und Loader können verwendet werden?"
},
@@ -1814,9 +1802,6 @@
"layout.banner.build-fail.title": {
"message": "Fehler beim generieren des Status von der API beim erstellen."
},
"layout.banner.preview.description": {
"message": "Falls du die offizielle Modrinth-Website aufrufen wolltest, besuche {url}. Diese Vorschauversion wird von Modrinth-Mitarbeitern zu Testzwecken genutzt. Sie wurde unter Verwendung von <branch-link>{owner}/{branch}</branch-link> @ {commit} erstellt."
},
"layout.banner.preview.title": {
"message": "Dies ist eine Vorschauversion der Modrinth-Webseite."
},
@@ -2801,24 +2786,12 @@
"report.already-reported": {
"message": "Du hast bereits {title} gemeldet"
},
"report.already-reported-description": {
"message": "Du hast bereits eine offene Meldung für {item, select, project {dieses Projekt} version {diese Version} user {diesen Benutzer} other {diesen Inhalt}}. Du kannst deiner Meldung weitere Details hinzufügen, falls du weitere Informationen hast."
},
"report.back-to-item": {
"message": "Zurück {item, select, project {zum Projekt} version {zur Version} user {zum Benutzer} other {zum Inhalt}}"
},
"report.body.description": {
"message": "Füge Links und Bilder hinzu, sofern relevant. Leere oder unzureichender Meldungen werden geschlossen und ignoriert."
},
"report.body.title": {
"message": "Bitte gib weiteren Kontext über deine Meldung"
},
"report.checking": {
"message": "Überprüfe {item, select, project {Projekt} version {Version} user {Benutzer} other {Inhalt}}..."
},
"report.could-not-find": {
"message": "Konnte {item, select, project {Projekt} version {Version} user {Benutzer} other {Inhalt}} nicht finden"
},
"report.for.violation": {
"message": "Verstoss gegen Modrinth's <rules-link>Regeln</rules-link> oder <terms-link>Nutzungsbedingungen</terms-link>"
},
@@ -2858,15 +2831,9 @@
"report.please-report": {
"message": "Bitte melde:"
},
"report.question.content-id": {
"message": "Was ist die ID {item, select, project {des Projekts} version {der Version} user {des Benutzers} other {des Inhalts}}?"
},
"report.question.content-type": {
"message": "Welche Art an Inhalt meldest du?"
},
"report.question.report-reason": {
"message": "Welche von Modrinths Regeln verletzt {item, select, project {dieses Projekt} version {diese Version} user {dieser Benutzer} other {dieser Inhalt}}?"
},
"report.report-content": {
"message": "Inhalt an Moderatoren melden"
},
@@ -3545,21 +3512,12 @@
"settings.billing.interval.month": {
"message": "Monat"
},
"settings.billing.interval.monthly": {
"message": "monatlich"
},
"settings.billing.interval.quarter": {
"message": "Quartal"
},
"settings.billing.interval.quarterly.adjective": {
"message": "vierteljährlich"
},
"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"
},
@@ -3644,9 +3602,6 @@
"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)"
},
@@ -3713,18 +3668,9 @@
"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"
},
@@ -1295,15 +1295,6 @@
"discover.install.heading.reset-modpack": {
"message": "Modpack zur Installation nach dem Zurücksetzen auswählen"
},
"discover.seo.description": {
"message": "Durchsuche und entdecke tausende Minecraft {projectType, select, mod {Mods} modpack {Modpacks} resourcepack {Ressourcenpakete} shader {Shader} plugin {Plugins} datapack {Datenpakete} other {Projekte}} auf Modrinth mit sofortigen und präzisen Suchergebnissen. Unsere Filter helfen dir dabei, schnell die besten Minecraft {projectType, select, mod {Mods} modpack {Modpacks} resourcepack {Ressourcenpakete} shader {Shader} plugin {Plugins} datapack {Datenpakete} other {Projekte}} zu finden."
},
"discover.seo.title": {
"message": "Durchsuche {projectType, select, mod {Mods} modpack {Modpacks} resourcepack {Ressourcenpakete} shader {Shader} plugin {Plugins} datapack {Datenpakete} other {Projekte}}"
},
"discover.seo.title-with-query": {
"message": "Durchsuche {projectType, select, mod {Mods} modpack {Modpacks} resourcepack {Ressourcenpakete} shader {Shader} plugin {Plugins} datapack {Datenpakete} other {Projekte}} | {query}"
},
"error.collection.404.list_item.1": {
"message": "Eventuell hast du die URL der Kollektion falsch eingegeben."
},
@@ -1469,9 +1460,6 @@
"hosting-marketing.faq.location": {
"message": "Wo befinden sich Server von Modrinth Hosting? Kann ich eine Region auswählen?"
},
"hosting-marketing.faq.location.answer": {
"message": "Derzeit sind Server in Nordamerika, Europa und Südostasien verfügbar, die du beim Kauf auswählen kannst. Weitere Regionen werden in Zukunft dazukommen! Falls du deine Region wechseln möchtest, wende dich bitte an den Support."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Welche Minecraft-Versionen und Loader können verwendet werden?"
},
@@ -1814,9 +1802,6 @@
"layout.banner.build-fail.title": {
"message": "Fehler beim Generieren des Status aus der API beim Erstellen."
},
"layout.banner.preview.description": {
"message": "Falls du die offizielle Modrinth-Website aufrufen wolltest, besuche {url}. Diese Vorschauversion wird von Modrinth-Mitarbeitern zu Testzwecken genutzt. Sie wurde unter Verwendung von <branch-link>{owner}/{branch}</branch-link> @ {commit} erstellt."
},
"layout.banner.preview.title": {
"message": "Dies ist eine Vorschauversion der Modrinth-Website."
},
@@ -2801,24 +2786,12 @@
"report.already-reported": {
"message": "Du hast {title} bereits gemeldet"
},
"report.already-reported-description": {
"message": "Du hast bereits eine offene Meldung für {item, select, project {dieses Projekt} version {diese Version} user {diesen Benutzer} other {diesen Inhalt}}. Du kannst deiner Meldung weitere Details hinzufügen, falls du weitere Informationen hast."
},
"report.back-to-item": {
"message": "Zurück {item, select, project {zum Projekt} version {zur Version} user {zum Benutzer} other {zum Inhalt}}"
},
"report.body.description": {
"message": "Füge nach Möglichkeit und Relevanz Links und Bilder ein. Leere oder unzureichende Meldungen werden geschlossen und ignoriert."
},
"report.body.title": {
"message": "Bitte gib weiteren Kontext über deine Meldung"
},
"report.checking": {
"message": "Überprüfe {item, select, project {Projekt} version {Version} user {Benutzer} other {Inhalt}}..."
},
"report.could-not-find": {
"message": "Konnte {item, select, project {Projekt} version {Version} user {Benutzer} other {Inhalt}} nicht finden"
},
"report.for.violation": {
"message": "Verstoß gegen Modrinths <rules-link>Regeln</rules-link> oder <terms-link>Nutzungsbedingungen</terms-link>"
},
@@ -2858,15 +2831,9 @@
"report.please-report": {
"message": "Bitte melde:"
},
"report.question.content-id": {
"message": "Wie lautet die ID {item, select, project {des Projekts} version {der Version} user {des Benutzers} other {des Inhalts}}?"
},
"report.question.content-type": {
"message": "Welche Art an Inhalt möchtest du melden?"
},
"report.question.report-reason": {
"message": "Welche von Modrinths Regeln verletzt {item, select, project {dieses Projekt} version {diese Version} user {dieser Benutzer} other {dieser Inhalt}}?"
},
"report.report-content": {
"message": "Inhalt den Moderatoren melden"
},
@@ -3545,21 +3512,12 @@
"settings.billing.interval.month": {
"message": "Monat"
},
"settings.billing.interval.monthly": {
"message": "monatlich"
},
"settings.billing.interval.quarter": {
"message": "Quartal"
},
"settings.billing.interval.quarterly.adjective": {
"message": "vierteljährlich"
},
"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"
},
@@ -3644,9 +3602,6 @@
"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)"
},
@@ -3713,18 +3668,9 @@
"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"
},
+46 -34
View File
@@ -123,7 +123,7 @@
"message": "∞ MB"
},
"app-marketing.features.performance.infinite-times-infinite-mb": {
"message": "∞ * ∞ MB"
"message": "∞ × ∞ MB"
},
"app-marketing.features.performance.less-than-150mb": {
"message": "< 150 MB"
@@ -1067,6 +1067,9 @@
"dashboard.projects.links.discord-invite.label": {
"message": "Discord invite"
},
"dashboard.projects.links.header.edit": {
"message": "Edit links"
},
"dashboard.projects.links.issue-tracker.description": {
"message": "A place for users to report bugs, issues, and concerns about your project."
},
@@ -1092,7 +1095,7 @@
"message": "Source code"
},
"dashboard.projects.links.wiki-page.description": {
"message": "A page containing information, documentation, and help for the project."
"message": "A page containing information, documentation, and help for the project"
},
"dashboard.projects.links.wiki-page.label": {
"message": "Wiki page"
@@ -1356,19 +1359,19 @@
"message": "No server world is available for install."
},
"discover.install.error.unsupported-content-type": {
"message": "This content type cannot be installed to a server from browse."
"message": "This content type cannot be installed to a server from Discover."
},
"discover.install.heading.reset-modpack": {
"message": "Selecting modpack to install after reset"
},
"discover.seo.description": {
"message": "Search and browse thousands of Minecraft {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}} on Modrinth with instant, accurate search results. Our filters help you quickly find the best Minecraft {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}}."
"message": "Search and browse thousands of Minecraft {projectType} on Modrinth with instant, accurate search results. Our filters help you quickly find the best Minecraft {projectType}."
},
"discover.seo.title": {
"message": "Search {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}}"
"message": "Search {projectType}"
},
"discover.seo.title-with-query": {
"message": "Search {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}} | {query}"
"message": "Search {projectType} | {query}"
},
"error.collection.404.list_item.1": {
"message": "You may have mistyped the collection's URL."
@@ -1881,7 +1884,7 @@
"message": "Error generating state from API when building."
},
"layout.banner.preview.description": {
"message": "If you meant to access the official Modrinth website, visit {url}. This preview deploy is used by Modrinth staff for testing purposes. It was built using <branch-link>{owner}/{branch}</branch-link> @ {commit}."
"message": "If you meant to access the official Modrinth website, visit {url}. This preview deploy is used by Modrinth staff for testing purposes. It was built using {ref}."
},
"layout.banner.preview.title": {
"message": "This is a preview deploy of the Modrinth website."
@@ -2357,6 +2360,9 @@
"muralpay.warning.wallet-address": {
"message": "Double-check your wallet address. Funds sent to an incorrect address cannot be recovered."
},
"organization.settings.projects.edit-links.affected-projects": {
"message": "Changes will be applied to {count, plural, one {# project} other {# projects}}."
},
"profile.bio.fallback.creator": {
"message": "A Modrinth creator."
},
@@ -2381,6 +2387,9 @@
"profile.button.set-affiliate": {
"message": "Set as affiliate"
},
"profile.collection.projects-count": {
"message": "{count, plural, one {# project} other {# projects}}"
},
"profile.details.label.auth-providers": {
"message": "Auth providers"
},
@@ -2450,6 +2459,12 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Download {username}'s projects on Modrinth"
},
"profile.official-account": {
"message": "Official Modrinth account"
},
"profile.official-account.bio": {
"message": "The official user account of Modrinth. Get support at <support-link></support-link> or via email at <email></email>"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> project follower} other {<stat>{count}</stat> project followers}}"
},
@@ -2898,10 +2913,10 @@
"message": "Visit projects dashboard"
},
"project.stats.downloads-label": {
"message": "download{count, plural, one {} other {s}}"
"message": "{count, plural, one {download} other {downloads}}"
},
"project.stats.followers-label": {
"message": "follower{count, plural, one {} other {s}}"
"message": "{count, plural, one {follower} other {followers}}"
},
"project.status.archived.message": {
"message": "{title} has been archived. {title} will not receive any further updates unless the author decides to unarchive the project."
@@ -2922,10 +2937,10 @@
"message": "You've already reported {title}"
},
"report.already-reported-description": {
"message": "You have an open report for this {item, select, project {project} version {version} user {user} other {content}} already. You can add more details to your report if you have more information to add."
"message": "You have an open report for this {item} already. You can add more details to your report if you have more information to add."
},
"report.back-to-item": {
"message": "Back to {item, select, project {project} version {version} user {user} other {content}}"
"message": "Back to {item}"
},
"report.body.description": {
"message": "Include links and images if possible and relevant. Empty or insufficient reports will be closed and ignored."
@@ -2934,10 +2949,10 @@
"message": "Please provide additional context about your report"
},
"report.checking": {
"message": "Checking {item, select, project {project} version {version} user {user} other {content}}..."
"message": "Checking {item}..."
},
"report.could-not-find": {
"message": "Could not find {item, select, project {project} version {version} user {user} other {content}}"
"message": "Could not find {item}"
},
"report.for.violation": {
"message": "Violation of Modrinth <rules-link>Rules</rules-link> or <terms-link>Terms of Use</terms-link>"
@@ -2979,13 +2994,13 @@
"message": "Please report:"
},
"report.question.content-id": {
"message": "What is the ID of the {item, select, project {project} version {version} user {user} other {content}}?"
"message": "What is the ID of the {item}?"
},
"report.question.content-type": {
"message": "What type of content are you reporting?"
},
"report.question.report-reason": {
"message": "Which of Modrinth's rules is this {item, select, project {project} version {version} user {user} other {content}} violating?"
"message": "Which of Modrinth's rules is this {item} violating?"
},
"report.report-content": {
"message": "Report content to moderators"
@@ -3099,25 +3114,25 @@
"message": "Write organizations"
},
"scopes.patCreate.description": {
"message": "Create personal API tokens"
"message": "Create personal access tokens"
},
"scopes.patCreate.label": {
"message": "Create PATs"
},
"scopes.patDelete.description": {
"message": "Delete your personal API tokens"
"message": "Delete your personal access tokens"
},
"scopes.patDelete.label": {
"message": "Delete PATs"
},
"scopes.patRead.description": {
"message": "View created API tokens"
"message": "View created personal access tokens"
},
"scopes.patRead.label": {
"message": "Read PATs"
},
"scopes.patWrite.description": {
"message": "Edit personal API tokens"
"message": "Edit personal access tokens"
},
"scopes.patWrite.label": {
"message": "Write PATs"
@@ -3326,6 +3341,9 @@
"servers.plan.small.description": {
"message": "Perfect for 15 friends with a few light mods."
},
"servers.purchase.step.plan.billed": {
"message": "billed {interval, select, monthly {monthly} quarterly {quarterly} yearly {yearly} other {{interval}}}"
},
"settings.account.button.complete-setup": {
"message": "Complete setup"
},
@@ -3488,6 +3506,12 @@
"settings.account.security.two-factor.description": {
"message": "Add an additional layer of security to your account during login."
},
"settings.account.security.two-factor.modal.remove.header": {
"message": "Remove 2FA"
},
"settings.account.security.two-factor.modal.setup.header": {
"message": "Setup 2FA"
},
"settings.account.security.two-factor.title": {
"message": "Two-factor authentication"
},
@@ -3665,21 +3689,12 @@
"settings.billing.interval.month": {
"message": "month"
},
"settings.billing.interval.monthly": {
"message": "monthly"
},
"settings.billing.interval.quarter": {
"message": "quarter"
},
"settings.billing.interval.quarterly.adjective": {
"message": "quarterly"
},
"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"
},
@@ -3764,9 +3779,6 @@
"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)"
},
@@ -3834,16 +3846,16 @@
"message": "Subscriptions"
},
"settings.billing.switch.switching-to-interval": {
"message": "Switching to {interval}"
"message": "Switching to {interval, select, monthly {monthly} yearly {yearly} other {{interval}}}"
},
"settings.billing.switch.to-interval": {
"message": "Switch to {interval}"
"message": "Switch to {interval, select, monthly {monthly} yearly {yearly} other {{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}"
"message": "Switches to {interval, select, monthly {monthly} yearly {yearly} other {{interval}}} billing on {date}"
},
"settings.billing.update-method": {
"message": "Update method"
+105 -51
View File
@@ -42,7 +42,7 @@
"message": "Al descargar la Modrinth App, 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)"
"message": "Descarga Modrinth App (Beta)"
},
"app-marketing.download.windows": {
"message": "Windows"
@@ -497,6 +497,27 @@
"conversation-thread.reply-modal.help-center-note": {
"message": "Si necesitas ponerte en contacto con el equipo de moderación, por favor utiliza el <help-center-link>Centro de ayuda de Modrinth</help-center-link> y haz clic en la burbuja azúl en la esquina inferior derecha para contactar soporte."
},
"conversation-thread.resubmit-modal.confirmation.description": {
"message": "Confirma que has atendido las observaciones de los moderadores"
},
"conversation-thread.resubmit-modal.confirmation.label": {
"message": "Confirmo que he atendido correctamente las observaciones de los moderadores."
},
"conversation-thread.resubmit-modal.description": {
"message": "Estás enviando <project-title>{projectTitle}</project-title> para ser revisado de nuevo por los moderadores."
},
"conversation-thread.resubmit-modal.header.resubmitting": {
"message": "Enviando de nuevo para revisión"
},
"conversation-thread.resubmit-modal.header.submitting": {
"message": "Enviando para revisión"
},
"conversation-thread.resubmit-modal.reminder": {
"message": "Asegúrate de haber leído y resuelto todas las observaciones del equipo de moderación."
},
"conversation-thread.resubmit-modal.warning": {
"message": "Envíos repetidos sin atender las observaciones de los moderadores pueden resultar en la suspensión de la cuenta."
},
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "Los archivos complementarios sirven para recursos de apoyo, como código fuente, no para versiones o variantes alternativas."
},
@@ -965,6 +986,9 @@
"dashboard.head-title": {
"message": "Panel de control"
},
"dashboard.notifications.empty.no-unread": {
"message": "No tienes notificaciones sin leer."
},
"dashboard.notifications.link.see-all": {
"message": "Ver todas"
},
@@ -995,6 +1019,9 @@
"dashboard.overview.notifications.button.view-history": {
"message": "Ver historial"
},
"dashboard.overview.notifications.empty.no-unread": {
"message": "No tienes notificaciones sin leer."
},
"dashboard.overview.notifications.error.loading": {
"message": "Error cargando notificaciones:"
},
@@ -1334,15 +1361,6 @@
"discover.install.heading.reset-modpack": {
"message": "Seleccionando modpack para instalar antes del reinicio"
},
"discover.seo.description": {
"message": "Busca y navega miles de Minecraft {projectType, select, mod {mods} modpack {modpacks} packs de recursos {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}} en Modrinth con resultados de busqueda instantáneos y precisos. Nuestros filtradores te ayudan a encontrar rápidamente lo mejor de Minecraft {projectType, select, mod {mods} modpack {modpacks} packs de recursos {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}}."
},
"discover.seo.title": {
"message": "Buscar {projectType, select, mod {mods} modpack {modpacks} packs de recursos {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}"
},
"discover.seo.title-with-query": {
"message": "Buscar {projectType, select, mod {mods} modpack {modpacks} packs de recursos {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects} | {query}"
},
"error.collection.404.list_item.1": {
"message": "Puede que hayas escrito mal la URL de la colección."
},
@@ -1509,7 +1527,7 @@
"message": "¿Dónde se encuentran los servidores de Modrinth Hosting? ¿Puedo elegir una región?"
},
"hosting-marketing.faq.location.answer": {
"message": "Actualmente disponemos de servidores en Norteamérica, Europa y el Sudeste Asiático entre los que puede elegir al realizar la compra. ¡En el futuro añadiremos más regiones! Si deseas cambiar de región, ponte en contacto con soporte."
"message": "Tenemos servidores disponibles a través de Norteamérica, Europa y el sudeste asiático que puedes seleccionar en el momento de tu compra. ¡Más regiones en el futuro! Si deseas cambiar tu región, por favor contacta con soporte."
},
"hosting-marketing.faq.versions-loaders": {
"message": "¿Qué versiones y loaders de Minecraft se pueden utilizar?"
@@ -2681,6 +2699,81 @@
"project.license.title": {
"message": "Licencia"
},
"project.moderation.admonition.approved.body.private": {
"message": "Tu proyecto es privado, lo que significa que solo pueden acceder tú y las personas a las que invites."
},
"project.moderation.admonition.approved.body.public": {
"message": "Tu proyecto está publicado y aparece en las búsquedas de Modrinth."
},
"project.moderation.admonition.approved.body.unlisted": {
"message": "Tu proyecto no está listado, lo que significa que solo se puede acceder a él a través de un link directo y no aparece en las búsquedas de Modrinth."
},
"project.moderation.admonition.approved.body.visibility-message": {
"message": "Puedes cambiar la visibilidad de tu proyecto en la <visibility-settings-link>configuración de visibilidad</visibility-settings-link> de tu proyecto."
},
"project.moderation.admonition.approved.header": {
"message": "Proyecto aprobado"
},
"project.moderation.admonition.draft.body": {
"message": "Este es un borrador de tu proyecto que nadie puede ver hasta que sea enviado para ser revisado y aprobado por el equipo de moderación de Modrinth."
},
"project.moderation.admonition.draft.header": {
"message": "Borrador"
},
"project.moderation.admonition.draft.submit-for-review": {
"message": "Una vez que hayas completado todos los pasos necesarios y te hayas asegurado de que tu proyecto cumple con las <rules-link>Reglas de contenido</rules-link> de Modrinth, puedes enviar tu proyecto a revisión."
},
"project.moderation.admonition.rejected.address-all-concerns": {
"message": "Por favor resuelve todas las observaciones de moderación, incluyendo cualquiera listada abajo, antes de enviar de nuevo el proyecto."
},
"project.moderation.admonition.rejected.header": {
"message": "Cambios solicitados"
},
"project.moderation.admonition.rejected.spam-notice": {
"message": "Enviar en repetidas ocasiones tu proyecto sin atender antes todas las observaciones de moderación puede resultar en la suspensión de la cuenta."
},
"project.moderation.admonition.under-review.body.1": {
"message": "Tu proyecto está en lista de espera para ser revisado por el equipo de moderación de Modrinth."
},
"project.moderation.admonition.under-review.body.2": {
"message": "Tu proyecto será escaneado y después revisado por moderadores humanos para asegurarnos de que esté de acuerdo con las <rules-link>Reglas de contenido</rules-link> y los <terms-link>Términos de uso</terms-link> de Modrinth."
},
"project.moderation.admonition.under-review.body.3": {
"message": "Aún puedes modificar tu proyecto, no afectará tu posición en la cola."
},
"project.moderation.admonition.under-review.body.4": {
"message": "Buscamos revisar envíos en un plazo de 24-48 horas, pero algunos proyectos pueden sufrir retrasos. Esto no indica ningún problema con tu envío."
},
"project.moderation.admonition.under-review.body.5": {
"message": "<emphasis>¡Apreciamos tu paciencia mientras nuestros moderadores trabajan duro para mantener Modrinth seguro y estaremos encantados de poder ayudarte a compartir tu contenido! 💚</emphasis>"
},
"project.moderation.admonition.under-review.header": {
"message": "Proyecto bajo revisión"
},
"project.moderation.admonition.withheld.body": {
"message": "Tu proyecto no aparecerá públicamente y solo se podrá acceder a él por un enlace directo.{requestedStatus, select,unlisted { Según tu <visibility-settings-link>configuración de visibilidad</visibility-settings-link>, es muy probable que no se necesite ninguna acción adicional.} other { Por favor resuelve todas las observaciones de moderación, incluyendo las listadas abajo, antes de enviar de nuevo el proyecto.}}"
},
"project.moderation.admonition.withheld.header": {
"message": "Deslistado por el staff"
},
"project.moderation.error.unauthorized": {
"message": "Sin autorización"
},
"project.moderation.thread.approved-warning": {
"message": "Este hilo no esta siendo monitorizado de manera activa, pero puede ser revisado para más información sobre tu proyecto de ser necesario."
},
"project.moderation.thread.help-center-note.1": {
"message": "Los moderadores de contenido no pueden dar soporte a la mayoría de los problemas y los mensajes de este hilo no notifican al staff."
},
"project.moderation.thread.help-center-note.2": {
"message": "Si necesitas ayuda o tienes consultas adicionales, por favor visita el <help-center-link>Centro de ayuda de Modrinth</help-center-link> y haz click en la burbuja azúl para contactar con soporte."
},
"project.moderation.thread.moderator-see-user-ui-toggle": {
"message": "Mostrar vista de miembro"
},
"project.moderation.thread.private-description": {
"message": "Este es un hilo de conversación con los moderadores de Modrinth. Podrían enviarte un mensaje con observaciones relacionadas a este proyecto."
},
"project.moderation.thread.title": {
"message": "Mensajes de moredación"
},
@@ -2816,24 +2909,12 @@
"report.already-reported": {
"message": "Ya has reportado {title}"
},
"report.already-reported-description": {
"message": "Ya tienes un reporte abierto para {item, select, project {este proyecto} version {esta versión} user {este usuario} other {este contenido}}. Puedes añadir más detalles a tu reporte si tienes más información que agregar."
},
"report.back-to-item": {
"message": "Volver {item, select, project {al proyecto} version {a la versión} user {al usuario} other {al contenido}}"
},
"report.body.description": {
"message": "Incluye enlaces e imágenes si es posible y relevante. Los reportes vacíos o insuficientes serán cerrados e ignorados."
},
"report.body.title": {
"message": "Por favor, proporciona contexto adicional acerca de tu reporte"
},
"report.checking": {
"message": "Revisando {item, select, project {proyecto} version {version} user {usuario} other {contenido}}..."
},
"report.could-not-find": {
"message": "No se pudo encontrar {item, select, project {el proyecto} version {la version} user {el usuario} other {el contenido}}"
},
"report.for.violation": {
"message": "Infracción de las <rules-link>Reglas</rules-link> o <terms-link>Términos de Uso</terms-link> de Modrinth"
},
@@ -2873,15 +2954,9 @@
"report.please-report": {
"message": "Por favor, informa:"
},
"report.question.content-id": {
"message": "¿Cual es la ID de {item, select, project {el proyecto} version {la versión} user {el usuario} other {el contenido}}?"
},
"report.question.content-type": {
"message": "¿Qué tipo de contenido estás reportando?"
},
"report.question.report-reason": {
"message": "¿Que regla de Mondrinth esta quebrantando {item, select, project {el proyecto} version {la versión} user {el usuario} other {el contenido}}?"
},
"report.report-content": {
"message": "Reportar contenido a moderadores"
},
@@ -3560,21 +3635,12 @@
"settings.billing.interval.month": {
"message": "mes"
},
"settings.billing.interval.monthly": {
"message": "mensual"
},
"settings.billing.interval.quarter": {
"message": "trimestre"
},
"settings.billing.interval.quarterly.adjective": {
"message": "trimestralmente"
},
"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 en la Modrinth App"
},
@@ -3659,9 +3725,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} CPUs compartidas (Picos de hasta {bursts} CPUs)"
},
@@ -3684,7 +3747,7 @@
"message": "Error al renovar la suscripción"
},
"settings.billing.pyro.resubscribe.request-submitted.text": {
"message": "Si el servidor se encuentra cancelado, puede tomar 10-15 minutos en preparar el servidor"
"message": "Si el servidor se encuentra cancelado, puede tomar de 10 a 15 minutos en preparar el servidor."
},
"settings.billing.pyro.resubscribe.request-submitted.title": {
"message": "Solicitud de renovación de suscripción enviada"
@@ -3728,18 +3791,9 @@
"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 costará {amount} adicionales por año"
},
"settings.billing.switches-to-billing-on": {
"message": "Se cambia a facturación {interval} el {date}"
},
"settings.billing.update-method": {
"message": "Actualizar método"
},
@@ -860,9 +860,6 @@
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Tarifas más bajas disponibles"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-message": {
"message": "Has seleccionado USD para PayPal Internacional. Te recomendamos que cambies a PayPal directo <direct-paypal-link> para obtener mejores tarifas (≈2% en lugar de ≈6%)."
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Retirada"
},
@@ -920,9 +917,6 @@
"dashboard.projects.links.button.edit": {
"message": "Editar links"
},
"dashboard.projects.links.changes-applied": {
"message": "Cambios seran a aplicados a {count} {count, plural,one {proyecto} other {proyectos}}."
},
"dashboard.projects.links.description": {
"message": "Los enlaces que especifique a continuación se sobrescribirán en cada uno de los proyectos seleccionados. Los que deje en blanco se ignorarán. Puede eliminar un enlace de todos los proyectos seleccionados mediante el botón de la papelera."
},
@@ -1367,9 +1361,6 @@
"hosting-marketing.faq.location": {
"message": "¿Dónde están localizados los servidores de Modrinth Hosting? ¿Puedo elegir la región?"
},
"hosting-marketing.faq.location.answer": {
"message": "Tenemos servidores disponibles en América del Norte, Europa y Sureste de Asia por el momento, que puedes elegir al momento de comprarlo. ¡Más regiones estarán disponibles en el futuro! Si te gustaría cambiar tu región por favor contáctate con soporte."
},
"hosting-marketing.faq.versions-loaders": {
"message": "¿Que versiones de Minecraft y loaders se pueden usar?"
},
@@ -2609,24 +2600,12 @@
"report.already-reported": {
"message": "Ya has reportado {title}"
},
"report.already-reported-description": {
"message": "Ya tienes un reporte abierto para este {item, select, project {project} version {version} user {user} other {content}}. Puedes añadir más detalles a tu reporte si tienes más información que agregar."
},
"report.back-to-item": {
"message": "Volver a {item, select, project {project} version {version} user {user} other {content}}"
},
"report.body.description": {
"message": "Incluya enlaces e imágenes si es posible y relevante. Los informes vacíos o insuficientes serán cerrados e ignorados."
},
"report.body.title": {
"message": "Por favor, proporcione más información sobre su informe"
},
"report.checking": {
"message": "Revisando {item, select, project {el proyecto} version {la version} user {el usuario} other {el contenido}}..."
},
"report.could-not-find": {
"message": "No se pudo encontrar {item, select, project {el proyecto} version {la version} user {el usuario} other {el contenido}}"
},
"report.for.violation": {
"message": "Violación de las <rules-link>Normas</rules-link> o los <terms-link>Términos de uso</terms-link> de Modrinth"
},
@@ -2666,15 +2645,9 @@
"report.please-report": {
"message": "Por favor, informe:"
},
"report.question.content-id": {
"message": "¿Cual es la ID de {item, select, project {el proyecto} version {la versión} user {el usuario} other {el contenido}}?"
},
"report.question.content-type": {
"message": "¿Qué tipo de contenido estás denunciando?"
},
"report.question.report-reason": {
"message": "¿Que regla de Mondrinth esta quebrantando {item, select, project {el proyecto} version {la versión} user {el usuario} other {el contenido}}?"
},
"report.report-content": {
"message": "Denunciar contenido a los moderadores"
},
@@ -3350,21 +3323,12 @@
"settings.billing.interval.month": {
"message": "mes"
},
"settings.billing.interval.monthly": {
"message": "mensual"
},
"settings.billing.interval.quarter": {
"message": "trimestre"
},
"settings.billing.interval.quarterly.adjective": {
"message": "trimestral"
},
"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"
},
@@ -3449,9 +3413,6 @@
"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)"
},
@@ -3518,18 +3479,9 @@
"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"
},
@@ -3719,9 +3671,6 @@
"settings.sessions.description": {
"message": "Aquí están todos los dispositivos que están actualmente conectados con tu cuenta Modrinth. Puedes cerrar sesión en cada uno de ellos individualmente.\n\nSi ves una entrada que no reconoces, cierra sesión en ese dispositivo y cambia la contraseña de tu cuenta Modrinth inmediatamente."
},
"settings.sessions.last-accessed-ago": {
"message": "Último Acceso"
},
"settings.sessions.unknown-os": {
"message": "Sistema operativo desconocido"
},
+336 -3
View File
@@ -191,9 +191,21 @@
"app-marketing.hero.download-modrinth-app-for-os": {
"message": "Lataa Modrinth App alustalle {os}"
},
"app-marketing.hero.minecraft-screenshot-alt": {
"message": "Kuvakaappaus Cobblemon instanssin pää valikko näytöstä."
},
"app-marketing.hero.more-download-options": {
"message": "Lisää lataus vaihtoehtoja"
},
"app-marketing.hide-other-packages": {
"message": "Piilota muut paketit"
},
"app-marketing.not-recommended": {
"message": "Emme suosittele että käytät näitä ellet tiedä mitä teet."
},
"app-marketing.show-other-packages": {
"message": "Näytä muut paketit"
},
"auth.authorize.action.authorize": {
"message": "Valtuuta"
},
@@ -254,9 +266,6 @@
"auth.sign-in.2fa.placeholder": {
"message": "Anna koodi..."
},
"auth.sign-in.additional-options": {
"message": "<forgot-password-Link> Unohditko salasanasi? </forgot-password-Link> • <create-account-link>Luo tili</create-account-link>"
},
"auth.sign-in.sign-in-with": {
"message": "Kirjaudu sisään käyttäen"
},
@@ -335,36 +344,171 @@
"collection.button.edit-icon": {
"message": "Muokkaa kuvaketta"
},
"collection.button.remove-icon": {
"message": "Poista kuvake"
},
"collection.button.remove-project": {
"message": "Poista projekti"
},
"collection.button.replace-icon": {
"message": "Korvaa kuvake"
},
"collection.button.select-icon": {
"message": "Valitse kuvake"
},
"collection.button.unfollow-project": {
"message": "Lopeta projektin seuraaminen"
},
"collection.delete-modal.description": {
"message": "Tämä poistaa pysyvästi tämän kokoelman. Tätä toimea ei voida peruuttaa."
},
"collection.delete-modal.title": {
"message": "Oletko varma että haluat poistaa tämän kokoelman?"
},
"collection.editing": {
"message": "Muokataan kokoelmaa"
},
"collection.error.not-found": {
"message": "Kokoelmaa ei löydy"
},
"collection.label.created-at": {
"message": "Luotu {ago}"
},
"collection.label.curated-by": {
"message": "Kuratoinut"
},
"collection.label.no-projects": {
"message": "Ei vielä projekteja kokelmassa"
},
"collection.label.projects-count": {
"message": "{count, plural, =0 {No projects yet} other {<stat>{count}</stat> {type}}}"
},
"collection.label.updated-at": {
"message": "Päivitetty {ago}"
},
"collection.return-link.dashboard-collections": {
"message": "Kokoelmasi"
},
"collection.return-link.user": {
"message": "{user}:n profiili"
},
"collection.title": {
"message": "{name} - kokoelma"
},
"conversation-thread.action.add-private-note": {
"message": "Lisää yksityinen muistiinpano"
},
"conversation-thread.action.approve": {
"message": "Hyväksy"
},
"conversation-thread.action.approve-with-reply": {
"message": "Hyväksy vastauksella"
},
"conversation-thread.action.close-thread": {
"message": "Sulje keskustelu"
},
"conversation-thread.action.close-with-reply": {
"message": "Sulje vastauksella"
},
"conversation-thread.action.reject": {
"message": "Hylkää"
},
"conversation-thread.action.reject-with-reply": {
"message": "Hylkää vastauksella"
},
"conversation-thread.action.reopen-thread": {
"message": "Avaa keskustelu uudelleen"
},
"conversation-thread.action.reply": {
"message": "Vastaa"
},
"conversation-thread.action.reply-to-thread": {
"message": "Vastaa keskusteluun"
},
"conversation-thread.action.resubmit-for-review": {
"message": "Lähetä uudelleen arvioitavaksi"
},
"conversation-thread.action.resubmit-for-review-with-reply": {
"message": "Lähetä uudelleen arvioitavaksi vastauksella"
},
"conversation-thread.action.send": {
"message": "Lähetä"
},
"conversation-thread.action.send-to-review": {
"message": "Lähetä arvioitavaksi"
},
"conversation-thread.action.send-to-review-with-reply": {
"message": "Lähetä arvioitavaksi vastauksella"
},
"conversation-thread.reply-editor.placeholder.reply": {
"message": "Vastaa keskusteluun..."
},
"conversation-thread.reply-editor.placeholder.send": {
"message": "Lähetä viesti..."
},
"conversation-thread.reply-modal.header": {
"message": "Vastaa keskusteluun"
},
"create.collection.collection-info": {
"message": "Sinun uusi kokoelma luodaan julkiseksi kokoelmaksi {count, plural, =0 {no projects} one {# project} other {# projects}}:lla. "
},
"create.collection.create-collection": {
"message": "Luo kokoelma"
},
"create.collection.name-label": {
"message": "Nimi"
},
"create.collection.name-placeholder": {
"message": "Syötä kokoelman nimi..."
},
"create.collection.summary-label": {
"message": "Yhteenveto"
},
"create.collection.title": {
"message": "Luodaan kokoelmaa"
},
"create.limit-alert.contact-support": {
"message": "Ota yhteyttä tukeen"
},
"create.limit-alert.type-collection": {
"message": "kokoelma"
},
"create.limit-alert.type-organization": {
"message": "organisaatio"
},
"create.limit-alert.type-plural-collection": {
"message": "kokoelmat"
},
"create.limit-alert.type-plural-organization": {
"message": "organisaatiot"
},
"create.limit-alert.type-plural-project": {
"message": "projektit"
},
"create.limit-alert.type-project": {
"message": "projekti"
},
"create.organization.create-organization": {
"message": "Luo organisaatio"
},
"create.organization.name-label": {
"message": "Nimi"
},
"create.organization.name-placeholder": {
"message": "Syötä organisaation nimi..."
},
"create.organization.summary-label": {
"message": "Yhteenveto"
},
"create.project.visibility-private": {
"message": "Yksityinen"
},
"create.project.visibility-public": {
"message": "Julkinen"
},
"create.project.visibility-unlisted": {
"message": "Piilotettu"
},
"dashboard.collections.button.create-new": {
"message": "Luo uusi"
},
@@ -374,18 +518,165 @@
"dashboard.collections.long-title": {
"message": "Kokoelmasi"
},
"dashboard.collections.sort.name-ascending": {
"message": "Nimi (A-Z)"
},
"dashboard.collections.sort.recently-created": {
"message": "Äskettäin luotu"
},
"dashboard.collections.sort.recently-updated": {
"message": "Äskettäin päivitetty"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Lataa {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Kaikki valmista! 🎉"
},
"dashboard.creator-tax-form-modal.entity.private-individual": {
"message": "Yksityishenkilö"
},
"dashboard.creator-tax-form-modal.header": {
"message": "Vero lomake"
},
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Oletko Yhdysvaltain kansalainen?"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Lisätiedot"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Määrä"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Yksityishenkilö"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Vahvista lompakkosi osoite"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Maksutapa"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "PayPal-tili"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "Vavhistamaton sähköposti"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Matalammat maksut saatavilla"
},
"dashboard.head-title": {
"message": "Hallintapaneeli"
},
"dashboard.notifications.empty.no-unread": {
"message": "Sinulla ei ole lukemattomia ilmoituksia."
},
"dashboard.notifications.link.see-all": {
"message": "Näytä kaikki"
},
"dashboard.notifications.link.view-history": {
"message": "Näytä ilmoitushistoria"
},
"dashboard.organizations.button.create": {
"message": "Luo organisaatio"
},
"dashboard.organizations.empty.cta": {
"message": "Tee organisaatio!"
},
"dashboard.organizations.error.fetch": {
"message": "Organisaatioiden haku epäonnistui"
},
"dashboard.organizations.member-count": {
"message": "{count} {count, plural, one {jäsen} other {jäsentä}}"
},
"dashboard.projects.head-title": {
"message": "Projektit"
},
"dashboard.projects.links.and-more": {
"message": "ja {count} lisää..."
},
"dashboard.projects.links.button.clear-link": {
"message": "Tyhjennä linkki"
},
"dashboard.projects.links.button.edit": {
"message": "Muokkaa linkkejä"
},
"dashboard.projects.links.discord-invite.description": {
"message": "Kutsulinkki sinun Discord-palvelimellesi."
},
"dashboard.projects.links.discord-invite.label": {
"message": "Discord-kutsu"
},
"dashboard.projects.links.placeholder.cleared": {
"message": "Olemassa oleva linkki tyhjennetään"
},
"dashboard.projects.links.placeholder.valid-discord-url": {
"message": "Syötä kelvollinen Discord-kutsu URL"
},
"dashboard.projects.links.placeholder.valid-url": {
"message": "Syötä kelvollinen URL"
},
"dashboard.projects.links.show-all-projects": {
"message": "Näytä kaikki projektit"
},
"dashboard.projects.links.source-code.label": {
"message": "Lähdekoodi"
},
"dashboard.projects.links.wiki-page.label": {
"message": "Wikisivu"
},
"dashboard.projects.project.icon-alt": {
"message": "Kuvake projektille {title}"
},
"dashboard.projects.sort.ascending": {
"message": "Nouseva"
},
"dashboard.projects.sort.descending": {
"message": "Laskeva"
},
"dashboard.projects.sort.option.name": {
"message": "Nimi"
},
"dashboard.projects.sort.option.status": {
"message": "Tila"
},
"dashboard.projects.sort.option.type": {
"message": "Tyyppi"
},
"dashboard.projects.table.icon": {
"message": "Kuvake"
},
"dashboard.projects.table.id": {
"message": "ID"
},
"dashboard.projects.table.name": {
"message": "Nimi"
},
"dashboard.projects.table.status": {
"message": "Tila"
},
"dashboard.projects.table.type": {
"message": "Tyyppi"
},
"dashboard.report.title": {
"message": "Raportti {id}"
},
"dashboard.reports.active-title": {
"message": "Aktiiviset raportit"
},
"dashboard.reports.title": {
"message": "Raportit"
},
"dashboard.revenue.available-now": {
"message": "Saatavilla nyt"
},
"dashboard.revenue.processing": {
"message": "Prosessoidaan"
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Lataa CSV-tiedostona"
},
"error.collection.404.list_item.1": {
"message": "Saatoit kirjoittaa kokoelman URL osoitteen väärin."
},
@@ -419,12 +710,51 @@
"error.project.404.list_title": {
"message": "Miksi?"
},
"error.project.404.title": {
"message": "Projektia ei löytynyt"
},
"error.user.404.list_title": {
"message": "Miksi?"
},
"error.user.404.title": {
"message": "Käyttäjää ei löytynyt"
},
"frog": {
"message": "Löysit sammakon! 🐸"
},
"frog.title": {
"message": "Sammakko"
},
"hosting-marketing.included.backups-included": {
"message": "Varmuuskopiot sisällyttäen"
},
"hosting-marketing.included.file-manager": {
"message": "Helppokäyttöinen tiedostoselain"
},
"hosting-marketing.included.file-manager.description": {
"message": "Etsi, hallinnoi, muokkaa ja lataa tiedostoja suoraan palvelimellesi helposti."
},
"hosting-marketing.included.help": {
"message": "Apua kun sitä tarvitset"
},
"hosting-marketing.included.help.description": {
"message": "Ota yhteyttä Modrinthin tiimiin milloin tahansa palvelinasioissa."
},
"hosting-marketing.included.sftp-access": {
"message": "SFTP pääsy"
},
"hosting-marketing.know-what-you-need": {
"message": "Tiedät jo mitä tarvitset?"
},
"hosting-marketing.medal.info": {
"message": "Kokeile ilmaista <orange>3Gt palvelinta</orange> 5 päivän ajan, jonka tarjoaa <orange>Medal</orange>"
},
"hosting-marketing.medal.learn-more": {
"message": "Lue lisää"
},
"hosting.plan.out-of-stock": {
"message": "Loppuunmyyty"
},
"landing.button.discover-mods": {
"message": "Löydä modeja"
},
@@ -512,6 +842,9 @@
"layout.action.new-project": {
"message": "Uusi projekti"
},
"layout.action.publish": {
"message": "Julkaise"
},
"layout.avatar.alt": {
"message": "Avatarisi"
},
@@ -881,9 +881,6 @@
"dashboard.notifications.link.view-history": {
"message": "Tingnan ang kasaysayan ng notipikasyon"
},
"dashboard.notifications.link.view-more": {
"message": "Tingnan ang {extraNotifs} pang {extraNotifs, plural, other {notipikasyon}}"
},
"dashboard.organizations.button.create": {
"message": "Lumikha ng organisasyon"
},
@@ -1235,9 +1232,6 @@
"hosting-marketing.faq.location": {
"message": "Nasaan ang mga server ng Modrinth Hosting? Makapipili ba ako ng rehiyon?"
},
"hosting-marketing.faq.location.answer": {
"message": "Mayroon kaming mga server na magagamit sa Hilagang Amerika, Yuropa, at Timog-silangang Asya sa kasalukuyang sandali na maaari mong piliin pagkatapos bumili. Dadating ang higit pang rehiyon sa hinaharap! Kung nais mong magpalit ng rehiyon, mangyaring abutin ang suporta."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Ano bang bersiyon ng Minecraft at loader ang magagamit?"
},
@@ -2483,24 +2477,12 @@
"report.already-reported": {
"message": "Nasumbong mo na ang {title}"
},
"report.already-reported-description": {
"message": "Ikaw ay mayroon nang bukas na sumbong para sa {item, select, project {proyektong} version {bersiyong} user {tagagamit na} other {kontentong}} ito. Ikaw ay maaaring magdagdag ng detalye sa iyong sumbong kapag mayroong impormasyong kang maisasama pa."
},
"report.back-to-item": {
"message": "Bumalik sa {item, select, project {proyekto} version {bersiyon} user {tagagamit} other {kontento}}"
},
"report.body.description": {
"message": "Maglagay ng mga link at imahe kung makakaya at matumpak. Ang mga sumbong na kumulang o walang laman ay agarang sininasara at binabalewala."
},
"report.body.title": {
"message": "Mangyaring magbigay ng karagdagang konteksto ukol sa iyong sumbong"
},
"report.checking": {
"message": "Tinitignan ang {item, select, project {proyekto} version {bersiyon} user {tagagamit} other {kontento}}..."
},
"report.could-not-find": {
"message": "Hindi mahanap ang {item, select, project {proyekto} version {bersiyon} user {tagagamit} other {kontento}}"
},
"report.for.violation": {
"message": "Paglabag sa <rules-link>Mga Patakaran</rules-link> o <terms-link>Mga Tuntunin sa Paggamit</terms-link> ng Modrinth"
},
@@ -2540,15 +2522,9 @@
"report.please-report": {
"message": "Pakisumbong:"
},
"report.question.content-id": {
"message": "Ano ang ID ng {item, select, project {proyekto} version {bersiyon} user {tagagamit} other {kontento}}?"
},
"report.question.content-type": {
"message": "Anong uri ng kontento ang iyong isusumbong?"
},
"report.question.report-reason": {
"message": "Aling sa mga tuntunin ng Modrinth ang nilabag ng {item, select, project {proyektong} version {bersiyong} user {tagagamit na} other {kontentong}} ito?"
},
"report.report-content": {
"message": "Isumbong ang kontento sa mga moderator"
},
@@ -3035,21 +3011,12 @@
"settings.billing.interval.month": {
"message": "buwan"
},
"settings.billing.interval.monthly": {
"message": "buwanan"
},
"settings.billing.interval.quarter": {
"message": "tatlong buwan"
},
"settings.billing.interval.quarterly.adjective": {
"message": "taluhang-buwan"
},
"settings.billing.interval.year": {
"message": "taon"
},
"settings.billing.interval.yearly": {
"message": "taunan"
},
"settings.billing.midas.benefits.title": {
"message": "Mga pakinabang"
},
@@ -3095,9 +3062,6 @@
"settings.billing.payment_method.title": {
"message": "Mga paraan ng pagbabayad"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.resubscribe.error.text": {
"message": "Isang error ang naganap habang pagre-resubscribe sa iyong Modrinth server."
},
+7 -58
View File
@@ -105,7 +105,7 @@
"message": "Moniteur d'activité"
},
"app-marketing.features.performance.cpu-percent": {
"message": "Pourcentage du processeur"
"message": "% Processeur"
},
"app-marketing.features.performance.description": {
"message": "Modrinth App est plus performante que la plupart des autres gestionnaires de mods, tout en n'utilisant que 150 Mo de mémoire vive !"
@@ -126,7 +126,7 @@
"message": "∞ * ∞ Mo"
},
"app-marketing.features.performance.less-than-150mb": {
"message": "moins de 150 Mo"
"message": "< 150 Mo"
},
"app-marketing.features.performance.modrinth-app": {
"message": "Modrinth App"
@@ -165,7 +165,7 @@
"message": "Partagez des modpacks"
},
"app-marketing.features.unlike-any-launcher": {
"message": "Un launcher comme"
"message": "Contrairement à tous les autres launchers"
},
"app-marketing.features.website.description": {
"message": "Modrinth App est entièrement intégrée au site Web, vous pouvez donc accéder à tous vos projets préférés depuis l'application !"
@@ -174,7 +174,7 @@
"message": "Intégration au site Web"
},
"app-marketing.features.youve-used-before": {
"message": "vous n'en avez jamais vu"
"message": "vous avez utilisé avant"
},
"app-marketing.hero.app-screenshot-alt": {
"message": "Capture d'écran de Modrinth App avec une instance Cobblemon ouverte sur la page « Contenu »."
@@ -1014,7 +1014,7 @@
"message": "Organisations"
},
"dashboard.overview.notifications.button.mark-all-as-read": {
"message": "Mettre tout comme étant lu."
"message": "Marquer tout comme lu"
},
"dashboard.overview.notifications.button.view-history": {
"message": "Voire l'historique"
@@ -1361,15 +1361,6 @@
"discover.install.heading.reset-modpack": {
"message": "Sélectionner un modpack à insaller après la réinitialisation"
},
"discover.seo.description": {
"message": "Recherchez et parcourez des milliers de {projectType, select, mod {mods} modpack {modpacks} resourcepack {packs de ressources} shader {shaders} plugin {plugins} datapack {packs de données} other {projets}} Minecraft sur Modrinth avec des résultars fidèles et rapides. Nos filtres vous aident à trouver les meilleurs {projectType, select, mod {mods} modpack {modpacks} resourcepack {packs de ressources} shader {shaders} plugin {plugins} datapack {packs de données} other {projets}}."
},
"discover.seo.title": {
"message": "Rechercher des {projectType, select, mod {mods} modpack {modpacks} resourcepack {packs de ressources} shader {shaders} plugin {plugins} datapack {packs de données} other {projets}}"
},
"discover.seo.title-with-query": {
"message": "Search {projectType, select, mod {mods} modpack {modpacks} resourcepack {packs de ressources} shader {shaders} plugin {plugins} datapack {packs de données} other {projets}} | {query}"
},
"error.collection.404.list_item.1": {
"message": "Vous avez peut-être mal tapé l'URL de la collection."
},
@@ -1536,7 +1527,7 @@
"message": "Où se trouvent les serveurs de Modrinth Hosting ? Puis-je choisir une région ?"
},
"hosting-marketing.faq.location.answer": {
"message": "Nous avons des serveurs disponibles en Amérique du Nord, en Europe et en Asie du Sud-Est en ce moment-même que vous pouvez choisir dès l'achat. Plus de régions à venir dans le futur ! Si vous souhaitez changer de région, veuillez contacter le support."
"message": "Nous avons des serveurs disponibles en Amérique du Nord, en Europe et en Asie du Sud-Est pour le moment que vous pouvez choisir lors de l'achat. Plus de régions sont à venir ! Si vous voulez changer de région, contactez le support."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Quelles versions de Minecraft et loaders peuvent-être utilisés ?"
@@ -1881,7 +1872,7 @@
"message": "Erreur lors de la génération de l’état à partir de lAPI pendant la construction."
},
"layout.banner.preview.description": {
"message": "Si vous voulez accéder au site officiel de Modrinth, visitez {url}. Cet aperçu\nde déploiement est utilisée par le staff de Modrinth pour des raisons d'essai.\nIl a été construit en utilisant <branch-link>{owner}/{branch}</branch-link> @ {commit}."
"message": "Si vous souhaitez accéder au site web officiel de Modrinth, rendez-vous sûr {url}. Cette version anticipée est utilisée par l'équipe de Modrinth à des fins de test. Elle a été créée avec {ref}."
},
"layout.banner.preview.title": {
"message": "Ceci est un déploiement de prévisualisation du site Modrinth."
@@ -2468,9 +2459,6 @@
"project-member-header.invitation-title": {
"message": "Invitation à rejoindre un projet"
},
"project-member-header.invitation-with-role": {
"message": "Vous avez été invité à être membre de ce projet sous le rôle de '{role}''."
},
"project-member-header.success-decline": {
"message": "Vous avez refusé linvitation à rejoindre l’équipe."
},
@@ -2921,24 +2909,12 @@
"report.already-reported": {
"message": "Vous avez déjà signalé {title}"
},
"report.already-reported-description": {
"message": "Vous avez déjà un rapport ouvert pour {item, select, project {ce projet} version {cette version} user {cet utilisateur} other {ce contenu}}. Vous pouvez ajouter plus de détails à votre rapport si vous avez plus d'information à ajouter."
},
"report.back-to-item": {
"message": "Retour vers {item, select, project {le projet} version {la version} user {l'utilisateur} other {le contenu}}"
},
"report.body.description": {
"message": "Incluez des liens et des images si possible et pertinentes. Les signalements vides ou insuffisants seront fermés et ignorés."
},
"report.body.title": {
"message": "Veuillez fournir des informations supplémentaires concernant votre signalement."
},
"report.checking": {
"message": "Vérification {item, select, project {du projet} version {de la version} user {de l'utilisateur} other {du contenu}}..."
},
"report.could-not-find": {
"message": "Impossible de trouver {item, select, project {la projet} version {la version} user {l'utilisateur} other {le contenu}}"
},
"report.for.violation": {
"message": "Violation des <rules-link>Règles</rules-link> ou des <terms-link>Conditions dutilisation</terms-link> de Modrinth"
},
@@ -2978,15 +2954,9 @@
"report.please-report": {
"message": "Veuillez signaler:"
},
"report.question.content-id": {
"message": "Quel est l'ID {item, select, project {du projet} version {de la version} user {de l'utilisateur} other {du contenu}} ?"
},
"report.question.content-type": {
"message": "Quel type de contenu signalez-vous?"
},
"report.question.report-reason": {
"message": "Quelle règle de Modrinth {item, select, project {ce projet enfreint-il} version {cette version enfreint-elle} user {cet utilisateur enfreint-il} other {ce contenu enfreint-il}} ?"
},
"report.report-content": {
"message": "Signaler le contenu aux modérateurs"
},
@@ -3665,21 +3635,12 @@
"settings.billing.interval.month": {
"message": "mois"
},
"settings.billing.interval.monthly": {
"message": "mensuel"
},
"settings.billing.interval.quarter": {
"message": "trimestre"
},
"settings.billing.interval.quarterly.adjective": {
"message": "trimestriel"
},
"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"
},
@@ -3764,9 +3725,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} processeurs partagés (pics jusqu’à {bursts} processeurs)"
},
@@ -3833,18 +3791,9 @@
"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"
},
@@ -1034,9 +1034,6 @@
"error.generic.default.list_item.1": {
"message": "בדוק אם Modrinth אינו זמין ב<status-link>דף הסטטוס</status-link> שלנו."
},
"error.generic.default.list_item.2": {
"message": "אם זה ממשיך לקרות, אנא ידע/י את צוות Modrinth דרך <discord-server>שרת הדיסקורד</discord-link>."
},
"error.generic.default.list_title": {
"message": "נסו שוב בעוד מספר דקות."
},
@@ -1163,9 +1160,6 @@
"hosting-marketing.faq.location": {
"message": "היכן ממוקמים שרתי האחסון של Modrinth? האם ניתן לבחור אזור?"
},
"hosting-marketing.faq.location.answer": {
"message": "כרגע זמינים עבורכם שרתים בצפון אמריקה, אירופה ודרום-מזרח אסיה, אותם ניתן לבחור בעמד הרכישה. אזורים נוספים יתווספו בעתיד! אם תרצו להחליף את האזור שלכם, אנא צרו קשר עם התמיכה."
},
"hosting-marketing.faq.versions-loaders": {
"message": "באילו גרסאות של מיינקראפט ובאילו Loaders ניתן להשתמש?"
},
@@ -2246,24 +2240,12 @@
"report.already-reported": {
"message": "כבר דיווחת {title}"
},
"report.already-reported-description": {
"message": "כבר קיים דיווח פתוח עבור ה{item, select, project {פרויקט} version {גרסה} user {משתמש} other {תוכן}} הזה. אפשר להוסיף פרטים נוספים לדיווח אם יש לך מידע נוסף לשתף."
},
"report.back-to-item": {
"message": "חזרה ל{item, select, project {פרויקט} version {גרסה} user {משתמש} other {תוכן}}"
},
"report.body.description": {
"message": "מומלץ להוסיף קישורים ותמונות אם הם רלוונטיים. דיווחים ריקים או חסרים ייסגרו ללא טיפול."
},
"report.body.title": {
"message": "נשמח לקבל פרטים נוספים על הדיווח שלך"
},
"report.checking": {
"message": "בודק את ה{item, select, project {פרויקט} version {גרסה} user {משתמש} other {תוכן}}..."
},
"report.could-not-find": {
"message": "לא נמצא {item, select, project {פרויקט} version {גרסה} user {משתמש} other {תוכן}}"
},
"report.for.violation": {
"message": "הפרה של <rules-link>חוקי Modrinth</rules-link> או <terms-link>תנאי השימוש</terms-link>"
},
@@ -2303,15 +2285,9 @@
"report.please-report": {
"message": "נא לדווח על:"
},
"report.question.content-id": {
"message": "מהו ה-ID של ה{item, select, project {פרויקט} version {גרסה} user {משתמש} other {תוכן}}?"
},
"report.question.content-type": {
"message": "מהו סוג התוכן שברצונך לדווח עליו?"
},
"report.question.report-reason": {
"message": "על איזה מחוקי Modrinth עובר ה{item, select, project {פרויקט} version {גרסה} user {משתמש} other {תוכן}} הזה?"
},
"report.report-content": {
"message": "דיווח על תוכן למנהלים"
},
+20 -98
View File
@@ -291,7 +291,7 @@
"message": "Már van fiókod?"
},
"auth.sign-up.subscribe.label": {
"message": "Iratkozzon fel a Modrinth frissítéseiről szóló értesítésekre"
"message": "Feliratkozás a Modrinth híreire és frissítéseire"
},
"auth.sign-up.title": {
"message": "Regisztráció"
@@ -333,7 +333,7 @@
"message": "Email-cím hitelesítése"
},
"auth.welcome.checkbox.subscribe": {
"message": "Iratkozzon fel a Modrinth frissítéseiről szóló értesítésekre"
"message": "Feliratkozás a Modrinth híreire és frissítéseire"
},
"auth.welcome.description": {
"message": "Most már része vagy annak a fantasztikus fejlesztők és felfedezők közösségének, akik már építenek, letöltenek és naprakészek maradnak a csodálatos modokkal kapcsolatban."
@@ -416,6 +416,9 @@
"conversation-thread.action.approve-with-reply": {
"message": "Jóváhagyás és válasz"
},
"conversation-thread.action.close-thread": {
"message": "Gondolatmenet lezárása"
},
"conversation-thread.action.close-with-reply": {
"message": "Bezárás és válasz"
},
@@ -488,9 +491,6 @@
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "A kiegészítő fájlok olyan kiegészítő forrásokhoz tartoznak, mint például a forráskód, nem pedig alternatív verziókhoz vagy változatokhoz."
},
"create.collection.collection-info": {
"message": "Az új gyűjteményed nyilvános gyűjteményként jön létre {count, plural, =0 {projektek nélkül} other {# projekttel}}."
},
"create.collection.create-collection": {
"message": "Gyűjtemény létrehozása"
},
@@ -650,9 +650,6 @@
"dashboard.affiliate-links.search": {
"message": "Társulati linkek keresése..."
},
"dashboard.analytics.from-projects": {
"message": "{count} projektből"
},
"dashboard.analytics.total-downloads": {
"message": "Összes letöltés"
},
@@ -674,9 +671,6 @@
"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} projekt"
},
"dashboard.collections.label.search-input": {
"message": "Keresd meg a gyűjteményeidet"
},
@@ -950,24 +944,21 @@
"dashboard.head-title": {
"message": "Irányítópult"
},
"dashboard.notifications.empty.no-unread": {
"message": "Nincsenek olvasatlan értesítéseid."
},
"dashboard.notifications.link.see-all": {
"message": "Összes megtekintése"
},
"dashboard.notifications.link.view-history": {
"message": "Értesítési előzmények megtekintése"
},
"dashboard.notifications.link.view-more": {
"message": "További {extraNotifs} értesítés megtekintése"
},
"dashboard.organizations.button.create": {
"message": "Szervezet létrehozása"
},
"dashboard.organizations.empty.cta": {
"message": "Hozz létre egy szervezetet!"
},
"dashboard.organizations.member-count": {
"message": "{count} tag"
},
"dashboard.organizations.title": {
"message": "Szervezetek"
},
@@ -1010,9 +1001,6 @@
"dashboard.projects.links.button.edit": {
"message": "Linkek szerkesztése"
},
"dashboard.projects.links.changes-applied": {
"message": "A változtatások <strong>{count}</strong> projektre vonatkoznak."
},
"dashboard.projects.links.discord-invite.description": {
"message": "Meghívólink a Discord szerveredre."
},
@@ -1304,15 +1292,6 @@
"discover.install.error.unsupported-content-type": {
"message": "Ez a tartalomtípus nem telepíthető a szerverre a „” menüpontból."
},
"discover.seo.description": {
"message": "Keress és böngéssz több ezer Minecraft-{projectType, select, mod {mod} modpack {modcsomag} resourcepack {forráscsomag} shader {shader} plugin {bővítmény} datapack {adatcsomag} other {projekt}} között a Modrinthon gyors és pontos keresési találatokkal. Szűrőink segítenek gyorsan megtalálni a legjobb Minecraft-{projectType, select, mod {modokat} modpack {modcsomagokat} resourcepack {forráscsomagokat} shader {shadereket} plugin {bővítményeket} datapack {adatcsomagokat} other {projekteket}}."
},
"discover.seo.title": {
"message": "{projectType, select, mod {Modok} modpack {Modcsomagok} resourcepack {Forráscsomagok} shader {Shaderek} plugin {Bővítmények} datapack {Adatcsomagok} other {Projektek}} keresése"
},
"discover.seo.title-with-query": {
"message": "{projectType, select, mod {Modok} modpack {Modcsomagok} resourcepack {Forráscsomagok} shader {Shaderek} plugin {Bővítmények} datapack {Adatcsomagok} other {Projektek}} keresése | {query}"
},
"error.collection.404.list_item.1": {
"message": "Elírhatad a gyűjtemémyed linkjét."
},
@@ -1478,9 +1457,6 @@
"hosting-marketing.faq.location": {
"message": "Hol találhatók a Modrinth Hosting szerverei? Kiválaszthatom a régiót?"
},
"hosting-marketing.faq.location.answer": {
"message": "Jelenleg Észak-Amerikában, Európában és Délkelet-Ázsiában állnak rendelkezésre szerverek, amelyek közül vásárláskor választhatsz. A jövőben további régiók is elérhetővé válnak! Ha szeretnéd megváltoztatni a régiót, vedd fel a kapcsolatot az ügyfélszolgálattal."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Melyik Minecraft verziók és betöltők használhatók?"
},
@@ -1749,7 +1725,7 @@
"message": "Játékosoknak"
},
"landing.section.for-players.tagline": {
"message": "Fedez fel több mint {count, number} alkotást"
"message": "Fedezz fel több mint {count, number} alkotást"
},
"landing.subheading": {
"message": "Fedezz fel, játssz és ossz meg Minecraft-tartalmakat a közösség számára létrehozott nyílt forráskódú platformunkon."
@@ -1815,7 +1791,7 @@
"message": "Mindig mellőzd"
},
"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}"
"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érlek próbáld meg újra, amikor az API újra elérhetővé válik. Hibakódok: {errors}; Az API jelenlegi linkje: {url}"
},
"layout.banner.build-fail.ignore": {
"message": "Mellőz"
@@ -1823,11 +1799,8 @@
"layout.banner.build-fail.title": {
"message": "Hiba történt az API állapotának generálása közben a fordítás során."
},
"layout.banner.preview.description": {
"message": "Ha a hivatalos Modrinth weboldalt szeretnéd elérni, látogass el a {url} oldalra. Ezt az előzetes verziót a Modrinth munkatársai tesztelési célokra használják. A <branch-link>{owner}/{branch</branch-link> @ {commit} használatával készült."
},
"layout.banner.preview.title": {
"message": "Ez a Modrinth weboldal előzetes telepítése."
"message": "Ez a Modrinth weboldal előzetes verziója."
},
"layout.banner.staging.description": {
"message": "A tesztelési környezet teljesen elkülönül az éles Modrinth adatbázistól. Ezt tesztelési és hibakeresési célokra használják, és a Modrinth backend vagy frontend fejlesztés alatt álló, az éles példánynál újabb verzióit futtathatja."
@@ -2360,9 +2333,6 @@
"profile.label.collection": {
"message": "Gyűjtemény"
},
"profile.label.downloads": {
"message": "{count} letöltés"
},
"profile.label.joined": {
"message": "Csatlakozott"
},
@@ -2381,9 +2351,6 @@
"profile.label.organizations": {
"message": "Szervezetek"
},
"profile.label.projects": {
"message": "{count} projekt"
},
"profile.label.saving": {
"message": "Mentés..."
},
@@ -2393,9 +2360,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Töltsd le {username} projektjeit a Modrinthon"
},
"profile.stats.projects-followers": {
"message": "<stat>{count}</stat> projektkövető"
},
"profile.user-id": {
"message": "Felhasználói azonosító: {id}"
},
@@ -2628,10 +2592,10 @@
"message": "Átdolgoztuk a Modrinth Környezetek rendszerét, és új lehetőségek érhetők el. Kérjük, ellenőrizd, hogy a metaadatok helyesek-e."
},
"project.environment.migration.review-button": {
"message": "Környezet beállítások Átnézése"
"message": "Környezeti beállítások áttekintése"
},
"project.environment.migration.title": {
"message": "Kérjük, tekintse át a környezet metaadatait"
"message": "Kérlek tekintsd át a környezeti metaadatokat"
},
"project.error.loading": {
"message": "Hiba a projektadatok {message} betöltése közben"
@@ -2669,12 +2633,18 @@
"project.moderation.admonition.draft.submit-for-review": {
"message": "Miután elvégezted az összes szükséges lépést, és meggyőződtél arról, hogy a projekted megfelel a Modrinth <rules-link>Tartalmi szabályainak</rules-link>, benyújthatod a projektedet felülvizsgálatra."
},
"project.moderation.admonition.rejected.header": {
"message": "Változtatások kérve lettek"
},
"project.moderation.admonition.under-review.body.5": {
"message": "<emphasis>Köszönjük türelmedet, amíg moderátoraink keményen dolgoznak a Modrinth biztonságának fenntartásán, és alig várjuk, hogy segíthessünk tartalmaid megosztásában! 💚</emphasis>"
},
"project.moderation.admonition.under-review.header": {
"message": "Projekt áttekintés alatt"
},
"project.moderation.thread.title": {
"message": "Moderációs üzenetek"
},
"project.moderation.title": {
"message": "Moderáció"
},
@@ -2747,21 +2717,12 @@
"project.settings.permissions.learn-more": {
"message": "További információ"
},
"project.settings.permissions.search-placeholder": {
"message": "Keresés {count} külső projekt között..."
},
"project.settings.title": {
"message": "Beállítások"
},
"project.settings.visit-dashboard": {
"message": "Projektek irányítópult megnyitása"
},
"project.stats.downloads-label": {
"message": "letöltés"
},
"project.stats.followers-label": {
"message": "követő"
},
"project.status.archived.message": {
"message": "A(z) {title} archiválásra került. A(z) {title} nem kap további frissítéseket, kivéve, ha a fejlesztő úgy dönt, hogy visszavonja a projekt archiválását."
},
@@ -2780,24 +2741,12 @@
"report.already-reported": {
"message": "Már feljelentetted ezt: {title}"
},
"report.already-reported-description": {
"message": "Már létezik egy nyitott jelentésed ehhez a {item, select, project {projekthez} version {verzióhoz} user {felhasználóhoz} other {tartalomhoz}}. További részletekkel egészítheted ki a jelentésed, ha van további információ, amit hozzá szeretnél adni."
},
"report.back-to-item": {
"message": "Vissza a {item, select, project {projekthez} version {verzióhoz} user {felhasználóhoz} other {tartalomhoz}}"
},
"report.body.description": {
"message": "Ha lehetséges és releváns, csatolj linkeket és képeket. Az üres vagy hiányos jelentéseket lezárjuk és figyelmen kívül hagyjuk."
},
"report.body.title": {
"message": "Adj meg további kontextust a jelentéseddel kapcsolatban"
},
"report.checking": {
"message": "{item, select, project {Projekt} version {Verzió} user {Felhasználó} other {Tartalom}} ellenőrzése..."
},
"report.could-not-find": {
"message": "{item, select, project {Projekt} version {Verzió} user {Felhasználó} other {Tartalom}} nem található"
},
"report.for.violation": {
"message": "A Modrinth <rules-link>Szabályzat</rules-link> vagy <terms-link>Felhasználási feltételek</terms-link> megsértése"
},
@@ -2837,15 +2786,9 @@
"report.please-report": {
"message": "Kérjük, az alábbiakat jelentsd:"
},
"report.question.content-id": {
"message": "Mi a {item, select, project {projekt} version {verzió} user {felhasználó} other {tartalom}} azonosítója?"
},
"report.question.content-type": {
"message": "Milyen típusú tartalmat jelentesz?"
},
"report.question.report-reason": {
"message": "A Modrinth melyik szabályát szegi meg ez a {item, select, project {projekt} version {verzió} user {felhasználó} other {tartalom}}?"
},
"report.report-content": {
"message": "Tartalom jelentése a moderátoroknak"
},
@@ -3489,7 +3432,7 @@
"message": "Amikor engedélyezel egy alkalmazást a Modrinth fiókoddal, hozzáférést biztosítasz számára a fiókodhoz. A fiókodhoz való hozzáférést bármikor kezelheted és ellenőrizheted itt."
},
"settings.authorizations.empty-state": {
"message": "Jelenleg nem tudjuk megjeleníteni a jogosult alkalmazásait, dolgozunk a probléma megoldásán. Kérjük, látogassa meg ezt az oldalt később!"
"message": "Jelenleg nem tudjuk megjeleníteni az azonosított alkalmazásokat, dolgozunk a probléma megoldásán. Kérlek látogasd meg ezt az oldalt később!"
},
"settings.authorizations.head-title": {
"message": "Engedélyek"
@@ -3524,21 +3467,12 @@
"settings.billing.interval.month": {
"message": "hónap"
},
"settings.billing.interval.monthly": {
"message": "havi"
},
"settings.billing.interval.quarter": {
"message": "negyedév"
},
"settings.billing.interval.quarterly.adjective": {
"message": "negyedéves"
},
"settings.billing.interval.year": {
"message": "év"
},
"settings.billing.interval.yearly": {
"message": "éves"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Reklámmentes böngészés a modrinth.com-on és a Modrinth App-ban"
},
@@ -3623,9 +3557,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} Megosztott CPU-k (maximum {bursts} CPU-ig terjedő löketek)"
},
@@ -3692,18 +3623,9 @@
"settings.billing.subscription.title": {
"message": "Előfizetések"
},
"settings.billing.switch.switching-to-interval": {
"message": "Váltás {interval} számlázásra"
},
"settings.billing.switch.to-interval": {
"message": "Váltás {interval} számlázásra "
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "A havi számlázás évente további {amount} költséggel jár"
},
"settings.billing.switches-to-billing-on": {
"message": "{interval} számlázásra vált {date} napon"
},
"settings.billing.update-method": {
"message": "Fizetési mód változtatása"
},
@@ -410,9 +410,6 @@
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "Berkas tambahan hanya untuk sumber pendukung seperti kode sumber, bukan untuk versi atau varian lain."
},
"create.collection.collection-info": {
"message": "Koleksi baru Anda akan dibuat sebagai koleksi publik dengan {count, plural, =0 {0 proyek} other {# proyek}}."
},
"create.collection.create-collection": {
"message": "Buat koleksi"
},
@@ -587,9 +584,6 @@
"dashboard.collections.empty.no-match-hint": {
"message": "Coba sesuaikan kata kunci pencarian atau penyaringan Anda."
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, other {proyek}}"
},
"dashboard.collections.label.search-input": {
"message": "Cari koleksi Anda"
},
@@ -1163,9 +1157,6 @@
"hosting-marketing.faq.location": {
"message": "Di mana server Modrinth Hosting terletak? Dapatkah saya memilih wilayah?"
},
"hosting-marketing.faq.location.answer": {
"message": "Server kami tersedia di Amerika Utara, Eropa, dan Asia Tenggara dan Anda dapat memilihnya saat membeli. Wilayah-wilayah lain akan segera hadir di masa mendatang! Bila Anda ingin mengganti wilayah Anda, mohon hubungi dukungan."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Versi dan pemuat Minecraft apa sajakah yang dapat digunakan?"
},
@@ -2027,9 +2018,6 @@
"profile.label.collection": {
"message": "Koleksi"
},
"profile.label.downloads": {
"message": "{count} {countPlural, plural, other {pengunduhan}}"
},
"profile.label.joined": {
"message": "Telah bergabung"
},
@@ -2048,9 +2036,6 @@
"profile.label.organizations": {
"message": "Organisasi"
},
"profile.label.projects": {
"message": "{count} {countPlural, plural, other {proyek}}"
},
"profile.label.saving": {
"message": "Menyimpan..."
},
@@ -2060,9 +2045,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Unduh proyek milik {username} di Modrinth"
},
"profile.stats.projects-followers": {
"message": "{count, plural, other {<stat>{count}</stat> pengikut proyek}}"
},
"profile.user-id": {
"message": "Pengenal Pengguna: {id}"
},
@@ -2390,12 +2372,6 @@
"project.settings.visit-dashboard": {
"message": "Kunjungi dasbor proyek"
},
"project.stats.downloads-label": {
"message": "unduhan{count, plural, other {}}"
},
"project.stats.followers-label": {
"message": "pengikut{count, plural, other {}}"
},
"project.status.archived.message": {
"message": "{title} telah diarsip. {title} tidak akan menerima pembaruan di masa mendatang kecuali pembuat memutuskan untuk membuka arsip proyek ini."
},
@@ -2405,24 +2381,12 @@
"report.already-reported": {
"message": "Anda sudah melaporkan {title}"
},
"report.already-reported-description": {
"message": "Anda memiliki laporan terbuka untuk {item, select, project {proyek} version {versi} user {pengguna} other {konten}} ini. Anda dapat menambah informasi tambahan ke laporan ini bila diperlukan."
},
"report.back-to-item": {
"message": "Kembali ke {item, select, project {proyek} version {versi} user {pengguna} other {konten}}"
},
"report.body.description": {
"message": "Sertakan tautan dan gambar bila memungkinkan dan relevan. Laporan yang kosong atau tidak mencukupi akan ditutup dan diabaikan."
},
"report.body.title": {
"message": "Mohon berikan konteks tambahan tentang laporan Anda"
},
"report.checking": {
"message": "Memeriksa {item, select, project {proyek} version {versi} user {pengguna} other {konten}}..."
},
"report.could-not-find": {
"message": "Tidak dapat menemukan {item, select, project {proyek} version {versi} user {pengguna} other {konten}}"
},
"report.for.violation": {
"message": "Pelanggaran <rules-link>Peraturan</rules-link> Modrinth atau <terms-link>Ketentuan Penggunaan</terms-link>"
},
@@ -2462,15 +2426,9 @@
"report.please-report": {
"message": "Mohon laporkan:"
},
"report.question.content-id": {
"message": "Apa pengenal (ID) dari {item, select, project {proyek} version {versi} user {pengguna} other {konten}} ini?"
},
"report.question.content-type": {
"message": "Konten jenis apa yang ingin Anda laporkan?"
},
"report.question.report-reason": {
"message": "Peraturan Modrinth manakah yang dilanggar oleh {item, select, project {proyek} version {versi} user {pengguna} other {konten}} ini?"
},
"report.report-content": {
"message": "Laporkan konten ke moderator"
},
+1 -76
View File
@@ -686,9 +686,6 @@
"dashboard.affiliate-links.search": {
"message": "Cerca tra i link affiliati..."
},
"dashboard.analytics.from-projects": {
"message": "da {count, plural, one {# progetto} other {# progetti}}"
},
"dashboard.analytics.total-downloads": {
"message": "Download totali"
},
@@ -995,9 +992,6 @@
"dashboard.notifications.link.view-history": {
"message": "Mostra cronologia notifiche"
},
"dashboard.notifications.link.view-more": {
"message": "Mostra {extraNotifs, plural, one {un'altra notifica} other {altre # notifiche}}"
},
"dashboard.organizations.button.create": {
"message": "Crea organizzazione"
},
@@ -1007,9 +1001,6 @@
"dashboard.organizations.error.fetch": {
"message": "Impossibile ottenere le organizzazioni"
},
"dashboard.organizations.member-count": {
"message": "{count, plural, one {# membro} other {# membri}}"
},
"dashboard.organizations.title": {
"message": "Organizzazioni"
},
@@ -1046,9 +1037,6 @@
"dashboard.projects.head-title": {
"message": "Progetti"
},
"dashboard.projects.links.and-more": {
"message": "e {count, plural, one {un altro ancora} other {altri #}}..."
},
"dashboard.projects.links.button.clear-link": {
"message": "Rimuovi link"
},
@@ -1361,15 +1349,6 @@
"discover.install.heading.reset-modpack": {
"message": "Pacchetti da installare dopo il ripristino"
},
"discover.seo.description": {
"message": "Cerca e esplora tra migliaia di {projectType, select, mod {mod} modpack {pacchetti di mod} resourcepack {pacchetti di risorse} shader {shader} plugin {plugin} datapack {pacchetti di dati} other {progetti}} presenti su Modrinth attraverso ricerche rapide e accurate. I nostri filtri ti aiuteranno a trovare quello che fa al caso tuo."
},
"discover.seo.title": {
"message": "Trova {projectType, select, mod {mod} modpack {pacchetti di mod} resourcepack {pacchetti di risorse} shader {shader} plugin {plugin} datapack {pacchetti di dati} other {progetti}}"
},
"discover.seo.title-with-query": {
"message": "Trova {projectType, select, mod {mod} modpack {pacchetti di mod} resourcepack {pacchetti di risorse} shader {shader} plugin {plugin} datapack {pacchetti di dati} other {progetti}} | {query}"
},
"error.collection.404.list_item.1": {
"message": "Forse c'è un errore di battitura nell'URL della raccolta."
},
@@ -1881,7 +1860,7 @@
"message": "Errore nella generazione dello stato da API durante il build."
},
"layout.banner.preview.description": {
"message": "Se volevi accedere al sito ufficiale, visita {url}. Questa versione serve allo staff di Modrinth per condurre test; basata su <branch-link>{owner}/{branch}</branch-link> @ {commit}."
"message": "Se volevi accedere al sito ufficiale, visita {url}. Questa versione serve allo staff di Modrinth per condurre test; basata su {ref}."
},
"layout.banner.preview.title": {
"message": "Questa versione del sito di Modrinth è un'anteprima."
@@ -2417,9 +2396,6 @@
"profile.label.collection": {
"message": "Raccolta"
},
"profile.label.downloads": {
"message": "{count} download"
},
"profile.label.joined": {
"message": "Iscrizione"
},
@@ -2450,9 +2426,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Scarica i progetti di {username} su Modrinth"
},
"profile.stats.projects-followers": {
"message": "<stat>{count, plural, =0 {Nessun} other {{count}}}</stat> follower del progetto"
},
"profile.user-id": {
"message": "ID utente: {id}"
},
@@ -2888,21 +2861,12 @@
"project.settings.permissions.learn-more": {
"message": "Scopri di più"
},
"project.settings.permissions.search-placeholder": {
"message": "Cerca tra {count, plural, one {# progetto esterno} other {# progetti esterni}}..."
},
"project.settings.title": {
"message": "Impostazioni"
},
"project.settings.visit-dashboard": {
"message": "Visita bacheca del progetto"
},
"project.stats.downloads-label": {
"message": "download"
},
"project.stats.followers-label": {
"message": "follower"
},
"project.status.archived.message": {
"message": "{title} è stato archiviato. {title} non riceverà più aggiornamenti a meno che l'autore decida di rimuoverlo dall'archivio."
},
@@ -2921,24 +2885,12 @@
"report.already-reported": {
"message": "Hai già segnalato {title}"
},
"report.already-reported-description": {
"message": "Hai già una segnalazione aperta per quest{item, select, project {o progetto} version {a versione} user {'utente} other {o contenuto}}. Puoi aggiungere più dettagli se hai informazioni da aggiungere."
},
"report.back-to-item": {
"message": "Torna al{item, select, project { progetto} version {la versione} user {l'utente} other { contenuto}}"
},
"report.body.description": {
"message": "Includi link e immagini se possibile e pertinente. Segnalazioni vuote o carenti saranno chiuse e ignorate."
},
"report.body.title": {
"message": "Si prega di fornire contesto aggiuntivo alla segnalazione"
},
"report.checking": {
"message": "Controllando {item, select, project {il progetto} version {la versione} user {l'utente} other {il contenuto}}..."
},
"report.could-not-find": {
"message": "Impossibile trovare {item, select, project {il progetto} version {la versione} user {l'utente} other {il contenuto}}"
},
"report.for.violation": {
"message": "Violazione delle <rules-link>regole</rules-link> o dei <terms-link>termini d'uso</terms-link> di Modrinth"
},
@@ -2978,15 +2930,9 @@
"report.please-report": {
"message": "Si prega di segnalare:"
},
"report.question.content-id": {
"message": "Qual è l'ID del{item, select, project { progetto} version {la versione} user {l'utente} other { contenuto}}?"
},
"report.question.content-type": {
"message": "Che tipo di contenuto stai segnalando?"
},
"report.question.report-reason": {
"message": "Quali regole di Modrinth sta violando quest{item, select, project {o progetto} version {a versione} user {'utente} other {o contenuto}}?"
},
"report.report-content": {
"message": "Segnala contenuto ai moderatori"
},
@@ -3665,21 +3611,12 @@
"settings.billing.interval.month": {
"message": "mese"
},
"settings.billing.interval.monthly": {
"message": "mensile"
},
"settings.billing.interval.quarter": {
"message": "trimestre"
},
"settings.billing.interval.quarterly.adjective": {
"message": "trimestrale"
},
"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"
},
@@ -3764,9 +3701,6 @@
"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)"
},
@@ -3833,18 +3767,9 @@
"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"
},
@@ -410,9 +410,6 @@
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "補足ファイルはソースコードなどの支援用リソースのためのものであり、別バージョンや派生版を配布するためのものではありません。"
},
"create.collection.collection-info": {
"message": "新しいコレクションは、{count, plural, =0 {空の} other {#個のプロジェクトを含む}}公開コレクションとして作成されます。"
},
"create.collection.create-collection": {
"message": "コレクションを作成"
},
@@ -575,9 +572,6 @@
"dashboard.affiliate-links.search": {
"message": "アフィリエイトリンクを検索…"
},
"dashboard.analytics.from-projects": {
"message": "{count} 件のプロジェクトから"
},
"dashboard.analytics.total-downloads": {
"message": "総ダウンロード数"
},
@@ -881,9 +875,6 @@
"dashboard.notifications.link.view-history": {
"message": "通知履歴を表示"
},
"dashboard.notifications.link.view-more": {
"message": "{extraNotifs} 件の通知をさらに表示"
},
"dashboard.organizations.button.create": {
"message": "組織を作成"
},
@@ -893,9 +884,6 @@
"dashboard.organizations.error.fetch": {
"message": "組織の取得に失敗しました"
},
"dashboard.organizations.member-count": {
"message": "{count} 人のメンバー"
},
"dashboard.organizations.title": {
"message": "組織"
},
@@ -920,9 +908,6 @@
"dashboard.projects.links.button.edit": {
"message": "リンクを編集"
},
"dashboard.projects.links.changes-applied": {
"message": "変更は <strong>{count}</strong> 件のプロジェクトに適用されます"
},
"dashboard.projects.links.description": {
"message": "下記に入力したリンクは、選択した各プロジェクトに上書きされます。空欄のままにしたリンクは無視されます。ゴミ箱ボタンを使用すると、選択したすべてのプロジェクトからリンクを削除できます。"
},
@@ -1373,9 +1358,6 @@
"hosting-marketing.faq.location": {
"message": "Modrinthでホストするサーバーはどこにありますか?地域を選択できますか?"
},
"hosting-marketing.faq.location.answer": {
"message": "現時点では、北アメリカ、ヨーロッパ、東南アジアのサーバーを購入時に選択できます。今後、より多くの地域に対応予定です!地域を変更したい場合はサポートまでお問い合わせください。"
},
"hosting-marketing.faq.versions-loaders": {
"message": "どのMinecraftのバージョンとローダーが使えますか?"
},
@@ -1457,9 +1439,6 @@
"hosting-marketing.know-what-you-need": {
"message": "必要なものが正確にわかっていますか?"
},
"hosting-marketing.medal.info": {
"message": "5日間無料で3GBのMedal提供のサーバーをお試しください"
},
"hosting-marketing.medal.learn-more": {
"message": "もっと詳しく知る"
},
@@ -2246,9 +2225,6 @@
"profile.label.collection": {
"message": "コレクション"
},
"profile.label.downloads": {
"message": "{count}件のダウンロード"
},
"profile.label.joined": {
"message": "参加: "
},
@@ -2279,9 +2255,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Modrinthで{username}のプロジェクトをダウンロードする"
},
"profile.stats.projects-followers": {
"message": "{count}件のプロジェクトフォロワー"
},
"profile.user-id": {
"message": "ユーザーID: {id}"
},
@@ -2609,12 +2582,6 @@
"project.settings.visit-dashboard": {
"message": "プロジェクトダッシュボードを見る"
},
"project.stats.downloads-label": {
"message": "件のダウンロード"
},
"project.stats.followers-label": {
"message": "人のフォロワー"
},
"project.status.archived.message": {
"message": "{title} はアーカイブされました。作者がプロジェクトのアーカイブを解除しない限り、今後 {title} に更新はありません。"
},
@@ -2624,24 +2591,12 @@
"report.already-reported": {
"message": "既に {title} をレポートしています"
},
"report.already-reported-description": {
"message": "この{item, select, project {プロジェクト} version {バージョン} user {ユーザー} other {コンテンツ}}に関するあなたの報告はすでに投稿されています。追記がある場合は、報告に詳細を追加できます。"
},
"report.back-to-item": {
"message": "{item, select, project {プロジェクト} version {バージョン} user {ユーザー} other {コンテンツ}}に戻る"
},
"report.body.description": {
"message": "可能で関連性がある場合は、リンクと画像を追加してください。空または不十分な報告は閉じられ、無視されます。"
},
"report.body.title": {
"message": "報告に関する追加情報をご提供ください"
},
"report.checking": {
"message": "{item, select, project {プロジェクト} version {バージョン} user {ユーザー} other {コンテンツ}}を確認中…"
},
"report.could-not-find": {
"message": "{item, select, project {プロジェクト} version {バージョン} user {ユーザー} other {コンテンツ}}が見つかりませんでした"
},
"report.for.violation": {
"message": "Modrinthの<rules-link>ルール</rules-link>または<terms-link>利用規約</terms-link>に違反している"
},
@@ -2681,15 +2636,9 @@
"report.please-report": {
"message": "是非報告ください:"
},
"report.question.content-id": {
"message": "{item, select, project {プロジェクト} version {バージョン} user {ユーザー} other {コンテンツ}}のIDは何ですか?"
},
"report.question.content-type": {
"message": "どの種類のコンテンツに関する報告ですか?"
},
"report.question.report-reason": {
"message": "この{item, select, project {プロジェクト} version {バージョン} user {ユーザー} other {コンテンツ}}は、Modrinthのどのルールに違反していますか?"
},
"report.report-content": {
"message": "コンテンツをモデレーターに報告する"
},
@@ -3365,21 +3314,12 @@
"settings.billing.interval.month": {
"message": "月"
},
"settings.billing.interval.monthly": {
"message": "月間"
},
"settings.billing.interval.quarter": {
"message": "四半期"
},
"settings.billing.interval.quarterly.adjective": {
"message": "3ヶ月ごと"
},
"settings.billing.interval.year": {
"message": "年"
},
"settings.billing.interval.yearly": {
"message": "年間"
},
"settings.billing.midas.benefits.ad-free": {
"message": "modrinth.comとModrinth Appを広告なしでブラウジング"
},
@@ -3464,9 +3404,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared}個の共有されたCPU ({bursts}個のCPUに増加)"
},
@@ -3533,18 +3470,9 @@
"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": "{date}に {interval} 払いに変更されます"
},
"settings.billing.update-method": {
"message": "支払い方法を更新"
},
+2 -89
View File
@@ -521,9 +521,6 @@
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "보조 파일은 소스 코드와 같은 지원용 리소스를 위한 것이며, 대체 버전이나 변형을 위한 것이 아닙니다."
},
"create.collection.collection-info": {
"message": "새 컬렉션은 {count, plural, =0 {프로젝트 없음} other {#개의 프로젝트}}를 포함한 공개 컬렉션으로 생성됩니다."
},
"create.collection.create-collection": {
"message": "컬렉션 생성"
},
@@ -680,14 +677,11 @@
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "취소"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "'{title}' 제휴 링크를 정말 삭제하시겠습니까?"
},
"dashboard.affiliate-links.search": {
"message": "제휴 링크 검색..."
},
"dashboard.analytics.from-projects": {
"message": "프로젝트 {count}개"
"message": "{count} {count, plural, one {프로젝트} other {프로젝트}}로"
},
"dashboard.analytics.total-downloads": {
"message": "다운로드 수"
@@ -995,9 +989,6 @@
"dashboard.notifications.link.view-history": {
"message": "알림 기록 보기"
},
"dashboard.notifications.link.view-more": {
"message": "알림 {extraNotifs}개 더 보기"
},
"dashboard.organizations.button.create": {
"message": "조직 생성"
},
@@ -1007,9 +998,6 @@
"dashboard.organizations.error.fetch": {
"message": "조직 정보 가져오기 실패"
},
"dashboard.organizations.member-count": {
"message": "멤버 {count}명"
},
"dashboard.organizations.title": {
"message": "조직"
},
@@ -1055,9 +1043,6 @@
"dashboard.projects.links.button.edit": {
"message": "링크 편집"
},
"dashboard.projects.links.changes-applied": {
"message": "변경사항이 <strong>{count}개</strong>의 프로젝트에 적용됩니다."
},
"dashboard.projects.links.description": {
"message": "아래 지정한 링크는 선택한 각 프로젝트에서 덮어쓰게 됩니다. 비워 둔 항목은 무시됩니다. 휴지통 버튼을 클릭하면 선택한 모든 프로젝트에서 링크를 삭제할 수 있습니다."
},
@@ -1361,15 +1346,6 @@
"discover.install.heading.reset-modpack": {
"message": "리셋 후 설치할 모드팩 선택"
},
"discover.seo.description": {
"message": "Modrinth에서 수천 개의 마인크래프트 {projectType, select, mod {모드를} modpack {모드팩을} resourcepack {리소스팩을} shader {셰이더를} plugin {플러그인을} datapack {데이터팩을} other {프로젝트를}} 즉각적이고 정확한 검색 결과로 찾아보세요. 제공되는 필터로 최적의 마인크래프트 {projectType, select, mod {모드를} modpack {모드팩을} resourcepack {리소스팩을} shader {쉐이더를} plugin {플러그인을} datapack {데이터팩을} other {프로젝트를}} 빠르게 찾을 수 있습니다."
},
"discover.seo.title": {
"message": "{projectType, select, mod {모드} modpack {모드팩} resourcepack {리소스팩} shader {셰이더} plugin {플러그인} datapack {데이터팩} other {프로젝트}} 검색"
},
"discover.seo.title-with-query": {
"message": "{projectType, select, mod {모드} modpack {모드팩} resourcepack {리소스팩} shader {셰이더} plugin {플러그인} datapack {데이터팩} other {프로젝트}} {query} 검색"
},
"error.collection.404.list_item.1": {
"message": "컬렉션 URL을 잘못 입력했을 수 있습니다."
},
@@ -1536,7 +1512,7 @@
"message": "Modrinth 호스팅 서버는 어디에 위치해 있나요? 지역을 선택할 수 있나요?"
},
"hosting-marketing.faq.location.answer": {
"message": "현재 서버는 구매 시 북미, 유럽, 동남아 지역 중에서 선택할 수 있습니다. 향후 더 많은 지역에서 서비스를 제공할 예정입니다! 지역을 변경이 필요하면 지원팀에 문의해 주세요."
"message": "현재 북미, 유럽, 동남아시아 전역에서 구매 시 선택할 수 있는 서버가 있습니다. 앞으로 더 많은 지역이 추가될 예정입니다! 지역을 변경하고 싶으시면 지원팀에 문의해 주세요."
},
"hosting-marketing.faq.versions-loaders": {
"message": "어떤 마인크래프트 버전과 로더를 사용할 수 있나요?"
@@ -1880,9 +1856,6 @@
"layout.banner.build-fail.title": {
"message": "빌드 중 API에서 상태 생성 오류가 발생했습니다."
},
"layout.banner.preview.description": {
"message": "공식 Modrinth 웹사이트에 접속하려는 경우, {url}을(를) 방문하세요. 이 미리보기 배포판은 Modrinth 운영진이 테스트 목적으로 사용하며, 이는 <branch-link>{owner}/{branch}</branch-link> @ {commit} 기반으로 빌드되었습니다."
},
"layout.banner.preview.title": {
"message": "이 웹사이트는 Modrinth의 미리보기입니다."
},
@@ -2450,9 +2423,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Modrinth에서 {username}의 프로젝트 다운로드"
},
"profile.stats.projects-followers": {
"message": "{count, plural, other {<stat>{count}</stat> 프로젝트 팔로워}}"
},
"profile.user-id": {
"message": "사용자 ID: {id}"
},
@@ -2888,57 +2858,30 @@
"project.settings.permissions.learn-more": {
"message": "더보기"
},
"project.settings.permissions.search-placeholder": {
"message": "{count}개의 {count, plural, other {외부 프로젝트}} 검색..."
},
"project.settings.title": {
"message": "설정"
},
"project.settings.visit-dashboard": {
"message": "프로젝트 대시보드 방문"
},
"project.stats.downloads-label": {
"message": "다운로드"
},
"project.stats.followers-label": {
"message": "팔로워"
},
"project.status.archived.message": {
"message": "{title} 은(는) 보관되었습니다. 작성자가 프로젝트 보관 해제를 결정하지 않는 한 더 이상 업데이트가 제공되지 않습니다."
},
"project.versions.title": {
"message": "버전"
},
"project.versions.withheld-versions-warning.description": {
"message": "{count, plural, other {해당 버전은}} 현재 보류 상태이며 공개되지 않았습니다. 이 모드팩 {count, plural, other {버전에}} 포함된 특정 파일들을 재배포할 수 있는 권한이 있음을 증명하는 자료를 제출해주세요."
},
"project.versions.withheld-versions-warning.resolve-button": {
"message": "해결"
},
"project.versions.withheld-versions-warning.title": {
"message": "알 수 없는 내장 콘텐츠로 인해 일부 {count, plural, other {버전}}은 공개되지 않았습니다"
},
"report.already-reported": {
"message": "이미 {title} 을(를) 신고했습니다"
},
"report.already-reported-description": {
"message": "이 {item, select, project {project} version {version} user {user} other {content}}에 대한 신고가 이미 접수되었습니다. 추가로 알릴 정보가 있다면 기존 신고에 더 자세한 내용을 추가할 수 있습니다."
},
"report.back-to-item": {
"message": "{item, select, project {프로젝트} version {버전} user {사용자} other {콘텐츠}}으로 돌아가기"
},
"report.body.description": {
"message": "가능하면 링크와 이미지를 포함하고 관련성이 있다면 알려주세요. 비어 있거나 성의 없는 신고는 무시됩니다."
},
"report.body.title": {
"message": "신고에 대한 추가 정황을 제공해 주세요"
},
"report.checking": {
"message": "확인중 {item, select, project {project} version {version} user {user} other {content}}..."
},
"report.could-not-find": {
"message": "{item, select, project {project} version {version} user {user} other {content}}를 찾을 수 없습니다."
},
"report.for.violation": {
"message": "Modrinth <rules-link>규칙</rules-link> 또는 <terms-link>이용 약관</terms-link>을 위반함"
},
@@ -2978,15 +2921,9 @@
"report.please-report": {
"message": "해당 상황에서 신고하세요:"
},
"report.question.content-id": {
"message": "이 {item, select, project {project} version {version} user {user} other {content}}의 ID는 무엇인가요?"
},
"report.question.content-type": {
"message": "신고하려는 콘텐츠의 유형이 무엇입니까?"
},
"report.question.report-reason": {
"message": "이 {item, select, project {project} version {version} user {user} other {content}}는 Modrinth의 어떤 규칙을 위반하고 있습니까?"
},
"report.report-content": {
"message": "관리자에게 콘텐츠 신고"
},
@@ -3515,9 +3452,6 @@
"settings.account.two-factor.setup.manual-secret": {
"message": "QR 코드가 스캔되지 않는다면, 수동으로 코드를 입력할 수 있습니다:"
},
"settings.account.two-factor.setup.scan": {
"message": "시작하려면 <authy-link>Authy<authy-link>, <microsoft-authenticator-link>Microsoft Authenticator<microsoft-authenticator-link>, 또는 기타 2단계 인증 앱으로 QR 코드를 스캔하세요."
},
"settings.account.two-factor.verify.description": {
"message": "접근을 승인하려면 인증 앱에서 받은 일회용 코드를 입력하세요."
},
@@ -3665,21 +3599,12 @@
"settings.billing.interval.month": {
"message": "월"
},
"settings.billing.interval.monthly": {
"message": "월간"
},
"settings.billing.interval.quarter": {
"message": "분기"
},
"settings.billing.interval.quarterly.adjective": {
"message": "분기별"
},
"settings.billing.interval.year": {
"message": "년"
},
"settings.billing.interval.yearly": {
"message": "연간"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Modrinth App 및 modrinth.com에서 광고 없이 브라우징"
},
@@ -3764,9 +3689,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} 공유 CPU (최대 {bursts} CPU까지 버스트)"
},
@@ -3833,18 +3755,9 @@
"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": "{date}에 {interval} 결제로 변경됨"
},
"settings.billing.update-method": {
"message": "결제수단 업데이트"
},
+21 -93
View File
@@ -449,6 +449,27 @@
"conversation-thread.action.send-to-review-with-reply": {
"message": "Hantar untuk semakan dengan balasan"
},
"conversation-thread.error.closing-report": {
"message": "Ralat semasa menutup laporan"
},
"conversation-thread.error.reopening-report": {
"message": "Ralat semasa membuka semula laporan"
},
"conversation-thread.error.sending-message": {
"message": "Ralat semasa menghantar mesej"
},
"conversation-thread.reply-editor.placeholder.reply": {
"message": "Balas bebenang..."
},
"conversation-thread.reply-editor.placeholder.send": {
"message": "Hantar mesej..."
},
"conversation-thread.reply-modal.confirmation.description": {
"message": "Sahkan bahawa penyederhana tidak memantau bebenang ini secara aktif"
},
"conversation-thread.reply-modal.confirmation.label": {
"message": "Saya akui bahawa penyederhana tidak memantau bebenang ini secara aktif."
},
"conversation-thread.resubmit-modal.description": {
"message": "Anda sedang menghantar <project-title>{projectTitle}</project-title> untuk disemak semula oleh penyederhana."
},
@@ -461,9 +482,6 @@
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "Fail tambahan adalah untuk sumber sokongan seperti kod sumber, bukan untuk versi atau varian alternatif."
},
"create.collection.collection-info": {
"message": "Koleksi baharu anda akan dibuat sebagai koleksi awam dengan {count, plural, =0 {0 projek} other {# projek}}."
},
"create.collection.create-collection": {
"message": "Cipta koleksi"
},
@@ -623,9 +641,6 @@
"dashboard.affiliate-links.search": {
"message": "Cari pautan afiliasi..."
},
"dashboard.analytics.from-projects": {
"message": "daripada {count} {count, plural, other {projek}}"
},
"dashboard.analytics.total-downloads": {
"message": "Jumlah muat turun"
},
@@ -647,9 +662,6 @@
"dashboard.collections.empty.no-match-hint": {
"message": "Cuba laraskan penapis atau istilah carian anda."
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, other {projek}}"
},
"dashboard.collections.label.search-input": {
"message": "Cari koleksi anda"
},
@@ -929,9 +941,6 @@
"dashboard.notifications.link.view-history": {
"message": "Lihat sejarah pemberitahuan"
},
"dashboard.notifications.link.view-more": {
"message": "Lihat {extraNotifs} lagi {extraNotifs, plural, other {pemberitahuan}}"
},
"dashboard.organizations.button.create": {
"message": "Cipta organisasi"
},
@@ -941,9 +950,6 @@
"dashboard.overview.notifications.loading": {
"message": "Sedang memuat pemberitahuan..."
},
"dashboard.projects.links.changes-applied": {
"message": "Perubahan akan diterapkan kepada <strong>{count}</strong> {count, plural, other {projek}}."
},
"dashboard.projects.links.description": {
"message": "Sebarang pautan yang anda nyatakan di bawah akan ditulis ganti pada setiap projek yang dipilih. Sebarang pautan yang anda biarkan kosong akan diabaikan. Anda boleh memadamkan pautan daripada semua projek yang dipilih menggunakan butang tong sampah."
},
@@ -1205,15 +1211,6 @@
"discover.install.cancel-reset": {
"message": "Batalkan penetapan semula"
},
"discover.seo.description": {
"message": "Cari dan layari beribu-ribu {projectType, select, mod {mod} modpack {pek mod} resourcepack {pek sumber} shader {pembayang} plugin {pemalam} datapack {pek data} other {projek}} Minecraft di Modrinth dengan hasil carian yang segera dan tepat. Penapis kami akan membantu anda mencari {projectType, select, mod {mod} modpack {pek mod} resourcepack {pek sumber} shader {pembayang} plugin {pemalam} datapack {pek data} other {projek}} yang terbaik."
},
"discover.seo.title": {
"message": "Cari {projectType, select, mod {mod} modpack {pek mod} resourcepack {pek sumber} shader {pembayang} plugin {pemalam} datapack {pek data} other {projek}}"
},
"discover.seo.title-with-query": {
"message": "Cari {projectType, select, mod {mod} modpack {pek mod} resourcepack {pek sumber} shader {pembayang} plugin {pemalam} datapack {pek data} other {projek}} | {query}"
},
"error.collection.404.list_item.1": {
"message": "Anda mungkin tersalah taip URL koleksi."
},
@@ -1373,9 +1370,6 @@
"hosting-marketing.faq.location": {
"message": "Di manakah pelayan Modrinth Hosting terletak? Bolehkah saya memilih rantau?"
},
"hosting-marketing.faq.location.answer": {
"message": "Kami mempunyai pelayan yang tersedia di Amerika Utara, Eropah dan Asia Tenggara pada masa ini yang boleh anda pilih semasa pembelian. Lebih banyak rantau akan datang pada masa hadapan! Jika anda ingin menukar rantau anda, sila hubungi sokongan."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Versi Minecraft dan pemuat apa yang boleh digunakan?"
},
@@ -1709,9 +1703,6 @@
"layout.banner.build-fail.title": {
"message": "Ralat menjana keadaan daripada API semasa membina."
},
"layout.banner.preview.description": {
"message": "Jika anda bermaksud untuk mengakses laman sesawang rasmi Modrinth, kunjungi {url}. Pralihat pelaksanaan ini digunakan oleh kakitangan Modrinth untuk tujuan pengujian. Ia dibina menggunakan <branch-link>{owner}/{branch}</branch-link> @ {commit}."
},
"layout.banner.preview.title": {
"message": "Ini ialah pengaturan pralihat laman sesawang Modrinth."
},
@@ -2246,9 +2237,6 @@
"profile.label.collection": {
"message": "Koleksi"
},
"profile.label.downloads": {
"message": "{count} {countPlural, plural, other {muat turun}}"
},
"profile.label.joined": {
"message": "Telah menyertai"
},
@@ -2267,9 +2255,6 @@
"profile.label.organizations": {
"message": "Organisasi"
},
"profile.label.projects": {
"message": "{count} {countPlural, plural, other {projek}}"
},
"profile.label.saving": {
"message": "Sedang menyimpan..."
},
@@ -2279,9 +2264,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Muat turun projek milik {username} di Modrinth"
},
"profile.stats.projects-followers": {
"message": "{count, plural, other {<stat>{count}</stat> pengikut projek}}"
},
"profile.user-id": {
"message": "ID Pengguna: {id}"
},
@@ -2717,57 +2699,30 @@
"project.settings.permissions.learn-more": {
"message": "Ketahui lebih lanjut"
},
"project.settings.permissions.search-placeholder": {
"message": "Cari {count} {count, plural, other {projek luaran}}..."
},
"project.settings.title": {
"message": "Tetapan"
},
"project.settings.visit-dashboard": {
"message": "Kunjungi papan pemuka projek"
},
"project.stats.downloads-label": {
"message": "muat turun{count, plural, other {}}"
},
"project.stats.followers-label": {
"message": "pengikut{count, plural, other {}}"
},
"project.status.archived.message": {
"message": "{title} telah diarkibkan. {title} tidak akan menerima sebarang kemas kini lanjut melainkan pengarang memutuskan untuk menyaharkibkan projek."
},
"project.versions.title": {
"message": "Versi"
},
"project.versions.withheld-versions-warning.description": {
"message": "{count, plural, other {Versi ini}} kini ditahan dan tidak disenaraikan secara umum. Sila berikan bukti bahawa anda mempunyai kebenaran untuk mengedarkan semula fail tertentu yang disertakan dalam {count, plural, other {versi}} pek mod ini."
},
"project.versions.withheld-versions-warning.resolve-button": {
"message": "Selesaikan"
},
"project.versions.withheld-versions-warning.title": {
"message": "{count, plural, other {Versi}} telah ditahan kerana kandungan terbenam yang tidak diketahui"
},
"report.already-reported": {
"message": "Anda telah melaporkan {title}"
},
"report.already-reported-description": {
"message": "Anda sudah mempunyai laporan terbuka untuk {item, select, project {projek} version {versi} user {pengguna} other {kandungan}} ini. Anda boleh menambah lebih banyak butiran pada laporan anda jika anda mempunyai lebih banyak maklumat untuk ditambahkan."
},
"report.back-to-item": {
"message": "Kembali ke {item, select, project {projek} version {versi} user {pengguna} other {kandungan}}"
},
"report.body.description": {
"message": "Sertakan pautan dan gambar jika boleh dan adalah berkaitan. Laporan kosong atau tidak mencukupi akan ditutup dan diabaikan."
},
"report.body.title": {
"message": "Sila berikan konteks tambahan tentang laporan anda"
},
"report.checking": {
"message": "Sedang menyemak {item, select, project {projek} version {versi} user {pengguna} other {kandungan}}..."
},
"report.could-not-find": {
"message": "Tidak dapat mencari {item, select, project {projek} version {versi} user {pengguna} other {kandungan}}"
},
"report.for.violation": {
"message": "Pelanggaran <rules-link>Peraturan</rules-link> atau <terms-link>Terma Penggunaan</terms-link> Modrinth"
},
@@ -2807,15 +2762,9 @@
"report.please-report": {
"message": "Tolong laporkan:"
},
"report.question.content-id": {
"message": "Apakah ID {item, select, project {projek} version {versi} user {pengguna} other {kandungan}} itu?"
},
"report.question.content-type": {
"message": "Apakah jenis kandungan yang anda hendak laporkan?"
},
"report.question.report-reason": {
"message": "Peraturan Modrinth manakah yang dilanggar oleh {item, select, project {projek} version {versi} user {pengguna} other {kandungan}} ini?"
},
"report.report-content": {
"message": "Laporkan kandungan kepada penyederhana"
},
@@ -3494,21 +3443,12 @@
"settings.billing.interval.month": {
"message": "bulan"
},
"settings.billing.interval.monthly": {
"message": "bulanan"
},
"settings.billing.interval.quarter": {
"message": "3 bulan"
},
"settings.billing.interval.quarterly.adjective": {
"message": "setiap tiga bulan"
},
"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"
},
@@ -3593,9 +3533,6 @@
"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)"
},
@@ -3662,18 +3599,9 @@
"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"
},
+26 -68
View File
@@ -281,9 +281,6 @@
"auth.sign-up.action.create-account": {
"message": "Account aanmaken"
},
"auth.sign-up.legal-dislaimer": {
"message": "Door een account te creëren, ga je akkoord met de <terms-link>Voorwaarden</terms-link> en het </privacy-policy-link>Privacybeleid</privacy-policy-link> van Modrinth."
},
"auth.sign-up.notification.password-mismatch.text": {
"message": "Wachtwoorden komen niet overeen!"
},
@@ -338,9 +335,6 @@
"auth.welcome.description": {
"message": "Je bent nu deel van de geweldige community van makers en ontdekkers die mods bouwen, downloaden en up-to-date blijven van geweldige mods."
},
"auth.welcome.label.tos": {
"message": "Door een account te hebben gemaakt, ben je akkoord gegaan met de <terms-link>Voorwaarden</terms-link> en het </privacy-policy-link>Privacybeleid</privacy-policy-link> van Modrinth."
},
"auth.welcome.long-title": {
"message": "Welkom op Modrinth!"
},
@@ -407,11 +401,20 @@
"collection.title": {
"message": "{name} - Collectie"
},
"conversation-thread.reply-modal.description": {
"message": "Je project is al goedgekeurd. Daarom houdt het moderatieteam deze thread niet actief in de gaten. Mocht er echter een probleem met je project zijn, dan kunnen zij je bericht wel zien."
},
"conversation-thread.reply-modal.help-center-note": {
"message": "Als je contact wilt opnemen met het moderatorteam, ga dan naar het <help-center-link>Modrinth Helpcentrum</help-center-link> en klik op het blauwe ballonnetje rechtsonder om contact op te nemen met de ondersteuning."
},
"conversation-thread.resubmit-modal.warning": {
"message": "Herhaaldelijk berichten plaatsen zonder in te gaan op de opmerkingen van de moderators kan leiden tot een opschorting van je account."
},
"create-project-version.create-modal.stage.add-files.admonition": {
"message": "Aanvullende bestanden zijn bedoeld voor ondersteunende bronnen zoals source code, niet voor alternatieve versies of varianten."
},
"create.collection.collection-info": {
"message": "Je nieuwe collectie wordt gemaakt als een publieke collectie met {{count, plural,=0 {geen projecten}one {# project}other {# projecten}}."
"message": "Je nieuwe collectie wordt gemaakt als een publieke collectie met {count, plural,=0 {geen projecten}one {# project}other {# projecten}}."
},
"create.collection.create-collection": {
"message": "Collectie aanmaken"
@@ -446,9 +449,6 @@
"create.limit-alert.limit-reached": {
"message": "{type} limiet bereikt"
},
"create.limit-alert.limit-reached-description": {
"message": "Je hebt het {type} limiet bereikt. Neem contact op met support om je limiet te verhogen."
},
"create.limit-alert.type-collection": {
"message": "Collectie"
},
@@ -572,6 +572,9 @@
"dashboard.affiliate-links.search": {
"message": "Zoek affiliatelinks..."
},
"dashboard.analytics.from-projects": {
"message": "van {count} {count, plural, one {project} other {projects}}"
},
"dashboard.collections.button.create-new": {
"message": "Maak nieuwe"
},
@@ -848,6 +851,18 @@
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "Je hebt je opnamelimiet <b>{withdrawLimit}</b> bereikt. Je moet een belastingformulier invullen om meer geld op te nemen."
},
"dashboard.notifications.link.view-more": {
"message": "Bekijk {extraNotifs} meer {extraNotifs, plural, one {notification} other {notifications}}"
},
"dashboard.organizations.member-count": {
"message": "{count} {count, plural, one {member} other {members}}"
},
"dashboard.projects.links.changes-applied": {
"message": "De wijzigingen worden toegepast op <strong>{count}</strong> {count, plural, one {project} other {projects}}."
},
"dashboard.projects.links.description": {
"message": "Alle links die u hieronder opgeeft, worden in elk van de geselecteerde projecten overschreven. Links die u leeg laat, worden genegeerd. U kunt een link uit alle geselecteerde projecten verwijderen met de prullenbakknop."
},
"dashboard.revenue.available-now": {
"message": "Nu beschikbaar"
},
@@ -1164,7 +1179,7 @@
"message": "Waar bevinden de servers van Modrinth Hosting zich? Kan ik een regio kiezen?"
},
"hosting-marketing.faq.location.answer": {
"message": "We hebben momenteel servers beschikbaar in Noord-Amerika, Europa en Zuidoost-Azië, waaruit u bij aankoop kunt kiezen. In de toekomst zullen er meer regio's volgen! Als u uw regio wilt wijzigen, neem dan contact op met de klantenservice."
"message": "Op dit moment hebben we servers beschikbaar in Noord-Amerika, Europa en Zuidoost-Azië, waaruit u bij aankoop kunt kiezen. In de toekomst komen er nog meer regios bij! Als u van regio wilt wisselen, neem dan contact op met de klantenservice."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Welke Minecraft-versies en loaders kunnen worden gebruikt?"
@@ -2405,24 +2420,12 @@
"report.already-reported": {
"message": "U heeft al {title} gerapporteerd"
},
"report.already-reported-description": {
"message": "Je hebt al een open report voor {item, select, project {project} version {version} user {user} other {content}}, je kan nog meer informatie toevoegen aan de report als je nog meer informatie hebt."
},
"report.back-to-item": {
"message": "Terug naar {item, select, project {project} version {version} user {user} other {content}}"
},
"report.body.description": {
"message": "Voeg linken en afbeelding als het mogelijk en relevant is. Lege of onvoldoende rapportages zullen gesloten worden en geregeerd worden."
},
"report.body.title": {
"message": "Geef alstublieft aanvoegende context over uw rapportage"
},
"report.checking": {
"message": "Controleren {item, select, project {project} version {version} user {user} other {content}}..."
},
"report.could-not-find": {
"message": "Kan {item, select, project {project} version {version} user {user} other {content}} niet vinden"
},
"report.for.violation": {
"message": "Het schenden van Modrinth <rules-link> Regels</rules-link> of <terms-link>Termen</terms-link>"
},
@@ -2462,15 +2465,9 @@
"report.please-report": {
"message": "Graag rapporteer:"
},
"report.question.content-id": {
"message": "Wat is het ID van {item, select, project {project} version {version} user {user} other {content}}?"
},
"report.question.content-type": {
"message": "Welk type conteant wil je rapporteren?"
},
"report.question.report-reason": {
"message": "Welke regels van Modrinth is {item, select, project {project} version {version} user {user} other {content}} zich niet aan het houden?"
},
"report.report-content": {
"message": "Meld content aan moderators"
},
@@ -3140,27 +3137,15 @@
"settings.billing.charges.title": {
"message": "Eerdere aanklachten"
},
"settings.billing.expires": {
"message": "Vervalt op {datum}"
},
"settings.billing.interval.month": {
"message": "maand"
},
"settings.billing.interval.monthly": {
"message": "maandelijks"
},
"settings.billing.interval.quarter": {
"message": "kwartaal"
},
"settings.billing.interval.quarterly.adjective": {
"message": "Per kwartaal"
},
"settings.billing.interval.year": {
"message": "jaar"
},
"settings.billing.interval.yearly": {
"message": "jaarlijks"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Reclamevrij surfen op modrinth.com en in de Modrinth app"
},
@@ -3173,9 +3158,6 @@
"settings.billing.midas.benefits.title": {
"message": "Voordelen"
},
"settings.billing.midas.save-per-year": {
"message": "Bespaar {bedrag} per jaar door over te stappen op jaarfacturering!"
},
"settings.billing.midas.status.cancelled.line1": {
"message": "Je hebt je abonnement opgezegd."
},
@@ -3215,9 +3197,6 @@
"settings.billing.next": {
"message": "Volgende:"
},
"settings.billing.or-yearly-save": {
"message": "Of {prijs} per jaar (bespaar {percent}%)!"
},
"settings.billing.payment_method.action.add": {
"message": "Voeg betalings-methode toe"
},
@@ -3245,9 +3224,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} Gedeelde CPU's (pieken tot {bursts} CPU's)"
},
@@ -3296,15 +3272,9 @@
"settings.billing.pyro_subscription.title": {
"message": "Modrinth Server Abonnementen"
},
"settings.billing.renews": {
"message": "Vernieuwt {datum}"
},
"settings.billing.resubscribe": {
"message": "Opnieuw abonneren"
},
"settings.billing.since": {
"message": "Sinds {datum}"
},
"settings.billing.subscribe": {
"message": "Abonneren"
},
@@ -3314,18 +3284,6 @@
"settings.billing.subscription.title": {
"message": "Abonnementen"
},
"settings.billing.switch.switching-to-interval": {
"message": "Overstappen naar {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Schakel over naar {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Bij maandelijkse facturering betaalt u {bedrag} extra per jaar"
},
"settings.billing.switches-to-billing-on": {
"message": "Gaat op {datum} over op facturering per {interval}"
},
"settings.billing.update-method": {
"message": "Update methode"
},
@@ -1238,9 +1238,6 @@
"hosting-marketing.faq.location": {
"message": "Hvor oppholder Modrinth Hosting-serverne seg? Kan jeg velge en region?"
},
"hosting-marketing.faq.location.answer": {
"message": "Akkurat nå, så har tilgjengelige servere i Nord-Amerika, Europa, og Sørøst-Asia som du kan velge etter kjøpet ditt. Det kommer flere regioner i framtida! Viss du vil bytte regionen din, vær så snill å ta kontakt med støtte."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Hvilke Minecraft-versjoner-og-loadere kan brukes?"
},
@@ -2480,24 +2477,12 @@
"report.already-reported": {
"message": "Du har allerede rapportert {title}"
},
"report.already-reported-description": {
"message": "Du har en åpen rapport for denne/dette {item, select, project {prosjektet} version {versjonen} user {brukeren} other {innholdet}} allerede. Du kan legge til flere detaljer til rapporten din hvis du har mer informasjon du vil legge til."
},
"report.back-to-item": {
"message": "Tilbake til {item, select, project {prosjekt} version {versjon} user {bruker} other {innhold}}"
},
"report.body.description": {
"message": "Viss det er mulig, inkluder lenker og bilder. Tomme eller utilstrekkelige rapporter kommer til å bli lukka ned og ignorert."
},
"report.body.title": {
"message": "Vær så snill å kom med mer kontekst om prosjektet ditt"
},
"report.checking": {
"message": "Sjekker {item, select, project {prosjekt} version {versjon} user {bruker} other {innhold}}..."
},
"report.could-not-find": {
"message": "Kunne ikke finne {item, select, project {prosjekt} version {versjon} user {bruker} other {innhold}}"
},
"report.for.violation": {
"message": "Brudd på <rules-link>Reglene</rules-link> til Modrinth eller <terms-link>Bruksvilkåra</terms-link> deres"
},
@@ -2537,15 +2522,9 @@
"report.please-report": {
"message": "Vær så snill å rapporter:"
},
"report.question.content-id": {
"message": "Hva er ID-en til {item, select, project {prosjektet} version {versjonen} user {brukeren} other {innholdet}}?"
},
"report.question.content-type": {
"message": "Hvilken type innhold rapporterer du?"
},
"report.question.report-reason": {
"message": "Hvilke av reglene til Modrinth bryter dette: {item, select, project {prosjekt} version {versjon} user {bruker} other {innhold}}?"
},
"report.report-content": {
"message": "Rapporter innhold til moderatorene"
},
@@ -3218,15 +3197,9 @@
"settings.billing.interval.month": {
"message": "måned"
},
"settings.billing.interval.monthly": {
"message": "månedlig"
},
"settings.billing.interval.year": {
"message": "år"
},
"settings.billing.interval.yearly": {
"message": "årlig"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Reklamefri surfing av modrinth.com og Modrinth App-en"
},
@@ -3311,9 +3284,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} Delte CPU-er (utbryter opp til {bursts} CPU-er)"
},
@@ -3377,18 +3347,9 @@
"settings.billing.subscription.title": {
"message": "Abonnement"
},
"settings.billing.switch.switching-to-interval": {
"message": "Bytt til {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Bytt til {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Månedlig fakturering kommer til å koste deg yttligere {amount} hvert year"
},
"settings.billing.switches-to-billing-on": {
"message": "Bytter til {interval} fakturering på {date}"
},
"settings.billing.update-method": {
"message": "Oppdater metode"
},
@@ -710,9 +710,6 @@
"dashboard.collections.empty.no-match-hint": {
"message": "Spróbuj zmienić filtry wyszukiwania lub zapytanie."
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, one {projekt} few {projekty} other {projektów}}"
},
"dashboard.collections.label.search-input": {
"message": "Szukaj swoich kolekcji"
},
@@ -995,9 +992,6 @@
"dashboard.notifications.link.view-history": {
"message": "Pokaż historię powiadomień"
},
"dashboard.notifications.link.view-more": {
"message": "Pokaż jeszcze {extraNotifs} {extraNotifs, plural, one {powiadomienie} few {powiadomienia} other {powiadomień}}"
},
"dashboard.organizations.button.create": {
"message": "Utwórz organizację"
},
@@ -1046,9 +1040,6 @@
"dashboard.projects.head-title": {
"message": "Projekty"
},
"dashboard.projects.links.and-more": {
"message": "i {count} {count, plural, one {inny} few {inne} other {innych}}..."
},
"dashboard.projects.links.button.clear-link": {
"message": "Wyczyść link"
},
@@ -1295,9 +1286,6 @@
"dashboard.withdraw.error.email-verification.title": {
"message": "Wymagana weryfikacja e-maila"
},
"dashboard.withdraw.error.generic.text": {
"message": "Nie udało się przesłać prośby o wypłatę, sprawdź podane dane lub skontaktuj się z obsługą"
},
"dashboard.withdraw.error.generic.title": {
"message": "Wypłata nie powiodła się"
},
@@ -1361,15 +1349,6 @@
"discover.install.heading.reset-modpack": {
"message": "Wybieranie paczki modów do zainstalowania po zresetowaniu"
},
"discover.seo.description": {
"message": "Szukaj i przeglądaj tysiące {projectType, select, mod {modów} modpack {paczek modów} resourcepack {paczek zasobów} shader {shaderów} plugin {pluginów} datapack {paczek danych} other {projektów}} Minecraft na Modrinth z natychmiastowymi, trafnymi wynikami wyszukiwania. Nasze filtry pomogą CI szybko znaleźć najlepsze projectType, select, mod {mody} modpack {paczki modów} resourcepack {paczki zasobów} shader {shadery} plugin {pluginy} datapack {paczki danych} other {projekty}} Minecraft."
},
"discover.seo.title": {
"message": "Szukaj {projectType, select, mod {modów} modpack {paczek modów} resourcepack {paczek zasobów} shader {shaderów} plugin {pluginów} datapack {paczek danych} other {projektów}}"
},
"discover.seo.title-with-query": {
"message": "Szukaj {projectType, select, mod {modów} modpack {paczek modów} resourcepack {paczek zasobów} shader {shaderów} plugin {pluginów} datapack {paczek danych} other {projektów}} | {query}"
},
"error.collection.404.list_item.1": {
"message": "Mogłeś źle napisać URL kolekcji."
},
@@ -1880,9 +1859,6 @@
"layout.banner.build-fail.title": {
"message": "Błąd podczas generowania stanu z API przy kompilacji."
},
"layout.banner.preview.description": {
"message": "Jeśli chciałeś/aś wejść na oficjalną stronę Modrinth, odwiedź {url}. To wydanie poglądowe jest używane przez administrację Modrinth do testów. Zostało utworzone z <branch-link>{owner}/{branch}</branch-link> @ {commit}."
},
"layout.banner.preview.title": {
"message": "To jest wydanie poglądowe strony Modrinth."
},
@@ -2417,9 +2393,6 @@
"profile.label.collection": {
"message": "Kolekcja"
},
"profile.label.downloads": {
"message": "{count} {countPlural, plural, one {pobranie} few {pobrania} other {pobrań}}"
},
"profile.label.joined": {
"message": "Dołączył(-a)"
},
@@ -2438,9 +2411,6 @@
"profile.label.organizations": {
"message": "Organizacje"
},
"profile.label.projects": {
"message": "{count} {countPlural, plural, one {projekt} few {projekty} other {projektów}}"
},
"profile.label.saving": {
"message": "Zapisywanie..."
},
@@ -2468,9 +2438,6 @@
"project-member-header.invitation-title": {
"message": "Zaproszenie do dołączenia do projektu"
},
"project-member-header.invitation-with-role": {
"message": "Zostałeś zaproszony do udziału w tym projekcie w roli '{role}''."
},
"project-member-header.success-decline": {
"message": "Odrzucono zaproszenie do zespołu"
},
@@ -2486,9 +2453,6 @@
"project-moderation-nags.resubmit-for-review": {
"message": "Wyślij ponownie do przeglądu"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Twój projekt został {status, select, rejected {odrzucony} witheld {wstrzymany} other {{status}}} przez zespół Modrinth. W większości przypadków możesz ponownie wysłać swój projekt do sprawdzenia po rozwiązaniu wspomnianego problemu."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Należy wykonać wszystkie czynności wymienione w liście kontrolnej dotyczącej publikacji!"
},
@@ -2897,9 +2861,6 @@
"project.settings.visit-dashboard": {
"message": "Odwiedź pulpit projektów"
},
"project.stats.downloads-label": {
"message": "{count, plural, one {pobranie} few {pobrania} other {pobrań}}"
},
"project.stats.followers-label": {
"message": "{count, plural, one {obserwujący} other {obserwujących}}"
},
@@ -2921,24 +2882,12 @@
"report.already-reported": {
"message": "Zgłosiłeś już {title}"
},
"report.already-reported-description": {
"message": "Masz już otwarte zgłoszenie dla {item, select, project {tego projektu} version {tej wersji} user {tego użytkownika} other {tych treści}}. Jeżeli masz więcej informacji, możesz dodać je do istniejącego zgłoszenia."
},
"report.back-to-item": {
"message": "Powróć do {item, select, project {projektu} version {wersji} user {użytkownika} other {treści}}"
},
"report.body.description": {
"message": "Jeśli to możliwe i istotne, prosimy o dołączenie linków i zdjęć. Puste lub niekompletne zgłoszenia zostaną zamknięte i zignorowane."
},
"report.body.title": {
"message": "Proszę podać dodatkowe informacje dotyczące zgłoszenia"
},
"report.checking": {
"message": "Sprawdzanie {item, select, project {projektu} version {wersji} user {użytkownika} other {treści}}..."
},
"report.could-not-find": {
"message": "Nie znaleziono {item, select, project {projektu} version {wersji} user {użytkownika} other {treści}}"
},
"report.for.violation": {
"message": "Naruszenie <rules-link>zasad Modrinth</rules-link> lub <terms-link>Warunków użytkowania</terms-link>"
},
@@ -2978,15 +2927,9 @@
"report.please-report": {
"message": "Proszę zgłosić:"
},
"report.question.content-id": {
"message": "Podaj identyfikator {item, select, project {tego projektu} version {tej wersji} user {tego użytkownika} other {tych treści}}"
},
"report.question.content-type": {
"message": "Jakiego rodzaju treści zgłaszasz?"
},
"report.question.report-reason": {
"message": "Które z zasad Modrinth {item, select, project {narusza ten projekt} version {narusza ta wersja} user {narusza ten użytkownik} other {naruszają te treści}}?"
},
"report.report-content": {
"message": "Zgłoś treści do moderacji"
},
@@ -3665,21 +3608,12 @@
"settings.billing.interval.month": {
"message": "miesiąc"
},
"settings.billing.interval.monthly": {
"message": "miesięcznie"
},
"settings.billing.interval.quarter": {
"message": "kwartał"
},
"settings.billing.interval.quarterly.adjective": {
"message": "kwartalną"
},
"settings.billing.interval.year": {
"message": "rok"
},
"settings.billing.interval.yearly": {
"message": "rocznie"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Brak reklam na modrinth.com i w Modrinth App"
},
@@ -3764,9 +3698,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} współdzielonych CPU (może osiągać do {bursts} CPU)"
},
@@ -3833,18 +3764,9 @@
"settings.billing.subscription.title": {
"message": "Subskrypcje"
},
"settings.billing.switch.switching-to-interval": {
"message": "Przełączanie na {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Przełącz na {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Miesięcznie będzie cię to kosztować dodatkowe {amount} na rok"
},
"settings.billing.switches-to-billing-on": {
"message": "Przechodzi na rozliczanie {interval} {date}"
},
"settings.billing.update-method": {
"message": "Zaktualizuj metodę"
},
+4 -64
View File
@@ -36,7 +36,7 @@
"message": "Mac"
},
"app-marketing.download.options-title": {
"message": "Opções de transferência"
"message": "Opções de download"
},
"app-marketing.download.terms": {
"message": "Ao baixar o Modrinth App, você concorda com nossos <terms-link>Termos</terms-link> e <privacy-link>Política de Privacidade</privacy-link>."
@@ -710,9 +710,6 @@
"dashboard.collections.empty.no-match-hint": {
"message": "Tente ajustar seus filtros ou termos de busca."
},
"dashboard.collections.label.projects-count": {
"message": "{count, plural, =0 {Nenhum projeto} one {{count} projeto} other {{count} projetos}}"
},
"dashboard.collections.label.search-input": {
"message": "Buscar suas coleções"
},
@@ -1361,15 +1358,6 @@
"discover.install.heading.reset-modpack": {
"message": "Selecionando o pacote de mods para instalar após a redefinição"
},
"discover.seo.description": {
"message": "Busque e explore milhares de {projectType, select, mod {mods} modpack {pacotes de mods} resourcepack {pacotes de recursos} shader {shaders} plugin {plugins} datapack {pacotes de dados} other {projetos}} de Minecraft no Modrinth com resultados de busca instantâneos e precisos. Nossos filtros ajudam você a encontrar rapidamente os melhores {projectType, select, mod {mods} modpack {pacotes de mods} resourcepack {pacotes de recursos} shader {shaders} plugin {plugins} datapack {pacotes de dados} other {projetos}} de Minecraft."
},
"discover.seo.title": {
"message": "Buscar {projectType, select, mod {mods} modpack {pacotes de mods} resourcepack {pacotes de recursos} shader {shaders} plugin {plugins} datapack {pacotes de dados} other {projetos}}"
},
"discover.seo.title-with-query": {
"message": "Buscar {projectType, select, mod {mods} modpack {pacotes de mods} resourcepack {pacotes de recursos} shader {shaders} plugin {plugins} datapack {pacotes de dados} other {projetos}} | {query}"
},
"error.collection.404.list_item.1": {
"message": "Você pode ter digitado incorretamente o URL da coleção."
},
@@ -1881,7 +1869,7 @@
"message": "Erro ao gerar o estado da API durante a compilação."
},
"layout.banner.preview.description": {
"message": "Se você pretendia acessar o site oficial do Modrinth, visite {url}. Essa versão de pré-lançamento é usada pela equipe da Modrinth para fins de teste. Ela foi construída com base em <branch-link>{owner}/{branch}</branch-link> @ {commit}."
"message": "Se você pretendia acessar o site oficial do Modrinth, visite {url}. Essa versão de pré-lançamento é usada pela equipe da Modrinth para fins de teste. Ela foi criada usando {ref}."
},
"layout.banner.preview.title": {
"message": "Esta é uma versão de pré-lançamento do site Modrinth."
@@ -2417,9 +2405,6 @@
"profile.label.collection": {
"message": "Coleção"
},
"profile.label.downloads": {
"message": "{count, plural, =0 {Nenhum download} one {{count} download} other {{count} downloads}}"
},
"profile.label.joined": {
"message": "Entrou"
},
@@ -2438,9 +2423,6 @@
"profile.label.organizations": {
"message": "Organizações"
},
"profile.label.projects": {
"message": "{count, plural, =0 {Nenhum projeto} one {{count} projeto} other {{count} projetos}}"
},
"profile.label.saving": {
"message": "Salvando..."
},
@@ -2450,9 +2432,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} — Baixe os projetos de {username} no Modrinth"
},
"profile.stats.projects-followers": {
"message": "{count, plural, =0 {{count} seguidores} one {<stat>{count}</stat> seguidor} other {<stat>{count}</stat> seguidores}} do projeto"
},
"profile.user-id": {
"message": "ID do usuário: {id}"
},
@@ -2565,10 +2544,10 @@
"message": "Servidor"
},
"project-type.shader.plural": {
"message": "Shaders"
"message": "Sombreadores"
},
"project-type.shader.singular": {
"message": "Shader"
"message": "Sombreador"
},
"project.about.details.created": {
"message": "Criado {date}"
@@ -2921,24 +2900,12 @@
"report.already-reported": {
"message": "Você já denunciou este {title}"
},
"report.already-reported-description": {
"message": "Você já tem uma denúncia aberta para {item, select, project {este projeto} version {esta versão} user {este usuário} other {este conteúdo}}. Se tiver mais informações, você pode adicionar mais detalhes ao seu relatório."
},
"report.back-to-item": {
"message": "Voltar para {item, select, project {o projeto} version {a versão} user {o usuário} other {o conteúdo}}"
},
"report.body.description": {
"message": "Se possível, inclua links e imagens relevantes. Denúncias vazias ou insuficientes serão fechadas e ignoradas."
},
"report.body.title": {
"message": "Forneça mais contexto sobre seu relatório"
},
"report.checking": {
"message": "Checando {item, select, project {projeto} version {versão} user {usuário} other {conteúdo}}..."
},
"report.could-not-find": {
"message": "Não foi possível encontrar {item, select, project {o projeto} version {a versão} user {o usuário} other {o conteúdo}}"
},
"report.for.violation": {
"message": "Violação das <rules-link>regras </rules-link> ou <terms-link>termos de uso</terms-link> do Modrinth"
},
@@ -2978,15 +2945,9 @@
"report.please-report": {
"message": "Denuncie apenas:"
},
"report.question.content-id": {
"message": "Qual é o ID {item, select, project {do projeto} version {da versão} user {do usuário} other {do conteúdo}}?"
},
"report.question.content-type": {
"message": "Que tipo de conteúdo você está denunciando?"
},
"report.question.report-reason": {
"message": "Qual das regras do Modrinth {item, select, project {este projeto} version {esta versão} user {este usuário} other {este conteúdo}} está violando?"
},
"report.report-content": {
"message": "Denunciar conteúdo aos moderadores"
},
@@ -3665,21 +3626,12 @@
"settings.billing.interval.month": {
"message": "mês"
},
"settings.billing.interval.monthly": {
"message": "mensal"
},
"settings.billing.interval.quarter": {
"message": "trimestre"
},
"settings.billing.interval.quarterly.adjective": {
"message": "trimestral"
},
"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"
},
@@ -3764,9 +3716,6 @@
"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)"
},
@@ -3833,18 +3782,9 @@
"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"
},
@@ -434,21 +434,9 @@
"create.collection.title": {
"message": "Criar uma coleção"
},
"create.limit-alert.approaching-limit": {
"message": "A alcançar o limite de {typePlural} ({current}/{max})"
},
"create.limit-alert.approaching-limit-description": {
"message": "Estás prestes a atingir o limite de {typePlural}, por favor contacta o suporte se precisas de mais do que {max} {typePlural}."
},
"create.limit-alert.contact-support": {
"message": "Contacta o suporte"
},
"create.limit-alert.limit-reached": {
"message": "limite de {typePlural} atingido"
},
"create.limit-alert.limit-reached-description": {
"message": "Atingiste o teu limite de {typePlural} de {max}. Por favor contacta o suporte para aumentar o teu limite."
},
"create.limit-alert.type-collection": {
"message": "coleção"
},
@@ -1229,9 +1217,6 @@
"hosting-marketing.faq.location": {
"message": "Onde estão localizados os servidores Modrinth Hosting? Posso escolher uma região?"
},
"hosting-marketing.faq.location.answer": {
"message": "Temos servidores disponíveis na América do Norte, Europa e Ásia Sudeste, que podes escolher no momento da compra. Mais regiões serão adicionadas no futuro! Se quiseres trocar a tua região, entra em contacto com o suporte."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Que versões de Minecraft e loaders podem ser utilizados?"
},
@@ -2471,24 +2456,12 @@
"report.already-reported": {
"message": "Já denunciaste {title}"
},
"report.already-reported-description": {
"message": "Já tens uma denúnia aberta para est{item, select,project {e projeto} version {a versão} user {e utilizador} other {e conteúdo}}. Podes adicionar mais detalhes à tua denúncia se tiveres mais informações."
},
"report.back-to-item": {
"message": "Voltar para {item, select,project {projeto} version {versão} user {utilizador} other {conteúdo}}"
},
"report.body.description": {
"message": "Inclui links e imagens se possível e relevante. Denúncias vazias ou insuficientes vão ser fechadas e ignoradas."
},
"report.body.title": {
"message": "Por favor fornece contexto adicional sobre a tua denúncia"
},
"report.checking": {
"message": "Verificando {item, select,project {projeto} version {versão} user {utilizador} other {conteúdo}}..."
},
"report.could-not-find": {
"message": "Não foi possível encontrar {item, select,project {o projeto} version {a versão} user {o utilizador} other {o conteúdo}}"
},
"report.for.violation": {
"message": "Violação das <rules-link>Regras</rules-link> ou <terms-link>Termos de Uso</terms-link> do Modrinth"
},
@@ -2528,15 +2501,9 @@
"report.please-report": {
"message": "Por favor denuncia:"
},
"report.question.content-id": {
"message": "Qual é o ID d{item, select,project {o projeto} version {a versão} user {o utilizador} other {o conteúdo}}?"
},
"report.question.content-type": {
"message": "Que tipo de conteúdo estás a denunciar?"
},
"report.question.report-reason": {
"message": "Qual das regras do Modrinth est{item, select,project {e projeto} version {a versão} user {e utilizador} other {e conteúdo}} está a violar?"
},
"report.report-content": {
"message": "Denunciar conteúdo aos moderadores"
},
@@ -3212,15 +3179,9 @@
"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 Modrinth App"
},
@@ -3305,9 +3266,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared} CPUs partilhadas (Reforço até {bursts} CPUs)"
},
@@ -3368,12 +3326,6 @@
"settings.billing.subscription.title": {
"message": "Subscrições"
},
"settings.billing.switch.switching-to-interval": {
"message": "Alterando para {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Alterar para {interval}"
},
"settings.billing.update-method": {
"message": "Atualizar método"
},
@@ -1331,9 +1331,6 @@
"project-member-header.invitation-title": {
"message": "Invitație de a te alătura proiectului"
},
"project-member-header.invitation-with-role": {
"message": "Ai fost invitat să devii membru al acestui proiect cu rolul de '{role}''."
},
"project-member-header.success-decline": {
"message": "Ai refuzat invitația în echipă"
},
+17 -98
View File
@@ -408,25 +408,25 @@
"message": "{name} — Коллекция"
},
"conversation-thread.action.add-private-note": {
"message": "Добавить примечание для себя"
"message": "Добавить приватную заметку"
},
"conversation-thread.action.approve": {
"message": "Одобрить"
},
"conversation-thread.action.approve-with-reply": {
"message": "Одобрить с ответом"
"message": "Одобрить с ответом"
},
"conversation-thread.action.close-thread": {
"message": "Закрыть ветку"
},
"conversation-thread.action.close-with-reply": {
"message": "Закрыть с ответом"
"message": "Закрыть с ответом"
},
"conversation-thread.action.reject": {
"message": "Отклонить"
},
"conversation-thread.action.reject-with-reply": {
"message": "Отклонить с ответом"
"message": "Отклонить с ответом"
},
"conversation-thread.action.reopen-thread": {
"message": "Возобновить ветку"
@@ -435,34 +435,34 @@
"message": "Ответить"
},
"conversation-thread.action.reply-to-thread": {
"message": "Ответить на ветку"
"message": "Ответить в ветке"
},
"conversation-thread.action.resubmit-for-review": {
"message": "Запросить перепроверку"
"message": "Отправить на перепроверку"
},
"conversation-thread.action.resubmit-for-review-with-reply": {
"message": "Запросить перепроверку с ответом"
"message": "Отправить на перепроверку с ответом"
},
"conversation-thread.action.send": {
"message": "Отправить"
},
"conversation-thread.action.send-to-review": {
"message": "Отправить на проверку"
"message": "Отправить на проверку"
},
"conversation-thread.action.send-to-review-with-reply": {
"message": "Отправить на проверку с ответом"
"message": "Отправить на проверку с ответом"
},
"conversation-thread.action.set-to-draft": {
"message": "Установить в черновик"
"message": "Установить в черновик"
},
"conversation-thread.action.set-to-draft-with-reply": {
"message": "Установить в черновик с ответом"
"message": "Установить в черновик с ответом"
},
"conversation-thread.action.withhold": {
"message": "Удержать"
},
"conversation-thread.action.withhold-with-reply": {
"message": "Удержать с ответом"
"message": "Удержать с ответом"
},
"conversation-thread.closed-thread.description": {
"message": "Эта ветка закрыта, новые сообщения в неё нельзя отправить."
@@ -477,10 +477,10 @@
"message": "Ошибка отправки сообщения"
},
"conversation-thread.reply-editor.placeholder.reply": {
"message": "Ответить в ветку..."
"message": "Ответьте в ветке..."
},
"conversation-thread.reply-editor.placeholder.send": {
"message": "Отправить сообщение..."
"message": "Отправьте сообщение..."
},
"conversation-thread.reply-modal.confirmation.description": {
"message": "Подтвердить, что модераторы не проводят активный просмотр"
@@ -492,7 +492,7 @@
"message": "Ваш проект уже одобрен. Из-за этого модерация не проводит активный просмотр этой ветки. Однако, если возникнет проблема с вашим проектом, она сможет увидеть ваше сообщение."
},
"conversation-thread.reply-modal.header": {
"message": "Ответить на ветку"
"message": "Ответ в ветке"
},
"conversation-thread.reply-modal.help-center-note": {
"message": "Если вам нужно выйти на контакт с командой модерации, используйте <help-center-link>справочный центр Modrinth</help-center-link> и нажмите на синий значок в правом нижнем углу для связи с поддержкой."
@@ -548,9 +548,6 @@
"create.limit-alert.approaching-limit": {
"message": "Почти исчерпан лимит {type} ({current}/{max})"
},
"create.limit-alert.approaching-limit-description": {
"message": "Почти достигнут лимит в {max} {type}. Увеличьте его, обратившись в поддержку."
},
"create.limit-alert.contact-support": {
"message": "Связаться с поддержкой"
},
@@ -686,9 +683,6 @@
"dashboard.affiliate-links.search": {
"message": "Поиск ссылок..."
},
"dashboard.analytics.from-projects": {
"message": "с {count, plural, one {# проекта} other {# проектов}}"
},
"dashboard.analytics.total-downloads": {
"message": "Всего скачиваний"
},
@@ -710,9 +704,6 @@
"dashboard.collections.empty.no-match-hint": {
"message": "Попробуйте изменить фильтры или запрос."
},
"dashboard.collections.label.projects-count": {
"message": "{count} {countPlural, plural, one {проект} few {проекта} other {проектов}}"
},
"dashboard.collections.label.search-input": {
"message": "Поиск по коллекциям"
},
@@ -995,9 +986,6 @@
"dashboard.notifications.link.view-history": {
"message": "История уведомлений"
},
"dashboard.notifications.link.view-more": {
"message": "Посмотреть ещё {extraNotifs, number}"
},
"dashboard.organizations.button.create": {
"message": "Создать организацию"
},
@@ -1007,9 +995,6 @@
"dashboard.organizations.error.fetch": {
"message": "Не удалось получить организации"
},
"dashboard.organizations.member-count": {
"message": "{count, plural, one {# участник} few {# участника} other {# участников}}"
},
"dashboard.organizations.title": {
"message": "Организации"
},
@@ -1361,15 +1346,6 @@
"discover.install.heading.reset-modpack": {
"message": "Выбор сборки модов для установки после сброса"
},
"discover.seo.description": {
"message": "Тысячи {projectType, select, mod {модов} modpack {сборок} resourcepack {наборов ресурсов} shader {шейдеров} plugin {плагинов} datapack {наборов данных} other {проектов}} для Minecraft на Modrinth. Мгновенный точный поиск и удобные фильтры помогут быстро найти лучшие {projectType, select, mod {моды} modpack {сборки} resourcepack {наборы ресурсов} shader {шейдеры} plugin {плагины} datapack {наборы данных} other {проекты}} для Minecraft."
},
"discover.seo.title": {
"message": "Поиск {projectType, select, mod {модов} modpack {сборок} resourcepack {наборов ресурсов} shader {шейдеров} plugin {плагинов} datapack {наборов данных} other {проектов}}"
},
"discover.seo.title-with-query": {
"message": "Поиск {projectType, select, mod {модов} modpack {сборок} resourcepack {наборов ресурсов} shader {шейдеров} plugin {плагинов} datapack {наборов данных} other {проектов}} | {query}"
},
"error.collection.404.list_item.1": {
"message": "В адресе коллекции может быть ошибка."
},
@@ -1881,7 +1857,7 @@
"message": "Ошибка генерации состояния от API во время сборки."
},
"layout.banner.preview.description": {
"message": "Официальный сайт Modrinth доступен по адресу {url}. Текущая предварительная версия предназначена для тестирования командой Modrinth и собрана из <branch-link>{owner}/{branch}</branch-link> @ {commit}."
"message": "Официальный сайт Modrinth доступен по адресу {url}. Текущая предварительная версия предназначена для тестирования командой Modrinth и собрана из {ref}."
},
"layout.banner.preview.title": {
"message": "Это предварительная версия сайта Modrinth."
@@ -2417,9 +2393,6 @@
"profile.label.collection": {
"message": "Коллекция"
},
"profile.label.downloads": {
"message": "{count} {countPlural, plural, one {скачивание} few {скачивания} other {скачиваний}}"
},
"profile.label.joined": {
"message": "Регистрация:"
},
@@ -2438,9 +2411,6 @@
"profile.label.organizations": {
"message": "Организации"
},
"profile.label.projects": {
"message": "{count} {countPlural, plural, one {проект} few {проекта} other {проектов}}"
},
"profile.label.saving": {
"message": "Сохранение..."
},
@@ -2450,9 +2420,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} — Скачать проекты {username} на Modrinth"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> подписчик} few {<stat>{count}</stat> подписчика} other {<stat>{count}</stat> подписчиков}} у проектов"
},
"profile.user-id": {
"message": "ID пользователя: {id}"
},
@@ -2496,7 +2463,7 @@
"message": "Запросите проверку"
},
"project-moderation-nags.submit-for-review-button": {
"message": "Отправить на проверку"
"message": "Отправить на проверку"
},
"project-moderation-nags.submit-for-review-desc": {
"message": "Проект сейчас виден только участникам. Для публикации он должен пройти проверку модераторами."
@@ -2897,12 +2864,6 @@
"project.settings.visit-dashboard": {
"message": "Управление проектами"
},
"project.stats.downloads-label": {
"message": "скачивани{count, plural, one {е} few {я} other {й}}"
},
"project.stats.followers-label": {
"message": "подписчик{count, plural, one {} few {а} other {ов}}"
},
"project.status.archived.message": {
"message": "{title} помещён в архив. {title} больше не будет получать обновления, если только автор не решит разархивировать проект."
},
@@ -2921,24 +2882,12 @@
"report.already-reported": {
"message": "Вы уже пожалова­лись на {title}"
},
"report.already-reported-description": {
"message": "Жалоба на {item, select, project {этот проект} version {эту версию} user {этого пользователя} other {этот контент}} уже отправлена. Если у вас есть дополнительная информация, добавьте её к жалобе."
},
"report.back-to-item": {
"message": "Вернуться к {item, select, project {проекту} version {версии} user {пользователю} other {контенту}}"
},
"report.body.description": {
"message": "При желании прикрепите ссылки и изображения. Неполные жалобы закрываются без рассмотрения."
},
"report.body.title": {
"message": "Добавьте подробности к жалобе"
},
"report.checking": {
"message": "Поиск {item, select, project {проекта} version {версии} user {пользователя} other {контента}}..."
},
"report.could-not-find": {
"message": "Не удалось найти {item, select, project {проект} version {версию} user {пользователя} other {контент}}"
},
"report.for.violation": {
"message": "На нарушение наших <rules-link>правил</rules-link> или <terms-link>условий</terms-link>"
},
@@ -2978,15 +2927,9 @@
"report.please-report": {
"message": "На что жаловаться"
},
"report.question.content-id": {
"message": "Какой ID у {item, select, project {проекта} version {версии} user {пользователя} other {контента}}?"
},
"report.question.content-type": {
"message": "На какой тип контента вы жалуетесь?"
},
"report.question.report-reason": {
"message": "Какое правило Modrinth нарушено {item, select, project {этим проектом} version {этой версией} user {этим пользователем} other {этим контентом}}?"
},
"report.report-content": {
"message": "Жалоба модерато­рам на контент"
},
@@ -3665,21 +3608,12 @@
"settings.billing.interval.month": {
"message": "месяц"
},
"settings.billing.interval.monthly": {
"message": "ежемесячно"
},
"settings.billing.interval.quarter": {
"message": "3 месяца"
},
"settings.billing.interval.quarterly.adjective": {
"message": "3 месяца"
},
"settings.billing.interval.year": {
"message": "год"
},
"settings.billing.interval.yearly": {
"message": "ежегодно"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Отсутствие рекламы на сайте и в приложении"
},
@@ -3764,12 +3698,6 @@
"settings.billing.price.per-interval": {
"message": "{price} в {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.cpu": {
"message": "{shared, plural, one {# разделяемый} other {# разделяемых}} CPU (рост до {bursts} CPU)"
},
"settings.billing.pyro.linked-server.not-found": {
"message": "Привязанный сервер не найден. Возможных причин несколько: сервер куплен только что — подождите, подготовка занимает до часа; сервер куплен давно — вероятно, его уже приостановили. Если что‑то не так, свяжитесь с поддержкой Modrinth, указав следующие данные:"
},
@@ -3833,18 +3761,9 @@
"settings.billing.subscription.title": {
"message": "Подписки"
},
"settings.billing.switch.switching-to-interval": {
"message": "Переход на {interval, select, ежемесячно {месяц} ежегодно {год} other {{interval}}}"
},
"settings.billing.switch.to-interval": {
"message": "Перейти на {interval, select, ежемесячно {месяц} ежегодно {год} other {{interval}}}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Ежемесячная оплата обойдётся на {amount} в год дороже"
},
"settings.billing.switches-to-billing-on": {
"message": "{interval, select, ежемесячно {Ежемесячная оплата} ежегодно {Ежегодная оплата} 3 месяца {Оплата раз в 3 месяца} other {{interval} оплата}} с {date}"
},
"settings.billing.update-method": {
"message": "Обновить способ"
},
@@ -515,9 +515,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Preuzmite projekte korisnika {username} na Modrinthu"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> pratilac projekta} few {<stat>{count}</stat> pratioca projekta} other {<stat>{count}</stat> pratilaca projekta}}"
},
"profile.user-id": {
"message": "ID korisnika: {id}"
},
@@ -614,12 +611,6 @@
"project.moderation.title": {
"message": "Moderacija"
},
"project.stats.downloads-label": {
"message": "{count, plural, one {{count} preuzimanje} other {{count} preuzimanja}}"
},
"project.stats.followers-label": {
"message": "{count, plural, one {{count} pratilac} few {{count} pratioca} other {{count} pratilaca}}"
},
"project.versions.title": {
"message": "Verzije"
},
@@ -1184,9 +1184,6 @@
"hosting-marketing.faq.location": {
"message": "Var finns Modrinth Hostings servrar? Kan jag välja region?"
},
"hosting-marketing.faq.location.answer": {
"message": "Vi har för närvarande servrar tillgängliga i Nordamerika, Europa och Sydostasien som du kan välja mellan vid köpet. Fler regioner kommer att läggas till i framtiden! Om du vill byta region, vänligen kontakta supporten."
},
"hosting-marketing.faq.versions-loaders": {
"message": "Vilka Minecraft versioner och loaders kan användas?"
},
@@ -2261,9 +2258,6 @@
"report.already-reported": {
"message": "Du har redan rapporterat {title}"
},
"report.already-reported-description": {
"message": "Du har redan en öppen rapport för {item, select, project {detta projekt} version {denna version} user {denna användare} other {detta innehåll}}. Du kan lägga till mer detaljer till din rapport om du har mer information att lägga till."
},
"report.body.title": {
"message": "Vänligen ge oss mer kontext om din rapport"
},
@@ -2786,21 +2780,12 @@
"settings.billing.interval.month": {
"message": "månad"
},
"settings.billing.interval.monthly": {
"message": "månatligen"
},
"settings.billing.interval.quarter": {
"message": "kvartal"
},
"settings.billing.interval.quarterly.adjective": {
"message": "kvartalsvis"
},
"settings.billing.interval.year": {
"message": "år"
},
"settings.billing.interval.yearly": {
"message": "årligen"
},
"settings.billing.midas.benefits.ad-free": {
"message": "Annonsfritt surfande på modrinth.com och Modrinth App"
},
@@ -2885,9 +2870,6 @@
"settings.billing.price.per-interval": {
"message": "{price} / {interval}"
},
"settings.billing.price.slash-interval": {
"message": "/{interval}"
},
"settings.billing.pyro.linked-server.server-id": {
"message": "Server ID: {id}"
},
@@ -2924,18 +2906,9 @@
"settings.billing.subscription.title": {
"message": "Prenumerationer"
},
"settings.billing.switch.switching-to-interval": {
"message": "Ändrar till {interval}"
},
"settings.billing.switch.to-interval": {
"message": "Ändra till {interval}"
},
"settings.billing.switch.tooltip.monthly-additional-per-year": {
"message": "Månatlig betalning kommer kosta dig ytterligare {amount} per år"
},
"settings.billing.switches-to-billing-on": {
"message": "Ändrar till {interval} betalning på {date}"
},
"settings.billing.update-method": {
"message": "Uppdatera metod"
},

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