Merge tag 'v0.10.20' into beta

This commit is contained in:
2025-11-27 05:08:45 +03:00
533 changed files with 42481 additions and 8973 deletions

View File

@@ -6,31 +6,21 @@
</NuxtLayout>
</template>
<script setup lang="ts">
import { NotificationPanel, provideNotificationManager } from '@modrinth/ui'
import { provideApi } from '@modrinth/ui/src/providers/api.ts'
import { RestModrinthApi } from '@modrinth/utils'
import { NotificationPanel, provideModrinthClient, provideNotificationManager } from '@modrinth/ui'
import ModrinthLoadingIndicator from '~/components/ui/modrinth-loading-indicator.ts'
import { createModrinthClient } from '~/helpers/api.ts'
import { FrontendNotificationManager } from '~/providers/frontend-notifications.ts'
import { FrontendNotificationManager } from './providers/frontend-notifications.ts'
const auth = await useAuth()
const config = useRuntimeConfig()
provideNotificationManager(new FrontendNotificationManager())
provideApi(
new RestModrinthApi((url: string, options?: object) => {
const match = url.match(/^\/v(\d+)\/(.+)$/)
if (match) {
const apiVersion = Number(match[1])
const path = match[2]
return useBaseFetch(path, {
...options,
apiVersion,
}) as Promise<Response>
} else {
throw new Error('Invalid format')
}
}),
)
const client = createModrinthClient(auth, {
apiBaseUrl: config.public.apiBaseUrl.replace('/v2/', '/'),
archonBaseUrl: config.public.pyroBaseUrl.replace('/v2/', '/'),
rateLimitKey: config.rateLimitKey,
})
provideModrinthClient(client)
</script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -1290,3 +1290,7 @@ svg.inline-svg {
}
}
}
.card-shadow {
box-shadow: var(--shadow-card);
}

View File

@@ -37,6 +37,7 @@ html {
--icon-32: 2rem;
interpolate-size: allow-keywords;
scrollbar-gutter: stable;
}
.light-mode {
@@ -89,7 +90,7 @@ html {
--color-hr: var(--color-text);
--color-table-border: #dfe2e5;
--color-table-alternate-row: #f2f4f7;
--color-table-alternate-row: #f0f1f2;
--landing-maze-bg: url('https://cdn.modrinth.com/landing-new/landing-light.webp');
--landing-maze-gradient-bg: url('https://cdn.modrinth.com/landing-new/landing-lower-light.webp');

View File

@@ -53,12 +53,15 @@
</svg>
</template>
<script setup>
<script setup lang="ts">
const loading = useLoading()
const config = useRuntimeConfig()
const flags = useFeatureFlags()
const api = computed(() => {
if (flags.value.demoMode) return 'prod'
const apiUrl = config.public.apiBaseUrl
if (apiUrl.startsWith('https://api.modrinth.com')) {
return 'prod'

View File

@@ -1,151 +0,0 @@
<template>
<div
class="checkbox-outer button-within"
:class="{ disabled, checked: modelValue }"
role="presentation"
@click="toggle"
>
<button
class="checkbox"
role="checkbox"
:disabled="disabled"
:class="{ checked: modelValue, collapsing: collapsingToggleStyle }"
:aria-label="description ?? label"
:aria-checked="modelValue"
>
<CheckIcon v-if="modelValue && !collapsingToggleStyle" aria-hidden="true" />
<DropdownIcon v-else-if="collapsingToggleStyle" aria-hidden="true" />
</button>
<!-- aria-hidden is set so screenreaders only use the <button>'s aria-label -->
<p v-if="label" aria-hidden="true">
{{ label }}
</p>
<slot v-else />
</div>
</template>
<script>
import { CheckIcon, DropdownIcon } from '@modrinth/assets'
export default {
components: {
CheckIcon,
DropdownIcon,
},
props: {
label: {
type: String,
required: false,
default: '',
},
disabled: {
type: Boolean,
required: false,
default: false,
},
description: {
type: String,
required: false,
default: null,
},
modelValue: Boolean,
clickEvent: {
type: Function,
required: false,
default: () => {},
},
collapsingToggleStyle: {
type: Boolean,
required: false,
default: false,
},
},
emits: ['update:modelValue'],
methods: {
toggle() {
if (!this.disabled) {
this.$emit('update:modelValue', !this.modelValue)
}
},
},
}
</script>
<style lang="scss" scoped>
.checkbox-outer {
display: flex;
align-items: center;
cursor: pointer;
p {
user-select: none;
padding: 0.2rem 0;
margin: 0;
}
&.disabled {
cursor: not-allowed;
}
&.checked {
outline: 2px solid transparent;
outline-offset: 4px;
border-radius: 0.25rem;
}
}
.checkbox {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
min-width: 1rem;
min-height: 1rem;
padding: 0;
margin: 0 0.5rem 0 0;
color: var(--color-button-text);
background-color: var(--color-button-bg);
border-radius: var(--size-rounded-control);
box-shadow:
var(--shadow-inset-sm),
0 0 0 0 transparent;
&.checked {
background-color: var(--color-brand);
}
svg {
color: var(--color-accent-contrast, var(--color-brand-inverted));
stroke-width: 0.2rem;
height: 0.8rem;
width: 0.8rem;
flex-shrink: 0;
}
&.collapsing {
background-color: transparent !important;
box-shadow: none;
svg {
color: inherit;
height: 1rem;
width: 1rem;
transition: transform 0.25s ease-in-out;
}
&.checked {
svg {
transform: rotate(180deg);
}
}
}
&:disabled {
box-shadow: none;
cursor: not-allowed;
}
}
</style>

View File

@@ -90,7 +90,7 @@ defineProps({
},
})
const tags = useTags()
const tags = useGeneratedState()
</script>
<style lang="scss" scoped>
.environment {

View File

@@ -1,32 +1,155 @@
<template>
<nav>
<ul>
<slot />
<nav :aria-label="ariaLabel" class="w-full">
<ul
class="card-shadow m-0 flex list-none flex-col items-start gap-1.5 rounded-2xl bg-bg-raised p-4"
>
<slot v-if="hasSlotContent" />
<template v-else>
<li v-for="(item, idx) in filteredItems" :key="getKey(item, idx)" class="contents">
<hr v-if="isSeparator(item)" class="my-1 w-full border-t border-solid" />
<div
v-else-if="isHeading(item)"
class="px-4 pb-1 pt-2 text-xs font-bold uppercase tracking-wide text-secondary"
>
{{ item.label }}
</div>
<NuxtLink
v-else-if="item.link ?? item.to"
:to="(item.link ?? item.to) as string"
class="nav-item inline-flex w-full cursor-pointer items-center gap-2 text-nowrap rounded-xl border-none bg-transparent px-4 py-2.5 text-left text-base font-semibold leading-tight text-button-text transition-all hover:bg-button-bg hover:text-contrast active:scale-[0.97]"
:class="{ 'is-active': isActive(item as NavStackLinkItem) }"
>
<component
:is="item.icon"
v-if="item.icon"
aria-hidden="true"
class="h-5 w-5 shrink-0"
/>
<span class="text-contrast">{{ item.label }}</span>
<span
v-if="item.badge != null"
class="rounded-full bg-brand-highlight px-2 text-sm font-bold text-brand"
>
{{ String(item.badge) }}
</span>
<span v-if="item.chevron" class="ml-auto"><ChevronRightIcon /></span>
</NuxtLink>
<button
v-else-if="item.action"
class="nav-item inline-flex w-full cursor-pointer items-center gap-2 text-nowrap rounded-xl border-none bg-transparent px-4 py-2.5 text-left text-base font-semibold leading-tight text-button-text transition-all hover:bg-button-bg hover:text-contrast active:scale-[0.97]"
:class="{ 'danger-button': item.danger }"
@click="item.action"
>
<component
:is="item.icon"
v-if="item.icon"
aria-hidden="true"
class="h-5 w-5 shrink-0"
/>
<span class="text-contrast">{{ item.label }}</span>
<span
v-if="item.badge != null"
class="rounded-full bg-brand-highlight px-2 text-sm font-bold text-brand"
>
{{ String(item.badge) }}
</span>
</button>
<span v-else>You frog. 🐸</span>
</li>
</template>
</ul>
</nav>
</template>
<script>
export default {}
<script setup lang="ts">
import { ChevronRightIcon } from '@modrinth/assets'
import { type Component, computed, useSlots } from 'vue'
type NavStackBaseItem = {
label: string
icon?: Component | string
badge?: string | number | null
chevron?: boolean
danger?: boolean
}
type NavStackLinkItem = NavStackBaseItem & {
type?: 'item'
link?: string | null
to?: string | null
action?: (() => void) | null
matchNested?: boolean
}
type NavStackSeparator = { type: 'separator' }
type NavStackHeading = { type: 'heading'; label: string }
export type NavStackEntry = (NavStackLinkItem | NavStackSeparator | NavStackHeading) & {
shown?: boolean
}
const props = defineProps<{
items?: NavStackEntry[]
ariaLabel?: string
}>()
const ariaLabel = computed(() => props.ariaLabel ?? 'Section navigation')
const route = useRoute()
const slots = useSlots()
const hasSlotContent = computed(() => {
const content = slots.default?.()
return !!(content && content.length)
})
function isSeparator(item: NavStackEntry): item is NavStackSeparator {
return (item as any).type === 'separator'
}
function isHeading(item: NavStackEntry): item is NavStackHeading {
return (item as any).type === 'heading'
}
function getKey(item: NavStackEntry, idx: number) {
if (isSeparator(item)) return `sep-${idx}`
if (isHeading(item)) return `head-${item.label}-${idx}`
const link = (item as NavStackLinkItem).link ?? (item as NavStackLinkItem).to
return link ? `link-${link}` : `action-${(item as NavStackLinkItem).label}-${idx}`
}
function isActive(item: NavStackLinkItem): boolean {
const link = item.link ?? item.to
if (!link) return false
const currentPath = route.path
if (item.matchNested) {
return currentPath.startsWith(link)
}
return currentPath === link
}
const filteredItems = computed(() => props.items?.filter((x) => x.shown === undefined || x.shown))
</script>
<style lang="scss" scoped>
ul {
display: flex;
flex-direction: column;
grid-gap: var(--spacing-card-xs);
flex-wrap: wrap;
list-style-type: none;
margin: 0;
padding: 0;
> :first-child {
margin-top: 0;
}
}
li {
display: unset;
text-align: unset;
}
.router-link-exact-active.nav-item,
.nav-item.is-active {
background: var(--color-button-bg-selected);
color: var(--color-button-text-selected);
}
.router-link-exact-active.nav-item .text-contrast,
.nav-item.is-active .text-contrast {
color: var(--color-button-text-selected);
}
</style>

View File

@@ -1,64 +0,0 @@
<template>
<NuxtLink v-if="link !== null" :to="link" class="nav-item">
<slot />
<span>{{ label }}</span>
<span v-if="badge" class="rounded-full bg-brand-highlight px-2 text-sm font-bold text-brand">{{
badge
}}</span>
<span v-if="chevron" class="ml-auto"><ChevronRightIcon /></span>
</NuxtLink>
<button v-else-if="action" class="nav-item" :class="{ 'danger-button': danger }" @click="action">
<slot />
<span>{{ label }}</span>
<span v-if="badge" class="rounded-full bg-brand-highlight px-2 text-sm font-bold text-brand">{{
badge
}}</span>
</button>
<span v-else>i forgor 💀</span>
</template>
<script>
import { ChevronRightIcon } from '@modrinth/assets'
export default {
components: {
ChevronRightIcon,
},
props: {
link: {
default: null,
type: String,
},
action: {
default: null,
type: Function,
},
label: {
required: true,
type: String,
},
badge: {
default: null,
type: String,
},
chevron: {
default: false,
type: Boolean,
},
danger: {
default: false,
type: Boolean,
},
},
}
</script>
<style lang="scss" scoped>
.nav-item {
@apply flex w-full cursor-pointer items-center gap-2 text-nowrap rounded-xl border-none bg-transparent px-4 py-2 text-left font-semibold text-button-text transition-all hover:bg-button-bg hover:text-contrast active:scale-[0.97];
}
.router-link-exact-active.nav-item {
@apply bg-button-bgSelected text-button-textSelected;
}
</style>

View File

@@ -376,7 +376,7 @@ const props = defineProps({
})
const flags = useFeatureFlags()
const tags = useTags()
const tags = useGeneratedState()
const type = computed(() =>
!props.notification.body || props.notification.body.type === 'legacy_markdown'

View File

@@ -152,7 +152,7 @@ const onSubmitHandler = () => {
border-radius: var(--radius-md);
overflow: hidden;
margin-top: var(--gap-md);
border: 1px solid var(--color-button-bg);
border: 1px solid var(--color-divider);
background-color: var(--color-raised-bg);
.table-row {

View File

@@ -212,7 +212,7 @@ export default {
},
},
setup() {
const tags = useTags()
const tags = useGeneratedState()
const formatRelativeTime = useRelativeTime()
return { tags, formatRelativeTime }

View File

@@ -0,0 +1,264 @@
<template>
<NewModal ref="modal">
<template #title>
<span class="text-lg font-extrabold text-contrast">Batch credit</span>
</template>
<div class="flex w-[500px] max-w-[90vw] flex-col gap-6">
<div class="flex flex-col gap-2">
<label class="flex flex-col gap-1">
<span class="text-lg font-semibold text-contrast"> Type </span>
<span>Select target to credit.</span>
</label>
<Combobox
v-model="mode"
:options="modeOptions"
placeholder="Select type"
class="max-w-[8rem]"
/>
</div>
<div class="flex flex-col gap-2">
<label for="days" class="flex flex-col gap-1">
<span class="text-lg font-semibold text-contrast"> Days to credit </span>
</label>
<input
id="days"
v-model.number="days"
class="w-32"
type="number"
min="1"
autocomplete="off"
/>
</div>
<div v-if="mode === 'nodes'" class="flex flex-col gap-3">
<div class="flex flex-col gap-2">
<label for="node-input" class="flex flex-col gap-1">
<span class="text-lg font-semibold text-contrast"> Node hostnames </span>
</label>
<div class="flex items-center gap-2">
<input
id="node-input"
v-model="nodeInput"
class="w-32"
type="text"
autocomplete="off"
/>
<ButtonStyled color="blue" color-fill="text">
<button class="shrink-0" @click="addNode">
<PlusIcon />
Add
</button>
</ButtonStyled>
</div>
<div v-if="selectedNodes.length" class="mt-1 flex flex-wrap gap-2">
<TagItem v-for="h in selectedNodes" :key="`node-${h}`" :action="() => removeNode(h)">
<XIcon />
{{ h }}
</TagItem>
</div>
</div>
</div>
<div v-else class="flex flex-col gap-3">
<div class="flex flex-col gap-2">
<label for="region-select" class="flex flex-col gap-1">
<span class="text-lg font-semibold text-contrast"> Region </span>
<span>This will credit all active servers in the region.</span>
</label>
<Combobox
v-model="selectedRegion"
:options="regions"
placeholder="Select region"
class="max-w-[24rem]"
/>
</div>
</div>
<div class="between flex items-center gap-4">
<label for="send-email-batch" class="flex flex-col gap-1">
<span class="text-lg font-semibold text-contrast"> Send email </span>
</label>
<Toggle id="send-email-batch" v-model="sendEmail" />
</div>
<div v-if="sendEmail" class="flex flex-col gap-2">
<label for="message-batch" class="flex flex-col gap-1">
<span class="text-lg font-semibold text-contrast"> Customize Email </span>
<span>
Unless a particularly bad or out of the ordinary event happened, keep this to the
default
</span>
</label>
<div
class="text-muted flex flex-col gap-2 rounded-lg border border-divider bg-button-bg p-4"
>
<span>Hi {user.name},</span>
<div class="textarea-wrapper">
<textarea
id="message-batch"
v-model="message"
rows="3"
class="w-full overflow-hidden !bg-surface-3"
/>
</div>
<span>
To make up for it, we've added {{ days }} day{{ pluralize(days) }} to your Modrinth
Servers subscription.
</span>
<span>
Your next charge was scheduled for {credit.previous_due} and will now be on
{credit.next_due}.
</span>
</div>
</div>
<div class="flex gap-2">
<ButtonStyled color="brand">
<button :disabled="applyDisabled" @click="apply">
<CheckIcon aria-hidden="true" />
Apply credits
</button>
</ButtonStyled>
<ButtonStyled>
<button @click="modal?.hide?.()">
<XIcon aria-hidden="true" />
Cancel
</button>
</ButtonStyled>
</div>
</div>
</NewModal>
</template>
<script setup lang="ts">
import { CheckIcon, PlusIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
Combobox,
injectNotificationManager,
NewModal,
TagItem,
Toggle,
} from '@modrinth/ui'
import { DEFAULT_CREDIT_EMAIL_MESSAGE } from '@modrinth/utils/utils.ts'
import { computed, ref } from 'vue'
import { useBaseFetch } from '#imports'
import { useServersFetch } from '~/composables/servers/servers-fetch.ts'
const { addNotification } = injectNotificationManager()
const modal = ref<InstanceType<typeof NewModal>>()
const days = ref(1)
const sendEmail = ref(true)
const message = ref('')
const modeOptions = [
{ value: 'nodes', label: 'Nodes' },
{ value: 'region', label: 'Region' },
]
const mode = ref<string>('nodes')
const nodeInput = ref('')
const selectedNodes = ref<string[]>([])
type RegionOpt = { value: string; label: string }
const regions = ref<RegionOpt[]>([])
const selectedRegion = ref<string | null>(null)
const nodeHostnames = ref<string[]>([])
function show(event?: Event) {
void ensureOverview()
message.value = DEFAULT_CREDIT_EMAIL_MESSAGE
modal.value?.show(event)
}
function hide() {
modal.value?.hide()
}
function addNode() {
const v = nodeInput.value.trim()
if (!v) return
if (!nodeHostnames.value.includes(v)) {
addNotification({
title: 'Unknown node',
text: "This hostname doesn't exist",
type: 'error',
})
return
}
if (!selectedNodes.value.includes(v)) selectedNodes.value.push(v)
nodeInput.value = ''
}
function removeNode(v: string) {
selectedNodes.value = selectedNodes.value.filter((x) => x !== v)
}
const applyDisabled = computed(() => {
if (days.value < 1) return true
if (mode.value === 'nodes') return selectedNodes.value.length === 0
return !selectedRegion.value
})
async function ensureOverview() {
if (regions.value.length || nodeHostnames.value.length) return
try {
const data = await useServersFetch<any>('/nodes/overview', { version: 'internal' })
regions.value = (data.regions || []).map((r: any) => ({
value: r.key,
label: `${r.display_name} (${r.key})`,
}))
nodeHostnames.value = data.node_hostnames || []
if (!selectedRegion.value && regions.value.length) selectedRegion.value = regions.value[0].value
} catch (err) {
addNotification({ title: 'Failed to load nodes overview', text: String(err), type: 'error' })
}
}
async function apply() {
try {
const body =
mode.value === 'nodes'
? {
nodes: selectedNodes.value.slice(),
days: Math.max(1, Math.floor(days.value)),
send_email: sendEmail.value,
message: message.value?.trim() || DEFAULT_CREDIT_EMAIL_MESSAGE,
}
: {
region: selectedRegion.value!,
days: Math.max(1, Math.floor(days.value)),
send_email: sendEmail.value,
message: message.value?.trim() || DEFAULT_CREDIT_EMAIL_MESSAGE,
}
await useBaseFetch('billing/credit', {
method: 'POST',
body: JSON.stringify(body),
internal: true,
})
addNotification({ title: 'Credits applied', type: 'success' })
modal.value?.hide()
selectedNodes.value = []
nodeInput.value = ''
message.value = ''
} catch (err: any) {
addNotification({
title: 'Error applying credits',
text: err?.data?.description ?? String(err),
type: 'error',
})
}
}
function pluralize(n: number): string {
return n === 1 ? '' : 's'
}
defineExpose({
show,
hide,
})
</script>

View File

@@ -356,7 +356,7 @@ svg {
:deep(.apexcharts-yaxistooltip) {
background: var(--color-raised-bg) !important;
border-radius: var(--radius-sm) !important;
border: 1px solid var(--color-button-bg) !important;
border: 1px solid var(--color-divider) !important;
box-shadow: var(--shadow-floating) !important;
font-size: var(--font-size-nm) !important;
}
@@ -371,7 +371,7 @@ svg {
:deep(.apexcharts-xaxistooltip) {
background: var(--color-raised-bg) !important;
border-radius: var(--radius-sm) !important;
border: 1px solid var(--color-button-bg) !important;
border: 1px solid var(--color-divider) !important;
font-size: var(--font-size-nm) !important;
color: var(--color-base) !important;

View File

@@ -891,7 +891,7 @@ const defaultRanges: RangeObject[] = [
flex-direction: column;
background-color: var(--color-bg);
border-radius: var(--radius-sm);
border: 1px solid var(--color-button-bg);
border: 1px solid var(--color-divider);
gap: var(--gap-md);
padding: var(--gap-md);
margin-top: var(--gap-md);
@@ -920,7 +920,7 @@ const defaultRanges: RangeObject[] = [
width: 100%;
height: 1rem;
background-color: var(--color-raised-bg);
border: 1px solid var(--color-button-bg);
border: 1px solid var(--color-divider);
border-radius: var(--radius-sm);
overflow: hidden;

View File

@@ -159,10 +159,10 @@ defineExpose({
flex-direction: column;
gap: var(--gap-xs);
border: 1px solid var(--color-button-bg);
border: 1px solid var(--color-divider);
border-radius: var(--radius-md);
background-color: var(--color-raised-bg);
box-shadow: var(--shadow-floating);
box-shadow: var(--shadow-card);
color: var(--color-base);
font-size: var(--font-size-nm);
@@ -192,7 +192,7 @@ svg {
:deep(.apexcharts-yaxistooltip) {
background: var(--color-raised-bg) !important;
border-radius: var(--radius-sm) !important;
border: 1px solid var(--color-button-bg) !important;
border: 1px solid var(--color-divider) !important;
box-shadow: var(--shadow-floating) !important;
font-size: var(--font-size-nm) !important;
}

View File

@@ -0,0 +1,570 @@
<template>
<NewModal
ref="withdrawModal"
:closable="currentStage !== 'completion'"
:hide-header="currentStage === 'completion'"
:merge-header="currentStage === 'completion'"
:scrollable="true"
max-content-height="72vh"
:on-hide="onModalHide"
>
<template #title>
<div v-if="shouldShowTitle" class="flex flex-wrap items-center gap-1 text-secondary">
<template v-if="currentStage === 'tax-form'">
<span class="text-lg font-bold text-contrast sm:text-xl">{{
formatMessage(messages.taxFormStage)
}}</span>
</template>
<template v-else-if="currentStage === 'method-selection'">
<span class="text-lg font-bold text-contrast sm:text-xl">{{
formatMessage(messages.methodSelectionStage)
}}</span>
<ChevronRightIcon class="size-5 text-secondary" stroke-width="3" />
<span class="text-lg text-secondary sm:text-xl">{{
formatMessage(messages.detailsLabel)
}}</span>
</template>
<template v-else-if="isDetailsStage">
<button
class="active:scale-9 bg-transparent p-0 text-lg text-secondary transition-colors duration-200 hover:text-primary sm:text-xl"
@click="goToBreadcrumbStage('method-selection')"
>
{{ formatMessage(messages.methodSelectionStage) }}
</button>
<ChevronRightIcon class="size-5 text-secondary" stroke-width="3" />
<span class="text-lg font-bold text-contrast sm:text-xl">{{
formatMessage(messages.detailsLabel)
}}</span>
</template>
</div>
</template>
<div class="mx-auto w-full max-w-[496px] sm:mx-0 sm:min-w-[496px]">
<TaxFormStage
v-if="currentStage === 'tax-form'"
:balance="balance"
:on-show-tax-form="showTaxFormModal"
/>
<MethodSelectionStage
v-else-if="currentStage === 'method-selection'"
:on-show-tax-form="showTaxFormModal"
@close-modal="withdrawModal?.hide()"
/>
<TremendousDetailsStage v-else-if="currentStage === 'tremendous-details'" />
<MuralpayKycStage v-else-if="currentStage === 'muralpay-kyc'" />
<MuralpayDetailsStage v-else-if="currentStage === 'muralpay-details'" />
<LegacyPaypalDetailsStage v-else-if="currentStage === 'paypal-details'" />
<CompletionStage v-else-if="currentStage === 'completion'" />
<div v-else>Something went wrong</div>
</div>
<template #actions>
<div v-if="currentStage === 'completion'" class="mt-4 flex w-full gap-3">
<ButtonStyled class="flex-1">
<button class="w-full text-contrast" @click="handleClose">
{{ formatMessage(messages.closeButton) }}
</button>
</ButtonStyled>
<ButtonStyled class="flex-1">
<button class="w-full text-contrast" @click="handleViewTransactions">
{{ formatMessage(messages.transactionsButton) }}
</button>
</ButtonStyled>
</div>
<div v-else class="mt-4 flex flex-col justify-end gap-2 sm:flex-row">
<ButtonStyled type="outlined">
<button
class="!border-surface-5"
:disabled="leftButtonConfig.disabled"
@click="leftButtonConfig.handler"
>
<component :is="leftButtonConfig.icon" />
{{ leftButtonConfig.label }}
</button>
</ButtonStyled>
<ButtonStyled :color="rightButtonConfig.color">
<button :disabled="rightButtonConfig.disabled" @click="rightButtonConfig.handler">
<component
:is="rightButtonConfig.icon"
v-if="rightButtonConfig.iconPosition === 'before'"
:class="rightButtonConfig.iconClass"
/>
{{ rightButtonConfig.label }}
<component
:is="rightButtonConfig.icon"
v-if="rightButtonConfig.iconPosition === 'after'"
:class="rightButtonConfig.iconClass"
/>
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
<CreatorTaxFormModal
ref="taxFormModal"
close-button-text="Continue"
@success="onTaxFormSuccess"
@cancelled="onTaxFormCancelled"
/>
</template>
<script setup lang="ts">
import {
ArrowLeftRightIcon,
ChevronRightIcon,
FileTextIcon,
LeftArrowIcon,
RightArrowIcon,
SpinnerIcon,
XIcon,
} from '@modrinth/assets'
import { ButtonStyled, commonMessages, injectNotificationManager, NewModal } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { computed, nextTick, onMounted, ref, useTemplateRef, watch } from 'vue'
import {
createWithdrawContext,
type PayoutMethod,
provideWithdrawContext,
TAX_THRESHOLD_ACTUAL,
type WithdrawStage,
} from '@/providers/creator-withdraw.ts'
import CreatorTaxFormModal from './CreatorTaxFormModal.vue'
import CompletionStage from './withdraw-stages/CompletionStage.vue'
import LegacyPaypalDetailsStage from './withdraw-stages/LegacyPaypalDetailsStage.vue'
import MethodSelectionStage from './withdraw-stages/MethodSelectionStage.vue'
import MuralpayDetailsStage from './withdraw-stages/MuralpayDetailsStage.vue'
import MuralpayKycStage from './withdraw-stages/MuralpayKycStage.vue'
import TaxFormStage from './withdraw-stages/TaxFormStage.vue'
import TremendousDetailsStage from './withdraw-stages/TremendousDetailsStage.vue'
type FormCompletionStatus = 'unknown' | 'unrequested' | 'unsigned' | 'tin-mismatch' | 'complete'
interface UserBalanceResponse {
available: number
withdrawn_lifetime: number
withdrawn_ytd: number
pending: number
dates: Record<string, number>
requested_form_type: string | null
form_completion_status: FormCompletionStatus | null
}
const props = defineProps<{
balance: UserBalanceResponse | null
preloadedPaymentData?: { country: string; methods: PayoutMethod[] } | null
}>()
const emit = defineEmits<{
(e: 'refresh-data' | 'hide'): void
}>()
const withdrawModal = useTemplateRef<InstanceType<typeof NewModal>>('withdrawModal')
const taxFormModal = ref<InstanceType<typeof CreatorTaxFormModal> | null>(null)
const isSubmitting = ref(false)
function show(preferred?: WithdrawStage) {
if (preferred) {
setStage(preferred, true)
withdrawModal.value?.show()
return
}
const firstStage = stages.value[0]
if (firstStage) {
setStage(firstStage, true)
}
withdrawModal.value?.show()
}
defineExpose({
show,
})
const { formatMessage } = useVIntl()
const { addNotification } = injectNotificationManager()
const withdrawContext = createWithdrawContext(
props.balance,
props.preloadedPaymentData || undefined,
)
provideWithdrawContext(withdrawContext)
const {
currentStage,
previousStep,
nextStep,
canProceed,
setStage,
withdrawData,
resetData,
stages,
submitWithdrawal,
restoreStateFromStorage,
clearSavedState,
} = withdrawContext
watch(
() => props.balance,
(newBalance) => {
if (newBalance) {
withdrawContext.balance.value = newBalance
}
},
{ deep: true },
)
onMounted(() => {
const route = useRoute()
const router = useRouter()
if (route.query.paypal_auth_return === 'true') {
const savedState = restoreStateFromStorage()
if (savedState?.data) {
withdrawData.value = { ...savedState.data }
nextTick(() => {
show(savedState.stage)
})
clearSavedState()
}
const query = { ...route.query }
delete query.paypal_auth_return
router.replace({ query })
}
})
const needsTaxForm = computed(() => {
if (!props.balance || currentStage.value !== 'tax-form') return false
const ytd = props.balance.withdrawn_ytd ?? 0
const available = props.balance.available ?? 0
const status = props.balance.form_completion_status
return status !== 'complete' && ytd + available >= 600
})
const remainingLimit = computed(() => {
if (!props.balance) return 0
const ytd = props.balance.withdrawn_ytd ?? 0
const raw = TAX_THRESHOLD_ACTUAL - ytd
if (raw <= 0) return 0
const cents = Math.floor(raw * 100)
return cents / 100
})
const leftButtonConfig = computed(() => {
if (previousStep.value) {
return {
icon: LeftArrowIcon,
label: formatMessage(commonMessages.backButton),
handler: () => setStage(previousStep.value, true),
disabled: isSubmitting.value,
}
}
return {
icon: XIcon,
label: formatMessage(commonMessages.cancelButton),
handler: () => withdrawModal.value?.hide(),
disabled: isSubmitting.value,
}
})
const rightButtonConfig = computed(() => {
const stage = currentStage.value
const isTaxFormStage = stage === 'tax-form'
const isDetailsStage =
stage === 'muralpay-details' || stage === 'tremendous-details' || stage === 'paypal-details'
if (isTaxFormStage && needsTaxForm.value && remainingLimit.value > 0) {
return {
icon: RightArrowIcon,
label: formatMessage(messages.continueWithLimit),
handler: continueWithLimit,
disabled: false,
color: 'standard' as const,
iconPosition: 'after' as const,
}
}
if (isTaxFormStage && needsTaxForm.value) {
return {
icon: FileTextIcon,
label: formatMessage(messages.completeTaxForm),
handler: showTaxFormModal,
disabled: false,
color: 'orange' as const,
iconPosition: 'before' as const,
}
}
if (isDetailsStage) {
return {
icon: isSubmitting.value ? SpinnerIcon : ArrowLeftRightIcon,
iconClass: isSubmitting.value ? 'animate-spin' : undefined,
label: formatMessage(messages.withdrawButton),
handler: handleWithdraw,
disabled: !canProceed.value || isSubmitting.value,
color: 'brand' as const,
iconPosition: 'before' as const,
}
}
return {
icon: RightArrowIcon,
label: formatMessage(commonMessages.nextButton),
handler: () => setStage(nextStep.value),
disabled: !canProceed.value,
color: 'standard' as const,
iconPosition: 'after' as const,
}
})
function continueWithLimit() {
withdrawData.value.tax.skipped = true
setStage(nextStep.value)
}
// TODO: God we need better errors from the backend (e.g error ids), this shit is insane
function getWithdrawalError(error: any): { title: string; text: string } {
const description = error?.data?.description?.toLowerCase() || ''
// Tax form error
if (description.includes('tax form')) {
return {
title: formatMessage(messages.errorTaxFormTitle),
text: formatMessage(messages.errorTaxFormText),
}
}
// Invalid crypto wallet address
if (
(description.includes('wallet') && description.includes('invalid')) ||
description.includes('wallet_address') ||
(description.includes('blockchain') && description.includes('invalid'))
) {
return {
title: formatMessage(messages.errorInvalidWalletTitle),
text: formatMessage(messages.errorInvalidWalletText),
}
}
// Invalid bank details
if (
(description.includes('bank') || description.includes('account')) &&
(description.includes('invalid') || description.includes('failed'))
) {
return {
title: formatMessage(messages.errorInvalidBankTitle),
text: formatMessage(messages.errorInvalidBankText),
}
}
// Invalid/fraudulent address
if (
description.includes('address') &&
(description.includes('invalid') ||
description.includes('verification') ||
description.includes('fraudulent'))
) {
return {
title: formatMessage(messages.errorInvalidAddressTitle),
text: formatMessage(messages.errorInvalidAddressText),
}
}
// Minimum amount not met
if (
description.includes('payoutminimumnotmeterror') ||
description.includes('minimum') ||
(description.includes('amount') && description.includes('less'))
) {
return {
title: formatMessage(messages.errorMinimumNotMetTitle),
text: formatMessage(messages.errorMinimumNotMetText),
}
}
// Generic fallback
return {
title: formatMessage(messages.errorGenericTitle),
text: formatMessage(messages.errorGenericText),
}
}
async function handleWithdraw() {
if (isSubmitting.value) return
try {
isSubmitting.value = true
await submitWithdrawal()
setStage('completion')
} catch (error) {
console.error('Withdrawal failed:', error)
const { title, text } = getWithdrawalError(error)
addNotification({
title,
text,
type: 'error',
})
} finally {
isSubmitting.value = false
}
}
const shouldShowTitle = computed(() => {
return currentStage.value !== 'completion'
})
const isDetailsStage = computed(() => {
const detailsStages: WithdrawStage[] = [
'tremendous-details',
'muralpay-kyc',
'muralpay-details',
'paypal-details',
]
const current = currentStage.value
return current ? detailsStages.includes(current) : false
})
function showTaxFormModal(e?: MouseEvent) {
withdrawModal.value?.hide()
taxFormModal.value?.startTaxForm(e ?? new MouseEvent('click'))
}
function onTaxFormSuccess() {
emit('refresh-data')
nextTick(() => {
show('method-selection')
})
}
function onTaxFormCancelled() {
show('tax-form')
}
function onModalHide() {
resetData()
emit('hide')
}
function goToBreadcrumbStage(stage: WithdrawStage) {
setStage(stage, true)
}
function handleClose() {
withdrawModal.value?.hide()
emit('refresh-data')
}
function handleViewTransactions() {
withdrawModal.value?.hide()
navigateTo('/dashboard/revenue/transfers')
}
const messages = defineMessages({
taxFormStage: {
id: 'dashboard.creator-withdraw-modal.stage.tax-form',
defaultMessage: 'Tax form',
},
methodSelectionStage: {
id: 'dashboard.creator-withdraw-modal.stage.method-selection',
defaultMessage: 'Method',
},
tremendousDetailsStage: {
id: 'dashboard.creator-withdraw-modal.stage.tremendous-details',
defaultMessage: 'Details',
},
muralpayKycStage: {
id: 'dashboard.creator-withdraw-modal.stage.muralpay-kyc',
defaultMessage: 'Verification',
},
muralpayDetailsStage: {
id: 'dashboard.creator-withdraw-modal.stage.muralpay-details',
defaultMessage: 'Account Details',
},
completionStage: {
id: 'dashboard.creator-withdraw-modal.stage.completion',
defaultMessage: 'Complete',
},
detailsLabel: {
id: 'dashboard.creator-withdraw-modal.details-label',
defaultMessage: 'Details',
},
completeTaxForm: {
id: 'dashboard.creator-withdraw-modal.complete-tax-form',
defaultMessage: 'Complete tax form',
},
continueWithLimit: {
id: 'dashboard.creator-withdraw-modal.continue-with-limit',
defaultMessage: 'Continue with limit',
},
withdrawButton: {
id: 'dashboard.creator-withdraw-modal.withdraw-button',
defaultMessage: 'Withdraw',
},
closeButton: {
id: 'dashboard.withdraw.completion.close-button',
defaultMessage: 'Close',
},
transactionsButton: {
id: 'dashboard.withdraw.completion.transactions-button',
defaultMessage: 'Transactions',
},
errorTaxFormTitle: {
id: 'dashboard.withdraw.error.tax-form.title',
defaultMessage: 'Please complete tax form',
},
errorTaxFormText: {
id: 'dashboard.withdraw.error.tax-form.text',
defaultMessage: 'You must complete a tax form to submit your withdrawal request.',
},
errorInvalidWalletTitle: {
id: 'dashboard.withdraw.error.invalid-wallet.title',
defaultMessage: 'Invalid wallet address',
},
errorInvalidWalletText: {
id: 'dashboard.withdraw.error.invalid-wallet.text',
defaultMessage:
'The crypto wallet address you provided is invalid. Please double-check and try again.',
},
errorInvalidBankTitle: {
id: 'dashboard.withdraw.error.invalid-bank.title',
defaultMessage: 'Invalid bank details',
},
errorInvalidBankText: {
id: 'dashboard.withdraw.error.invalid-bank.text',
defaultMessage:
'The bank account details you provided are invalid. Please verify your information.',
},
errorInvalidAddressTitle: {
id: 'dashboard.withdraw.error.invalid-address.title',
defaultMessage: 'Address verification failed',
},
errorInvalidAddressText: {
id: 'dashboard.withdraw.error.invalid-address.text',
defaultMessage:
'The address you provided could not be verified. Please check your address details.',
},
errorMinimumNotMetTitle: {
id: 'dashboard.withdraw.error.minimum-not-met.title',
defaultMessage: 'Amount too low',
},
errorMinimumNotMetText: {
id: 'dashboard.withdraw.error.minimum-not-met.text',
defaultMessage:
"The withdrawal amount (after fees) doesn't meet the minimum requirement. Please increase your withdrawal amount.",
},
errorGenericTitle: {
id: 'dashboard.withdraw.error.generic.title',
defaultMessage: 'Unable to withdraw',
},
errorGenericText: {
id: 'dashboard.withdraw.error.generic.text',
defaultMessage:
'We were unable to submit your withdrawal request, please check your details or contact support.',
},
})
</script>

View File

@@ -0,0 +1,158 @@
<template>
<div class="flex flex-col gap-2">
<div class="flex items-center gap-2">
<div class="relative flex-1">
<input
ref="amountInput"
:value="modelValue"
type="number"
step="0.01"
:min="minAmount"
:max="safeMaxAmount"
:disabled="isDisabled"
:placeholder="formatMessage(formFieldPlaceholders.amountPlaceholder)"
class="w-full rounded-[14px] bg-surface-4 py-2.5 pl-4 pr-4 text-contrast placeholder:text-secondary"
@input="handleInput"
/>
</div>
<Combobox
v-if="showCurrencySelector"
:model-value="selectedCurrency"
:options="currencyOptions"
class="w-min"
@update:model-value="$emit('update:selectedCurrency', $event)"
>
<template v-for="option in currencyOptions" :key="option.value" #[`option-${option.value}`]>
<span class="font-semibold leading-tight">{{ option.label }}</span>
</template>
</Combobox>
<ButtonStyled>
<button class="px-4 py-2" :disabled="isDisabled" @click="setMaxAmount">
{{ formatMessage(commonMessages.maxButton) }}
</button>
</ButtonStyled>
</div>
<div>
<span class="my-1 mt-0 text-secondary">{{ formatMoney(safeMaxAmount) }} available.</span>
<Transition name="fade">
<span v-if="isBelowMinimum" class="text-red">
Amount must be at least {{ formatMoney(minAmount) }}.
</span>
</Transition>
<Transition name="fade">
<span v-if="isAboveMaximum" class="text-red">
Amount cannot exceed {{ formatMoney(safeMaxAmount) }}.
</span>
</Transition>
</div>
</div>
</template>
<script setup lang="ts">
import { ButtonStyled, Combobox, commonMessages, formFieldPlaceholders } from '@modrinth/ui'
import { formatMoney } from '@modrinth/utils'
import { useVIntl } from '@vintl/vintl'
import { computed, nextTick, ref, watch } from 'vue'
const props = withDefaults(
defineProps<{
modelValue: number | undefined
maxAmount: number
minAmount?: number
showCurrencySelector?: boolean
selectedCurrency?: string
currencyOptions?: Array<{ value: string; label: string }>
}>(),
{
minAmount: 0.01,
showCurrencySelector: false,
currencyOptions: () => [],
},
)
const emit = defineEmits<{
'update:modelValue': [value: number | undefined]
'update:selectedCurrency': [value: string]
}>()
const { formatMessage } = useVIntl()
const amountInput = ref<HTMLInputElement | null>(null)
const safeMaxAmount = computed(() => {
return Math.max(0, props.maxAmount)
})
const isDisabled = computed(() => {
return safeMaxAmount.value < 0.01
})
const isBelowMinimum = computed(() => {
return (
props.modelValue !== undefined && props.modelValue > 0 && props.modelValue < props.minAmount
)
})
const isAboveMaximum = computed(() => {
return props.modelValue !== undefined && props.modelValue > safeMaxAmount.value
})
async function setMaxAmount() {
const maxValue = safeMaxAmount.value
emit('update:modelValue', maxValue)
await nextTick()
if (amountInput.value) {
amountInput.value.value = maxValue.toFixed(2)
}
}
function handleInput(event: Event) {
const input = event.target as HTMLInputElement
const value = input.value
if (value && value.includes('.')) {
const parts = value.split('.')
if (parts[1] && parts[1].length > 2) {
const rounded = Math.floor(parseFloat(value) * 100) / 100
emit('update:modelValue', rounded)
input.value = rounded.toString()
return
}
}
const numValue = value === '' ? undefined : parseFloat(value)
emit('update:modelValue', numValue)
}
watch(
() => props.modelValue,
async (newAmount) => {
if (newAmount !== undefined && newAmount !== null) {
if (newAmount > safeMaxAmount.value) {
emit('update:modelValue', safeMaxAmount.value)
await nextTick()
if (amountInput.value) {
amountInput.value.value = safeMaxAmount.value.toFixed(2)
}
} else if (newAmount < 0) {
emit('update:modelValue', 0)
}
}
},
)
</script>
<style scoped>
.fade-enter-active {
transition: opacity 200ms ease-out;
}
.fade-leave-active {
transition: opacity 150ms ease-in;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>

View File

@@ -0,0 +1,152 @@
<template>
<div class="flex flex-row gap-2 md:gap-3">
<div
class="flex h-10 min-h-10 w-10 min-w-10 justify-center rounded-full border-[1px] border-solid border-button-bg bg-bg-raised !p-0 shadow-md md:h-12 md:min-h-12 md:w-12 md:min-w-12"
>
<ArrowDownIcon v-if="isIncome" class="my-auto size-6 text-secondary md:size-8" />
<ArrowUpIcon v-else class="my-auto size-6 text-secondary md:size-8" />
</div>
<div class="flex w-full flex-row justify-between">
<div class="flex flex-col">
<span class="text-base font-semibold text-contrast md:text-lg">{{
transaction.type === 'payout_available'
? formatPayoutSource(transaction.payout_source)
: formatMethodName(transaction.method_type || transaction.method)
}}</span>
<span class="text-xs text-secondary md:text-sm">
<template v-if="transaction.type === 'withdrawal'">
<span
:class="[
transaction.status === 'cancelling' || transaction.status === 'cancelled'
? 'text-red'
: '',
]"
>{{ formatTransactionStatus(transaction.status) }} <BulletDivider
/></span>
</template>
{{ dayjs(transaction.created).format('MMM DD YYYY') }}
<template v-if="transaction.type === 'withdrawal' && transaction.fee">
<BulletDivider /> Fee {{ formatMoney(transaction.fee) }}
</template>
</span>
</div>
<div class="my-auto flex flex-row items-center gap-2">
<span
class="text-base font-semibold md:text-lg"
:class="transaction.type === 'payout_available' ? 'text-green' : 'text-contrast'"
>{{ formatMoney(transaction.amount) }}</span
>
<template v-if="transaction.type === 'withdrawal' && transaction.status === 'in-transit'">
<Tooltip theme="dismissable-prompt" :triggers="['hover', 'focus']" no-auto-focus>
<span class="my-auto align-middle"
><ButtonStyled circular type="outlined" size="small">
<button class="align-middle" @click="cancelPayout">
<XIcon />
</button> </ButtonStyled
></span>
<template #popper>
<div class="font-semibold text-contrast">Cancel transaction</div>
</template>
</Tooltip>
</template>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ArrowDownIcon, ArrowUpIcon, XIcon } from '@modrinth/assets'
import { BulletDivider, ButtonStyled, injectNotificationManager } from '@modrinth/ui'
import { capitalizeString, formatMoney } from '@modrinth/utils'
import dayjs from 'dayjs'
import { Tooltip } from 'floating-vue'
type PayoutStatus = 'in-transit' | 'cancelling' | 'cancelled' | 'success' | 'failed'
type PayoutMethodType = 'paypal' | 'venmo' | 'tremendous' | 'muralpay'
type PayoutSource = 'creator_rewards' | 'affilites'
type WithdrawalTransaction = {
type: 'withdrawal'
id: string
status: PayoutStatus
created: string
amount: number
fee?: number | null
method_type?: PayoutMethodType | null
method?: string
method_id?: string
method_address?: string | null
}
type PayoutAvailableTransaction = {
type: 'payout_available'
created: string
payout_source: PayoutSource
amount: number
}
type Transaction = WithdrawalTransaction | PayoutAvailableTransaction
const props = defineProps<{
transaction: Transaction
}>()
const emit = defineEmits<{
(e: 'cancelled'): void
}>()
const { addNotification } = injectNotificationManager()
const isIncome = computed(() => props.transaction.type === 'payout_available')
function formatTransactionStatus(status: string): string {
if (status === 'in-transit') return 'In Transit'
return capitalizeString(status)
}
function formatMethodName(method: string | undefined): string {
if (!method) return 'Unknown'
switch (method) {
case 'paypal':
return 'PayPal'
case 'venmo':
return 'Venmo'
case 'tremendous':
return 'Tremendous'
case 'muralpay':
return 'Muralpay'
default:
return capitalizeString(method)
}
}
function formatPayoutSource(source: string | undefined): string {
if (!source) return 'Income'
return source
.split('_')
.map((word: string) => capitalizeString(word))
.join(' ')
}
async function cancelPayout(): Promise<void> {
startLoading()
try {
const transaction = props.transaction
if (transaction.type !== 'withdrawal') return
await useBaseFetch(`payout/${transaction.id}`, {
method: 'DELETE',
apiVersion: 3,
})
await useAuth()
emit('cancelled')
} catch (err: any) {
addNotification({
title: 'Failed to cancel transaction',
text: err.data ? err.data.description : err,
type: 'error',
})
}
stopLoading()
}
</script>

View File

@@ -0,0 +1,119 @@
<template>
<Transition
enter-active-class="transition-all duration-300 ease-out"
enter-from-class="opacity-0 max-h-0"
enter-to-class="opacity-100 max-h-40"
leave-active-class="transition-all duration-200 ease-in"
leave-from-class="opacity-100 max-h-40"
leave-to-class="opacity-0 max-h-0"
>
<div v-if="amount > 0" class="flex flex-col gap-2.5 rounded-[20px] bg-surface-2 p-4">
<div class="flex items-center justify-between">
<span class="text-primary">{{ formatMessage(messages.feeBreakdownAmount) }}</span>
<span class="font-semibold text-contrast">{{ formatMoney(amount || 0) }}</span>
</div>
<div class="flex items-center justify-between">
<span class="text-primary">{{ formatMessage(messages.feeBreakdownFee) }}</span>
<span class="h-4 font-semibold text-contrast">
<template v-if="feeLoading">
<LoaderCircleIcon class="size-5 animate-spin !text-secondary" />
</template>
<template v-else>-{{ formatMoney(fee || 0) }}</template>
</span>
</div>
<div class="h-px bg-surface-5" />
<div class="flex items-center justify-between">
<span class="text-primary">{{ formatMessage(messages.feeBreakdownNetAmount) }}</span>
<span class="font-semibold text-contrast">
{{ formatMoney(netAmount) }}
<template v-if="shouldShowExchangeRate">
<span> ({{ formattedLocalCurrency }})</span>
</template>
</span>
</div>
<template v-if="shouldShowExchangeRate">
<div class="flex items-center justify-between text-sm">
<span class="text-primary">{{ formatMessage(messages.feeBreakdownExchangeRate) }}</span>
<span class="text-secondary"
>1 USD = {{ exchangeRate?.toFixed(4) }} {{ localCurrency }}</span
>
</div>
</template>
</div>
</Transition>
</template>
<script setup lang="ts">
import { LoaderCircleIcon } from '@modrinth/assets'
import { formatMoney } from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { computed } from 'vue'
const props = withDefaults(
defineProps<{
amount: number
fee: number | null
feeLoading: boolean
exchangeRate?: number | null
localCurrency?: string
}>(),
{
exchangeRate: null,
localCurrency: undefined,
},
)
const { formatMessage } = useVIntl()
const netAmount = computed(() => {
const amount = props.amount || 0
const fee = props.fee || 0
return Math.max(0, amount - fee)
})
const shouldShowExchangeRate = computed(() => {
if (!props.localCurrency) return false
if (props.localCurrency === 'USD') return false
return props.exchangeRate !== null && props.exchangeRate !== undefined && props.exchangeRate > 0
})
const netAmountInLocalCurrency = computed(() => {
if (!shouldShowExchangeRate.value) return null
return netAmount.value * (props.exchangeRate || 0)
})
const formattedLocalCurrency = computed(() => {
if (!shouldShowExchangeRate.value || !netAmountInLocalCurrency.value || !props.localCurrency)
return ''
try {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: props.localCurrency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(netAmountInLocalCurrency.value)
} catch {
return `${props.localCurrency} ${netAmountInLocalCurrency.value.toFixed(2)}`
}
})
const messages = defineMessages({
feeBreakdownAmount: {
id: 'dashboard.creator-withdraw-modal.fee-breakdown-amount',
defaultMessage: 'Amount',
},
feeBreakdownFee: {
id: 'dashboard.creator-withdraw-modal.fee-breakdown-fee',
defaultMessage: 'Fee',
},
feeBreakdownNetAmount: {
id: 'dashboard.creator-withdraw-modal.fee-breakdown-net-amount',
defaultMessage: 'Net amount',
},
feeBreakdownExchangeRate: {
id: 'dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate',
defaultMessage: 'FX rate',
},
})
</script>

View File

@@ -0,0 +1,301 @@
<template>
<div class="flex flex-col items-center gap-4">
<div class="flex w-full items-center justify-center gap-2.5">
<span class="text-xl font-semibold text-contrast sm:text-2xl">
{{ formatMessage(messages.title) }}
</span>
</div>
<div class="flex w-full flex-col gap-3">
<div class="span-4 flex w-full flex-col gap-2.5 rounded-2xl bg-surface-2 p-4">
<div
class="flex w-full flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-0"
>
<span class="text-sm font-normal text-primary sm:text-[1rem]">
{{ formatMessage(messages.method) }}
</span>
<span class="break-words text-sm font-semibold text-contrast sm:text-[1rem]">
{{ result?.methodType || 'N/A' }}
</span>
</div>
<div
class="flex w-full flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-0"
>
<span class="text-sm font-normal text-primary sm:text-[1rem]">
{{ formatMessage(messages.recipient) }}
</span>
<span class="break-words text-sm font-semibold text-contrast sm:text-[1rem]">
{{ result?.recipientDisplay || 'N/A' }}
</span>
</div>
<div
v-if="destinationLabel && destinationValue"
class="flex w-full flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-0"
>
<span class="text-sm font-normal text-primary sm:text-[1rem]">
{{ destinationLabel }}
</span>
<span class="break-words font-mono text-sm font-semibold text-contrast sm:text-[1rem]">
{{ destinationValue }}
</span>
</div>
<div
class="flex w-full flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-0"
>
<span class="text-sm font-normal text-primary sm:text-[1rem]">
{{ formatMessage(messages.date) }}
</span>
<span class="break-words text-sm font-semibold text-contrast sm:text-[1rem]">
{{ formattedDate }}
</span>
</div>
<div
class="flex w-full flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-0"
>
<span class="text-sm font-normal text-primary sm:text-[1rem]">
{{ formatMessage(messages.amount) }}
</span>
<span class="break-words text-sm font-semibold text-contrast sm:text-[1rem]">
{{ formatMoney(result?.amount || 0) }}
</span>
</div>
<div
class="flex w-full flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-0"
>
<span class="text-sm font-normal text-primary sm:text-[1rem]">
{{ formatMessage(messages.fee) }}
</span>
<span class="break-words text-sm font-semibold text-contrast sm:text-[1rem]">
{{ formatMoney(result?.fee || 0) }}
</span>
</div>
<div class="border-b-1 h-0 w-full rounded-full border-b border-solid border-divider" />
<div
class="flex w-full flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-0"
>
<span class="text-sm font-normal text-primary sm:text-[1rem]">
{{ formatMessage(messages.netAmount) }}
</span>
<span class="break-words text-sm font-semibold text-contrast sm:text-[1rem]">
{{ formatMoney(result?.netAmount || 0) }}
<template v-if="shouldShowExchangeRate">
<span> ({{ formattedLocalCurrency }})</span>
</template>
</span>
</div>
<template v-if="shouldShowExchangeRate">
<div
class="flex w-full flex-col gap-1 sm:flex-row sm:items-center sm:justify-between sm:gap-0"
>
<span class="text-sm font-normal text-primary sm:text-[1rem]">
{{ formatMessage(messages.exchangeRate) }}
</span>
<span class="break-words text-sm font-normal text-secondary sm:text-[1rem]">
1 USD = {{ withdrawData.calculation.exchangeRate?.toFixed(4) }}
{{ localCurrency }}
</span>
</div>
</template>
</div>
<span
v-if="withdrawData.providerData.type === 'tremendous'"
class="w-full break-words text-center text-sm font-normal text-primary sm:text-[1rem]"
>
<IntlFormatted
:message-id="messages.emailConfirmation"
:values="{ email: withdrawData.result?.recipientDisplay }"
>
<template #b="{ children }">
<strong>
<component :is="() => normalizeChildren(children)" />
</strong>
</template>
</IntlFormatted>
</span>
</div>
<Teleport to="body">
<div
v-if="showConfetti"
class="pointer-events-none fixed inset-0 z-[9999] flex items-center justify-center"
>
<ConfettiExplosion />
</div>
</Teleport>
</div>
</template>
<script setup lang="ts">
import { formatMoney } from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import dayjs from 'dayjs'
import { computed, onMounted, ref } from 'vue'
import ConfettiExplosion from 'vue-confetti-explosion'
import { type TremendousProviderData, useWithdrawContext } from '@/providers/creator-withdraw.ts'
import { getRailConfig } from '@/utils/muralpay-rails'
import { normalizeChildren } from '@/utils/vue-children.ts'
const { withdrawData } = useWithdrawContext()
const { formatMessage } = useVIntl()
const result = computed(() => withdrawData.value.result)
const showConfetti = ref(false)
onMounted(() => {
showConfetti.value = true
setTimeout(() => {
showConfetti.value = false
}, 5000)
})
const formattedDate = computed(() => {
if (!result.value?.created) return 'N/A'
return dayjs(result.value.created).format('MMMM D, YYYY')
})
const selectedRail = computed(() => {
const railId = withdrawData.value.selection.method
return railId ? getRailConfig(railId) : null
})
const localCurrency = computed(() => {
// Check if it's Tremendous withdrawal with currency
if (withdrawData.value.providerData.type === 'tremendous') {
return (withdrawData.value.providerData as TremendousProviderData).currency
}
// Fall back to MuralPay rail currency
return selectedRail.value?.currency
})
const shouldShowExchangeRate = computed(() => {
if (!localCurrency.value) return false
if (localCurrency.value === 'USD') return false
const exchangeRate = withdrawData.value.calculation.exchangeRate
return exchangeRate !== null && exchangeRate !== undefined && exchangeRate > 0
})
const netAmountInLocalCurrency = computed(() => {
if (!shouldShowExchangeRate.value) return null
const netAmount = result.value?.netAmount || 0
const exchangeRate = withdrawData.value.calculation.exchangeRate || 0
return netAmount * exchangeRate
})
const formattedLocalCurrency = computed(() => {
if (!shouldShowExchangeRate.value || !netAmountInLocalCurrency.value || !localCurrency.value)
return ''
try {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: localCurrency.value,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(netAmountInLocalCurrency.value)
} catch {
return `${localCurrency.value} ${netAmountInLocalCurrency.value.toFixed(2)}`
}
})
const isMuralPayWithdrawal = computed(() => {
return withdrawData.value.providerData.type === 'muralpay'
})
const destinationLabel = computed(() => {
if (!isMuralPayWithdrawal.value) return null
const rail = selectedRail.value
if (!rail) return null
if (rail.type === 'crypto') {
return formatMessage(messages.wallet)
} else if (rail.type === 'fiat') {
return formatMessage(messages.account)
}
return null
})
const destinationValue = computed(() => {
if (!isMuralPayWithdrawal.value || withdrawData.value.providerData.type !== 'muralpay') {
return null
}
const accountDetails = withdrawData.value.providerData.accountDetails
const rail = selectedRail.value
if (rail?.type === 'crypto' && accountDetails.walletAddress) {
const addr = accountDetails.walletAddress
if (addr.length > 10) {
return `${addr.slice(0, 6)}...${addr.slice(-4)}`
}
return addr
} else if (rail?.type === 'fiat' && accountDetails.bankAccountNumber) {
const accountType = accountDetails.accountType || 'Account'
const last4 = accountDetails.bankAccountNumber.slice(-4)
const formattedType = accountType.charAt(0) + accountType.slice(1).toLowerCase()
return `${formattedType} (${last4})`
}
return null
})
const messages = defineMessages({
title: {
id: 'dashboard.withdraw.completion.title',
defaultMessage: 'Withdraw complete',
},
method: {
id: 'dashboard.withdraw.completion.method',
defaultMessage: 'Method',
},
recipient: {
id: 'dashboard.withdraw.completion.recipient',
defaultMessage: 'Recipient',
},
wallet: {
id: 'dashboard.withdraw.completion.wallet',
defaultMessage: 'Wallet',
},
account: {
id: 'dashboard.withdraw.completion.account',
defaultMessage: 'Account',
},
date: {
id: 'dashboard.withdraw.completion.date',
defaultMessage: 'Date',
},
amount: {
id: 'dashboard.withdraw.completion.amount',
defaultMessage: 'Amount',
},
fee: {
id: 'dashboard.withdraw.completion.fee',
defaultMessage: 'Fee',
},
netAmount: {
id: 'dashboard.withdraw.completion.net-amount',
defaultMessage: 'Net amount',
},
exchangeRate: {
id: 'dashboard.withdraw.completion.exchange-rate',
defaultMessage: 'Exchange rate',
},
emailConfirmation: {
id: 'dashboard.withdraw.completion.email-confirmation',
defaultMessage:
"You'll receive an email at <b>{email}</b> with instructions to redeem your withdrawal.",
},
closeButton: {
id: 'dashboard.withdraw.completion.close-button',
defaultMessage: 'Close',
},
transactionsButton: {
id: 'dashboard.withdraw.completion.transactions-button',
defaultMessage: 'Transactions',
},
})
</script>

View File

@@ -0,0 +1,352 @@
<template>
<div class="flex flex-col gap-4 sm:gap-5">
<div v-if="isPayPal" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast"
>{{ formatMessage(messages.paypalAccount) }} <span class="text-red">*</span></span
>
</label>
<div class="flex flex-col gap-2">
<ButtonStyled v-if="!isPayPalAuthenticated" color="standard">
<a :href="paypalAuthUrl" class="w-min" @click="handlePayPalAuth">
<PayPalColorIcon class="size-5" />
{{ formatMessage(messages.signInWithPaypal) }}
</a>
</ButtonStyled>
<ButtonStyled v-else>
<button class="w-min" @click="handleDisconnectPaypal">
<XIcon /> {{ formatMessage(messages.disconnectButton) }}
</button>
</ButtonStyled>
</div>
</div>
<div v-if="isPayPal && isPayPalAuthenticated" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">{{
formatMessage(messages.account)
}}</span>
</label>
<div class="flex flex-col gap-2 rounded-2xl bg-surface-2 px-4 py-2.5">
<span>{{ paypalEmail }}</span>
</div>
</div>
<div v-if="isVenmo" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast"
>{{ formatMessage(messages.venmoHandle) }} <span class="text-red">*</span></span
>
</label>
<div class="flex flex-row gap-2">
<input
v-model="venmoHandle"
type="text"
:placeholder="formatMessage(messages.venmoHandlePlaceholder)"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
<ButtonStyled color="brand">
<button
v-tooltip="!hasVenmoChanged ? 'Change the venmo username to save.' : undefined"
:disabled="venmoSaving || !hasVenmoChanged"
@click="saveVenmoHandle"
>
<CheckIcon v-if="venmoSaveSuccess" />
<SaveIcon v-else />
{{
venmoSaveSuccess
? formatMessage(messages.savedButton)
: formatMessage(messages.saveButton)
}}
</button>
</ButtonStyled>
</div>
<span v-if="venmoSaveError" class="text-sm font-bold text-red">
{{ venmoSaveError }}
</span>
</div>
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast"
>{{ formatMessage(formFieldLabels.amount) }} <span class="text-red">*</span></span
>
</label>
<RevenueInputField
v-model="formData.amount"
:max-amount="effectiveMaxAmount"
:min-amount="selectedMethodDetails?.interval?.standard?.min || 0.01"
/>
<WithdrawFeeBreakdown
:amount="formData.amount || 0"
:fee="calculatedFee"
:fee-loading="feeLoading"
/>
<Checkbox v-model="agreedTerms">
<span>
<IntlFormatted :message-id="financialMessages.rewardsProgramTermsAgreement">
<template #terms-link="{ children }">
<nuxt-link to="/legal/cmp" class="text-link">
<component :is="() => normalizeChildren(children)" />
</nuxt-link>
</template>
</IntlFormatted>
</span>
</Checkbox>
</div>
</div>
</template>
<script setup lang="ts">
import { CheckIcon, PayPalColorIcon, SaveIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, Checkbox, financialMessages, formFieldLabels } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import { useDebounceFn } from '@vueuse/core'
import { computed, onMounted, ref, watch } from 'vue'
import RevenueInputField from '@/components/ui/dashboard/RevenueInputField.vue'
import WithdrawFeeBreakdown from '@/components/ui/dashboard/WithdrawFeeBreakdown.vue'
import { getAuthUrl, removeAuthProvider, useAuth } from '@/composables/auth.js'
import { useWithdrawContext } from '@/providers/creator-withdraw.ts'
import { normalizeChildren } from '@/utils/vue-children.ts'
const { withdrawData, maxWithdrawAmount, availableMethods, calculateFees, saveStateToStorage } =
useWithdrawContext()
const { formatMessage } = useVIntl()
const auth = await useAuth()
const isPayPal = computed(() => withdrawData.value.selection.provider === 'paypal')
const isVenmo = computed(() => withdrawData.value.selection.provider === 'venmo')
const selectedMethodDetails = computed(() => {
const methodId = withdrawData.value.selection.methodId
if (!methodId) return null
return availableMethods.value.find((m) => m.id === methodId) || null
})
const isPayPalAuthenticated = computed(() => {
return (auth.value.user as any)?.auth_providers?.includes('paypal') || false
})
const paypalEmail = computed(() => {
return (auth.value.user as any)?.payout_data?.paypal_address || ''
})
const paypalAuthUrl = computed(() => {
const route = useRoute()
const authToken = useCookie('auth-token')
const separator = route.fullPath.includes('?') ? '&' : '?'
const returnUrl = `${route.fullPath}${separator}paypal_auth_return=true`
return `${getAuthUrl('paypal', returnUrl)}&auth_token=${authToken.value}`
})
function handlePayPalAuth() {
saveStateToStorage()
}
async function handleDisconnectPaypal() {
try {
await removeAuthProvider('paypal')
} catch (error) {
console.error('Failed to disconnect PayPal:', error)
}
}
const venmoHandle = ref<string>((auth.value.user as any)?.venmo_handle || '')
const initialVenmoHandle = ref<string>((auth.value.user as any)?.venmo_handle || '')
const venmoSaving = ref(false)
const venmoSaveSuccess = ref(false)
const venmoSaveError = ref<string | null>(null)
const hasVenmoChanged = computed(() => {
return venmoHandle.value.trim() !== initialVenmoHandle.value.trim()
})
async function saveVenmoHandle() {
if (!venmoHandle.value.trim()) {
venmoSaveError.value = 'Please enter a Venmo handle'
return
}
venmoSaving.value = true
venmoSaveError.value = null
venmoSaveSuccess.value = false
try {
await useBaseFetch(`user/${(auth.value.user as any)?.id}`, {
method: 'PATCH',
body: {
venmo_handle: venmoHandle.value.trim(),
},
})
// @ts-expect-error auth.js is not typed
await useAuth(auth.value.token)
initialVenmoHandle.value = venmoHandle.value.trim()
venmoSaveSuccess.value = true
setTimeout(() => {
venmoSaveSuccess.value = false
}, 3000)
} catch (error) {
console.error('Failed to update Venmo handle:', error)
venmoSaveError.value = 'Failed to save Venmo handle. Please try again.'
} finally {
venmoSaving.value = false
}
}
const maxAmount = computed(() => maxWithdrawAmount.value)
const roundedMaxAmount = computed(() => Math.floor(maxAmount.value * 100) / 100)
const effectiveMaxAmount = computed(() => {
const apiMax = selectedMethodDetails.value?.interval?.standard?.max
if (apiMax) {
return Math.min(roundedMaxAmount.value, apiMax)
}
return roundedMaxAmount.value
})
const formData = ref<Record<string, any>>({
amount: withdrawData.value.calculation.amount || undefined,
})
const agreedTerms = computed({
get: () => withdrawData.value.agreedTerms,
set: (value) => {
withdrawData.value.agreedTerms = value
},
})
const isComponentValid = computed(() => {
const hasAmount = (formData.value.amount || 0) > 0
const hasAgreed = agreedTerms.value
if (!hasAmount || !hasAgreed) return false
if (isPayPal.value) {
return isPayPalAuthenticated.value
} else if (isVenmo.value) {
return venmoHandle.value.trim().length > 0
}
return false
})
const calculatedFee = ref<number>(0)
const feeLoading = ref(false)
const calculateFeesDebounced = useDebounceFn(async () => {
const amount = formData.value.amount
if (!amount || amount <= 0) {
calculatedFee.value = 0
return
}
const methodId = withdrawData.value.selection.methodId
if (!methodId) {
calculatedFee.value = 0
return
}
feeLoading.value = true
try {
await calculateFees()
calculatedFee.value = withdrawData.value.calculation.fee ?? 0
} catch (error) {
console.error('Failed to calculate fees:', error)
calculatedFee.value = 0
} finally {
feeLoading.value = false
}
}, 500)
watch(
() => formData.value.amount,
() => {
withdrawData.value.calculation.amount = formData.value.amount ?? 0
if (formData.value.amount) {
feeLoading.value = true
calculateFeesDebounced()
} else {
calculatedFee.value = 0
feeLoading.value = false
}
},
{ deep: true },
)
watch(
[isComponentValid, venmoHandle, () => formData.value.amount, agreedTerms, isPayPalAuthenticated],
() => {
withdrawData.value.stageValidation.paypalDetails = isComponentValid.value
},
{ immediate: true },
)
onMounted(async () => {
if (formData.value.amount) {
feeLoading.value = true
calculateFeesDebounced()
}
})
const messages = defineMessages({
paymentMethod: {
id: 'dashboard.creator-withdraw-modal.paypal-details.payment-method',
defaultMessage: 'Payment method',
},
paypalAccount: {
id: 'dashboard.creator-withdraw-modal.paypal-details.paypal-account',
defaultMessage: 'PayPal account',
},
account: {
id: 'dashboard.creator-withdraw-modal.paypal-details.account',
defaultMessage: 'Account',
},
signInWithPaypal: {
id: 'dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal',
defaultMessage: 'Sign in with PayPal',
},
paypalAuthDescription: {
id: 'dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description',
defaultMessage: 'Connect your PayPal account to receive payments directly.',
},
venmoHandle: {
id: 'dashboard.creator-withdraw-modal.paypal-details.venmo-handle',
defaultMessage: 'Venmo handle',
},
venmoHandlePlaceholder: {
id: 'dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder',
defaultMessage: '@username',
},
venmoDescription: {
id: 'dashboard.creator-withdraw-modal.paypal-details.venmo-description',
defaultMessage: 'Enter your Venmo handle to receive payments.',
},
disconnectButton: {
id: 'dashboard.creator-withdraw-modal.paypal-details.disconnect-account',
defaultMessage: 'Disconnect account',
},
saveButton: {
id: 'dashboard.creator-withdraw-modal.paypal-details.save-button',
defaultMessage: 'Save',
},
savedButton: {
id: 'dashboard.creator-withdraw-modal.paypal-details.saved-button',
defaultMessage: 'Saved',
},
saveSuccess: {
id: 'dashboard.creator-withdraw-modal.paypal-details.save-success',
defaultMessage: 'Venmo handle saved successfully!',
},
})
</script>

View File

@@ -0,0 +1,323 @@
<template>
<div class="flex flex-col gap-4">
<Admonition v-if="shouldShowTaxLimitWarning" type="warning">
<IntlFormatted
:message-id="messages.taxLimitWarning"
:values="{
amount: formatMoney(maxWithdrawAmount),
}"
>
<template #b="{ children }">
<span class="font-semibold">
<component :is="() => normalizeChildren(children)" />
</span>
</template>
<template #tax-link="{ children }">
<span class="cursor-pointer text-link" @click="onShowTaxForm">
<component :is="() => normalizeChildren(children)" />
</span>
</template>
</IntlFormatted>
</Admonition>
<div class="flex flex-col">
<div class="flex flex-col gap-2.5">
<div class="flex flex-row gap-1 align-middle">
<span class="align-middle font-semibold text-contrast">{{
formatMessage(messages.region)
}}</span>
<UnknownIcon
v-tooltip="formatMessage(messages.regionTooltip)"
class="mt-auto size-5 text-secondary"
/>
</div>
<Combobox
:model-value="selectedCountryCode"
:options="countries"
:placeholder="formatMessage(messages.countryPlaceholder)"
searchable
:search-placeholder="formatMessage(messages.countrySearchPlaceholder)"
:max-height="240"
class="h-12"
@update:model-value="handleCountryChange"
/>
</div>
<div class="flex flex-col gap-2.5">
<div class="flex flex-row gap-1 align-middle">
<span class="align-middle font-semibold text-contrast">{{
formatMessage(messages.selectMethod)
}}</span>
</div>
<div v-if="loading" class="flex min-h-[120px] items-center justify-center">
<SpinnerIcon class="size-8 animate-spin text-contrast" />
</div>
<template v-else>
<ButtonStyled
v-for="method in paymentOptions"
:key="method.value"
:color="withdrawData.selection.method === method.value ? 'green' : 'standard'"
:highlighted="withdrawData.selection.method === method.value"
type="chip"
>
<button
class="!justify-start !gap-2 !text-left sm:!h-10"
@click="handleMethodSelection(method)"
>
<component :is="method.icon" class="shrink-0" />
<span class="flex-1 truncate text-sm sm:text-[1rem]">
{{ typeof method.label === 'string' ? method.label : formatMessage(method.label) }}
</span>
<span class="ml-auto shrink-0 text-xs font-normal text-secondary sm:text-sm">{{
method.fee
}}</span>
</button>
</ButtonStyled>
</template>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { SpinnerIcon, UnknownIcon } from '@modrinth/assets'
import {
Admonition,
ButtonStyled,
Combobox,
injectNotificationManager,
useDebugLogger,
} from '@modrinth/ui'
import { formatMoney } from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import { useGeolocation } from '@vueuse/core'
import { useCountries, useFormattedCountries, useUserCountry } from '@/composables/country.ts'
import { type PayoutMethod, useWithdrawContext } from '@/providers/creator-withdraw.ts'
import { normalizeChildren } from '@/utils/vue-children.ts'
const debug = useDebugLogger('MethodSelectionStage')
const {
withdrawData,
availableMethods,
paymentOptions,
balance,
maxWithdrawAmount,
paymentMethodsCache,
} = useWithdrawContext()
const userCountry = useUserCountry()
const allCountries = useCountries()
const { coords } = useGeolocation()
const { formatMessage } = useVIntl()
const { addNotification } = injectNotificationManager()
const auth = await useAuth()
const messages = defineMessages({
taxLimitWarning: {
id: 'dashboard.creator-withdraw-modal.method-selection.tax-limit-warning',
defaultMessage:
'Your withdraw limit is <b>{amount}</b>, <tax-link>complete a tax form</tax-link> to withdraw more.',
},
region: {
id: 'dashboard.creator-withdraw-modal.method-selection.region',
defaultMessage: 'Region',
},
regionTooltip: {
id: 'dashboard.creator-withdraw-modal.method-selection.region-tooltip',
defaultMessage: 'Some payout methods are not available in certain regions.',
},
countryPlaceholder: {
id: 'dashboard.creator-withdraw-modal.method-selection.country-placeholder',
defaultMessage: 'Select your country',
},
countrySearchPlaceholder: {
id: 'dashboard.creator-withdraw-modal.method-selection.country-search-placeholder',
defaultMessage: 'Search countries...',
},
selectMethod: {
id: 'dashboard.creator-withdraw-modal.method-selection.select-method',
defaultMessage: 'Select withdraw method',
},
errorTitle: {
id: 'dashboard.creator-withdraw-modal.method-selection.error-title',
defaultMessage: 'Failed to load payment methods',
},
errorText: {
id: 'dashboard.creator-withdraw-modal.method-selection.error-text',
defaultMessage: 'Unable to fetch available payment methods. Please try again later.',
},
})
defineProps<{
onShowTaxForm: () => void
}>()
const emit = defineEmits<{
(e: 'close-modal'): void
}>()
const countries = useFormattedCountries()
const selectedCountryCode = computed(() => withdrawData.value.selection.country?.id)
const shouldShowTaxLimitWarning = computed(() => {
const balanceValue = balance.value
if (!balanceValue) return false
const formIncomplete = balanceValue.form_completion_status !== 'complete'
const wouldHitLimit = (balanceValue.withdrawn_ytd ?? 0) + (balanceValue.available ?? 0) >= 600
return formIncomplete && wouldHitLimit
})
const loading = ref(false)
watch(
() => withdrawData.value.selection.country,
async (country) => {
debug('Watch triggered, country:', country)
if (!country) {
availableMethods.value = []
return
}
if (paymentMethodsCache.value[country.id]) {
debug('Using cached methods for', country.id)
availableMethods.value = paymentMethodsCache.value[country.id]
return
}
loading.value = true
debug('Fetching payout methods for country:', country.id)
try {
const methods = (await useBaseFetch('payout/methods', {
apiVersion: 3,
query: { country: country.id },
})) as PayoutMethod[]
debug('Received payout methods:', methods)
paymentMethodsCache.value[country.id] = methods
availableMethods.value = methods
} catch (e) {
console.error('[MethodSelectionStage] Failed to fetch payout methods:', e)
addNotification({
title: formatMessage(messages.errorTitle),
text: formatMessage(messages.errorText),
type: 'error',
})
emit('close-modal')
} finally {
loading.value = false
}
},
{ immediate: true },
)
function handleMethodSelection(option: {
value: string
methodId: string | undefined
type: string
}) {
withdrawData.value.selection.method = option.value
withdrawData.value.selection.methodId = option.methodId ?? null
if (option.type === 'tremendous') {
withdrawData.value.selection.provider = 'tremendous'
} else if (option.type === 'fiat' || option.type === 'crypto') {
withdrawData.value.selection.provider = 'muralpay'
} else if (option.type === 'paypal') {
withdrawData.value.selection.provider = 'paypal'
} else if (option.type === 'venmo') {
withdrawData.value.selection.provider = 'venmo'
} else {
withdrawData.value.selection.provider = 'muralpay'
}
}
watch(paymentOptions, (newOptions) => {
withdrawData.value.selection.method = null
withdrawData.value.selection.methodId = null
withdrawData.value.selection.provider = null
if (newOptions.length === 1) {
const option = newOptions[0]
handleMethodSelection(option)
}
})
watch(
() => withdrawData.value.selection.provider,
(newProvider) => {
if (newProvider === 'tremendous') {
const userEmail = (auth.value.user as any)?.email || ''
withdrawData.value.providerData = {
type: 'tremendous',
deliveryEmail: userEmail,
giftCardDetails: null,
currency: undefined,
}
} else if (newProvider === 'muralpay') {
withdrawData.value.providerData = {
type: 'muralpay',
kycData: {} as any,
accountDetails: {},
}
} else if (newProvider === 'paypal' || newProvider === 'venmo') {
withdrawData.value.providerData = {
type: newProvider,
}
}
},
)
function handleCountryChange(countryCode: string | null) {
debug('handleCountryChange called with:', countryCode)
if (countryCode) {
const normalizedCode = countryCode.toUpperCase()
const country = allCountries.value.find((c) => c.alpha2 === normalizedCode)
debug('Found country:', country)
if (country) {
withdrawData.value.selection.country = {
id: country.alpha2,
name: country.alpha2 === 'TW' ? 'Taiwan' : country.nameShort,
}
debug('Set selectedCountry to:', withdrawData.value.selection.country)
}
} else {
withdrawData.value.selection.country = null
}
}
debug('Setup: userCountry.value =', userCountry.value)
debug('Setup: current selectedCountry =', withdrawData.value.selection.country)
if (!withdrawData.value.selection.country) {
const defaultCountryCode = userCountry.value || 'US'
debug('Setup: calling handleCountryChange with', defaultCountryCode)
handleCountryChange(defaultCountryCode)
debug('Setup: selectedCountryCode computed =', selectedCountryCode.value)
}
async function getCountryFromGeoIP(lat: number, lon: number): Promise<string | null> {
try {
const response = await fetch(
`https://api.bigdatacloud.net/data/reverse-geocode-client?latitude=${lat}&longitude=${lon}&localityLanguage=en`,
)
const data = await response.json()
return data.countryCode || null
} catch {
return null
}
}
onMounted(async () => {
if (withdrawData.value.selection.country?.id === 'US' && !userCountry.value) {
if (coords.value.latitude && coords.value.longitude) {
const geoCountry = await getCountryFromGeoIP(coords.value.latitude, coords.value.longitude)
if (geoCountry) {
handleCountryChange(geoCountry)
}
}
}
})
</script>

View File

@@ -0,0 +1,516 @@
<template>
<div class="flex flex-col gap-3 sm:gap-4">
<Admonition
v-if="selectedRail?.warningMessage"
type="warning"
:header="formatMessage(messages.cryptoWarningHeader)"
>
{{ formatMessage(selectedRail.warningMessage) }}
</Admonition>
<div v-if="selectedRail?.type === 'crypto'" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(messages.coin) }}
</span>
</label>
<div
class="flex min-h-[44px] items-center gap-2 rounded-[14px] bg-surface-2 px-4 py-2.5 sm:min-h-0"
>
<component
:is="getCurrencyIcon(selectedRail.currency)"
class="size-5 shrink-0"
:class="getCurrencyColor(selectedRail.currency)"
/>
<span class="text-sm font-semibold text-contrast sm:text-[1rem]">{{
selectedRail.currency
}}</span>
</div>
</div>
<div v-if="selectedRail?.type === 'fiat'" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(messages.accountOwner) }}
</span>
</label>
<div class="w-full rounded-[14px] bg-surface-2 p-3 sm:p-4">
<div class="flex flex-col gap-1">
<span class="break-words text-sm font-semibold text-contrast sm:text-[1rem]">
{{ accountOwnerName }}
</span>
<span class="break-words text-xs text-primary sm:text-sm">
{{ accountOwnerAddress }}
</span>
</div>
</div>
</div>
<div v-if="selectedRail?.requiresBankName" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.bankName) }}
<span class="text-red">*</span>
</span>
</label>
<Combobox
v-if="shouldShowBankNameDropdown"
v-model="formData.bankName"
:options="bankNameOptions"
:searchable="true"
:placeholder="formatMessage(formFieldPlaceholders.bankNamePlaceholderDropdown)"
class="h-10"
/>
<input
v-else
v-model="formData.bankName"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.bankNamePlaceholder)"
autocomplete="off"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
</div>
<div v-for="field in selectedRail?.fields" :key="field.name" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(field.label) }}
<span v-if="field.required" class="text-red">*</span>
</span>
</label>
<input
v-if="['text', 'email', 'tel'].includes(field.type)"
v-model="formData[field.name]"
:type="field.type"
:placeholder="field.placeholder ? formatMessage(field.placeholder) : undefined"
:pattern="field.pattern"
:autocomplete="field.autocomplete || 'off'"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
<Combobox
v-else-if="field.type === 'select'"
v-model="formData[field.name]"
:options="
(field.options || []).map((opt) => ({
value: opt.value,
label: formatMessage(opt.label),
}))
"
:placeholder="field.placeholder ? formatMessage(field.placeholder) : undefined"
class="h-10"
/>
<input
v-else-if="field.type === 'date'"
v-model="formData[field.name]"
type="date"
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
/>
<span v-if="field.helpText" class="text-sm text-secondary">
{{ formatMessage(field.helpText) }}
</span>
</div>
<Transition
enter-active-class="transition-all duration-300 ease-out"
enter-from-class="opacity-0 max-h-0"
enter-to-class="opacity-100 max-h-40"
leave-active-class="transition-all duration-200 ease-in"
leave-from-class="opacity-100 max-h-40"
leave-to-class="opacity-0 max-h-0"
>
<div v-if="dynamicDocumentNumberField" class="overflow-hidden">
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ dynamicDocumentNumberField.label }}
<span v-if="dynamicDocumentNumberField.required" class="text-red">*</span>
</span>
</label>
<input
v-model="formData.documentNumber"
:type="dynamicDocumentNumberField.type"
:placeholder="dynamicDocumentNumberField.placeholder"
autocomplete="off"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
</div>
</div>
</Transition>
<div v-if="selectedRail?.blockchain" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(messages.network) }}
</span>
</label>
<div
class="flex min-h-[44px] items-center gap-2 rounded-[14px] bg-surface-2 px-4 py-2.5 sm:min-h-0"
>
<component
:is="getBlockchainIcon(selectedRail.blockchain)"
class="size-5 shrink-0"
:class="getBlockchainColor(selectedRail.blockchain)"
/>
<span class="text-sm font-semibold text-contrast sm:text-[1rem]">{{
selectedRail.blockchain
}}</span>
</div>
</div>
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.amount) }}
<span class="text-red">*</span>
</span>
</label>
<RevenueInputField
v-model="formData.amount"
:min-amount="effectiveMinAmount"
:max-amount="effectiveMaxAmount"
/>
<WithdrawFeeBreakdown
v-if="allRequiredFieldsFilled"
:amount="formData.amount || 0"
:fee="calculatedFee"
:fee-loading="feeLoading"
:exchange-rate="exchangeRate"
:local-currency="selectedRail?.currency"
/>
<Checkbox v-model="agreedTerms">
<span
><IntlFormatted :message-id="financialMessages.rewardsProgramTermsAgreement">
<template #terms-link="{ children }">
<nuxt-link to="/legal/cmp" class="text-link">
<component :is="() => normalizeChildren(children)" />
</nuxt-link>
</template> </IntlFormatted
></span>
</Checkbox>
</div>
</div>
</template>
<script setup lang="ts">
import {
Admonition,
Checkbox,
Combobox,
financialMessages,
formFieldLabels,
formFieldPlaceholders,
} from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import { useDebounceFn } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import RevenueInputField from '@/components/ui/dashboard/RevenueInputField.vue'
import WithdrawFeeBreakdown from '@/components/ui/dashboard/WithdrawFeeBreakdown.vue'
import { useGeneratedState } from '@/composables/generated'
import { useWithdrawContext } from '@/providers/creator-withdraw.ts'
import {
getBlockchainColor,
getBlockchainIcon,
getCurrencyColor,
getCurrencyIcon,
} from '@/utils/finance-icons.ts'
import { getRailConfig } from '@/utils/muralpay-rails'
import { normalizeChildren } from '@/utils/vue-children.ts'
const { withdrawData, maxWithdrawAmount, availableMethods, calculateFees } = useWithdrawContext()
const { formatMessage } = useVIntl()
const generatedState = useGeneratedState()
const selectedRail = computed(() => {
const railId = withdrawData.value.selection.method
return railId ? getRailConfig(railId) : null
})
const selectedMethodDetails = computed(() => {
const methodId = withdrawData.value.selection.methodId
if (!methodId) return null
return availableMethods.value.find((m) => m.id === methodId) || null
})
const maxAmount = computed(() => maxWithdrawAmount.value)
const roundedMaxAmount = computed(() => Math.floor(maxAmount.value * 100) / 100)
const effectiveMinAmount = computed(
() => selectedMethodDetails.value?.interval?.standard?.min || 0.01,
)
const effectiveMaxAmount = computed(() => {
const apiMax = selectedMethodDetails.value?.interval?.standard?.max
if (apiMax) {
return Math.min(roundedMaxAmount.value, apiMax)
}
return roundedMaxAmount.value
})
const availableBankNames = computed(() => {
const rail = selectedRail.value
if (!rail || !rail.railCode) return []
const bankDetails = generatedState.value.muralBankDetails?.[rail.railCode]
return bankDetails?.bankNames || []
})
const shouldShowBankNameDropdown = computed(() => {
return availableBankNames.value.length > 0
})
const bankNameOptions = computed(() => {
return availableBankNames.value.map((name) => ({
value: name,
label: name,
}))
})
const providerData = withdrawData.value.providerData
const existingAccountDetails = providerData.type === 'muralpay' ? providerData.accountDetails : {}
const existingAmount = withdrawData.value.calculation.amount
const formData = ref<Record<string, any>>({
amount: existingAmount || undefined,
bankName: existingAccountDetails?.bankName ?? '',
...existingAccountDetails,
})
const agreedTerms = computed({
get: () => withdrawData.value.agreedTerms,
set: (value) => {
withdrawData.value.agreedTerms = value
},
})
const calculatedFee = ref<number | null>(null)
const exchangeRate = ref<number | null>(null)
const feeLoading = ref(false)
const hasDocumentTypeField = computed(() => {
const rail = selectedRail.value
if (!rail) return false
return rail.fields.some((field) => field.name === 'documentType')
})
const dynamicDocumentNumberField = computed(() => {
if (!hasDocumentTypeField.value) return null
const documentType = formData.value.documentType
if (!documentType) return null
const labelMap: Record<string, string> = {
NATIONAL_ID: formatMessage(messages.documentNumberNationalId),
PASSPORT: formatMessage(messages.documentNumberPassport),
RESIDENT_ID: formatMessage(messages.documentNumberResidentId),
RUC: formatMessage(messages.documentNumberRuc),
TAX_ID: formatMessage(messages.documentNumberTaxId),
}
const placeholderMap: Record<string, string> = {
NATIONAL_ID: formatMessage(messages.documentNumberNationalIdPlaceholder),
PASSPORT: formatMessage(messages.documentNumberPassportPlaceholder),
RESIDENT_ID: formatMessage(messages.documentNumberResidentIdPlaceholder),
RUC: formatMessage(messages.documentNumberRucPlaceholder),
TAX_ID: formatMessage(messages.documentNumberTaxIdPlaceholder),
}
return {
name: 'documentNumber',
type: 'text' as const,
label: labelMap[documentType] || 'Document number',
placeholder: placeholderMap[documentType] || 'Enter document number',
required: true,
}
})
const accountOwnerName = computed(() => {
const providerDataValue = withdrawData.value.providerData
if (providerDataValue.type !== 'muralpay') return ''
const kycData = providerDataValue.kycData
if (!kycData) return ''
if (kycData.type === 'individual') {
return `${kycData.firstName} ${kycData.lastName}`
} else if (kycData.type === 'business') {
return kycData.name
}
return ''
})
const accountOwnerAddress = computed(() => {
const providerDataValue = withdrawData.value.providerData
if (providerDataValue.type !== 'muralpay') return ''
const kycData = providerDataValue.kycData
if (!kycData || !kycData.physicalAddress) return ''
const addr = kycData.physicalAddress
const parts = [
addr.address1,
addr.address2,
addr.city,
addr.state,
addr.zip,
addr.country,
].filter(Boolean)
return parts.join(', ')
})
const allRequiredFieldsFilled = computed(() => {
const rail = selectedRail.value
if (!rail) return false
const amount = formData.value.amount
if (!amount || amount <= 0) return false
if (rail.requiresBankName && !formData.value.bankName) return false
const requiredFields = rail.fields.filter((f) => f.required)
const allRequiredPresent = requiredFields.every((f) => {
const value = formData.value[f.name]
return value !== undefined && value !== null && value !== ''
})
if (!allRequiredPresent) return false
if (dynamicDocumentNumberField.value?.required && !formData.value.documentNumber) return false
return true
})
const calculateFeesDebounced = useDebounceFn(async () => {
const amount = formData.value.amount
const rail = selectedRail.value
const providerDataValue = withdrawData.value.providerData
const kycData = providerDataValue.type === 'muralpay' ? providerDataValue.kycData : null
if (!amount || amount <= 0 || !rail || !kycData) {
calculatedFee.value = null
exchangeRate.value = null
return
}
feeLoading.value = true
try {
await calculateFees()
calculatedFee.value = withdrawData.value.calculation.fee
exchangeRate.value = withdrawData.value.calculation.exchangeRate
} catch (error) {
console.error('Failed to calculate fees:', error)
calculatedFee.value = 0
exchangeRate.value = null
} finally {
feeLoading.value = false
}
}, 500)
watch(
formData,
() => {
withdrawData.value.calculation.amount = formData.value.amount ?? 0
if (withdrawData.value.providerData.type === 'muralpay') {
withdrawData.value.providerData.accountDetails = { ...formData.value }
}
if (allRequiredFieldsFilled.value) {
feeLoading.value = true
calculateFeesDebounced()
} else {
calculatedFee.value = null
exchangeRate.value = null
feeLoading.value = false
}
},
{ deep: true },
)
if (allRequiredFieldsFilled.value) {
feeLoading.value = true
calculateFeesDebounced()
}
watch(
() => withdrawData.value.selection.method,
(newMethod, oldMethod) => {
if (oldMethod && newMethod !== oldMethod) {
formData.value = {
amount: undefined,
bankName: '',
}
if (withdrawData.value.providerData.type === 'muralpay') {
withdrawData.value.providerData.accountDetails = {}
}
withdrawData.value.calculation.amount = 0
calculatedFee.value = null
exchangeRate.value = null
}
},
)
const messages = defineMessages({
accountOwner: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.account-owner',
defaultMessage: 'Account owner',
},
cryptoWarningHeader: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header',
defaultMessage: 'Confirm your wallet address',
},
coin: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.coin',
defaultMessage: 'Coin',
},
network: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.network',
defaultMessage: 'Network',
},
documentNumberNationalId: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id',
defaultMessage: 'National ID number',
},
documentNumberPassport: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-passport',
defaultMessage: 'Passport number',
},
documentNumberResidentId: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id',
defaultMessage: 'Resident ID number',
},
documentNumberRuc: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc',
defaultMessage: 'RUC number',
},
documentNumberTaxId: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id',
defaultMessage: 'Tax ID number',
},
documentNumberNationalIdPlaceholder: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder',
defaultMessage: 'Enter national ID number',
},
documentNumberPassportPlaceholder: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder',
defaultMessage: 'Enter passport number',
},
documentNumberResidentIdPlaceholder: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder',
defaultMessage: 'Enter resident ID number',
},
documentNumberRucPlaceholder: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder',
defaultMessage: 'Enter RUC number',
},
documentNumberTaxIdPlaceholder: {
id: 'dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder',
defaultMessage: 'Enter tax ID number',
},
})
</script>

View File

@@ -0,0 +1,362 @@
<template>
<div class="flex flex-col gap-3 sm:gap-4">
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(messages.entityQuestion) }}
<span class="text-red">*</span>
</span>
</label>
<Chips
v-model="entityType"
:items="['individual', 'business']"
:format-label="
(item: string) =>
item === 'individual'
? formatMessage(messages.privateIndividual)
: formatMessage(messages.businessEntity)
"
:never-empty="false"
:capitalize="false"
/>
<span class="leading-tight text-primary">
{{ formatMessage(messages.entityDescription) }}
</span>
</div>
<div v-if="entityType" class="flex flex-col gap-4">
<div v-if="entityType === 'business'" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.businessName) }}
<span class="text-red">*</span>
</span>
</label>
<input
v-model="formData.businessName"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.businessNamePlaceholder)"
autocomplete="organization"
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
/>
</div>
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.email) }}
<span class="text-red">*</span>
</span>
</label>
<input
v-model="formData.email"
type="email"
:placeholder="formatMessage(formFieldPlaceholders.emailPlaceholder)"
autocomplete="email"
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
/>
</div>
<div v-if="entityType === 'individual'" class="flex flex-col gap-6">
<div class="flex flex-col gap-3 sm:flex-row sm:gap-4">
<div class="flex flex-1 flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.firstName) }}
<span class="text-red">*</span>
</span>
</label>
<input
v-model="formData.firstName"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.firstNamePlaceholder)"
autocomplete="given-name"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
</div>
<div class="flex flex-1 flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.lastName) }}
<span class="text-red">*</span>
</span>
</label>
<input
v-model="formData.lastName"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.lastNamePlaceholder)"
autocomplete="family-name"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
</div>
</div>
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.dateOfBirth) }}
<span class="text-red">*</span>
</span>
</label>
<input
v-model="formData.dateOfBirth"
type="date"
:max="maxDate"
autocomplete="bday"
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
/>
</div>
</div>
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.addressLine) }}
<span class="text-red">*</span>
</span>
</label>
<input
v-model="formData.physicalAddress.address1"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.addressPlaceholder)"
autocomplete="address-line1"
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
/>
</div>
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.addressLine2) }}
</span>
</label>
<input
v-model="formData.physicalAddress.address2"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.address2Placeholder)"
autocomplete="address-line2"
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
/>
</div>
<div class="flex flex-col gap-3 sm:flex-row sm:gap-4">
<div class="flex flex-1 flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.city) }}
<span class="text-red">*</span>
</span>
</label>
<input
v-model="formData.physicalAddress.city"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.cityPlaceholder)"
autocomplete="address-level2"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
</div>
<div class="flex flex-1 flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.stateProvince) }}
<span class="text-red">*</span>
</span>
</label>
<Combobox
v-if="subdivisionOptions.length > 0"
v-model="formData.physicalAddress.state"
:options="subdivisionOptions"
:placeholder="formatMessage(formFieldPlaceholders.statePlaceholder)"
searchable
search-placeholder="Search subdivisions..."
/>
<input
v-else
v-model="formData.physicalAddress.state"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.statePlaceholder)"
autocomplete="address-level1"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
</div>
</div>
<div class="flex flex-col gap-3 sm:flex-row sm:gap-4">
<div class="flex flex-1 flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.postalCode) }}
<span class="text-red">*</span>
</span>
</label>
<input
v-model="formData.physicalAddress.zip"
type="text"
:placeholder="formatMessage(formFieldPlaceholders.postalCodePlaceholder)"
autocomplete="postal-code"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
</div>
<div class="flex flex-1 flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(formFieldLabels.country) }}
<span class="text-red">*</span>
</span>
</label>
<Combobox
v-model="formData.physicalAddress.country"
:options="countryOptions"
:placeholder="formatMessage(formFieldPlaceholders.countryPlaceholder)"
searchable
search-placeholder="Search countries..."
/>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { Chips, Combobox, formFieldLabels, formFieldPlaceholders } from '@modrinth/ui'
import { useVIntl } from '@vintl/vintl'
import { useFormattedCountries } from '@/composables/country.ts'
import { useGeneratedState } from '@/composables/generated.ts'
import { useWithdrawContext } from '@/providers/creator-withdraw.ts'
const { withdrawData } = useWithdrawContext()
const { formatMessage } = useVIntl()
const generatedState = useGeneratedState()
const providerData = withdrawData.value.providerData
const existingKycData = providerData.type === 'muralpay' ? providerData.kycData : null
const entityType = ref<'individual' | 'business' | null>(existingKycData?.type ?? null)
interface PayoutRecipientInfoMerged {
email: string
firstName?: string
lastName?: string
dateOfBirth?: string
businessName?: string
physicalAddress: {
address1: string
address2: string | null
country: string
state: string
city: string
zip: string
}
}
const auth = await useAuth()
const formData = ref<PayoutRecipientInfoMerged>({
email: existingKycData?.email ?? `${(auth.value.user as any)?.email}`,
firstName: existingKycData?.type === 'individual' ? existingKycData.firstName : '',
lastName: existingKycData?.type === 'individual' ? existingKycData.lastName : '',
dateOfBirth: existingKycData?.type === 'individual' ? existingKycData.dateOfBirth : '',
businessName: existingKycData?.type === 'business' ? existingKycData.name : '',
physicalAddress: {
address1: existingKycData?.physicalAddress?.address1 ?? '',
address2: existingKycData?.physicalAddress?.address2 ?? null,
country:
existingKycData?.physicalAddress?.country ?? withdrawData.value.selection.country?.id ?? '',
state: existingKycData?.physicalAddress?.state ?? '',
city: existingKycData?.physicalAddress?.city ?? '',
zip: existingKycData?.physicalAddress?.zip ?? '',
},
})
const maxDate = computed(() => {
const today = new Date()
const year = today.getFullYear() - 18
const month = String(today.getMonth() + 1).padStart(2, '0')
const day = String(today.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
})
const countryOptions = useFormattedCountries()
const subdivisionOptions = computed(() => {
const selectedCountry = formData.value.physicalAddress.country
if (!selectedCountry) return []
const subdivisions = generatedState.value.subdivisions?.[selectedCountry] ?? []
return subdivisions.map((sub) => ({
value: sub.code.includes('-') ? sub.code.split('-')[1] : sub.code,
label: sub.localVariant || sub.name,
}))
})
watch(
[entityType, formData],
() => {
if (!entityType.value) {
if (withdrawData.value.providerData.type === 'muralpay') {
withdrawData.value.providerData.kycData = null as any
}
return
}
if (withdrawData.value.providerData.type !== 'muralpay') return
if (entityType.value === 'individual') {
if (formData.value.dateOfBirth) {
withdrawData.value.providerData.kycData = {
type: 'individual',
firstName: formData.value.firstName || '',
lastName: formData.value.lastName || '',
email: formData.value.email,
dateOfBirth: formData.value.dateOfBirth,
physicalAddress: {
address1: formData.value.physicalAddress.address1,
address2: formData.value.physicalAddress.address2 || undefined,
country: formData.value.physicalAddress.country,
state: formData.value.physicalAddress.state,
city: formData.value.physicalAddress.city,
zip: formData.value.physicalAddress.zip,
},
}
}
} else {
withdrawData.value.providerData.kycData = {
type: 'business',
name: formData.value.businessName || '',
email: formData.value.email,
physicalAddress: {
address1: formData.value.physicalAddress.address1,
address2: formData.value.physicalAddress.address2 || undefined,
country: formData.value.physicalAddress.country,
state: formData.value.physicalAddress.state,
city: formData.value.physicalAddress.city,
zip: formData.value.physicalAddress.zip,
},
}
}
},
{ deep: true },
)
const messages = defineMessages({
entityQuestion: {
id: 'dashboard.creator-withdraw-modal.kyc.entity-question',
defaultMessage: 'Are you a withdrawing as an individual or business?',
},
entityDescription: {
id: 'dashboard.creator-withdraw-modal.kyc.entity-description',
defaultMessage:
'A business entity refers to a registered organization such as a corporation, partnership, or LLC.',
},
privateIndividual: {
id: 'dashboard.creator-withdraw-modal.kyc.private-individual',
defaultMessage: 'Private individual',
},
businessEntity: {
id: 'dashboard.creator-withdraw-modal.kyc.business-entity',
defaultMessage: 'Business entity',
},
})
</script>

View File

@@ -0,0 +1,159 @@
<template>
<div class="flex flex-col gap-2.5 sm:gap-3">
<div class="flex flex-col gap-3">
<div class="flex w-full flex-col gap-1 sm:flex-row sm:justify-between sm:gap-0">
<span class="font-semibold text-contrast">{{ formatMessage(messages.withdrawLimit) }}</span>
<div>
<span class="text-orange">{{ formatMoney(usedLimit) }}</span> /
<span class="text-contrast">{{ formatMoney(600) }}</span>
</div>
</div>
<div class="flex h-2.5 w-full overflow-hidden rounded-full bg-surface-2">
<div
v-if="usedLimit > 0"
class="gradient-border bg-orange"
:style="{ width: `${(usedLimit / 600) * 100}%` }"
></div>
</div>
</div>
<template v-if="remainingLimit > 0">
<span>
<IntlFormatted
:message-id="messages.nearingThreshold"
:values="{
amountRemaining: formatMoney(remainingLimit),
}"
>
<template #b="{ children }">
<span class="font-medium">
<component :is="() => normalizeChildren(children)" />
</span>
</template>
</IntlFormatted>
</span>
<Admonition
type="warning"
show-actions-underneath
:header="formatMessage(messages.taxFormRequiredHeader)"
>
<span class="text-sm font-normal md:text-base">
{{
formatMessage(messages.taxFormRequiredBodyWithLimit, {
limit: formatMoney(remainingLimit),
})
}}
</span>
<template #icon="{ iconClass }">
<FileTextIcon :class="iconClass" />
</template>
<template #actions>
<ButtonStyled color="orange">
<button @click="showTaxFormModal">
{{ formatMessage(messages.completeTaxForm) }}
</button>
</ButtonStyled>
</template>
</Admonition>
</template>
<template v-else>
<span>
<IntlFormatted
:message-id="messages.withdrawLimitUsed"
:values="{ withdrawLimit: formatMoney(600) }"
>
<template #b="{ children }">
<b>
<component :is="() => normalizeChildren(children)" />
</b>
</template>
</IntlFormatted>
</span>
</template>
</div>
</template>
<script setup lang="ts">
import { FileTextIcon } from '@modrinth/assets'
import { Admonition, ButtonStyled } from '@modrinth/ui'
import { formatMoney } from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import { computed } from 'vue'
import { TAX_THRESHOLD_ACTUAL } from '@/providers/creator-withdraw.ts'
import { normalizeChildren } from '@/utils/vue-children.ts'
const props = defineProps<{
balance: any
onShowTaxForm: () => void
}>()
const { formatMessage } = useVIntl()
const usedLimit = computed(() => props.balance?.withdrawn_ytd ?? 0)
const remainingLimit = computed(() => {
const raw = TAX_THRESHOLD_ACTUAL - usedLimit.value
if (raw <= 0) return 0
const cents = Math.floor(raw * 100)
return cents / 100
})
function showTaxFormModal() {
props.onShowTaxForm()
}
const messages = defineMessages({
withdrawLimit: {
id: 'dashboard.creator-withdraw-modal.withdraw-limit',
defaultMessage: 'Withdraw limit',
},
nearingThreshold: {
id: 'dashboard.creator-withdraw-modal.nearing-threshold',
defaultMessage:
"You're nearing the withdraw threshold. You can withdraw <b>{amountRemaining}</b> now, but a tax form is required for more.",
},
taxFormRequiredHeader: {
id: 'dashboard.creator-withdraw-modal.tax-form-required.header',
defaultMessage: 'Tax form required',
},
taxFormRequiredBody: {
id: 'dashboard.creator-withdraw-modal.tax-form-required.body',
defaultMessage:
'To withdraw your full <b>{available}</b> available balance please complete the form below. It is required for tax reporting and only needs to be done once.',
},
taxFormRequiredBodyWithLimit: {
id: 'dashboard.creator-withdraw-modal.tax-form-required.body-with-limit',
defaultMessage:
"You must complete a W-9 or W-8 form for Modrinth's tax records so we remain compliant with tax regulations.",
},
completeTaxForm: {
id: 'dashboard.creator-withdraw-modal.complete-tax-form',
defaultMessage: 'Complete tax form',
},
withdrawLimitUsed: {
id: 'dashboard.creator-withdraw-modal.withdraw-limit-used',
defaultMessage:
"You've used up your <b>{withdrawLimit}</b> withdrawal limit. You must complete a tax form to withdraw more.",
},
})
</script>
<style lang="css" scoped>
.gradient-border {
position: relative;
&::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), transparent);
border-radius: inherit;
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask-composite: xor;
padding: 2px;
pointer-events: none;
}
}
</style>

View File

@@ -0,0 +1,653 @@
<template>
<div class="flex flex-col gap-4 sm:gap-5">
<Transition
enter-active-class="transition-all duration-300 ease-out"
enter-from-class="opacity-0 max-h-0"
enter-to-class="opacity-100 max-h-40"
leave-active-class="transition-all duration-200 ease-in"
leave-from-class="opacity-100 max-h-40"
leave-to-class="opacity-0 max-h-0"
>
<div v-if="isUnverifiedEmail" class="overflow-hidden">
<Admonition type="warning" :header="formatMessage(messages.unverifiedEmailHeader)">
{{ formatMessage(messages.unverifiedEmailMessage) }}
</Admonition>
</div>
</Transition>
<Transition
enter-active-class="transition-all duration-300 ease-out"
enter-from-class="opacity-0 max-h-0"
enter-to-class="opacity-100 max-h-40"
leave-active-class="transition-all duration-200 ease-in"
leave-from-class="opacity-100 max-h-40"
leave-to-class="opacity-0 max-h-0"
>
<div v-if="shouldShowUsdWarning" class="overflow-hidden">
<Admonition type="warning" :header="formatMessage(messages.usdPaypalWarningHeader)">
<IntlFormatted :message-id="messages.usdPaypalWarningMessage">
<template #direct-paypal-link="{ children }">
<span class="cursor-pointer text-link" @click="switchToDirectPaypal">
<component :is="() => normalizeChildren(children)" />
</span>
</template>
</IntlFormatted>
</Admonition>
</div>
</Transition>
<div v-if="!showGiftCardSelector && selectedMethodDisplay" class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast">
{{ formatMessage(messages.paymentMethod) }}
</span>
</label>
<div
class="flex min-h-[44px] items-center gap-2 rounded-[14px] bg-surface-2 px-4 py-2.5 sm:min-h-0"
>
<component :is="selectedMethodDisplay.icon" class="size-5 shrink-0" />
<span class="break-words text-sm font-semibold text-contrast sm:text-[1rem]">{{
typeof selectedMethodDisplay.label === 'string'
? selectedMethodDisplay.label
: formatMessage(selectedMethodDisplay.label)
}}</span>
</div>
</div>
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast"
>{{ formatMessage(formFieldLabels.email) }} <span class="text-red">*</span></span
>
</label>
<input
v-model="deliveryEmail"
type="email"
:placeholder="formatMessage(formFieldPlaceholders.emailPlaceholder)"
autocomplete="email"
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
/>
</div>
<div v-if="showGiftCardSelector" class="flex flex-col gap-1">
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast"
>{{ categoryLabel }} <span class="text-red">*</span></span
>
</label>
<Combobox
v-model="selectedGiftCardId"
:options="rewardOptions"
:placeholder="`Select ${categoryLabel.toLowerCase()}`"
searchable
:search-placeholder="`Search ${categoryLabelPlural.toLowerCase()}...`"
class="h-10"
>
<template #selected>
<div v-if="selectedRewardOption" class="flex items-center gap-2">
<img
v-if="selectedRewardOption.imageUrl"
:src="selectedRewardOption.imageUrl"
:alt="selectedRewardOption.label"
class="size-5 rounded-full object-cover"
loading="lazy"
/>
<span class="font-semibold leading-tight">{{ selectedRewardOption.label }}</span>
</div>
</template>
<template v-for="option in rewardOptions" :key="option.value" #[`option-${option.value}`]>
<div class="flex items-center gap-2">
<img
v-if="option.imageUrl"
:src="option.imageUrl"
:alt="option.label"
class="size-5 rounded-full object-cover"
loading="lazy"
/>
<span class="font-semibold leading-tight">{{ option.label }}</span>
</div>
</template>
</Combobox>
</div>
<span v-if="selectedMethodDetails" class="text-secondary">
{{ formatMoney(effectiveMinAmount) }} min,
{{ formatMoney(selectedMethodDetails.interval?.standard?.max ?? effectiveMaxAmount) }}
max withdrawal amount.
</span>
</div>
<div class="flex flex-col gap-2.5">
<label>
<span class="text-md font-semibold text-contrast"
>{{ formatMessage(formFieldLabels.amount) }} <span class="text-red">*</span></span
>
</label>
<div v-if="showGiftCardSelector && useFixedDenominations" class="flex flex-col gap-2.5">
<Chips
v-model="selectedDenomination"
:items="denominationOptions"
:format-label="(amt: number) => formatMoney(amt)"
:never-empty="false"
:capitalize="false"
/>
<span v-if="denominationOptions.length === 0" class="text-error text-sm">
No denominations available for your current balance
</span>
</div>
<div v-else class="flex flex-col gap-2">
<RevenueInputField
v-model="formData.amount"
v-model:selected-currency="selectedCurrency"
:max-amount="effectiveMaxAmount"
:min-amount="effectiveMinAmount"
:show-currency-selector="showPayPalCurrencySelector"
:currency-options="currencyOptions"
/>
</div>
<WithdrawFeeBreakdown
v-if="allRequiredFieldsFilled"
:amount="formData.amount || 0"
:fee="calculatedFee"
:fee-loading="feeLoading"
:exchange-rate="exchangeRate"
:local-currency="showPayPalCurrencySelector ? selectedCurrency : undefined"
/>
<Checkbox v-model="agreedTerms">
<span>
<IntlFormatted :message-id="financialMessages.rewardsProgramTermsAgreement">
<template #terms-link="{ children }">
<nuxt-link to="/legal/cmp" class="text-link">
<component :is="() => normalizeChildren(children)" />
</nuxt-link>
</template>
</IntlFormatted>
</span>
</Checkbox>
</div>
</div>
</template>
<script setup lang="ts">
import {
Admonition,
Checkbox,
Chips,
Combobox,
financialMessages,
formFieldLabels,
formFieldPlaceholders,
paymentMethodMessages,
useDebugLogger,
} from '@modrinth/ui'
import { formatMoney } from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import { useDebounceFn } from '@vueuse/core'
import { computed, onMounted, ref, watch } from 'vue'
import RevenueInputField from '@/components/ui/dashboard/RevenueInputField.vue'
import WithdrawFeeBreakdown from '@/components/ui/dashboard/WithdrawFeeBreakdown.vue'
import { useAuth } from '@/composables/auth.js'
import { useBaseFetch } from '@/composables/fetch.js'
import { type PayoutMethod, useWithdrawContext } from '@/providers/creator-withdraw.ts'
import { normalizeChildren } from '@/utils/vue-children.ts'
const debug = useDebugLogger('TremendousDetailsStage')
const {
withdrawData,
maxWithdrawAmount,
availableMethods,
paymentOptions,
calculateFees,
setStage,
paymentMethodsCache,
} = useWithdrawContext()
const { formatMessage } = useVIntl()
const auth = await useAuth()
const userEmail = computed(() => {
return (auth.value.user as any)?.email || ''
})
const providerData = withdrawData.value.providerData
const initialDeliveryEmail =
providerData.type === 'tremendous'
? providerData.deliveryEmail || userEmail.value || ''
: userEmail.value || ''
const deliveryEmail = ref<string>(initialDeliveryEmail)
const showGiftCardSelector = computed(() => {
const method = withdrawData.value.selection.method
return method === 'merchant_card' || method === 'charity'
})
const showPayPalCurrencySelector = computed(() => {
const method = withdrawData.value.selection.method
return method === 'paypal'
})
const shouldShowUsdWarning = computed(() => {
const method = withdrawData.value.selection.method
const currency = selectedCurrency.value
return method === 'paypal' && currency === 'USD'
})
const selectedMethodDisplay = computed(() => {
const method = withdrawData.value.selection.method
if (!method) return null
return paymentOptions.value.find((m) => m.value === method) || null
})
const categoryLabel = computed(() => {
const method = withdrawData.value.selection.method
switch (method) {
case 'visa_card':
return formatMessage(paymentMethodMessages.virtualVisa)
case 'merchant_card':
return formatMessage(paymentMethodMessages.giftCard)
case 'charity':
return formatMessage(paymentMethodMessages.charity)
default:
return formatMessage(messages.reward)
}
})
const categoryLabelPlural = computed(() => {
const method = withdrawData.value.selection.method
switch (method) {
case 'visa_card':
return formatMessage(paymentMethodMessages.virtualVisaPlural)
case 'merchant_card':
return formatMessage(paymentMethodMessages.giftCardPlural)
case 'charity':
return formatMessage(paymentMethodMessages.charityPlural)
default:
return formatMessage(messages.rewardPlural)
}
})
const isUnverifiedEmail = computed(() => {
if (!deliveryEmail.value || !userEmail.value) return false
return deliveryEmail.value.toLowerCase() !== userEmail.value.toLowerCase()
})
const maxAmount = computed(() => maxWithdrawAmount.value)
const roundedMaxAmount = computed(() => Math.floor(maxAmount.value * 100) / 100)
const formData = ref<Record<string, any>>({
amount: withdrawData.value.calculation.amount || undefined,
})
const selectedGiftCardId = ref<string | null>(withdrawData.value.selection.methodId || null)
const currencyOptions = [
{ value: 'USD', label: 'USD' },
{ value: 'AUD', label: 'AUD' },
{ value: 'CAD', label: 'CAD' },
{ value: 'CHF', label: 'CHF' },
{ value: 'CZK', label: 'CZK' },
{ value: 'DKK', label: 'DKK' },
{ value: 'EUR', label: 'EUR' },
{ value: 'GBP', label: 'GBP' },
{ value: 'MXN', label: 'MXN' },
{ value: 'NOK', label: 'NOK' },
{ value: 'NZD', label: 'NZD' },
{ value: 'PLN', label: 'PLN' },
{ value: 'SEK', label: 'SEK' },
{ value: 'SGD', label: 'SGD' },
]
function getCurrencyFromCountryCode(countryCode: string | undefined): string {
if (!countryCode) return 'USD'
const code = countryCode.toUpperCase()
const countryToCurrency: Record<string, string> = {
US: 'USD', // United States
GB: 'GBP', // UK
CA: 'CAD', // Canada
AU: 'AUD', // Australia
CH: 'CHF', // Switzerland
CZ: 'CZK', // Czech Republic
DK: 'DKK', // Denmark
MX: 'MXN', // Mexico
NO: 'NOK', // Norway
NZ: 'NZD', // New Zealand
PL: 'PLN', // Poland
SE: 'SEK', // Sweden
SG: 'SGD', // Singapore
// Eurozone countries
AT: 'EUR', // Austria
BE: 'EUR', // Belgium
CY: 'EUR', // Cyprus
EE: 'EUR', // Estonia
FI: 'EUR', // Finland
FR: 'EUR', // France
DE: 'EUR', // Germany
GR: 'EUR', // Greece
IE: 'EUR', // Ireland
IT: 'EUR', // Italy
LV: 'EUR', // Latvia
LT: 'EUR', // Lithuania
LU: 'EUR', // Luxembourg
MT: 'EUR', // Malta
NL: 'EUR', // Netherlands
PT: 'EUR', // Portugal
SK: 'EUR', // Slovakia
SI: 'EUR', // Slovenia
ES: 'EUR', // Spain
}
return countryToCurrency[code] || 'USD'
}
const initialCurrency = getCurrencyFromCountryCode(withdrawData.value.selection.country?.id)
const selectedCurrency = ref<string>(initialCurrency)
const agreedTerms = computed({
get: () => withdrawData.value.agreedTerms,
set: (value) => {
withdrawData.value.agreedTerms = value
},
})
const calculatedFee = ref<number>(0)
const exchangeRate = ref<number | null>(null)
const feeLoading = ref(false)
const rewardOptions = ref<
Array<{
value: string
label: string
imageUrl?: string
methodDetails?: {
id: string
name: string
interval?: {
fixed?: { values: number[] }
standard?: { min: number; max: number }
}
}
}>
>([])
const selectedRewardOption = computed(() => {
if (!selectedGiftCardId.value) return null
return rewardOptions.value.find((opt) => opt.value === selectedGiftCardId.value) || null
})
const selectedMethodDetails = computed(() => {
console.log(rewardOptions.value, selectedGiftCardId.value)
if (!selectedGiftCardId.value) return null
const option = rewardOptions.value.find((opt) => opt.value === selectedGiftCardId.value)
debug('Selected method details:', option?.methodDetails)
return option?.methodDetails || null
})
const useFixedDenominations = computed(() => {
const hasFixed = !!selectedMethodDetails.value?.interval?.fixed?.values
debug('Use fixed denominations:', hasFixed, selectedMethodDetails.value?.interval)
return hasFixed
})
const denominationOptions = computed(() => {
const fixedValues = selectedMethodDetails.value?.interval?.fixed?.values
if (!fixedValues) return []
const filtered = fixedValues
.filter((amount) => amount <= roundedMaxAmount.value)
.sort((a, b) => a - b)
debug(
'Denomination options (filtered by max):',
filtered,
'from',
fixedValues,
'max:',
roundedMaxAmount.value,
)
return filtered
})
const effectiveMinAmount = computed(() => {
return selectedMethodDetails.value?.interval?.standard?.min || 0.01
})
const effectiveMaxAmount = computed(() => {
const methodMax = selectedMethodDetails.value?.interval?.standard?.max
if (methodMax !== undefined && methodMax !== null) {
return Math.min(roundedMaxAmount.value, methodMax)
}
return roundedMaxAmount.value
})
const selectedDenomination = computed({
get: () => formData.value.amount,
set: (value) => {
formData.value.amount = value
},
})
const allRequiredFieldsFilled = computed(() => {
const amount = formData.value.amount
if (!amount || amount <= 0) return false
if (!deliveryEmail.value) return false
if (showGiftCardSelector.value && !selectedGiftCardId.value) return false
return true
})
const calculateFeesDebounced = useDebounceFn(async () => {
const amount = formData.value.amount
if (!amount || amount <= 0) {
calculatedFee.value = 0
exchangeRate.value = null
return
}
const methodId = showGiftCardSelector.value
? selectedGiftCardId.value
: withdrawData.value.selection.methodId
if (!methodId) {
calculatedFee.value = 0
exchangeRate.value = null
return
}
feeLoading.value = true
try {
await calculateFees()
calculatedFee.value = withdrawData.value.calculation.fee ?? 0
exchangeRate.value = withdrawData.value.calculation.exchangeRate
} catch (error) {
console.error('Failed to calculate fees:', error)
calculatedFee.value = 0
exchangeRate.value = null
} finally {
feeLoading.value = false
}
}, 500)
watch(deliveryEmail, (newEmail) => {
if (withdrawData.value.providerData.type === 'tremendous') {
withdrawData.value.providerData.deliveryEmail = newEmail
}
})
watch(
selectedCurrency,
(newCurrency) => {
if (withdrawData.value.providerData.type === 'tremendous') {
;(withdrawData.value.providerData as any).currency = newCurrency
}
},
{ immediate: true },
)
watch(
() => withdrawData.value.selection.country?.id,
(newCountryId) => {
if (showPayPalCurrencySelector.value && newCountryId) {
const detectedCurrency = getCurrencyFromCountryCode(newCountryId)
selectedCurrency.value = detectedCurrency
}
},
)
watch(
[() => formData.value.amount, selectedGiftCardId, deliveryEmail, selectedCurrency],
() => {
withdrawData.value.calculation.amount = formData.value.amount ?? 0
if (showGiftCardSelector.value && selectedGiftCardId.value) {
withdrawData.value.selection.methodId = selectedGiftCardId.value
}
if (allRequiredFieldsFilled.value) {
feeLoading.value = true
calculateFeesDebounced()
} else {
calculatedFee.value = 0
exchangeRate.value = null
feeLoading.value = false
}
},
{ deep: true },
)
onMounted(async () => {
const methods = availableMethods.value
const selectedMethod = withdrawData.value.selection.method
rewardOptions.value = methods
.filter((m) => m.type === 'tremendous')
.filter(
(m) =>
m.category === selectedMethod ||
(selectedMethod === 'merchant_card' && m.category === 'visa_card'),
)
.map((m) => ({
value: m.id,
label: m.name,
imageUrl: m.image_url || m.image_logo_url || undefined,
methodDetails: {
id: m.id,
name: m.name,
interval: m.interval,
},
}))
debug('Loaded reward options:', rewardOptions.value.length, 'methods')
debug('Sample method with interval:', rewardOptions.value[0]?.methodDetails)
if (allRequiredFieldsFilled.value) {
feeLoading.value = true
calculateFeesDebounced()
}
})
watch(
() => withdrawData.value.selection.method,
(newMethod, oldMethod) => {
if (oldMethod && newMethod !== oldMethod) {
formData.value = {
amount: undefined,
}
selectedGiftCardId.value = null
calculatedFee.value = 0
exchangeRate.value = null
// Clear currency when switching away from PayPal International
if (newMethod !== 'paypal' && withdrawData.value.providerData.type === 'tremendous') {
;(withdrawData.value.providerData as any).currency = undefined
}
}
},
)
async function switchToDirectPaypal() {
withdrawData.value.selection.country = {
id: 'US',
name: 'United States',
}
let usMethods = paymentMethodsCache.value['US']
if (!usMethods) {
try {
usMethods = (await useBaseFetch('payout/methods', {
apiVersion: 3,
query: { country: 'US' },
})) as PayoutMethod[]
paymentMethodsCache.value['US'] = usMethods
} catch (error) {
console.error('Failed to fetch US payment methods:', error)
return
}
}
availableMethods.value = usMethods
const directPaypal = usMethods.find((m) => m.type === 'paypal')
if (directPaypal) {
withdrawData.value.selection.provider = 'paypal'
withdrawData.value.selection.method = directPaypal.id
withdrawData.value.selection.methodId = directPaypal.id
withdrawData.value.providerData = {
type: 'paypal',
}
await setStage('paypal-details', true)
} else {
console.error('An error occured - no paypal in US region??')
}
}
const messages = defineMessages({
unverifiedEmailHeader: {
id: 'dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header',
defaultMessage: 'Unverified email',
},
unverifiedEmailMessage: {
id: 'dashboard.creator-withdraw-modal.tremendous-details.unverified-email-message',
defaultMessage:
'The delivery email you have entered is not associated with your Modrinth account. Modrinth cannot recover rewards sent to an incorrect email address.',
},
paymentMethod: {
id: 'dashboard.creator-withdraw-modal.tremendous-details.payment-method',
defaultMessage: 'Payment method',
},
reward: {
id: 'dashboard.creator-withdraw-modal.tremendous-details.reward',
defaultMessage: 'Reward',
},
rewardPlaceholder: {
id: 'dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder',
defaultMessage: 'Select reward',
},
rewardPlural: {
id: 'dashboard.creator-withdraw-modal.tremendous-details.reward-plural',
defaultMessage: 'Rewards',
},
usdPaypalWarningHeader: {
id: 'dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header',
defaultMessage: 'Lower fees available',
},
usdPaypalWarningMessage: {
id: 'dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-message',
defaultMessage:
'You selected USD for PayPal International. <direct-paypal-link>Switch to direct PayPal</direct-paypal-link> for better fees (≈2% instead of ≈6%).',
},
})
</script>

View File

@@ -139,7 +139,7 @@ const messages = defineMessages({
resubmitForReviewDesc: {
id: 'project-moderation-nags.resubmit-for-review-desc',
defaultMessage:
"Your project has been {status} by Modrinth's staff. In most cases, you can resubmit for review after addressing the staff's message.",
"Your project has been {status, select, rejected {rejected} withheld {withheld} other {{status}}} by Modrinth's staff. In most cases, you can resubmit for review after addressing the staff's message.",
},
visitModerationPage: {
id: 'project-moderation-nags.visit-moderation-page',

View File

@@ -105,10 +105,9 @@
<script setup>
import { ReportIcon, UnknownIcon, VersionIcon } from '@modrinth/assets'
import { Avatar, Badge, CopyCode, useRelativeTime } from '@modrinth/ui'
import { formatProjectType } from '@modrinth/utils'
import { formatProjectType, renderHighlightedString } from '@modrinth/utils'
import ThreadSummary from '~/components/ui/thread/ThreadSummary.vue'
import { renderHighlightedString } from '~/helpers/highlight.js'
import { getProjectTypeForUrl } from '~/helpers/projects.js'
const formatRelativeTime = useRelativeTime()

View File

@@ -26,7 +26,7 @@ export default {
},
},
setup() {
const tags = useTags()
const tags = useGeneratedState()
return { tags }
},

View File

@@ -1,77 +0,0 @@
<template>
<Checkbox
class="filter"
:model-value="activeFilters.includes(facetName)"
:description="displayName"
@update:model-value="toggle()"
>
<div class="filter-text">
<div v-if="icon" aria-hidden="true" class="icon" v-html="icon" />
<div v-else class="icon">
<slot />
</div>
<span aria-hidden="true"> {{ displayName }}</span>
</div>
</Checkbox>
</template>
<script>
import Checkbox from '~/components/ui/Checkbox.vue'
export default {
components: {
Checkbox,
},
props: {
facetName: {
type: String,
default: '',
},
displayName: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
activeFilters: {
type: Array,
default() {
return []
},
},
},
emits: ['toggle'],
methods: {
toggle() {
this.$emit('toggle', this.facetName)
},
},
}
</script>
<style lang="scss" scoped>
.filter {
margin-bottom: 0.5rem;
:deep(.filter-text) {
display: flex;
align-items: center;
.icon {
height: 1rem;
svg {
margin-right: 0.25rem;
width: 1rem;
height: 1rem;
}
}
}
span {
user-select: none;
}
}
</style>

View File

@@ -13,23 +13,14 @@ import {
TrashIcon,
XIcon,
} from '@modrinth/assets'
import {
ButtonStyled,
commonMessages,
injectNotificationManager,
OverflowMenu,
ProgressBar,
} from '@modrinth/ui'
import { ButtonStyled, commonMessages, OverflowMenu, ProgressBar } from '@modrinth/ui'
import type { Backup } from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import dayjs from 'dayjs'
import { computed, ref } from 'vue'
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'
import { computed } from 'vue'
const flags = useFeatureFlags()
const { formatMessage } = useVIntl()
const { addNotification } = injectNotificationManager()
const emit = defineEmits<{
(e: 'download' | 'rename' | 'restore' | 'lock' | 'retry'): void
@@ -42,13 +33,11 @@ const props = withDefaults(
preview?: boolean
kyrosUrl?: string
jwt?: string
server?: ModrinthServer
}>(),
{
preview: false,
kyrosUrl: undefined,
jwt: undefined,
server: undefined,
},
)
@@ -135,48 +124,7 @@ const messages = defineMessages({
id: 'servers.backups.item.retry',
defaultMessage: 'Retry',
},
downloadingBackup: {
id: 'servers.backups.item.downloading-backup',
defaultMessage: 'Downloading backup...',
},
downloading: {
id: 'servers.backups.item.downloading',
defaultMessage: 'Downloading',
},
})
const downloadingState = ref<{ progress: number; state: string } | undefined>(undefined)
const downloading = computed(() => downloadingState.value)
const handleDownload = async () => {
if (!props.server?.backups || downloading.value) {
return
}
downloadingState.value = { progress: 0, state: 'ongoing' }
try {
const download = props.server.backups.downloadBackup(props.backup.id, props.backup.name)
download.onProgress((p) => {
downloadingState.value = { progress: p.progress, state: 'ongoing' }
})
await download.promise
emit('download')
} catch (error) {
console.error('Failed to download backup:', error)
addNotification({
type: 'error',
title: 'Download failed',
text: error instanceof Error ? error.message : 'Failed to download backup',
})
} finally {
downloadingState.value = undefined
}
}
</script>
<template>
<div
@@ -244,15 +192,6 @@ const handleDownload = async () => {
class="max-w-full"
/>
</div>
<div v-else-if="downloading" class="col-span-2 flex flex-col gap-3 text-blue">
{{ formatMessage(messages.downloadingBackup) }}
<ProgressBar
:progress="downloading.progress >= 0 ? downloading.progress : 0"
color="blue"
:waiting="downloading.progress <= 0"
class="max-w-full"
/>
</div>
<template v-else>
<div class="col-span-2">
{{ dayjs(backup.created_at).format('MMMM D, YYYY [at] h:mm A') }}
@@ -284,32 +223,34 @@ const handleDownload = async () => {
</button>
</ButtonStyled>
<template v-else>
<ButtonStyled v-show="!downloading">
<button :disabled="!server?.backups" @click="handleDownload">
<ButtonStyled>
<a
:class="{
disabled: !kyrosUrl || !jwt,
}"
:href="`https://${kyrosUrl}/modrinth/v0/backups/${backup.id}/download?auth=${jwt}`"
@click="() => emit('download')"
>
<DownloadIcon />
{{ formatMessage(commonMessages.downloadButton) }}
</button>
</a>
</ButtonStyled>
<ButtonStyled circular type="transparent">
<OverflowMenu
:options="[
{
id: 'rename',
action: () => emit('rename'),
disabled: !!restoring || !!downloading,
},
{ id: 'rename', action: () => emit('rename') },
{
id: 'restore',
action: () => emit('restore'),
disabled: !!restoring || !!downloading,
disabled: !!restoring,
},
{ id: 'lock', action: () => emit('lock'), disabled: !!restoring || !!downloading },
{ id: 'lock', action: () => emit('lock') },
{ divider: true },
{
id: 'delete',
color: 'red',
action: () => emit('delete'),
disabled: !!restoring || !!downloading,
disabled: !!restoring,
},
]"
>

View File

@@ -27,13 +27,13 @@
</p>
</div>
<TeleportDropdownMenu
<Combobox
:id="'interval-field'"
v-model="backupIntervalsLabel"
:disabled="!autoBackupEnabled || isSaving"
name="interval"
:options="Object.keys(backupIntervals)"
placeholder="Backup interval"
:options="Object.keys(backupIntervals).map((k) => ({ value: k, label: k }))"
:display-value="backupIntervalsLabel"
/>
<div class="mt-4 flex justify-start gap-4">
@@ -57,12 +57,7 @@
<script setup lang="ts">
import { SaveIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
injectNotificationManager,
NewModal,
TeleportDropdownMenu,
} from '@modrinth/ui'
import { ButtonStyled, Combobox, injectNotificationManager, NewModal } from '@modrinth/ui'
import { computed, ref } from 'vue'
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'

View File

@@ -60,16 +60,24 @@
</NuxtLink>
</div>
</div>
<TeleportDropdownMenu
<Combobox
v-model="selectedVersion"
name="Project"
:options="filteredVersions"
placeholder="No valid versions found"
:options="
filteredVersions.map((v) => ({
value: v,
label: typeof v === 'object' ? v.version_number : String(v),
}))
"
:display-value="
selectedVersion
? typeof selectedVersion === 'object'
? selectedVersion.version_number
: String(selectedVersion)
: 'No valid versions found'
"
class="!min-w-full"
:disabled="filteredVersions.length === 0"
:display-name="
(version) => (typeof version === 'object' ? version?.version_number : version)
"
/>
<Checkbox v-model="showBetaAlphaReleases"> Show any beta and alpha releases </Checkbox>
</template>
@@ -241,16 +249,16 @@ import {
Admonition,
Avatar,
ButtonStyled,
Checkbox,
Combobox,
CopyCode,
NewModal,
TeleportDropdownMenu,
} from '@modrinth/ui'
import TagItem from '@modrinth/ui/src/components/base/TagItem.vue'
import { formatCategory, formatVersionsForDisplay, type Mod, type Version } from '@modrinth/utils'
import { computed, ref } from 'vue'
import Accordion from '~/components/ui/Accordion.vue'
import Checkbox from '~/components/ui/Checkbox.vue'
import ContentVersionFilter, {
type ListedGameVersion,
type ListedPlatform,
@@ -282,7 +290,7 @@ const versionsError = ref('')
const showBetaAlphaReleases = ref(false)
const unlockFilterAccordion = ref()
const versionFilter = ref(true)
const tags = useTags()
const tags = useGeneratedState()
const noCompatibleVersions = ref(false)
const { pluginLoaders, modLoaders } = tags.value.loaders.reduce(

View File

@@ -120,7 +120,7 @@ import {
UpdatedIcon,
XIcon,
} from '@modrinth/assets'
import { ButtonStyled, Checkbox, NewModal } from '@modrinth/ui'
import { ButtonStyled, Checkbox, NewModal, ServerInfoLabels } from '@modrinth/ui'
import type { PowerAction as ServerPowerAction, ServerState } from '@modrinth/utils'
import { useStorage } from '@vueuse/core'
import { computed, ref } from 'vue'
@@ -130,7 +130,6 @@ import type { BackupInProgressReason } from '~/pages/servers/manage/[id].vue'
import LoadingIcon from './icons/LoadingIcon.vue'
import PanelSpinner from './PanelSpinner.vue'
import ServerInfoLabels from './ServerInfoLabels.vue'
import TeleportOverflowMenu from './TeleportOverflowMenu.vue'
const flags = useFeatureFlags()

View File

@@ -17,10 +17,11 @@
</div>
<div class="flex w-full flex-col gap-4">
<TeleportDropdownMenu
<Combobox
v-if="props.versions?.length"
v-model="selectedVersion"
:options="versionOptions"
:options="versionOptions.map((v) => ({ value: v, label: v }))"
:display-value="selectedVersion || 'Select version...'"
placeholder="Select version..."
name="version"
class="w-full max-w-full"
@@ -68,12 +69,7 @@
<script setup lang="ts">
import { DownloadIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
injectNotificationManager,
NewModal,
TeleportDropdownMenu,
} from '@modrinth/ui'
import { ButtonStyled, Combobox, injectNotificationManager, NewModal } from '@modrinth/ui'
import { ModrinthServersFetchError } from '@modrinth/utils'
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'
@@ -96,7 +92,7 @@ const emit = defineEmits<{
const modal = ref()
const hardReset = ref(false)
const isLoading = ref(false)
const selectedVersion = ref('')
const selectedVersion = ref(props.currentVersion?.version_number || '')
const versionOptions = computed(() => props.versions?.map((v) => v.version_number) || [])

View File

@@ -54,11 +54,12 @@
<div class="flex w-full flex-col gap-2 rounded-2xl bg-table-alternateRow p-4">
<div class="text-lg font-bold text-contrast">Minecraft version</div>
<TeleportDropdownMenu
<Combobox
v-model="selectedMCVersion"
name="mcVersion"
:options="mcVersions"
class="w-full max-w-[100%]"
:options="mcVersions.map((v) => ({ value: v, label: v }))"
:display-value="selectedMCVersion || 'Select Minecraft version...'"
class="!w-full"
placeholder="Select Minecraft version..."
/>
<div class="mt-2 flex items-center justify-between gap-2">
@@ -108,10 +109,17 @@
</div>
</template>
<template v-else-if="selectedLoaderVersions.length > 0">
<TeleportDropdownMenu
<Combobox
v-model="selectedLoaderVersion"
name="loaderVersion"
:options="selectedLoaderVersions"
:options="selectedLoaderVersions.map((v) => ({ value: v, label: v }))"
:display-value="
selectedLoaderVersion ||
(selectedLoader.toLowerCase() === 'paper' ||
selectedLoader.toLowerCase() === 'purpur'
? 'Select build number...'
: 'Select loader version...')
"
class="w-full max-w-[100%]"
:placeholder="
selectedLoader.toLowerCase() === 'paper' ||
@@ -201,9 +209,9 @@ import { DropdownIcon, RightArrowIcon, ServerIcon, XIcon } from '@modrinth/asset
import {
BackupWarning,
ButtonStyled,
Combobox,
injectNotificationManager,
NewModal,
TeleportDropdownMenu,
Toggle,
} from '@modrinth/ui'
import { type Loaders, ModrinthServersFetchError } from '@modrinth/utils'
@@ -433,7 +441,7 @@ onMounted(() => {
fetchLoaderVersions()
})
const tags = useTags()
const tags = useGeneratedState()
const mcVersions = computed(() =>
tags.value.gameVersions
.filter((x) =>

View File

@@ -1,39 +0,0 @@
<template>
<div
v-if="game"
v-tooltip="'Change server version'"
class="min-w-0 flex-none flex-row items-center gap-2 first:!flex"
>
<GameIcon aria-hidden="true" class="size-5 shrink-0" />
<NuxtLink
v-if="isLink"
:to="serverId ? `/servers/manage/${serverId}/options/loader` : ''"
class="flex min-w-0 items-center truncate text-sm font-semibold"
:class="serverId ? 'hover:underline' : ''"
>
<div class="flex flex-row items-center gap-1">
{{ game[0].toUpperCase() + game.slice(1) }}
<span v-if="mcVersion">{{ mcVersion }}</span>
<span v-else class="inline-block h-3 w-12 animate-pulse rounded bg-button-border"></span>
</div>
</NuxtLink>
<div v-else class="flex min-w-0 flex-row items-center gap-1 truncate text-sm font-semibold">
{{ game[0].toUpperCase() + game.slice(1) }}
<span v-if="mcVersion">{{ mcVersion }}</span>
<span v-else class="inline-block h-3 w-16 animate-pulse rounded bg-button-border"></span>
</div>
</div>
</template>
<script setup lang="ts">
import { GameIcon } from '@modrinth/assets'
defineProps<{
game: string
mcVersion: string
isLink?: boolean
}>()
const route = useNativeRoute()
const serverId = route.params.id as string
</script>

View File

@@ -1,26 +0,0 @@
<template>
<div
class="experimental-styles-within flex size-16 shrink-0 overflow-hidden rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
>
<client-only>
<img
v-if="image"
class="h-full w-full select-none object-fill"
alt="Server Icon"
:src="image"
/>
<img
v-else
class="h-full w-full select-none object-fill"
alt="Server Icon"
src="~/assets/images/servers/minecraft_server_icon.png"
/>
</client-only>
</div>
</template>
<script setup lang="ts">
defineProps<{
image: string | undefined
}>()
</script>

View File

@@ -1,45 +0,0 @@
<template>
<div>
<ServerGameLabel
v-if="showGameLabel"
:game="serverData.game"
:mc-version="serverData.mc_version ?? ''"
:is-link="linked"
/>
<ServerLoaderLabel
:loader="serverData.loader"
:loader-version="serverData.loader_version ?? ''"
:no-separator="column"
:is-link="linked"
/>
<ServerSubdomainLabel
v-if="serverData.net?.domain"
:subdomain="serverData.net.domain"
:no-separator="column"
:is-link="linked"
/>
<ServerUptimeLabel
v-if="uptimeSeconds"
:uptime-seconds="uptimeSeconds"
:no-separator="column"
/>
</div>
</template>
<script setup lang="ts">
import ServerGameLabel from './ServerGameLabel.vue'
import ServerLoaderLabel from './ServerLoaderLabel.vue'
import ServerSubdomainLabel from './ServerSubdomainLabel.vue'
import ServerUptimeLabel from './ServerUptimeLabel.vue'
interface ServerInfoLabelsProps {
serverData: Record<string, any>
showGameLabel: boolean
showLoaderLabel: boolean
uptimeSeconds?: number
column?: boolean
linked?: boolean
}
defineProps<ServerInfoLabelsProps>()
</script>

View File

@@ -1,174 +0,0 @@
<template>
<div>
<NuxtLink :to="status === 'suspended' ? '' : `/servers/manage/${props.server_id}`">
<div
class="flex flex-row items-center overflow-x-hidden rounded-2xl border-[1px] border-solid border-button-bg bg-bg-raised p-4 transition-transform duration-100"
:class="{
'!rounded-b-none border-b-0': status === 'suspended' || !!pendingChange,
'opacity-75': status === 'suspended',
'active:scale-95': status !== 'suspended' && !pendingChange,
}"
data-pyro-server-listing
:data-pyro-server-listing-id="server_id"
>
<ServerIcon v-if="status !== 'suspended'" :image="image" />
<div
v-else
class="bg-bg-secondary flex size-16 items-center justify-center rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
>
<LockIcon class="size-12 text-secondary" />
</div>
<div class="ml-4 flex flex-col gap-2.5">
<div class="flex flex-row items-center gap-2">
<h2 class="m-0 text-xl font-bold text-contrast">{{ name }}</h2>
<ChevronRightIcon />
</div>
<div
v-if="projectData?.title"
class="m-0 flex flex-row items-center gap-2 text-sm font-medium text-secondary"
>
<Avatar
:src="iconUrl"
no-shadow
style="min-height: 20px; min-width: 20px; height: 20px; width: 20px"
alt="Server Icon"
/>
Using {{ projectData?.title || 'Unknown' }}
</div>
<div
v-if="isConfiguring"
class="flex min-w-0 items-center gap-2 truncate text-sm font-semibold text-brand"
>
<SparklesIcon class="size-5 shrink-0" /> New server
</div>
<ServerInfoLabels
v-else
:server-data="{ game, mc_version, loader, loader_version, net }"
:show-game-label="showGameLabel"
:show-loader-label="showLoaderLabel"
:linked="false"
class="pointer-events-none flex w-full flex-row flex-wrap items-center gap-4 text-secondary *:hidden sm:flex-row sm:*:flex"
/>
</div>
</div>
</NuxtLink>
<div
v-if="status === 'suspended' && suspension_reason === 'upgrading'"
class="relative flex w-full flex-row items-center gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-blue bg-bg-blue p-4 text-sm font-bold text-contrast"
>
<PanelSpinner />
Your server's hardware is currently being upgraded and will be back online shortly.
</div>
<div
v-else-if="status === 'suspended' && suspension_reason === 'cancelled'"
class="relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
>
<div class="flex flex-row gap-2">
<PanelErrorIcon class="!size-5" /> Your server has been cancelled. Please update your
billing information or contact Modrinth Support for more information.
</div>
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
</div>
<div
v-else-if="status === 'suspended' && suspension_reason"
class="relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
>
<div class="flex flex-row gap-2">
<PanelErrorIcon class="!size-5" /> Your server has been suspended: {{ suspension_reason }}.
Please update your billing information or contact Modrinth Support for more information.
</div>
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
</div>
<div
v-else-if="status === 'suspended'"
class="relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
>
<div class="flex flex-row gap-2">
<PanelErrorIcon class="!size-5" /> Your server has been suspended. Please update your
billing information or contact Modrinth Support for more information.
</div>
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
</div>
<div
v-if="pendingChange && status !== 'suspended'"
class="relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-orange bg-bg-orange p-4 text-sm font-bold text-contrast"
>
<div>
Your server will {{ pendingChange.verb.toLowerCase() }} to the "{{
pendingChange.planSize
}}" plan on {{ formatDate(pendingChange.date) }}.
</div>
<ServersSpecs
class="!font-normal !text-contrast"
:ram="Math.round((pendingChange.ramGb ?? 0) * 1024)"
:storage="Math.round((pendingChange.storageGb ?? 0) * 1024)"
:cpus="pendingChange.cpuBurst"
bursting-link="https://docs.modrinth.com/servers/bursting"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ChevronRightIcon, LockIcon, SparklesIcon } from '@modrinth/assets'
import { Avatar, CopyCode, ServersSpecs } from '@modrinth/ui'
import type { Project, Server } from '@modrinth/utils'
import dayjs from 'dayjs'
import { useModrinthServers } from '~/composables/servers/modrinth-servers.ts'
import PanelErrorIcon from './icons/PanelErrorIcon.vue'
import PanelSpinner from './PanelSpinner.vue'
import ServerIcon from './ServerIcon.vue'
import ServerInfoLabels from './ServerInfoLabels.vue'
type PendingChange = {
planSize: string
cpu: number
cpuBurst: number
ramGb: number
swapGb?: number
storageGb?: number
date: string | number | Date
intervalChange?: string | null
verb: string
}
const props = defineProps<Partial<Server> & { pendingChange?: PendingChange }>()
if (props.server_id && props.status === 'available') {
// Necessary only to get server icon
await useModrinthServers(props.server_id, ['general'])
}
const showGameLabel = computed(() => !!props.game)
const showLoaderLabel = computed(() => !!props.loader)
let projectData: Ref<Project | null>
if (props.upstream) {
const { data } = await useAsyncData<Project>(
`server-project-${props.server_id}`,
async (): Promise<Project> => {
const result = await useBaseFetch(`project/${props.upstream?.project_id}`)
return result as Project
},
)
projectData = data
} else {
projectData = ref(null)
}
const image = useState<string | undefined>(`server-icon-${props.server_id}`, () => undefined)
const iconUrl = computed(() => projectData.value?.icon_url || undefined)
const isConfiguring = computed(() => props.flows?.intro)
const formatDate = (d: unknown) => {
try {
return dayjs(d as any).format('MMMM D, YYYY')
} catch {
return ''
}
}
</script>

View File

@@ -1,24 +0,0 @@
<template>
<div class="flex flex-row items-center gap-8 overflow-x-hidden rounded-3xl bg-bg-raised p-4">
<div class="relative grid place-content-center">
<img
no-shadow
size="lg"
alt="Server Icon"
class="size-[96px] rounded-xl bg-bg-raised opacity-50"
src="~/assets/images/servers/minecraft_server_icon.png"
/>
<div class="absolute inset-0 grid place-content-center">
<LoadingIcon class="size-8 animate-spin text-contrast" />
</div>
</div>
<div class="flex flex-col gap-4">
<h2 class="m-0 text-contrast">Your new server is being prepared.</h2>
<p class="m-0">It'll appear here once it's ready.</p>
</div>
</div>
</template>
<script lang="ts" setup>
import LoadingIcon from './icons/LoadingIcon.vue'
</script>

View File

@@ -1,47 +0,0 @@
<template>
<div v-tooltip="'Change server loader'" class="flex min-w-0 flex-row items-center gap-4 truncate">
<div v-if="!noSeparator" class="experimental-styles-within h-6 w-0.5 bg-button-border"></div>
<div class="flex flex-row items-center gap-2">
<LoaderIcon v-if="loader" :loader="loader" class="flex shrink-0 [&&]:size-5" />
<div v-else class="size-5 shrink-0 animate-pulse rounded-full bg-button-border"></div>
<NuxtLink
v-if="isLink"
:to="serverId ? `/servers/manage/${serverId}/options/loader` : ''"
class="flex min-w-0 items-center text-sm font-semibold"
:class="serverId ? 'hover:underline' : ''"
>
<span v-if="loader">
{{ loader }}
<span v-if="loaderVersion">{{ loaderVersion }}</span>
</span>
<span v-else class="flex gap-2">
<span class="inline-block h-4 w-12 animate-pulse rounded bg-button-border"></span>
<span class="inline-block h-4 w-12 animate-pulse rounded bg-button-border"></span>
</span>
</NuxtLink>
<div v-else class="min-w-0 text-sm font-semibold">
<span v-if="loader">
{{ loader }}
<span v-if="loaderVersion">{{ loaderVersion }}</span>
</span>
<span v-else class="flex gap-2">
<span class="inline-block h-4 w-12 animate-pulse rounded bg-button-border"></span>
<span class="inline-block h-4 w-12 animate-pulse rounded bg-button-border"></span>
</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import LoaderIcon from './icons/LoaderIcon.vue'
defineProps<{
noSeparator?: boolean
loader?: 'Fabric' | 'Quilt' | 'Forge' | 'NeoForge' | 'Paper' | 'Spigot' | 'Bukkit' | 'Vanilla'
loaderVersion?: string
isLink?: boolean
}>()
const route = useNativeRoute()
const serverId = route.params.id as string
</script>

View File

@@ -1,19 +0,0 @@
<template>
<div class="flex h-full flex-col items-center justify-center gap-8">
<img
src="https://cdn.modrinth.com/servers/excitement.webp"
alt=""
class="max-w-[360px]"
style="mask-image: radial-gradient(97% 77% at 50% 25%, #d9d9d9 0, hsla(0, 0%, 45%, 0) 100%)"
/>
<h1 class="m-0 text-contrast">You don't have any servers yet!</h1>
<p class="m-0">Modrinth Servers is a new way to play modded Minecraft with your friends.</p>
<ButtonStyled size="large" type="standard" color="brand">
<NuxtLink to="/servers#plan">Create a Server</NuxtLink>
</ButtonStyled>
</div>
</template>
<script setup lang="ts">
import { ButtonStyled } from '@modrinth/ui'
</script>

View File

@@ -1,50 +0,0 @@
<template>
<div
v-if="subdomain && !isHidden"
v-tooltip="'Copy custom URL'"
class="flex min-w-0 flex-row items-center gap-4 truncate hover:cursor-pointer"
>
<div v-if="!noSeparator" class="experimental-styles-within h-6 w-0.5 bg-button-border"></div>
<div class="flex flex-row items-center gap-2">
<LinkIcon class="flex size-5 shrink-0" />
<div
class="flex min-w-0 text-sm font-semibold"
:class="serverId ? 'hover:underline' : ''"
@click="copySubdomain"
>
{{ subdomain }}.modrinth.gg
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { LinkIcon } from '@modrinth/assets'
import { injectNotificationManager } from '@modrinth/ui'
import { useStorage } from '@vueuse/core'
const { addNotification } = injectNotificationManager()
const props = defineProps<{
subdomain: string
noSeparator?: boolean
}>()
const copySubdomain = () => {
navigator.clipboard.writeText(props.subdomain + '.modrinth.gg')
addNotification({
title: 'Custom URL copied',
text: "Your server's URL has been copied to your clipboard.",
type: 'success',
})
}
const route = useNativeRoute()
const serverId = computed(() => route.params.id as string)
const userPreferences = useStorage(`pyro-server-${serverId.value}-preferences`, {
hideSubdomainLabel: false,
})
const isHidden = computed(() => userPreferences.value.hideSubdomainLabel)
</script>

View File

@@ -1,67 +0,0 @@
<template>
<div
v-if="uptimeSeconds || uptimeSeconds !== 0"
v-tooltip="`Online for ${verboseUptime}`"
class="server-action-buttons-anim flex min-w-0 flex-row items-center gap-4"
data-pyro-uptime
>
<div v-if="!noSeparator" class="experimental-styles-within h-6 w-0.5 bg-button-border"></div>
<div class="flex gap-2">
<Timer class="flex size-5 shrink-0" />
<time class="truncate text-sm font-semibold" :aria-label="verboseUptime">
{{ formattedUptime }}
</time>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import Timer from './icons/Timer.vue'
const props = defineProps<{
uptimeSeconds: number
noSeparator?: boolean
}>()
const formattedUptime = computed(() => {
const days = Math.floor(props.uptimeSeconds / (24 * 3600))
const hours = Math.floor((props.uptimeSeconds % (24 * 3600)) / 3600)
const minutes = Math.floor((props.uptimeSeconds % 3600) / 60)
const seconds = props.uptimeSeconds % 60
let formatted = ''
if (days > 0) {
formatted += `${days}d `
}
if (hours > 0 || days > 0) {
formatted += `${hours}h `
}
formatted += `${minutes}m ${seconds}s`
return formatted.trim()
})
const verboseUptime = computed(() => {
const days = Math.floor(props.uptimeSeconds / (24 * 3600))
const hours = Math.floor((props.uptimeSeconds % (24 * 3600)) / 3600)
const minutes = Math.floor((props.uptimeSeconds % 3600) / 60)
const seconds = props.uptimeSeconds % 60
let verbose = ''
if (days > 0) {
verbose += `${days} day${days > 1 ? 's' : ''} `
}
if (hours > 0) {
verbose += `${hours} hour${hours > 1 ? 's' : ''} `
}
if (minutes > 0) {
verbose += `${minutes} minute${minutes > 1 ? 's' : ''} `
}
verbose += `${seconds} second${seconds > 1 ? 's' : ''}`
return verbose.trim()
})
</script>

View File

@@ -1,270 +1,24 @@
<template>
<ModrinthServersPurchaseModal
v-if="customer"
ref="purchaseModal"
:publishable-key="config.public.stripePublishableKey"
:initiate-payment="async (body) => await initiatePayment(body)"
:available-products="pyroProducts"
:on-error="handleError"
:customer="customer"
:payment-methods="paymentMethods"
:currency="selectedCurrency"
:return-url="`${config.public.siteUrl}/servers/manage`"
:pings="regionPings"
:regions="regions"
:refresh-payment-methods="fetchPaymentData"
:fetch-stock="fetchStock"
:plan-stage="true"
:existing-plan="currentPlanFromSubscription"
:existing-subscription="subscription || undefined"
:on-finalize-no-payment-change="finalizeDowngrade"
@hide="
() => {
subscription = null
}
"
<ServersUpgradeModalWrapperBase
ref="wrapperRef"
:stripe-publishable-key="config.public.stripePublishableKey"
:site-url="config.public.siteUrl"
:products="generatedState.products || []"
/>
</template>
<script setup lang="ts">
import { injectNotificationManager, ModrinthServersPurchaseModal } from '@modrinth/ui'
import type { ServerPlan } from '@modrinth/ui/src/utils/billing'
import type { UserSubscription } from '@modrinth/utils'
import { computed, onMounted, ref } from 'vue'
// TODO: Remove this wrapper when we figure out how to do cross platform state + stripe
import { ServersUpgradeModalWrapper as ServersUpgradeModalWrapperBase } from '@modrinth/ui'
import { useServersFetch } from '~/composables/servers/servers-fetch.ts'
import { products } from '~/generated/state.json'
const { addNotification } = injectNotificationManager()
import { useGeneratedState } from '~/composables/generated'
const config = useRuntimeConfig()
const purchaseModal = ref<InstanceType<typeof ModrinthServersPurchaseModal> | null>(null)
const customer = ref<any>(null)
const paymentMethods = ref<any[]>([])
const selectedCurrency = ref<string>('USD')
const regions = ref<any[]>([])
const regionPings = ref<any[]>([])
const generatedState = useGeneratedState()
const pyroProducts = (products as any[])
.filter((p) => p?.metadata?.type === 'pyro')
.sort((a, b) => (a?.metadata?.ram ?? 0) - (b?.metadata?.ram ?? 0))
function handleError(err: any) {
console.error('Purchase modal error:', err)
}
async function fetchPaymentData() {
try {
const [customerData, paymentMethodsData] = await Promise.all([
useBaseFetch('billing/customer', { internal: true }),
useBaseFetch('billing/payment_methods', { internal: true }),
])
customer.value = customerData as any
paymentMethods.value = paymentMethodsData as any[]
} catch (error) {
console.error('Error fetching payment data:', error)
}
}
function fetchStock(region: any, request: any) {
return useServersFetch(`stock?region=${region.shortcode}`, {
method: 'POST',
body: {
...request,
},
bypassAuth: true,
}).then((res: any) => res.available as number)
}
function pingRegions() {
useServersFetch('regions', {
method: 'GET',
version: 1,
bypassAuth: true,
}).then((res: any) => {
regions.value = res as any[]
;(regions.value as any[]).forEach((region: any) => {
runPingTest(region)
})
})
}
const PING_COUNT = 20
const PING_INTERVAL = 200
const MAX_PING_TIME = 1000
function runPingTest(region: any, index = 1) {
if (index > 10) {
regionPings.value.push({
region: region.shortcode,
ping: -1,
})
return
}
const wsUrl = `wss://${region.shortcode}${index}.${region.zone}/pingtest`
try {
const socket = new WebSocket(wsUrl)
const pings: number[] = []
socket.onopen = () => {
for (let i = 0; i < PING_COUNT; i++) {
setTimeout(() => {
socket.send(String(performance.now()))
}, i * PING_INTERVAL)
}
setTimeout(
() => {
socket.close()
const median = Math.round([...pings].sort((a, b) => a - b)[Math.floor(pings.length / 2)])
if (median) {
regionPings.value.push({
region: region.shortcode,
ping: median,
})
}
},
PING_COUNT * PING_INTERVAL + MAX_PING_TIME,
)
}
socket.onmessage = (event) => {
const start = Number(event.data)
pings.push(performance.now() - start)
}
socket.onerror = () => {
runPingTest(region, index + 1)
}
} catch {
// ignore
}
}
const subscription = ref<UserSubscription | null>(null)
// Dry run state
const dryRunResponse = ref<{
requires_payment: boolean
required_payment_is_proration: boolean
} | null>(null)
const pendingDowngradeBody = ref<any | null>(null)
const currentPlanFromSubscription = computed<ServerPlan | undefined>(() => {
return subscription.value
? (pyroProducts.find(
(p) =>
p.prices.filter((price: { id: string }) => price.id === subscription.value?.price_id)
.length > 0,
) ?? undefined)
: undefined
})
const currentInterval = computed(() => {
const interval = subscription.value?.interval
if (interval === 'monthly' || interval === 'quarterly') {
return interval
}
return 'monthly'
})
async function initiatePayment(body: any): Promise<any> {
if (subscription.value) {
const transformedBody = {
interval: body.charge?.interval,
payment_method: body.type === 'confirmation_token' ? body.token : body.id,
product: body.charge?.product_id,
region: body.metadata?.server_region,
}
try {
const dry = await useBaseFetch(`billing/subscription/${subscription.value.id}?dry=true`, {
internal: true,
method: 'PATCH',
body: transformedBody,
})
if (dry && typeof dry === 'object' && 'requires_payment' in dry) {
dryRunResponse.value = dry as any
pendingDowngradeBody.value = transformedBody
if (dry.requires_payment) {
return await finalizeImmediate(transformedBody)
} else {
return null
}
} else {
// Fallback if dry run not supported
return await finalizeImmediate(transformedBody)
}
} catch (e) {
console.error('Dry run failed, attempting immediate patch', e)
return await finalizeImmediate(transformedBody)
}
} else {
addNotification({
title: 'Unable to determine subscription ID.',
text: 'Please contact support.',
type: 'error',
})
return Promise.reject(new Error('Unable to determine subscription ID.'))
}
}
async function finalizeImmediate(body: any) {
const result = await useBaseFetch(`billing/subscription/${subscription.value?.id}`, {
internal: true,
method: 'PATCH',
body,
})
return result
}
async function finalizeDowngrade() {
if (!subscription.value || !pendingDowngradeBody.value) return
try {
await finalizeImmediate(pendingDowngradeBody.value)
addNotification({
title: 'Subscription updated',
text: 'Your plan has been downgraded and will take effect next billing cycle.',
type: 'success',
})
} catch (e) {
addNotification({
title: 'Failed to apply subscription changes',
text: 'Please try again or contact support.',
type: 'error',
})
throw e
} finally {
dryRunResponse.value = null
pendingDowngradeBody.value = null
}
}
async function open(id?: string) {
if (id) {
const subscriptions = (await useBaseFetch(`billing/subscriptions`, {
internal: true,
})) as any[]
for (const sub of subscriptions) {
if (sub?.metadata?.id === id) {
subscription.value = sub
break
}
}
} else {
subscription.value = null
}
purchaseModal.value?.show(currentInterval.value)
}
const wrapperRef = ref<InstanceType<typeof ServersUpgradeModalWrapperBase> | null>(null)
defineExpose({
open,
})
onMounted(() => {
fetchPaymentData()
pingRegions()
open: (id?: string) => wrapperRef.value?.open(id),
})
</script>

View File

@@ -1,458 +0,0 @@
<template>
<div class="relative inline-block h-9 w-full max-w-80">
<button
ref="triggerRef"
type="button"
aria-haspopup="listbox"
:aria-expanded="dropdownVisible"
:aria-controls="listboxId"
:aria-labelledby="listboxId"
class="duration-50 flex h-full w-full cursor-pointer select-none appearance-none items-center justify-between gap-4 rounded-xl border-none bg-button-bg px-4 py-2 shadow-sm !outline-none transition-all ease-in-out"
:class="triggerClasses"
@click="toggleDropdown"
@keydown="handleTriggerKeyDown"
>
<span>{{ selectedOption }}</span>
<DropdownIcon
class="transition-transform duration-200 ease-in-out"
:class="{ 'rotate-180': dropdownVisible }"
/>
</button>
<Teleport to="#teleports">
<transition
enter-active-class="transition-opacity duration-200 ease-out"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="transition-opacity duration-200 ease-in"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div
v-if="dropdownVisible"
:id="listboxId"
ref="optionsContainer"
role="listbox"
tabindex="-1"
:aria-activedescendant="activeDescendant"
class="experimental-styles-within fixed z-50 bg-button-bg shadow-lg outline-none"
:class="{
'rounded-b-xl': !isRenderingUp,
'rounded-t-xl': isRenderingUp,
}"
:style="positionStyle"
@keydown="handleListboxKeyDown"
>
<div
class="overflow-y-auto"
:style="{ height: `${virtualListHeight}px` }"
@scroll="handleScroll"
>
<div :style="{ height: `${totalHeight}px`, position: 'relative' }">
<div
v-for="item in visibleOptions"
:key="item.index"
:style="{
position: 'absolute',
top: 0,
transform: `translateY(${item.index * ITEM_HEIGHT}px)`,
width: '100%',
height: `${ITEM_HEIGHT}px`,
}"
>
<div
:id="`${listboxId}-option-${item.index}`"
role="option"
:aria-selected="selectedValue === item.option"
class="hover:brightness-85 flex h-full cursor-pointer select-none items-center px-4 transition-colors duration-150 ease-in-out"
:class="{
'bg-brand font-bold text-brand-inverted': selectedValue === item.option,
'bg-bg-raised': focusedOptionIndex === item.index,
'rounded-b-xl': item.index === props.options.length - 1 && !isRenderingUp,
'rounded-t-xl': item.index === 0 && isRenderingUp,
}"
@click="selectOption(item.option, item.index)"
@mousemove="focusedOptionIndex = item.index"
>
{{ displayName(item.option) }}
</div>
</div>
</div>
</div>
</div>
</transition>
</Teleport>
</div>
</template>
<script setup lang="ts">
import { DropdownIcon } from '@modrinth/assets'
import type { CSSProperties } from 'vue'
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
const ITEM_HEIGHT = 44
const BUFFER_ITEMS = 5
type OptionValue = string | number | Record<string, any>
interface Props {
options: OptionValue[]
name: string
defaultValue?: OptionValue | null
placeholder?: string | number | null
modelValue?: OptionValue | null
renderUp?: boolean
disabled?: boolean
displayName?: (option: OptionValue) => string
}
const props = withDefaults(defineProps<Props>(), {
defaultValue: null,
placeholder: null,
modelValue: null,
renderUp: false,
disabled: false,
displayName: (option: OptionValue) => String(option),
})
const emit = defineEmits<{
(e: 'input' | 'update:modelValue', value: OptionValue): void
(e: 'change', value: { option: OptionValue; index: number }): void
}>()
const dropdownVisible = ref(false)
const selectedValue = ref<OptionValue | null>(props.modelValue || props.defaultValue)
const focusedOptionIndex = ref<number | null>(null)
const optionsContainer = ref<HTMLElement | null>(null)
const scrollTop = ref(0)
const isRenderingUp = ref(false)
const virtualListHeight = ref(300)
const isOpen = ref(false)
const openDropdownCount = ref(0)
const listboxId = `pyro-listbox-${Math.random().toString(36).substring(2, 11)}`
const triggerRef = ref<HTMLButtonElement | null>(null)
const positionStyle = ref<CSSProperties>({
position: 'fixed',
top: '0px',
left: '0px',
width: '0px',
zIndex: 999,
})
const totalHeight = computed(() => props.options.length * ITEM_HEIGHT)
const visibleOptions = computed(() => {
const startIndex = Math.floor(scrollTop.value / ITEM_HEIGHT) - BUFFER_ITEMS
const visibleCount = Math.ceil(virtualListHeight.value / ITEM_HEIGHT) + 2 * BUFFER_ITEMS
return Array.from({ length: visibleCount }, (_, i) => {
const index = startIndex + i
if (index >= 0 && index < props.options.length) {
return {
index,
option: props.options[index],
}
}
return null
}).filter((item): item is { index: number; option: OptionValue } => item !== null)
})
const selectedOption = computed(() => {
if (selectedValue.value !== null && selectedValue.value !== undefined) {
return props.displayName(selectedValue.value as OptionValue)
}
return props.placeholder || 'Select an option'
})
const radioValue = computed<OptionValue>({
get() {
return props.modelValue ?? selectedValue.value ?? ''
},
set(newValue: OptionValue) {
emit('update:modelValue', newValue)
selectedValue.value = newValue
},
})
const triggerClasses = computed(() => ({
'!cursor-not-allowed opacity-50 grayscale': props.disabled,
'rounded-b-none': dropdownVisible.value && !isRenderingUp.value && !props.disabled,
'rounded-t-none': dropdownVisible.value && isRenderingUp.value && !props.disabled,
}))
const updatePosition = async () => {
if (!triggerRef.value) return
await nextTick()
const triggerRect = triggerRef.value.getBoundingClientRect()
const viewportHeight = window.innerHeight
const margin = 8
const contentHeight = props.options.length * ITEM_HEIGHT
const preferredHeight = Math.min(contentHeight, 300)
const spaceBelow = viewportHeight - triggerRect.bottom
const spaceAbove = triggerRect.top
isRenderingUp.value = spaceBelow < preferredHeight && spaceAbove > spaceBelow
virtualListHeight.value = isRenderingUp.value
? Math.min(spaceAbove - margin, preferredHeight)
: Math.min(spaceBelow - margin, preferredHeight)
positionStyle.value = {
position: 'fixed',
left: `${triggerRect.left}px`,
width: `${triggerRect.width}px`,
zIndex: 999,
...(isRenderingUp.value
? { bottom: `${viewportHeight - triggerRect.top}px`, top: 'auto' }
: { top: `${triggerRect.bottom}px`, bottom: 'auto' }),
}
}
const toggleDropdown = () => {
if (!props.disabled) {
if (dropdownVisible.value) {
closeDropdown()
} else {
openDropdown()
}
}
}
const handleResize = () => {
if (dropdownVisible.value) {
requestAnimationFrame(() => {
updatePosition()
})
}
}
const handleScroll = (event: Event) => {
const target = event.target as HTMLElement
scrollTop.value = target.scrollTop
}
const closeAllDropdowns = () => {
const event = new CustomEvent('close-all-dropdowns')
window.dispatchEvent(event)
}
const selectOption = (option: OptionValue, index: number) => {
radioValue.value = option
emit('change', { option, index })
closeDropdown()
}
const focusNextOption = () => {
if (focusedOptionIndex.value === null) {
focusedOptionIndex.value = 0
} else {
focusedOptionIndex.value = (focusedOptionIndex.value + 1) % props.options.length
}
scrollToFocused()
}
const focusPreviousOption = () => {
if (focusedOptionIndex.value === null) {
focusedOptionIndex.value = props.options.length - 1
} else {
focusedOptionIndex.value =
(focusedOptionIndex.value - 1 + props.options.length) % props.options.length
}
scrollToFocused()
}
const scrollToFocused = () => {
if (focusedOptionIndex.value === null) return
const optionsElement = optionsContainer.value?.querySelector('.overflow-y-auto')
if (!optionsElement) return
const targetScrollTop = focusedOptionIndex.value * ITEM_HEIGHT
const scrollBottom = optionsElement.clientHeight
if (targetScrollTop < optionsElement.scrollTop) {
optionsElement.scrollTop = targetScrollTop
} else if (targetScrollTop + ITEM_HEIGHT > optionsElement.scrollTop + scrollBottom) {
optionsElement.scrollTop = targetScrollTop - scrollBottom + ITEM_HEIGHT
}
}
const openDropdown = async () => {
if (!props.disabled) {
closeAllDropdowns()
dropdownVisible.value = true
isOpen.value = true
openDropdownCount.value++
document.body.style.overflow = 'hidden'
await updatePosition()
nextTick(() => {
optionsContainer.value?.focus()
})
}
}
const closeDropdown = () => {
if (isOpen.value) {
dropdownVisible.value = false
isOpen.value = false
openDropdownCount.value--
if (openDropdownCount.value === 0) {
document.body.style.overflow = ''
}
focusedOptionIndex.value = null
triggerRef.value?.focus()
}
}
const handleTriggerKeyDown = (event: KeyboardEvent) => {
switch (event.key) {
case 'ArrowDown':
case 'ArrowUp':
event.preventDefault()
if (!dropdownVisible.value) {
openDropdown()
focusedOptionIndex.value = event.key === 'ArrowUp' ? props.options.length - 1 : 0
} else if (event.key === 'ArrowDown') {
focusNextOption()
} else {
focusPreviousOption()
}
break
case 'Enter':
case ' ':
event.preventDefault()
if (!dropdownVisible.value) {
openDropdown()
focusedOptionIndex.value = 0
} else if (focusedOptionIndex.value !== null) {
selectOption(props.options[focusedOptionIndex.value], focusedOptionIndex.value)
}
break
case 'Escape':
event.preventDefault()
closeDropdown()
break
case 'Tab':
if (dropdownVisible.value) {
event.preventDefault()
}
break
}
}
const handleListboxKeyDown = (event: KeyboardEvent) => {
switch (event.key) {
case 'Enter':
case ' ':
event.preventDefault()
if (focusedOptionIndex.value !== null) {
selectOption(props.options[focusedOptionIndex.value], focusedOptionIndex.value)
}
break
case 'ArrowDown':
event.preventDefault()
focusNextOption()
break
case 'ArrowUp':
event.preventDefault()
focusPreviousOption()
break
case 'Escape':
event.preventDefault()
closeDropdown()
break
case 'Tab':
event.preventDefault()
break
case 'Home':
event.preventDefault()
focusedOptionIndex.value = 0
scrollToFocused()
break
case 'End':
event.preventDefault()
focusedOptionIndex.value = props.options.length - 1
scrollToFocused()
break
default:
if (event.key.length === 1) {
const char = event.key.toLowerCase()
const index = props.options.findIndex((option) =>
props.displayName(option).toLowerCase().startsWith(char),
)
if (index !== -1) {
focusedOptionIndex.value = index
scrollToFocused()
}
}
break
}
}
onMounted(() => {
window.addEventListener('resize', handleResize)
window.addEventListener('scroll', handleResize, true)
window.addEventListener('click', (event) => {
if (!isChildOfDropdown(event.target as HTMLElement)) {
closeDropdown()
}
})
window.addEventListener('close-all-dropdowns', closeDropdown)
if (selectedValue.value) {
focusedOptionIndex.value = props.options.findIndex((option) => option === selectedValue.value)
}
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
window.removeEventListener('scroll', handleResize, true)
window.removeEventListener('click', (event) => {
if (!isChildOfDropdown(event.target as HTMLElement)) {
closeDropdown()
}
})
window.removeEventListener('close-all-dropdowns', closeDropdown)
if (isOpen.value) {
openDropdownCount.value--
if (openDropdownCount.value === 0) {
document.body.style.overflow = ''
}
}
})
watch(
() => props.modelValue,
(newValue) => {
selectedValue.value = newValue
},
)
watch(dropdownVisible, async (newValue) => {
if (newValue) {
await updatePosition()
scrollTop.value = 0
}
})
const activeDescendant = computed(() =>
focusedOptionIndex.value !== null ? `${listboxId}-option-${focusedOptionIndex.value}` : undefined,
)
const isChildOfDropdown = (element: HTMLElement | null): boolean => {
let currentNode: HTMLElement | null = element
while (currentNode) {
if (currentNode === triggerRef.value || currentNode === optionsContainer.value) {
return true
}
currentNode = currentNode.parentElement
}
return false
}
</script>

View File

@@ -36,7 +36,7 @@
v-for="(option, index) in filteredOptions"
:key="isDivider(option) ? `divider-${index}` : option.id"
>
<div v-if="isDivider(option)" class="h-px w-full bg-button-bg"></div>
<div v-if="isDivider(option)" class="h-px w-full bg-surface-5"></div>
<ButtonStyled v-else type="transparent" role="menuitem" :color="option.color">
<button
v-if="typeof option.action === 'function'"
@@ -288,19 +288,10 @@ const handleMouseOver = (index: number) => {
// Scrolling is disabled for keyboard navigation
const disableBodyScroll = () => {
// Make opening not shift page when there's a vertical scrollbar
const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth
if (scrollBarWidth > 0) {
document.body.style.paddingRight = `${scrollBarWidth}px`
} else {
document.body.style.paddingRight = ''
}
document.body.style.overflow = 'hidden'
}
const enableBodyScroll = () => {
document.body.style.paddingRight = ''
document.body.style.overflow = ''
}

View File

@@ -1,59 +0,0 @@
<template>
<div class="overlay"></div>
<img
src="https://cdn-raw.modrinth.com/medal-banner-background.webp"
class="background-pattern dark-pattern shadow-xl"
alt=""
/>
<img
src="https://cdn-raw.modrinth.com/medal-banner-background-light.webp"
class="background-pattern light-pattern shadow-xl"
alt=""
/>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--medal-promotion-bg-gradient);
z-index: 1;
border-radius: inherit;
}
.light-mode,
.light {
.background-pattern.dark-pattern {
display: none;
}
.background-pattern.light-pattern {
display: block;
}
}
.background-pattern.dark-pattern {
display: block;
}
.background-pattern.light-pattern {
display: none;
}
.background-pattern {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
object-fit: cover;
object-position: bottom;
background-color: var(--medal-promotion-bg);
border-radius: inherit;
color: var(--medal-promotion-bg-orange);
}
</style>

View File

@@ -31,10 +31,9 @@
<script lang="ts" setup>
import { ExternalIcon } from '@modrinth/assets'
import { ButtonStyled } from '@modrinth/ui'
import { ButtonStyled, MedalBackgroundImage } from '@modrinth/ui'
import MedalIcon from '~/assets/images/illustrations/medal_icon.svg?component'
import MedalBackgroundImage from '~/components/ui/servers/marketing/MedalBackgroundImage.vue'
</script>
<style scoped lang="scss">

View File

@@ -39,14 +39,12 @@
<script setup lang="ts">
import { ClockIcon, RocketIcon } from '@modrinth/assets'
import { ButtonStyled } from '@modrinth/ui'
import { ButtonStyled, MedalBackgroundImage } from '@modrinth/ui'
import type { UserSubscription } from '@modrinth/utils'
import dayjs from 'dayjs'
import dayjsDuration from 'dayjs/plugin/duration'
import type { ComponentPublicInstance } from 'vue'
import MedalBackgroundImage from '~/components/ui/servers/marketing/MedalBackgroundImage.vue'
import ServersUpgradeModalWrapper from '../ServersUpgradeModalWrapper.vue'
dayjs.extend(dayjsDuration)

View File

@@ -1,226 +0,0 @@
<template>
<div class="rounded-2xl shadow-xl">
<div
class="medal-promotion flex flex-row items-center overflow-x-hidden rounded-t-2xl p-4 transition-transform duration-100"
:class="status === 'suspended' ? 'rounded-b-none border-b-0 opacity-75' : 'rounded-b-2xl'"
data-pyro-server-listing
:data-pyro-server-listing-id="server_id"
>
<MedalBackgroundImage />
<AutoLink
:to="status === 'suspended' ? '' : `/servers/manage/${props.server_id}`"
class="z-10 flex flex-grow flex-row items-center overflow-x-hidden"
:class="status !== 'suspended' && 'active:scale-95'"
>
<Avatar
v-if="status !== 'suspended'"
src="https://cdn-raw.modrinth.com/medal_icon.webp"
size="64px"
class="z-10"
/>
<div
v-else
class="bg-bg-secondary z-10 flex size-16 shrink-0 items-center justify-center rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
>
<LockIcon class="size-12 text-secondary" />
</div>
<div class="z-10 ml-4 flex min-w-0 flex-col gap-2.5">
<div class="flex flex-row items-center gap-2">
<h2 class="m-0 truncate text-xl font-bold text-contrast">{{ name }}</h2>
<ChevronRightIcon />
<span class="truncate">
<span class="text-medal-orange">
{{ timeLeftCountdown.days }}
</span>
days
<span class="text-medal-orange">
{{ timeLeftCountdown.hours }}
</span>
hours
<span class="text-medal-orange">
{{ timeLeftCountdown.minutes }}
</span>
minutes
<span class="text-medal-orange">
{{ timeLeftCountdown.seconds }}
</span>
seconds remaining...
</span>
</div>
<div
v-if="projectData?.title"
class="m-0 flex flex-row items-center gap-2 text-sm font-medium text-secondary"
>
<Avatar
:src="iconUrl"
no-shadow
style="min-height: 20px; min-width: 20px; height: 20px; width: 20px"
alt="Server Icon"
/>
Using {{ projectData?.title || 'Unknown' }}
</div>
<div
v-if="isConfiguring"
class="text-medal-orange flex min-w-0 items-center gap-2 truncate text-sm font-semibold"
>
<SparklesIcon class="size-5 shrink-0" /> New server
</div>
<ServerInfoLabels
v-else
:server-data="{ game, mc_version, loader, loader_version, net }"
:show-game-label="showGameLabel"
:show-loader-label="showLoaderLabel"
:linked="false"
class="pointer-events-none flex w-full flex-row flex-wrap items-center gap-4 text-secondary *:hidden sm:flex-row sm:*:flex"
/>
</div>
</AutoLink>
<div class="z-10 ml-auto">
<ButtonStyled color="medal-promo" type="outlined" size="large">
<button class="my-auto" @click="handleUpgrade"><RocketIcon /> Upgrade</button>
</ButtonStyled>
</div>
</div>
<div
v-if="status === 'suspended' && suspension_reason === 'upgrading'"
class="relative flex w-full flex-row items-center gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-blue bg-bg-blue p-4 text-sm font-bold text-contrast"
>
<PanelSpinner />
Your server's hardware is currently being upgraded and will be back online shortly.
</div>
<div
v-else-if="status === 'suspended' && suspension_reason === 'cancelled'"
class="relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
>
<div class="flex flex-row gap-2">
<PanelErrorIcon class="!size-5" /> Your Medal server trial has ended and your server has
been suspended. Please upgrade to continue to use your server.
</div>
</div>
<div
v-else-if="status === 'suspended' && suspension_reason"
class="relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
>
<div class="flex flex-row gap-2">
<PanelErrorIcon class="!size-5" /> Your server has been suspended: {{ suspension_reason }}.
Please update your billing information or contact Modrinth Support for more information.
</div>
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
</div>
<div
v-else-if="status === 'suspended'"
class="relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
>
<div class="flex flex-row gap-2">
<PanelErrorIcon class="!size-5" /> Your server has been suspended. Please update your
billing information or contact Modrinth Support for more information.
</div>
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
</div>
</div>
</template>
<script setup lang="ts">
import { ChevronRightIcon, LockIcon, RocketIcon, SparklesIcon } from '@modrinth/assets'
import { AutoLink, Avatar, ButtonStyled, CopyCode } from '@modrinth/ui'
import type { Project, Server } from '@modrinth/utils'
import dayjs from 'dayjs'
import dayjsDuration from 'dayjs/plugin/duration'
import MedalBackgroundImage from '~/components/ui/servers/marketing/MedalBackgroundImage.vue'
import PanelErrorIcon from '../icons/PanelErrorIcon.vue'
import PanelSpinner from '../PanelSpinner.vue'
import ServerInfoLabels from '../ServerInfoLabels.vue'
dayjs.extend(dayjsDuration)
const props = defineProps<Partial<Server>>()
const emit = defineEmits<{ (e: 'upgrade'): void }>()
const showGameLabel = computed(() => !!props.game)
const showLoaderLabel = computed(() => !!props.loader)
let projectData: Ref<Project | null>
if (props.upstream) {
const { data } = await useAsyncData<Project>(
`server-project-${props.server_id}`,
async (): Promise<Project> => {
const result = await useBaseFetch(`project/${props.upstream?.project_id}`)
return result as Project
},
)
projectData = data
} else {
projectData = ref(null)
}
const iconUrl = computed(() => projectData.value?.icon_url || undefined)
const isConfiguring = computed(() => props.flows?.intro)
const timeLeftCountdown = ref({ days: 0, hours: 0, minutes: 0, seconds: 0 })
const expiryDate = computed(() => (props.medal_expires ? dayjs(props.medal_expires) : null))
function handleUpgrade(event: Event) {
event.stopPropagation()
emit('upgrade')
}
function updateCountdown() {
if (!expiryDate.value) {
timeLeftCountdown.value = { days: 0, hours: 0, minutes: 0, seconds: 0 }
return
}
const now = dayjs()
const diff = expiryDate.value.diff(now)
if (diff <= 0) {
timeLeftCountdown.value = { days: 0, hours: 0, minutes: 0, seconds: 0 }
return
}
const duration = dayjs.duration(diff)
timeLeftCountdown.value = {
days: duration.days(),
hours: duration.hours(),
minutes: duration.minutes(),
seconds: duration.seconds(),
}
}
watch(expiryDate, () => updateCountdown(), { immediate: true })
const intervalId = ref<NodeJS.Timeout | null>(null)
onMounted(() => {
intervalId.value = setInterval(updateCountdown, 1000)
})
onUnmounted(() => {
if (intervalId.value) clearInterval(intervalId.value)
})
</script>
<style scoped lang="scss">
.medal-promotion {
position: relative;
border: 1px solid var(--medal-promotion-bg-orange);
background: inherit; // allows overlay + pattern to take over
overflow: hidden;
}
.text-medal-orange {
color: var(--medal-promotion-text-orange);
font-weight: bold;
}
.border-medal-orange {
border-color: var(--medal-promotion-bg-orange);
}
</style>

View File

@@ -261,9 +261,14 @@ import {
SendIcon,
XIcon,
} from '@modrinth/assets'
import { CopyCode, injectNotificationManager, MarkdownEditor, OverflowMenu } from '@modrinth/ui'
import {
Checkbox,
CopyCode,
injectNotificationManager,
MarkdownEditor,
OverflowMenu,
} from '@modrinth/ui'
import Checkbox from '~/components/ui/Checkbox.vue'
import Modal from '~/components/ui/Modal.vue'
import ThreadMessage from '~/components/ui/thread/ThreadMessage.vue'
import { useImageUpload } from '~/composables/image-upload.ts'

View File

@@ -0,0 +1,22 @@
export const useAffiliates = () => {
const affiliateCookie = useCookie('mrs_afl', {
maxAge: 60 * 60 * 24 * 7, // 7 days
sameSite: 'lax',
secure: true,
httpOnly: false,
path: '/',
})
const setAffiliateCode = (code: string) => {
affiliateCookie.value = code
}
const getAffiliateCode = (): string | undefined => {
return affiliateCookie.value || undefined
}
return {
setAffiliateCode,
getAffiliateCode,
}
}

View File

@@ -1,5 +1,39 @@
import { useGeneratedState } from '@/composables/generated.ts'
import { useRequestHeaders, useState } from '#imports'
export const useCountries = () => {
const generated = useGeneratedState()
return computed(() => generated.value.countries ?? [])
}
export const useFormattedCountries = () => {
const countries = useCountries()
return computed(() =>
countries.value.map((country) => {
let label = country.nameShort
if (country.alpha2 === 'TW') {
label = 'Taiwan'
} else if (country.nameShort.length > 30) {
label = `${country.nameShort} (${country.alpha2})`
}
return {
value: country.alpha2,
label,
}
}),
)
}
export const useSubdivisions = (countryCode: ComputedRef<string> | Ref<string> | string) => {
const generated = useGeneratedState()
const code = isRef(countryCode) ? countryCode : ref(countryCode)
return computed(() => generated.value.subdivisions?.[unref(code)] ?? [])
}
export const useUserCountry = () => {
const country = useState<string>('userCountry', () => 'US')
const fromServer = useState<boolean>('userCountryFromServer', () => false)

View File

@@ -19,6 +19,7 @@ const validateValues = <K extends PropertyKey>(flags: Record<K, FlagValue>) => f
export const DEFAULT_FEATURE_FLAGS = validateValues({
// Developer flags
developerMode: false,
demoMode: false,
showVersionFilesInTable: false,
// showAdsWithPlus: false,
alwaysShowChecklistAsPopup: true,

View File

@@ -0,0 +1,122 @@
import type { ISO3166, Labrinth } from '@modrinth/api-client'
import generatedState from '~/generated/state.json'
export interface ProjectType {
actual: string
id: string
display: string
}
export interface LoaderData {
pluginLoaders: string[]
pluginPlatformLoaders: string[]
allPluginLoaders: string[]
dataPackLoaders: string[]
modLoaders: string[]
hiddenModLoaders: string[]
}
// Re-export types from api-client for convenience
export type Country = ISO3166.Country
export type Subdivision = ISO3166.Subdivision
export interface GeneratedState extends Labrinth.State.GeneratedState {
// Additional runtime-defined fields not from the API
projectTypes: ProjectType[]
loaderData: LoaderData
projectViewModes: string[]
approvedStatuses: string[]
rejectedStatuses: string[]
staffRoles: string[]
// Metadata
lastGenerated?: string
apiUrl?: string
}
/**
* Composable for accessing the complete generated state.
* This includes both fetched data and runtime-defined constants.
*/
export const useGeneratedState = () =>
useState<GeneratedState>('generatedState', () => ({
// Cast JSON data to typed API responses
categories: (generatedState.categories ?? []) as Labrinth.Tags.v2.Category[],
loaders: (generatedState.loaders ?? []) as Labrinth.Tags.v2.Loader[],
gameVersions: (generatedState.gameVersions ?? []) as Labrinth.Tags.v2.GameVersion[],
donationPlatforms: (generatedState.donationPlatforms ??
[]) as Labrinth.Tags.v2.DonationPlatform[],
reportTypes: (generatedState.reportTypes ?? []) as string[],
muralBankDetails: generatedState.muralBankDetails as
| Record<string, { bankNames: string[] }>
| undefined,
countries: (generatedState.countries ?? []) as ISO3166.Country[],
subdivisions: (generatedState.subdivisions ?? {}) as Record<string, ISO3166.Subdivision[]>,
projectTypes: [
{
actual: 'mod',
id: 'mod',
display: 'mod',
},
{
actual: 'mod',
id: 'plugin',
display: 'plugin',
},
{
actual: 'mod',
id: 'datapack',
display: 'data pack',
},
{
actual: 'shader',
id: 'shader',
display: 'shader',
},
{
actual: 'resourcepack',
id: 'resourcepack',
display: 'resource pack',
},
{
actual: 'modpack',
id: 'modpack',
display: 'modpack',
},
],
loaderData: {
pluginLoaders: ['bukkit', 'spigot', 'paper', 'purpur', 'sponge', 'folia'],
pluginPlatformLoaders: ['bungeecord', 'waterfall', 'velocity'],
allPluginLoaders: [
'bukkit',
'spigot',
'paper',
'purpur',
'sponge',
'bungeecord',
'waterfall',
'velocity',
'folia',
],
dataPackLoaders: ['datapack'],
modLoaders: ['forge', 'fabric', 'quilt', 'liteloader', 'modloader', 'rift', 'neoforge'],
hiddenModLoaders: ['liteloader', 'modloader', 'rift'],
},
projectViewModes: ['list', 'grid', 'gallery'],
approvedStatuses: ['approved', 'archived', 'unlisted', 'private'],
rejectedStatuses: ['rejected', 'withheld'],
staffRoles: ['moderator', 'admin'],
homePageProjects: generatedState.homePageProjects as unknown as
| Labrinth.Projects.v2.Project[]
| undefined,
homePageSearch: generatedState.homePageSearch as Labrinth.Search.v2.SearchResults | undefined,
homePageNotifs: generatedState.homePageNotifs as Labrinth.Search.v2.SearchResults | undefined,
products: generatedState.products as Labrinth.Billing.Internal.Product[] | undefined,
lastGenerated: generatedState.lastGenerated,
apiUrl: generatedState.apiUrl,
errors: generatedState.errors,
}))

View File

@@ -106,87 +106,4 @@ export class BackupsModule extends ServerModule {
async getAutoBackup(): Promise<AutoBackupSettings> {
return await useServersFetch(`servers/${this.serverId}/autobackup`)
}
downloadBackup(
backupId: string,
backupName: string,
): {
promise: Promise<void>
onProgress: (cb: (p: { loaded: number; total: number; progress: number }) => void) => void
cancel: () => void
} {
const progressSubject = new EventTarget()
const abortController = new AbortController()
const downloadPromise = new Promise<void>((resolve, reject) => {
const auth = this.server.general?.node
if (!auth?.instance || !auth?.token) {
reject(new Error('Missing authentication credentials'))
return
}
const xhr = new XMLHttpRequest()
xhr.addEventListener('progress', (e) => {
if (e.lengthComputable) {
const progress = e.loaded / e.total
progressSubject.dispatchEvent(
new CustomEvent('progress', {
detail: { loaded: e.loaded, total: e.total, progress },
}),
)
} else {
// progress = -1 to indicate indeterminate size
progressSubject.dispatchEvent(
new CustomEvent('progress', {
detail: { loaded: e.loaded, total: 0, progress: -1 },
}),
)
}
})
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
try {
const blob = xhr.response
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `${backupName}.zip`
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
window.URL.revokeObjectURL(url)
resolve()
} catch (error) {
reject(error)
}
} else {
reject(new Error(`Download failed with status ${xhr.status}`))
}
}
xhr.onerror = () => reject(new Error('Download failed'))
xhr.onabort = () => reject(new Error('Download cancelled'))
xhr.open(
'GET',
`https://${auth.instance}/modrinth/v0/backups/${backupId}/download?auth=${auth.token}`,
)
xhr.responseType = 'blob'
xhr.send()
abortController.signal.addEventListener('abort', () => xhr.abort())
})
return {
promise: downloadPromise,
onProgress: (cb: (p: { loaded: number; total: number; progress: number }) => void) => {
progressSubject.addEventListener('progress', ((e: CustomEvent) => {
cb(e.detail)
}) as EventListener)
},
cancel: () => abortController.abort(),
}
}
}

View File

@@ -1,64 +0,0 @@
import tags from '~/generated/state.json'
export const useTags = () =>
useState('tags', () => ({
categories: tags.categories,
loaders: tags.loaders,
gameVersions: tags.gameVersions,
donationPlatforms: tags.donationPlatforms,
reportTypes: tags.reportTypes,
projectTypes: [
{
actual: 'mod',
id: 'mod',
display: 'mod',
},
{
actual: 'mod',
id: 'plugin',
display: 'plugin',
},
{
actual: 'mod',
id: 'datapack',
display: 'data pack',
},
{
actual: 'shader',
id: 'shader',
display: 'shader',
},
{
actual: 'resourcepack',
id: 'resourcepack',
display: 'resource pack',
},
{
actual: 'modpack',
id: 'modpack',
display: 'modpack',
},
],
loaderData: {
pluginLoaders: ['bukkit', 'spigot', 'paper', 'purpur', 'sponge', 'folia'],
pluginPlatformLoaders: ['bungeecord', 'waterfall', 'velocity'],
allPluginLoaders: [
'bukkit',
'spigot',
'paper',
'purpur',
'sponge',
'bungeecord',
'waterfall',
'velocity',
'folia',
],
dataPackLoaders: ['datapack'],
modLoaders: ['forge', 'fabric', 'quilt', 'liteloader', 'modloader', 'rift', 'neoforge'],
hiddenModLoaders: ['liteloader', 'modloader', 'rift'],
},
projectViewModes: ['list', 'grid', 'gallery'],
approvedStatuses: ['approved', 'archived', 'unlisted', 'private'],
rejectedStatuses: ['rejected', 'withheld'],
staffRoles: ['moderator', 'admin'],
}))

View File

@@ -52,16 +52,28 @@
<script setup>
import { SadRinthbot } from '@modrinth/assets'
import { NotificationPanel, provideNotificationManager } from '@modrinth/ui'
import { NotificationPanel, provideModrinthClient, provideNotificationManager } from '@modrinth/ui'
import { defineMessage, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import Logo404 from '~/assets/images/404.svg'
import ModrinthLoadingIndicator from './components/ui/modrinth-loading-indicator.ts'
import { createModrinthClient } from './helpers/api.ts'
import { FrontendNotificationManager } from './providers/frontend-notifications.ts'
const auth = await useAuth()
const config = useRuntimeConfig()
provideNotificationManager(new FrontendNotificationManager())
const client = createModrinthClient(auth.value, {
apiBaseUrl: config.public.apiBaseUrl.replace('/v2/', '/'),
archonBaseUrl: config.public.pyroBaseUrl.replace('/v2/', '/'),
rateLimitKey: config.rateLimitKey,
})
provideModrinthClient(client)
const { formatMessage } = useVIntl()
const props = defineProps({

View File

@@ -0,0 +1,39 @@
import {
type AbstractFeature,
type AuthConfig,
AuthFeature,
CircuitBreakerFeature,
NuxtCircuitBreakerStorage,
type NuxtClientConfig,
NuxtModrinthClient,
VerboseLoggingFeature,
} from '@modrinth/api-client'
import type { Ref } from 'vue'
export function createModrinthClient(
auth: Ref<{ token: string | undefined }>,
config: { apiBaseUrl: string; archonBaseUrl: string; rateLimitKey?: string },
): NuxtModrinthClient {
const optionalFeatures = [
import.meta.dev ? (new VerboseLoggingFeature() as AbstractFeature) : undefined,
].filter(Boolean) as AbstractFeature[]
const clientConfig: NuxtClientConfig = {
labrinthBaseUrl: config.apiBaseUrl,
archonBaseUrl: config.archonBaseUrl,
rateLimitKey: config.rateLimitKey,
features: [
new AuthFeature({
token: async () => auth.value.token,
} as AuthConfig),
new CircuitBreakerFeature({
storage: new NuxtCircuitBreakerStorage(),
maxFailures: 3,
resetTimeout: 30000,
}),
...optionalFeatures,
],
}
return new NuxtModrinthClient(clientConfig)
}

View File

@@ -1,65 +0,0 @@
// Configs
import { configuredXss, md } from '@modrinth/utils'
import hljs from 'highlight.js/lib/core'
import gradle from 'highlight.js/lib/languages/gradle'
// Coding
import groovy from 'highlight.js/lib/languages/groovy'
import ini from 'highlight.js/lib/languages/ini'
import java from 'highlight.js/lib/languages/java'
// Scripting
import javascript from 'highlight.js/lib/languages/javascript'
import json from 'highlight.js/lib/languages/json'
import kotlin from 'highlight.js/lib/languages/kotlin'
import lua from 'highlight.js/lib/languages/lua'
import properties from 'highlight.js/lib/languages/properties'
import python from 'highlight.js/lib/languages/python'
import scala from 'highlight.js/lib/languages/scala'
import xml from 'highlight.js/lib/languages/xml'
import yaml from 'highlight.js/lib/languages/yaml'
/* REGISTRATION */
// Scripting
hljs.registerLanguage('javascript', javascript)
hljs.registerLanguage('python', python)
hljs.registerLanguage('lua', lua)
// Coding
hljs.registerLanguage('java', java)
hljs.registerLanguage('kotlin', kotlin)
hljs.registerLanguage('scala', scala)
hljs.registerLanguage('groovy', groovy)
// Configs
hljs.registerLanguage('gradle', gradle)
hljs.registerLanguage('json', json)
hljs.registerLanguage('ini', ini)
hljs.registerLanguage('yaml', yaml)
hljs.registerLanguage('xml', xml)
hljs.registerLanguage('properties', properties)
/* ALIASES */
// Scripting
hljs.registerAliases(['js'], { languageName: 'javascript' })
hljs.registerAliases(['py'], { languageName: 'python' })
// Coding
hljs.registerAliases(['kt'], { languageName: 'kotlin' })
// Configs
hljs.registerAliases(['json5'], { languageName: 'json' })
hljs.registerAliases(['toml'], { languageName: 'ini' })
hljs.registerAliases(['yml'], { languageName: 'yaml' })
hljs.registerAliases(['html', 'htm', 'xhtml', 'mcui', 'fxml'], { languageName: 'xml' })
export const renderHighlightedString = (string) =>
configuredXss.process(
md({
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(str, { language: lang }).value
} catch {
/* empty */
}
}
return ''
},
}).render(string),
)

View File

@@ -3,7 +3,7 @@ export const getProjectTypeForUrl = (type, categories) => {
}
export const getProjectTypeForUrlShorthand = (type, categories, overrideTags) => {
const tags = overrideTags ?? useTags().value
const tags = overrideTags ?? useGeneratedState().value
if (type === 'mod') {
const isMod = categories.some((category) => {
@@ -87,7 +87,7 @@ export function getVersionsToDisplay(project) {
}
export function formatVersionsForDisplay(gameVersions, overrideTags) {
const tags = overrideTags ?? useTags().value
const tags = overrideTags ?? useGeneratedState().value
const inputVersions = gameVersions.slice()
const allVersions = tags.gameVersions.slice()

View File

@@ -26,7 +26,14 @@
</div>
</div>
</div>
<div ref="main_page" class="layout" :class="{ 'expanded-mobile-nav': isBrowseMenuOpen }">
<div
ref="main_page"
class="layout"
:class="{
'expanded-mobile-nav': isBrowseMenuOpen,
'modrinth-parent__no-modal-blurs': !cosmetics.advancedRendering,
}"
>
<PagewideBanner v-if="isRussia && !flags.hideRussiaCensorshipBanner" variant="error">
<template #title>
<div class="flex flex-col gap-1 text-contrast">
@@ -213,8 +220,15 @@
class="experimental-styles-within desktop-only relative z-[5] mx-auto grid max-w-[1280px] grid-cols-[1fr_auto] items-center gap-2 px-6 py-4 lg:grid-cols-[auto_1fr_auto]"
>
<div>
<NuxtLink to="/" :aria-label="formatMessage(messages.modrinthHomePage)">
<TextLogo aria-hidden="true" class="h-7 w-auto text-contrast" />
<NuxtLink
to="/"
:aria-label="formatMessage(messages.modrinthHomePage)"
class="group hover:brightness-[--hover-brightness] focus-visible:brightness-[--hover-brightness]"
>
<TextLogo
aria-hidden="true"
class="h-7 w-auto text-contrast transition-transform group-active:scale-[0.98]"
/>
</NuxtLink>
</div>
<div
@@ -362,7 +376,7 @@
formatMessage(navMenuMessages.discoverContent)
}}</span>
<span class="contents md:hidden">{{ formatMessage(navMenuMessages.discover) }}</span>
<DropdownIcon aria-hidden="true" class="h-5 w-5 text-secondary" />
<DropdownIcon aria-hidden="true" class="h-5 w-5" />
<template #mods>
<BoxIcon aria-hidden="true" />
@@ -455,6 +469,12 @@
link: '/admin/user_email',
shown: isAdmin(auth.user),
},
{
id: 'affiliates',
color: 'primary',
link: '/admin/affiliates',
shown: isAdmin(auth.user),
},
{
id: 'servers-notices',
color: 'primary',
@@ -464,7 +484,7 @@
{
id: 'servers-nodes',
color: 'primary',
link: '/admin/servers/nodes',
action: (event) => $refs.modal_batch_credit.show(event),
shown: isAdmin(auth.user),
},
]"
@@ -478,7 +498,7 @@
<ReportIcon aria-hidden="true" /> {{ formatMessage(messages.reports) }}
</template>
<template #user-lookup>
<UserIcon aria-hidden="true" /> {{ formatMessage(messages.lookupByEmail) }}
<UserSearchIcon aria-hidden="true" /> {{ formatMessage(messages.lookupByEmail) }}
</template>
<template #file-lookup>
<FileIcon aria-hidden="true" /> {{ formatMessage(messages.fileLookup) }}
@@ -486,7 +506,12 @@
<template #servers-notices>
<IssuesIcon aria-hidden="true" /> {{ formatMessage(messages.manageServerNotices) }}
</template>
<template #servers-nodes> <ServerIcon aria-hidden="true" /> Server Nodes </template>
<template #affiliates>
<AffiliateIcon aria-hidden="true" /> {{ formatMessage(messages.manageAffiliates) }}
</template>
<template #servers-nodes>
<ServerIcon aria-hidden="true" /> Credit server nodes
</template>
</OverflowMenu>
</ButtonStyled>
<ButtonStyled type="transparent">
@@ -541,11 +566,14 @@
<template #notifications>
<BellIcon aria-hidden="true" /> {{ formatMessage(commonMessages.notificationsLabel) }}
</template>
<template #reports>
<ReportIcon aria-hidden="true" /> {{ formatMessage(messages.activeReports) }}
</template>
<template #saved>
<BookmarkIcon aria-hidden="true" /> {{ formatMessage(messages.savedProjects) }}
<LibraryIcon aria-hidden="true" /> {{ formatMessage(commonMessages.collectionsLabel) }}
</template>
<template #servers>
<ServerIcon aria-hidden="true" /> {{ formatMessage(commonMessages.serversLabel) }}
<ServerIcon aria-hidden="true" /> {{ formatMessage(messages.myServers) }}
</template>
<template #plus>
<ArrowBigUpDashIcon aria-hidden="true" />
@@ -563,6 +591,10 @@
<template #organizations>
<OrganizationIcon aria-hidden="true" /> {{ formatMessage(messages.organizations) }}
</template>
<template #affiliate-links>
<AffiliateIcon aria-hidden="true" />
{{ formatMessage(commonMessages.affiliateLinksButton) }}
</template>
<template #revenue>
<CurrencyIcon aria-hidden="true" /> {{ formatMessage(messages.revenue) }}
</template>
@@ -735,7 +767,9 @@
<button
class="tab button-animation"
:title="formatMessage(messages.toggleMenu)"
:aria-label="isMobileMenuOpen ? 'Close menu' : 'Open menu'"
:aria-label="
isMobileMenuOpen ? formatMessage(messages.closeMenu) : formatMessage(messages.openMenu)
"
@click="toggleMobileMenu()"
>
<template v-if="!auth.user">
@@ -759,6 +793,7 @@
<ProjectCreateModal v-if="auth.user" ref="modal_creation" />
<CollectionCreateModal ref="modal_collection_creation" />
<OrganizationCreateModal ref="modal_organization_creation" />
<BatchCreditModal v-if="auth.user && isAdmin(auth.user)" ref="modal_batch_credit" />
<slot id="main" />
</main>
<footer
@@ -810,7 +845,9 @@
</template>
</IntlFormatted>
</p>
<p class="m-0">© 2025 Rinth, Inc.</p>
<p class="m-0">
{{ formatMessage(footerMessages.copyright, { year: currentYear }) }}
</p>
</div>
</div>
<div class="mt-4 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:contents">
@@ -850,10 +887,10 @@
</template>
<script setup>
import {
AffiliateIcon,
ArrowBigUpDashIcon,
BellIcon,
BlueskyIcon,
BookmarkIcon,
BookTextIcon,
BoxIcon,
BracesIcon,
@@ -891,6 +928,7 @@ import {
SunIcon,
TwitterIcon,
UserIcon,
UserSearchIcon,
XIcon,
} from '@modrinth/assets'
import {
@@ -903,10 +941,11 @@ import {
OverflowMenu,
PagewideBanner,
} from '@modrinth/ui'
import { isAdmin, isStaff } from '@modrinth/utils'
import { isAdmin, isStaff, UserBadge } from '@modrinth/utils'
import { IntlFormatted } from '@vintl/vintl/components'
import TextLogo from '~/components/brand/TextLogo.vue'
import BatchCreditModal from '~/components/ui/admin/BatchCreditModal.vue'
import CollectionCreateModal from '~/components/ui/create/CollectionCreateModal.vue'
import OrganizationCreateModal from '~/components/ui/create/OrganizationCreateModal.vue'
import ProjectCreateModal from '~/components/ui/create/ProjectCreateModal.vue'
@@ -1159,6 +1198,10 @@ const messages = defineMessages({
id: 'layout.action.manage-server-notices',
defaultMessage: 'Manage server notices',
},
manageAffiliates: {
id: 'layout.action.manage-affiliates',
defaultMessage: 'Manage affiliate links',
},
newProject: {
id: 'layout.action.new-project',
defaultMessage: 'New project',
@@ -1203,6 +1246,22 @@ const messages = defineMessages({
id: 'layout.nav.analytics',
defaultMessage: 'Analytics',
},
activeReports: {
id: 'layout.nav.active-reports',
defaultMessage: 'Active reports',
},
myServers: {
id: 'layout.nav.my-servers',
defaultMessage: 'My servers',
},
openMenu: {
id: 'layout.mobile.open-menu',
defaultMessage: 'Open menu',
},
closeMenu: {
id: 'layout.mobile.close-menu',
defaultMessage: 'Close menu',
},
})
const footerMessages = defineMessages({
@@ -1215,6 +1274,10 @@ const footerMessages = defineMessages({
defaultMessage:
'NOT AN OFFICIAL MINECRAFT SERVICE. NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT.',
},
copyright: {
id: 'layout.footer.copyright',
defaultMessage: '© {year} Rinth, Inc.',
},
})
useHead({
@@ -1257,6 +1320,8 @@ useSeoMeta({
const developerModeCounter = ref(0)
const currentYear = new Date().getFullYear()
const isMobileMenuOpen = ref(false)
const isBrowseMenuOpen = ref(false)
const navRoutes = computed(() => [
@@ -1299,14 +1364,6 @@ const userMenuOptions = computed(() => {
color: 'purple',
shown: !flags.value.hidePlusPromoInUserMenu && !isPermission(auth.value.user.badges, 1 << 0),
},
{
id: 'notifications',
link: '/dashboard/notifications',
},
{
id: 'saved',
link: '/dashboard/collections',
},
{
id: 'servers',
link: '/servers/manage',
@@ -1328,6 +1385,21 @@ const userMenuOptions = computed(() => {
{
divider: true,
},
{
id: 'notifications',
link: '/dashboard/notifications',
},
{
id: 'reports',
link: '/dashboard/reports',
},
{
id: 'saved',
link: '/dashboard/collections',
},
{
divider: true,
},
{
id: 'projects',
link: '/dashboard/projects',
@@ -1336,14 +1408,19 @@ const userMenuOptions = computed(() => {
id: 'organizations',
link: '/dashboard/organizations',
},
{
id: 'revenue',
link: '/dashboard/revenue',
},
{
id: 'analytics',
link: '/dashboard/analytics',
},
{
id: 'affiliate-links',
link: '/dashboard/affiliate-links',
shown: auth.value.user.badges & UserBadge.AFFILIATE,
},
{
id: 'revenue',
link: '/dashboard/revenue',
},
]
options = [
@@ -1752,7 +1829,7 @@ const footerLinks = [
padding-bottom: var(--size-rounded-card);
left: 0;
background-color: var(--color-raised-bg);
z-index: 6;
z-index: 11; // 20 = modals, 10 = svg icons
transform: translateY(100%);
transition: transform 0.4s cubic-bezier(0.54, 0.84, 0.42, 1);
border-radius: var(--size-rounded-card) var(--size-rounded-card) 0 0;
@@ -1833,7 +1910,7 @@ const footerLinks = [
bottom: 0;
background-color: var(--color-raised-bg);
box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.3);
z-index: 7;
z-index: 11; // 20 = modals, 10 = svg icons
width: 100%;
align-items: center;
justify-content: space-between;

View File

@@ -1,4 +1,10 @@
{
"action.cancel": {
"message": "إلغاء"
},
"action.continue": {
"message": "متابعة"
},
"admin.billing.error.not-found": {
"message": "المستخدم غير موجود"
},
@@ -326,6 +332,24 @@
"auth.verify-email.failed-verification.action": {
"message": "إعادة إرسال بريد التحقق"
},
"auth.verify-email.failed-verification.description": {
"message": "تعذّر علينا التحقّق من بريدك الإلكتروني. حاول إعادة إرسال رسالة التحقّق من خلال لوحة التحكم بعد تسجيل الدخول."
},
"auth.verify-email.failed-verification.description.logged-in": {
"message": "تعذّر علينا التحقّق من بريدك الإلكتروني. حاول إعادة إرسال رسالة التحقّق باستخدام الزر أدناه."
},
"auth.verify-email.failed-verification.title": {
"message": "فشل التحقق من البريد الإلكتروني"
},
"auth.verify-email.post-verification.description": {
"message": "تم التحقّق من عنوان بريدك الإلكتروني بنجاح!"
},
"auth.verify-email.post-verification.title": {
"message": "التحقّق من البريد الإلكتروني"
},
"auth.verify-email.title": {
"message": "تحقّق من البريد الإلكتروني"
},
"auth.welcome.checkbox.subscribe": {
"message": "اشترك في التحديثات حول مودرنث"
},
@@ -338,6 +362,21 @@
"auth.welcome.long-title": {
"message": "مرحبًا بك في مودرنث!"
},
"auth.welcome.title": {
"message": "مرحبًا"
},
"collection.button.delete-icon": {
"message": "حذف الأيقونة"
},
"collection.button.edit-icon": {
"message": "تعديل الأيقونة"
},
"collection.button.remove-project": {
"message": "إزالة المشروع"
},
"collection.button.unfollow-project": {
"message": "إلغاء متابعة المشروع"
},
"collection.delete-modal.description": {
"message": "سيتم حذف هذه المجموعة نهائيًا. لا يمكن التراجع عن هذا الإجراء."
},
@@ -347,6 +386,120 @@
"collection.description": {
"message": "{description} - عرض المجموعة {name} بواسطة {username} على مودرنث"
},
"collection.description.following": {
"message": "مجموعة تم إنشاؤها تلقائيًا تضمّ جميع المشاريع التي تتابعها."
},
"collection.error.not-found": {
"message": "لم يتم العثور على المجموعة"
},
"collection.label.collection": {
"message": "مجموعة"
},
"collection.label.created-at": {
"message": "تم الإنشاء منذ {ago}"
},
"collection.label.curated-by": {
"message": "من إعداد"
},
"collection.label.no-projects": {
"message": "لا تحتوي هذه المجموعة على أي مشاريع!"
},
"collection.label.no-projects-auth": {
"message": "ليس لديك أي مشاريع. هل ترغب في <create-link>إضافة مشروع</create-link>؟"
},
"collection.label.owner": {
"message": "المالك"
},
"collection.label.projects-count": {
"message": "{count, plural,\n one {<stat>{count}</stat> مشروع}\n other {<stat>{count}</stat> مشاريع}\n}"
},
"collection.label.updated-at": {
"message": "تم التحديث منذ {ago}"
},
"collection.title": {
"message": "{name} - مجموعة"
},
"common.no": {
"message": "لا"
},
"common.yes": {
"message": "نعم"
},
"create.collection.cancel": {
"message": "إلغاء"
},
"create.collection.collection-info": {
"message": "سيتم إنشاء مجموعتك الجديدة كمجموعة عامة تحتوي على {count, plural,\n one {# مشروع}\n other {# مشاريع}\n}."
},
"create.collection.create-collection": {
"message": "إنشاء مجموعة"
},
"create.collection.error-title": {
"message": "حدث خطأ"
},
"create.collection.name-label": {
"message": "الاسم"
},
"create.collection.name-placeholder": {
"message": "أدخل اسم المجموعة..."
},
"create.collection.summary-description": {
"message": "جملة أو جملتان تصف مجموعتك."
},
"create.collection.summary-label": {
"message": "الملخّص"
},
"create.collection.summary-placeholder": {
"message": "هذه مجموعة من..."
},
"create.collection.title": {
"message": "إنشاء مجموعة"
},
"create.limit-alert.approaching-limit": {
"message": "تقترب من حدّ {type} ({current}/{max})"
},
"create.limit-alert.approaching-limit-description": {
"message": "أنت على وشك بلوغ حدّ {type}. يُرجى التواصل مع الدعم إذا كنت بحاجة إلى أكثر من {max} {typePlural}."
},
"create.limit-alert.contact-support": {
"message": "تواصل مع الدعم الفني"
},
"create.limit-alert.limit-reached": {
"message": "تم بلوغ حدّ {type}"
},
"create.limit-alert.limit-reached-description": {
"message": "لقد وصلت إلى حدّ {type} الخاص بك وهو {max}. يُرجى التواصل مع الدعم لزيادة الحدّ."
},
"create.limit-alert.type-collection": {
"message": "مجموعة"
},
"create.limit-alert.type-organization": {
"message": "مؤسسة"
},
"create.limit-alert.type-plural-collection": {
"message": "مجموعات"
},
"create.limit-alert.type-plural-organization": {
"message": "مؤسسات"
},
"create.limit-alert.type-plural-project": {
"message": "مشاريع"
},
"create.limit-alert.type-project": {
"message": "مشروع"
},
"create.organization.cancel": {
"message": "إلغاء"
},
"create.organization.create-organization": {
"message": "إنشاء مؤسسة"
},
"create.organization.error-title": {
"message": "حدث خطأ"
},
"create.organization.name-label": {
"message": ""
},
"error.collection.404.list_item.3": {
"message": "قد تكون هذه المجموعة قد أزالها فريق مراقبة مودرنث لانتهاك <tou-link>شروط الاستخدام</tou-link> الخاصة بنا."
},
@@ -356,15 +509,54 @@
"error.generic.default.list_item.2": {
"message": "إذا استمر حدوث ذلك، قد ترغب في إعلام فريق مودرنث بالانضمام إلى <discord-link>سيرفر ديسكورد</discord-link> الخاص بنا."
},
"error.organization.404.list_item.1": {
"message": "ربما أدخلت عنوان URL الخاص بالمؤسسة بشكل غير صحيح."
},
"error.organization.404.list_item.2": {
"message": "قد يكون مالك المؤسسة قد غيّر عنوان الـURL أو حذفه."
},
"error.organization.404.list_item.3": {
"message": "قد تكون هذه المنظمة قد أزالها فريق مراقبة مودرنث لانتهاك <tou-link>شروط الاستخدام</tou-link> الخاصة بنا."
},
"error.organization.404.list_title": {
"message": "لماذا؟"
},
"error.organization.404.title": {
"message": "لم يتم العثور على المؤسسة"
},
"error.project.404.list_item.1": {
"message": "ربما أدخلت عنوان URL الخاص بالمؤسسة بشكل غير صحيح."
},
"error.project.404.list_item.2": {
"message": "قد يكون مالك المشروع قد غيّر عنوان الـURL، أو جعل المشروع خاصًا، أو حذفه."
},
"error.project.404.list_item.3": {
"message": "قد يكون هذا المشروع قد أزاله فريق مراقبة مودرنث لانتهاك <tou-link>شروط الاستخدام</tou-link> الخاصة بنا."
},
"error.project.404.list_title": {
"message": "لماذا؟"
},
"error.project.404.title": {
"message": "لم يتم العثور على المشروع"
},
"error.user.404.list_item.1": {
"message": "ربما أدخلت اسم مستخدم المستخدم بشكل غير صحيح."
},
"error.user.404.list_item.2": {
"message": "قد يكون المستخدم قد غيّر اسم المستخدم أو حذف حسابه."
},
"error.user.404.list_item.3": {
"message": "تم تعطيل حساب هذا المستخدم لانتهاكه <tou-link>شروط الاستخدام</tou-link> الخاصة بمودرنث."
},
"error.user.404.list_title": {
"message": "لماذا؟"
},
"error.user.404.title": {
"message": "لم يتم العثور على المُستخدم"
},
"frog": {
"message": "لقد تم ضفدعتك! 🐸"
},
"landing.button.discover-mods": {
"message": "اكتشف المودات"
},

View File

@@ -1,6 +1,9 @@
{
"action.cancel": {
"message": "Paphai"
},
"app-marketing.download.description": {
"message": "Magamit ang among desktop nga aplikasyon sa magkalahi-lahi nga plataporma, pamili sa imong giganahan nga bersiyon."
"message": "Magamit ang among desktop nga aplikasyon sa magkalahi-lahi nga pantawan, pamili sa imong giganahan nga bersiyon."
},
"app-marketing.download.download-appimage": {
"message": "Karganugi ang AppImage"
@@ -35,15 +38,54 @@
"app-marketing.download.windows": {
"message": "Windows"
},
"app-marketing.features.importing.multimc-alt": {
"message": "MultiMC"
},
"app-marketing.features.mod-management.actions": {
"message": "Mga Kalihokan"
},
"app-marketing.features.mod-management.description": {
"message": "Ginapadali sa Modrinth ang pagpamahala sa tanan nimong kausaban sa mausa nga dapit. Makataud, makatangtang, ug makapasibo sa mga kausaban sa usa ra ka tuplok."
},
"app-marketing.features.mod-management.installed-mods": {
"message": "Mga gitaud nga kausaban"
},
"app-marketing.features.mod-management.name": {
"message": "Ngalan"
},
"app-marketing.features.mod-management.search-mods": {
"message": "Mangita og mga kausaban"
},
"app-marketing.features.open-source.title": {
"message": "Bukas nga tinubdan"
},
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.infinite-mb": {
"message": "∞ MB"
},
"app-marketing.features.performance.less-than-150mb": {
"message": "< 150 MB"
},
"app-marketing.features.performance.modrinth-app": {
"message": "Modrinth App"
},
"app-marketing.features.performance.one-billion-percent": {
"message": "1 ka wakat nga %"
},
"app-marketing.features.performance.ram": {
"message": "RAM"
},
"app-marketing.features.performance.small": {
"message": "Gagmay"
},
"app-marketing.features.play.description": {
"message": "Gamita ang Modrinth App sa pagkarganug ug pagdula sa imong paborito nga mga kausaban ug putos sa kausaban."
},
"app-marketing.features.sharing.share-button": {
"message": "Pag-ambit"
},
"app-marketing.hero.download-button": {
"message": "Karganugi ang Modrinth App"
},
@@ -56,11 +98,23 @@
"app-marketing.hero.more-download-options": {
"message": "Dugang nga Kapilian sa Pagkarganug"
},
"auth.reset-password.method-choice.email-username.placeholder": {
"message": "Dagiwat"
},
"auth.sign-in.additional-options": {
"message": "<forgot-password-link>Nalimtan ang tinago nga pulong?</forgot-password-link> • <create-account-link>Paghimo ug akawnt</create-account-link>"
},
"auth.sign-up.email.label": {
"message": "Dagiwat"
},
"auth.verify-email.action.account-settings": {
"message": "Mga gusto sa akawnt"
"message": "Mga himutangan sa akawnt"
},
"auth.verify-email.post-verification.description": {
"message": "Malampusong napamatud-an ang padal-anan sa imong dagiwat!"
},
"auth.welcome.description": {
"message": "Lakip na ka karon sa niining makapahingangha nga dakbalangay sama sa mga magbubuhat ug manunuhid nga gatukod, gakarganug, ug gasunod sa kapanahonan sa mga makapahibulong nga mga kausaban."
"message": "Lakip na ka karon sa niining makapahingangha nga dakbalangay sama sa mga magbubuhat ug manunuhid nga pagtukod, pagkarganug, ug pagsunod sa kapanahonan sa mga makapahibulong nga mga kausaban."
},
"collection.button.edit-icon": {
"message": "Usba ang amoy"
@@ -71,6 +125,51 @@
"collection.delete-modal.description": {
"message": "Hangtod sa kahangturan nga matangtang kining gitipon. Kini nga aksyon dili mabawi."
},
"collection.error.not-found": {
"message": "Dili makit-i ang tinigom"
},
"collection.label.owner": {
"message": "Tag-iya"
},
"common.no": {
"message": "Hindi"
},
"common.yes": {
"message": "Oo"
},
"create.collection.cancel": {
"message": "Paphai"
},
"create.collection.name-label": {
"message": "Ngalan"
},
"create.organization.cancel": {
"message": "Paphai"
},
"create.organization.name-label": {
"message": "Ngalan"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "Paphai"
},
"create.project.name-label": {
"message": "Ngalan"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-public": {
"message": "Publiko"
},
"create.project.visibility-unlisted": {
"message": "Wala malista"
},
"dashboard.collections.label.search-input": {
"message": "Mangita sa imong mga gitigom"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Usa ka entidad sa negosyo ang langyaw nga entidad nga naghan-ay gawas sa Tinipong Bansa (sama sa di-US nga korporasyon, partnership, o LLC)."
},
@@ -80,17 +179,62 @@
"dashboard.creator-tax-form-modal.entity.question": {
"message": "Usa ka ba nga pribado nga indibidwal o uban sa usa ka langyaw nga entidad?"
},
"error.collection.404.list_title": {
"message": "Ngano?"
},
"error.generic.default.title": {
"message": "Ayay!"
},
"error.organization.404.list_title": {
"message": "Ngano?"
},
"error.project.404.list_title": {
"message": "Ngano?"
},
"error.user.404.list_title": {
"message": "Ngano?"
},
"frog.altText": {
"message": "Usa ka matinuod nga pamintal sa labirintong palaka"
},
"frog.title": {
"message": "Baki"
},
"landing.button.discover-mods": {
"message": "Pagkaplag og mga kausaban"
},
"landing.button.go-to-dashboard": {
"message": "Adtoan ang talad sa pagsubay"
},
"landing.creator.feature.data-statistics.description": {
"message": "Makadawat og detalyado nga pagtaho sa mga paglantaw og panid, ihap sa pagkarganug, ug kinitaan"
},
"landing.feature.launcher.description": {
"message": "Ang bukas nga tinubdan nga API sa Modrinth nagtugot sa mga tiglansad nga makadugang sa lawom nga panagsama sa Modrinth. Mahimo nimong magamit ang Modrinth pinaagi sa <link>among aplikasyon</link> ug sa pipila nga labing inila nga mga tiglansad sama sa ATLauncher, MultiMC, ug Prism Launcher."
},
"landing.heading.the-place-for-minecraft": {
"message": "Dapit alang sa Minecraft nga {content}"
},
"landing.heading.the-place-for-minecraft.mods": {
"message": "mga kausaban"
},
"landing.heading.the-place-for-minecraft.resource-packs": {
"message": "mga putos sa kabtangan"
"message": "mga putos sa kahinguhaan"
},
"landing.notifications.has-been-updated": {
"message": "Napasibo ang {title}!"
},
"landing.search.label": {
"message": "Mangita"
},
"landing.search.placeholder": {
"message": "Mangita..."
},
"landing.section.for-players.label": {
"message": "Alang sa mga Magdudula"
},
"landing.subheading": {
"message": "Pagkaplag, pagdula, ug pagbahin og mga Minecraft nga kontento sa among bukas nga tinubdan nga plataporma nga gihimo alang sa dakbalangay."
"message": "Pagkaplag, pagdula, ug pagbahin og mga Minecraft nga kontento sa among bukas nga tinubdan nga pantawan nga gihimo alang sa dakbalangay."
},
"layout.action.create-new": {
"message": "Pagbuhat og bag-o..."
@@ -98,14 +242,23 @@
"layout.action.reports": {
"message": "Mga pagtaho"
},
"layout.banner.account-action": {
"message": "Gakinahanglan og akawnt"
},
"layout.banner.add-email.button": {
"message": "Mga gusto sa akawnt"
"message": "Duawi ang mga himutangan sa akawnt"
},
"layout.banner.add-email.description": {
"message": "Tungod sa mga hinungdan sa kahilwasan, manginahanglan ang Modrinth nga morehistro ka og padad-anan sa dagiwat sa imong akawnt."
},
"layout.banner.build-fail.description": {
"message": "Napakyas sa pagmugna og kahimtang gikan sa API kining pagkatap sa frontend sa Modrinth. Basin tungod sa pagkabalda o sayop sa paghan-ay. Pagtukod pag-usab kon magamit na ang API. Mga kalagdaan sa sayop: {errors}; Ang kasamtangan nga URL sa API: {url}"
"message": "Napakyas sa pagmugna og kahimtang gikan sa API kining pagkatap sa frontend sa Modrinth. Basin tungod sa pagkabalda o sayop sa paghan-ay. Paggama pag-usab kon magamit na ang API. Mga kalagdaan sa sayop: {errors}; Ang kasamtangan nga URL sa API: {url}"
},
"layout.banner.build-fail.title": {
"message": "Naay sayup sa pagmugna sa kahimtang gikan sa API samtang gapatukod."
"message": "Naay sayup sa pagmugna sa kahimtang gikan sa API samtang naggama."
},
"layout.banner.verify-email.description": {
"message": "Tungod sa mga hinungdan sa kahilwasan, manginahanglan ang Modrinth nga mapamatud-an ang padad-anan sa dagiwat sa imong akawnt."
},
"layout.footer.about": {
"message": "Mahitungod"
@@ -162,7 +315,7 @@
"message": "Modrinth Servers"
},
"layout.footer.resources": {
"message": "Mga Kabtangan"
"message": "Mga Kahinguhaan"
},
"layout.footer.resources.api-docs": {
"message": "Dokumentasyon sa API"
@@ -192,7 +345,13 @@
"message": "X"
},
"layout.meta.description": {
"message": "Pagkarganug ug mga pagbag-o, pagsukip, putos sa datos, tigpandong, putos sa kabtangan, ug putos sa pagbag-o sa Modrinth. Pagdiskobre ug pagmantala ug mga proyekto sa Modrinth nga adunay moderno, sayon gamiton nga dunggoanan ug API."
"message": "Pagkarganug ug mga pagbag-o, pagsukip, putos sa lawsayod, tigpandong, putos sa kahinguhaan, ug putos sa pagbag-o sa Modrinth. Pagdiskobre ug pagmantala ug mga proyekto sa Modrinth nga adunay moderno, sayon gamiton nga dunggoanan ug API."
},
"layout.nav.home": {
"message": "Puloy-anan"
},
"layout.nav.search": {
"message": "Mangita"
},
"moderation.page.projects": {
"message": "Mga Proyekto"
@@ -203,35 +362,80 @@
"moderation.page.technicalReview": {
"message": "Teknikal ng Pagsusi"
},
"moderation.search.placeholder": {
"message": "Mangita..."
},
"profile.bio.fallback.creator": {
"message": "Usa ka magbubuhat sa Modrinth."
},
"profile.bio.fallback.user": {
"message": "Usa ka tiggamit sa Modrinth."
},
"profile.details.label.email": {
"message": "Dagiwat"
},
"profile.label.badges": {
"message": "Tsapa"
},
"profile.label.joined": {
"message": "Miapil"
},
"profile.label.no": {
"message": "Hindi"
},
"profile.label.yes": {
"message": "Oo"
},
"profile.meta.description": {
"message": "Pagkarganug og mga proyekto ni {username} sa Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Pagkarganug og mga proyekto ni {username} sa Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, other {<stat>{count}</stat> ka karganug sa proyekto}}"
"project-member-header.accept": {
"message": "Dawati"
},
"project-member-header.error": {
"message": "Kasaypanan"
},
"project-type.datapack.plural": {
"message": "Mga Putos sa Datos"
"message": "Mga Putos sa Lawsayod"
},
"project-type.datapack.singular": {
"message": "Putos sa Datos"
"message": "Putos sa Lawsayod"
},
"project-type.mod.plural": {
"message": "Mga Kausaban"
},
"project-type.mod.singular": {
"message": "Kausaban"
},
"project-type.plugin.singular": {
"message": "Pagsukip"
},
"project-type.resourcepack.plural": {
"message": "Mga Putos sa Kabtangan"
"message": "Mga Putos sa Kahinguhaan"
},
"project-type.resourcepack.singular": {
"message": "Putos sa Kabtangan"
"message": "Putos sa Kahinguhaan"
},
"project-type.shader.singular": {
"message": "Tigpandong"
},
"project.about.details.updated": {
"message": "Nasibo {date}"
},
"project.download.game-version": {
"message": "Bersiyon sa dula: {version}"
},
"project.download.install-with-app": {
"message": "Itaud gamit ang Modrint App"
},
"project.download.no-app": {
"message": "Wala kay Modrinth App?"
},
"project.download.platform": {
"message": "Plataporma: {platform}"
"message": "Pantawan: {platform}"
},
"project.download.search-game-versions": {
"message": "Mangita og mga bersiyon sa dula..."
@@ -239,6 +443,9 @@
"project.download.select-game-version": {
"message": "Pilia tanang bersiyon sa dula"
},
"project.download.select-platform": {
"message": "Pamili og pantawan"
},
"project.download.show-all-versions": {
"message": "Ipakita ang tanang bersiyon"
},
@@ -272,40 +479,112 @@
"project.settings.environment.notice.review-options.description": {
"message": "Bag-o ra namo gipalambo ang sistema sa Mga Kalikopan sa Modrinth ug ang mga bag-ong kapilian magamit na karon. Mahimo nga susiha nga husto ang gipili sa ubos ug tuploka ang 'Pamatud-i' sa imong paghuman!"
},
"project.settings.environment.verification.verify-button": {
"message": "Pamatud-i"
},
"project.settings.general.name.title": {
"message": "Ngalan"
},
"project.settings.general.url.title": {
"message": "URL"
},
"project.settings.title": {
"message": "Mga Gusto"
},
"project.stats.downloads-label": {
"message": "karganug{count, plural, one {} other {}}"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Napakyas ang pag-andam sa karganug"
"scopes.performAnalytics.description": {
"message": "Buhata ang mga kalihokan sa matukibon"
},
"servers.backups.item.prepare-download": {
"message": "Andami ang karganug"
"servers.backups.item.lock": {
"message": "Pagtrangka"
},
"servers.backups.item.prepare-download-again": {
"message": "Sulayi pag-usab ang pag-andam"
"servers.backups.item.locked": {
"message": "Nagtrangka"
},
"servers.backups.item.preparing-download": {
"message": "Gaandam sa karganug..."
"servers.backups.item.rename": {
"message": "Ilisdi ang ngalan"
},
"servers.backups.item.retry": {
"message": "Sulayi pag-usab"
},
"servers.backups.item.unlock": {
"message": "Yabihan"
},
"servers.notice.actions": {
"message": "Mga Kalihokan"
},
"servers.notice.begins": {
"message": "Magsugod"
},
"servers.notice.id": {
"message": "ID"
},
"servers.notice.level": {
"message": "Patag"
},
"servers.plan.large.name": {
"message": "Dagko"
},
"servers.plan.medium.name": {
"message": "Tungatunga"
},
"servers.plan.small.name": {
"message": "Gagmay"
},
"settings.billing.payment_method_type.eftpos": {
"message": "EFTPOS"
},
"settings.billing.payment_method_type.jcb": {
"message": "JCB"
},
"settings.billing.payment_method_type.paypal": {
"message": "PayPal"
},
"settings.billing.payment_method_type.unknown": {
"message": "Diiniliang pamaagi sa pagbayad"
},
"settings.billing.payment_method_type.visa": {
"message": "Visa"
},
"settings.display.flags.description": {
"message": "Magpagana o di-magpagana og tino nga mga bahin sa imong himan."
"message": "Magpagana o di-magpagana og tino nga mga panagway sa imong himan."
},
"settings.display.project-list-layouts.datapack": {
"message": "Panid sa mga Putos sa Datos"
"message": "Panid sa Mga Putos sa Lawsayod"
},
"settings.display.project-list-layouts.description": {
"message": "Pamili og imong gigusto nga paghan-ay alang sa matag usa nga panid nga mopakita sa mga listahan sa proyekto sa imong himan."
"message": "Pamili og imong gigusto nga paghan-ay alang sa matag panid nga mopakita sa mga listahan sa proyekto sa imong himan."
},
"settings.display.project-list-layouts.resourcepack": {
"message": "Panid sa mga Putos sa Kabtangan"
"message": "Panid sa Mga Putos sa Kahinguhaan"
},
"settings.display.project-list-layouts.title": {
"message": "Mga paghan-ay sa listahan sa proyekto"
},
"settings.display.theme.description": {
"message": "Pamili og imong gigusto nga hiligotanong kulay alang sa Modrinth sa kini nga himan."
},
"settings.language.languages.search-field.placeholder": {
"message": "Mangita og pinulongan..."
},
"settings.pats.modal.create.name.label": {
"message": "Ngalan"
},
"settings.profile.bio.title": {
"message": "Kagibuhi"
},
"settings.profile.profile-picture.reset": {
"message": "Pag-usab"
},
"settings.sessions.description": {
"message": "Ania dini tanan ang mga himan nga karon nakalog-in sa imong akawnt sa Modrinth. Mahimo kang maglog-out sa matag usa.\n\nKung makakita ka og usa nga dili nimo mailhan, paglog-out sa maong himan ug usba dayon ang tinago nga pulong sa imong akawnt sa Modrinth."
},
"settings.sessions.unknown-os": {
"message": "Diinilang OS"
},
"settings.sessions.unknown-platform": {
"message": "Diinilang pantawan"
}
}

View File

@@ -461,6 +461,12 @@
"create.organization.name-label": {
"message": "Název"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-public": {
"message": "Veřejné"
},
@@ -782,9 +788,6 @@
"profile.error.not-found": {
"message": "Uživatel nenalezen"
},
"profile.joined-at": {
"message": "Připojil/a se <date>{ago}</date>"
},
"profile.label.badges": {
"message": "Odznaky"
},
@@ -812,12 +815,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Stáhněte si projekty od {username} na Modrinthu"
},
"profile.stats.downloads": {
"message": "{count, plural, other {<stat>{count}</stat> stažení}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> projekt} few {<stat>{count}</stat> projekty} other {<stat>{count}</stat> projektů}}"
},
"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}}"
},
@@ -959,6 +956,9 @@
"project.settings.general.name.title": {
"message": "Název"
},
"project.settings.general.url.title": {
"message": "URL"
},
"project.stats.downloads-label": {
"message": "stažení{count, plural, one {} few {} many {} other {}}"
},
@@ -1052,18 +1052,6 @@
"report.submit": {
"message": "Odeslat hlášení"
},
"revenue.transfers.total": {
"message": "Vybrali jste celkem {amount}."
},
"revenue.transfers.total.method": {
"message": "Vybrali jste {amount} skrze {method}."
},
"revenue.transfers.total.year": {
"message": "V roce {year} jste vybrali {amount}."
},
"revenue.transfers.total.year_method": {
"message": "V roce {year} jste vybrali {amount} skrze {method}."
},
"scopes.analytics.label": {
"message": "Přečíst analytiku"
},

View File

@@ -1,4 +1,10 @@
{
"action.cancel": {
"message": "Annuller"
},
"action.continue": {
"message": "Forsæt"
},
"admin.billing.error.not-found": {
"message": "Bruger ikke fundet"
},
@@ -65,6 +71,24 @@
"app-marketing.features.mod-management.byAuthor": {
"message": "af {author}"
},
"app-marketing.features.mod-management.description": {
"message": "Modrinth gør det nemt at håndtere alle dine mods i et sted. Du kan installere, afinstallere, og opdatere mods med et enkelt klik."
},
"app-marketing.features.mod-management.installed-mods": {
"message": "Installerede mods"
},
"app-marketing.features.mod-management.name": {
"message": "Navn"
},
"app-marketing.features.mod-management.search-mods": {
"message": "Søg mods"
},
"app-marketing.features.mod-management.title": {
"message": "Mod håndtering"
},
"app-marketing.features.mod-management.version": {
"message": "Version"
},
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},

View File

@@ -566,6 +566,27 @@
"create.project.visibility-unlisted": {
"message": "Nicht gelistet"
},
"dashboard.affiliate-links.create.button": {
"message": "Partnerlink erstellen"
},
"dashboard.affiliate-links.error.title": {
"message": "Fehler beim laden von Partnerlinks"
},
"dashboard.affiliate-links.header": {
"message": "Deine Partnerlinks"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "Dies wird permanent den Partbercode `{id}` widerrufen und alle existierenden Links, welche es nutzen, werden nicht mehr gültig sein."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Widerrufen"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "Bist du sicher dass du deinen \"{title}\" Partnerlink widerrufen willst?"
},
"dashboard.affiliate-links.search": {
"message": "Partnerlinks durchsuchen..."
},
"dashboard.collections.button.create-new": {
"message": "Erstellen"
},
@@ -578,6 +599,18 @@
"dashboard.collections.long-title": {
"message": "Deine Kollektionen"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "{formType} herunterladen"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "Dein {formType} Steuerformular wurde erfolgreich eingereicht!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Du kannst nun frei abheben. Falls du fragen hast oder deine Daten aktualisieren musst <support-link>kontaktiere den Support</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Alles ist bereit! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Eine ausländische Einheit bezeichnet eine ausserhalb der Vereinigten Staaten gegründete Geschäftseinheit (z.B. eine nicht US-amerikanische Kapitalgesellschaft, Personengesellschaft oder LLC)."
},
@@ -602,6 +635,339 @@
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Bist du ein US Bürger?"
},
"dashboard.creator-withdraw-modal.complete-tax-form": {
"message": "Steuerformular abschliessen"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Mit Limit weitermachen"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Details"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Menge"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "FX rate"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Gebühr"
},
"dashboard.creator-withdraw-modal.fee-breakdown-net-amount": {
"message": "Nettobetrag"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Wirtschaftseinheit"
},
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Eine Wirtschaftseinheit bezieht sich auf eine registrierte Organisation wie ein Unternehmen, Partnerschaft oder GmbH."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "Hebst du als Einzelperson oder Firma ab?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Privatperson"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Land auswählen"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Länder suchen..."
},
"dashboard.creator-withdraw-modal.method-selection.error-text": {
"message": "Fehler beim laden verfügbarer Zahlungsmethoden. Versuch es später erneut."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Laden von Zahlungsmethoden fehlgeschlagen"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Region"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Einige Zahlungsmöglichkeiten sind in bestimmten Regionen nicht verfügbar."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Auszahlungsmethode auswählen"
},
"dashboard.creator-withdraw-modal.method-selection.tax-limit-warning": {
"message": "Dein Auszahlungslimit ist <b>{amount}</b>. <tax-link>Fülle das Steuerformular aus</tax-link> um mehr abzuheben."
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Kontoinhaber"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Coin"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Bestätige deine Wallet-Adresse"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id": {
"message": "Personalausweisnummer"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder": {
"message": "Personalausweisnummer eingeben"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport": {
"message": "Passnummer"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder": {
"message": "Passnummer eingeben"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id": {
"message": "Personalausweisnummer"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder": {
"message": "Personalausweisnummer eingeben"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc": {
"message": "RUC-Nummer"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder": {
"message": "RUC-Nummer eingeben"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id": {
"message": "Steueridentifikationsnummer"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder": {
"message": "Steueridentifikationsnummer eingeben"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Netzwerk"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "Du näherst dich dem Auszahlungslimit. Du kannst noch <b>{amountRemaining}</b> abheben, aber ein Steuerformular wird benötigt, um mehr abzuheben."
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Konto"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Konto trennen"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Zahlungsmethode"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "PayPal-Konto"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Verbinde dein PayPal-Konto um Zahlungen direkt zu erhalten."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Speichern"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Venmo-Benutzername erfolgreich gespeichert!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Gespeichert"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Mit PayPal anmelden"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-description": {
"message": "Gib deinen Venmo-Benutzernamen ein um Zahlungen zu erhalten."
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle": {
"message": "Venmo-Benutzername"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@benutzername"
},
"dashboard.creator-withdraw-modal.stage.completion": {
"message": "Abgeschlossen"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Methode"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Kontodetails"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Verifizierung"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Steuerformular"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Details"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "Um dein vollständiges Guthaben von <b>{available}</b> abzuheben musst du das unten stehende Formular ausfüllen. Dies wird für die Steuererklärung benötigt und muss nur einmal ausgefüllt werden."
},
"dashboard.creator-withdraw-modal.tax-form-required.body-with-limit": {
"message": "Du musst ein W-9- oder W-8-Formular für die Steuerunterlagen von Modrinth ausfüllen, damit wir die Steuervorschriften einhalten können."
},
"dashboard.creator-withdraw-modal.tax-form-required.header": {
"message": "Steuerformular benötigt"
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Zahlungsmethode"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Belohnung"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder": {
"message": "Belohnung auswählen"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Belohnungen"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "Unverifizierte E-Mail"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-message": {
"message": "Die Zustellungs-E-Mail die du eingegeben hast ist nicht mit deinem Modrinth-Konto verbunden. Belohnungen, welche an eine falsche E-Mail-Adresse gesendet werden können von Modrinth nicht wiederhergestellt werden."
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Weniger Gebühren verfügbar"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-message": {
"message": "Du has USD für PayPal International ausgewählt. <direct-paypal-link>Wechsle zu direktem PayPal</direct-paypal-link> für bessere Gebühren (≈2% statt ≈6%)."
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Auszahlen"
},
"dashboard.creator-withdraw-modal.withdraw-limit": {
"message": "Auszahlungslimit"
},
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "Du hast dein Auszahlungslimit von <b>{withdrawLimit}</b> aufgebraucht. Du musst ein Steuerformular ausfüllen, um merh abzuheben."
},
"dashboard.revenue.available-now": {
"message": "Jetzt verfügbar"
},
"dashboard.revenue.balance": {
"message": "Guthaben"
},
"dashboard.revenue.estimated-tooltip.msg1": {
"message": "Geschätzte Einnahmen können sich bis zur verfügbarmachung ändern."
},
"dashboard.revenue.estimated-tooltip.msg2": {
"message": "Klicke um zu erfahren, wie Modrinth deine Einnahmen verwaltet (Englisch)."
},
"dashboard.revenue.estimated-with-date": {
"message": "Geschätzt {date}"
},
"dashboard.revenue.processing": {
"message": "Verarbeitet"
},
"dashboard.revenue.processing.tooltip": {
"message": "Einnahmen bleiben in bearbeitung bis zum ende des Monats, und werden 60 Tage danach verfügbar."
},
"dashboard.revenue.stats.received": {
"message": "Erhalten"
},
"dashboard.revenue.stats.transactions": {
"message": "Transaktionen"
},
"dashboard.revenue.stats.withdrawn": {
"message": "Ausgezahlt"
},
"dashboard.revenue.tos": {
"message": "Durch das hochladen von Projekten auf Modrinth, und das abheben von Geld von deinem Konto, stimmst du den <terms-link>Bedingungen des Rewards-Programm</terms-link> zu. Erfahre mehr über das <info-link>Reward-Programm</info-link>."
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Als CSV herunterladen"
},
"dashboard.revenue.transactions.header": {
"message": "Transaktionen"
},
"dashboard.revenue.transactions.none": {
"message": "Keine Transaktionen"
},
"dashboard.revenue.transactions.none.desc": {
"message": "Deine Auszahlungen und Abhebungen erscheinen hier."
},
"dashboard.revenue.transactions.see-all": {
"message": "Alle anzeigen"
},
"dashboard.revenue.withdraw.blocked-tin-mismatch": {
"message": "Deine Auszahlungen sind vorrübergehend gesperrt, da deine TIN oder SSN nicht mit den IRS-Aufzeichnungen übereinstimmt. Bitte kontaktiere den Support um dein Steuerformular zurückzusetzen und erneut einzureichen."
},
"dashboard.revenue.withdraw.card.description": {
"message": "Hebe von deinem Verfügbaren Guthaben über einen Zahlungsmethode ab."
},
"dashboard.revenue.withdraw.card.title": {
"message": "Abheben"
},
"dashboard.revenue.withdraw.header": {
"message": "Abheben"
},
"dashboard.withdraw.completion.account": {
"message": "Konto"
},
"dashboard.withdraw.completion.amount": {
"message": "Menge"
},
"dashboard.withdraw.completion.close-button": {
"message": "Schliessen"
},
"dashboard.withdraw.completion.date": {
"message": "Datum"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "Du wirst eine E-Mail auf <b>{email}</b> mit Instruktionen zur Einlösung deiner Auszahlung."
},
"dashboard.withdraw.completion.exchange-rate": {
"message": "Wechselkurs"
},
"dashboard.withdraw.completion.fee": {
"message": "Gebühr"
},
"dashboard.withdraw.completion.method": {
"message": "Methode"
},
"dashboard.withdraw.completion.net-amount": {
"message": "Nettobetrag"
},
"dashboard.withdraw.completion.recipient": {
"message": "Empfänger"
},
"dashboard.withdraw.completion.title": {
"message": "Abhebung abgeschlossen"
},
"dashboard.withdraw.completion.transactions-button": {
"message": "Transaktionen"
},
"dashboard.withdraw.completion.wallet": {
"message": "Wallet"
},
"dashboard.withdraw.error.generic.text": {
"message": "Wir konnten deine Auszahlungsanforderung nicht übermitteln. Bitte überprüfe deine Angaben oder kontaktiere den Support."
},
"dashboard.withdraw.error.generic.title": {
"message": "Abheben nicht möglich"
},
"dashboard.withdraw.error.invalid-address.text": {
"message": "Die angegebene Adresse konnte nicht bestätigt werden. Bitte überprüfe deine Adressdetails."
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Adressbestätigung fehlgeschlagen"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": "Die angegebenen Bankinformationen sind ungültig. Bitte überprüfe deine Informationen."
},
"dashboard.withdraw.error.invalid-bank.title": {
"message": "Ungültige Bankinformationen"
},
"dashboard.withdraw.error.invalid-wallet.text": {
"message": "Die Crypto-Wallet Adresse die du gegeben hast ist ungültig. Bitte überprüfe sie und versuch es erneut."
},
"dashboard.withdraw.error.invalid-wallet.title": {
"message": "Ungültige Wallet-Adresse"
},
"dashboard.withdraw.error.minimum-not-met.text": {
"message": "Die Auszahlungsmenge (Nach abzug von Gebühren) entspricht nicht dem Mindestbetrag. Bitte erhöhe deine Auszahlungsmenge."
},
"dashboard.withdraw.error.minimum-not-met.title": {
"message": "Menge zu gering"
},
"dashboard.withdraw.error.tax-form.text": {
"message": "Du musst ein Steuerformular ausfüllen, um deinen Antrag auf Auszahling einzureichen."
},
"dashboard.withdraw.error.tax-form.title": {
"message": "Bitte Steuerformular ausfüllen"
},
"error.collection.404.list_item.1": {
"message": "Du hast eventuell die Kollektions-URL falsch geschrieben."
},
@@ -857,6 +1223,9 @@
"layout.action.lookup-by-email": {
"message": "Über E-Mail ansehen"
},
"layout.action.manage-affiliates": {
"message": "Partnerlinks verwalten"
},
"layout.action.manage-server-notices": {
"message": "Servermitteilungen verwalten"
},
@@ -912,11 +1281,20 @@
"message": "Steuerformular abschliessen"
},
"layout.banner.tax.description": {
"message": "Du hast dieses Jahr bereits mehr als $600 von Modrinth abgehoben. Um die Steuervorschriften einzuhalten, musst du ein Steuerformular ausfüllen. Deine Abhebungen werden ausgesetzt, bis dieses Formular eingereicht wurde."
"message": "Du hast bereits mehr als $600 von Modrinth für dieses Jahr abgehoben. Um geltende Steuervorschriften einzuhalten, musst du ein Steuerformular ausfüllen. Deine Abhebungen werden ausgesetzt, bis dieses Formular eingereicht wurde."
},
"layout.banner.tax.title": {
"message": "Steuerformular benötigt"
},
"layout.banner.tin-mismatch.action": {
"message": "Support kontaktieren"
},
"layout.banner.tin-mismatch.description": {
"message": "Deine Abbuchungen sind vorrübergehend blockiert, da deine TIN oder SSN nicht mit IRS-Aufzeichnungen übereinstimmt. Bitte kontakitiere den Support umd dein Steuerformular zurückzusetzen und erneut zu übermitteln."
},
"layout.banner.tin-mismatch.title": {
"message": "Steuerformular fehlgeschlagen"
},
"layout.banner.verify-email.action": {
"message": "Verifizierungs-E-Mail erneut senden"
},
@@ -941,6 +1319,9 @@
"layout.footer.about.status": {
"message": "Status"
},
"layout.footer.copyright": {
"message": "© {year} Rinth, Inc."
},
"layout.footer.legal": {
"message": "Rechtliches"
},
@@ -1019,8 +1400,17 @@
"layout.meta.og-description": {
"message": "Entdecke und veröffentliche Minecraft-Inhalte!"
},
"layout.mobile.close-menu": {
"message": "Menü schliessen"
},
"layout.mobile.open-menu": {
"message": "Menü öffnen"
},
"layout.nav.active-reports": {
"message": "Aktive Meldungen"
},
"layout.nav.analytics": {
"message": "Analytik"
"message": "Analysen"
},
"layout.nav.discover": {
"message": "Entdecken"
@@ -1046,6 +1436,9 @@
"layout.nav.modrinth-home-page": {
"message": "Modrinth Startseite"
},
"layout.nav.my-servers": {
"message": "Meine Server"
},
"layout.nav.organizations": {
"message": "Organisationen"
},
@@ -1091,27 +1484,342 @@
"moderation.technical.search.placeholder": {
"message": "Technische Rezensionen durchsuchen..."
},
"muralpay.account-type.checking": {
"message": "Girokonto"
},
"muralpay.account-type.savings": {
"message": "Sparkonto"
},
"muralpay.country.at": {
"message": "Österreich"
},
"muralpay.country.be": {
"message": "Belgien"
},
"muralpay.country.cy": {
"message": "Zypern"
},
"muralpay.country.de": {
"message": "Deutschland"
},
"muralpay.country.ee": {
"message": "Estland"
},
"muralpay.country.es": {
"message": "Spanien"
},
"muralpay.country.fi": {
"message": "Finnland"
},
"muralpay.country.fr": {
"message": "Frankreich"
},
"muralpay.country.gr": {
"message": "Griechenland"
},
"muralpay.country.ie": {
"message": "Irland"
},
"muralpay.country.it": {
"message": "Italien"
},
"muralpay.country.lt": {
"message": "Litauen"
},
"muralpay.country.lu": {
"message": "Luxenburg"
},
"muralpay.country.lv": {
"message": "Lettland"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Niederlande"
},
"muralpay.country.pt": {
"message": "Portugal"
},
"muralpay.country.sk": {
"message": "Slowakei"
},
"muralpay.document-type.national-id": {
"message": "Personalausweis"
},
"muralpay.document-type.passport": {
"message": "Reisepass"
},
"muralpay.document-type.resident-id": {
"message": "Aufenthaltsgenehmigung"
},
"muralpay.document-type.ruc": {
"message": "RUC"
},
"muralpay.document-type.tax-id": {
"message": "Steuer-ID"
},
"muralpay.field.account-number": {
"message": "Kontonummer"
},
"muralpay.field.account-number-cbu-cvu": {
"message": "Kontonummer (CBU/CVU)"
},
"muralpay.field.account-number-cci": {
"message": "Kontonummer (CCI)"
},
"muralpay.field.account-number-type": {
"message": "Kontonummertyp"
},
"muralpay.field.account-type": {
"message": "Kontotyp"
},
"muralpay.field.bank-account-number": {
"message": "Kontonummer"
},
"muralpay.field.branch-code": {
"message": "Filialcode"
},
"muralpay.field.clabe": {
"message": "CLABE"
},
"muralpay.field.country": {
"message": "Land"
},
"muralpay.field.cpf-cnpj": {
"message": "CPF/CNPJ"
},
"muralpay.field.cuit-cuil": {
"message": "CUIT/CUIL"
},
"muralpay.field.document-type": {
"message": "Dokumententyp"
},
"muralpay.field.iban": {
"message": "IBAN"
},
"muralpay.field.phone-number": {
"message": "Telefonnummer"
},
"muralpay.field.pix-email": {
"message": "PIX-E-Mail"
},
"muralpay.field.pix-key-type": {
"message": "PIX-Schlüsseltyp"
},
"muralpay.field.pix-phone": {
"message": "PIX-Telefon"
},
"muralpay.field.routing-number": {
"message": "Bankleitzahl"
},
"muralpay.field.swift-bic": {
"message": "SWIFT/BIC"
},
"muralpay.field.wallet-address": {
"message": "Wallet-Adresse"
},
"muralpay.help.cbu-cvu": {
"message": "Clave Bancaria Uniforme oder Clave Virtual Uniforme"
},
"muralpay.help.cci": {
"message": "Código de Cuenta Interbancaria"
},
"muralpay.help.clabe": {
"message": "Clave Bancaria Estandarizada (Mexikanische Bankkontonummer)"
},
"muralpay.help.cpf-cnpj": {
"message": "Brasilianische Steueridentifikationsnummer"
},
"muralpay.help.cuit-cuil": {
"message": "Argentinische Steuer-ID"
},
"muralpay.help.iban": {
"message": "Internationale Bankkontonummer"
},
"muralpay.help.swift-bic": {
"message": "Bankleitzahl"
},
"muralpay.pix-type.bank-account": {
"message": "Bankkonto"
},
"muralpay.pix-type.document": {
"message": "CPF/CNPJ"
},
"muralpay.pix-type.email": {
"message": "E-Mail"
},
"muralpay.pix-type.phone": {
"message": "Telefonnummer"
},
"muralpay.placeholder.account-number": {
"message": "Kontonummer eingeben"
},
"muralpay.placeholder.cbu-cvu": {
"message": "CBU oder CVU eingeben"
},
"muralpay.placeholder.cbu-cvu-type": {
"message": "CBU oder CVU"
},
"muralpay.placeholder.cci": {
"message": "20-stelligen CCI eingeben"
},
"muralpay.placeholder.cuit-cuil": {
"message": "CUIT oder CUIL eingeben"
},
"muralpay.placeholder.enter-account-number": {
"message": "Kontonummer eingeben"
},
"muralpay.placeholder.enter-branch-code": {
"message": "Filialcode eingeben"
},
"muralpay.placeholder.enter-clabe": {
"message": "18-stelligen CLABE eingeben"
},
"muralpay.placeholder.enter-cpf-cnpj": {
"message": "CPF oder CNPJ eingeben"
},
"muralpay.placeholder.enter-iban": {
"message": "IBAN eingeben"
},
"muralpay.placeholder.enter-pix-email": {
"message": "PIX-E-Mail eingeben"
},
"muralpay.placeholder.enter-routing-number": {
"message": "9-stellige Bankleitzahl eingeben"
},
"muralpay.placeholder.enter-swift-bic": {
"message": "SWIFT/BIC-Code eingeben"
},
"muralpay.placeholder.iban-crc": {
"message": "Costarikanische IBAN eingeben"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
"muralpay.placeholder.pix-phone": {
"message": "+55..."
},
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"muralpay.rail.fiat-ars.name": {
"message": "Banküberweisung (ARS)"
},
"muralpay.rail.fiat-brl.name": {
"message": "PIX-Überweisung (BRL)"
},
"muralpay.rail.fiat-clp.name": {
"message": "Banküberweisung (CLP)"
},
"muralpay.rail.fiat-cop.name": {
"message": "Banküberweisung (COP)"
},
"muralpay.rail.fiat-crc.name": {
"message": "Banküberweisung (CRC)"
},
"muralpay.rail.fiat-eur.name": {
"message": "Banküberweisung (EUR)"
},
"muralpay.rail.fiat-mxn.name": {
"message": "Banküberweisung (MXN)"
},
"muralpay.rail.fiat-pen.name": {
"message": "Banküberweisung (PEN)"
},
"muralpay.rail.fiat-usd-peru.name": {
"message": "Banküberweisung (USD - Peru)"
},
"muralpay.rail.fiat-usd.name": {
"message": "Banküberweisung (USD)"
},
"muralpay.rail.fiat-zar.name": {
"message": "Banküberweisung (ZAR)"
},
"muralpay.rail.usdc-base.name": {
"message": "USDC (Base)"
},
"muralpay.rail.usdc-celo.name": {
"message": "USDC (Celo)"
},
"muralpay.rail.usdc-ethereum.name": {
"message": "USDC (Ethereum)"
},
"muralpay.rail.usdc-polygon.name": {
"message": "Crypto (USDC)"
},
"muralpay.warning.wallet-address": {
"message": "Überprüfe deine Wallet-Adresse. An eine falsche Adresse gesendete Gelder können nicht wiederhergestellt werden."
},
"profile.bio.fallback.creator": {
"message": "Ein Modrinth Ersteller."
},
"profile.bio.fallback.user": {
"message": "Ein Modrinth Benutzer."
},
"profile.button.billing": {
"message": "Nutzer Zahlungen verwalten"
},
"profile.button.edit-role": {
"message": "Rolle bearbeiten"
},
"profile.button.info": {
"message": "Nutzerdetails ansehen"
},
"profile.button.manage-projects": {
"message": "Projekte verwalten"
},
"profile.button.remove-affiliate": {
"message": "Als Partner entfernen"
},
"profile.button.set-affiliate": {
"message": "Als Partner setzen"
},
"profile.details.label.auth-providers": {
"message": "Authentifizierungsanbieter"
},
"profile.details.label.email": {
"message": "E-Mail"
},
"profile.details.label.has-password": {
"message": "Hat Passwort"
},
"profile.details.label.has-totp": {
"message": "Hat TOTP"
},
"profile.details.label.payment-methods": {
"message": "Zahlungsmethoden"
},
"profile.details.tooltip.email-not-verified": {
"message": "E-Mail nicht verifiziert"
},
"profile.details.tooltip.email-verified": {
"message": "E-Mail verifiziert"
},
"profile.error.not-found": {
"message": "Benutzer nicht gefunden"
},
"profile.joined-at": {
"message": "<date>{ago}</date> beigetreten"
"profile.label.affiliate": {
"message": "Partner"
},
"profile.label.badges": {
"message": "Abzeichen"
},
"profile.label.collection": {
"message": "Kollektion"
},
"profile.label.details": {
"message": "Details"
},
"profile.label.downloads": {
"message": "{count} {count, plural, one {Download} other {Downloads}}"
},
"profile.label.joined": {
"message": "Beigetreten"
},
"profile.label.no": {
"message": "Nein"
},
"profile.label.no-collections": {
"message": "Dieser Nutzer hat keine Kollektionen!"
},
@@ -1127,18 +1835,21 @@
"profile.label.organizations": {
"message": "Organisationen"
},
"profile.label.projects": {
"message": "{count} Projekt{count, plural, one {} other {e}}"
},
"profile.label.saving": {
"message": "Speichert..."
},
"profile.label.yes": {
"message": "Ja"
},
"profile.meta.description": {
"message": "Lade {username}'s Projekte auf Modrinth herunter"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Lade {username}'s Projekte auf Modrinth herunter"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> Projekt download} other {<stat>{count}</stat> Projekt downloads}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> Projek} other {<stat>{count}</stat> Projekte}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat>} other {<stat>{count}</stat>}} Projekt-Follower"
},
@@ -1188,7 +1899,7 @@
"message": "Erneut zur Überprüfung einreichen"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Dein Projekt wurde {status} von Modrinth-Mitarbeitern. In den meisten Fällen kannst du das Projekt erneut zur Überprüfung einreichen, nachdem du die Punkte in der Mitarbeiter-Nachricht adressiert hast."
"message": "Dein Projekt wurde vom Modrinth-Team {status, select, rejected {abgelehnt} withheld {zurückgehalten} other {{status}}}. In der Regel hast du die Möglichkeit, es nach Umsetzung der Anmerkungen erneut einzureichen."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Du musst die benötigten Schritte in der Veröffentlichungsliste abschliessen!"
@@ -1595,23 +2306,11 @@
"report.submit": {
"message": "Meldung einreichen"
},
"revenue.transfers.total": {
"message": "Du hast insgesammt {amount} abgehoben."
},
"revenue.transfers.total.method": {
"message": "Du hast {amount} über {method} abgehoben."
},
"revenue.transfers.total.year": {
"message": "Du hast {amount} im Jahr {year} abgehoben."
},
"revenue.transfers.total.year_method": {
"message": "Du hast {amount} im Jahr {year} über {method} abgehoben."
},
"scopes.analytics.description": {
"message": "Zugriff auf Analysedaten"
},
"scopes.analytics.label": {
"message": "Lesezugriff Analytiks"
"message": "Lesezugriff Analysen"
},
"scopes.collectionCreate.description": {
"message": "Kollektionen erstellen"
@@ -1865,9 +2564,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Backup-Wiederherstellung im gange"
},
"servers.backups.item.already-preparing": {
"message": "Bereite bereits Backup zum download vor"
},
"servers.backups.item.automated": {
"message": "Automatisiert"
},
@@ -1877,9 +2573,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Erstellung eines Backup fehlgeschlagen"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Vorbereitung von download fehlgeschlagen"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Wiederherstellung von Backup fehlgeschlagen"
},
@@ -1889,15 +2582,6 @@
"servers.backups.item.locked": {
"message": "Gesperrt"
},
"servers.backups.item.prepare-download": {
"message": "Download vorbereiten"
},
"servers.backups.item.prepare-download-again": {
"message": "Versuche vorbereitung erneut"
},
"servers.backups.item.preparing-download": {
"message": "Download vorbereiten..."
},
"servers.backups.item.queued-for-backup": {
"message": "Zur sicherung in warteschlange gestellt"
},

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
"et": "Estnisch",
"fi": "Finnisch",
"fr": "Französisch",
"fr-BE": "Französisch (Belgien, Wallonisch)",
"fr-BE": "Französisch (Belgien)",
"fr-CA": "Französisch (Kanada)",
"he": "Hebräisch",
"hi": "Hindi",
@@ -35,9 +35,9 @@
"lt": "Litauisch",
"lv": "Lettisch",
"ms": "Malaiisch",
"nb": "Norwegisch, Bokmål",
"nb": "Norwegisch (Bokmål)",
"nl": "Niederländisch",
"nn": "Neues Norwegisch",
"nn": "Norwegisch (Nynorsk)",
"pes": "Persisch",
"pl": "Polnisch",
"pt": "Portugiesisch",

View File

@@ -5,6 +5,6 @@
},
"searchTerms": {
"description": "Please provide additional search terms associated with the language, if needed, to enhance the search functionality (e.g., American English, Deutschland). Each search term should be entered on a separate line. Translate as a hyphen (-) if no additional terms are needed.",
"message": "Deutschland\nDE\nDEU\nGermany\nGerman\nGER"
"message": "Deutschland\nDeutsch\nHochdeutsch\nDE\nDEU\nGermany\nGerman\nGER"
}
}

View File

@@ -1,7 +1,43 @@
{
"action.continue": {
"message": "Συνέχεια"
},
"admin.billing.error.not-found": {
"message": "Ο χρήστης δε βρέθηκε"
},
"app-marketing.download.description": {
"message": "Η εφαρμογή μας για υπολογιστές είναι διαθέσιμη σε όλες τις πλατφόρμες, επιλέξτε την έκδοση που επιθυμείτε."
},
"app-marketing.download.download-appimage": {
"message": "Λήψη του AppImages"
},
"app-marketing.download.download-beta": {
"message": "Λήψη της beta"
},
"app-marketing.download.download-deb": {
"message": "Λήψη του DEB"
},
"app-marketing.download.download-rpm": {
"message": "Λήψη του RPM"
},
"app-marketing.download.linux": {
"message": "Linux"
},
"app-marketing.download.linux-disclaimer": {
"message": "Οι εκδόσεις Linux της εφαρμογής Modrinth είναι <issues-link>γνωστό ότι παρουσιάζουν προβλήματα</issues-link> σε ορισμένα συστήματα και διαμορφώσεις. Εάν η εφαρμογή Modrinth είναι ασταθής στο σύστημά σας, σας ενθαρρύνουμε να δοκιμάσετε άλλες εφαρμογές όπως το <prism-link>Prism Launcher</prism-link> για να εγκαταστήσετε εύκολα το περιεχόμενο του Modrinth."
},
"app-marketing.download.mac": {
"message": "Mac"
},
"app-marketing.download.options-title": {
"message": "Επιλογές λήψης"
},
"app-marketing.download.terms": {
"message": "Με τη λήψη του Modrinth App, συμφωνείτε με τους <terms-link>Όρους</terms-link> και την <privacy-link>Πολιτική Απορρήτου</privacy-link> μας."
},
"app-marketing.download.third-party-packages": {
"message": "Πακέτα τρίτων"
},
"auth.authorize.action.authorize": {
"message": "Εξουσιοδότηση"
},

View File

@@ -11,6 +11,7 @@
"el": "Ελληνικά",
"en-GB": "Αγγλικά (Ηνωμένο Βασίλειο)",
"en-US": "Αγγλικά (Ηνωμένες Πολιτείες)",
"en-x-lolcat": "LOLCAT",
"en-x-pirate": "Αγγλικά (Πειρατικά)",
"en-x-updown": "Αγγλικά (Ανάποδα)",
"en-x-uwu": "Αγγλικά (UwU)",
@@ -47,6 +48,7 @@
"sk": "Σλοβακικά",
"sv": "Σουηδικά",
"th": "Ταϊλανδικά",
"tok": "Τόκι Πόνα",
"tr": "Τουρκικά",
"tt": "Ταταρικά",
"uk": "Ουκρανικά",

View File

@@ -566,6 +566,27 @@
"create.project.visibility-unlisted": {
"message": "Unlisted"
},
"dashboard.affiliate-links.create.button": {
"message": "Create affiliate link"
},
"dashboard.affiliate-links.error.title": {
"message": "Error loading affiliate links"
},
"dashboard.affiliate-links.header": {
"message": "Your affiliate links"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "This will permanently revoke the affiliate code `{id}` and any existing links with this code that have been shared will no longer be valid."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Revoke"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "Are you sure you want to revoke your ''{title}'' affiliate link?"
},
"dashboard.affiliate-links.search": {
"message": "Search affiliate links..."
},
"dashboard.collections.button.create-new": {
"message": "Create new"
},
@@ -614,6 +635,339 @@
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Are you a US citizen?"
},
"dashboard.creator-withdraw-modal.complete-tax-form": {
"message": "Complete tax form"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Continue with limit"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Details"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Amount"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "FX rate"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Fee"
},
"dashboard.creator-withdraw-modal.fee-breakdown-net-amount": {
"message": "Net amount"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Business entity"
},
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "A business entity refers to a registered organization such as a corporation, partnership, or LLC."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "Are you a withdrawing as an individual or business?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Private individual"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Select your country"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Search countries..."
},
"dashboard.creator-withdraw-modal.method-selection.error-text": {
"message": "Unable to fetch available payment methods. Please try again later."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Failed to load payment methods"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Region"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Some payout methods are not available in certain regions."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Select withdraw method"
},
"dashboard.creator-withdraw-modal.method-selection.tax-limit-warning": {
"message": "Your withdraw limit is <b>{amount}</b>, <tax-link>complete a tax form</tax-link> to withdraw more."
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Account owner"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Coin"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Confirm your wallet address"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id": {
"message": "National ID number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder": {
"message": "Enter national ID number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport": {
"message": "Passport number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder": {
"message": "Enter passport number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id": {
"message": "Resident ID number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder": {
"message": "Enter resident ID number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc": {
"message": "RUC number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder": {
"message": "Enter RUC number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id": {
"message": "Tax ID number"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder": {
"message": "Enter tax ID number"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Network"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "You're nearing the withdraw threshold. You can withdraw <b>{amountRemaining}</b> now, but a tax form is required for more."
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Account"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Disconnect account"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Payment method"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "PayPal account"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Connect your PayPal account to receive payments directly."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Save"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Venmo handle saved successfully!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Saved"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Sign in with PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-description": {
"message": "Enter your Venmo handle to receive payments."
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle": {
"message": "Venmo handle"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@username"
},
"dashboard.creator-withdraw-modal.stage.completion": {
"message": "Complete"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Method"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Account Details"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Verification"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Tax form"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Details"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "To withdraw your full <b>{available}</b> available balance please complete the form below. It is required for tax reporting and only needs to be done once."
},
"dashboard.creator-withdraw-modal.tax-form-required.body-with-limit": {
"message": "You must complete a W-9 or W-8 form for Modrinth's tax records so we remain compliant with tax regulations."
},
"dashboard.creator-withdraw-modal.tax-form-required.header": {
"message": "Tax form required"
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Payment method"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Reward"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder": {
"message": "Select reward"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Rewards"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "Unverified email"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-message": {
"message": "The delivery email you have entered is not associated with your Modrinth account. Modrinth cannot recover rewards sent to an incorrect email address."
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Lower fees available"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-message": {
"message": "You selected USD for PayPal International. <direct-paypal-link>Switch to direct PayPal</direct-paypal-link> for better fees (≈2% instead of ≈6%)."
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Withdraw"
},
"dashboard.creator-withdraw-modal.withdraw-limit": {
"message": "Withdraw limit"
},
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "You've used up your <b>{withdrawLimit}</b> withdrawal limit. You must complete a tax form to withdraw more."
},
"dashboard.revenue.available-now": {
"message": "Available now"
},
"dashboard.revenue.balance": {
"message": "Balance"
},
"dashboard.revenue.estimated-tooltip.msg1": {
"message": "Estimated revenue may be subject to change until it is made available."
},
"dashboard.revenue.estimated-tooltip.msg2": {
"message": "Click to read about how Modrinth handles your revenue."
},
"dashboard.revenue.estimated-with-date": {
"message": "Estimated {date}"
},
"dashboard.revenue.processing": {
"message": "Processing"
},
"dashboard.revenue.processing.tooltip": {
"message": "Revenue stays in processing until the end of the month, then becomes available 60 days later."
},
"dashboard.revenue.stats.received": {
"message": "Received"
},
"dashboard.revenue.stats.transactions": {
"message": "Transactions"
},
"dashboard.revenue.stats.withdrawn": {
"message": "Withdrawn"
},
"dashboard.revenue.tos": {
"message": "By uploading projects to Modrinth and withdrawing money from your account, you agree to our <terms-link>Rewards Program Terms</terms-link>. Learn more about the <info-link>Reward Program</info-link>."
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Download as CSV"
},
"dashboard.revenue.transactions.header": {
"message": "Transactions"
},
"dashboard.revenue.transactions.none": {
"message": "No transactions"
},
"dashboard.revenue.transactions.none.desc": {
"message": "Your payouts and withdrawals will appear here."
},
"dashboard.revenue.transactions.see-all": {
"message": "See all"
},
"dashboard.revenue.withdraw.blocked-tin-mismatch": {
"message": "Your withdrawals are temporarily locked because your TIN or SSN didn't match IRS records. Please contact support to reset and resubmit your tax form."
},
"dashboard.revenue.withdraw.card.description": {
"message": "Withdraw from your available balance to any payout method."
},
"dashboard.revenue.withdraw.card.title": {
"message": "Withdraw"
},
"dashboard.revenue.withdraw.header": {
"message": "Withdraw"
},
"dashboard.withdraw.completion.account": {
"message": "Account"
},
"dashboard.withdraw.completion.amount": {
"message": "Amount"
},
"dashboard.withdraw.completion.close-button": {
"message": "Close"
},
"dashboard.withdraw.completion.date": {
"message": "Date"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "You'll receive an email at <b>{email}</b> with instructions to redeem your withdrawal."
},
"dashboard.withdraw.completion.exchange-rate": {
"message": "Exchange rate"
},
"dashboard.withdraw.completion.fee": {
"message": "Fee"
},
"dashboard.withdraw.completion.method": {
"message": "Method"
},
"dashboard.withdraw.completion.net-amount": {
"message": "Net amount"
},
"dashboard.withdraw.completion.recipient": {
"message": "Recipient"
},
"dashboard.withdraw.completion.title": {
"message": "Withdraw complete"
},
"dashboard.withdraw.completion.transactions-button": {
"message": "Transactions"
},
"dashboard.withdraw.completion.wallet": {
"message": "Wallet"
},
"dashboard.withdraw.error.generic.text": {
"message": "We were unable to submit your withdrawal request, please check your details or contact support."
},
"dashboard.withdraw.error.generic.title": {
"message": "Unable to withdraw"
},
"dashboard.withdraw.error.invalid-address.text": {
"message": "The address you provided could not be verified. Please check your address details."
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Address verification failed"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": "The bank account details you provided are invalid. Please verify your information."
},
"dashboard.withdraw.error.invalid-bank.title": {
"message": "Invalid bank details"
},
"dashboard.withdraw.error.invalid-wallet.text": {
"message": "The crypto wallet address you provided is invalid. Please double-check and try again."
},
"dashboard.withdraw.error.invalid-wallet.title": {
"message": "Invalid wallet address"
},
"dashboard.withdraw.error.minimum-not-met.text": {
"message": "The withdrawal amount (after fees) doesn't meet the minimum requirement. Please increase your withdrawal amount."
},
"dashboard.withdraw.error.minimum-not-met.title": {
"message": "Amount too low"
},
"dashboard.withdraw.error.tax-form.text": {
"message": "You must complete a tax form to submit your withdrawal request."
},
"dashboard.withdraw.error.tax-form.title": {
"message": "Please complete tax form"
},
"error.collection.404.list_item.1": {
"message": "You may have mistyped the collection's URL."
},
@@ -869,6 +1223,9 @@
"layout.action.lookup-by-email": {
"message": "Lookup by email"
},
"layout.action.manage-affiliates": {
"message": "Manage affiliate links"
},
"layout.action.manage-server-notices": {
"message": "Manage server notices"
},
@@ -962,6 +1319,9 @@
"layout.footer.about.status": {
"message": "Status"
},
"layout.footer.copyright": {
"message": "© {year} Rinth, Inc."
},
"layout.footer.legal": {
"message": "Legal"
},
@@ -1040,6 +1400,15 @@
"layout.meta.og-description": {
"message": "Discover and publish Minecraft content!"
},
"layout.mobile.close-menu": {
"message": "Close menu"
},
"layout.mobile.open-menu": {
"message": "Open menu"
},
"layout.nav.active-reports": {
"message": "Active reports"
},
"layout.nav.analytics": {
"message": "Analytics"
},
@@ -1067,6 +1436,9 @@
"layout.nav.modrinth-home-page": {
"message": "Modrinth home page"
},
"layout.nav.my-servers": {
"message": "My servers"
},
"layout.nav.organizations": {
"message": "Organizations"
},
@@ -1112,6 +1484,273 @@
"moderation.technical.search.placeholder": {
"message": "Search tech reviews..."
},
"muralpay.account-type.checking": {
"message": "Checking"
},
"muralpay.account-type.savings": {
"message": "Savings"
},
"muralpay.country.at": {
"message": "Austria"
},
"muralpay.country.be": {
"message": "Belgium"
},
"muralpay.country.cy": {
"message": "Cyprus"
},
"muralpay.country.de": {
"message": "Germany"
},
"muralpay.country.ee": {
"message": "Estonia"
},
"muralpay.country.es": {
"message": "Spain"
},
"muralpay.country.fi": {
"message": "Finland"
},
"muralpay.country.fr": {
"message": "France"
},
"muralpay.country.gr": {
"message": "Greece"
},
"muralpay.country.ie": {
"message": "Ireland"
},
"muralpay.country.it": {
"message": "Italy"
},
"muralpay.country.lt": {
"message": "Lithuania"
},
"muralpay.country.lu": {
"message": "Luxembourg"
},
"muralpay.country.lv": {
"message": "Latvia"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Netherlands"
},
"muralpay.country.pt": {
"message": "Portugal"
},
"muralpay.country.sk": {
"message": "Slovakia"
},
"muralpay.document-type.national-id": {
"message": "National ID"
},
"muralpay.document-type.passport": {
"message": "Passport"
},
"muralpay.document-type.resident-id": {
"message": "Resident ID"
},
"muralpay.document-type.ruc": {
"message": "RUC"
},
"muralpay.document-type.tax-id": {
"message": "Tax ID"
},
"muralpay.field.account-number": {
"message": "Account number"
},
"muralpay.field.account-number-cbu-cvu": {
"message": "Account number (CBU/CVU)"
},
"muralpay.field.account-number-cci": {
"message": "Account number (CCI)"
},
"muralpay.field.account-number-type": {
"message": "Account number type"
},
"muralpay.field.account-type": {
"message": "Account type"
},
"muralpay.field.bank-account-number": {
"message": "Account number"
},
"muralpay.field.branch-code": {
"message": "Branch code"
},
"muralpay.field.clabe": {
"message": "CLABE"
},
"muralpay.field.country": {
"message": "Country"
},
"muralpay.field.cpf-cnpj": {
"message": "CPF/CNPJ"
},
"muralpay.field.cuit-cuil": {
"message": "CUIT/CUIL"
},
"muralpay.field.document-type": {
"message": "Document type"
},
"muralpay.field.iban": {
"message": "IBAN"
},
"muralpay.field.phone-number": {
"message": "Phone number"
},
"muralpay.field.pix-email": {
"message": "PIX email"
},
"muralpay.field.pix-key-type": {
"message": "PIX key type"
},
"muralpay.field.pix-phone": {
"message": "PIX phone"
},
"muralpay.field.routing-number": {
"message": "Routing number"
},
"muralpay.field.swift-bic": {
"message": "SWIFT/BIC"
},
"muralpay.field.wallet-address": {
"message": "Wallet address"
},
"muralpay.help.cbu-cvu": {
"message": "Clave Bancaria Uniforme or Clave Virtual Uniforme"
},
"muralpay.help.cci": {
"message": "Código de Cuenta Interbancaria"
},
"muralpay.help.clabe": {
"message": "Clave Bancaria Estandarizada (Mexican bank account number)"
},
"muralpay.help.cpf-cnpj": {
"message": "Brazilian tax identification number"
},
"muralpay.help.cuit-cuil": {
"message": "Argentine tax ID"
},
"muralpay.help.iban": {
"message": "International Bank Account Number"
},
"muralpay.help.swift-bic": {
"message": "Bank Identifier Code"
},
"muralpay.pix-type.bank-account": {
"message": "Bank account"
},
"muralpay.pix-type.document": {
"message": "CPF/CNPJ"
},
"muralpay.pix-type.email": {
"message": "Email"
},
"muralpay.pix-type.phone": {
"message": "Phone number"
},
"muralpay.placeholder.account-number": {
"message": "Enter account number"
},
"muralpay.placeholder.cbu-cvu": {
"message": "Enter CBU or CVU"
},
"muralpay.placeholder.cbu-cvu-type": {
"message": "CBU or CVU"
},
"muralpay.placeholder.cci": {
"message": "Enter 20-digit CCI"
},
"muralpay.placeholder.cuit-cuil": {
"message": "Enter CUIT or CUIL"
},
"muralpay.placeholder.enter-account-number": {
"message": "Enter account number"
},
"muralpay.placeholder.enter-branch-code": {
"message": "Enter branch code"
},
"muralpay.placeholder.enter-clabe": {
"message": "Enter 18-digit CLABE"
},
"muralpay.placeholder.enter-cpf-cnpj": {
"message": "Enter CPF or CNPJ"
},
"muralpay.placeholder.enter-iban": {
"message": "Enter IBAN"
},
"muralpay.placeholder.enter-pix-email": {
"message": "Enter PIX email"
},
"muralpay.placeholder.enter-routing-number": {
"message": "Enter 9-digit routing number"
},
"muralpay.placeholder.enter-swift-bic": {
"message": "Enter SWIFT/BIC code"
},
"muralpay.placeholder.iban-crc": {
"message": "Enter Costa Rican IBAN"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
"muralpay.placeholder.pix-phone": {
"message": "+55..."
},
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"muralpay.rail.fiat-ars.name": {
"message": "Bank Transfer (ARS)"
},
"muralpay.rail.fiat-brl.name": {
"message": "PIX Transfer (BRL)"
},
"muralpay.rail.fiat-clp.name": {
"message": "Bank Transfer (CLP)"
},
"muralpay.rail.fiat-cop.name": {
"message": "Bank Transfer (COP)"
},
"muralpay.rail.fiat-crc.name": {
"message": "Bank Transfer (CRC)"
},
"muralpay.rail.fiat-eur.name": {
"message": "Bank Transfer (EUR)"
},
"muralpay.rail.fiat-mxn.name": {
"message": "Bank Transfer (MXN)"
},
"muralpay.rail.fiat-pen.name": {
"message": "Bank Transfer (PEN)"
},
"muralpay.rail.fiat-usd-peru.name": {
"message": "Bank Transfer (USD - Peru)"
},
"muralpay.rail.fiat-usd.name": {
"message": "Bank Transfer (USD)"
},
"muralpay.rail.fiat-zar.name": {
"message": "Bank Transfer (ZAR)"
},
"muralpay.rail.usdc-base.name": {
"message": "USDC (Base)"
},
"muralpay.rail.usdc-celo.name": {
"message": "USDC (Celo)"
},
"muralpay.rail.usdc-ethereum.name": {
"message": "USDC (Ethereum)"
},
"muralpay.rail.usdc-polygon.name": {
"message": "Crypto (USDC)"
},
"muralpay.warning.wallet-address": {
"message": "Double-check your wallet address. Funds sent to an incorrect address cannot be recovered."
},
"profile.bio.fallback.creator": {
"message": "A Modrinth creator."
},
@@ -1130,6 +1769,12 @@
"profile.button.manage-projects": {
"message": "Manage projects"
},
"profile.button.remove-affiliate": {
"message": "Remove as affiliate"
},
"profile.button.set-affiliate": {
"message": "Set as affiliate"
},
"profile.details.label.auth-providers": {
"message": "Auth providers"
},
@@ -1154,6 +1799,9 @@
"profile.error.not-found": {
"message": "User not found"
},
"profile.label.affiliate": {
"message": "Affiliate"
},
"profile.label.badges": {
"message": "Badges"
},
@@ -1251,7 +1899,7 @@
"message": "Resubmit for review"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Your project has been {status} by Modrinth's staff. In most cases, you can resubmit for review after addressing the staff's message."
"message": "Your project has been {status, select, rejected {rejected} withheld {withheld} other {{status}}} by Modrinth's staff. In most cases, you can resubmit for review after addressing the staff's message."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "You must complete the required steps in the publishing checklist!"
@@ -1658,18 +2306,6 @@
"report.submit": {
"message": "Submit report"
},
"revenue.transfers.total": {
"message": "You have withdrawn {amount} in total."
},
"revenue.transfers.total.method": {
"message": "You have withdrawn {amount} through {method}."
},
"revenue.transfers.total.year": {
"message": "You have withdrawn {amount} in {year}."
},
"revenue.transfers.total.year_method": {
"message": "You have withdrawn {amount} in {year} through {method}."
},
"scopes.analytics.description": {
"message": "Access your analytics data"
},
@@ -1934,12 +2570,6 @@
"servers.backups.item.creating-backup": {
"message": "Creating backup..."
},
"servers.backups.item.downloading": {
"message": "Downloading"
},
"servers.backups.item.downloading-backup": {
"message": "Downloading backup..."
},
"servers.backups.item.failed-to-create-backup": {
"message": "Failed to create backup"
},

View File

@@ -566,6 +566,27 @@
"create.project.visibility-unlisted": {
"message": "No listado"
},
"dashboard.affiliate-links.create.button": {
"message": "Crear enlace de afiliado"
},
"dashboard.affiliate-links.error.title": {
"message": "Error al cargar los enlaces de afiliado"
},
"dashboard.affiliate-links.header": {
"message": "Tus enlaces de afiliado"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "Esto revocará de forma permanente el código de afiliado `{id}` y cualquier enlace existente con este código que se haya compartido ya no será válido."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Revocar"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "¿Estás seguro de que quieres revocar tu enlace de afiliado ''{title}''?"
},
"dashboard.affiliate-links.search": {
"message": "Buscar enlaces de afiliado..."
},
"dashboard.collections.button.create-new": {
"message": "Crear nuevo"
},
@@ -578,6 +599,18 @@
"dashboard.collections.long-title": {
"message": "Tus colecciones"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Descargar {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "¡Tu {formType} formulario fiscal se ha enviado correctamente!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Ahora puedes retirar libremente. Si tienes preguntas o necesitas actualizar tus datos <support-link>contacta con soporte</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "¡Ya estás listo! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Una entidad extranjera es una entidad comercial constituida fuera de Estados Unidos (como una corporación, sociedad o LLC no estadounidense)."
},
@@ -602,6 +635,336 @@
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "¿Eres ciudadano estadounidense?"
},
"dashboard.creator-withdraw-modal.complete-tax-form": {
"message": "Llena el formulario fiscal"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Continuar con el límite"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Detalles"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Cantidad"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "Tipo de cambio"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Tarifa"
},
"dashboard.creator-withdraw-modal.fee-breakdown-net-amount": {
"message": "Cantidad neta"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Entidad comercial"
},
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Una entidad comercial se refiere a una organización registrada, como una sociedad anónima, una sociedad colectiva o una sociedad de responsabilidad limitada."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "¿Estás retirando como particular o como empresa?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Particular"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Selecciona tu país"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Buscar países..."
},
"dashboard.creator-withdraw-modal.method-selection.error-text": {
"message": "No se pueden obtener los métodos de pago disponibles. Inténtalo de nuevo más tarde."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Error al cargar los métodos de pago"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Región"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Algunos métodos de pago no están disponibles en ciertas regiones."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Selecciona el método para retirar"
},
"dashboard.creator-withdraw-modal.method-selection.tax-limit-warning": {
"message": "Tu límite de retiro es <b>{amount}</b>, <tax-link>llena un formulario fiscal</tax-link> para retirar más."
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Titular de la cuenta"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Moneda"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Confirma tu dirección de cartera"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id": {
"message": "Número de identificación nacional"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder": {
"message": "Escribe el número de identificación nacional"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport": {
"message": "Número de pasaporte"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder": {
"message": "Escribe el número de pasaporte"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder": {
"message": "Escribe el número de identificación de residente"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc": {
"message": "Número de RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder": {
"message": "Escribe el número RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id": {
"message": "Número de identificación fiscal"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder": {
"message": "Escribe el número de identificación fiscal"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Red"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "Estás cerca del límite de retiro. Puedes retirar <b>{amountRemaining}</b> ahora, pero se requiere un formulario de fiscal para poder retirar más."
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Cuenta"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Desconectar cuenta"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Método de pago"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "Cuenta de PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Conecta tu cuenta de PayPal para recibir pagos directamente."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Guardar"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "¡Nombre de usuario de Venmo guardado con éxito!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Guardado"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Iniciar sesión con PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-description": {
"message": "Escribe tu nombre de usuario de Venmo para recibir pagos."
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle": {
"message": "Nombre de usario de Venmo"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@usuario"
},
"dashboard.creator-withdraw-modal.stage.completion": {
"message": "Completado"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Método"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Detalles de la cuenta"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Verificación"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Formulario fiscal"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Detalles"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "Para retirar tu saldo total <b>{available}</b> disponible, llena el siguiente formulario. Es necesario para la declaración de impuestos y solo es necesario hacerlo una vez."
},
"dashboard.creator-withdraw-modal.tax-form-required.body-with-limit": {
"message": "Debes llenar un formulario W-9 o W-8 para los registros fiscales de Modrinth, así nos mantenemos al día con las normativas de impuestos."
},
"dashboard.creator-withdraw-modal.tax-form-required.header": {
"message": "Formulario fiscal requerido"
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Método de pago"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Recompensa"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder": {
"message": "Seleccionar recompensa"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Recompensas"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "Correo electrónico no verificado"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-message": {
"message": "El correo electrónico de entrega que has ingresado no está asociado a tu cuenta de Modrinth. Modrinth no puede recuperar las recompensas enviadas a una dirección de correo electrónico incorrecta."
},
"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. <direct-paypal-link>Cambia a PayPal directo</direct-paypal-link> para obtener mejores tarifas (≈2 % en lugar de ≈6 %)."
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Retirar"
},
"dashboard.creator-withdraw-modal.withdraw-limit": {
"message": "Límite de retiro"
},
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "Has agotado tu límite de retiro <b>{withdrawLimit}</b>. Debes completar un formulario de impuestos para retirar más."
},
"dashboard.revenue.available-now": {
"message": "Disponible ahora"
},
"dashboard.revenue.balance": {
"message": "Saldo"
},
"dashboard.revenue.estimated-tooltip.msg1": {
"message": "Los ingresos estimados pueden estar sujetos a cambios hasta que estén disponibles."
},
"dashboard.revenue.estimated-tooltip.msg2": {
"message": "Haz clic aquí para leer acerca del cómo Modrinth gestiona tus ingresos."
},
"dashboard.revenue.estimated-with-date": {
"message": "Fecha estimada {date}"
},
"dashboard.revenue.processing": {
"message": "Procesando"
},
"dashboard.revenue.processing.tooltip": {
"message": "Los ingresos permanecen en proceso hasta final de mes, luego están disponibles 60 días después."
},
"dashboard.revenue.stats.received": {
"message": "Recibido"
},
"dashboard.revenue.stats.transactions": {
"message": "Transacciones"
},
"dashboard.revenue.stats.withdrawn": {
"message": "Retiros"
},
"dashboard.revenue.tos": {
"message": "Al subir proyectos a Modrinth y retirar dinero de tu cuenta, aceptas nuestros <terms-link>Términos del programa de recompensas</terms-link>. Aprende más acerca del <info-link>Programa de recompensas</info-link>."
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Descargar como CSV"
},
"dashboard.revenue.transactions.header": {
"message": "Transacciones"
},
"dashboard.revenue.transactions.none": {
"message": "Sin transacciones"
},
"dashboard.revenue.transactions.none.desc": {
"message": "Tus pagos y retiros aparecerán aquí."
},
"dashboard.revenue.transactions.see-all": {
"message": "Ver todo"
},
"dashboard.revenue.withdraw.blocked-tin-mismatch": {
"message": "Tus retiros están temporalmente bloqueados por que tu TIN o SSN no coinciden con los registros del IRS. Conte en contacto con el equipo de soporte para restablecerlos y reenviar tu formulario fiscal."
},
"dashboard.revenue.withdraw.card.description": {
"message": "Retira dinero de tu saldo disponible a cualquier método de pago."
},
"dashboard.revenue.withdraw.card.title": {
"message": "Retirar"
},
"dashboard.revenue.withdraw.header": {
"message": "Retirar"
},
"dashboard.withdraw.completion.account": {
"message": "Cuenta"
},
"dashboard.withdraw.completion.amount": {
"message": "Cantidad"
},
"dashboard.withdraw.completion.close-button": {
"message": "Cerrar"
},
"dashboard.withdraw.completion.date": {
"message": "Fecha"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "Recibirás un correo electrónico a <b>{email}</b> con instrucciones para canjear tu retiro."
},
"dashboard.withdraw.completion.exchange-rate": {
"message": "Tipo de cambio"
},
"dashboard.withdraw.completion.fee": {
"message": "Tarifa"
},
"dashboard.withdraw.completion.method": {
"message": "Método"
},
"dashboard.withdraw.completion.net-amount": {
"message": "Cantidad neta"
},
"dashboard.withdraw.completion.recipient": {
"message": "Destinatario"
},
"dashboard.withdraw.completion.title": {
"message": "Retiro completado"
},
"dashboard.withdraw.completion.transactions-button": {
"message": "Transacciones"
},
"dashboard.withdraw.completion.wallet": {
"message": "Cartera"
},
"dashboard.withdraw.error.generic.text": {
"message": "No hemos podido enviar tu solicitud de retiro. Por favor, revisa tus datos o ponte en contacto con el servicio de asistencia."
},
"dashboard.withdraw.error.generic.title": {
"message": "No se puede retirar"
},
"dashboard.withdraw.error.invalid-address.text": {
"message": "No se ha podido verificar la dirección que has introducido. Por favor, revisa tus datos de dirección."
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Error al verificar la dirección"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": "Los datos de la cuenta bancaria que proporcionaste no son válidos. Por favor, verifica la información."
},
"dashboard.withdraw.error.invalid-bank.title": {
"message": "Datos bancarios no válidos"
},
"dashboard.withdraw.error.invalid-wallet.text": {
"message": "La dirección de la cartera de criptomonedas que proporcionaste no es válida. Por favor, revísala y vuelve a intentarlo."
},
"dashboard.withdraw.error.invalid-wallet.title": {
"message": "Dirección de cartera no válida"
},
"dashboard.withdraw.error.minimum-not-met.text": {
"message": "El monto a retirar (después de las tarifas) no cumple con el requisito mínimo. Por favor, aumenta la cantidad a retirar."
},
"dashboard.withdraw.error.minimum-not-met.title": {
"message": "Cantidad demasiado baja"
},
"dashboard.withdraw.error.tax-form.text": {
"message": "Debes completar un formulario fiscal para poder enviar tu solicitud de retiro."
},
"dashboard.withdraw.error.tax-form.title": {
"message": "Por favor, llena el formulario fiscal"
},
"error.collection.404.list_item.1": {
"message": "Puede que hayas escrito mal la URL de la colección."
},
@@ -857,6 +1220,9 @@
"layout.action.lookup-by-email": {
"message": "Buscar por correo electrónico"
},
"layout.action.manage-affiliates": {
"message": "Administrar enlaces de afiliado"
},
"layout.action.manage-server-notices": {
"message": "Administrar notificaciones del servidor"
},
@@ -912,11 +1278,20 @@
"message": "Completar formulario fiscal"
},
"layout.banner.tax.description": {
"message": "Ya retiraste más de \\$600 de Modrinth este año. Para cumplir con las regulaciones fiscales, necesitas completar un formulario fiscal. Tus retiros estarán en pausa hasta que envíes este formulario."
"message": "Ya has retirado más de 600 dólares de Modrinth este año. Para cumplir con las regulaciones fiscales, necesitas llenar un formulario fiscal. Tus retiros estarán en pausa hasta que envíes el formulario."
},
"layout.banner.tax.title": {
"message": "Formulario fiscal requerido"
},
"layout.banner.tin-mismatch.action": {
"message": "Contactar con soporte"
},
"layout.banner.tin-mismatch.description": {
"message": "Tus retiros están temporalmente bloqueados por que tu TIN o SSN no coinciden con los registros del IRS. Conte en contacto con el equipo de soporte para restablecerlos y reenviar tu formulario fiscal."
},
"layout.banner.tin-mismatch.title": {
"message": "Formulario fiscal erróneo"
},
"layout.banner.verify-email.action": {
"message": "Reenviar correo de verificación"
},
@@ -941,6 +1316,9 @@
"layout.footer.about.status": {
"message": "Estado"
},
"layout.footer.copyright": {
"message": "© {year} Rinth, Inc."
},
"layout.footer.legal": {
"message": "Legal"
},
@@ -1019,6 +1397,15 @@
"layout.meta.og-description": {
"message": "¡Descubre y publica contenido de Minecraft!"
},
"layout.mobile.close-menu": {
"message": "Cerrar menú"
},
"layout.mobile.open-menu": {
"message": "Abrir menú"
},
"layout.nav.active-reports": {
"message": "Reportes activos"
},
"layout.nav.analytics": {
"message": "Estadísticas"
},
@@ -1046,6 +1433,9 @@
"layout.nav.modrinth-home-page": {
"message": "Página de inicio de Modrinth"
},
"layout.nav.my-servers": {
"message": "Mis servidores"
},
"layout.nav.organizations": {
"message": "Organizaciones"
},
@@ -1091,27 +1481,336 @@
"moderation.technical.search.placeholder": {
"message": "Buscar revisiones técnicas..."
},
"muralpay.account-type.checking": {
"message": "Cuenta de cheques"
},
"muralpay.account-type.savings": {
"message": "Ahorros"
},
"muralpay.country.at": {
"message": "Austria"
},
"muralpay.country.be": {
"message": "Bélgica"
},
"muralpay.country.cy": {
"message": "Chipre"
},
"muralpay.country.de": {
"message": "Alemania"
},
"muralpay.country.ee": {
"message": "Estonia"
},
"muralpay.country.es": {
"message": "España"
},
"muralpay.country.fi": {
"message": "Finlandia"
},
"muralpay.country.fr": {
"message": "Francia"
},
"muralpay.country.gr": {
"message": "Grecia"
},
"muralpay.country.ie": {
"message": "Irlanda"
},
"muralpay.country.it": {
"message": "Italia"
},
"muralpay.country.lt": {
"message": "Lituania"
},
"muralpay.country.lu": {
"message": "Luxemburgo"
},
"muralpay.country.lv": {
"message": "Letonia"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Países Bajos"
},
"muralpay.country.pt": {
"message": "Portugal"
},
"muralpay.country.sk": {
"message": "Eslovaquia"
},
"muralpay.document-type.passport": {
"message": "Pasaporte"
},
"muralpay.document-type.ruc": {
"message": "RUC"
},
"muralpay.document-type.tax-id": {
"message": "Identificación fiscal"
},
"muralpay.field.account-number": {
"message": "Número de cuenta"
},
"muralpay.field.account-number-cbu-cvu": {
"message": "Número de cuenta (CBU/CVU)"
},
"muralpay.field.account-number-cci": {
"message": "Número de cuenta (CCI)"
},
"muralpay.field.account-number-type": {
"message": "Tipo de número de cuenta"
},
"muralpay.field.account-type": {
"message": "Tipo de cuenta"
},
"muralpay.field.bank-account-number": {
"message": "Número de cuenta"
},
"muralpay.field.branch-code": {
"message": "Código de sucursal"
},
"muralpay.field.clabe": {
"message": "CLABE"
},
"muralpay.field.country": {
"message": "País"
},
"muralpay.field.cpf-cnpj": {
"message": "CPF/CNPJ"
},
"muralpay.field.cuit-cuil": {
"message": "CUIT/CUIL"
},
"muralpay.field.document-type": {
"message": "Tipo de documento"
},
"muralpay.field.iban": {
"message": "IBAN"
},
"muralpay.field.phone-number": {
"message": "Número telefónico"
},
"muralpay.field.pix-email": {
"message": "Correo electrónico PIX"
},
"muralpay.field.pix-key-type": {
"message": "Tipo de clave PIX"
},
"muralpay.field.pix-phone": {
"message": "Teléfono PIX"
},
"muralpay.field.routing-number": {
"message": "Número de ruta"
},
"muralpay.field.swift-bic": {
"message": "SWIFT/BIC"
},
"muralpay.field.wallet-address": {
"message": "Dirección de cartera"
},
"muralpay.help.cbu-cvu": {
"message": "Clave Bancaria Uniforme o Clave Virtual Uniforme"
},
"muralpay.help.cci": {
"message": "Código de cuenta interbancaria"
},
"muralpay.help.clabe": {
"message": "Clave bancaria estandarizada (Número de cuenta bancaria mexicana)"
},
"muralpay.help.cpf-cnpj": {
"message": "Número de identificación fiscal brasileño"
},
"muralpay.help.cuit-cuil": {
"message": "Identificación fiscal argentina"
},
"muralpay.help.iban": {
"message": "Número de cuenta bancaria internacional"
},
"muralpay.help.swift-bic": {
"message": "Código de identificación bancaria"
},
"muralpay.pix-type.bank-account": {
"message": "Cuenta bancaria"
},
"muralpay.pix-type.document": {
"message": "CPF/CNPJ"
},
"muralpay.pix-type.email": {
"message": "Correo electrónico"
},
"muralpay.pix-type.phone": {
"message": "Número telefónico"
},
"muralpay.placeholder.account-number": {
"message": "Escribe el número de cuenta"
},
"muralpay.placeholder.cbu-cvu": {
"message": "Ingresa el CBU o el CVU"
},
"muralpay.placeholder.cbu-cvu-type": {
"message": "CBU o CVU"
},
"muralpay.placeholder.cci": {
"message": "Ingresa el CCI de 20 dígitos"
},
"muralpay.placeholder.cuit-cuil": {
"message": "Ingresa el CUIT o el CUIL"
},
"muralpay.placeholder.enter-account-number": {
"message": "Escribe el número de cuenta"
},
"muralpay.placeholder.enter-branch-code": {
"message": "Escribe el código de sucursal"
},
"muralpay.placeholder.enter-clabe": {
"message": "Ingresa la CLABE de 18 dígitos"
},
"muralpay.placeholder.enter-cpf-cnpj": {
"message": "Ingresa el CPF o CNPJ"
},
"muralpay.placeholder.enter-iban": {
"message": "Escribe el IBAN"
},
"muralpay.placeholder.enter-pix-email": {
"message": "Escribe tu correo electrónico de PIX"
},
"muralpay.placeholder.enter-routing-number": {
"message": "Escribe el número de ruta de 9 dígitos"
},
"muralpay.placeholder.enter-swift-bic": {
"message": "Escribe el código SWIFT/BIC"
},
"muralpay.placeholder.iban-crc": {
"message": "Ingresa el IBAN de Costa Rica"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
"muralpay.placeholder.pix-phone": {
"message": "+55..."
},
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"muralpay.rail.fiat-ars.name": {
"message": "Transferencia bancaria (ARS)"
},
"muralpay.rail.fiat-brl.name": {
"message": "Transferencia PIX (BRL)"
},
"muralpay.rail.fiat-clp.name": {
"message": "Transferencia bancaria (CLP)"
},
"muralpay.rail.fiat-cop.name": {
"message": "Transferencia bancaria (COP)"
},
"muralpay.rail.fiat-crc.name": {
"message": "Transferencia bancaria (CRC)"
},
"muralpay.rail.fiat-eur.name": {
"message": "Transferencia bancaria (EUR)"
},
"muralpay.rail.fiat-mxn.name": {
"message": "Transferencia bancaria (MXN)"
},
"muralpay.rail.fiat-pen.name": {
"message": "Transferencia bancaria (PEN)"
},
"muralpay.rail.fiat-usd-peru.name": {
"message": "Transferencia bancaria (USD - Perú)"
},
"muralpay.rail.fiat-usd.name": {
"message": "Transferencia bancaria (USD)"
},
"muralpay.rail.fiat-zar.name": {
"message": "Transferencia bancaria (ZAR)"
},
"muralpay.rail.usdc-base.name": {
"message": "USDC (Base)"
},
"muralpay.rail.usdc-celo.name": {
"message": "USDC (Celo)"
},
"muralpay.rail.usdc-ethereum.name": {
"message": "USDC (Ethereum)"
},
"muralpay.rail.usdc-polygon.name": {
"message": "Cripto (USDC)"
},
"muralpay.warning.wallet-address": {
"message": "Verifica dos veces la dirección de tu billetera. Los fondos enviados a una dirección incorrecta no se pueden recuperar."
},
"profile.bio.fallback.creator": {
"message": "Un creador de Modrinth."
},
"profile.bio.fallback.user": {
"message": "Un usuario de Modrinth."
},
"profile.button.billing": {
"message": "Gestionar la facturación de usuario"
},
"profile.button.edit-role": {
"message": "Editar rol"
},
"profile.button.info": {
"message": "Ver detalles de usuario"
},
"profile.button.manage-projects": {
"message": "Gestionar proyectos"
},
"profile.button.remove-affiliate": {
"message": "Remover como afiliado"
},
"profile.button.set-affiliate": {
"message": "Configurar como afiliado"
},
"profile.details.label.auth-providers": {
"message": "Proveedores de autenticación"
},
"profile.details.label.email": {
"message": "Correo electrónico"
},
"profile.details.label.has-password": {
"message": "Tiene contraseña"
},
"profile.details.label.has-totp": {
"message": "Tiene TOTP"
},
"profile.details.label.payment-methods": {
"message": "Métodos de pago"
},
"profile.details.tooltip.email-not-verified": {
"message": "Correo electrónico no verificado"
},
"profile.details.tooltip.email-verified": {
"message": "Correo electrónico verificado"
},
"profile.error.not-found": {
"message": "Usuario no encontrado"
},
"profile.joined-at": {
"message": "Se unió el <date>{ago}</date>"
"profile.label.affiliate": {
"message": "Afiliado"
},
"profile.label.badges": {
"message": "Insignias"
},
"profile.label.collection": {
"message": "Colección"
},
"profile.label.details": {
"message": "Detalles"
},
"profile.label.downloads": {
"message": "{count} {count, plural, one {descarga} other {descargas}}"
},
"profile.label.joined": {
"message": "Se unió"
},
"profile.label.no": {
"message": "No"
},
"profile.label.no-collections": {
"message": "¡Este usuario no tiene colecciones!"
},
@@ -1127,18 +1826,21 @@
"profile.label.organizations": {
"message": "Organizaciones"
},
"profile.label.projects": {
"message": "{count} {count, plural, one {proyecto} other {proyectos}}"
},
"profile.label.saving": {
"message": "Guardando..."
},
"profile.label.yes": {
"message": "Sí"
},
"profile.meta.description": {
"message": "Descarga proyectos de {username} en Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Descarga proyectos de {username} en Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> descarga del proyecto} other {<stat>{count}</stat> descargas del proyecto}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> proyecto} other {<stat>{count}</stat> proyectos}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> seguidor del proyecto} other {<stat>{count}</stat> seguidores del proyecto}}"
},
@@ -1188,7 +1890,7 @@
"message": "Reenviar para revisión"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Tu proyecto ha sido {status} por el staff de Modrinth. En la mayoría de los casos, puedes volver a enviarlo para su revisión después de responder al mensaje del staff."
"message": "Tu proyecto ha sido {status, select, rejected {rechazado} withheld {retenido} other {{status}}} por el equipo de Modrinth. En la mayoría de los casos, puedes volver a enviarlo para su revisión después de responder a las observaciones que el equipo te haya dado."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "¡Debes completar los pasos requeridos en la lista de verificación de publicación!"
@@ -1595,18 +2297,6 @@
"report.submit": {
"message": "Enviar reporte"
},
"revenue.transfers.total": {
"message": "Has retirado {amount} en total."
},
"revenue.transfers.total.method": {
"message": "Has retirado {amount} mediante {method}."
},
"revenue.transfers.total.year": {
"message": "Has retirado {amount} en {year}."
},
"revenue.transfers.total.year_method": {
"message": "Has retirado {amount} en {year} mediante {method}."
},
"scopes.analytics.description": {
"message": "Accede a tus datos analíticos"
},
@@ -1865,9 +2555,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Restauración del respaldo en curso"
},
"servers.backups.item.already-preparing": {
"message": "Ya se está preparando el respaldo para su descarga"
},
"servers.backups.item.automated": {
"message": "Automatizado"
},
@@ -1877,9 +2564,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "No se pudo crear el respaldo"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Error al preparar la descarga"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Error al restaurar desde el respaldo"
},
@@ -1889,15 +2573,6 @@
"servers.backups.item.locked": {
"message": "Bloqueado"
},
"servers.backups.item.prepare-download": {
"message": "Preparar descarga"
},
"servers.backups.item.prepare-download-again": {
"message": "Intenta prepararlo de nuevo"
},
"servers.backups.item.preparing-download": {
"message": "Preparando descarga..."
},
"servers.backups.item.queued-for-backup": {
"message": "En cola para respaldo"
},

View File

@@ -428,6 +428,9 @@
"create.collection.cancel": {
"message": "Cancelar"
},
"create.collection.collection-info": {
"message": "Tu nueva colección se creará como colección pública {count, plural, =0 {sin ningún proyecto} one {# proyecto} other {# proyectos}}."
},
"create.collection.create-collection": {
"message": "Crear colección"
},
@@ -464,6 +467,9 @@
"create.limit-alert.limit-reached": {
"message": "{type} límite alcanzado"
},
"create.limit-alert.limit-reached-description": {
"message": "Has alcanzado tu {type} límite de {max}. Contacta con soporte para incrementar tu límite."
},
"create.limit-alert.type-collection": {
"message": "colección"
},
@@ -560,6 +566,24 @@
"create.project.visibility-unlisted": {
"message": "No listado"
},
"dashboard.affiliate-links.create.button": {
"message": "Crear enlace de afiliado"
},
"dashboard.affiliate-links.error.title": {
"message": "Error al cargar los enlaces de afiliado"
},
"dashboard.affiliate-links.header": {
"message": "Tus enlaces de afiliado"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "Esto revocará permanentemente el código de afiliado `{id}` y cualquier enlace existente con este código que se haya compartido dejará de ser válido."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Revocar"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "¿Estás seguro de que deseas revocar tu enlace de afiliado «{title}»?"
},
"dashboard.collections.button.create-new": {
"message": "Crear nuevo"
},
@@ -572,6 +596,18 @@
"dashboard.collections.long-title": {
"message": "Tus colecciones"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Descarga {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "¡Tu {formType} formulario de impuestos se ha subido exitosamente!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Puedes retirarte por ahora. Si tiene preguntas o necesita actualizar tus datos <support-link>contacte con soporte</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "¡Está todo listo! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Una entidad extranjera es una entidad comercial constituida fuera de los Estados Unidos (como una sociedad anónima, una sociedad colectiva o una sociedad de responsabilidad limitada no estadounidense)."
},
@@ -587,12 +623,90 @@
"dashboard.creator-tax-form-modal.header": {
"message": "Formulario fiscal"
},
"dashboard.creator-tax-form-modal.security.description": {
"message": "Modrinth utiliza el proveedor externo Track1099 para recopilar y almacenar de forma segura tus formularios de impuestos. <security-link>Aprende más aquí.</security-link>"
},
"dashboard.creator-tax-form-modal.security.header": {
"message": "Prácticas de seguridad"
},
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "¿Es usted ciudadano estadounidense?"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Detalles"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Cantidad"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Seleccione el país"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Buscar país..."
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Región"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Algunos métodos de pago no están disponibles en determinadas regiones."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Seleccionar método de retirada"
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Dueño de la cuenta"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Moneda"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "Estás cerca del límite de retirada. Puedes retirar <b>{amountRemaining}</b> ahora, pero se requiere un formulario de impuestos para retirar más."
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "Cuenta de Paypal"
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Guardar"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Guardado"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Entrar con PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@username"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Método"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "Para retirar el saldo total <b>{available}</b> disponible, rellene el siguiente formulario. Es necesario para la declaración de impuestos y solo hay que hacerlo una vez."
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Método de pago"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "Email no verificado"
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Retirada"
},
"dashboard.revenue.tos": {
"message": "Al subir proyectos a Modrinth y retirar dinero de tu cuenta, aceptas nuestros <terms-link>Términos del programa de recompensas</terms-link>. Más información sobre el <info-link>Programa de recompensas</info-link>."
},
"dashboard.withdraw.completion.close-button": {
"message": "Cerrar"
},
"dashboard.withdraw.completion.date": {
"message": "Fecha"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "Recibirás un correo electrónico en <b>{email}</b> con instrucciones para canjear tu retirada."
},
"dashboard.withdraw.completion.method": {
"message": "Método"
},
"error.collection.404.list_item.1": {
"message": "Has escrito mal en enlace de esta colección."
},
@@ -875,6 +989,9 @@
"layout.banner.add-email.description": {
"message": "Por motivos de seguridad, Modrinth necesita que registres una dirección de correo electrónico en tu cuenta."
},
"layout.banner.build-fail.description": {
"message": "Esta implementación del frontend de Modrinth no ha podido generar el estado desde la API. Esto puede deberse a una interrupción del servicio o a un error en la configuración. Vuelve a compilar cuando la API esté disponible. Códigos de error: {errors}; La URL actual de la API es: {url}"
},
"layout.banner.build-fail.title": {
"message": "Error al generar el estado desde la API durante la compilación."
},
@@ -897,11 +1014,20 @@
"message": "Rellene el formulario fiscal"
},
"layout.banner.tax.description": {
"message": "Ya ha retirado más de 600 dólares de Modrinth este año. Para cumplir con la normativa fiscal, debe rellenar un formulario de impuestos. Sus retiradas quedarán en suspenso hasta que envíe este formulario."
"message": "Ya ha retirado más de 600 dólares de Modrinth este año. Para cumplir con la normativa fiscal, debes rellenar un formulario de impuestos. Tus retiradas quedarán en suspenso hasta que envíes el formulario."
},
"layout.banner.tax.title": {
"message": "Se requiere formulario fiscal"
},
"layout.banner.tin-mismatch.action": {
"message": "Contacta con soporte"
},
"layout.banner.tin-mismatch.description": {
"message": "Tus retiradas están bloqueadas temporalmente porque tu TIN o SSN no coinciden con los registros del IRS. Ponte en contacto con el servicio de asistencia para restablecer y volver a enviar tu formulario fiscal."
},
"layout.banner.tin-mismatch.title": {
"message": "Error en el formulario fiscal"
},
"layout.banner.verify-email.action": {
"message": "Reenviar verificación de correo electrónico"
},
@@ -926,6 +1052,9 @@
"layout.footer.about.status": {
"message": "Estado"
},
"layout.footer.copyright": {
"message": "© {year} Rinth, Inc."
},
"layout.footer.legal": {
"message": "Legal"
},
@@ -1004,6 +1133,12 @@
"layout.meta.og-description": {
"message": "¡Descubre y publica contenido de Minecraft!"
},
"layout.mobile.close-menu": {
"message": "Cerrar menú"
},
"layout.mobile.open-menu": {
"message": "Abrir menú"
},
"layout.nav.analytics": {
"message": "Análisis"
},
@@ -1031,6 +1166,9 @@
"layout.nav.modrinth-home-page": {
"message": "Página de inicio de Modrinth"
},
"layout.nav.my-servers": {
"message": "Mis servidores"
},
"layout.nav.organizations": {
"message": "Organizaciones"
},
@@ -1076,27 +1214,147 @@
"moderation.technical.search.placeholder": {
"message": "Buscar reseñas tecnológicas..."
},
"muralpay.account-type.savings": {
"message": "Guardando"
},
"muralpay.country.at": {
"message": "Austria"
},
"muralpay.country.be": {
"message": "Bélgica"
},
"muralpay.country.cy": {
"message": "Chipre"
},
"muralpay.country.de": {
"message": "Alemania"
},
"muralpay.country.ee": {
"message": "Estonia"
},
"muralpay.country.es": {
"message": "España"
},
"muralpay.country.fi": {
"message": "Finlandia"
},
"muralpay.country.fr": {
"message": "Francia"
},
"muralpay.country.gr": {
"message": "Grecia"
},
"muralpay.country.ie": {
"message": "Irlanda"
},
"muralpay.country.it": {
"message": "Italia"
},
"muralpay.country.lt": {
"message": "Lituania"
},
"muralpay.country.lu": {
"message": "Luxemburgo"
},
"muralpay.country.lv": {
"message": "Letonia"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Países Bajos"
},
"muralpay.country.pt": {
"message": "Portugal"
},
"muralpay.country.sk": {
"message": "Eslovaquia"
},
"muralpay.document-type.passport": {
"message": "Pasaporte"
},
"muralpay.field.country": {
"message": "País"
},
"muralpay.field.iban": {
"message": "IBAN"
},
"muralpay.help.cci": {
"message": "Código de Cuenta Interbancaria"
},
"muralpay.pix-type.email": {
"message": "Correo electrónico"
},
"profile.bio.fallback.creator": {
"message": "Creador en Modrinth."
},
"profile.bio.fallback.user": {
"message": "Usuario de Modrinth."
},
"profile.button.billing": {
"message": "Gestionar la facturación de los usuarios"
},
"profile.button.edit-role": {
"message": "Editar rol"
},
"profile.button.info": {
"message": "Ver detalles del usuario"
},
"profile.button.manage-projects": {
"message": "Gestionar proyectos"
},
"profile.button.remove-affiliate": {
"message": "Borrar como afiliado"
},
"profile.button.set-affiliate": {
"message": "Establecer como afiliado"
},
"profile.details.label.auth-providers": {
"message": "Autentificar proveedores"
},
"profile.details.label.email": {
"message": "Correo electrónico"
},
"profile.details.label.has-password": {
"message": "Tiene contraseña"
},
"profile.details.label.has-totp": {
"message": "Tiene autentificación de doble factor"
},
"profile.details.label.payment-methods": {
"message": "Métodos de pago"
},
"profile.details.tooltip.email-not-verified": {
"message": "Correo electrónico no verificado"
},
"profile.details.tooltip.email-verified": {
"message": "Correo electrónico verificado"
},
"profile.error.not-found": {
"message": "Usuario no encontrado"
},
"profile.joined-at": {
"message": "Se unió <date>{ago}</date>"
"profile.label.affiliate": {
"message": "Afiliado"
},
"profile.label.badges": {
"message": "Medallas"
},
"profile.label.collection": {
"message": "Colección"
},
"profile.label.details": {
"message": "Detalles"
},
"profile.label.downloads": {
"message": "{count} {count, plural, one {descarga} other {descargas}}"
},
"profile.label.joined": {
"message": "Se unió hace"
},
"profile.label.no": {
"message": "No"
},
"profile.label.no-collections": {
"message": "¡Este usuario no tiene colecciones!"
},
@@ -1112,9 +1370,24 @@
"profile.label.organizations": {
"message": "Organizaciones"
},
"profile.label.projects": {
"message": "{count} {count, plural, one {proyecto} other {proyectos}}"
},
"profile.label.saving": {
"message": "Guardando..."
},
"profile.label.yes": {
"message": "Sí"
},
"profile.meta.description": {
"message": "Descargar los proyectos de {username} en Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Descarga los proyectos en Modrinth de {username}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> seguidor} other {<stat>{count}</stat> seguidores}}"
},
"profile.user-id": {
"message": "ID de usuario: {id}"
},
@@ -1160,9 +1433,6 @@
"project-moderation-nags.resubmit-for-review": {
"message": "Reenviar para revisión"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Tu proyecto ha sido {status} por el personal de Modrinth. En la mayoría de los casos, puedes volver a enviarlo para su revisión después de responder al mensaje del personal."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "¡Debes completar los pasos requeridos en la lista de verificación de publicación!"
},
@@ -1292,6 +1562,9 @@
"project.download.game-version-tooltip": {
"message": "{title} solo está disponible para {version}"
},
"project.download.game-version-unsupported-tooltip": {
"message": "{title} no está soportado para la versión {gameVersion} de {platform}"
},
"project.download.install-with-app": {
"message": "Instalar con la aplicación Modrinth"
},
@@ -1310,6 +1583,9 @@
"project.download.platform-tooltip": {
"message": "{title} olo está disponible para {platform}"
},
"project.download.platform-unsupported-tooltip": {
"message": "{title} no está soportado para {platform} en la {gameVersion}"
},
"project.download.search-game-versions": {
"message": "Buscar versiones del juego..."
},
@@ -1331,9 +1607,15 @@
"project.environment.migration-no-permission.message": {
"message": "Acabamos de renovar el sistema de entornos en Modrinth y ahora hay nuevas opciones disponibles. No tienes permiso para modificar estos ajustes, pero avisa a otro miembro del proyecto de que hay que verificar los metadatos del entorno."
},
"project.environment.migration-no-permission.title": {
"message": "Los metadatos del entorno necesitan ser revisados"
},
"project.environment.migration.learn-more": {
"message": "Más información sobre este cambio"
},
"project.environment.migration.message": {
"message": "Acabamos de renovar el sistema de entornos en Modrinth y ahora hay nuevas opciones disponibles. Visita la configuración de tu proyecto y comprueba que los metadatos sean correctos."
},
"project.environment.migration.review-button": {
"message": "Revisar la configuración del entorno"
},
@@ -1475,6 +1757,12 @@
"report.not-for.bug-reports.description": {
"message": "Puedes informar de los errores en su <issues-link>sistema de seguimiento de incidencias</issues-link>."
},
"report.not-for.dmca.description": {
"message": "Consulte nuestra <policy-link>Política de derechos de autor</policy-link>."
},
"report.note.copyright.1": {
"message": "Tenga en cuenta que *no* está enviando una solicitud de retirada en virtud de la DMCA, sino un informe sobre contenido vuelto a subir."
},
"report.note.malicious.1": {
"message": "Los informes de contenido malicioso o engañoso deben incluir pruebas sustanciales del comportamiento, como muestras de código."
},
@@ -1502,18 +1790,6 @@
"report.submit": {
"message": "Enviar reporte"
},
"revenue.transfers.total": {
"message": "Has retirado un total de {amount}."
},
"revenue.transfers.total.method": {
"message": "Has retirado {amount} a través de {method}."
},
"revenue.transfers.total.year": {
"message": "Has retirado {amount} en {year}."
},
"revenue.transfers.total.year_method": {
"message": "Has retirado {amount} en {year} mediante {method}."
},
"scopes.analytics.description": {
"message": "Accede a tus datos de analítica"
},
@@ -1580,6 +1856,9 @@
"scopes.organizationWrite.label": {
"message": "Escribir organizaciones"
},
"scopes.patCreate.description": {
"message": "Crear tokens de API personales"
},
"scopes.patCreate.label": {
"message": "Crear PATs"
},
@@ -1589,12 +1868,18 @@
"scopes.patDelete.label": {
"message": "Eliminar PATs"
},
"scopes.patRead.description": {
"message": "Ver tokens de API creados"
},
"scopes.patRead.label": {
"message": "Leer PATs"
},
"scopes.patWrite.description": {
"message": "Editar tokens de API personales"
},
"scopes.patWrite.label": {
"message": "Escribir PATs"
},
"scopes.payoutsRead.description": {
"message": "Lea sus datos de pagos"
},
@@ -1763,9 +2048,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Restauración de copia de seguridad en curso"
},
"servers.backups.item.already-preparing": {
"message": "Ya se está preparando la copia de seguridad para su descarga"
},
"servers.backups.item.automated": {
"message": "Automatizado"
},
@@ -1775,9 +2057,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Error al crear la copia de seguridad"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Error al preparar la descarga"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Error al restaurar desde la copia de seguridad"
},
@@ -1787,15 +2066,6 @@
"servers.backups.item.locked": {
"message": "Bloqueado"
},
"servers.backups.item.prepare-download": {
"message": "Preparando descarga"
},
"servers.backups.item.prepare-download-again": {
"message": "Intenta prepararlo de nuevo"
},
"servers.backups.item.preparing-download": {
"message": "Preparando descarga..."
},
"servers.backups.item.queued-for-backup": {
"message": "En cola para la copia de seguridad"
},
@@ -1904,12 +2174,57 @@
"settings.billing.payment_method_type.amazon_pay": {
"message": "Amazon Pay"
},
"settings.billing.payment_method_type.amex": {
"message": "American Express"
},
"settings.billing.payment_method_type.cashapp": {
"message": "Cash App"
},
"settings.billing.payment_method_type.diners": {
"message": "Diners Club"
},
"settings.billing.payment_method_type.discover": {
"message": "Descubrir"
},
"settings.billing.payment_method_type.eftpos": {
"message": "EFTPOS"
},
"settings.billing.payment_method_type.jcb": {
"message": "JCB"
},
"settings.billing.payment_method_type.mastercard": {
"message": "MasterCard"
},
"settings.billing.payment_method_type.paypal": {
"message": "PayPal"
},
"settings.billing.payment_method_type.unionpay": {
"message": "UnionPay"
},
"settings.billing.payment_method_type.unknown": {
"message": "Método de pago desconocido"
},
"settings.billing.payment_method_type.visa": {
"message": "Visa"
},
"settings.billing.pyro_subscription.description": {
"message": "Gestiona tus suscripciones a servidores de Modrinth."
},
"settings.billing.pyro_subscription.title": {
"message": "Suscripciones a servidores de Modrinth"
},
"settings.billing.subscription.description": {
"message": "Gestiona tus suscripciones de Modrinth."
},
"settings.billing.subscription.title": {
"message": "Suscripciones"
},
"settings.display.banner.developer-mode.button": {
"message": "Desactivar modo desarrollador"
},
"settings.display.banner.developer-mode.description": {
"message": "El <strong>modo desarrollador</strong> está activo. Esto te permitirá ver los ID internos de varios elementos de Modrinth, lo que puede resultarte útil si eres desarrollador y utilizas la API de Modrinth. Haz clic 5 veces en el logotipo de Modrinth situado en la parte inferior de la página para activar o desactivar el modo desarrollador."
},
"settings.display.flags.description": {
"message": "Activar o desactivar determinadas funciones de este dispositivo."
},
@@ -1952,9 +2267,15 @@
"settings.display.sidebar.advanced-rendering.title": {
"message": "Renderizado avanzado"
},
"settings.display.sidebar.external-links-new-tab.description": {
"message": "Haz que los enlaces que salen de Modrinth se abran en una nueva pestaña. Independientemente de esta configuración, los enlaces del mismo dominio y de las descripciones Markdown se abrirán en la misma pestaña, y los enlaces de los anuncios y las páginas de edición se abrirán en una nueva pestaña."
},
"settings.display.sidebar.external-links-new-tab.title": {
"message": "Abrir enlaces externos en una nueva pestaña"
},
"settings.display.sidebar.hide-app-promos.description": {
"message": "Oculta los botones «Obtener la aplicación Modrinth» de la navegación principal. La página de la aplicación Modrinth sigue estando disponible en la página de inicio o en el pie de página."
},
"settings.display.sidebar.hide-app-promos.title": {
"message": "Ocultar promociones de la aplicación de Modrinth"
},
@@ -2012,6 +2333,9 @@
"settings.language.languages.search-field.placeholder": {
"message": "Buscar un idioma..."
},
"settings.language.languages.search-results-announcement": {
"message": "{matches, plural, =0 {Sin coincidencias} one {# coincidencias} other {# coincidencias}} en tu búsqueda."
},
"settings.language.languages.search.no-results": {
"message": "No hay idiomas que coincidan con tu búsqueda."
},

View File

@@ -1,4 +1,7 @@
{
"action.cancel": {
"message": "Kanselahin"
},
"app-marketing.download.description": {
"message": "Magagamit ang aming desktop app sa ibat-ibang plataporma, piliin ang iyong gugustohing bersiyon."
},
@@ -35,15 +38,54 @@
"app-marketing.download.windows": {
"message": "Windows"
},
"app-marketing.features.importing.multimc-alt": {
"message": "MultiMC"
},
"app-marketing.features.mod-management.actions": {
"message": "Mga Aksiyon"
},
"app-marketing.features.mod-management.description": {
"message": "Pinapadali ng Modrinth na ma-manage ang lahat ng iyong mod sa iisang lugar. Makaka-install, uninstall, at update ng mga mod sa iisang pindot lang."
},
"app-marketing.features.mod-management.installed-mods": {
"message": "Mga na-install na mod"
},
"app-marketing.features.mod-management.name": {
"message": "Pangalan"
},
"app-marketing.features.mod-management.search-mods": {
"message": "Maghanap ng mga mod"
},
"app-marketing.features.open-source.title": {
"message": "Open source"
},
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.infinite-mb": {
"message": "∞ MB"
},
"app-marketing.features.performance.less-than-150mb": {
"message": "< 150 MB"
},
"app-marketing.features.performance.modrinth-app": {
"message": "Modrinth App"
},
"app-marketing.features.performance.one-billion-percent": {
"message": "1 bilyong %"
},
"app-marketing.features.performance.ram": {
"message": "RAM"
},
"app-marketing.features.performance.small": {
"message": "Maliit"
},
"app-marketing.features.play.description": {
"message": "Gamitin ang Modrinth App sa pagdownload at paglaro ng iyong mga paboritong mods at modpacks."
},
"app-marketing.features.sharing.share-button": {
"message": "Ibahagi"
},
"app-marketing.hero.download-button": {
"message": "I-download ang Modrinth App"
},
@@ -56,9 +98,21 @@
"app-marketing.hero.more-download-options": {
"message": "Higit na Pagpipilian sa Pagdownload"
},
"auth.reset-password.method-choice.email-username.placeholder": {
"message": "Email"
},
"auth.sign-in.additional-options": {
"message": "<forgot-password-link>Nalimutan ang password?</forgot-password-link> • <create-account-link>Gumawa ng akawnt</create-account-link>"
},
"auth.sign-up.email.label": {
"message": "Email"
},
"auth.verify-email.action.account-settings": {
"message": "Mga setting sa account"
},
"auth.verify-email.post-verification.description": {
"message": "Tagumpay na napatunayan ang adres ng iyong email!"
},
"auth.welcome.description": {
"message": "Ikaw ay parte na ngayon ng kahanga-hangang komunidad na ito ng mga tagagawa at manlalalakbay na nagtataguyod, nagda-download, at nananatiling napapanahon sa mga nakamamanghang na mga mod."
},
@@ -71,6 +125,51 @@
"collection.delete-modal.description": {
"message": "Habambuhay na matatanggal ang koleksiyong ito. Hindi mababawi ang pagkilos na ito."
},
"collection.error.not-found": {
"message": "Hindi mahanap ang koleksiyon"
},
"collection.label.owner": {
"message": "May-ari"
},
"common.no": {
"message": "Hindi"
},
"common.yes": {
"message": "Oo"
},
"create.collection.cancel": {
"message": "Kanselahin"
},
"create.collection.name-label": {
"message": "Pangalan"
},
"create.organization.cancel": {
"message": "Kanselahin"
},
"create.organization.name-label": {
"message": "Pangalan"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "Kanselahin"
},
"create.project.name-label": {
"message": "Pangalan"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-public": {
"message": "Publiko"
},
"create.project.visibility-unlisted": {
"message": "Unlisted"
},
"dashboard.collections.label.search-input": {
"message": "Maghanap sa iyong mga koleksiyon"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Ang banyagang entidad ay isang kalakalang entidad na nakaayos sa labas ng Estados Unidos (tulod ng di-US na korporasyon, partnership, o LLC)."
},
@@ -80,15 +179,60 @@
"dashboard.creator-tax-form-modal.entity.question": {
"message": "Isa ka bang pribadong indibidwal o parte ng isang banyagang entidad?"
},
"error.collection.404.list_title": {
"message": "Bakit?"
},
"error.generic.default.title": {
"message": "Hala!"
},
"error.organization.404.list_title": {
"message": "Bakit?"
},
"error.project.404.list_title": {
"message": "Bakit?"
},
"error.user.404.list_title": {
"message": "Bakit?"
},
"frog.altText": {
"message": "Isang photorealistic na pagpipinta ng frog labyrinth"
},
"frog.title": {
"message": "Palaka"
},
"landing.button.discover-mods": {
"message": "Magtuklas ng mga mod"
},
"landing.button.go-to-dashboard": {
"message": "Pumunta sa dashboard"
},
"landing.creator.feature.data-statistics.description": {
"message": "Makatanggap ng detalyadong reporta ng mga pagtingin ng pahina, bilang ng pagdownload, at revenue"
},
"landing.feature.launcher.description": {
"message": "Binibigyang-daan ng open-source API ng Modrinth ang mga launcher na makadagdag ng malalimang pagsasama sa Modrinth. Maaari mong gamitin ang Modrinth sa <link>aming app</link> at sa iilang pinakasikat na mga launcher gaya ng ATLauncher, MultiMC, at Prism Launcher."
},
"landing.heading.the-place-for-minecraft": {
"message": "Ang lugar para sa Minecraft na {content}"
},
"landing.heading.the-place-for-minecraft.mods": {
"message": "mga mod"
},
"landing.heading.the-place-for-minecraft.resource-packs": {
"message": "mga resource pack"
},
"landing.notifications.has-been-updated": {
"message": "Na-update ang {title}!"
},
"landing.search.label": {
"message": "Maghanap"
},
"landing.search.placeholder": {
"message": "Maghanap..."
},
"landing.section.for-players.label": {
"message": "Para sa mga Manlalaro"
},
"landing.subheading": {
"message": "Magtuklas, maglaro, at magbahagi ng mga Minecraft content sa aming open-source na platapormang ginawa para sa komunidad."
},
@@ -98,8 +242,14 @@
"layout.action.reports": {
"message": "Mga reporta"
},
"layout.banner.account-action": {
"message": "Nangangailangan ng akawnt"
},
"layout.banner.add-email.button": {
"message": "Mga setting sa account"
"message": "Bisitahin ang mga setting sa account"
},
"layout.banner.add-email.description": {
"message": "Dahil sa mga kadahilang pangseguridad, kailangan ng Modrinth na makapag-register ka ng email address sa iyong akawnt."
},
"layout.banner.build-fail.description": {
"message": "Itong pinakalat na frontend ng Modrinth ay bigong makabuo ng estato galing sa API. Maaaring dahil ito sa isang outage o error sa konpigurasyon. Muling itayo kapag magagamit na ang API. Error codes: {errors}; Kasalukuyang URL ng API ay: {url}"
@@ -107,6 +257,9 @@
"layout.banner.build-fail.title": {
"message": "May error sa pagbuo ng estado galing sa API habang nagpapatayo."
},
"layout.banner.verify-email.description": {
"message": "Dahil sa mga kadahilang pangseguridad, kailangan ng Modrinth na mapatunayan ang email address sa iyong akawnt."
},
"layout.footer.about": {
"message": "Tungkol"
},
@@ -194,6 +347,12 @@
"layout.meta.description": {
"message": "Mag-download ng mga Minecraft mod, plugin, datapack, shader, resourcepack, at modpack sa Modrinth. Tumuklas at mag-publish ng mga proyekto sa Modrinth na may modernong, madaling gamitin na interface at API."
},
"layout.nav.home": {
"message": "Home"
},
"layout.nav.search": {
"message": "Maghanap"
},
"moderation.page.projects": {
"message": "Mga Proyekto"
},
@@ -203,14 +362,41 @@
"moderation.page.technicalReview": {
"message": "Teknikal na Pagsusuri"
},
"moderation.search.placeholder": {
"message": "Maghanap..."
},
"profile.bio.fallback.creator": {
"message": "Isang tagagawa sa Modrinth."
},
"profile.bio.fallback.user": {
"message": "Isang Modrinth user."
},
"profile.details.label.email": {
"message": "Email"
},
"profile.label.badges": {
"message": "Tsapa"
},
"profile.label.joined": {
"message": "Sumali"
},
"profile.label.no": {
"message": "Hindi"
},
"profile.label.yes": {
"message": "Oo"
},
"profile.meta.description": {
"message": "Magdownload ng mga proyekto ni {username} sa Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Magdownload ng mga proyekto ni {username} sa Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> download ng proyekto} other {<stat>{count}</stat> na download ng proyekto}}"
"project-member-header.accept": {
"message": "Tanggapin"
},
"project-member-header.error": {
"message": "Error"
},
"project-type.datapack.plural": {
"message": "Mga Data Pack"
@@ -218,15 +404,33 @@
"project-type.datapack.singular": {
"message": "Data Pack"
},
"project-type.mod.plural": {
"message": "Mga Mod"
},
"project-type.mod.singular": {
"message": "Mod"
},
"project-type.plugin.singular": {
"message": "Plugin"
},
"project-type.resourcepack.plural": {
"message": "Mga Resource Pack"
},
"project-type.resourcepack.singular": {
"message": "Resource Pack"
},
"project-type.shader.singular": {
"message": "Shader"
},
"project.about.details.updated": {
"message": "In-update {date}"
},
"project.download.game-version": {
"message": "Bersiyon ng laro: {version}"
},
"project.download.install-with-app": {
"message": "I-install gamit ang Modrinth App"
},
"project.download.no-app": {
"message": "Wala kang Modrinth App?"
},
@@ -239,6 +443,9 @@
"project.download.select-game-version": {
"message": "Piliin ang lahat ng bersiyon ng laro"
},
"project.download.select-platform": {
"message": "Pumili ng plataporma"
},
"project.download.show-all-versions": {
"message": "Ipakita ang lahat ng bersiyon"
},
@@ -272,40 +479,112 @@
"project.settings.environment.notice.review-options.description": {
"message": "Kakaunlad lang ng aming sistema sa Mga Environment sa Modrinth at magagamit na ngayon ang mga bagong pagpipilian. Mangyaring suriin na tama ang napili sa ibaba at pindutin ang 'Patunayan' kapag tapos ka na!"
},
"project.settings.environment.verification.verify-button": {
"message": "Patunayan"
},
"project.settings.general.name.title": {
"message": "Pangalan"
},
"project.settings.general.url.title": {
"message": "URL"
},
"project.settings.title": {
"message": "Mga Setting"
},
"project.stats.downloads-label": {
"message": "download {count, plural, one {} other {}}"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Hindi mahanda ang download"
"scopes.performAnalytics.description": {
"message": "Gawin ang mga aksiyon sa analitika"
},
"servers.backups.item.prepare-download": {
"message": "Ihanda ang download"
"servers.backups.item.lock": {
"message": "I-lock"
},
"servers.backups.item.prepare-download-again": {
"message": "Subukang muli ang paghahanda"
"servers.backups.item.locked": {
"message": "Ni-lock"
},
"servers.backups.item.preparing-download": {
"message": "Hinahanda ang download..."
"servers.backups.item.rename": {
"message": "I-rename"
},
"servers.backups.item.retry": {
"message": "Retry"
},
"servers.backups.item.unlock": {
"message": "I-unlock"
},
"servers.notice.actions": {
"message": "Mga Aksiyon"
},
"servers.notice.begins": {
"message": "Magsisimula"
},
"servers.notice.id": {
"message": "ID"
},
"servers.notice.level": {
"message": "Level"
},
"servers.plan.large.name": {
"message": "Large"
},
"servers.plan.medium.name": {
"message": "Medium"
},
"servers.plan.small.name": {
"message": "Small"
},
"settings.billing.payment_method_type.eftpos": {
"message": "EFTPOS"
},
"settings.billing.payment_method_type.jcb": {
"message": "JCB"
},
"settings.billing.payment_method_type.paypal": {
"message": "PayPal"
},
"settings.billing.payment_method_type.unknown": {
"message": "Hindi kilalang payment method"
},
"settings.billing.payment_method_type.visa": {
"message": "Visa"
},
"settings.display.flags.description": {
"message": "Magpagana o huwag magpagana ng mga tiyak na feature sa iyong device."
},
"settings.display.project-list-layouts.datapack": {
"message": "Pahina ng mga Data Pack"
"message": "Pahina ng Mga Data Pack"
},
"settings.display.project-list-layouts.description": {
"message": "Pumili ng iyong gugustohing pag-aayos ng bawat pahinang magpapakita sa mga listahan ng proyekto sa iyong device."
"message": "Pumili ng iyong gugustohing ayos ng bawat pahinang magpapakita sa mga listahan ng proyekto sa iyong device."
},
"settings.display.project-list-layouts.resourcepack": {
"message": "Pahina ng mga Resource Pack"
"message": "Pahina ng Mga Resource Pack"
},
"settings.display.project-list-layouts.title": {
"message": "Mga ayos ng listahan ng proyekto"
},
"settings.display.theme.description": {
"message": "Pumili ng iyong gugustohing paksang-kulay para sa Modrinth ng nitong device."
},
"settings.language.languages.search-field.placeholder": {
"message": "Maghanap ng lengguwahe..."
},
"settings.pats.modal.create.name.label": {
"message": "Pangalan"
},
"settings.profile.bio.title": {
"message": "Biyograpiya"
},
"settings.profile.profile-picture.reset": {
"message": "I-reset"
},
"settings.sessions.description": {
"message": "Narito ang lahat ng mga device na kasalukuyang nakalog-in sa iyong Modrinth account. Maaari mong maisaisang malog-out ang bawat isa.\n\nKung makakita ka ng isang hindi mo nakikilala, maglog-out sa device na iyon at agarang palitan ang password ng iyong Modrinth account."
},
"settings.sessions.unknown-os": {
"message": "Hindi kilalang OS"
},
"settings.sessions.unknown-platform": {
"message": "Hindi kilalang plataforma"
}
}

View File

@@ -437,6 +437,9 @@
"create.collection.name-label": {
"message": "Nom"
},
"create.collection.name-placeholder": {
"message": "Entrez le nom de la collection..."
},
"create.collection.summary-description": {
"message": "Une ou deux phrases qui décrivent vôtre collection."
},
@@ -446,6 +449,9 @@
"create.collection.summary-placeholder": {
"message": "C'est une collection de..."
},
"create.collection.title": {
"message": "Création de la collection"
},
"create.limit-alert.contact-support": {
"message": "Contacter le support"
},
@@ -479,6 +485,63 @@
"create.organization.name-label": {
"message": "Nom"
},
"create.organization.name-placeholder": {
"message": "Entrez le nom de l'organisation..."
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "Annuler"
},
"create.project.create-project": {
"message": "Créer un projet"
},
"create.project.error-title": {
"message": "Une erreur est survenue"
},
"create.project.name-label": {
"message": "Nom"
},
"create.project.name-placeholder": {
"message": "Entrez le nom du projet..."
},
"create.project.summary-description": {
"message": "Une phrase ou deux qui décrivent votre projet."
},
"create.project.summary-label": {
"message": "Sommaire"
},
"create.project.summary-placeholder": {
"message": "Ce projet ajoute..."
},
"create.project.title": {
"message": "Création d'un projet"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-label": {
"message": "Visibilité"
},
"create.project.visibility-private": {
"message": "Privé"
},
"create.project.visibility-public": {
"message": "Publique"
},
"create.project.visibility-unlisted": {
"message": "Non répertorié"
},
"dashboard.affiliate-links.create.button": {
"message": "Créer un lien affilié"
},
"dashboard.affiliate-links.header": {
"message": "Vos liens affiliés"
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Révoquer"
},
"dashboard.collections.button.create-new": {
"message": "Créer un nouveau"
},
@@ -491,6 +554,12 @@
"dashboard.collections.long-title": {
"message": "Vos collections"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Télécharger {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Tout est prêt ! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Une entité étrangère correspond à toute entreprise située en dehors des États-Unis d'Amérique (par exemple, une entreprise non américaine, une entreprise partenaire ou LLC)."
},
@@ -536,6 +605,9 @@
"error.generic.404.title": {
"message": "Page introuvable"
},
"error.generic.451.title": {
"message": "Contenu indisponible pour des raisons légal"
},
"error.generic.default.list_item.1": {
"message": "Vérifiez si Modrinth est hors ligne sur notre <status-link>page de statut</status-link>."
},
@@ -764,6 +836,9 @@
"layout.action.lookup-by-email": {
"message": "Recherche par email"
},
"layout.action.manage-affiliates": {
"message": "Gérer les liens affiliés"
},
"layout.action.manage-server-notices": {
"message": "Gérer les notifications du serveur"
},
@@ -818,12 +893,12 @@
"layout.banner.tax.action": {
"message": "Remplir la déclaration de revenus"
},
"layout.banner.tax.description": {
"message": "Vous avez désormais retiré plus de 600 $ depuis Modrinth cette année. Pour être en règle avec la législation, vous devez remplir une déclaration de revenus. Vos demandes de retrait sont en attente tant que le formulaire n'a pas été rempli."
},
"layout.banner.tax.title": {
"message": "Déclaration de revenus nécessaire"
},
"layout.banner.tin-mismatch.action": {
"message": "Contacter le support"
},
"layout.banner.verify-email.action": {
"message": "Renvoyer un e-mail de vérification"
},
@@ -998,27 +1073,48 @@
"moderation.technical.search.placeholder": {
"message": "Rechercher des revues techniques…"
},
"profile.bio.fallback.creator": {
"message": "Un créateur Modrinth."
},
"profile.bio.fallback.user": {
"message": "Un utilisateur Modrinth."
},
"profile.button.billing": {
"message": "Gérer la facturation de lutilisateur"
},
"profile.button.edit-role": {
"message": "Modifier le rôle"
},
"profile.button.info": {
"message": "Afficher les détails de lutilisateur"
},
"profile.button.manage-projects": {
"message": "Gérer les projets"
},
"profile.details.tooltip.email-verified": {
"message": "Email vérifié"
},
"profile.error.not-found": {
"message": "Utilisateur introuvable"
},
"profile.joined-at": {
"message": "Inscrit le <date>{ago}</date>"
"profile.label.affiliate": {
"message": "Affilié"
},
"profile.label.badges": {
"message": "Badges"
},
"profile.label.collection": {
"message": "Collection"
},
"profile.label.details": {
"message": "Détails"
},
"profile.label.downloads": {
"message": "{count} {count, plural, one {téléchargement} other {téléchargements}}"
},
"profile.label.no": {
"message": "Non"
},
"profile.label.no-collections": {
"message": "Cet utilisateur n'a aucune collection !"
},
@@ -1034,18 +1130,21 @@
"profile.label.organizations": {
"message": "Organisations"
},
"profile.label.projects": {
"message": "{count} {count, plural, one {projet} other {projets}}"
},
"profile.label.saving": {
"message": "Sauvegarde en cours..."
},
"profile.label.yes": {
"message": "Oui"
},
"profile.meta.description": {
"message": "Téléchargez les projets de {username} sur Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Téléchargez les projets de {username} sur Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> téléchargement} other {<stat>{count}</stat> téléchargements}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> projet} other {<stat>{count}</stat> projets}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> abonné} other {<stat>{count}</stat> abonnés}} aux projets"
},
@@ -1073,6 +1172,9 @@
"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": {
"message": "Succès"
},
@@ -1091,15 +1193,15 @@
"project-moderation-nags.resubmit-for-review": {
"message": "Soumettre à nouveau pour révision"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Ton projet a été {status} par le personnel de Modrinth. Tu peux soumettre à nouveau pour examen après avoir adressé le message du personnel."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Vous devez compléter les étapes obligatoires dans la liste de contrôle de publication!"
},
"project-moderation-nags.submit-for-review": {
"message": "Soumettre pour examen"
},
"project-moderation-nags.submit-for-review-button": {
"message": "Soumettre pour examen"
},
"project-moderation-nags.submit-for-review-desc": {
"message": "Votre projet nest visible que par les membres du projet. Il doit être examiné par des modérateurs avant dêtre publié."
},
@@ -1496,18 +1598,6 @@
"report.submit": {
"message": "Soumettre le signalement"
},
"revenue.transfers.total": {
"message": "Vous avez retiré {amount} au total."
},
"revenue.transfers.total.method": {
"message": "Vous avez retiré {amount} via {method}."
},
"revenue.transfers.total.year": {
"message": "Vous avez retiré {amount} en {year}."
},
"revenue.transfers.total.year_method": {
"message": "Vous avez retiré {amount} en {year} via {method}."
},
"scopes.analytics.description": {
"message": "Accéder à vos données analytiques"
},
@@ -1766,9 +1856,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Restauration de sauvegarde en cours"
},
"servers.backups.item.already-preparing": {
"message": "Préparation de la sauvegarde pour le téléchargement déjà en cours "
},
"servers.backups.item.automated": {
"message": "Automatisé"
},
@@ -1778,9 +1865,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Échec de la création de la sauvegarde"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Échec de la préparation du téléchargement"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Échec de la restauration à partir de la sauvegarde"
},
@@ -1790,15 +1874,6 @@
"servers.backups.item.locked": {
"message": "Verrouillé"
},
"servers.backups.item.prepare-download": {
"message": "Préparer le téléchargement"
},
"servers.backups.item.prepare-download-again": {
"message": "Réessayer la préparation"
},
"servers.backups.item.preparing-download": {
"message": "Préparation du téléchargement…"
},
"servers.backups.item.queued-for-backup": {
"message": "En file pour sauvegarde"
},

View File

@@ -24,28 +24,28 @@
"message": "הורד את קובץ ה-RPM"
},
"app-marketing.download.linux": {
"message": "Linux"
"message": "לינוקס"
},
"app-marketing.download.linux-disclaimer": {
"message": "ידוע שלגרסאות Linux של Modrinth App יש <issues-link>בעיות</issues-link> במערכות ובתצורות מסוימות. אם Modrinth App אינו יציב במערכת שלך, אנו ממליצים לך לנסות יישומים אחרים כמו <prism-link>Prism Launcher</prism-link> כדי להתקין בקלות תוכן מ-Modrinth."
"message": "ידוע שלגרסאות לינוקס של אפליקציית מודרינת' יש <issues-link>בעיות</issues-link> במערכות ובתצורות מסוימות. אם אפליקציית מודרינת' אינה יציבה במערכת שלך, אנו ממליצים לך לנסות יישומים אחרים כמו <prism-link>Prism Launcher</prism-link> כדי להתקין בקלות תוכן ממודרינת'."
},
"app-marketing.download.mac": {
"message": "Mac"
"message": "מאק"
},
"app-marketing.download.options-title": {
"message": "אפשרויות הורדה"
},
"app-marketing.download.terms": {
"message": "בהורדת Modrinth App אתה מסכים ל<terms-link>תנאים</terms-link> ול<privacy-link>מדיניות הפרטיות</privacy-link> שלנו."
"message": "בהורדת אפליקציית מודרינת' אתה מסכים ל<terms-link>תנאים</terms-link> ול<privacy-link>מדיניות הפרטיות</privacy-link> שלנו."
},
"app-marketing.download.third-party-packages": {
"message": "חבילות צד שלישי"
},
"app-marketing.download.title": {
"message": "הורד את Modrinth App (בטא)"
"message": "הורד את אפליקציית מודרינת' (בטא)"
},
"app-marketing.download.windows": {
"message": "Windows"
"message": "ווינדוס"
},
"app-marketing.features.follow.description": {
"message": "שמור תוכן שאתה אוהב וקבל עדכונים בלחיצה אחת."
@@ -54,7 +54,7 @@
"message": "עקוב אחר פרויקטים"
},
"app-marketing.features.importing.description": {
"message": "ייבא את כל הפרופילים המועדפים עליך מהמפעיל שבו השתמשת לפני כן, והתחל להשתמש ב-Modrinth App תוך שניות!"
"message": "ייבא את כל הפרופילים המועדפים עליך מהמפעיל שבו השתמשת לפני כן, והתחל להשתמש באפליקציית מודרינת' תוך שניות!"
},
"app-marketing.features.importing.gdlauncher-alt": {
"message": "GDLauncher"
@@ -72,7 +72,7 @@
"message": "מאת {author}"
},
"app-marketing.features.mod-management.description": {
"message": "Modrinth הופך את ניהול כל המודים שלך לפשוט ונוח במקום אחד. באפשרותך להתקין, להסיר ולעדכן מודים בלחיצה אחת."
"message": "מודרינת' הופך את ניהול כל המודים שלך לפשוט ונוח במקום אחד. באפשרותך להתקין, להסיר ולעדכן מודים בלחיצה אחת."
},
"app-marketing.features.mod-management.installed-mods": {
"message": "מודים מותקנים"
@@ -96,7 +96,7 @@
"message": "מצב לא מקוון"
},
"app-marketing.features.open-source.description": {
"message": "המפעיל של Modrinth הוא קוד פתוח לחלוטין. באפשרותך לצפות בקוד המקור ב<github-link>GitHub</github-link>!"
"message": "המפעיל של מודרינת' הוא קוד פתוח לחלוטין. באפשרותך לצפות בקוד המקור ב<github-link>GitHub</github-link>!"
},
"app-marketing.features.open-source.title": {
"message": "קוד פתוח"
@@ -108,7 +108,7 @@
"message": "% מעבד"
},
"app-marketing.features.performance.description": {
"message": "Modrinth App פועל עם ביצועים טובים יותר ממנהלי מודים מובילים רבים, תוך שימוש ב-150 מגה-בייט RAM בלבד!"
"message": "אפליקציית מודרינת' פועל עם ביצועים טובים יותר ממנהלי מודים מובילים רבים, תוך שימוש בכ-150 מגה בייט זיכרון (RAM) בלבד!"
},
"app-marketing.features.performance.discord": {
"message": "דיסקורד"
@@ -129,7 +129,7 @@
"message": "פחות מ-150 מגה-בייט"
},
"app-marketing.features.performance.modrinth-app": {
"message": "אפליקציית Modrinth"
"message": "Modrinth App"
},
"app-marketing.features.performance.one-billion-percent": {
"message": "1 מיליארד %"
@@ -153,7 +153,7 @@
"message": "שחק עם המודים האהובים עליך"
},
"app-marketing.features.sharing.description": {
"message": "בנה, שתף ושחק בחבילות מודים עם כל אחד מאלפי המודים וחבילות המודים שיש כאן ב-Modrinth."
"message": "בנה, שתף ושחק בחבילות מודים עם כל אחד מאלפי המודים וחבילות המודים שיש כאן במודרינת'."
},
"app-marketing.features.sharing.modpack": {
"message": "מודפק"
@@ -168,7 +168,7 @@
"message": "לא כמו שום מפעיל"
},
"app-marketing.features.website.description": {
"message": "יישומון מודרינף נתמך במלואו עם האתר, כך שניתן לגשת לכל הפרויקטים האהובים עליכם מהיישומון!"
"message": "אפליקציית מודרינת' נתמכת במלואה עם האתר, כך שניתן לגשת לכל הפרויקטים האהובים עליכם מהאפליקציה!"
},
"app-marketing.features.website.title": {
"message": "אינטגרציה עם האתר"
@@ -177,19 +177,25 @@
"message": "השתמשת בעבר"
},
"app-marketing.hero.app-screenshot-alt": {
"message": "תמונה של יישומון מודרינף עם התקנה של קובלמון שנפתחת בעמוד \"התוכן\"."
"message": "תמונה של אפליקציית מודרינת' עם התקנה של Cobblemon שנפתחת בעמוד ה\"תוכן\"."
},
"app-marketing.hero.description": {
"message": "יישומון מודרינף הוא launcher מיוחד, בקוד פתוח, שמאפשר לכם לשחק עם המודים שאתם אוהבים, ושומר עליהם מעודכנים. הכל בחבילה אחת, קומפקטית ומסודרת."
"message": "אפליקציית מודרינת' היא משגר (launcher) מיוחד, קוד פתוח, שמאפשר לכם לשחק עם המודים שאתם אוהבים, ושומר עליהם מעודכנים. הכל בחבילה אחת, קומפקטית ומסודרת."
},
"app-marketing.hero.download-button": {
"message": "יישומון מודרינף - לחץ להורדה"
"message": "הורד את Modrinth App"
},
"app-marketing.hero.download-modrinth-app": {
"message": "הורד את יישומון מודרינף"
"message": "הורד את אפליקציית מודרינת'"
},
"app-marketing.hero.download-modrinth-app-for-os": {
"message": "הורד את יישומון מודרינף עבור {os}"
"message": "הורד את Modrinth App עבור {os}"
},
"app-marketing.hero.minecraft-screenshot-alt": {
"message": "תמונה ראשית מהפנורמה של המודפק cobblemon."
},
"app-marketing.hero.more-download-options": {
"message": "אפשרויות הורדה נוספות"
},
"auth.authorize.action.authorize": {
"message": "אימות"
@@ -347,6 +353,12 @@
"auth.welcome.checkbox.subscribe": {
"message": "הירשם לעדכונים על Modrinth"
},
"auth.welcome.description": {
"message": "אתה עכשיו חלק מהקהילה המדהימה של יוצרים ומשתמשים שכבר בונים, מורידים ומתעדכנים עם מודים מגניבים."
},
"auth.welcome.label.tos": {
"message": "ע\"י יצירת חשבון, אתה הסכמת ל<terms-link>תנאים</terms-link> של מודרינפ ו<privacy-policy-link>מדיניות הפרטיות</privacy-policy-link>."
},
"auth.welcome.long-title": {
"message": "ברוכים הבאים ל-Modrinth!"
},
@@ -365,6 +377,18 @@
"collection.button.unfollow-project": {
"message": "הסר מעקב מפרוייקט"
},
"collection.delete-modal.description": {
"message": "זה יגרום להסרה של הקולנוע הזאת לתמיד. אין אפשרות לבטל."
},
"collection.delete-modal.title": {
"message": "אתה בטוח שאתה רוצה למחוק את הקולקציה?"
},
"collection.description": {
"message": "{description} צפה באוסף {name} מ{username} במודרינת'"
},
"collection.description.following": {
"message": "אוסף שנוצר אוטומטית של כל הפרויקטים שאתה עוקב אחריו."
},
"collection.error.not-found": {
"message": "אוסף לא נמצא"
},
@@ -374,6 +398,9 @@
"collection.label.created-at": {
"message": "נוצר {ago}"
},
"collection.label.curated-by": {
"message": "נוצר על ידי"
},
"collection.label.no-projects": {
"message": "אין לאוסף זה פרוייקטים!"
},
@@ -392,6 +419,153 @@
"collection.title": {
"message": "{name} - אוסף"
},
"common.no": {
"message": "לא"
},
"common.yes": {
"message": "כן"
},
"create.collection.cancel": {
"message": "בטל"
},
"create.collection.collection-info": {
"message": "האוסף החדש שלך יווצר עכשיו כאוסף ציבורי עם {count, plural, =0 {no projects} one {# project} other {# projects}}."
},
"create.collection.create-collection": {
"message": "צור אוסף"
},
"create.collection.error-title": {
"message": "אירעה שגיאה"
},
"create.collection.name-label": {
"message": "שם"
},
"create.collection.name-placeholder": {
"message": "הכנס שם לאוסף..."
},
"create.collection.summary-description": {
"message": "משפט או שניים שמתאים בקצרה את האוסף שלך."
},
"create.collection.summary-label": {
"message": "תקציר"
},
"create.collection.summary-placeholder": {
"message": "זה האוסף של..."
},
"create.collection.title": {
"message": "צור אוסף"
},
"create.limit-alert.approaching-limit": {
"message": "מתקרב למגבלה של {type} ({current}/{max})"
},
"create.limit-alert.approaching-limit-description": {
"message": "הינך עומד/ת להגיע למגבלת ה{type}, אנה צרו קשר עם שירות לקוחות במידה וצריך יותר מ{max}{typePlural}."
},
"create.limit-alert.contact-support": {
"message": "צור קשר עם תמיכה"
},
"create.limit-alert.limit-reached": {
"message": "הגעת לגבול של {type}"
},
"create.limit-alert.limit-reached-description": {
"message": "הגעת להגבלת ה{type} מתוך {max}. אנה צרו קשר עם שרות לקוחות על מנת להעלות את ההגבלה."
},
"create.limit-alert.type-collection": {
"message": "אוסף"
},
"create.limit-alert.type-organization": {
"message": "ארגון"
},
"create.limit-alert.type-plural-collection": {
"message": "אוספים"
},
"create.limit-alert.type-plural-organization": {
"message": "ארגונים"
},
"create.limit-alert.type-plural-project": {
"message": "פרויקטים"
},
"create.limit-alert.type-project": {
"message": "פרויקט"
},
"create.organization.cancel": {
"message": "בטל"
},
"create.organization.create-organization": {
"message": "צור ארגון"
},
"create.organization.error-title": {
"message": "התרחשה תקלה"
},
"create.organization.name-label": {
"message": "שם"
},
"create.organization.name-placeholder": {
"message": "הכנס שם ארגון..."
},
"create.organization.ownership-info": {
"message": "אתה תהיה הבעלים של ארגון זה, אבל אתה יכול להזמין חברים אחרים ולהעביר את הבעלות אליהם בכל זמן."
},
"create.organization.summary-description": {
"message": "משפט או שניים שמפרטים על הארגון שלך."
},
"create.organization.summary-label": {
"message": "סיכום"
},
"create.organization.summary-placeholder": {
"message": "ארגון ל..."
},
"create.organization.title": {
"message": "יוצר ארגון"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "בטל"
},
"create.project.create-project": {
"message": "צור פרויקט"
},
"create.project.error-title": {
"message": "התרחשה תקלה"
},
"create.project.name-label": {
"message": "שם"
},
"create.project.name-placeholder": {
"message": "הכנס שם פרויקט..."
},
"create.project.summary-description": {
"message": "משפט או שניים שמפרטים על הפרויקט שלך."
},
"create.project.summary-label": {
"message": "סיכום"
},
"create.project.summary-placeholder": {
"message": "הפרויקט מוסיף..."
},
"create.project.title": {
"message": "יוצר פרויקט"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-description": {
"message": "מצב נראות הפרויקט שלך אחרי שאושר."
},
"create.project.visibility-label": {
"message": "מצב נראות"
},
"create.project.visibility-private": {
"message": "פרויקט פרטי"
},
"create.project.visibility-public": {
"message": "פרויקט פומבי"
},
"create.project.visibility-unlisted": {
"message": "לא מוגדר"
},
"dashboard.collections.button.create-new": {
"message": "צור חדש"
},
@@ -404,18 +578,78 @@
"dashboard.collections.long-title": {
"message": "האוספים שלך"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "הורדת {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "מס {formType} שלך נשלח בהצלחה!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "ברשותך לצאת עכשיו. אם יש שאלות או צורך לעדכן את פרטיך <support-link>צרו קשר עם שירות לקוחות</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "הכל מוכן!🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "ארגון חיצוני הוא עסק ממוסד מחוץ לארצות הברית (כמו חברה לא-ארה״בית, שותפות, או LLC)."
},
"dashboard.creator-tax-form-modal.entity.foreign-entity": {
"message": "ארגון חיצוני"
},
"dashboard.creator-tax-form-modal.entity.private-individual": {
"message": "אדם פרטי"
},
"dashboard.creator-tax-form-modal.entity.question": {
"message": "הינך גוף פרטי או חלק מארגון חיצוני?"
},
"dashboard.creator-tax-form-modal.header": {
"message": "קובץ מס"
},
"dashboard.creator-tax-form-modal.security.description": {
"message": "Modrinth משתמשים בגוף החיצוני Track1099 על מנת לאסוף ולשמור בבטיחות את קבצי המס שלך.\n<security-link>עוד מידע כאן.</security-link>"
},
"dashboard.creator-tax-form-modal.security.header": {
"message": "הליכים בטחונים"
},
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "הינך אזרח מארה״ב?"
},
"error.collection.404.list_item.1": {
"message": "ייתכן שהקלדת כתובת URL שגויה של האוסף."
},
"error.collection.404.list_item.2": {
"message": "ייתכן שהאוסף פרטי."
},
"error.collection.404.list_item.3": {
"message": "יכול להיות שהקובץ שלך נסתר על ידי צוות Modrinth משום שפגע ב<tou-link>תנאי השימוש</tou-link>."
},
"error.collection.404.list_title": {
"message": "למה?"
},
"error.collection.404.title": {
"message": "קובץ לא נמצא"
},
"error.generic.404.subtitle": {
"message": "העמוד שחיפשת לא קיים."
},
"error.generic.404.title": {
"message": "עמוד לא קיים"
},
"error.generic.451.subtitle": {
"message": "עמוד זה נחסם מסיבות משפטיות, כגון צנזורה ממשלתית או הליכים משפטיים מתמשכים."
},
"error.generic.451.title": {
"message": "תוכן לא נגיש מסיבות משפטיות"
},
"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": "נסו שוב בעוד מספר דקות."
},
"error.generic.default.subtitle": {
"message": "משהו השתבש."
},
@@ -527,15 +761,81 @@
"landing.error.failedToLoadRandomProjects": {
"message": "נכשל בניסיון טעינת פרויקטים אקראיים :("
},
"landing.feature.follow.description": {
"message": "התעדכן/י כל פעם הפקרויקטים האהובים עליך מתעדכנים."
},
"landing.feature.follow.heading": {
"message": "עקבו אחר פרויקטים שאתם אוהבים"
},
"landing.feature.launcher.description": {
"message": "ה-API הפתוח של Modrinth מאפשר למשגרים (Launchers) להוסיף אינטגרציה עמוקה עם הפלטפורמה. אתם יכולים להשתמש ב-Modrinth דרך האפליקציה שלנו, וגם דרך כמה מהמשגרים הפופולריים ביותר כמו ATLauncher, MultiMC ו-Prism Launcher."
"message": "ה-API הפתוח של Modrinth מאפשר למפעילים לשלב אינטגרציה עמוקה עם Modrinth. ניתן להשתמש ב-Modrinth דרך <link>האפליקציה שלנו</link>, וגם באמצעות כמה מהמפעילים הפופולריים ביותר, כמו ATLauncher, MultiMC ו-Prism Launcher."
},
"landing.feature.launcher.heading": {
"message": "שחק עם המפעיל האהוב עליך"
},
"landing.feature.search.description": {
"message": "מערכת החיפוש הזריזה והפילטרים העוצמתיים של Modrinth מאפשרים למצוא את מה שמחפשים בזמן כתיבה."
},
"landing.feature.search.heading": {
"message": "מצא/י מה שתרצה/י, במהירות וקלות"
},
"landing.heading.the-place-for-minecraft": {
"message": "המקום ל{content} מיינקראפט"
},
"landing.heading.the-place-for-minecraft.data-packs": {
"message": "חבילות תוכן / Data Packs"
},
"landing.heading.the-place-for-minecraft.modpacks": {
"message": "חבילות מודים / Modpacks"
},
"landing.heading.the-place-for-minecraft.mods": {
"message": "מודים"
},
"landing.heading.the-place-for-minecraft.plugins": {
"message": "פלאגינים"
},
"landing.heading.the-place-for-minecraft.resource-packs": {
"message": "טקסטורות"
},
"landing.heading.the-place-for-minecraft.servers": {
"message": "שרתים"
},
"landing.heading.the-place-for-minecraft.shaders": {
"message": "הצללות / שיידרים"
},
"landing.launcher.atlauncher-label": {
"message": "ATLauncher"
},
"landing.launcher.graphic-alt": {
"message": "הצגה של חלון מיינקראפט מופשט, עם לוגו Mojang בצבע ירוק Modrinth."
},
"landing.launcher.modrinth-app-label": {
"message": "Modrinth App"
},
"landing.launcher.prism-launcher-label": {
"message": "Prism Launcher"
},
"landing.notifications.has-been-updated": {
"message": "{title} עודכן!"
},
"landing.notifications.heading": {
"message": "עדכונים"
},
"landing.notifications.received-time": {
"message": "זמן קבלה: {time}"
},
"landing.notifications.version-released": {
"message": "גרסא {version} יצאה לגרסאת המשחק {gameVersion}"
},
"landing.search.label": {
"message": "חיפוש"
},
"landing.search.placeholder": {
"message": "חיפוש..."
},
"landing.search.sort-by.label": {
"message": "מיון לפי"
},
"landing.section.for-players.label": {
"message": "בשביל שחקנים"
},
@@ -621,7 +921,7 @@
"message": "מוצרים"
},
"layout.footer.products.app": {
"message": "אפליקציית Modrinth"
"message": "Modrinth App"
},
"layout.footer.products.plus": {
"message": "Modrinth+"
@@ -646,5 +946,68 @@
},
"layout.footer.social.bluesky": {
"message": "Bluesky"
},
"layout.footer.social.discord": {
"message": "דיסקורד"
},
"layout.footer.social.github": {
"message": "GitHub"
},
"layout.footer.social.mastodon": {
"message": "מסטודון"
},
"layout.footer.social.x": {
"message": "X"
},
"layout.nav.modrinth-app": {
"message": "Modrinth App"
},
"moderation.page.projects": {
"message": "פרויקטים"
},
"profile.label.no": {
"message": "לא"
},
"profile.label.yes": {
"message": "כן"
},
"project-member-header.error": {
"message": "שגיאה"
},
"project-type.datapack.plural": {
"message": "חבילות נתונים"
},
"project-type.datapack.singular": {
"message": "חבילת נתונים"
},
"project-type.mod.plural": {
"message": "מודים"
},
"project-type.mod.singular": {
"message": "מוד"
},
"project.actions.dont-show-again": {
"message": "אל תציג שוב"
},
"project.description.title": {
"message": "תיאור"
},
"project.download.install-with-app": {
"message": "התקן באמצעות Modrinth App"
},
"project.settings.general.name.title": {
"message": "שם"
},
"project.settings.title": {
"message": "הגדרות"
},
"settings.language.languages.language-label-error": {
"message": "{label}. שגיאה"
},
"settings.pats.modal.create.name.label": {
"message": "שם"
},
"settings.profile.profile-picture.title": {
"message": "תמונת פרופיל"
}
}

View File

@@ -2,6 +2,12 @@
"admin.billing.error.not-found": {
"message": "Korisnik nije pronađen"
},
"app-marketing.features.follow.title": {
"message": "Zasljedi projekte"
},
"app-marketing.features.importing.description": {
"message": "!"
},
"auth.authorize.action.authorize": {
"message": "Ovlasti"
},

View File

@@ -167,12 +167,21 @@
"app-marketing.features.unlike-any-launcher": {
"message": "Olyan Minecraft inditóprogram"
},
"app-marketing.features.website.description": {
"message": "A Modrinth alkalmazás teljes mértékben integrálva van a weboldallal, így az alkalmazásból elérheted az összes kedvenc projektedet!"
},
"app-marketing.features.website.title": {
"message": "Weboldal integráció"
},
"app-marketing.features.youve-used-before": {
"message": "ami eltérő"
},
"app-marketing.hero.app-screenshot-alt": {
"message": "A Modrinth alkalmazás képernyőképe, amelyen a Cobblemon példány a „Tartalom” oldalon van megnyitva."
},
"app-marketing.hero.description": {
"message": "A Modrinth App egy egyedülálló, nyílt forráskódú kliens, amely lehetővé teszi, hogy kedvenc modjaidat játssz, és naprakészen tartsd őket, mindezt egy kis, praktikus csomagban."
},
"app-marketing.hero.download-button": {
"message": "Modrinth App letöltése"
},
@@ -182,6 +191,9 @@
"app-marketing.hero.download-modrinth-app-for-os": {
"message": "Modrinth App letöltése {os} re/ra"
},
"app-marketing.hero.minecraft-screenshot-alt": {
"message": "A Cobblemon példány főmenüjének képernyőképe."
},
"app-marketing.hero.more-download-options": {
"message": "Több letöltési lehetőség"
},
@@ -197,21 +209,45 @@
"auth.authorize.authorize-app-name": {
"message": "{appName} Engedélyezése"
},
"auth.authorize.error.no-redirect-url": {
"message": "Átirányítási útvonal nem találhatóa válaszban"
},
"auth.authorize.redirect-url": {
"message": "Át leszel irányítva ide <redirect-url>{url}</redirect-url>"
},
"auth.reset-password.method-choice.action": {
"message": "Visszaállítási email küldése"
},
"auth.reset-password.method-choice.description": {
"message": "Írja be az email-címét az alábbi mezőbe, és küldünk Önnek egy hivatkozást, amivel vissza tudja állítani a fiókját."
},
"auth.reset-password.method-choice.email-username.label": {
"message": "Email vagy felhasználónév"
},
"auth.reset-password.method-choice.email-username.placeholder": {
"message": "Email"
},
"auth.reset-password.notification.email-sent.text": {
"message": "Egy email el lett küldve önnek az email-címére amennyiben az email-cím el volt mente a fiókjában."
},
"auth.reset-password.notification.email-sent.title": {
"message": "Email küldve"
},
"auth.reset-password.notification.password-reset.text": {
"message": "Mostmár be tudd lépni a fiókjába az új jelszavával."
},
"auth.reset-password.notification.password-reset.title": {
"message": "A jelszavad sikeresen visszaállítva"
},
"auth.reset-password.post-challenge.action": {
"message": "Jelszó visszaállítása"
},
"auth.reset-password.post-challenge.confirm-password.label": {
"message": "Jelszó megerősítése"
},
"auth.reset-password.post-challenge.description": {
"message": "Írja be az új jelszavát az alábbi mezőbe, hogy hozzáférjen a fiókjához."
},
"auth.reset-password.title": {
"message": "Jelszó visszaállítása"
},
@@ -257,6 +293,9 @@
"auth.sign-up.label.username": {
"message": "Felhasználónév"
},
"auth.sign-up.legal-dislaimer": {
"message": "Fiók létrehozásával Ön elfogadja a Modrinth <terms-link>Felhasználási feltételeit</terms-link> és <privacy-policy-link>Adatvédelmi irányelveit</privacy-policy-link>."
},
"auth.sign-up.notification.password-mismatch.text": {
"message": "A jelszavak nem jegyeznek!"
},
@@ -266,6 +305,9 @@
"auth.sign-up.sign-in-option.title": {
"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"
},
"auth.sign-up.title": {
"message": "Regisztráció"
},
@@ -290,15 +332,33 @@
"auth.verify-email.failed-verification.action": {
"message": "Hítelesítő email újraküldése"
},
"auth.verify-email.failed-verification.description": {
"message": "Nem tudtuk ellenőrizni az e-mail címét. Próbálja meg újra elküldeni az ellenőrző e-mailt a bejelentkezés után a vezérlőpulton keresztül."
},
"auth.verify-email.failed-verification.description.logged-in": {
"message": "Nem tudtuk ellenőrizni az e-mail címét. Kérjük, próbálja meg újra elküldeni az ellenőrző e-mailt az alábbi gombra kattintva."
},
"auth.verify-email.failed-verification.title": {
"message": "Email hítelesítés sikertelen"
},
"auth.verify-email.post-verification.description": {
"message": "Email cím sikeresen meglett erősítve!"
},
"auth.verify-email.post-verification.title": {
"message": "Email megerősítés"
},
"auth.verify-email.title": {
"message": "Email-cím megerősítése"
},
"auth.welcome.checkbox.subscribe": {
"message": "Iratkozzon fel a Modrinth frissítéseiről szóló értesítésekre"
},
"auth.welcome.description": {
"message": "Most már része vagy annak a fantasztikus alkotó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."
},
"auth.welcome.label.tos": {
"message": "Fiók létrehozásával Ön elfogadja a Modrinth <terms-link>Felhasználási feltételeit</terms-link> és <privacy-policy-link>Adatvédelmi irányelveit</privacy-policy-link>."
},
"auth.welcome.long-title": {
"message": "Üdvözlünk a Modrinth-onl!"
},
@@ -317,39 +377,591 @@
"collection.button.unfollow-project": {
"message": "Projektek kikövetése"
},
"collection.delete-modal.description": {
"message": "Ezzel a gyűjtemény véglegesen törlődik. Ez a művelet nem vonható vissza."
},
"collection.delete-modal.title": {
"message": "Biztos vagy hogy törölni akarod ezt a gyűjteményt?"
},
"collection.description": {
"message": "{description}- Nézd meg a {name} nevű gyűjtemény {username} által Modrinth-on"
},
"collection.description.following": {
"message": "Az összes követett projekt automatikusan generált gyűjteménye."
},
"collection.error.not-found": {
"message": "Nncs ilyen gyűjtemény"
},
"collection.label.collection": {
"message": "Gyűjtemény"
},
"collection.label.created-at": {
"message": "Létrehozva {ago}"
},
"collection.label.curated-by": {
"message": "Kurátor"
},
"collection.label.no-projects": {
"message": "Ez a gyűjtemény egy projektet sem tartalmaz!"
},
"collection.label.no-projects-auth": {
"message": "Nincs egyetlen projekted sem.\nSzeretnél <create-link>hozzáadni egyet</create-link>?"
},
"collection.label.owner": {
"message": "Tulajdonos"
},
"collection.label.projects-count": {
"message": "{count, plural, one {<stat>{count}</stat> projekt} other {<stat>{count}</stat> projekt}}"
},
"collection.label.updated-at": {
"message": "Frissítve {ago}"
},
"collection.title": {
"message": "{name} - Gyűjtemény"
},
"common.no": {
"message": "Nem"
},
"common.yes": {
"message": "Igen"
},
"create.collection.cancel": {
"message": "Mégsem"
},
"create.collection.collection-info": {
"message": "Az új gyűjteményed nyilvános gyűjteményként jön létre, {count, plural, =0 {nincs projekt} one {# projekt} other {# projekt}}."
},
"create.collection.create-collection": {
"message": "Gyűjtemény létrehozása"
},
"create.collection.error-title": {
"message": "Hiba történt"
},
"create.collection.name-label": {
"message": "Név"
},
"create.collection.name-placeholder": {
"message": "Adj meg egy nevet a gyűjteményednek..."
},
"create.collection.summary-description": {
"message": "Egy mondat vagy kettő ami leírja a lényegét a gyűjteményedet."
},
"create.collection.summary-label": {
"message": "Összegzés"
},
"create.collection.summary-placeholder": {
"message": "Ez egy gyűjtemény..."
},
"create.collection.title": {
"message": "Gyűjtemény lérehozása"
},
"create.limit-alert.approaching-limit": {
"message": "Közeledsz a {type} limithez ({current}/{max})"
},
"create.limit-alert.approaching-limit-description": {
"message": "Már majdnem eléred a {type} határt, kérjük, lépj kapcsolatba a támogatással, ha több mint {max} {typePlural}-ra van szükséged."
},
"create.limit-alert.contact-support": {
"message": "Támogatással való kapcsolatba lépés"
},
"create.limit-alert.limit-reached": {
"message": "{type} limit elérve"
},
"create.limit-alert.limit-reached-description": {
"message": "Elérte a {max} {type} korlátot. Kérjük, vegye fel a kapcsolatot az ügyfélszolgálattal a korlát növelése érdekében."
},
"create.limit-alert.type-collection": {
"message": "gyűjtemény"
},
"create.limit-alert.type-organization": {
"message": "szervezet"
},
"create.limit-alert.type-plural-collection": {
"message": "gyűjtemények"
},
"create.limit-alert.type-plural-organization": {
"message": "szervezetek"
},
"create.limit-alert.type-plural-project": {
"message": "projektek"
},
"create.limit-alert.type-project": {
"message": "projekt"
},
"create.organization.cancel": {
"message": "Mégsem"
},
"create.organization.create-organization": {
"message": "Szervezet létrehozása"
},
"create.organization.error-title": {
"message": "Hiba történt"
},
"create.organization.name-label": {
"message": "Név"
},
"create.organization.name-placeholder": {
"message": "Adj meg a szerverzetednek egy nevet..."
},
"create.organization.ownership-info": {
"message": "Átfogod ruház a tulajdon jogod erre a szervervezetre, de már meghívhatsz másokat és átruházhatod a tulajdon jogot bármikor."
},
"create.organization.summary-description": {
"message": "Egy vagy több mondat ami leírja a szervezetedet."
},
"create.organization.summary-label": {
"message": "Összegzés"
},
"create.organization.summary-placeholder": {
"message": "Egy szervezet neki..."
},
"create.organization.title": {
"message": "Hozz létre egy szervezetet"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "Mégsem"
},
"create.project.create-project": {
"message": "Projekt létrehozása"
},
"create.project.error-title": {
"message": "Hiba történt"
},
"create.project.name-label": {
"message": "Név"
},
"create.project.name-placeholder": {
"message": "Adj meg egy projekt nevet..."
},
"create.project.summary-description": {
"message": "Egy vagy kettő mondat ami leírja a projektedet."
},
"create.project.summary-label": {
"message": "Összegzés"
},
"create.project.summary-placeholder": {
"message": "Ez a projekt hozzá add..."
},
"create.project.title": {
"message": "Projekt létrehozása"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-description": {
"message": "A projekt láthatósága jóváhagyása után."
},
"create.project.visibility-label": {
"message": "Láthatóság"
},
"create.project.visibility-private": {
"message": "Privát"
},
"create.project.visibility-public": {
"message": "Nyílvános"
},
"create.project.visibility-unlisted": {
"message": "Nem nyílvános"
},
"dashboard.collections.button.create-new": {
"message": "Új létrehozása"
},
"dashboard.collections.label.projects-count": {
"message": "{count, plural, one {{count} projekt} other {{count} projekt}}"
},
"dashboard.collections.label.search-input": {
"message": "Keresd meg a gyűjteményeidet"
},
"dashboard.collections.long-title": {
"message": "Gyűjteményeid"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Letöltés {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "A/Az {formType} adóbevallásodat sikeresen elküldtük!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Mostantól szabadon kivehetsz a fiókodról. Amennyiben kérdésed van, vagy frissítenéd az adataidat <support-link>vedd fel velünk a kapcsolatot</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Készen állsz!🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "A külföldi jogi személy olyan üzleti egységet jelent, amelyet az Egyesült Államokon kívül hoztak létre (például nem amerikai részvénytársaság, társulás vagy korlátolt felelősségű társaság LLC)."
},
"dashboard.creator-tax-form-modal.entity.foreign-entity": {
"message": "Idegen entitáns"
},
"dashboard.creator-tax-form-modal.entity.private-individual": {
"message": "Magánszemély"
},
"dashboard.creator-tax-form-modal.entity.question": {
"message": "Te magánszemély vagy, vagy egy külföldi céghez tartozol?"
},
"dashboard.creator-tax-form-modal.header": {
"message": "Adóűrlap"
},
"dashboard.creator-tax-form-modal.security.description": {
"message": "A Modrinth a Track1099 nevű harmadik fél szolgáltatót használja az adóűrlapjaid biztonságos begyűjtésére és tárolására. <security-link>További információk itt.</security-link>"
},
"dashboard.creator-tax-form-modal.security.header": {
"message": "Biztonsági gyakorlatok"
},
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Amerikai állampolgár vagy?"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Folytatás limittel"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Részletek"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Mennyiség"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "FX rate"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Válaszd ki az országodat"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Országok keresése..."
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Régió"
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Fiók tulajdonosa"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Érme"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Hálózat"
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Fiók"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Fiók leválasztása"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Fizetési mód"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "PayPal fiók"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Csatlakoztasd a PayPal fiókodat hogy tudjál fizetni keresztül rajta."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Mentés"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Venmo handle sikeresen mentve!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Mentve"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Bejelentkezés PayPalálal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@felhasználónév"
},
"error.collection.404.list_item.1": {
"message": "Elírhatad a gyűjtemémyed URL-ét."
},
"error.collection.404.list_item.2": {
"message": "Ez a gyűjtemény lehet hogy privát."
},
"error.collection.404.list_item.3": {
"message": "Gyűjteményt a Modrinth moderációs csapata eltávolíthatta, mert megsértette a <tou-link>Felhasználási feltételeinket</tou-link>."
},
"error.collection.404.list_title": {
"message": "Miért?"
},
"error.collection.404.title": {
"message": "Nem található gyűjtemény"
},
"error.generic.404.subtitle": {
"message": "Ez az oldal ami iránt érdeklődsz úgy látszik hogy nem létezik."
},
"error.generic.404.title": {
"message": "Nem taláható oldal"
},
"error.generic.451.subtitle": {
"message": "Ez az oldal le lett tiltva legális okok miatt mint például, kormányzati cenzúra vagy folyamatban lévő jogi eljárások miatt."
},
"error.generic.451.title": {
"message": "Tartalom nem elérhető legális okok miatt"
},
"error.generic.default.list_item.1": {
"message": "Ellenőrizd, hogy a Modrinth elérhető-e a <status-link>Állapotoldalon</status-link>."
},
"error.generic.default.list_item.2": {
"message": "Ha ez továbbra is történik, valószínűleg tudatni szeretnéd a Modrinth csapatával. Ezt úgy tehetet meg, hogy csatlakozol a <discord-link>Discord szerverünkre</discord-link>."
},
"error.generic.default.list_title": {
"message": "Kerjük próbáld újra pár perc múlva."
},
"error.generic.default.subtitle": {
"message": "A manóba, valami rosszul sült el!"
},
"error.generic.default.title": {
"message": "Ajjaj!"
},
"error.organization.404.list_item.1": {
"message": "Rosszul írhattad a szervezet URL címét."
},
"error.organization.404.list_item.2": {
"message": "A szervezet készítője megváltoztathatta, vagy törölhette az URL-t."
},
"error.organization.404.list_item.3": {
"message": "A szervezet törölve lehetett a Modrinth moderációs csapata által, amiért megsértette a <tou-link>Terms of Use</tou-link>-t."
},
"error.organization.404.list_title": {
"message": "Miért?"
},
"error.organization.404.title": {
"message": "Szervezet nem található"
},
"error.project.404.list_item.1": {
"message": "Rosszul írhattad a projekt URL címét."
},
"error.project.404.list_item.2": {
"message": "A projekt lészítője megváltoztathatta az URL címet, vagy a projektet privátta tette, esetleg ki is törölte."
},
"error.project.404.list_item.3": {
"message": "A projekt valószínűleg le lett törölve a Modrinth moderációs csapat által, amiért megsértette a <tou-link>Terms of Use</tou-link>-t."
},
"error.project.404.list_title": {
"message": "Miért?"
},
"error.project.404.title": {
"message": "Projekt nem található"
},
"error.user.404.list_item.1": {
"message": "Rosszul írhattad a felhasználó nevét."
},
"error.user.404.list_item.2": {
"message": "A felhasználó megváltoztathatta a nevét, vagy törölhette fiókját."
},
"error.user.404.list_item.3": {
"message": "A felhasználó fiókja fel lehet függesztve, amiért megsértette a Modrinth <tou-link>Terms of Use</tou-link>-t."
},
"error.user.404.list_title": {
"message": "Miért?"
},
"error.user.404.title": {
"message": "Felhasználó nem található"
},
"frog": {
"message": "Békázva lettél!🐸🐸"
},
"frog.altText": {
"message": "Egy fotórealisztikus festmény egy béka labirintusról"
},
"frog.froggedPeople": {
"message": "{count, plural, one {{count} more person} other {{count} more people}} is békázva lett!🐸🐸"
},
"frog.sinceOpened": {
"message": "Ez a lap {ago} lett megnyitva"
},
"frog.title": {
"message": "Béka"
},
"landing.button.discover-mods": {
"message": "Modok felfedezése"
},
"landing.button.go-to-dashboard": {
"message": "Vissza a főoldalra"
},
"landing.creator.feature.constantly-evolving.description": {
"message": "Kapd meg a legjobb modolási élményt folyamatos frissítésekkel a Modrinth csapattól"
},
"landing.creator.feature.constantly-evolving.title": {
"message": "Folyamatos Változás"
},
"landing.creator.feature.discovery.title": {
"message": "Felfedezés"
},
"landing.heading.the-place-for-minecraft.plugins": {
"message": "pluginok"
},
"landing.heading.the-place-for-minecraft.resource-packs": {
"message": "forráscsomagok"
},
"landing.heading.the-place-for-minecraft.servers": {
"message": "szerverek"
},
"landing.launcher.atlauncher-label": {
"message": "ATLauncher"
},
"landing.launcher.modrinth-app-label": {
"message": "Modrinth App"
},
"landing.launcher.prism-launcher-label": {
"message": "Prism Launcher"
},
"landing.notifications.has-been-updated": {
"message": "{title} frissítve lett!"
},
"landing.notifications.heading": {
"message": "Értesítések"
},
"landing.notifications.received-time": {
"message": "Kaptad {time} óta"
},
"landing.notifications.version-released": {
"message": "Egy új verzió {version} kijött erre: {gameVersion}"
},
"landing.search.label": {
"message": "Keresés"
},
"landing.search.placeholder": {
"message": "Keresés..."
},
"landing.search.sort-by.label": {
"message": "Rendezés"
},
"landing.section.for-creators.label": {
"message": "Készítőknek"
},
"landing.section.for-players.label": {
"message": "Játékosoknak"
},
"layout.action.change-theme": {
"message": "Kinézet"
},
"layout.action.create-new": {
"message": "Új létrehozása..."
},
"layout.action.file-lookup": {
"message": "Fájl keresés"
},
"layout.action.lookup-by-email": {
"message": "Email alapján keresés"
},
"layout.action.manage-server-notices": {
"message": "Szerver megjegyzések kezelése"
},
"layout.action.new-collection": {
"message": "Új gyűjtemény"
},
"layout.action.new-organization": {
"message": "Új Szervezet"
},
"layout.action.new-project": {
"message": "Új projekt"
},
"layout.action.reports": {
"message": "Jelentések"
},
"layout.action.review-projects": {
"message": "Projektek átnézése"
},
"layout.avatar.alt": {
"message": "Avatárod"
},
"layout.banner.account-action": {
"message": "Fiók akció szükséges"
},
"layout.banner.add-email.button": {
"message": "Nézze meg fiókbeállításait"
},
"layout.banner.add-email.description": {
"message": "Biztonsági okok miatt, Modrinthen kell egy email cím a fiókodhoz."
},
"layout.banner.staging.title": {
"message": "A Modrinth színreviteli környezetét nézed"
},
"layout.banner.subscription-payment-failed.button": {
"message": "Számlázási információ frissítése"
},
"layout.banner.subscription-payment-failed.title": {
"message": "Számlázási akció szükséges."
},
"layout.banner.tin-mismatch.action": {
"message": "Támogatással való kapcsolatba lépés"
},
"layout.footer.about": {
"message": "Rólunk"
},
"layout.footer.about.careers": {
"message": "Karrierek"
},
"layout.footer.about.changelog": {
"message": "Változtatások"
},
"layout.footer.about.news": {
"message": "Hírek"
},
"layout.footer.about.rewards-program": {
"message": "Jutalom program"
},
"layout.footer.about.status": {
"message": "Státusz"
},
"layout.footer.legal": {
"message": "Jogi megjegyzések"
},
"layout.footer.legal-disclaimer": {
"message": "NEM HIVATALOS MINECRAFT SZOLGÁLTATÁS. A MOJANG VAGY MICROSOFT NEM HAGYTA JÓVÁ, ÉS NEM PARTNERÜK."
},
"layout.footer.products.app": {
"message": "Modrinth App"
},
"layout.footer.products.plus": {
"message": "Modrinth+"
},
"layout.footer.products.servers": {
"message": "Modrinth Servers"
},
"layout.footer.resources": {
"message": "Források"
},
"layout.footer.resources.api-docs": {
"message": "API dokumentáció"
},
"layout.footer.social.discord": {
"message": "Discord"
},
"layout.footer.social.github": {
"message": "GitHub"
},
"layout.footer.social.mastodon": {
"message": "Mastodon"
},
"layout.footer.social.x": {
"message": "X"
},
"layout.menu-toggle.action": {
"message": "Menü ki-be"
},
"moderation.page.reports": {
"message": "Jelentések"
},
"moderation.sort.by": {
"message": "Rendezés"
},
"profile.details.label.email": {
"message": "Email"
},
"profile.details.label.payment-methods": {
"message": "Kifizetési módok"
},
"profile.details.tooltip.email-not-verified": {
"message": "Nem hitelesített email"
},
"profile.details.tooltip.email-verified": {
"message": "Hitelesített email"
},
"profile.user-id": {
"message": "Felhasználói ID: {id}"
},

View File

@@ -1,4 +1,301 @@
{
"action.cancel": {
"message": "Batal"
},
"action.continue": {
"message": "Lanjutkan"
},
"admin.billing.error.not-found": {
"message": "Pengguna tidak ditemukan"
},
"app-marketing.download.description": {
"message": "Aplikasi destop kami tersedia pada semua platform, pilih versi yang Anda inginkan."
},
"app-marketing.download.download-appimage": {
"message": "Unduh Applmage"
},
"app-marketing.download.download-beta": {
"message": "Unduh versi beta"
},
"app-marketing.download.download-deb": {
"message": "Unduh DEB"
},
"app-marketing.download.download-rpm": {
"message": "Unduh RPM"
},
"app-marketing.download.linux": {
"message": "Linux"
},
"app-marketing.download.linux-disclaimer": {
"message": "Modrinth App untuk Linux <issues-link>memiliki isu</issues-link> pada sistem dan konfigurasi tertentu. Bila Modrinth App tidak stabil pada sistem Anda, kami menyarankan Anda untuk mencoba aplikasi lain seperti <prism-link>Prism Launcher</prism-link> untuk mengunduh konten Modrinth dengan mudah."
},
"app-marketing.download.mac": {
"message": "Mac"
},
"app-marketing.download.options-title": {
"message": "Pilihan pengunduhan"
},
"app-marketing.download.terms": {
"message": "Dengan mengunduh Modrinth App, Anda menyetujui <terms-link>Syarat</terms-link> dan <privacy-link>Kebijakan Privasi</privacy-link> kami."
},
"app-marketing.download.third-party-packages": {
"message": "Paket pihak ketiga"
},
"app-marketing.download.title": {
"message": "Unduh Modrinth App (Beta)"
},
"app-marketing.download.windows": {
"message": "Windows"
},
"app-marketing.features.follow.description": {
"message": "Simpan konten yang Anda suka dan dapatkan pembaruan dengan satu klik saja."
},
"app-marketing.features.follow.title": {
"message": "Ikuti proyek"
},
"app-marketing.features.importing.description": {
"message": "Impor semua profil favorit Anda dari peluncur yang telah Anda gunakan sebelumnya, dan mulai penggunaan Modrinth App dalam beberapa saat!"
},
"app-marketing.features.importing.gdlauncher-alt": {
"message": "GDLauncher"
},
"app-marketing.features.importing.multimc-alt": {
"message": "MultiMC"
},
"app-marketing.features.importing.title": {
"message": "Pengimporan profil"
},
"app-marketing.features.mod-management.actions": {
"message": "Tindakan"
},
"app-marketing.features.mod-management.byAuthor": {
"message": "oleh {author}"
},
"app-marketing.features.mod-management.description": {
"message": "Modrinth mempermudah pengurusan seluruh mod Anda dalam satu tempat. Anda dapat memasang, menghapus, dan memperbarui mod dalam satu klik."
},
"app-marketing.features.mod-management.installed-mods": {
"message": "Mod terpasang"
},
"app-marketing.features.mod-management.name": {
"message": "Nama"
},
"app-marketing.features.mod-management.search-mods": {
"message": "Cari mod"
},
"app-marketing.features.mod-management.title": {
"message": "Pengelolaan mod"
},
"app-marketing.features.mod-management.version": {
"message": "Versi"
},
"app-marketing.features.offline.description": {
"message": "Mainkan mod Anda, baik saat daring maupun luring."
},
"app-marketing.features.offline.title": {
"message": "Mode luring"
},
"app-marketing.features.open-source.description": {
"message": "Peluncur Modrinth sepenuhnya bersumber terbuka. Anda dapat melihat kode sumber pada <github-link>GitHub</github-link> kami!"
},
"app-marketing.features.open-source.title": {
"message": "Sumber terbuka"
},
"app-marketing.features.performance.activity-monitor": {
"message": "Pemantauan aktivitas"
},
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.description": {
"message": "Modrinth App bekerja lebih baik daripada pengurus mod ternama lainnya, dengan menggunakan hanya 150 MB RAM!"
},
"app-marketing.features.performance.discord": {
"message": "Discord"
},
"app-marketing.features.performance.good-performance": {
"message": "Kinerja baik"
},
"app-marketing.features.performance.google-chrome": {
"message": "Google Chrome"
},
"app-marketing.features.performance.infinite-mb": {
"message": "∞ MB"
},
"app-marketing.features.performance.infinite-times-infinite-mb": {
"message": "∞ * ∞ MB"
},
"app-marketing.features.performance.less-than-150mb": {
"message": "< 150 MB"
},
"app-marketing.features.performance.modrinth-app": {
"message": "Modrinth App"
},
"app-marketing.features.performance.one-billion-percent": {
"message": "1 miliar %"
},
"app-marketing.features.performance.process-name": {
"message": "Nama proses"
},
"app-marketing.features.performance.ram": {
"message": "RAM"
},
"app-marketing.features.performance.small": {
"message": "Kecil"
},
"app-marketing.features.performance.title": {
"message": "Berkinerja"
},
"app-marketing.features.play.description": {
"message": "Gunakan Modrinth App untuk mengunduh dan memainkan mod dan paket mod favorit Anda."
},
"app-marketing.features.play.title": {
"message": "Mainkan mod favorit Anda"
},
"app-marketing.features.sharing.description": {
"message": "Buat, bagikan, dan mainkan paket mod dengan berbagai pilihan mod dan paket mod yang dibagikan di Modrinth."
},
"app-marketing.features.sharing.modpack": {
"message": "Paket Mod"
},
"app-marketing.features.sharing.share-button": {
"message": "Bagikan"
},
"app-marketing.features.sharing.title": {
"message": "Bagikan paket mod"
},
"app-marketing.features.unlike-any-launcher": {
"message": "Tidak seperti peluncur lain"
},
"app-marketing.features.website.description": {
"message": "Modrinth App berintegrasi penuh dengan situs web, sehingga Anda dapat mengakses semua proyek favorit Anda dari aplikasi!"
},
"app-marketing.features.website.title": {
"message": "Integrasi situs web"
},
"app-marketing.features.youve-used-before": {
"message": "yang pernah Anda gunakan"
},
"app-marketing.hero.app-screenshot-alt": {
"message": "Tangkapan layar dari Modrinth App dengan pemasangan Cobblemon dibuka pada halaman 'Konten'."
},
"app-marketing.hero.description": {
"message": "Modrinth App adalah peluncur unik dan bersumber terbuka yang memperbolehkan Anda untuk memainkan mod-mod favorit Anda dan memastikannya diperbarui, semuanya dalam satu kemasan ringkas."
},
"app-marketing.hero.download-button": {
"message": "Unduh Modrinth App"
},
"app-marketing.hero.download-modrinth-app": {
"message": "Unduh Modrinth App"
},
"app-marketing.hero.download-modrinth-app-for-os": {
"message": "Unduh Modrinth App untuk {os}"
},
"app-marketing.hero.minecraft-screenshot-alt": {
"message": "Tangkapan layar menu utama pemasangan Cobblemon."
},
"app-marketing.hero.more-download-options": {
"message": "Pilihan Pengunduhan Lainnya"
},
"auth.authorize.action.authorize": {
"message": "Sahkan"
},
"auth.authorize.action.decline": {
"message": "Tolak"
},
"auth.authorize.app-info": {
"message": "<strong>{appName}</strong> oleh <creator-link>{creator}</creator-link> akan dapat:"
},
"auth.authorize.authorize-app-name": {
"message": "Mengesahkan {appName}"
},
"auth.authorize.redirect-url": {
"message": "Anda akan dialihkan ke <redirect-url>{url}</redirect-url>"
},
"auth.reset-password.method-choice.action": {
"message": "Kirim sur-el pemulihan"
},
"auth.reset-password.method-choice.description": {
"message": "Masukkan sur-el Anda di bawah dan kami akan mengirimkan tautan untuk memulihkan akun Anda."
},
"auth.reset-password.method-choice.email-username.label": {
"message": "Sur-el atau nama pengguna"
},
"auth.reset-password.method-choice.email-username.placeholder": {
"message": "Sur-el"
},
"auth.reset-password.notification.email-sent.text": {
"message": "Sur-el berisi instruksi telah dikirim kepada Anda bila sur-el tersebut sebelumnya tersimpan di akun Anda."
},
"auth.reset-password.notification.email-sent.title": {
"message": "Sur-el terkirim"
},
"auth.reset-password.notification.password-reset.text": {
"message": "Anda sekarang dapat masuk ke akun Anda dengan kata sandi baru."
},
"auth.reset-password.notification.password-reset.title": {
"message": "Kata sandi berhasil diatur ulang"
},
"auth.reset-password.post-challenge.action": {
"message": "Atur ulang kata sandi"
},
"auth.reset-password.post-challenge.confirm-password.label": {
"message": "Konfirmasi kata sandi"
},
"auth.reset-password.post-challenge.description": {
"message": "Masukkan kata sandi baru di bawah untuk mengakses akun Anda."
},
"auth.reset-password.title": {
"message": "Atur Ulang Kata Sandi"
},
"auth.reset-password.title.long": {
"message": "Atur ulang kata sandi Anda"
},
"auth.sign-in.2fa.description": {
"message": "Mohon masukkan kode autentikasi dwifaktor untuk melanjutkan."
},
"auth.sign-in.2fa.label": {
"message": "Masukkan kode dwifaktor"
},
"auth.sign-in.2fa.placeholder": {
"message": "Masukkan kode..."
},
"auth.sign-in.additional-options": {
"message": "<forgot-password-link>Lupa kata sandi?</forgot-password-link> • <create-account-link>Buat akun</create-account-link>"
},
"auth.sign-in.email-username.label": {
"message": "Sur-el atau nama pengguna"
},
"auth.sign-in.password.label": {
"message": "Kata sandi"
},
"auth.sign-in.sign-in-with": {
"message": "Masuk dengan"
},
"auth.sign-in.title": {
"message": "Masuk"
},
"auth.sign-in.use-password": {
"message": "Atau gunakan kata sandi"
},
"auth.sign-up.action.create-account": {
"message": "Buat akun"
},
"auth.sign-up.confirm-password.label": {
"message": "Konfirmasi kata sandi"
},
"auth.sign-up.email.label": {
"message": "Sur-el"
},
"auth.sign-up.label.username": {
"message": "Nama pengguna"
},
"auth.sign-up.legal-dislaimer": {
"message": "Dengan membuat sebuah akun, Anda menyetujui <terms-link>Ketentuan</terms-link> dan <privacy-policy-link>Kebijakan Privasi</privacy-policy-link> Modrinth."
},
"auth.sign-up.notification.password-mismatch.text": {
"message": "Kata sandi tidak cocok!"
},
"frog": {
"message": "Anda terkodok-kodok!🐸"
}

View File

@@ -5,6 +5,6 @@
},
"searchTerms": {
"description": "Please provide additional search terms associated with the language, if needed, to enhance the search functionality (e.g., American English, Deutschland). Each search term should be entered on a separate line. Translate as a hyphen (-) if no additional terms are needed.",
"message": "Indonesia\nBahasa Indonesia"
"message": "Indonesia\nBahasa Indonesia\nIndonesian\nIND\nID"
}
}

View File

@@ -578,6 +578,18 @@
"dashboard.collections.long-title": {
"message": "Le tue raccolte"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Scarica {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "Il tuo modulo fiscale {formType} è stato inviato con successo!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Ora puoi nuovamente ritirare denaro. Se hai altre domande o devi aggiornare le tue informazioni <support-link>contatta l'assistenza</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Tutto fatto! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Entità estera fa riferimento a un'entità commerciale stabilita fuori dagli Stati Uniti (per esempio società, partenariati, o LLC non statunitensi)."
},
@@ -912,11 +924,20 @@
"message": "Completa il modulo fiscale"
},
"layout.banner.tax.description": {
"message": "Hai già ritirato oltre $600 da Modrinth quest'ano. Per essere in regola con le norme fiscali devi completare un modulo fiscale. I tuoi prelievi saranno sospesi finché questo modulo sarà inviato."
"message": "Hai già ritirato oltre $600 da Modrinth quest'anno. Per essere in regola con le norme fiscali devi completare un modulo fiscale. I tuoi prelievi saranno sospesi finché questo modulo sarà inviato."
},
"layout.banner.tax.title": {
"message": "Modulo fiscale obbligatorio"
},
"layout.banner.tin-mismatch.action": {
"message": "Contatta assistenza"
},
"layout.banner.tin-mismatch.description": {
"message": "I tuoi prelievi sono temporaneamente bloccati perché il tuo TIN o SSN non corrispondono ai registri dell'IRS. Si prega di contattare l'assistenza per resettare e reinviare il tuo modulo fiscale."
},
"layout.banner.tin-mismatch.title": {
"message": "Modulo fiscale fallito"
},
"layout.banner.verify-email.action": {
"message": "Reinvia email di verifica"
},
@@ -1091,27 +1112,66 @@
"moderation.technical.search.placeholder": {
"message": "Cerca revisioni tecniche..."
},
"profile.bio.fallback.creator": {
"message": "Un creatore su Modrinth."
},
"profile.bio.fallback.user": {
"message": "Un utente di Modrinth."
},
"profile.button.billing": {
"message": "Gestisci pagamento utente"
},
"profile.button.edit-role": {
"message": "Modifica ruolo"
},
"profile.button.info": {
"message": "Mostra dettagli utente"
},
"profile.button.manage-projects": {
"message": "Gestisci progetti"
},
"profile.details.label.auth-providers": {
"message": "Fornitori autenticazione"
},
"profile.details.label.email": {
"message": "Email"
},
"profile.details.label.has-password": {
"message": "Usa una password"
},
"profile.details.label.has-totp": {
"message": "Usa TOTP"
},
"profile.details.label.payment-methods": {
"message": "Metodi di pagamento"
},
"profile.details.tooltip.email-not-verified": {
"message": "Email non verificata"
},
"profile.details.tooltip.email-verified": {
"message": "Email verificata"
},
"profile.error.not-found": {
"message": "Utente non trovato"
},
"profile.joined-at": {
"message": "Registrato <date>{ago}</date>"
},
"profile.label.badges": {
"message": "Badge"
},
"profile.label.collection": {
"message": "Raccolta"
},
"profile.label.details": {
"message": "Dettagli"
},
"profile.label.downloads": {
"message": "{count} {count, plural, one {download} other {download}}"
},
"profile.label.joined": {
"message": "Registrazione"
},
"profile.label.no": {
"message": "No"
},
"profile.label.no-collections": {
"message": "Questo utente non ha raccolte!"
},
@@ -1127,18 +1187,21 @@
"profile.label.organizations": {
"message": "Organizzazioni"
},
"profile.label.projects": {
"message": "{count} {count, plural, one {progetto} other {progetti}}"
},
"profile.label.saving": {
"message": "Salvando..."
},
"profile.label.yes": {
"message": "Sì"
},
"profile.meta.description": {
"message": "Scarica i progetti di {username} su Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Scarica i progetti di {username} su Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> download del progetto} other {<stat>{count}</stat> download del progetto}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> progetto} other {<stat>{count}</stat> progetti}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> follower del progetto} other {<stat>{count}</stat> follower del progetto}}"
},
@@ -1187,9 +1250,6 @@
"project-moderation-nags.resubmit-for-review": {
"message": "Ripresenta per la revisione"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Il tuo progetto è stato {status} dallo staff di Modrinth. Nella maggioranza dei casi, potrai ripresentarlo per una revisione dopo aver risposto al messaggio dello staff."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Devi completare i passaggi obbligatori nella checklist di pubblicazione!"
},
@@ -1595,18 +1655,6 @@
"report.submit": {
"message": "Invia segnalazione"
},
"revenue.transfers.total": {
"message": "Hai prelevato in tutto {amount}."
},
"revenue.transfers.total.method": {
"message": "Hai prelevato {amount} tramite {method}."
},
"revenue.transfers.total.year": {
"message": "Hai prelevato {amount} nel {year}."
},
"revenue.transfers.total.year_method": {
"message": "Hai prelevato {amount} nel {year} tramite {method}."
},
"scopes.analytics.description": {
"message": "Accedere ai tuoi dati analitici"
},
@@ -1865,9 +1913,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Ripristino backup in corso"
},
"servers.backups.item.already-preparing": {
"message": "Preparando backup per il download"
},
"servers.backups.item.automated": {
"message": "Automatizzato"
},
@@ -1877,9 +1922,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Errore nella creazione del backup"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Errore nella preparazione download"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Errore nel ripristino da backup"
},
@@ -1889,15 +1931,6 @@
"servers.backups.item.locked": {
"message": "Bloccato"
},
"servers.backups.item.prepare-download": {
"message": "Prepara download"
},
"servers.backups.item.prepare-download-again": {
"message": "Prova a preparare di nuovo"
},
"servers.backups.item.preparing-download": {
"message": "Preparando download..."
},
"servers.backups.item.queued-for-backup": {
"message": "In coda per backup"
},

View File

@@ -167,12 +167,24 @@
"app-marketing.features.unlike-any-launcher": {
"message": "他のランチャーと異なる点"
},
"app-marketing.features.website.description": {
"message": "Modrinth Appはウェブサイトと完全に統合されているため、あなたはお気に入りのプロジェクトにアプリからアクセスできます"
},
"app-marketing.features.website.title": {
"message": "ウェブサイトとの統合"
},
"app-marketing.hero.download-button": {
"message": "Modrinth アプリをダウンロードする"
},
"app-marketing.hero.download-modrinth-app": {
"message": "Modrinth アプリをダウンロードする"
},
"app-marketing.hero.download-modrinth-app-for-os": {
"message": "{os}向けのModrinth Appをダウンロード"
},
"app-marketing.hero.more-download-options": {
"message": "詳細なダウンロード設定"
},
"auth.authorize.action.authorize": {
"message": "認証"
},
@@ -398,6 +410,126 @@
"common.yes": {
"message": "はい"
},
"create.collection.cancel": {
"message": "キャンセル"
},
"create.collection.collection-info": {
"message": "新しいコレクションは、{count, plural, =0 {空の} other {#個のプロジェクトを含む}}公開コレクションとして作成されます。"
},
"create.collection.create-collection": {
"message": "コレクションを作成"
},
"create.collection.error-title": {
"message": "エラーが発生しました"
},
"create.collection.name-label": {
"message": "名前"
},
"create.collection.name-placeholder": {
"message": "コレクション名を入力…"
},
"create.collection.summary-description": {
"message": "1~2文程度のコレクションの説明。"
},
"create.collection.summary-label": {
"message": "概要"
},
"create.collection.title": {
"message": "コレクションを作成中"
},
"create.limit-alert.contact-support": {
"message": "サポートに連絡"
},
"create.limit-alert.type-collection": {
"message": "コレクション"
},
"create.limit-alert.type-organization": {
"message": "組織"
},
"create.limit-alert.type-plural-collection": {
"message": "コレクション"
},
"create.limit-alert.type-plural-organization": {
"message": "組織"
},
"create.limit-alert.type-plural-project": {
"message": "プロジェクト"
},
"create.limit-alert.type-project": {
"message": "プロジェクト"
},
"create.organization.cancel": {
"message": "キャンセル"
},
"create.organization.create-organization": {
"message": "組織を作成"
},
"create.organization.error-title": {
"message": "エラーが発生しました"
},
"create.organization.name-label": {
"message": "名前"
},
"create.organization.name-placeholder": {
"message": "組織名を入力…"
},
"create.organization.summary-description": {
"message": "1~2文程度のあなたの組織の説明。"
},
"create.organization.summary-label": {
"message": "概要"
},
"create.organization.summary-placeholder": {
"message": "…のための組織です"
},
"create.organization.title": {
"message": "組織を作成"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "キャンセル"
},
"create.project.create-project": {
"message": "プロジェクトを作成"
},
"create.project.error-title": {
"message": "エラーが発生しました"
},
"create.project.name-label": {
"message": "名前"
},
"create.project.name-placeholder": {
"message": "プロジェクト名を入力…"
},
"create.project.summary-description": {
"message": "1~2文程度のプロジェクトの説明。"
},
"create.project.summary-label": {
"message": "概要"
},
"create.project.title": {
"message": "プロジェクトを作成中"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-label": {
"message": "公開範囲"
},
"create.project.visibility-private": {
"message": "非公開"
},
"create.project.visibility-public": {
"message": "公開"
},
"create.project.visibility-unlisted": {
"message": "限定公開"
},
"dashboard.affiliate-links.create.button": {
"message": "アフィリエイトリンクを作成"
},
"dashboard.collections.button.create-new": {
"message": "新規作成"
},
@@ -410,6 +542,24 @@
"dashboard.collections.long-title": {
"message": "コレクション"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "ダウンロード {formType}"
},
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "あなたはアメリカ国民ですか?"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "ネットワーク"
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "アカウント"
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "保存"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "保存済み"
},
"error.collection.404.list_item.1": {
"message": "コレクションの URL を誤って入力した可能性があります。"
},
@@ -482,6 +632,9 @@
"landing.creator.feature.monetization.title": {
"message": "収益化"
},
"landing.creator.feature.team-management.description": {
"message": "チームメンバーを招待し、役割と権限を簡単に管理しましょう"
},
"landing.creator.feature.team-management.title": {
"message": "チーム管理"
},
@@ -501,7 +654,7 @@
"message": "データパック"
},
"landing.heading.the-place-for-minecraft.modpacks": {
"message": "modパック"
"message": "Modパック"
},
"landing.heading.the-place-for-minecraft.mods": {
"message": "mod"
@@ -521,18 +674,27 @@
"landing.launcher.atlauncher-label": {
"message": "ATLauncher"
},
"landing.launcher.modrinth-app-label": {
"message": "Modrinth App"
},
"landing.launcher.prism-launcher-label": {
"message": "Prism Launcher"
},
"landing.notifications.heading": {
"message": "通知"
},
"landing.search.label": {
"message": "検索"
},
"landing.search.placeholder": {
"message": "検索…"
},
"landing.search.sort-by.label": {
"message": "並び替え"
},
"landing.section.for-creators.label": {
"message": "クリエーター"
},
"landing.section.for-players.label": {
"message": "プレイヤー向け"
},
@@ -554,6 +716,15 @@
"layout.action.lookup-by-email": {
"message": "メールで探す"
},
"layout.action.new-collection": {
"message": "新規コレクション"
},
"layout.action.new-organization": {
"message": "新規組織"
},
"layout.action.new-project": {
"message": "新規プロジェクト"
},
"layout.avatar.alt": {
"message": "あなたのアバター"
},
@@ -584,9 +755,18 @@
"layout.footer.about.status": {
"message": "ステータス"
},
"layout.footer.legal-disclaimer": {
"message": "Minecraftの公式サービスではありません。MojangまたはMicrosoftの承認または連携はありません。"
},
"layout.footer.legal.copyright-policy": {
"message": "著作権ポリシーとDMCA"
},
"layout.footer.legal.privacy-policy": {
"message": "プライバシーポリシー"
},
"layout.footer.legal.rules": {
"message": "コンテンツルール"
},
"layout.footer.legal.security-notice": {
"message": "セキュリティに関するお知らせ"
},
@@ -641,9 +821,30 @@
"layout.meta.description": {
"message": "ModrinthでMinecraftのMOD、プラグイン、データパック、シェーダー、リソースパック、そしてModパックをダウンロードしましょう。Modrinthでは、モダンで使いやすいインターフェースとAPIを使って、プロジェクトを発見したり公開したりできます。"
},
"layout.nav.analytics": {
"message": "統計"
},
"layout.nav.get-modrinth-app": {
"message": "Modrinthアプリを入手"
},
"layout.nav.home": {
"message": "ホーム"
},
"layout.nav.host-a-server": {
"message": "サーバーをホスト"
},
"layout.nav.organizations": {
"message": "組織"
},
"layout.nav.profile": {
"message": "プロフィール"
},
"layout.nav.projects": {
"message": "プロジェクト"
},
"layout.nav.revenue": {
"message": "収益"
},
"layout.nav.search": {
"message": "検索"
},
@@ -743,6 +944,12 @@
"project-type.modpack.singular": {
"message": "Modパック"
},
"project-type.resourcepack.plural": {
"message": "リソースパック"
},
"project-type.shader.plural": {
"message": "シェーダー"
},
"project.collections.create-new": {
"message": "コレクションを作成"
},
@@ -763,5 +970,26 @@
},
"project.navigation.changelog": {
"message": "変更履歴"
},
"settings.display.sidebar.advanced-rendering.description": {
"message": "ぼかし効果などの高度なレンダリングを有効にします。グラフィック アクセラレーションが使用できない場合は、パフォーマンスが低下する可能性があります。"
},
"settings.display.sidebar.advanced-rendering.title": {
"message": "高度なレンダリング"
},
"settings.display.theme.description": {
"message": "このデバイスでのお好みのテーマを選択してください。"
},
"settings.display.theme.title": {
"message": "テーマ"
},
"settings.pats.modal.create.action": {
"message": "PATを作成"
},
"ui.latest-news-row.latest-news": {
"message": "Modrinthの最新ニュース"
},
"ui.latest-news-row.view-all": {
"message": "すべてのニュースを見る"
}
}

View File

@@ -29,6 +29,9 @@
"app-marketing.download.options-title": {
"message": "다운로드 옵션"
},
"app-marketing.download.terms": {
"message": "Modrinth App을 다운로드하면 <terms-link> 이용 약관</terms-link>과 <privacy-link>개인정보 처리방침</privacy-link>에 동의하는 것으로 간주합니다."
},
"app-marketing.download.third-party-packages": {
"message": "제3자 패키지"
},
@@ -38,6 +41,9 @@
"app-marketing.download.windows": {
"message": "Windows"
},
"app-marketing.features.importing.description": {
"message": "이전에 사용하던 런처의 즐겨찾기 프로필을 불러와, Modrinth App에서 바로 시작해보세요!"
},
"app-marketing.features.importing.multimc-alt": {
"message": "MultiMC"
},
@@ -89,6 +95,9 @@
"app-marketing.features.performance.small": {
"message": "적음"
},
"app-marketing.features.play.description": {
"message": "Modrinth App을 통해 여러분이 좋아하는 모드와 모드팩을 다운로드하고 바로 플레이하세요."
},
"app-marketing.features.sharing.modpack": {
"message": "모드팩"
},
@@ -98,6 +107,12 @@
"app-marketing.features.sharing.title": {
"message": "모드팩 공유"
},
"app-marketing.features.website.title": {
"message": ""
},
"app-marketing.features.youve-used-before": {
"message": "이전에 사용"
},
"auth.authorize.action.authorize": {
"message": "승인"
},
@@ -317,6 +332,18 @@
"collection.title": {
"message": "{name} - 컬렉션"
},
"create.collection.error-title": {
"message": "오류 발생"
},
"create.collection.summary-description": {
"message": "당신의 collection을 문장으로 설명해주세요."
},
"create.limit-alert.limit-reached": {
"message": ""
},
"create.limit-alert.limit-reached-description": {
"message": "{type} 한도 {max}에 도달했습니다. 한도를 늘리려면 고객 지원팀에 문의하세요."
},
"create.limit-alert.type-collection": {
"message": "컬렉션"
},
@@ -341,9 +368,15 @@
"create.organization.create-organization": {
"message": "조직 만들기"
},
"create.organization.error-title": {
"message": "오류 발생"
},
"create.organization.name-label": {
"message": "이름"
},
"create.organization.ownership-info": {
"message": "당신은 이 Organization의 관리자이며, 필요시 다른 멤버를 초대하거나 권한을 이전할 수 있습니다."
},
"create.organization.summary-label": {
"message": "개요"
},
@@ -362,9 +395,18 @@
"create.project.summary-label": {
"message": "개요"
},
"create.project.summary-placeholder": {
"message": "이 프로젝트는 ...을 추가합니다"
},
"create.project.title": {
"message": "프로젝트 생성"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-description": {
"message": ""
},
"dashboard.collections.button.create-new": {
"message": "새로 만들기"
},
@@ -506,6 +548,9 @@
"landing.search.placeholder": {
"message": "검색..."
},
"landing.section.for-creators.description": {
"message": ""
},
"layout.action.change-theme": {
"message": "테마 변경"
},
@@ -683,9 +728,6 @@
"profile.error.not-found": {
"message": "사용자를 찾을 수 없습니다"
},
"profile.joined-at": {
"message": "<date>{ago}</date> 전에 가입함"
},
"profile.label.badges": {
"message": "배지"
},
@@ -713,12 +755,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Modrinth에서 {username}의 프로젝트 다운로드"
},
"profile.stats.downloads": {
"message": "{count, plural, other {<stat>{count}</stat> 프로젝트 다운로드}}"
},
"profile.stats.projects": {
"message": "{count, plural, other {<stat>{count}</stat> 프로젝트}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, other {<stat>{count}</stat> 프로젝트 팔로워}}"
},
@@ -962,18 +998,6 @@
"report.submit": {
"message": "신고 제출"
},
"revenue.transfers.total": {
"message": "총 {amount} 만큼 인출했습니다."
},
"revenue.transfers.total.method": {
"message": "{method}(으)로 총 {amount} 만큼 인출했습니다."
},
"revenue.transfers.total.year": {
"message": "{year}년에 총 {amount} 만큼 인출했습니다."
},
"revenue.transfers.total.year_method": {
"message": "{method}(으)로 {year}년에 총 {amount} 만큼 인출했습니다."
},
"scopes.analytics.description": {
"message": "통계 접근"
},
@@ -1208,9 +1232,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "백업 생성에 실패했습니다"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "다운로드 준비를 실패했습니다"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "백업을 복구하는데 실패했습니다"
},
@@ -1220,15 +1241,6 @@
"servers.backups.item.locked": {
"message": "잠김"
},
"servers.backups.item.prepare-download": {
"message": "다운로드 준비중"
},
"servers.backups.item.prepare-download-again": {
"message": "다시 시도하기"
},
"servers.backups.item.preparing-download": {
"message": "다운로드를 준비하는 중..."
},
"servers.backups.item.queued-for-backup": {
"message": "백업 대기열에 추가됨"
},

View File

@@ -566,6 +566,27 @@
"create.project.visibility-unlisted": {
"message": "تيدق دسنارايکن"
},
"dashboard.affiliate-links.create.button": {
"message": "Cipta pautan afiliasi"
},
"dashboard.affiliate-links.error.title": {
"message": "Ralat semasa memuatkan pautan afiliasi"
},
"dashboard.affiliate-links.header": {
"message": "Pautan afiliasi anda"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "Ini akan membatalkan kod afiliasi `{id}` secara kekal dan sebarang pautan sedia ada dengan kod ini yang telah dikongsi tidak lagi sah."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Batalkan"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "Adakah anda pasti mahu membatalkan pautan afiliasi anda yang bernama ''{title}''?"
},
"dashboard.affiliate-links.search": {
"message": "Cari pautan afiliasi..."
},
"dashboard.collections.button.create-new": {
"message": "چيڤتا بهارو"
},
@@ -578,6 +599,18 @@
"dashboard.collections.long-title": {
"message": "کوليکسي اندا"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "موات تورون {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "بورڠ چوکاي {formType} اندا تله برجاي دهانتر!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "اندا بوليه مڠلوارکن واڠ دڠن بيبس سکارڠ. جک اندا ممڤوڽاءي سوءالن اتاو ڤرلو مڠمس کيني بوتيرن اندا <support-link>هوبوڠي سوکوڠن</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "سلساي! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "اينتيتي اسيڠ برمقصود اينتيتي ڤرنياݢاءن يڠ دأنجورکن دلوار اميريکا شريکت (سڤرتي ڤربادنن⹁ ڤرکوڠسين اتاو LLC بوکن ا.س.)."
},
@@ -602,6 +635,336 @@
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "اداکه اندا ورݢانݢارا اميريکا شريکت؟"
},
"dashboard.creator-withdraw-modal.complete-tax-form": {
"message": "Lengkapkan borang cukai"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Teruskan dengan had"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Butiran"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Amaun"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "Kadar FX"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Yuran"
},
"dashboard.creator-withdraw-modal.fee-breakdown-net-amount": {
"message": "Amaun bersih"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Entiti bisnes"
},
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Entiti bisnes merujuk kepada organisasi terdaftar seperti perbadanan, perkongsian atau LLC."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "Adakah anda sedang mengeluarkan wang sebagai seorang individu atau sebuah perniagaan?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Individu persendirian"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Pilih negara anda"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Cari negara..."
},
"dashboard.creator-withdraw-modal.method-selection.error-text": {
"message": "Tidak dapat mengambil kaedah pembayaran yang tersedia. Sila cuba lagi kemudian."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Gagal memuatkan kaedah pembayaran"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Rantau"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Sesetengah kaedah pembayaran tidak tersedia di rantau tertentu."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Pilih kaedah pengeluaran"
},
"dashboard.creator-withdraw-modal.method-selection.tax-limit-warning": {
"message": "Had pengeluaran anda ialah <b>{amount}</b>, <tax-link>lengkapkan borang cukai</tax-link> untuk mengeluarkan lebih banyak wang."
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Pemilik akaun"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Syiling"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Sahkan alamat dompet anda"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id": {
"message": "Nombor ID kebangsaan"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder": {
"message": "Masukkan nombor ID kebangsaan"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport": {
"message": "Nombor pasport"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder": {
"message": "Masukkan nombor pasport"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id": {
"message": "Masukkan nombor ID penduduk"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder": {
"message": "Masukkan nombor ID penduduk"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc": {
"message": "Nombor RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder": {
"message": "Masukkan nombor RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id": {
"message": "Nombor ID cukai"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder": {
"message": "Masukkan nombor ID cukai"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Rangkaian"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "Anda hampir mencapai ambang pengeluaran. Anda boleh mengeluarkan <b>{amountRemaining}</b> sekarang, tetapi borang cukai diperlukan untuk mengeluarkan lebih banyak wang."
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Akaun"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Putuskan sambungan akaun"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Kaedah pembayaran"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "Akaun PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Sambungkan akaun PayPal anda untuk menerima pembayaran secara langsung."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Simpan"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Nama pemegang Venmo berjaya disimpan!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Disimpan"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Daftar masuk dengan PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-description": {
"message": "Masukkan nama pemegang Venmo anda untuk menerima pembayaran."
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle": {
"message": "Nama pemegang Venmo"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@nama-pengguna"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Kaedah"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Butiran Akaun"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Pengesahan"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Borang cukai"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Butiran"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "Untuk mengeluarkan baki penuh anda yang tersedia sebanyak <b>{available}</b>, sila lengkapkan borang di bawah. Ia diperlukan untuk pelaporan cukai dan hanya perlu dilakukan sekali sahaja."
},
"dashboard.creator-withdraw-modal.tax-form-required.body-with-limit": {
"message": "Anda mesti melengkapkan borang W-9 atau W-8 untuk rekod cukai Modrinth supaya kami kekal mematuhi peraturan cukai."
},
"dashboard.creator-withdraw-modal.tax-form-required.header": {
"message": "Borang cukai diperlukan"
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Kaedah pembayaran"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Ganjaran"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder": {
"message": "Pilih ganjaran"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Ganjaran"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "E-mel yang belum disahkan"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-message": {
"message": "E-mel penghantaran yang anda masukkan tidak dikaitkan dengan akaun Modrinth anda. Modrinth tidak dapat mendapatkan semula ganjaran yang dihantar ke alamat e-mel yang salah."
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Yuran lebih rendah tersedia"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-message": {
"message": "Anda memilih USD untuk PayPal Antarabangsa. <direct-paypal-link>Tukar kepada PayPal langsung</direct-paypal-link> untuk yuran yang lebih baik (≈2% dan bukannya ≈6%)."
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Keluarkan"
},
"dashboard.creator-withdraw-modal.withdraw-limit": {
"message": "Had pengeluaran wang"
},
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "Anda telah menggunakan had pengeluaran anda sebanyak <b>{withdrawLimit}</b>. Anda mesti melengkapkan borang cukai untuk mengeluarkan lebih banyak wang."
},
"dashboard.revenue.available-now": {
"message": "Tersedia sekarang"
},
"dashboard.revenue.balance": {
"message": "Baki"
},
"dashboard.revenue.estimated-tooltip.msg1": {
"message": "Anggaran hasil pendapatan mungkin tertakluk kepada perubahan sehingga ia tersedia."
},
"dashboard.revenue.estimated-tooltip.msg2": {
"message": "Klik untuk membaca tentang cara Modrinth mengendalikan pendapatan anda."
},
"dashboard.revenue.estimated-with-date": {
"message": "Anggaran {date}"
},
"dashboard.revenue.processing": {
"message": "Memproses"
},
"dashboard.revenue.processing.tooltip": {
"message": "Hasil pendapatan kekal dalam pemprosesan sehingga akhir bulan, dan kemudian akan tersedia 60 hari kemudian."
},
"dashboard.revenue.stats.received": {
"message": "Diterima"
},
"dashboard.revenue.stats.transactions": {
"message": "Transaksi"
},
"dashboard.revenue.stats.withdrawn": {
"message": "Telah dikeluarkan"
},
"dashboard.revenue.tos": {
"message": "Dengan memuat naik projek ke Modrinth dan mengeluarkan wang daripada akaun anda, anda bersetuju dengan <terms-link>Terma Program Ganjaran</terms-link> kami. Ketahui lebih lanjut tentang <info-link>Program Ganjaran</info-link> ini."
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Muat turun sebagai CSV"
},
"dashboard.revenue.transactions.header": {
"message": "Transaksi"
},
"dashboard.revenue.transactions.none": {
"message": "Tiada transaksi"
},
"dashboard.revenue.transactions.none.desc": {
"message": "Pembayaran dan pengeluaran anda akan dipaparkan di sini."
},
"dashboard.revenue.transactions.see-all": {
"message": "Lihat semua"
},
"dashboard.revenue.withdraw.blocked-tin-mismatch": {
"message": "Pengeluaran anda telah dikunci buat sementara waktu kerana TIN atau SSN anda tidak sepadan dengan rekod IRS. Sila hubungi sokongan untuk menetapkan semula dan menghantar semula borang cukai anda."
},
"dashboard.revenue.withdraw.card.description": {
"message": "Keluarkan wang daripada baki yang tersedia kepada mana-mana kaedah pembayaran."
},
"dashboard.revenue.withdraw.card.title": {
"message": "Pengeluaran"
},
"dashboard.revenue.withdraw.header": {
"message": "Pengeluaran"
},
"dashboard.withdraw.completion.account": {
"message": "Akaun"
},
"dashboard.withdraw.completion.amount": {
"message": "Amaun"
},
"dashboard.withdraw.completion.close-button": {
"message": "Tutup"
},
"dashboard.withdraw.completion.date": {
"message": "Tarikh"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "Anda akan menerima e-mel di <b>{email}</b> dengan arahan untuk menebus pengeluaran anda."
},
"dashboard.withdraw.completion.exchange-rate": {
"message": "Kadar pertukaran"
},
"dashboard.withdraw.completion.fee": {
"message": "Yuran"
},
"dashboard.withdraw.completion.method": {
"message": "Kaedah"
},
"dashboard.withdraw.completion.net-amount": {
"message": "Amaun bersih"
},
"dashboard.withdraw.completion.recipient": {
"message": "Penerima"
},
"dashboard.withdraw.completion.title": {
"message": "Pengeluaran selesai"
},
"dashboard.withdraw.completion.transactions-button": {
"message": "Transaksi"
},
"dashboard.withdraw.completion.wallet": {
"message": "Dompet"
},
"dashboard.withdraw.error.generic.text": {
"message": "Kami tidak dapat menghantar permintaan pengeluaran anda, sila semak butiran anda atau hubungi sokongan."
},
"dashboard.withdraw.error.generic.title": {
"message": "Tidak dapat mengeluarkan wang"
},
"dashboard.withdraw.error.invalid-address.text": {
"message": "Alamat yang anda berikan tidak dapat disahkan. Sila semak butiran alamat anda."
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Pengesahan alamat gagal"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": "Butiran akaun bank yang anda berikan tidak sah. Sila sahkan maklumat anda."
},
"dashboard.withdraw.error.invalid-bank.title": {
"message": "Butiran bank tidak sah"
},
"dashboard.withdraw.error.invalid-wallet.text": {
"message": "Alamat dompet kripto yang anda berikan tidak sah. Sila semak semula dan cuba lagi."
},
"dashboard.withdraw.error.invalid-wallet.title": {
"message": "Alamat dompet tidak sah"
},
"dashboard.withdraw.error.minimum-not-met.text": {
"message": "Amaun pengeluaran (selepas yuran) tidak memenuhi keperluan minimum. Sila tingkatkan amaun pengeluaran anda."
},
"dashboard.withdraw.error.minimum-not-met.title": {
"message": "Amaun terlalu rendah"
},
"dashboard.withdraw.error.tax-form.text": {
"message": "Anda mesti melengkapkan borang cukai untuk menyerahkan permintaan pengeluaran anda."
},
"dashboard.withdraw.error.tax-form.title": {
"message": "Sila lengkapkan borang cukai"
},
"error.collection.404.list_item.1": {
"message": "اندا موڠکين ترساله تاءيڤ URL کوليکسي."
},
@@ -857,6 +1220,9 @@
"layout.action.lookup-by-email": {
"message": "چاري ملالوءي إي-ميل"
},
"layout.action.manage-affiliates": {
"message": "Urus pautan afiliasi"
},
"layout.action.manage-server-notices": {
"message": "اوروس نوتيس ڤلاين"
},
@@ -917,6 +1283,15 @@
"layout.banner.tax.title": {
"message": "بورڠ چوکاي دڤرلوکن"
},
"layout.banner.tin-mismatch.action": {
"message": "هوبوڠي سوکوڠن"
},
"layout.banner.tin-mismatch.description": {
"message": "ڤڠلوارن اندا تله دکونچي بوات سمنتارا وقتو کران TIN اتاو SSN اندا تيدق سڤادن دڠن ريکود IRS. سيلا هوبوڠي سوکوڠن اونتوق منتڤکن سمولا دان مڠهانتر سمولا بورڠ چوکاي اندا."
},
"layout.banner.tin-mismatch.title": {
"message": "بورڠ چوکاي ݢاݢل"
},
"layout.banner.verify-email.action": {
"message": "هانتر سمولا إي-ميل ڤڠصحن"
},
@@ -941,6 +1316,9 @@
"layout.footer.about.status": {
"message": "ستاتوس"
},
"layout.footer.copyright": {
"message": "© {year} Rinth, Inc."
},
"layout.footer.legal": {
"message": "اوندڠ‌٢"
},
@@ -1019,6 +1397,15 @@
"layout.meta.og-description": {
"message": "تموءي دان تربيتکن کاندوڠن ماءينکرف‌ت!"
},
"layout.mobile.close-menu": {
"message": "Tutup menu"
},
"layout.mobile.open-menu": {
"message": "Buka menu"
},
"layout.nav.active-reports": {
"message": "Laporan yang aktif"
},
"layout.nav.analytics": {
"message": "اناليتيک"
},
@@ -1046,6 +1433,9 @@
"layout.nav.modrinth-home-page": {
"message": "لامن اوتام Modrinth"
},
"layout.nav.my-servers": {
"message": "Pelayan saya"
},
"layout.nav.organizations": {
"message": "اورݢانيساسي"
},
@@ -1091,27 +1481,342 @@
"moderation.technical.search.placeholder": {
"message": "چاري ڤنيلاين تيکنيکل..."
},
"muralpay.account-type.checking": {
"message": "Cek"
},
"muralpay.account-type.savings": {
"message": "Simpanan"
},
"muralpay.country.at": {
"message": "Austria"
},
"muralpay.country.be": {
"message": "Belgium"
},
"muralpay.country.cy": {
"message": "Cyprus"
},
"muralpay.country.de": {
"message": "Jerman"
},
"muralpay.country.ee": {
"message": "Estonia"
},
"muralpay.country.es": {
"message": "Sepanyol"
},
"muralpay.country.fi": {
"message": "Finland"
},
"muralpay.country.fr": {
"message": "Perancis"
},
"muralpay.country.gr": {
"message": "Yunani"
},
"muralpay.country.ie": {
"message": "Ireland"
},
"muralpay.country.it": {
"message": "Itali"
},
"muralpay.country.lt": {
"message": "Lithuania"
},
"muralpay.country.lu": {
"message": "Luxembourg"
},
"muralpay.country.lv": {
"message": "Latvia"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Belanda"
},
"muralpay.country.pt": {
"message": "Portugal"
},
"muralpay.country.sk": {
"message": "Slovakia"
},
"muralpay.document-type.national-id": {
"message": "ID Kebangsaan"
},
"muralpay.document-type.passport": {
"message": "Pasport"
},
"muralpay.document-type.resident-id": {
"message": "ID Penduduk"
},
"muralpay.document-type.ruc": {
"message": "RUC"
},
"muralpay.document-type.tax-id": {
"message": "ID cukai"
},
"muralpay.field.account-number": {
"message": "Nombor akaun"
},
"muralpay.field.account-number-cbu-cvu": {
"message": "Nombor akaun (CBU/CVU)"
},
"muralpay.field.account-number-cci": {
"message": "Nombor akaun (CCI)"
},
"muralpay.field.account-number-type": {
"message": "Jenis nombor akaun"
},
"muralpay.field.account-type": {
"message": "Jenis akaun"
},
"muralpay.field.bank-account-number": {
"message": "Nombor akaun"
},
"muralpay.field.branch-code": {
"message": "Kod cawangan"
},
"muralpay.field.clabe": {
"message": "CLABE"
},
"muralpay.field.country": {
"message": "Negara"
},
"muralpay.field.cpf-cnpj": {
"message": "CPF/CNPJ"
},
"muralpay.field.cuit-cuil": {
"message": "CUIT/CUIL"
},
"muralpay.field.document-type": {
"message": "Jenis dokumen"
},
"muralpay.field.iban": {
"message": "IBAN"
},
"muralpay.field.phone-number": {
"message": "Nombor telefon"
},
"muralpay.field.pix-email": {
"message": "E-mel PIX"
},
"muralpay.field.pix-key-type": {
"message": "Jenis kunci PIX"
},
"muralpay.field.pix-phone": {
"message": "Telefon PIX"
},
"muralpay.field.routing-number": {
"message": "Nombor penghalaan"
},
"muralpay.field.swift-bic": {
"message": "SWIFT/BIC"
},
"muralpay.field.wallet-address": {
"message": "Alamat dompet"
},
"muralpay.help.cbu-cvu": {
"message": "Clave Bancaria Uniforme atau Clave Virtual Uniforme"
},
"muralpay.help.cci": {
"message": "Código de Cuenta Interbancaria"
},
"muralpay.help.clabe": {
"message": "Clave Bancaria Estandarizada (Nombor akaun bank Mexico)"
},
"muralpay.help.cpf-cnpj": {
"message": "Nombor pengenalan cukai Brazil"
},
"muralpay.help.cuit-cuil": {
"message": "ID cukai Argentina"
},
"muralpay.help.iban": {
"message": "Nombor Akaun Bank Antarabangsa (IBAN)"
},
"muralpay.help.swift-bic": {
"message": "Kod Pengenalpastian Bank (BIC)"
},
"muralpay.pix-type.bank-account": {
"message": "Akaun bank"
},
"muralpay.pix-type.document": {
"message": "CPF/CNPJ"
},
"muralpay.pix-type.email": {
"message": "E-mel"
},
"muralpay.pix-type.phone": {
"message": "Nombor telefon"
},
"muralpay.placeholder.account-number": {
"message": "Masukkan nombor akaun"
},
"muralpay.placeholder.cbu-cvu": {
"message": "Masukkan CBU atau CVU"
},
"muralpay.placeholder.cbu-cvu-type": {
"message": "CBU atau CVU"
},
"muralpay.placeholder.cci": {
"message": "Masukkan CCI 20 digit"
},
"muralpay.placeholder.cuit-cuil": {
"message": "Masukkan CUIT atau CUIL"
},
"muralpay.placeholder.enter-account-number": {
"message": "Masukkan nombor akaun"
},
"muralpay.placeholder.enter-branch-code": {
"message": "Masukkan kod cawangan"
},
"muralpay.placeholder.enter-clabe": {
"message": "Masukkan CLABE 18 digit"
},
"muralpay.placeholder.enter-cpf-cnpj": {
"message": "Masukkan CPF atau CNPJ"
},
"muralpay.placeholder.enter-iban": {
"message": "Masukkan IBAN"
},
"muralpay.placeholder.enter-pix-email": {
"message": "Masukkan e-mel PIX"
},
"muralpay.placeholder.enter-routing-number": {
"message": "Masukkan nombor penghalaan 9 digit"
},
"muralpay.placeholder.enter-swift-bic": {
"message": "Masukkan kod SWIFT/BIC"
},
"muralpay.placeholder.iban-crc": {
"message": "Masukkan IBAN Costa Rica"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
"muralpay.placeholder.pix-phone": {
"message": "+55..."
},
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"muralpay.rail.fiat-ars.name": {
"message": "Pindahan Bank (ARS)"
},
"muralpay.rail.fiat-brl.name": {
"message": "Pindahan PIX (BRL)"
},
"muralpay.rail.fiat-clp.name": {
"message": "Pindahan Bank (CLP)"
},
"muralpay.rail.fiat-cop.name": {
"message": "Pindahan Bank (COP)"
},
"muralpay.rail.fiat-crc.name": {
"message": "Pindahan Bank (CRC)"
},
"muralpay.rail.fiat-eur.name": {
"message": "Pindahan Bank (EUR)"
},
"muralpay.rail.fiat-mxn.name": {
"message": "Pindahan Bank (MXN)"
},
"muralpay.rail.fiat-pen.name": {
"message": "Pindahan Bank (PEN)"
},
"muralpay.rail.fiat-usd-peru.name": {
"message": "Pindahan Bank (USD - Peru)"
},
"muralpay.rail.fiat-usd.name": {
"message": "Pindahan Bank (USD)"
},
"muralpay.rail.fiat-zar.name": {
"message": "Pindahan Bank (ZAR)"
},
"muralpay.rail.usdc-base.name": {
"message": "USDC (Base)"
},
"muralpay.rail.usdc-celo.name": {
"message": "USDC (Celo)"
},
"muralpay.rail.usdc-ethereum.name": {
"message": "USDC (Ethereum)"
},
"muralpay.rail.usdc-polygon.name": {
"message": "Kripto (USDC)"
},
"muralpay.warning.wallet-address": {
"message": "Semak semula alamat dompet anda. Dana yang dihantar ke alamat yang salah tidak boleh dipulihkan."
},
"profile.bio.fallback.creator": {
"message": "سأورڠ ڤنچيڤتا Modrinth."
},
"profile.bio.fallback.user": {
"message": "سأورڠ ڤڠݢونا Modrinth."
},
"profile.button.billing": {
"message": "اوروس ڤڠبيلن ڤڠݢونا"
},
"profile.button.edit-role": {
"message": "سونتيڠ ڤرانن"
},
"profile.button.info": {
"message": "ليهت بوتيرن ڤڠݢونا"
},
"profile.button.manage-projects": {
"message": "اوروس ڤروجيک"
},
"profile.button.remove-affiliate": {
"message": "Alih keluar rakan afiliasi"
},
"profile.button.set-affiliate": {
"message": "Tetapkan sebagai rakan afiliasi"
},
"profile.details.label.auth-providers": {
"message": "ڤڽديا ڤڠصحن"
},
"profile.details.label.email": {
"message": "إي-ميل"
},
"profile.details.label.has-password": {
"message": "ممڤوڽاءي کات لالوان"
},
"profile.details.label.has-totp": {
"message": "ممڤوڽاءي TOTP"
},
"profile.details.label.payment-methods": {
"message": "قاعده ڤمبايرن"
},
"profile.details.tooltip.email-not-verified": {
"message": "إي-ميل تيدق دصحکن"
},
"profile.details.tooltip.email-verified": {
"message": "إي-ميل دصحکن"
},
"profile.error.not-found": {
"message": "ڤڠݢونا تيدق دجومڤاءي"
},
"profile.joined-at": {
"message": "تله مڽرتاءي <date>{ago}</date>"
"profile.label.affiliate": {
"message": "Afiliasi"
},
"profile.label.badges": {
"message": "لنچان"
},
"profile.label.collection": {
"message": "کوليکسي"
},
"profile.label.details": {
"message": "بوتيرن"
},
"profile.label.downloads": {
"message": "{count} {count, plural, other {موات تورون}}"
},
"profile.label.joined": {
"message": "تله مڽرتاءي ڤد"
},
"profile.label.no": {
"message": "تيدق"
},
"profile.label.no-collections": {
"message": "ڤڠݢونا اين تيدق مميليقي سبارڠ کوليکسي!"
},
@@ -1127,18 +1832,21 @@
"profile.label.organizations": {
"message": "اورݢانيساسي"
},
"profile.label.projects": {
"message": "{count} {count, plural, other {ڤروجيک}}"
},
"profile.label.saving": {
"message": "سدڠ مڽيمڤن..."
},
"profile.label.yes": {
"message": "يا"
},
"profile.meta.description": {
"message": "موات تورون ڤروجيک ميليق {username} دModrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - موات تورون ڤروجيک ميليق {username} دModrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, other {<stat>{count}</stat> موات تورون}}"
},
"profile.stats.projects": {
"message": "{count, plural, other {<stat>{count}</stat> ڤروجيک}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, other {<stat>{count}</stat> ڤڠيکوت ڤروجيک}}"
},
@@ -1188,7 +1896,7 @@
"message": "سره سمولا اونتوق ڤنيلاين"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "ڤروجيک اندا تله {status} اوليه ستف Modrinth. دالم کباڽقن کيس⹁ اندا بوليه مڽرهکن سمولا اونتوق سيمقن سلڤس مناڠني ميسيج کاکيتاڠن."
"message": "Projek anda telah {status, select, rejected {ditolak} withheld {ditahan} other {{status}}} oleh staf Modrinth. Dalam kebanyakan kes, anda boleh menyerahkan semula untuk semakan selepas menangani masalah yang dikemukakan dalam mesej kakitangan."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "اندا مستي ملڠکڤکن لڠکه٢ يڠ دڤرلوکن دالم سناراي سيمق ڤنربيتن!"
@@ -1595,18 +2303,6 @@
"report.submit": {
"message": "سيرهکن لاڤورن"
},
"revenue.transfers.total": {
"message": "اندا تله مڠلوارکن {amount} سچارا کسلوروهن."
},
"revenue.transfers.total.method": {
"message": "اندا تله مڠلوارکن {amount} ملالوءي {method}."
},
"revenue.transfers.total.year": {
"message": "اندا تله مڠلوارکن {amount} ڤد تاهون {year}."
},
"revenue.transfers.total.year_method": {
"message": "اندا تله مڠلوارکن {amount} ڤد تاهون {year} ملالوءي {method}."
},
"scopes.analytics.description": {
"message": "مڠکسيس داتا اناليتيس اندا"
},
@@ -1865,9 +2561,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "ڤموليهن ساندرن سدڠ دجالنکن"
},
"servers.backups.item.already-preparing": {
"message": "سوده مڽدياکن ساندرن اونتوق موات تورون"
},
"servers.backups.item.automated": {
"message": "داءوتوماتيککن"
},
@@ -1877,9 +2570,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "ݢاݢل منچيڤتا ساندرن"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "ݢاݢل مڽدياکن موات تورون"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "ݢاݢل مموليهکن درڤد ساندرن"
},
@@ -1889,15 +2579,6 @@
"servers.backups.item.locked": {
"message": "دکونچي"
},
"servers.backups.item.prepare-download": {
"message": "سدياکن موات تورون"
},
"servers.backups.item.prepare-download-again": {
"message": "چوبا سدياکن لاݢي"
},
"servers.backups.item.preparing-download": {
"message": "سدڠ مڽدياکن موات تورون..."
},
"servers.backups.item.queued-for-backup": {
"message": "دالم باريسن اونتوق دساندر"
},

View File

@@ -566,6 +566,27 @@
"create.project.visibility-unlisted": {
"message": "Tidak disenaraikan"
},
"dashboard.affiliate-links.create.button": {
"message": "Cipta pautan afiliasi"
},
"dashboard.affiliate-links.error.title": {
"message": "Ralat semasa memuatkan pautan afiliasi"
},
"dashboard.affiliate-links.header": {
"message": "Pautan afiliasi anda"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "Ini akan membatalkan kod afiliasi `{id}` secara kekal dan sebarang pautan sedia ada dengan kod ini yang telah dikongsi tidak lagi sah."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Batalkan"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "Adakah anda pasti mahu membatalkan pautan afiliasi anda yang bernama ''{title}''?"
},
"dashboard.affiliate-links.search": {
"message": "Cari pautan afiliasi..."
},
"dashboard.collections.button.create-new": {
"message": "Cipta baharu"
},
@@ -578,6 +599,18 @@
"dashboard.collections.long-title": {
"message": "Koleksi anda"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Muat turun {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "Borang cukai {formType} anda telah berjaya dihantar!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Anda boleh mengeluarkan wang dengan bebas sekarang. Jika anda mempunyai soalan atau perlu mengemas kini butiran anda <support-link>hubungi sokongan</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Selesai! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Entiti asing bermaksud entiti perniagaan yang dianjurkan di luar Amerika Syarikat (seperti perbadanan, perkongsian atau LLC bukan AS)."
},
@@ -602,6 +635,336 @@
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Adakah anda warganegara AS?"
},
"dashboard.creator-withdraw-modal.complete-tax-form": {
"message": "Lengkapkan borang cukai"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Teruskan dengan had"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Butiran"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Amaun"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "Kadar FX"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Yuran"
},
"dashboard.creator-withdraw-modal.fee-breakdown-net-amount": {
"message": "Amaun bersih"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Entiti bisnes"
},
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Entiti bisnes merujuk kepada organisasi terdaftar seperti perbadanan, perkongsian atau LLC."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "Adakah anda sedang mengeluarkan wang sebagai seorang individu atau sebuah perniagaan?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Individu persendirian"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Pilih negara anda"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Cari negara..."
},
"dashboard.creator-withdraw-modal.method-selection.error-text": {
"message": "Tidak dapat mengambil kaedah pembayaran yang tersedia. Sila cuba lagi kemudian."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Gagal memuatkan kaedah pembayaran"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Rantau"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Sesetengah kaedah pembayaran tidak tersedia di rantau tertentu."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Pilih kaedah pengeluaran"
},
"dashboard.creator-withdraw-modal.method-selection.tax-limit-warning": {
"message": "Had pengeluaran anda ialah <b>{amount}</b>, <tax-link>lengkapkan borang cukai</tax-link> untuk mengeluarkan lebih banyak wang."
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Pemilik akaun"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Syiling"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Sahkan alamat dompet anda"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id": {
"message": "Nombor ID kebangsaan"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder": {
"message": "Masukkan nombor ID kebangsaan"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport": {
"message": "Nombor pasport"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder": {
"message": "Masukkan nombor pasport"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id": {
"message": "Masukkan nombor ID penduduk"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder": {
"message": "Masukkan nombor ID penduduk"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc": {
"message": "Nombor RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder": {
"message": "Masukkan nombor RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id": {
"message": "Nombor ID cukai"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder": {
"message": "Masukkan nombor ID cukai"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Rangkaian"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "Anda hampir mencapai ambang pengeluaran. Anda boleh mengeluarkan <b>{amountRemaining}</b> sekarang, tetapi borang cukai diperlukan untuk mengeluarkan lebih banyak wang."
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Akaun"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Putuskan sambungan akaun"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Kaedah pembayaran"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "Akaun PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Sambungkan akaun PayPal anda untuk menerima pembayaran secara langsung."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Simpan"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Nama pemegang Venmo berjaya disimpan!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Disimpan"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Daftar masuk dengan PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-description": {
"message": "Masukkan nama pemegang Venmo anda untuk menerima pembayaran."
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle": {
"message": "Nama pemegang Venmo"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@nama-pengguna"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Kaedah"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Butiran Akaun"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Pengesahan"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Borang cukai"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Butiran"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "Untuk mengeluarkan baki penuh anda yang tersedia sebanyak <b>{available}</b>, sila lengkapkan borang di bawah. Ia diperlukan untuk pelaporan cukai dan hanya perlu dilakukan sekali sahaja."
},
"dashboard.creator-withdraw-modal.tax-form-required.body-with-limit": {
"message": "Anda mesti melengkapkan borang W-9 atau W-8 untuk rekod cukai Modrinth supaya kami kekal mematuhi peraturan cukai."
},
"dashboard.creator-withdraw-modal.tax-form-required.header": {
"message": "Borang cukai diperlukan"
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Kaedah pembayaran"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Ganjaran"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder": {
"message": "Pilih ganjaran"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Ganjaran"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "E-mel yang belum disahkan"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-message": {
"message": "E-mel penghantaran yang anda masukkan tidak dikaitkan dengan akaun Modrinth anda. Modrinth tidak dapat mendapatkan semula ganjaran yang dihantar ke alamat e-mel yang salah."
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Yuran lebih rendah tersedia"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-message": {
"message": "Anda memilih USD untuk PayPal Antarabangsa. <direct-paypal-link>Tukar kepada PayPal langsung</direct-paypal-link> untuk yuran yang lebih baik (≈2% dan bukannya ≈6%)."
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Keluarkan"
},
"dashboard.creator-withdraw-modal.withdraw-limit": {
"message": "Had pengeluaran wang"
},
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "Anda telah menggunakan had pengeluaran anda sebanyak <b>{withdrawLimit}</b>. Anda mesti melengkapkan borang cukai untuk mengeluarkan lebih banyak wang."
},
"dashboard.revenue.available-now": {
"message": "Tersedia sekarang"
},
"dashboard.revenue.balance": {
"message": "Baki"
},
"dashboard.revenue.estimated-tooltip.msg1": {
"message": "Anggaran hasil pendapatan mungkin tertakluk kepada perubahan sehingga ia tersedia."
},
"dashboard.revenue.estimated-tooltip.msg2": {
"message": "Klik untuk membaca tentang cara Modrinth mengendalikan pendapatan anda."
},
"dashboard.revenue.estimated-with-date": {
"message": "Anggaran {date}"
},
"dashboard.revenue.processing": {
"message": "Memproses"
},
"dashboard.revenue.processing.tooltip": {
"message": "Hasil pendapatan kekal dalam pemprosesan sehingga akhir bulan, dan kemudian akan tersedia 60 hari kemudian."
},
"dashboard.revenue.stats.received": {
"message": "Diterima"
},
"dashboard.revenue.stats.transactions": {
"message": "Transaksi"
},
"dashboard.revenue.stats.withdrawn": {
"message": "Telah dikeluarkan"
},
"dashboard.revenue.tos": {
"message": "Dengan memuat naik projek ke Modrinth dan mengeluarkan wang daripada akaun anda, anda bersetuju dengan <terms-link>Terma Program Ganjaran</terms-link> kami. Ketahui lebih lanjut tentang <info-link>Program Ganjaran</info-link> ini."
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Muat turun sebagai CSV"
},
"dashboard.revenue.transactions.header": {
"message": "Transaksi"
},
"dashboard.revenue.transactions.none": {
"message": "Tiada transaksi"
},
"dashboard.revenue.transactions.none.desc": {
"message": "Pembayaran dan pengeluaran anda akan dipaparkan di sini."
},
"dashboard.revenue.transactions.see-all": {
"message": "Lihat semua"
},
"dashboard.revenue.withdraw.blocked-tin-mismatch": {
"message": "Pengeluaran anda telah dikunci buat sementara waktu kerana TIN atau SSN anda tidak sepadan dengan rekod IRS. Sila hubungi sokongan untuk menetapkan semula dan menghantar semula borang cukai anda."
},
"dashboard.revenue.withdraw.card.description": {
"message": "Keluarkan wang daripada baki yang tersedia kepada mana-mana kaedah pembayaran."
},
"dashboard.revenue.withdraw.card.title": {
"message": "Pengeluaran"
},
"dashboard.revenue.withdraw.header": {
"message": "Pengeluaran"
},
"dashboard.withdraw.completion.account": {
"message": "Akaun"
},
"dashboard.withdraw.completion.amount": {
"message": "Amaun"
},
"dashboard.withdraw.completion.close-button": {
"message": "Tutup"
},
"dashboard.withdraw.completion.date": {
"message": "Tarikh"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "Anda akan menerima e-mel di <b>{email}</b> dengan arahan untuk menebus pengeluaran anda."
},
"dashboard.withdraw.completion.exchange-rate": {
"message": "Kadar pertukaran"
},
"dashboard.withdraw.completion.fee": {
"message": "Yuran"
},
"dashboard.withdraw.completion.method": {
"message": "Kaedah"
},
"dashboard.withdraw.completion.net-amount": {
"message": "Amaun bersih"
},
"dashboard.withdraw.completion.recipient": {
"message": "Penerima"
},
"dashboard.withdraw.completion.title": {
"message": "Pengeluaran selesai"
},
"dashboard.withdraw.completion.transactions-button": {
"message": "Transaksi"
},
"dashboard.withdraw.completion.wallet": {
"message": "Dompet"
},
"dashboard.withdraw.error.generic.text": {
"message": "Kami tidak dapat menghantar permintaan pengeluaran anda, sila semak butiran anda atau hubungi sokongan."
},
"dashboard.withdraw.error.generic.title": {
"message": "Tidak dapat mengeluarkan wang"
},
"dashboard.withdraw.error.invalid-address.text": {
"message": "Alamat yang anda berikan tidak dapat disahkan. Sila semak butiran alamat anda."
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Pengesahan alamat gagal"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": "Butiran akaun bank yang anda berikan tidak sah. Sila sahkan maklumat anda."
},
"dashboard.withdraw.error.invalid-bank.title": {
"message": "Butiran bank tidak sah"
},
"dashboard.withdraw.error.invalid-wallet.text": {
"message": "Alamat dompet kripto yang anda berikan tidak sah. Sila semak semula dan cuba lagi."
},
"dashboard.withdraw.error.invalid-wallet.title": {
"message": "Alamat dompet tidak sah"
},
"dashboard.withdraw.error.minimum-not-met.text": {
"message": "Amaun pengeluaran (selepas yuran) tidak memenuhi keperluan minimum. Sila tingkatkan amaun pengeluaran anda."
},
"dashboard.withdraw.error.minimum-not-met.title": {
"message": "Amaun terlalu rendah"
},
"dashboard.withdraw.error.tax-form.text": {
"message": "Anda mesti melengkapkan borang cukai untuk menyerahkan permintaan pengeluaran anda."
},
"dashboard.withdraw.error.tax-form.title": {
"message": "Sila lengkapkan borang cukai"
},
"error.collection.404.list_item.1": {
"message": "Anda mungkin tersalah taip URL koleksi."
},
@@ -857,6 +1220,9 @@
"layout.action.lookup-by-email": {
"message": "Cari melalui e-mel"
},
"layout.action.manage-affiliates": {
"message": "Urus pautan afiliasi"
},
"layout.action.manage-server-notices": {
"message": "Urus notis pelayan"
},
@@ -917,6 +1283,15 @@
"layout.banner.tax.title": {
"message": "Borang cukai diperlukan"
},
"layout.banner.tin-mismatch.action": {
"message": "Hubungi sokongan"
},
"layout.banner.tin-mismatch.description": {
"message": "Pengeluaran anda telah dikunci buat sementara waktu kerana TIN atau SSN anda tidak sepadan dengan rekod IRS. Sila hubungi sokongan untuk menetapkan semula dan menghantar semula borang cukai anda."
},
"layout.banner.tin-mismatch.title": {
"message": "Borang cukai gagal"
},
"layout.banner.verify-email.action": {
"message": "Hantar semula e-mel pengesahan"
},
@@ -941,6 +1316,9 @@
"layout.footer.about.status": {
"message": "Status"
},
"layout.footer.copyright": {
"message": "© {year} Rinth, Inc."
},
"layout.footer.legal": {
"message": "Undang-undang"
},
@@ -1019,6 +1397,15 @@
"layout.meta.og-description": {
"message": "Temui dan terbitkan kandungan Minecraft!"
},
"layout.mobile.close-menu": {
"message": "Tutup menu"
},
"layout.mobile.open-menu": {
"message": "Buka menu"
},
"layout.nav.active-reports": {
"message": "Laporan yang aktif"
},
"layout.nav.analytics": {
"message": "Analitik"
},
@@ -1046,6 +1433,9 @@
"layout.nav.modrinth-home-page": {
"message": "Laman utama Modrinth"
},
"layout.nav.my-servers": {
"message": "Pelayan saya"
},
"layout.nav.organizations": {
"message": "Organisasi"
},
@@ -1091,27 +1481,342 @@
"moderation.technical.search.placeholder": {
"message": "Cari penilaian teknikal..."
},
"muralpay.account-type.checking": {
"message": "Cek"
},
"muralpay.account-type.savings": {
"message": "Simpanan"
},
"muralpay.country.at": {
"message": "Austria"
},
"muralpay.country.be": {
"message": "Belgium"
},
"muralpay.country.cy": {
"message": "Cyprus"
},
"muralpay.country.de": {
"message": "Jerman"
},
"muralpay.country.ee": {
"message": "Estonia"
},
"muralpay.country.es": {
"message": "Sepanyol"
},
"muralpay.country.fi": {
"message": "Finland"
},
"muralpay.country.fr": {
"message": "Perancis"
},
"muralpay.country.gr": {
"message": "Yunani"
},
"muralpay.country.ie": {
"message": "Ireland"
},
"muralpay.country.it": {
"message": "Itali"
},
"muralpay.country.lt": {
"message": "Lithuania"
},
"muralpay.country.lu": {
"message": "Luxembourg"
},
"muralpay.country.lv": {
"message": "Latvia"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Belanda"
},
"muralpay.country.pt": {
"message": "Portugal"
},
"muralpay.country.sk": {
"message": "Slovakia"
},
"muralpay.document-type.national-id": {
"message": "ID Kebangsaan"
},
"muralpay.document-type.passport": {
"message": "Pasport"
},
"muralpay.document-type.resident-id": {
"message": "ID Penduduk"
},
"muralpay.document-type.ruc": {
"message": "RUC"
},
"muralpay.document-type.tax-id": {
"message": "ID cukai"
},
"muralpay.field.account-number": {
"message": "Nombor akaun"
},
"muralpay.field.account-number-cbu-cvu": {
"message": "Nombor akaun (CBU/CVU)"
},
"muralpay.field.account-number-cci": {
"message": "Nombor akaun (CCI)"
},
"muralpay.field.account-number-type": {
"message": "Jenis nombor akaun"
},
"muralpay.field.account-type": {
"message": "Jenis akaun"
},
"muralpay.field.bank-account-number": {
"message": "Nombor akaun"
},
"muralpay.field.branch-code": {
"message": "Kod cawangan"
},
"muralpay.field.clabe": {
"message": "CLABE"
},
"muralpay.field.country": {
"message": "Negara"
},
"muralpay.field.cpf-cnpj": {
"message": "CPF/CNPJ"
},
"muralpay.field.cuit-cuil": {
"message": "CUIT/CUIL"
},
"muralpay.field.document-type": {
"message": "Jenis dokumen"
},
"muralpay.field.iban": {
"message": "IBAN"
},
"muralpay.field.phone-number": {
"message": "Nombor telefon"
},
"muralpay.field.pix-email": {
"message": "E-mel PIX"
},
"muralpay.field.pix-key-type": {
"message": "Jenis kunci PIX"
},
"muralpay.field.pix-phone": {
"message": "Telefon PIX"
},
"muralpay.field.routing-number": {
"message": "Nombor penghalaan"
},
"muralpay.field.swift-bic": {
"message": "SWIFT/BIC"
},
"muralpay.field.wallet-address": {
"message": "Alamat dompet"
},
"muralpay.help.cbu-cvu": {
"message": "Clave Bancaria Uniforme atau Clave Virtual Uniforme"
},
"muralpay.help.cci": {
"message": "Código de Cuenta Interbancaria"
},
"muralpay.help.clabe": {
"message": "Clave Bancaria Estandarizada (Nombor akaun bank Mexico)"
},
"muralpay.help.cpf-cnpj": {
"message": "Nombor pengenalan cukai Brazil"
},
"muralpay.help.cuit-cuil": {
"message": "ID cukai Argentina"
},
"muralpay.help.iban": {
"message": "Nombor Akaun Bank Antarabangsa (IBAN)"
},
"muralpay.help.swift-bic": {
"message": "Kod Pengenalpastian Bank (BIC)"
},
"muralpay.pix-type.bank-account": {
"message": "Akaun bank"
},
"muralpay.pix-type.document": {
"message": "CPF/CNPJ"
},
"muralpay.pix-type.email": {
"message": "E-mel"
},
"muralpay.pix-type.phone": {
"message": "Nombor telefon"
},
"muralpay.placeholder.account-number": {
"message": "Masukkan nombor akaun"
},
"muralpay.placeholder.cbu-cvu": {
"message": "Masukkan CBU atau CVU"
},
"muralpay.placeholder.cbu-cvu-type": {
"message": "CBU atau CVU"
},
"muralpay.placeholder.cci": {
"message": "Masukkan CCI 20 digit"
},
"muralpay.placeholder.cuit-cuil": {
"message": "Masukkan CUIT atau CUIL"
},
"muralpay.placeholder.enter-account-number": {
"message": "Masukkan nombor akaun"
},
"muralpay.placeholder.enter-branch-code": {
"message": "Masukkan kod cawangan"
},
"muralpay.placeholder.enter-clabe": {
"message": "Masukkan CLABE 18 digit"
},
"muralpay.placeholder.enter-cpf-cnpj": {
"message": "Masukkan CPF atau CNPJ"
},
"muralpay.placeholder.enter-iban": {
"message": "Masukkan IBAN"
},
"muralpay.placeholder.enter-pix-email": {
"message": "Masukkan e-mel PIX"
},
"muralpay.placeholder.enter-routing-number": {
"message": "Masukkan nombor penghalaan 9 digit"
},
"muralpay.placeholder.enter-swift-bic": {
"message": "Masukkan kod SWIFT/BIC"
},
"muralpay.placeholder.iban-crc": {
"message": "Masukkan IBAN Costa Rica"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
"muralpay.placeholder.pix-phone": {
"message": "+55..."
},
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"muralpay.rail.fiat-ars.name": {
"message": "Pindahan Bank (ARS)"
},
"muralpay.rail.fiat-brl.name": {
"message": "Pindahan PIX (BRL)"
},
"muralpay.rail.fiat-clp.name": {
"message": "Pindahan Bank (CLP)"
},
"muralpay.rail.fiat-cop.name": {
"message": "Pindahan Bank (COP)"
},
"muralpay.rail.fiat-crc.name": {
"message": "Pindahan Bank (CRC)"
},
"muralpay.rail.fiat-eur.name": {
"message": "Pindahan Bank (EUR)"
},
"muralpay.rail.fiat-mxn.name": {
"message": "Pindahan Bank (MXN)"
},
"muralpay.rail.fiat-pen.name": {
"message": "Pindahan Bank (PEN)"
},
"muralpay.rail.fiat-usd-peru.name": {
"message": "Pindahan Bank (USD - Peru)"
},
"muralpay.rail.fiat-usd.name": {
"message": "Pindahan Bank (USD)"
},
"muralpay.rail.fiat-zar.name": {
"message": "Pindahan Bank (ZAR)"
},
"muralpay.rail.usdc-base.name": {
"message": "USDC (Base)"
},
"muralpay.rail.usdc-celo.name": {
"message": "USDC (Celo)"
},
"muralpay.rail.usdc-ethereum.name": {
"message": "USDC (Ethereum)"
},
"muralpay.rail.usdc-polygon.name": {
"message": "Kripto (USDC)"
},
"muralpay.warning.wallet-address": {
"message": "Semak semula alamat dompet anda. Dana yang dihantar ke alamat yang salah tidak boleh dipulihkan."
},
"profile.bio.fallback.creator": {
"message": "Seorang pencipta Modrinth."
},
"profile.bio.fallback.user": {
"message": "Seorang pengguna Modrinth."
},
"profile.button.billing": {
"message": "Urus pengebilan pengguna"
},
"profile.button.edit-role": {
"message": "Sunting peranan"
},
"profile.button.info": {
"message": "Lihat butiran pengguna"
},
"profile.button.manage-projects": {
"message": "Urus projek"
},
"profile.button.remove-affiliate": {
"message": "Alih keluar rakan afiliasi"
},
"profile.button.set-affiliate": {
"message": "Tetapkan sebagai rakan afiliasi"
},
"profile.details.label.auth-providers": {
"message": "Penyedia pengesahan"
},
"profile.details.label.email": {
"message": "E-mel"
},
"profile.details.label.has-password": {
"message": "Mempunyai kata laluan"
},
"profile.details.label.has-totp": {
"message": "Mempunyai TOTP"
},
"profile.details.label.payment-methods": {
"message": "Kaedah pembayaran"
},
"profile.details.tooltip.email-not-verified": {
"message": "E-mel tidak disahkan"
},
"profile.details.tooltip.email-verified": {
"message": "E-mel disahkan"
},
"profile.error.not-found": {
"message": "Pengguna tidak dijumpai"
},
"profile.joined-at": {
"message": "Telah menyertai <date>{ago}</date>"
"profile.label.affiliate": {
"message": "Afiliasi"
},
"profile.label.badges": {
"message": "Lencana"
},
"profile.label.collection": {
"message": "Koleksi"
},
"profile.label.details": {
"message": "Butiran"
},
"profile.label.downloads": {
"message": "{count} {count, plural, other {muat turun}}"
},
"profile.label.joined": {
"message": "Telah menyertai pada"
},
"profile.label.no": {
"message": "Tidak"
},
"profile.label.no-collections": {
"message": "Pengguna ini tidak memiliki sebarang koleksi!"
},
@@ -1127,18 +1832,21 @@
"profile.label.organizations": {
"message": "Organisasi"
},
"profile.label.projects": {
"message": "{count} {count, plural, other {projek}}"
},
"profile.label.saving": {
"message": "Sedang menyimpan..."
},
"profile.label.yes": {
"message": "Ya"
},
"profile.meta.description": {
"message": "Muat turun projek milik {username} di Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Muat turun projek milik {username} di Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, other {<stat>{count}</stat> muat turun}}"
},
"profile.stats.projects": {
"message": "{count, plural, other {<stat>{count}</stat> projek}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, other {<stat>{count}</stat> pengikut projek}}"
},
@@ -1188,7 +1896,7 @@
"message": "Serah semula untuk penilaian"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Projek anda telah {status} oleh staf Modrinth. Dalam kebanyakan kes, anda boleh menyerahkan semula untuk semakan selepas menangani mesej kakitangan."
"message": "Projek anda telah {status, select, rejected {ditolak} withheld {ditahan} other {{status}}} oleh staf Modrinth. Dalam kebanyakan kes, anda boleh menyerahkan semula untuk semakan selepas menangani masalah yang dikemukakan dalam mesej kakitangan."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Anda mesti melengkapkan langkah-langkah yang diperlukan dalam senarai semak penerbitan!"
@@ -1595,18 +2303,6 @@
"report.submit": {
"message": "Serahkan laporan"
},
"revenue.transfers.total": {
"message": "Anda telah mengeluarkan {amount} secara keseluruhan."
},
"revenue.transfers.total.method": {
"message": "Anda telah mengeluarkan {amount} melalui {method}."
},
"revenue.transfers.total.year": {
"message": "Anda telah mengeluarkan {amount} pada tahun {year}."
},
"revenue.transfers.total.year_method": {
"message": "Anda telah mengeluarkan {amount} pada tahun {year} melalui {method}."
},
"scopes.analytics.description": {
"message": "Mengakses data analitis anda"
},
@@ -1865,9 +2561,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Pemulihan sandaran sedang dijalankan"
},
"servers.backups.item.already-preparing": {
"message": "Sudah menyediakan sandaran untuk muat turun"
},
"servers.backups.item.automated": {
"message": "Diautomatikkan"
},
@@ -1877,9 +2570,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Gagal mencipta sandaran"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Gagal menyediakan muat turun"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Gagal memulihkan daripada sandaran"
},
@@ -1889,15 +2579,6 @@
"servers.backups.item.locked": {
"message": "Dikunci"
},
"servers.backups.item.prepare-download": {
"message": "Sediakan muat turun"
},
"servers.backups.item.prepare-download-again": {
"message": "Cuba sediakan lagi"
},
"servers.backups.item.preparing-download": {
"message": "Sedang menyediakan muat turun..."
},
"servers.backups.item.queued-for-backup": {
"message": "Dalam barisan untuk disandar"
},
@@ -2178,7 +2859,7 @@
"message": "Cipta PAT"
},
"settings.pats.description": {
"message": "PAT boleh digunakan untuk mengakses API Modrinth. Untuk mendapatkan maklumat lanjut, lihat <doc-link>Dokumentasi API Modrinth</doc-link>. Ia boleh dibuat dan ditarik balik pada bila-bila masa."
"message": "PAT boleh digunakan untuk mengakses API Modrinth. Untuk mendapatkan maklumat lanjut, lihat <doc-link>Dokumentasi API Modrinth</doc-link>. Ia boleh dibuat dan dibatalkan pada bila-bila masa."
},
"settings.pats.modal.create.action": {
"message": "Cipta PAT"
@@ -2211,7 +2892,7 @@
"message": "Sunting token"
},
"settings.pats.token.action.revoke": {
"message": "Tarik balik token"
"message": "Batalkan token"
},
"settings.pats.token.expired-ago": {
"message": "Telah luput {ago}"
@@ -2250,7 +2931,7 @@
"message": "Nama pengguna"
},
"settings.sessions.action.revoke-session": {
"message": "Tarik balik sesi"
"message": "Batalkan sesi"
},
"settings.sessions.created-ago": {
"message": "Dicipta {ago}"

View File

@@ -1,4 +1,10 @@
{
"action.cancel": {
"message": "Annuleren"
},
"action.continue": {
"message": "Doorgaan"
},
"admin.billing.error.not-found": {
"message": "Gebruiker niet gevonden"
},
@@ -170,6 +176,9 @@
"app-marketing.features.youve-used-before": {
"message": "je hebt het al gezien"
},
"app-marketing.hero.app-screenshot-alt": {
"message": "Screenshot van de Modrinth App met een Cobblemon installatie geopend op de 'Content' pagina."
},
"app-marketing.hero.description": {
"message": "De Modrinth App is een unieke, openbare launcher waarmee je je favoriete mods kunt spelen en up-to-date houden, allemaal in één handig app."
},
@@ -410,6 +419,153 @@
"collection.title": {
"message": "{name} - Collectie"
},
"common.no": {
"message": "Nee"
},
"common.yes": {
"message": "Ja"
},
"create.collection.cancel": {
"message": "Annuleren"
},
"create.collection.collection-info": {
"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"
},
"create.collection.error-title": {
"message": "Er is een fout opgetreden"
},
"create.collection.name-label": {
"message": "Naam"
},
"create.collection.name-placeholder": {
"message": "Vul collectienaam in"
},
"create.collection.summary-description": {
"message": "Eén of twee zinnen die je collectie beschrijven."
},
"create.collection.summary-label": {
"message": "Samenvatting"
},
"create.collection.summary-placeholder": {
"message": "Dit is een collectie van..."
},
"create.collection.title": {
"message": "Een collectie aanmaken"
},
"create.limit-alert.approaching-limit": {
"message": "{type} limiet is naderend ({current}/{max})"
},
"create.limit-alert.approaching-limit-description": {
"message": "Je staat op het punt het {type} limiet te bereiken, neem contact op met support als je meer dan {max} {typePlural} nodig hebt."
},
"create.limit-alert.contact-support": {
"message": "Neem contact op met support"
},
"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"
},
"create.limit-alert.type-organization": {
"message": "Organisatie"
},
"create.limit-alert.type-plural-collection": {
"message": "Collecties"
},
"create.limit-alert.type-plural-organization": {
"message": "Organisaties"
},
"create.limit-alert.type-plural-project": {
"message": "Projecten"
},
"create.limit-alert.type-project": {
"message": "Project"
},
"create.organization.cancel": {
"message": "Annuleren"
},
"create.organization.create-organization": {
"message": "Organisatie aanmaken"
},
"create.organization.error-title": {
"message": "Er is een fout opgetreden"
},
"create.organization.name-label": {
"message": "Naam"
},
"create.organization.name-placeholder": {
"message": "Vul organisatienaam in"
},
"create.organization.ownership-info": {
"message": "Jij wordt de eigenaar van deze organisatie, maar je kan andere leden uitnodigen en het beheer altijd overdragen."
},
"create.organization.summary-description": {
"message": "Eén of twee zinnen die je organisatie beschrijven."
},
"create.organization.summary-label": {
"message": "Samenvatting"
},
"create.organization.summary-placeholder": {
"message": "Een organisatie voor..."
},
"create.organization.title": {
"message": "Een organisatie aanmaken"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "Annuleren"
},
"create.project.create-project": {
"message": "Project aanmaken"
},
"create.project.error-title": {
"message": "Er is een fout opgetreden"
},
"create.project.name-label": {
"message": "Naam"
},
"create.project.name-placeholder": {
"message": "Voer projectnaam in..."
},
"create.project.summary-description": {
"message": "Eén of twee zinnen die je project beschrijven."
},
"create.project.summary-label": {
"message": "Samenvatting"
},
"create.project.summary-placeholder": {
"message": "Dit project..."
},
"create.project.title": {
"message": "Een project aanmaken"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-description": {
"message": "De zichtbaarheid van je project nadat het is goedgekeurd."
},
"create.project.visibility-label": {
"message": "Zichtbaarheid"
},
"create.project.visibility-private": {
"message": "Privé"
},
"create.project.visibility-public": {
"message": "Publiek"
},
"create.project.visibility-unlisted": {
"message": "Niet vermeld"
},
"dashboard.collections.button.create-new": {
"message": "Maak nieuwe"
},
@@ -422,6 +578,42 @@
"dashboard.collections.long-title": {
"message": "Je collecties"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Download {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "Je {formType} belastingformulier is succesvol verstuurd!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Je bent nu vrij om je geld over te boeken. Als je vragen hebt of je details wilt updaten, neem dan <support-link>contact op met support</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Je bent helemaal klaar! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Een buitenlandse entiteit is een bedrijf dat opgericht is buiten de Verenigde Staten (zoals een niet-Amerikaanse onderneming, partnerschap of LLC)"
},
"dashboard.creator-tax-form-modal.entity.foreign-entity": {
"message": "Buitenlandse entiteit"
},
"dashboard.creator-tax-form-modal.entity.private-individual": {
"message": "Particulier"
},
"dashboard.creator-tax-form-modal.entity.question": {
"message": "Ben je een particulier of maak je deel uit van een buitenlandse entiteit?"
},
"dashboard.creator-tax-form-modal.header": {
"message": "Belastingformulier"
},
"dashboard.creator-tax-form-modal.security.description": {
"message": "Modrinth maakt gebruik van de externe leverancier Track1099 om je belastingformulieren veilig te verzamelen en op te slaan. <security-link>Leer hier meer.</security-link>"
},
"dashboard.creator-tax-form-modal.security.header": {
"message": "Veiligheidsmaatregelen"
},
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Ben je een inwoner van de VS?"
},
"error.collection.404.list_item.1": {
"message": "U heeft mogelijk de URL van de collectie fout ingetypt."
},
@@ -443,6 +635,12 @@
"error.generic.404.title": {
"message": "Pagina niet gevonden"
},
"error.generic.451.subtitle": {
"message": "Deze pagina is geblokkeerd om juridische redenen, zoals censuur door de overheid of lopende juridische procedures."
},
"error.generic.451.title": {
"message": "Content niet beschikbaar om juridische redenen"
},
"error.generic.default.list_item.1": {
"message": "Controleer of Modrinth een storing heeft op onze <status-link>Status pagina</status-link>."
},
@@ -536,9 +734,15 @@
"landing.creator.feature.data-statistics.title": {
"message": "Cijfers en Statistieken "
},
"landing.creator.feature.discovery.description": {
"message": "Word ontdekt door duizenden gebruikers door middel van zoekresultaten, onze startpagina, Discord server, en nog veel meer mogelijkheden in de toekomst!"
},
"landing.creator.feature.discovery.title": {
"message": "Ontdekken"
},
"landing.creator.feature.diverse-ecosystem.description": {
"message": "Integreer je build-tools met behulp van Minotaur voor automatische uploads meteen wanneer je een nieuwe versie releaset. "
},
"landing.creator.feature.diverse-ecosystem.title": {
"message": "Een Diverse Ecosysteem "
},
@@ -548,15 +752,96 @@
"landing.creator.feature.monetization.title": {
"message": "Maak jouw projecten te gelden"
},
"landing.creator.feature.team-management.description": {
"message": "Nodig je teamleden uit en beheer rollen en machtigingen eenvoudig"
},
"landing.creator.feature.team-management.title": {
"message": "Team Beheer"
},
"landing.error.failedToLoadRandomProjects": {
"message": "Het is niet gelukt om willekeurige projecten te laden :("
},
"landing.feature.follow.description": {
"message": "Krijg een melding wanneer je favoriete projecten worden bijgewerkt en blijf op de hoogte."
},
"landing.feature.follow.heading": {
"message": "Volg je favoriete projecten"
},
"landing.feature.launcher.description": {
"message": "Modrinth's open-source API biedt launchers diepe integratie met Modrinth. Je kan Modrinth gebruikern via onze <link>eigen app</link> en populaire launchers als ATLauncher, MultiMC, en Prism Launcher."
},
"landing.feature.launcher.heading": {
"message": "Speel via je favoriete launcher"
},
"landing.feature.search.description": {
"message": "Dankzij Modrinth's razendsnelle zoekfunctie en filters vindt je wat je zoekt terwijl je typt."
},
"landing.feature.search.heading": {
"message": "Vind wat je zoekt, snel en eenvoudig"
},
"landing.heading.the-place-for-minecraft": {
"message": "Dé plek voor Minecraft {content}"
},
"landing.heading.the-place-for-minecraft.data-packs": {
"message": "data packs"
},
"landing.heading.the-place-for-minecraft.modpacks": {
"message": "modpacks"
},
"landing.heading.the-place-for-minecraft.mods": {
"message": "mods"
},
"landing.heading.the-place-for-minecraft.plugins": {
"message": "plugins"
},
"landing.heading.the-place-for-minecraft.resource-packs": {
"message": "bronpakketten"
},
"landing.heading.the-place-for-minecraft.servers": {
"message": "servers"
},
"landing.heading.the-place-for-minecraft.shaders": {
"message": "shaders"
},
"landing.launcher.atlauncher-label": {
"message": "ATLauncher"
},
"landing.launcher.graphic-alt": {
"message": "Een vereenvoudigde weergave van een Minecraft venster, met het Mojang Studios logo in Modrinth groen."
},
"landing.launcher.modrinth-app-label": {
"message": "Modrinth App"
},
"landing.launcher.prism-launcher-label": {
"message": "Prism Launcher"
},
"landing.notifications.heading": {
"message": "Meldingen"
},
"landing.notifications.received-time": {
"message": "Ontvangen {time}"
},
"landing.notifications.version-released": {
"message": "Versie {version} is gereleased voor {gameVersion}"
},
"landing.search.label": {
"message": "Zoeken"
},
"landing.search.placeholder": {
"message": "Zoeken..."
},
"landing.search.sort-by.label": {
"message": "Sorteer op"
},
"landing.section.for-creators.description": {
"message": "Geef je creaties een online thuis en bereik een groot publiek met toegewijde spelers."
},
"landing.section.for-creators.label": {
"message": "Voor Creators"
},
"landing.section.for-creators.tagline": {
"message": "Deel je content met de wereld"
},
"layout.action.change-theme": {
"message": "Thema aanpassen"
},
@@ -854,9 +1139,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Backup creatie in de werken"
},
"servers.backups.item.already-preparing": {
"message": "Al aan het voorbereiden van backup voor het downloaden"
},
"servers.backups.item.automated": {
"message": "Geautomatiseerd"
},
@@ -866,21 +1148,9 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Maken van back-up mislukt"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Voorbereiden van download mislukt"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Terugzetten van back-up mislukt"
},
"servers.backups.item.prepare-download": {
"message": "Download voorbereiden"
},
"servers.backups.item.prepare-download-again": {
"message": "Voorbereiden opnieuw proberen"
},
"servers.backups.item.preparing-download": {
"message": "Download voorbereiden..."
},
"servers.backups.item.queued-for-backup": {
"message": "Backup in de wachtrij"
},

View File

@@ -566,6 +566,27 @@
"create.project.visibility-unlisted": {
"message": "Niepubliczny"
},
"dashboard.affiliate-links.create.button": {
"message": "Utwórz link afiliacyjny"
},
"dashboard.affiliate-links.error.title": {
"message": "Błąd podczas ładowania linków afiliacyjnych"
},
"dashboard.affiliate-links.header": {
"message": "Twoje linki afiliacyjne"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "Unieważni to nieodwołalnie kod afiliacyjny `{id}`. Wszystkie udostępnione linki używające tego kodu zostaną unieważnione."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Unieważnij"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "Czy na pewno chcesz unieważnić link afiliacyjny \"{title}\"?"
},
"dashboard.affiliate-links.search": {
"message": "Szukaj linku afiliacyjnego..."
},
"dashboard.collections.button.create-new": {
"message": "Stwórz nową"
},
@@ -578,6 +599,18 @@
"dashboard.collections.long-title": {
"message": "Twoje kolekcje"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Pobierz {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "Twój formularz podatkowy {formType} został pomyślnie przesłany!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Możesz teraz wypłacać bez ograniczeń. Jeżeli masz pytania lub chcesz zaktualizować swoje dane, <support-link>skontaktuj się z obsługą</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Gotowe! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Podmiot zagraniczny oznacza podmiot gospodarczy zorganizowany poza Stanami Zjednoczonymi (na przykład korporacja spoza Stanów Zjednoczonych, spółka osobowa bądź sp. z o.o.)."
},
@@ -602,6 +635,339 @@
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Czy jesteś obywatelem Stanów Zjednoczonych?"
},
"dashboard.creator-withdraw-modal.complete-tax-form": {
"message": "Wypełnij formularz podatkowy"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Kontynuuj z limitem"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Szczegóły"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Kwota"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "Kurs walutowy"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Opłata"
},
"dashboard.creator-withdraw-modal.fee-breakdown-net-amount": {
"message": "Kwota netto"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Podmiot gospodarczy"
},
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Podmiot gospodarczy to na przykład korporacja, spółka osobowa bądź sp. z o.o."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "Czy wypłacasz jako osoba prywatna, czy jako podmiot gospodarczy?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Osoba prywatna"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Wybierz swój kraj"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Szukaj kraju..."
},
"dashboard.creator-withdraw-modal.method-selection.error-text": {
"message": "Nie udało się odczytać dostępnych metod płatniczych. Spróbuj ponownie później."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Nie udało się odczytać dostępnych metod płatniczych"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Region"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Niektóre sposoby wypłacania nie są dostępne w niektórych regionach."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Wybierz metodę wypłacania"
},
"dashboard.creator-withdraw-modal.method-selection.tax-limit-warning": {
"message": "Twój limit wypłat wynosi <b>{amount}</b>, <tax-link>wypełnij formularz podatkowy</tax-link> by wypłacić więcej."
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Właściciel konta"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Waluta"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Potwierdź adres portfela"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id": {
"message": "Numer identyfikatora krajowego"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder": {
"message": "Podaj numer identyfikatora krajowego"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport": {
"message": "Numer paszportu"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder": {
"message": "Podaj numer paszportu"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id": {
"message": "Numer identyfikatora rezydenta"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder": {
"message": "Podaj numer identyfikatora rezydenta"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc": {
"message": "Numer RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder": {
"message": "Podaj numer RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id": {
"message": "Numer identyfikatora podatkowego"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder": {
"message": "Podaj numer identyfikatora podatkowego"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Sieć"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "Niedługo przekroczysz limit wypłat. Możesz wypłacić jeszcze <b>{amountRemaining}</b>. By wypłacić więcej, musisz wypełnić formularz podatkowy."
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Konto"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Odłącz konto"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Metoda płatności"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "Konto PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Połącz konto PayPal, by bezpośrednio otrzymywać wypłaty."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Zapisz"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Nazwa użytkownika Venmo została zapisana pomyślnie!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Zapisano"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Zaloguj się z PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-description": {
"message": "Podaj nazwę użytkownika Venmo, by otrzymywać wypłaty."
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle": {
"message": "Nazwa użytkownika Venmo"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@nazwa_użytkownika"
},
"dashboard.creator-withdraw-modal.stage.completion": {
"message": "Zakończ"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Metoda"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Szczegóły konta"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Weryfikacja"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Formularz podatkowy"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Szczegóły"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "By wypłacić całe saldo konta (<b>{available}</b>) musisz wypełnić ten formularz. Jest on wymagany dla sprawozdawczości podatkowej i musi być wypełniony tylko raz."
},
"dashboard.creator-withdraw-modal.tax-form-required.body-with-limit": {
"message": "Musisz wypełnić formularz podatkowy W-9 lub W-8 dla zapisów podatkowych Modrinth, abyśmy mogli zachować zgodność z przepisami podatkowymi."
},
"dashboard.creator-withdraw-modal.tax-form-required.header": {
"message": "Wymagany jest formularz podatkowy"
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Metoda płatności"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Nagroda"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder": {
"message": "Wybierz nagrodę"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Nagrody"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "Adres e-mail nie jest zweryfikowany"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-message": {
"message": "Podany adres e-mail nie jest powiązany z Twoim kontem Modrinth. Modrinth nie może odzyskać nagród wysłanych na niepoprawny adres e-mail."
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Dostępne niższe opłaty"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-message": {
"message": "Wybrano walutę USD w opcji międzynarodowej PayPal. <direct-paypal-link>Przełącz się na bezpośredni PayPal</direct-paypal-link> dla niższych opłat (≈2% zamiast ≈6%)."
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Wypłać"
},
"dashboard.creator-withdraw-modal.withdraw-limit": {
"message": "Limit wypłat"
},
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "Przekroczono limit wypłat (<b>{withdrawLimit}</b>). Musisz wypełnić formularz podatkowy, by wypłacić więcej."
},
"dashboard.revenue.available-now": {
"message": "Dostępne teraz"
},
"dashboard.revenue.balance": {
"message": "Saldo"
},
"dashboard.revenue.estimated-tooltip.msg1": {
"message": "Szacunkowe przychody mogą ulec zmianie do momentu ich udostępnienia."
},
"dashboard.revenue.estimated-tooltip.msg2": {
"message": "Kliknij tutaj, by dowiedzieć się, jak Modrinth oblicza Twoje przychody."
},
"dashboard.revenue.estimated-with-date": {
"message": "Oszacowane na {date}"
},
"dashboard.revenue.processing": {
"message": "Przetwarzane"
},
"dashboard.revenue.processing.tooltip": {
"message": "Przychody są przetwarzane do końca miesiąca, po czym są dostępne 60 dni później."
},
"dashboard.revenue.stats.received": {
"message": "Otrzymane"
},
"dashboard.revenue.stats.transactions": {
"message": "Transakcje"
},
"dashboard.revenue.stats.withdrawn": {
"message": "Wypłacone"
},
"dashboard.revenue.tos": {
"message": "Udostępniając projekty na Modrinth i wypłacając pieniądze z konta, wyrażasz zgodę na <terms-link>Warunki programu wynagrodzenia</terms-link>. Dowiedz się więcej o <info-link>programie wynagrodzenia</info-link>."
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Pobierz jako CSV"
},
"dashboard.revenue.transactions.header": {
"message": "Transakcje"
},
"dashboard.revenue.transactions.none": {
"message": "Brak transakcji"
},
"dashboard.revenue.transactions.none.desc": {
"message": "Tutaj pojawią się otrzymane fundusze i wypłaty."
},
"dashboard.revenue.transactions.see-all": {
"message": "Zobacz wszystkie"
},
"dashboard.revenue.withdraw.blocked-tin-mismatch": {
"message": "Twoje wypłaty są tymczasowo zablokowane, ponieważ Twój TIN lub SSN nie pasował do zapisów IRS. Skontaktuj się z obsługą, by resetować i ponownie wysłać Twój formularz podatkowy."
},
"dashboard.revenue.withdraw.card.description": {
"message": "Wypłać z salda Twojego konta poprzez daną metodę płatności."
},
"dashboard.revenue.withdraw.card.title": {
"message": "Wypłata"
},
"dashboard.revenue.withdraw.header": {
"message": "Wypłata"
},
"dashboard.withdraw.completion.account": {
"message": "Konto"
},
"dashboard.withdraw.completion.amount": {
"message": "Kwota"
},
"dashboard.withdraw.completion.close-button": {
"message": "Zamknij"
},
"dashboard.withdraw.completion.date": {
"message": "Data"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "Otrzymasz e-mail na adres <b>{email}</b> z instrukcjami, jak otrzymać wypłatę."
},
"dashboard.withdraw.completion.exchange-rate": {
"message": "Kurs walut"
},
"dashboard.withdraw.completion.fee": {
"message": "Opłata"
},
"dashboard.withdraw.completion.method": {
"message": "Metoda"
},
"dashboard.withdraw.completion.net-amount": {
"message": "Kwota netto"
},
"dashboard.withdraw.completion.recipient": {
"message": "Odbiorca"
},
"dashboard.withdraw.completion.title": {
"message": "Wypłata ukończona"
},
"dashboard.withdraw.completion.transactions-button": {
"message": "Transakcje"
},
"dashboard.withdraw.completion.wallet": {
"message": "Portfel"
},
"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ę"
},
"dashboard.withdraw.error.invalid-address.text": {
"message": "Podany adres nie mógł być zweryfikowany. Sprawdź ponownie adres."
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Weryfikacja adresu nie powiodła się"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": "Podane detale bankowe są nieprawidłowe. Zweryfikuj podane informacje."
},
"dashboard.withdraw.error.invalid-bank.title": {
"message": "Nieprawidłowe detale bankowe"
},
"dashboard.withdraw.error.invalid-wallet.text": {
"message": "Podany portfel krypto jest nieprawidłowy. Zweryfikuj podane informacje."
},
"dashboard.withdraw.error.invalid-wallet.title": {
"message": "Nieprawidłowy adres portfela"
},
"dashboard.withdraw.error.minimum-not-met.text": {
"message": "Kwota do wypłaty (po opłatach) jest zbyt niska. Podaj wyższą kwotę do wypłaty."
},
"dashboard.withdraw.error.minimum-not-met.title": {
"message": "Zbyt niska kwota"
},
"dashboard.withdraw.error.tax-form.text": {
"message": "Musisz wypełnić formularz podatkowy, by móc złożyć wniosek o wypłatę."
},
"dashboard.withdraw.error.tax-form.title": {
"message": "Wypełnij formularz podatkowy"
},
"error.collection.404.list_item.1": {
"message": "Mogłeś źle napisać URL kolekcji."
},
@@ -722,9 +1088,15 @@
"landing.creator.feature.data-statistics.title": {
"message": "Dane i statystyki"
},
"landing.creator.feature.discovery.description": {
"message": "Spraw, by tysiące użytkowników mogło znaleźć Twój projekt przez wyszukiwarkę, naszą stronę główną, serwer Discord, i nie tylko!"
},
"landing.creator.feature.discovery.title": {
"message": "Odkrycie"
},
"landing.creator.feature.diverse-ecosystem.description": {
"message": "Integruj swoje narzędzia budowania poprzez Minotaur, by automatycznie aktualizować swoje projekty gdy tylko wydasz nową wersję"
},
"landing.creator.feature.diverse-ecosystem.title": {
"message": "Zróżnicowany ekosystem"
},
@@ -836,6 +1208,9 @@
"landing.section.for-players.tagline": {
"message": "Odkryj ponad {count} kreacji"
},
"landing.subheading": {
"message": "Odkrywaj, graj i udostępniaj treści Minecraft poprzez naszą otwartoźródłową platformę, stworzoną dla społeczności."
},
"layout.action.change-theme": {
"message": "Zmień motyw"
},
@@ -848,6 +1223,9 @@
"layout.action.lookup-by-email": {
"message": "Szukaj po e-mailu"
},
"layout.action.manage-affiliates": {
"message": "Zarządzaj linkami afiliacyjnymi"
},
"layout.action.manage-server-notices": {
"message": "Zarządzaj ogłoszeniami serwera"
},
@@ -899,9 +1277,24 @@
"layout.banner.subscription-payment-failed.title": {
"message": "Wymagana akcja w sprawie płatności."
},
"layout.banner.tax.action": {
"message": "Wypełnij formularz podatkowy"
},
"layout.banner.tax.description": {
"message": "Wypłaciłeś/aś ponad 600$ z Modrinth w tym roku. Aby spełnić wymogi podatkowe, musisz wypełnić formularz podatkowy. Twoje wypłaty są spauzowane, aż nie wypełnisz formularza podatkowego."
},
"layout.banner.tax.title": {
"message": "Wymagany jest formularz podatkowy"
},
"layout.banner.tin-mismatch.action": {
"message": "Skontaktuj się z obsługą"
},
"layout.banner.tin-mismatch.description": {
"message": "Twoje wypłaty są tymczasowo zablokowane, ponieważ Twój TIN lub SSN nie pasował do zapisów IRS. Skontaktuj się z obsługą, by resetować i ponownie wysłać Twój formularz podatkowy."
},
"layout.banner.tin-mismatch.title": {
"message": "Formularz podatkowy został odrzucony"
},
"layout.banner.verify-email.action": {
"message": "Wyślij ponownie e-mail weryfikacyjny"
},
@@ -921,11 +1314,14 @@
"message": "Wiadomości"
},
"layout.footer.about.rewards-program": {
"message": "Program nagród"
"message": "Program wynagrodzenia"
},
"layout.footer.about.status": {
"message": "Status"
},
"layout.footer.copyright": {
"message": "© {year} Rinth, Inc."
},
"layout.footer.legal": {
"message": "Polityka"
},
@@ -1004,6 +1400,15 @@
"layout.meta.og-description": {
"message": "Odkrywaj i publikuj zawartość Minecraft!"
},
"layout.mobile.close-menu": {
"message": "Zamknij menu"
},
"layout.mobile.open-menu": {
"message": "Otwórz menu"
},
"layout.nav.active-reports": {
"message": "Aktywne raporty"
},
"layout.nav.analytics": {
"message": "Analizy"
},
@@ -1031,6 +1436,9 @@
"layout.nav.modrinth-home-page": {
"message": "Strona główna Modrinth"
},
"layout.nav.my-servers": {
"message": "Moje serwery"
},
"layout.nav.organizations": {
"message": "Organizacje"
},
@@ -1076,27 +1484,342 @@
"moderation.technical.search.placeholder": {
"message": "Wyszukaj recenzje technologiczne..."
},
"muralpay.account-type.checking": {
"message": "Czekowe"
},
"muralpay.account-type.savings": {
"message": "Oszczędnościowe"
},
"muralpay.country.at": {
"message": "Austria"
},
"muralpay.country.be": {
"message": "Belgia"
},
"muralpay.country.cy": {
"message": "Cypr"
},
"muralpay.country.de": {
"message": "Niemcy"
},
"muralpay.country.ee": {
"message": "Estonia"
},
"muralpay.country.es": {
"message": "Hiszpania"
},
"muralpay.country.fi": {
"message": "Finlandia"
},
"muralpay.country.fr": {
"message": "Francja"
},
"muralpay.country.gr": {
"message": "Grecja"
},
"muralpay.country.ie": {
"message": "Irlandia"
},
"muralpay.country.it": {
"message": "Włochy"
},
"muralpay.country.lt": {
"message": "Litwa"
},
"muralpay.country.lu": {
"message": "Luksemburg"
},
"muralpay.country.lv": {
"message": "Łotwa"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Niderlandy"
},
"muralpay.country.pt": {
"message": "Portugalia"
},
"muralpay.country.sk": {
"message": "Słowacja"
},
"muralpay.document-type.national-id": {
"message": "Identyfikator krajowy"
},
"muralpay.document-type.passport": {
"message": "Paszport"
},
"muralpay.document-type.resident-id": {
"message": "Identyfikator rezydenta"
},
"muralpay.document-type.ruc": {
"message": "RUC"
},
"muralpay.document-type.tax-id": {
"message": "Identyfikator podatkowy"
},
"muralpay.field.account-number": {
"message": "Numer konta"
},
"muralpay.field.account-number-cbu-cvu": {
"message": "Numer konta (CBU/CVU)"
},
"muralpay.field.account-number-cci": {
"message": "Numer konta (CCI)"
},
"muralpay.field.account-number-type": {
"message": "Rodzaj numeru konta"
},
"muralpay.field.account-type": {
"message": "Typ konta"
},
"muralpay.field.bank-account-number": {
"message": "Numer konta"
},
"muralpay.field.branch-code": {
"message": "Kod oddziału"
},
"muralpay.field.clabe": {
"message": "CLABE"
},
"muralpay.field.country": {
"message": "Kraj"
},
"muralpay.field.cpf-cnpj": {
"message": "CPF/CNPJ"
},
"muralpay.field.cuit-cuil": {
"message": "CUIT/CUIL"
},
"muralpay.field.document-type": {
"message": "Rodzaj dokumentu"
},
"muralpay.field.iban": {
"message": "IBAN"
},
"muralpay.field.phone-number": {
"message": "Numer tel."
},
"muralpay.field.pix-email": {
"message": "E-mail PIX"
},
"muralpay.field.pix-key-type": {
"message": "Rodzaj klucza PIX"
},
"muralpay.field.pix-phone": {
"message": "Tel. PIX"
},
"muralpay.field.routing-number": {
"message": "Numer rozliczeniowy"
},
"muralpay.field.swift-bic": {
"message": "SWIFT/BIC"
},
"muralpay.field.wallet-address": {
"message": "Adres portfela"
},
"muralpay.help.cbu-cvu": {
"message": "Clave Bancaria Uniforme lub Clave Virtual Uniforme"
},
"muralpay.help.cci": {
"message": "Código de Cuenta Interbancaria"
},
"muralpay.help.clabe": {
"message": "Clave Bancaria Estandarizada (Meksykański numer konta bankowego)"
},
"muralpay.help.cpf-cnpj": {
"message": "Brazylijski numer identyfikacyjny podatków"
},
"muralpay.help.cuit-cuil": {
"message": "Argentyńskie ID podatków"
},
"muralpay.help.iban": {
"message": "Międzynarodowy numer rachunku bankowego (IBAN)"
},
"muralpay.help.swift-bic": {
"message": "Kod identyfikujący bank (BIC)"
},
"muralpay.pix-type.bank-account": {
"message": "Konto bankowe"
},
"muralpay.pix-type.document": {
"message": "CPF/CNPJ"
},
"muralpay.pix-type.email": {
"message": "E-mail"
},
"muralpay.pix-type.phone": {
"message": "Numer telefonu"
},
"muralpay.placeholder.account-number": {
"message": "Podaj numer konta"
},
"muralpay.placeholder.cbu-cvu": {
"message": "Podaj CBU lub CVU"
},
"muralpay.placeholder.cbu-cvu-type": {
"message": "CBU lub CVU"
},
"muralpay.placeholder.cci": {
"message": "Wprowadź 20-cyfrowe CCI"
},
"muralpay.placeholder.cuit-cuil": {
"message": "Wprowadź CUIT lub CUIL"
},
"muralpay.placeholder.enter-account-number": {
"message": "Wprowadź numer konta"
},
"muralpay.placeholder.enter-branch-code": {
"message": "Podaj kod oddziału"
},
"muralpay.placeholder.enter-clabe": {
"message": "Wprowadź 18-cyfrowe CLABE"
},
"muralpay.placeholder.enter-cpf-cnpj": {
"message": "Wprowadź CPF lub CNPJ"
},
"muralpay.placeholder.enter-iban": {
"message": "Wprowadź IBAN"
},
"muralpay.placeholder.enter-pix-email": {
"message": "Wprowadź e-mail PIX"
},
"muralpay.placeholder.enter-routing-number": {
"message": "Podaj 9-cyfrowy numer rozliczeniowy"
},
"muralpay.placeholder.enter-swift-bic": {
"message": "Wprowadź kod SWIFT/BIC"
},
"muralpay.placeholder.iban-crc": {
"message": "Wprowadź kostarykański IBAN"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
"muralpay.placeholder.pix-phone": {
"message": "+55..."
},
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"muralpay.rail.fiat-ars.name": {
"message": "Przelew bankowy (ARS)"
},
"muralpay.rail.fiat-brl.name": {
"message": "Przelew PIX (BRL)"
},
"muralpay.rail.fiat-clp.name": {
"message": "Przelew bankowy (CLP)"
},
"muralpay.rail.fiat-cop.name": {
"message": "Przelew bankowy (COP)"
},
"muralpay.rail.fiat-crc.name": {
"message": "Przelew bankowy (CRC)"
},
"muralpay.rail.fiat-eur.name": {
"message": "Przelew bankowy (EUR)"
},
"muralpay.rail.fiat-mxn.name": {
"message": "Przelew bankowy (MXN)"
},
"muralpay.rail.fiat-pen.name": {
"message": "Przelew bankowy (PEN)"
},
"muralpay.rail.fiat-usd-peru.name": {
"message": "Przelew bankowy (USD - Peru)"
},
"muralpay.rail.fiat-usd.name": {
"message": "Przelew bankowy (USD)"
},
"muralpay.rail.fiat-zar.name": {
"message": "Przelew bankowy (ZAR)"
},
"muralpay.rail.usdc-base.name": {
"message": "USDC (Base)"
},
"muralpay.rail.usdc-celo.name": {
"message": "USDC (Celo)"
},
"muralpay.rail.usdc-ethereum.name": {
"message": "USDC (Ethereum)"
},
"muralpay.rail.usdc-polygon.name": {
"message": "Krypto (USDC)"
},
"muralpay.warning.wallet-address": {
"message": "Sprawdź podwójnie adres portfela. Fundusze przesłane na nieprawidłowy portfel nie mogą być odzyskane."
},
"profile.bio.fallback.creator": {
"message": "Twórca Modrinth."
},
"profile.bio.fallback.user": {
"message": "Użytkownik Modrinth."
},
"profile.button.billing": {
"message": "Zarządzaj rozliczaniem użytkownika"
},
"profile.button.edit-role": {
"message": "Edytuj rolę"
},
"profile.button.info": {
"message": "Otwórz szczegóły użytkownika"
},
"profile.button.manage-projects": {
"message": "Zarządzaj projektami"
},
"profile.button.remove-affiliate": {
"message": "Usuń afiliację"
},
"profile.button.set-affiliate": {
"message": "Ustaw jako afiliację"
},
"profile.details.label.auth-providers": {
"message": "Dostawcy uwierzytelniania"
},
"profile.details.label.email": {
"message": "E-mail"
},
"profile.details.label.has-password": {
"message": "Ma hasło"
},
"profile.details.label.has-totp": {
"message": "Ma TOTP"
},
"profile.details.label.payment-methods": {
"message": "Metody płatności"
},
"profile.details.tooltip.email-not-verified": {
"message": "E-mail nie jest zweryfikowany"
},
"profile.details.tooltip.email-verified": {
"message": "E-mail jest zweryfikowany"
},
"profile.error.not-found": {
"message": "Nie znaleziono użytkownika"
},
"profile.joined-at": {
"message": "Dołączono <date>{ago}</date>"
"profile.label.affiliate": {
"message": "Afiliacja"
},
"profile.label.badges": {
"message": "Odznaki"
},
"profile.label.collection": {
"message": "Kolekcja"
},
"profile.label.details": {
"message": "Szczegóły"
},
"profile.label.downloads": {
"message": "{count} {count, plural, one {pobranie} few {pobrania} other {pobrań}}"
},
"profile.label.joined": {
"message": "Dołączył(-a)"
},
"profile.label.no": {
"message": "Nie"
},
"profile.label.no-collections": {
"message": "Ten użytkownik nie ma żadnych kolekcji!"
},
@@ -1112,18 +1835,21 @@
"profile.label.organizations": {
"message": "Organizacje"
},
"profile.label.projects": {
"message": "{count} {count, plural, one {projekt} few {projekty} other {projektów}}"
},
"profile.label.saving": {
"message": "Zapisywanie..."
},
"profile.label.yes": {
"message": "Tak"
},
"profile.meta.description": {
"message": "Pobieraj projekty {username} na Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Pobieraj projekty {username} na Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> pobranie projektu} few {<stat>{count}</stat> pobrania projektu} other {<stat>{count}</stat> pobrań projektu}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> projekt} other {<stat>{count}</stat> projekty}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> obserwujący projekt} other {<stat>{count}</stat> obserwujących projekt}}"
},
@@ -1173,7 +1899,7 @@
"message": "Wyślij ponownie do przeglądu"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Twój projekt został {status} przez pracowników Modrinth. W większości przypadków możesz ponownie przesłać go do oceny po uwzględnieniu uwag pracowników."
"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!"
@@ -1580,18 +2306,6 @@
"report.submit": {
"message": "Wyślij zgłoszenie"
},
"revenue.transfers.total": {
"message": "Razem wypłacono {amount}."
},
"revenue.transfers.total.method": {
"message": "Wypłacono {amount} przez {method}."
},
"revenue.transfers.total.year": {
"message": "W roku {year} wypłaciłeś kwotę {amount}."
},
"revenue.transfers.total.year_method": {
"message": "W roku {year} wypłaciłeś {amount} za pomocą {method}."
},
"scopes.analytics.description": {
"message": "Dostęp do danych analityki"
},
@@ -1850,9 +2564,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Trwa przywracanie kopii zapasowej"
},
"servers.backups.item.already-preparing": {
"message": "Już przygotowuję kopię zapasową do pobrania"
},
"servers.backups.item.automated": {
"message": "Zautomatyzowane"
},
@@ -1862,9 +2573,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Nie udało się utworzyć kopii zapasowej"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Nie udało się przygotować pliku do pobrania"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Nie udało się przywrócić danych z kopii zapasowej"
},
@@ -1874,15 +2582,6 @@
"servers.backups.item.locked": {
"message": "Zablokowane"
},
"servers.backups.item.prepare-download": {
"message": "Przygotuj do pobrania"
},
"servers.backups.item.prepare-download-again": {
"message": "Spróbuj przygotować ponownie"
},
"servers.backups.item.preparing-download": {
"message": "Przygotowywanie do pobrania..."
},
"servers.backups.item.queued-for-backup": {
"message": "W kolejce do tworzenia kopii zapasowej"
},

View File

@@ -273,7 +273,7 @@
"message": "Senha"
},
"auth.sign-in.sign-in-with": {
"message": "Entrar com"
"message": "Iniciar sessão com"
},
"auth.sign-in.title": {
"message": "Iniciar sessão"
@@ -354,13 +354,13 @@
"message": "Inscreva-se para receber atualizações sobre o Modrinth"
},
"auth.welcome.description": {
"message": "Agora você faz parte de uma comunidade incrível de criadores e exploradores que já criam, baixam e se mantêm atualizados com mods incríveis."
"message": "Agora você faz parte da incrível comunidade de criadores e exploradores que já estão criando, baixando e acompanhando mods incríveis."
},
"auth.welcome.label.tos": {
"message": "Ao criar uma conta, você concorda com os <terms-link>Termos</terms-link> e a <privacy-policy-link>Política de Privacidade</privacy-policy-link> do Modrinth."
},
"auth.welcome.long-title": {
"message": "Bem-vindo ao Modrinth!"
"message": "Bem-vindo(a) ao Modrinth!"
},
"auth.welcome.title": {
"message": "Bem-vindo"
@@ -566,6 +566,27 @@
"create.project.visibility-unlisted": {
"message": "Não listado"
},
"dashboard.affiliate-links.create.button": {
"message": "Criar link de afiliado"
},
"dashboard.affiliate-links.error.title": {
"message": "Erro ao carregar links de afiliado"
},
"dashboard.affiliate-links.header": {
"message": "Seus links de afiliado"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "Isso permanentemente revocará o código afiliado `{id}` e quaisquer links existentes com este código que foram compartilhados não serão mais válidos."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Revogar"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "Você tem certeza de que quer revocar seu link de afiliado \"{title}\"?"
},
"dashboard.affiliate-links.search": {
"message": "Procurar links de afiliado..."
},
"dashboard.collections.button.create-new": {
"message": "Criar nova"
},
@@ -578,6 +599,18 @@
"dashboard.collections.long-title": {
"message": "Suas coleções"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Baixar {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "Seu formulário de imposto {formType} foi enviado com sucesso!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Você já pode sacar livremente. Se tiver dúvidas ou precisar atualizar suas informações, <support-link>entre em contato com o suporte</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Tudo pronto! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Uma entidade estrangeira significa uma entidade comercial organizada fora dos Estados Unidos (como uma corporação, parceria ou LLC não americana)."
},
@@ -602,6 +635,339 @@
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "Você é um cidadão americano?"
},
"dashboard.creator-withdraw-modal.complete-tax-form": {
"message": "Preencha o formulário fiscal"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Continuar com limite"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Detalhes"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Quantia"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "Taxa de câmbio"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Taxa"
},
"dashboard.creator-withdraw-modal.fee-breakdown-net-amount": {
"message": "Valor líquido"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Entidade corporativa"
},
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Uma entidade corporativa se refere a uma organização registrada, tais como uma corporação, parceria ou LLC."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "Você está retirando como um indivíduo ou negócio?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Indivíduo privado"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Selecione teu país"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Pesquisar países..."
},
"dashboard.creator-withdraw-modal.method-selection.error-text": {
"message": "Não foi possível obter os métodos de pagamento disponíveis. Por favor, tente novamente mais tarde."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Falha ao carregar métodos de pagamento"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Região"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Alguns métodos de pagamento não estão disponíveis em certas regiões."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Selecione o método de retirada"
},
"dashboard.creator-withdraw-modal.method-selection.tax-limit-warning": {
"message": "Seu limite de saque é de <b>{amount}</b>. <tax-link>Preencha um formulário fiscal</tax-link> para sacar mais."
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Dono da conta"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Moeda"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Confirme o endereço da sua carteira"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id": {
"message": "Número de ID nacional"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder": {
"message": "Digite o número de ID nacional"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport": {
"message": "Número de passaporte"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder": {
"message": "Digite o número de passaporte"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id": {
"message": "Número de ID de residente"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder": {
"message": "Digite o número de ID de residente"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc": {
"message": "Número do RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder": {
"message": "Digite o número RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id": {
"message": "Número de ID fiscal"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder": {
"message": "Digite o número de ID fiscal"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Rede"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "Você está perto do limite de retirada. Você pode retirar <b>{amountRemaining}</b> agora, mas será necessário um formulário fiscal para poder retirar mais."
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Conta"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Desconectar conta"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Método de pagamento"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "Conta do PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Conecte sua conta PayPal para receber pagamentos diretos."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Guardar"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Nome de usuário do Venmo salvo com sucesso!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Guardado"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Iniciar sessão com o PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-description": {
"message": "Digite seu nome de usuário do Venmo para receber pagamentos."
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle": {
"message": "Nome de usuário do Venmo"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@usuário"
},
"dashboard.creator-withdraw-modal.stage.completion": {
"message": "Concluído"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Método"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Detalhes da Conta"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Verificação"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Formulário fiscal"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Detalhes"
},
"dashboard.creator-withdraw-modal.tax-form-required.body": {
"message": "Para retirar seu saldo total de <b>{available}</b> disponível, por favor, complete o formulário abaixo. É necessário para a declaração de impostos e é apenas necessário ser feito uma vez."
},
"dashboard.creator-withdraw-modal.tax-form-required.body-with-limit": {
"message": "Você deve completar um formulário W-9 ou W-8 para os registros fiscais de Modrinth, para assim, mantermos nossas regulações de impostos em dia."
},
"dashboard.creator-withdraw-modal.tax-form-required.header": {
"message": "Formulário fiscal necessário"
},
"dashboard.creator-withdraw-modal.tremendous-details.payment-method": {
"message": "Método de pagamento"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward": {
"message": "Recompensa"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-placeholder": {
"message": "Selecionar recompensa"
},
"dashboard.creator-withdraw-modal.tremendous-details.reward-plural": {
"message": "Recompensas"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-header": {
"message": "E-mail não verificado"
},
"dashboard.creator-withdraw-modal.tremendous-details.unverified-email-message": {
"message": "O e-mail de entrega que você digitou não está associado com sua conta Modrinth. A Modrinth não pode recuperar recompensas enviada para um endereço de e-mail incorreto."
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-header": {
"message": "Taxas mais baixas disponíveis"
},
"dashboard.creator-withdraw-modal.tremendous-details.usd-paypal-warning-message": {
"message": "Você selecionou USD para PayPal Internacional. <direct-paypal-link>Alterne para o PayPal direto</direct-paypal-link> para obter taxas melhores (≈2% ao invés de ≈6%)."
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Retirar"
},
"dashboard.creator-withdraw-modal.withdraw-limit": {
"message": "Limite de retirada"
},
"dashboard.creator-withdraw-modal.withdraw-limit-used": {
"message": "Você esgotou seu limite de retirada <b>{withdrawLimit}</b>. Você deve completar o formulário fiscal para retirar mais."
},
"dashboard.revenue.available-now": {
"message": "Disponível agora"
},
"dashboard.revenue.balance": {
"message": "Saldo"
},
"dashboard.revenue.estimated-tooltip.msg1": {
"message": "A renda estimada pode está sujeita a mudanças até que esteja disponível."
},
"dashboard.revenue.estimated-tooltip.msg2": {
"message": "Clique para ler sobre como a Modrinth lida com sua renda."
},
"dashboard.revenue.estimated-with-date": {
"message": "Estimada {date}"
},
"dashboard.revenue.processing": {
"message": "Processando"
},
"dashboard.revenue.processing.tooltip": {
"message": "A renda permanece processando até o fim do mês, e então, fica disponível 60 dias depois."
},
"dashboard.revenue.stats.received": {
"message": "Recebido"
},
"dashboard.revenue.stats.transactions": {
"message": "Transações"
},
"dashboard.revenue.stats.withdrawn": {
"message": "Retirado"
},
"dashboard.revenue.tos": {
"message": "Ao enviar projetos a Mondrith e retirar dinheiro da sua conta, você concorda com nossos <terms-link>Termos do Programa de Recompensas</terms-link>.Saiba mais sobre o <info-link>Programa de Recompensa</info-link>."
},
"dashboard.revenue.transactions.btn.download-csv": {
"message": "Baixar como CSV"
},
"dashboard.revenue.transactions.header": {
"message": "Transações"
},
"dashboard.revenue.transactions.none": {
"message": "Sem transações"
},
"dashboard.revenue.transactions.none.desc": {
"message": "Seus pagamentos e retiradas aparecerão aqui."
},
"dashboard.revenue.transactions.see-all": {
"message": "Ver todas"
},
"dashboard.revenue.withdraw.blocked-tin-mismatch": {
"message": "Suas restiradas estão temporariamente bloqueadas devido a seu TIN ou SSN não coincidirem com seus registros do IRS. Por favor, contate o suporte para reestabelecer e reenviar seu formulário fiscal."
},
"dashboard.revenue.withdraw.card.description": {
"message": "Transfira o saldo disponível usando o método de pagamento desejado."
},
"dashboard.revenue.withdraw.card.title": {
"message": "Retirar"
},
"dashboard.revenue.withdraw.header": {
"message": "Retirar"
},
"dashboard.withdraw.completion.account": {
"message": "Conta"
},
"dashboard.withdraw.completion.amount": {
"message": "Quantia"
},
"dashboard.withdraw.completion.close-button": {
"message": "Fechar"
},
"dashboard.withdraw.completion.date": {
"message": "Data"
},
"dashboard.withdraw.completion.email-confirmation": {
"message": "Você receberá um e-mail em <b>{email}</b> com instruções para resgatar sua retirada."
},
"dashboard.withdraw.completion.exchange-rate": {
"message": "Taxa de troca"
},
"dashboard.withdraw.completion.fee": {
"message": "Taxa"
},
"dashboard.withdraw.completion.method": {
"message": "Método"
},
"dashboard.withdraw.completion.net-amount": {
"message": "Quantidade da rede"
},
"dashboard.withdraw.completion.recipient": {
"message": "Destinatário"
},
"dashboard.withdraw.completion.title": {
"message": "Retirada completa"
},
"dashboard.withdraw.completion.transactions-button": {
"message": "Transações"
},
"dashboard.withdraw.completion.wallet": {
"message": "Carteira"
},
"dashboard.withdraw.error.generic.text": {
"message": "Não conseguimos enviar seu pedido de retirada, por favor, cheque seus dados ou contate o suporte."
},
"dashboard.withdraw.error.generic.title": {
"message": "Não "
},
"dashboard.withdraw.error.invalid-address.text": {
"message": "O endereço que providenciou não pôde ser verificado. Por favor, cheque os dados do seu endereço."
},
"dashboard.withdraw.error.invalid-address.title": {
"message": "Erro ao verificar o endereço"
},
"dashboard.withdraw.error.invalid-bank.text": {
"message": "Os dados da conta do banco que providenciou são inválidos. Por favor, verifique as informações."
},
"dashboard.withdraw.error.invalid-bank.title": {
"message": "Dados do banco inválidos"
},
"dashboard.withdraw.error.invalid-wallet.text": {
"message": "O endereço da carteira de criptomoedas que providenciou é inválido. Por favor, revise e tente novamente."
},
"dashboard.withdraw.error.invalid-wallet.title": {
"message": "Endereço da carteira inválido"
},
"dashboard.withdraw.error.minimum-not-met.text": {
"message": "A quantidade que retirada (após as taxas) não coincide com o requisito mínimo. Por favor, aumente a quantidade a retirar."
},
"dashboard.withdraw.error.minimum-not-met.title": {
"message": "Quantia muito baixo"
},
"dashboard.withdraw.error.tax-form.text": {
"message": "Você deve completar o formulário fiscal para enviar seu pedido de retirada."
},
"dashboard.withdraw.error.tax-form.title": {
"message": "Por favor, complete seu formulário fiscal"
},
"error.collection.404.list_item.1": {
"message": "Você pode ter digitado incorretamente o URL da coleção."
},
@@ -723,7 +1089,7 @@
"message": "Dados e estatísticas"
},
"landing.creator.feature.discovery.description": {
"message": "Faça com que seu projeto seja descoberto por milhares de usuários nas buscas, em nossa página inicial, no servidor de Discord e muitas outras formas que virão no futuro!"
"message": "Faça com que seu projeto seja descoberto por milhares de usuários nas buscas, em nossa página inicial, no servidor de Discord e muitas outras formas que chegarão no futuro!"
},
"landing.creator.feature.discovery.title": {
"message": "Descoberta"
@@ -857,6 +1223,9 @@
"layout.action.lookup-by-email": {
"message": "Procurar por e-mail"
},
"layout.action.manage-affiliates": {
"message": "Gerenciar links de afiliado"
},
"layout.action.manage-server-notices": {
"message": "Gerenciar notificações do servidor"
},
@@ -912,11 +1281,20 @@
"message": "Preencha o formulário fiscal"
},
"layout.banner.tax.description": {
"message": "Você já retirou mais de US$ 600 do Modrinth este ano. Para cumprir as normas fiscais, você precisa preencher um formulário fiscal. Suas retiradas ficarão suspensas até que esse formulário seja enviado."
"message": "Você já retirou mais de $600 do Modrinth neste ano. Para cumprir as regras fiscais, é preciso preencher um formulário de impostos. Seus saques ficarão pausados até que o formulário seja enviado."
},
"layout.banner.tax.title": {
"message": "Formulário fiscal necessário"
},
"layout.banner.tin-mismatch.action": {
"message": "Contatar suporte"
},
"layout.banner.tin-mismatch.description": {
"message": "Seus saques estão temporariamente bloqueados porque seu TIN ou SSN não corresponde aos registros do IRS. Por favor, entre em contato com o suporte para redefinir e reenviar seu formulário de impostos."
},
"layout.banner.tin-mismatch.title": {
"message": "Falha ao enviar formulário de impostos"
},
"layout.banner.verify-email.action": {
"message": "Reenviar verificação de e-mail"
},
@@ -941,6 +1319,9 @@
"layout.footer.about.status": {
"message": "Status"
},
"layout.footer.copyright": {
"message": "© {year} Rinth, Inc."
},
"layout.footer.legal": {
"message": "Termos e Políticas"
},
@@ -1019,6 +1400,15 @@
"layout.meta.og-description": {
"message": "Descubra e publique conteúdo de Minecraft!"
},
"layout.mobile.close-menu": {
"message": "Fechar menu"
},
"layout.mobile.open-menu": {
"message": "Abrir menu"
},
"layout.nav.active-reports": {
"message": "Ativar relatórios"
},
"layout.nav.analytics": {
"message": "Estatísticas"
},
@@ -1046,6 +1436,9 @@
"layout.nav.modrinth-home-page": {
"message": "Página principal do Modrinth"
},
"layout.nav.my-servers": {
"message": "Meus servidores"
},
"layout.nav.organizations": {
"message": "Organizações"
},
@@ -1065,7 +1458,7 @@
"message": "Buscar"
},
"layout.nav.upgrade-to-modrinth-plus": {
"message": "Atualize para o Modrinth+"
"message": "Assinar o Modrinth+"
},
"moderation.filter.by": {
"message": "Filtrar por"
@@ -1091,27 +1484,342 @@
"moderation.technical.search.placeholder": {
"message": "Buscar revisões técnicas..."
},
"muralpay.account-type.checking": {
"message": "Checando"
},
"muralpay.account-type.savings": {
"message": "Poupança"
},
"muralpay.country.at": {
"message": "Áustria"
},
"muralpay.country.be": {
"message": "Bélgica"
},
"muralpay.country.cy": {
"message": "Chipre"
},
"muralpay.country.de": {
"message": "Alemanha"
},
"muralpay.country.ee": {
"message": "Estônia"
},
"muralpay.country.es": {
"message": "Espanha"
},
"muralpay.country.fi": {
"message": "Finlândia"
},
"muralpay.country.fr": {
"message": "França"
},
"muralpay.country.gr": {
"message": "Grécia"
},
"muralpay.country.ie": {
"message": "Irlanda"
},
"muralpay.country.it": {
"message": "Itália"
},
"muralpay.country.lt": {
"message": "Lituânia"
},
"muralpay.country.lu": {
"message": "Luxemburgo"
},
"muralpay.country.lv": {
"message": "Letônia"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Países Baixos"
},
"muralpay.country.pt": {
"message": "Portugal"
},
"muralpay.country.sk": {
"message": "Eslováquia"
},
"muralpay.document-type.national-id": {
"message": "ID Nacional"
},
"muralpay.document-type.passport": {
"message": "Passaporte"
},
"muralpay.document-type.resident-id": {
"message": "ID de Residente"
},
"muralpay.document-type.ruc": {
"message": "RUC"
},
"muralpay.document-type.tax-id": {
"message": "ID Fiscal"
},
"muralpay.field.account-number": {
"message": "Número da conta"
},
"muralpay.field.account-number-cbu-cvu": {
"message": "Número da conta (CBU/CVU)"
},
"muralpay.field.account-number-cci": {
"message": "Número da conta (CCI)"
},
"muralpay.field.account-number-type": {
"message": "Tipo de número da conta"
},
"muralpay.field.account-type": {
"message": "Tipo da conta"
},
"muralpay.field.bank-account-number": {
"message": "Número da conta"
},
"muralpay.field.branch-code": {
"message": "Código da filial"
},
"muralpay.field.clabe": {
"message": "CLABE"
},
"muralpay.field.country": {
"message": "País"
},
"muralpay.field.cpf-cnpj": {
"message": "CPF/CNPJ"
},
"muralpay.field.cuit-cuil": {
"message": "CUIT/CUIL"
},
"muralpay.field.document-type": {
"message": "Tipo de documento"
},
"muralpay.field.iban": {
"message": "IBAN"
},
"muralpay.field.phone-number": {
"message": "Número de telefone"
},
"muralpay.field.pix-email": {
"message": "E-mail do PIX"
},
"muralpay.field.pix-key-type": {
"message": "Chave do PIX"
},
"muralpay.field.pix-phone": {
"message": "Telefone do PIX"
},
"muralpay.field.routing-number": {
"message": "Número de rota"
},
"muralpay.field.swift-bic": {
"message": "SWIFT/BIC"
},
"muralpay.field.wallet-address": {
"message": "Endereço da carteira"
},
"muralpay.help.cbu-cvu": {
"message": "Clave Bancaria Uniforme ou Clave Virtual Uniforme"
},
"muralpay.help.cci": {
"message": "Código de Cuenta Interbancaria"
},
"muralpay.help.clabe": {
"message": "Clave Bancaria Estandarizada (Número de conta bancará Mexicana)"
},
"muralpay.help.cpf-cnpj": {
"message": "Número de identificação fiscal brasileiro"
},
"muralpay.help.cuit-cuil": {
"message": "ID fiscal Argentino"
},
"muralpay.help.iban": {
"message": "Número de Conta Bancaria Internacional"
},
"muralpay.help.swift-bic": {
"message": "Código de Identificação Bancaria"
},
"muralpay.pix-type.bank-account": {
"message": "Conta bancaria"
},
"muralpay.pix-type.document": {
"message": "CPF/CNPJ"
},
"muralpay.pix-type.email": {
"message": "E-mail"
},
"muralpay.pix-type.phone": {
"message": "Número de telefone"
},
"muralpay.placeholder.account-number": {
"message": "Digitar número da conta"
},
"muralpay.placeholder.cbu-cvu": {
"message": "Digitar o CBU ou CVU"
},
"muralpay.placeholder.cbu-cvu-type": {
"message": "CBU ou CVU"
},
"muralpay.placeholder.cci": {
"message": "Digitar CCI de 20 dígitos"
},
"muralpay.placeholder.cuit-cuil": {
"message": "Digitar CUIT ou CUIL"
},
"muralpay.placeholder.enter-account-number": {
"message": "Digitar número da conta"
},
"muralpay.placeholder.enter-branch-code": {
"message": "Digitar código de poupança"
},
"muralpay.placeholder.enter-clabe": {
"message": "Digitar a CLABE de 18 dígitos"
},
"muralpay.placeholder.enter-cpf-cnpj": {
"message": "Digitar CPF ou CNPJ"
},
"muralpay.placeholder.enter-iban": {
"message": "Digitar IBAN"
},
"muralpay.placeholder.enter-pix-email": {
"message": "Digitar e-mail PIX"
},
"muralpay.placeholder.enter-routing-number": {
"message": "Digitar número de rota de 9 dígitos"
},
"muralpay.placeholder.enter-swift-bic": {
"message": "Digitar código SWIFT/BIC"
},
"muralpay.placeholder.iban-crc": {
"message": "Digitar IBAN Costa-riquenho"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
"muralpay.placeholder.pix-phone": {
"message": "+55..."
},
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"muralpay.rail.fiat-ars.name": {
"message": "Transferência bancária (ARS)"
},
"muralpay.rail.fiat-brl.name": {
"message": "Transferência PIX (BRL)"
},
"muralpay.rail.fiat-clp.name": {
"message": "Transferência bancária (CLP)"
},
"muralpay.rail.fiat-cop.name": {
"message": "Transferência bancária (COP)"
},
"muralpay.rail.fiat-crc.name": {
"message": "Transferência bancária (CRC)"
},
"muralpay.rail.fiat-eur.name": {
"message": "Transferência bancária (EUR)"
},
"muralpay.rail.fiat-mxn.name": {
"message": "Transferência bancária (MXN)"
},
"muralpay.rail.fiat-pen.name": {
"message": "Transferência bancária (PEN)"
},
"muralpay.rail.fiat-usd-peru.name": {
"message": "Transferência bancária (USD - Peru)"
},
"muralpay.rail.fiat-usd.name": {
"message": "Transferência bancária (USD)"
},
"muralpay.rail.fiat-zar.name": {
"message": "Transferência bancária (ZAR)"
},
"muralpay.rail.usdc-base.name": {
"message": "USDC (Base)"
},
"muralpay.rail.usdc-celo.name": {
"message": "USDC (Celo)"
},
"muralpay.rail.usdc-ethereum.name": {
"message": "USDC (Ethereum)"
},
"muralpay.rail.usdc-polygon.name": {
"message": "Cripto (USDC)"
},
"muralpay.warning.wallet-address": {
"message": "Verifique novamente seu endereço da carteira. Fundos enviados para um endereço incorreto não podem ser recuperados."
},
"profile.bio.fallback.creator": {
"message": "Um criador Modrinth."
},
"profile.bio.fallback.user": {
"message": "Usuário comum."
},
"profile.button.billing": {
"message": "Gerenciar cobrança do usuário"
},
"profile.button.edit-role": {
"message": "Editar cargo"
},
"profile.button.info": {
"message": "Ver detalhes do usuário"
},
"profile.button.manage-projects": {
"message": "Gerenciar projetos"
},
"profile.button.remove-affiliate": {
"message": "Remover como afiliado"
},
"profile.button.set-affiliate": {
"message": "Configurar como afiliado"
},
"profile.details.label.auth-providers": {
"message": "Provedores de autenticação"
},
"profile.details.label.email": {
"message": "E-mail"
},
"profile.details.label.has-password": {
"message": "Possui senha"
},
"profile.details.label.has-totp": {
"message": "Possui TOTP"
},
"profile.details.label.payment-methods": {
"message": "Métodos de pagamento"
},
"profile.details.tooltip.email-not-verified": {
"message": "E-mail não verificado"
},
"profile.details.tooltip.email-verified": {
"message": "E-mail verificado"
},
"profile.error.not-found": {
"message": "Usuário não encontrado"
},
"profile.joined-at": {
"message": "Entrou há <date>{ago}</date>"
"profile.label.affiliate": {
"message": "Afiliado"
},
"profile.label.badges": {
"message": "Emblemas"
},
"profile.label.collection": {
"message": "Coleção"
},
"profile.label.details": {
"message": "Detalhes"
},
"profile.label.downloads": {
"message": "{count, plural, =0 {Nenhum download} one {{count} download} other {{count} downloads}}\n"
},
"profile.label.joined": {
"message": "Entrou"
},
"profile.label.no": {
"message": "Não"
},
"profile.label.no-collections": {
"message": "Este usuário não possui coleções!"
},
@@ -1127,18 +1835,21 @@
"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..."
},
"profile.label.yes": {
"message": "Sim"
},
"profile.meta.description": {
"message": "Baixe os projetos de {username} no Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} — Baixe os projetos de {username} no Modrinth"
},
"profile.stats.downloads": {
"message": "“{count, plural, one {<stat>{count}</stat> projeto baixado} other {<stat>{count}</stat> projetos baixados}}”"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> projeto} other {<stat>{count}</stat> projetos}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> seguidor} other {<stat>{count}</stat> seguidores}} do projeto"
},
@@ -1188,7 +1899,7 @@
"message": "Reenviar para revisão"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Seu projeto foi {status} pela equipe do Modrinth. Na maioria dos casos, você pode enviar uma revisão após resolver a mensagem da equipe."
"message": "Seu projeto foi {status, select, rejected {rejeitado} withheld {retido} other {{status}}} pela equipe da Mondrith. Na maioria dos casos, você pode reenviar para revisão após responder às observações que a equipe lhe deu."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Você precisa completar as etapas necessárias nas tarefas de publicação!"
@@ -1595,18 +2306,6 @@
"report.submit": {
"message": "Enviar denúncia"
},
"revenue.transfers.total": {
"message": "Você sacou {amount} no total."
},
"revenue.transfers.total.method": {
"message": "Você sacou {amount} através de {method}."
},
"revenue.transfers.total.year": {
"message": "Você sacou {amount} em {year}."
},
"revenue.transfers.total.year_method": {
"message": "Você sacou {amount} em {year} através de {method}."
},
"scopes.analytics.description": {
"message": "Acessas suas estatísticas"
},
@@ -1865,9 +2564,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Restauração de backup em andamento"
},
"servers.backups.item.already-preparing": {
"message": "O download de um backup já está sendo preparado"
},
"servers.backups.item.automated": {
"message": "Automatizado"
},
@@ -1877,9 +2573,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Falha ao criar um backup"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Falha ao preparar o download"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Falha ao restaurar um backup"
},
@@ -1889,15 +2582,6 @@
"servers.backups.item.locked": {
"message": "Trancado"
},
"servers.backups.item.prepare-download": {
"message": "Preparar download"
},
"servers.backups.item.prepare-download-again": {
"message": "Tente preparar novamente"
},
"servers.backups.item.preparing-download": {
"message": "Preparando download..."
},
"servers.backups.item.queued-for-backup": {
"message": "Na fila para backup"
},
@@ -2127,7 +2811,7 @@
"message": "Selecione seu tema de cor preferido para o Modrinth neste dispositivo."
},
"settings.display.theme.title": {
"message": "Cor do tema"
"message": "Tema"
},
"settings.language.categories.auto": {
"message": "Automático"

View File

@@ -425,6 +425,168 @@
"common.yes": {
"message": "Sim"
},
"create.collection.cancel": {
"message": "Cancelar"
},
"create.collection.collection-info": {
"message": "A tua nova coleção vai ser criada como uma coleção pública {count, plural,=0 {sem projetos}one {com # projeto}other {com # projetos}}."
},
"create.collection.create-collection": {
"message": "Criar coleção"
},
"create.collection.error-title": {
"message": "Ocorreu um erro"
},
"create.collection.name-label": {
"message": "Nome"
},
"create.collection.name-placeholder": {
"message": "Insere o nome da coleção..."
},
"create.collection.summary-description": {
"message": "Uma ou duas frases que descrevem a tua coleção."
},
"create.collection.summary-label": {
"message": "Resumo"
},
"create.collection.summary-placeholder": {
"message": "Isto é uma coleção de..."
},
"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"
},
"create.limit-alert.type-organization": {
"message": "organização"
},
"create.limit-alert.type-plural-collection": {
"message": "coleções"
},
"create.limit-alert.type-plural-organization": {
"message": "organizações"
},
"create.limit-alert.type-plural-project": {
"message": "projetos"
},
"create.limit-alert.type-project": {
"message": "projeto"
},
"create.organization.cancel": {
"message": "Cancelar"
},
"create.organization.create-organization": {
"message": "Criar organização"
},
"create.organization.error-title": {
"message": "Ocorreu um erro"
},
"create.organization.name-label": {
"message": "Nome"
},
"create.organization.name-placeholder": {
"message": "Inserir nome da organização..."
},
"create.organization.ownership-info": {
"message": "Serás o dono desta organização, mas podes convidar outros membros e transferir o cargo de dono a qualquer momento."
},
"create.organization.summary-description": {
"message": "Uma ou duas frases que descrevem a tua organização."
},
"create.organization.summary-label": {
"message": "Resumo"
},
"create.organization.summary-placeholder": {
"message": "Uma organização para..."
},
"create.organization.title": {
"message": "Criar uma organização"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "Cancelar"
},
"create.project.create-project": {
"message": "Criar projeto"
},
"create.project.error-title": {
"message": "Ocorreu um erro"
},
"create.project.name-label": {
"message": "Nome"
},
"create.project.name-placeholder": {
"message": "Insere o nome do projeto..."
},
"create.project.summary-description": {
"message": "Uma ou duas frases que descrevem o teu projeto."
},
"create.project.summary-label": {
"message": "Resumo"
},
"create.project.summary-placeholder": {
"message": "Este projeto adiciona..."
},
"create.project.title": {
"message": "Criar um projeto"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-description": {
"message": "A visibilidade do teu projeto após ser aprovado."
},
"create.project.visibility-label": {
"message": "Visibilidade"
},
"create.project.visibility-private": {
"message": "Privado"
},
"create.project.visibility-public": {
"message": "Público"
},
"create.project.visibility-unlisted": {
"message": "Não listado"
},
"dashboard.affiliate-links.create.button": {
"message": "Criar link de afiliado"
},
"dashboard.affiliate-links.error.title": {
"message": "Erro a carregar links de afiliado"
},
"dashboard.affiliate-links.header": {
"message": "Os teus links de afiliado"
},
"dashboard.affiliate-links.revoke-confirm.body": {
"message": "Isto vai revogar permanentemente o código de afiliado \"{id}\" e quaisquer links partilhados com este código deixarão de ser válidos."
},
"dashboard.affiliate-links.revoke-confirm.button": {
"message": "Revogar"
},
"dashboard.affiliate-links.revoke-confirm.title": {
"message": "Tens a certeza que queres revogar o teu link de afiliado \"{title}\"?"
},
"dashboard.affiliate-links.search": {
"message": "Procurar links de afiliado..."
},
"dashboard.collections.button.create-new": {
"message": "Criar nova"
},
@@ -437,6 +599,201 @@
"dashboard.collections.long-title": {
"message": "As tuas coleções"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Transferir {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "O teu formulário de imposto {formType} foi enviado com sucesso!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Podes levantar fundos livremente agora. Se tiveres dúvidas ou precisares de atualizar os teus detalhes <support-link>contacta o suporte</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Está tudo feito! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Uma entidade estrangeira é uma entidade empresarial organizada fora dos Estados Unidos (tais como uma corporação, parceria ou LLC não americanas)."
},
"dashboard.creator-tax-form-modal.entity.foreign-entity": {
"message": "Entidade estrangeira"
},
"dashboard.creator-tax-form-modal.entity.private-individual": {
"message": "Indivíduo privado"
},
"dashboard.creator-tax-form-modal.entity.question": {
"message": "És um indivíduo privado ou parte de uma entidade estrangeira?"
},
"dashboard.creator-tax-form-modal.header": {
"message": "Formulário de imposto"
},
"dashboard.creator-tax-form-modal.security.description": {
"message": "Modrinth usa o provedor externo Track1099 para recolher e armazenar os teus formulários de imposto com segurança. <security-link>Sabe mais aqui.</security-link>"
},
"dashboard.creator-tax-form-modal.security.header": {
"message": "Práticas de segurança"
},
"dashboard.creator-tax-form-modal.us-citizen.question": {
"message": "És um cidadão dos EUA?"
},
"dashboard.creator-withdraw-modal.complete-tax-form": {
"message": "Completar o formulário de imposto"
},
"dashboard.creator-withdraw-modal.continue-with-limit": {
"message": "Continuar com limite"
},
"dashboard.creator-withdraw-modal.details-label": {
"message": "Detalhes"
},
"dashboard.creator-withdraw-modal.fee-breakdown-amount": {
"message": "Quantia"
},
"dashboard.creator-withdraw-modal.fee-breakdown-exchange-rate": {
"message": "Taxa de câmbio"
},
"dashboard.creator-withdraw-modal.fee-breakdown-fee": {
"message": "Taxa"
},
"dashboard.creator-withdraw-modal.fee-breakdown-net-amount": {
"message": "Valor líquido"
},
"dashboard.creator-withdraw-modal.kyc.business-entity": {
"message": "Entidade empresarial"
},
"dashboard.creator-withdraw-modal.kyc.entity-description": {
"message": "Uma entidade empresarial refere-se a uma organização registada tais como uma corporação, parceria, ou LLC."
},
"dashboard.creator-withdraw-modal.kyc.entity-question": {
"message": "Estás a levantar como indivíduo ou como negócio?"
},
"dashboard.creator-withdraw-modal.kyc.private-individual": {
"message": "Indivíduo privado"
},
"dashboard.creator-withdraw-modal.method-selection.country-placeholder": {
"message": "Seleciona o teu país"
},
"dashboard.creator-withdraw-modal.method-selection.country-search-placeholder": {
"message": "Pesquisar países..."
},
"dashboard.creator-withdraw-modal.method-selection.error-text": {
"message": "Não foi possível obter os métodos de pagamento disponíveis. Tenta novamente mais tarde."
},
"dashboard.creator-withdraw-modal.method-selection.error-title": {
"message": "Erro a carregar os métodos de pagamento"
},
"dashboard.creator-withdraw-modal.method-selection.region": {
"message": "Região"
},
"dashboard.creator-withdraw-modal.method-selection.region-tooltip": {
"message": "Alguns métodos de pagamento não estão disponíveis em determinadas regiões."
},
"dashboard.creator-withdraw-modal.method-selection.select-method": {
"message": "Selecionar método de levantamento"
},
"dashboard.creator-withdraw-modal.method-selection.tax-limit-warning": {
"message": "O teu limite de levantamento é <b>{amount}</b>, <tax-link>completa um formulário de imposto</tax-link> para levantar mais."
},
"dashboard.creator-withdraw-modal.muralpay-details.account-owner": {
"message": "Dono da conta"
},
"dashboard.creator-withdraw-modal.muralpay-details.coin": {
"message": "Moeda"
},
"dashboard.creator-withdraw-modal.muralpay-details.crypto-warning-header": {
"message": "Confirma o endereço da tua carteira"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id": {
"message": "Número de identificação nacional"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-national-id-placeholder": {
"message": "Insere o número de identificação nacional"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport": {
"message": "Número do passaporte"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-passport-placeholder": {
"message": "Insere o número do passaporte"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id": {
"message": "Número de residência"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-resident-id-placeholder": {
"message": "Insere o número da residência"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc": {
"message": "Número RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-ruc-placeholder": {
"message": "Insere o número RUC"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id": {
"message": "Número de identificação de imposto"
},
"dashboard.creator-withdraw-modal.muralpay-details.document-number-tax-id-placeholder": {
"message": "Insere o número de identificação de imposto"
},
"dashboard.creator-withdraw-modal.muralpay-details.network": {
"message": "Rede"
},
"dashboard.creator-withdraw-modal.nearing-threshold": {
"message": "Estás próximo de atingir o limite de levantamento. Podes levantar <b>{amountRemaining}</b> agora, mas é necessário um formulário de imposto para levantar mais."
},
"dashboard.creator-withdraw-modal.paypal-details.account": {
"message": "Conta"
},
"dashboard.creator-withdraw-modal.paypal-details.disconnect-account": {
"message": "Desconectar conta"
},
"dashboard.creator-withdraw-modal.paypal-details.payment-method": {
"message": "Método de pagamento"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-account": {
"message": "Conta PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.paypal-auth-description": {
"message": "Conecta a tua conta PayPal para receber pagamentos diretamente."
},
"dashboard.creator-withdraw-modal.paypal-details.save-button": {
"message": "Guardar"
},
"dashboard.creator-withdraw-modal.paypal-details.save-success": {
"message": "Nome de utilizador Venmo guardado com sucesso!"
},
"dashboard.creator-withdraw-modal.paypal-details.saved-button": {
"message": "Guardado"
},
"dashboard.creator-withdraw-modal.paypal-details.sign-in-with-paypal": {
"message": "Iniciar sessão com PayPal"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-description": {
"message": "Insere o teu nome de utilizador Venmo para receber pagamentos."
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle": {
"message": "Nome de utilizador Venmo"
},
"dashboard.creator-withdraw-modal.paypal-details.venmo-handle-placeholder": {
"message": "@nome de utilizador"
},
"dashboard.creator-withdraw-modal.stage.completion": {
"message": "Concluído"
},
"dashboard.creator-withdraw-modal.stage.method-selection": {
"message": "Método"
},
"dashboard.creator-withdraw-modal.stage.muralpay-details": {
"message": "Detalhes da conta"
},
"dashboard.creator-withdraw-modal.stage.muralpay-kyc": {
"message": "Verificação"
},
"dashboard.creator-withdraw-modal.stage.tax-form": {
"message": "Formulário de imposto"
},
"dashboard.creator-withdraw-modal.stage.tremendous-details": {
"message": "Detalhes"
},
"dashboard.creator-withdraw-modal.withdraw-button": {
"message": "Levantar"
},
"error.collection.404.list_item.1": {
"message": "Podes ter inserido incorretamente o URL da coleção."
},
@@ -612,7 +969,7 @@
"message": "plugins"
},
"landing.heading.the-place-for-minecraft.resource-packs": {
"message": "pacote de recursos"
"message": "pacotes de recursos"
},
"landing.heading.the-place-for-minecraft.servers": {
"message": "servidores"
@@ -881,6 +1238,69 @@
"moderation.technical.search.placeholder": {
"message": "Pesquisar revisões técnicas..."
},
"muralpay.country.at": {
"message": "Áustria"
},
"muralpay.country.be": {
"message": "Bélgica"
},
"muralpay.country.cy": {
"message": "Chipre"
},
"muralpay.country.de": {
"message": "Alemanha"
},
"muralpay.country.ee": {
"message": "Estónia"
},
"muralpay.country.es": {
"message": "Espanha"
},
"muralpay.country.fi": {
"message": "Finlândia"
},
"muralpay.country.fr": {
"message": "França"
},
"muralpay.country.gr": {
"message": "Grécia"
},
"muralpay.country.ie": {
"message": "Irlanda"
},
"muralpay.country.it": {
"message": "Itália"
},
"muralpay.country.lt": {
"message": "Lituânia"
},
"muralpay.country.lu": {
"message": "Luxemburgo"
},
"muralpay.country.lv": {
"message": "Letónia"
},
"muralpay.country.mt": {
"message": "Malta"
},
"muralpay.country.nl": {
"message": "Holanda"
},
"muralpay.country.pt": {
"message": "Portugal"
},
"muralpay.country.sk": {
"message": "Eslováquia"
},
"muralpay.placeholder.phone-cop": {
"message": "+57..."
},
"muralpay.placeholder.pix-phone": {
"message": "+55..."
},
"muralpay.placeholder.wallet-address-eth": {
"message": "0x..."
},
"profile.button.billing": {
"message": "Gerir faturação do utilizador"
},
@@ -893,15 +1313,15 @@
"profile.error.not-found": {
"message": "Utilizador não encontrado"
},
"profile.joined-at": {
"message": "Juntou-se <date>{ago}</date>"
},
"profile.label.badges": {
"message": "Emblemas"
},
"profile.label.details": {
"message": "Detalhes"
},
"profile.label.no": {
"message": "Não"
},
"profile.label.no-collections": {
"message": "Este utilizador não tem coleções!"
},
@@ -917,18 +1337,18 @@
"profile.label.organizations": {
"message": "Organizações"
},
"profile.label.saving": {
"message": "A guardar..."
},
"profile.label.yes": {
"message": "Sim"
},
"profile.meta.description": {
"message": "Transfere os projetos de {username} no Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Transfere os projetos de {username} no Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> transferência do projeto} other {<stat>{count}</stat> transferências do projeto}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> projeto} other {<stat>{count}</stat> projetos}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> seguidor do projeto} other {<stat>{count}</stat> seguidores do projeto}}"
},
@@ -974,9 +1394,6 @@
"project-moderation-nags.resubmit-for-review": {
"message": "Reenviar para revisão"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "O teu projeto foi {status} pela equipa do Modrinth. Na maior parte dos casos, podes reenviar para revisão após resolver o que foi mencionado na mensagem da equipa."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Deves completar os passos necessários na lista de verificação de publicação!"
},
@@ -1376,18 +1793,6 @@
"report.submit": {
"message": "Enviar denúncia"
},
"revenue.transfers.total": {
"message": "Levantaste {amount} no total."
},
"revenue.transfers.total.method": {
"message": "Levantaste {amount} através de {method}."
},
"revenue.transfers.total.year": {
"message": "Levantaste {amount} em {year}."
},
"revenue.transfers.total.year_method": {
"message": "Levantaste {amount} em {year} através de {method}."
},
"scopes.analytics.description": {
"message": "Acede às tuas estatísticas"
},
@@ -1646,9 +2051,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Restauro de backup em curso"
},
"servers.backups.item.already-preparing": {
"message": "Preparação do backup para transferência já em curso"
},
"servers.backups.item.automated": {
"message": "Automático"
},
@@ -1658,9 +2060,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Falha a criar backup"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Falha a preparar transferência"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Falha a restaurar do backup"
},
@@ -1670,15 +2069,6 @@
"servers.backups.item.locked": {
"message": "Trancado"
},
"servers.backups.item.prepare-download": {
"message": "Preparar transferência"
},
"servers.backups.item.prepare-download-again": {
"message": "Tenta preparar novamente"
},
"servers.backups.item.preparing-download": {
"message": "Preparando transferência..."
},
"servers.backups.item.queued-for-backup": {
"message": "Na fila para backup"
},

View File

@@ -578,6 +578,18 @@
"dashboard.collections.long-title": {
"message": "Colecțiile tale"
},
"dashboard.creator-tax-form-modal.confirmation.download-button": {
"message": "Descarcă {formType}"
},
"dashboard.creator-tax-form-modal.confirmation.success": {
"message": "Formularul tău fiscal {formType} a fost trimis cu succes!"
},
"dashboard.creator-tax-form-modal.confirmation.support-text": {
"message": "Poți retrage liber acum. Dacă ai întrebări sau trebuie să îți actualizezi detaliile, <support-link>contactează suportul</support-link>."
},
"dashboard.creator-tax-form-modal.confirmation.title": {
"message": "Totul este pregătit! 🎉"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "O entitate străină înseamnă o entitate de afaceri organizată în afara Statelor Unite (cum ar fi o corporație, un parteneriat sau un SRL non-SUA)."
},
@@ -911,9 +923,6 @@
"layout.banner.tax.action": {
"message": "Completează formularul fiscal"
},
"layout.banner.tax.description": {
"message": "Ai retras deja peste $600 de la Modrinth anul acesta. Pentru a respecta reglementările fiscale, trebuie să completezi un formular fiscal. Retragerile tale sunt puse pe pauză până când acest formular este trimis."
},
"layout.banner.tax.title": {
"message": "Formular fiscal necesar"
},
@@ -1094,6 +1103,9 @@
"profile.button.billing": {
"message": "Administrează facturarea utilizatorului"
},
"profile.button.edit-role": {
"message": "Editează rolul"
},
"profile.button.info": {
"message": "Vizualizează detaliile utilizatorului"
},
@@ -1103,9 +1115,6 @@
"profile.error.not-found": {
"message": "Utilizatorul nu a fost găsit"
},
"profile.joined-at": {
"message": "S-a alăturat în urmă cu <date>{ago}</date>"
},
"profile.label.badges": {
"message": "Insigne"
},
@@ -1133,12 +1142,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Descarcă proiectele lui {username} pe Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> descărcare} few {<stat>{count}</stat> descărcări} other {<stat>{count}</stat> de descărcări}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> proiect} few {<stat>{count}</stat> proiecte} other {<stat>{count}</stat> de proiecte}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> urmăritor} other {<stat>{count}</stat> urmăritori}}"
},
@@ -1187,9 +1190,6 @@
"project-moderation-nags.resubmit-for-review": {
"message": "Retrimite pentru revizuire"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Proiectul tău a fost {status} de către echipa Modrinth. În cele mai multe cazuri, poți retrimite pentru revizuire după ce ai rezolvat mesajul echipei."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Trebuie să completezi pașii necesari din lista de verificare pentru publicare!"
},
@@ -1595,18 +1595,6 @@
"report.submit": {
"message": "Trimite raportul"
},
"revenue.transfers.total": {
"message": "Ați retras în total {amount}."
},
"revenue.transfers.total.method": {
"message": "Ați retras {amount} prin {method}."
},
"revenue.transfers.total.year": {
"message": "Ați retras {amount} în {year}."
},
"revenue.transfers.total.year_method": {
"message": "Ați retras suma de {amount} în anul {year} prin intermediul {method}."
},
"scopes.analytics.description": {
"message": "Accesați-vă datele analitice"
},
@@ -1865,9 +1853,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Restaurare copie de rezervă în curs"
},
"servers.backups.item.already-preparing": {
"message": "Se pregătește deja copia de rezervă pentru descărcare"
},
"servers.backups.item.automated": {
"message": "Automat"
},
@@ -1877,9 +1862,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Eșec la crearea copiei de rezervă"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Eșec la pregătirea descărcării"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Eșec la restaurarea din copie de rezervă"
},
@@ -1889,15 +1871,6 @@
"servers.backups.item.locked": {
"message": "Blocat"
},
"servers.backups.item.prepare-download": {
"message": "Pregătește descărcarea"
},
"servers.backups.item.prepare-download-again": {
"message": "Încearcă să pregătești din nou"
},
"servers.backups.item.preparing-download": {
"message": "Se pregătește descărcarea..."
},
"servers.backups.item.queued-for-backup": {
"message": "Programat pentru copiere de rezervă"
},
@@ -2061,34 +2034,34 @@
"message": "Activați sau dezactivați anumite caracteristici pe acest dispozitiv."
},
"settings.display.flags.title": {
"message": "Comută funcțiile"
"message": "Funcții avansate"
},
"settings.display.project-list-layouts.datapack": {
"message": "Pagina Pachetelor de Date"
"message": "Pagina cu pachete de date"
},
"settings.display.project-list-layouts.description": {
"message": "Selectează aspectul preferat pentru fiecare pagină care afișează liste de proiecte pe acest dispozitiv."
},
"settings.display.project-list-layouts.mod": {
"message": "Pagina Modurilor"
"message": "Pagina cu moduri"
},
"settings.display.project-list-layouts.modpack": {
"message": "Pagina Pachetelor de Moduri"
"message": "Pagina cu pachete de moduri"
},
"settings.display.project-list-layouts.plugin": {
"message": "Pagina Pluginurilor"
"message": "Pagina cu pluginuri"
},
"settings.display.project-list-layouts.resourcepack": {
"message": "Pagina Pachetelor de Resurse"
"message": "Pagina cu pachete de resurse"
},
"settings.display.project-list-layouts.shader": {
"message": "Pagina Shaderurilor"
"message": "Pagina cu shadere"
},
"settings.display.project-list-layouts.title": {
"message": "Aspectul listelor de proiecte"
},
"settings.display.project-list-layouts.user": {
"message": "Pagini de profil ale utilizatorilor"
"message": "Paginile de profil ale utilizatorului"
},
"settings.display.project-list.layouts.collection": {
"message": "Colecție"
@@ -2100,10 +2073,10 @@
"message": "Redare avansată"
},
"settings.display.sidebar.external-links-new-tab.description": {
"message": "Deschide linkurile externe de pe Modrinth într-un tab nou. Indiferent de această setare, linkurile de pe același domeniu și din descrierile Markdown se vor deschide în același tab, iar linkurile din reclame și paginile de editare se vor deschide într-un tab nou."
"message": "Deschide linkurile externe de pe Modrinth într-o pagină nouă. Indiferent de această setare, linkurile de pe același domeniu și din descrierile Markdown se vor deschide în aceeași pagină, iar linkurile din reclame și paginile de editare se vor deschide într-o pagină nouă."
},
"settings.display.sidebar.external-links-new-tab.title": {
"message": "Deschide linkurile externe într-un tab nou"
"message": "Deschide linkurile externe într-o pagină nouă"
},
"settings.display.sidebar.hide-app-promos.description": {
"message": "Ascunde butoanele \"Descarcă Modrinth App\" din navigarea principală. Pagina aplicației Modrinth poate fi găsită în continuare pe pagina de destinație sau în subsol."

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"be": "Белорусский",
"bg": "Болгарский",
"bn": "Бенгальский",
"ca": "Каталонский",
"ca": "Каталанский",
"cs": "Чешский",
"da": "Датский",
"de": "Немецкий",
@@ -35,9 +35,9 @@
"lt": "Литовский",
"lv": "Латышский",
"ms": "Малайский",
"nb": "Норвежский (букмол)",
"nb": "Норвежский букмол",
"nl": "Нидерландский",
"nn": "Норвежский (нюнорск)",
"nn": "Норвежский нюнорск",
"pes": "Персидский",
"pl": "Польский",
"pt": "Португальский",
@@ -53,6 +53,6 @@
"tt": "Татарский",
"uk": "Украинский",
"vi": "Вьетнамский",
"zh-Hans": "Китайский (упрощенный)",
"zh-Hans": "Китайский (упрощённый)",
"zh-Hant": "Китайский (традиционный)"
}

View File

@@ -506,9 +506,6 @@
"profile.error.not-found": {
"message": "Korisnik nije pronađen"
},
"profile.joined-at": {
"message": "Pridružio/la se <date>{ago}</date>"
},
"profile.label.badges": {
"message": "Bedževi"
},
@@ -536,12 +533,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Preuzmite projekte korisnika {username} na Modrinthu"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> preuzimanje projekta} few {<stat>{count}</stat> preuzimanja projekta} other {<stat>{count}</stat> preuzimanja projekata}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> projekat} few {<stat>{count}</stat> projekta} other {<stat>{count}</stat> projekata}}"
},
"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}}"
},
@@ -746,18 +737,6 @@
"report.submit": {
"message": "Pošaljite prijavu"
},
"revenue.transfers.total": {
"message": "Isplatili ste ukupno {amount}."
},
"revenue.transfers.total.method": {
"message": "Isplatili ste {amount} putem {method}."
},
"revenue.transfers.total.year": {
"message": "Isplatili ste {amount} u {year}."
},
"revenue.transfers.total.year_method": {
"message": "Isplatili ste {amount} u {year} putem {method}."
},
"scopes.analytics.description": {
"message": "Pristupite svojim analitičkim podacima"
},
@@ -1016,9 +995,6 @@
"servers.backup.restore.in-progress.tooltip": {
"message": "Vraćanje iz backupa u toku"
},
"servers.backups.item.already-preparing": {
"message": "Već se priprema backup za preuzimanje"
},
"servers.backups.item.automated": {
"message": "Automatski"
},
@@ -1028,9 +1004,6 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Neuspešno kreiranje backupa"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Neuspešno pripremanje za preuzimanje"
},
"servers.backups.item.failed-to-restore-backup": {
"message": "Neuspešno vraćanje iz backupa"
},
@@ -1040,15 +1013,6 @@
"servers.backups.item.locked": {
"message": "Zaključano"
},
"servers.backups.item.prepare-download": {
"message": "Pripremi preuzimanje"
},
"servers.backups.item.prepare-download-again": {
"message": "Pokušajte ponovo da pripremite"
},
"servers.backups.item.preparing-download": {
"message": "Pripremanje preuzimanja..."
},
"servers.backups.item.queued-for-backup": {
"message": "U redu za backup"
},

View File

@@ -1,4 +1,10 @@
{
"action.cancel": {
"message": "Avbryt"
},
"action.continue": {
"message": "Fortsätt"
},
"admin.billing.error.not-found": {
"message": "Användaren hittades inte"
},
@@ -170,6 +176,9 @@
"app-marketing.features.youve-used-before": {
"message": "du använt förut"
},
"app-marketing.hero.app-screenshot-alt": {
"message": "Skärmdump av Modrinth App med en Cobblemon-instans öppen på sidan ”Innehåll”."
},
"app-marketing.hero.description": {
"message": "Modrinth App är en unik launcher med öppen källkod som låter dig spela dina favoritmods och hålla de uppdaterade, allt i ett smidigt litet paket."
},
@@ -182,6 +191,9 @@
"app-marketing.hero.download-modrinth-app-for-os": {
"message": "Ladda ner Modrinth App för {os}"
},
"app-marketing.hero.minecraft-screenshot-alt": {
"message": "Skärmdump av huvudmenyn i Cobblemon-instansen."
},
"app-marketing.hero.more-download-options": {
"message": "Fler nerladdningsalternativ"
},
@@ -407,6 +419,90 @@
"collection.title": {
"message": "{name} - samling"
},
"common.no": {
"message": "Nej"
},
"common.yes": {
"message": "Ja"
},
"create.collection.cancel": {
"message": "Avbryt"
},
"create.collection.collection-info": {
"message": "Din nya samling kommer skapas som en offentlig samling med {count, plural, =0 {inga projekt} one {# projekt} other {# projekt}}."
},
"create.collection.create-collection": {
"message": "Skapa samling"
},
"create.collection.error-title": {
"message": "Ett fel inträffade"
},
"create.collection.name-label": {
"message": "Namn"
},
"create.collection.name-placeholder": {
"message": "Ange samlingens namn..."
},
"create.collection.summary-description": {
"message": "En mening eller två som beskriver din samling."
},
"create.collection.summary-label": {
"message": "Sammanfattning"
},
"create.collection.summary-placeholder": {
"message": "Det här är en samling av..."
},
"create.collection.title": {
"message": "Skapar samling"
},
"create.limit-alert.approaching-limit": {
"message": "Nära {type}gränsen ({current}/{max})"
},
"create.limit-alert.approaching-limit-description": {
"message": "Du är nära {type}gränsen, kontakta support om du behöver mer än {max} {typePlural}."
},
"create.limit-alert.contact-support": {
"message": "Kontakta support"
},
"create.limit-alert.limit-reached": {
"message": "{type}gräns nådd"
},
"create.limit-alert.limit-reached-description": {
"message": "Du har nått din {type}gräns av {max}. Vänligen kontakta support för att öka gränsen."
},
"create.limit-alert.type-collection": {
"message": "samling"
},
"create.limit-alert.type-organization": {
"message": "organisation"
},
"create.limit-alert.type-plural-collection": {
"message": "samling"
},
"create.limit-alert.type-plural-organization": {
"message": "organisationer"
},
"create.limit-alert.type-plural-project": {
"message": "projekt"
},
"create.limit-alert.type-project": {
"message": "projekt"
},
"create.organization.cancel": {
"message": "Avbryt"
},
"create.organization.create-organization": {
"message": "Skapa organisation"
},
"create.organization.error-title": {
"message": "Ett fel inträffade"
},
"create.organization.name-label": {
"message": "Namn"
},
"create.organization.summary-label": {
"message": "Sammanfattning"
},
"dashboard.collections.button.create-new": {
"message": "Skapa ny"
},
@@ -419,6 +515,15 @@
"dashboard.collections.long-title": {
"message": "Dina samlingar"
},
"dashboard.creator-tax-form-modal.entity.foreign-entity": {
"message": "Främmande entitet"
},
"dashboard.creator-tax-form-modal.entity.private-individual": {
"message": "Privat individ"
},
"dashboard.creator-tax-form-modal.entity.question": {
"message": "Är du en privat individ eller en del av en främmande entitet?"
},
"error.collection.404.list_item.1": {
"message": "Du kan ha skrivit fel på samlingens URL."
},
@@ -896,9 +1001,6 @@
"profile.error.not-found": {
"message": "Användare hittades inte"
},
"profile.joined-at": {
"message": "Gick med <date>{ago}</date>"
},
"profile.label.badges": {
"message": "Märken"
},
@@ -926,12 +1028,6 @@
"profile.meta.description-with-bio": {
"message": "{bio} - Ladda ned {username}s projekt på Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> nedladdning} other {<stat>{count}</stat> nedladdningar}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> projekt} other {<stat>{count}</stat> projekt}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> följare} other {<stat>{count}</stat> följare}}"
},
@@ -977,9 +1073,6 @@
"project-moderation-nags.resubmit-for-review": {
"message": "Begär ny granskning"
},
"project-moderation-nags.resubmit-for-review-desc": {
"message": "Ditt projekt har blivit {status} av Modrinths moderatorer. Vanligtvis kan du skicka in projektet igen efter du har åtgärdat problemet."
},
"project-moderation-nags.submit-checklist-tooltip": {
"message": "Du måste sltuföra alla steg i checklistan för publicering!"
},
@@ -1457,24 +1550,12 @@
"servers.backups.item.failed-to-create-backup": {
"message": "Misslyckades med att skapa säkerhetskopia"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Misslyckades med att förbereda nerladdning"
},
"servers.backups.item.lock": {
"message": "Lås"
},
"servers.backups.item.locked": {
"message": "Låst"
},
"servers.backups.item.prepare-download": {
"message": "Förbered nedladdning"
},
"servers.backups.item.prepare-download-again": {
"message": "Försök förbereda igen"
},
"servers.backups.item.preparing-download": {
"message": "Förbereder nedladdning..."
},
"servers.backups.item.queued-for-backup": {
"message": "Köad för säkerhetskopiering"
},

View File

@@ -1,6 +1,9 @@
{
"action.cancel": {
"message": "Bawiin"
},
"app-marketing.download.description": {
"message": "Magagamit ang aming desktop na aplikasyon sa samot-saring plataporma, piliin ang iyong ninanais na bersiyon."
"message": "Magagamit ang aming desktop na aplikasyon sa samot-saring batyawan, piliin ang iyong ninanais na bersiyon."
},
"app-marketing.download.download-appimage": {
"message": "Idalamba ang AppImage"
@@ -35,15 +38,54 @@
"app-marketing.download.windows": {
"message": "Windows"
},
"app-marketing.features.importing.multimc-alt": {
"message": "MultiMC"
},
"app-marketing.features.mod-management.actions": {
"message": "Mga Kilos"
},
"app-marketing.features.mod-management.description": {
"message": "Pinapadali ng Modrinth na pamahalaan ang lahat ng iyong pambago sa iisang pook. Makakakabit, makakaalis, at makakapagsapanahon ng mga pambago sa iisang pindot lang."
},
"app-marketing.features.mod-management.installed-mods": {
"message": "Mga pambagong kinabit"
},
"app-marketing.features.mod-management.name": {
"message": "Pangalan"
},
"app-marketing.features.mod-management.search-mods": {
"message": "Maghanap ng mga pambago"
},
"app-marketing.features.open-source.title": {
"message": "Bukas na pinagmulan"
},
"app-marketing.features.performance.cpu-percent": {
"message": "% CPU"
},
"app-marketing.features.performance.infinite-mb": {
"message": "∞ MB"
},
"app-marketing.features.performance.less-than-150mb": {
"message": "< 150 MB"
},
"app-marketing.features.performance.modrinth-app": {
"message": "Modrinth App"
},
"app-marketing.features.performance.one-billion-percent": {
"message": "1 gatos na %"
},
"app-marketing.features.performance.ram": {
"message": "RAM"
},
"app-marketing.features.performance.small": {
"message": "Maliit"
},
"app-marketing.features.play.description": {
"message": "Gamitin ang Modrinth App sa pagdalamba at paglaro ng iyong mga paboritong pambago at balot ng pambago."
},
"app-marketing.features.sharing.share-button": {
"message": "Ibahagi"
},
"app-marketing.hero.download-button": {
"message": "Idalamba ang Modrinth App"
},
@@ -56,9 +98,21 @@
"app-marketing.hero.more-download-options": {
"message": "Higit na Pagpipilian sa Pagdalamba"
},
"auth.reset-password.method-choice.email-username.placeholder": {
"message": "Dagisulat"
},
"auth.sign-in.additional-options": {
"message": "<forgot-password-link>Nalimutan ang lihim na salita?</forgot-password-link> • <create-account-link>Lumikha ng akawnt</create-account-link>"
},
"auth.sign-up.email.label": {
"message": "Dagisulat"
},
"auth.verify-email.action.account-settings": {
"message": "Mga kagustuhan sa akawnt"
},
"auth.verify-email.post-verification.description": {
"message": "Tagumpay na napatunayan ang tinitirhan ng iyong dagisulat!"
},
"auth.welcome.description": {
"message": "Bahagi ka na ngayon ng nitong kahanga-hangang pamayanan kabilang sa mga tagalikha at manlalakbay na nagtataguyod, nagdadalamba, at nananatiling napapanahon sa mga nakamamanghang mga pambago."
},
@@ -71,6 +125,51 @@
"collection.delete-modal.description": {
"message": "Habambuhay na matatanggal ang pagtitipong ito. Hindi mababawi ang pagkilos na ito."
},
"collection.error.not-found": {
"message": "Hindi mahanap ang pagtitipon"
},
"collection.label.owner": {
"message": "May-ari"
},
"common.no": {
"message": "Hindi"
},
"common.yes": {
"message": "Oo"
},
"create.collection.cancel": {
"message": "Bawiin"
},
"create.collection.name-label": {
"message": "Pangalan"
},
"create.organization.cancel": {
"message": "Bawiin"
},
"create.organization.name-label": {
"message": "Pangalan"
},
"create.organization.url-label": {
"message": "URL"
},
"create.project.cancel": {
"message": "Bawiin"
},
"create.project.name-label": {
"message": "Pangalan"
},
"create.project.url-label": {
"message": "URL"
},
"create.project.visibility-public": {
"message": "Publiko"
},
"create.project.visibility-unlisted": {
"message": "Hindi nakatala"
},
"dashboard.collections.label.search-input": {
"message": "Maghanap sa iyong mga pagtitipon"
},
"dashboard.creator-tax-form-modal.entity.description": {
"message": "Isang kalakalang entidad ang banyagang entidad na nakaayos sa labas ng Nangagkakaisang Banwa (tulod ng di-US na korporasyon, partnership, o LLC)."
},
@@ -80,17 +179,62 @@
"dashboard.creator-tax-form-modal.entity.question": {
"message": "Isa ka bang pribadong indibidwal o parte ng isang banyagang entidad?"
},
"error.collection.404.list_title": {
"message": "Bakit?"
},
"error.generic.default.title": {
"message": "Naku!"
},
"error.organization.404.list_title": {
"message": "Bakit?"
},
"error.project.404.list_title": {
"message": "Bakit?"
},
"error.user.404.list_title": {
"message": "Bakit?"
},
"frog.altText": {
"message": "Isang malakatotohanang pagpipinta ng laberintong palaka"
},
"frog.title": {
"message": "Palaka"
},
"landing.button.discover-mods": {
"message": "Magtuklas ng mga pambago"
},
"landing.button.go-to-dashboard": {
"message": "Pumunta sa hapag ng pagsubaybay"
},
"landing.creator.feature.data-statistics.description": {
"message": "Makatanggap ng detalyadong ulat ng mga pagtingin ng pahina, bilang ng pagdownload, at kinikita"
},
"landing.feature.launcher.description": {
"message": "Binibigyang-daan ng bukas na pinagmulang API ng Modrinth ang mga tagapaglunsad na makadagdag ng malalimang pagsasama sa Modrinth. Maaari mong gamitin ang Modrinth sa <link>aming aplikasyon</link> at sa iilang pinakasikat na mga tagapaglunsad gaya ng ATLauncher, MultiMC, at Prism Launcher."
},
"landing.heading.the-place-for-minecraft": {
"message": "Ang pook para sa Minecraft na {content}"
},
"landing.heading.the-place-for-minecraft.mods": {
"message": "mga pambago"
},
"landing.heading.the-place-for-minecraft.resource-packs": {
"message": "mga balot ng mapagkukunan"
},
"landing.notifications.has-been-updated": {
"message": "Naisapanahon ang {title}!"
},
"landing.search.label": {
"message": "Maghanap"
},
"landing.search.placeholder": {
"message": "Maghanap..."
},
"landing.section.for-players.label": {
"message": "Para sa mga Manlalaro"
},
"landing.subheading": {
"message": "Magtuklas, maglaro, at magbahagi ng mga kontentong Minecraft sa aming bukas na pinagmulang platapormang ginawa para sa pamayanan."
"message": "Magtuklas, maglaro, at magbahagi ng mga kontentong Minecraft sa aming bukas na pinagmulang batyawang ginawa para sa pamayanan."
},
"layout.action.create-new": {
"message": "Gumawa ng bago..."
@@ -98,8 +242,14 @@
"layout.action.reports": {
"message": "Mga pag-ulat"
},
"layout.banner.account-action": {
"message": "Nangangailangan ng akawnt"
},
"layout.banner.add-email.button": {
"message": "Mga kagustuhan sa akawnt"
"message": "Bisitahin ang mga kagustuhan sa akawnt"
},
"layout.banner.add-email.description": {
"message": "Dahil sa mga kadahilang pangkaligtasan, kailangan ng Modrinth na makapagrehistro ka ng tinitirhan ng dagisulat sa iyong akawnt."
},
"layout.banner.build-fail.description": {
"message": "Bigong makabuo ng kalagayan galing sa API ang nitong pinakalat na frontend ng Modrinth. Marahil dahil ito sa isang pagkawalan o kamalian sa pagsasaaayos. Muling itayo kapag magagamit na ang API. Mga palahudyatan ng kamalian: {errors}; Ang kasalukuyang URL ng API: {url}"
@@ -107,6 +257,9 @@
"layout.banner.build-fail.title": {
"message": "May kamalian sa pagbuo ng katayuan galing sa API habang nagpapatayo."
},
"layout.banner.verify-email.description": {
"message": "Dahil sa mga kadahilang pangkaligtasan, kailangan ng Modrinth na mapatunayan ang tinitirhan ng dagisulat sa iyong akawnt."
},
"layout.footer.about": {
"message": "Tungkol"
},
@@ -194,6 +347,12 @@
"layout.meta.description": {
"message": "Magpasayong sipi ng mga pambago, pansaksak, balot ng malak, tagalilom, balot ng mapagkukunan, at balot ng pambago ng Minecraft sa Modrinth. Tumuklas at maglathala ng mga panukala sa Modrinth na may makabagong, madaling magamit na daungan at API."
},
"layout.nav.home": {
"message": "Tirahan"
},
"layout.nav.search": {
"message": "Maghanap"
},
"moderation.page.projects": {
"message": "Mga Panukala"
},
@@ -203,14 +362,41 @@
"moderation.page.technicalReview": {
"message": "Aghimuing Pagsusuri"
},
"moderation.search.placeholder": {
"message": "Maghanap..."
},
"profile.bio.fallback.creator": {
"message": "Isang tagalikha sa Modrinth."
},
"profile.bio.fallback.user": {
"message": "Isang tagagamit sa Modrinth."
},
"profile.details.label.email": {
"message": "Dagisulat"
},
"profile.label.badges": {
"message": "Tsapa"
},
"profile.label.joined": {
"message": "Sumali"
},
"profile.label.no": {
"message": "Hindi"
},
"profile.label.yes": {
"message": "Oo"
},
"profile.meta.description": {
"message": "Magdalamba ng mga panukala ni {username} sa Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Magdalamba ng mga panukala ni {username} sa Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> dalamba ng panukala} other {<stat>{count}</stat> na dalamba ng panukala}}"
"project-member-header.accept": {
"message": "Tanggapin"
},
"project-member-header.error": {
"message": "Kamalian"
},
"project-type.datapack.plural": {
"message": "Mga Balot ng Malak"
@@ -218,20 +404,38 @@
"project-type.datapack.singular": {
"message": "Balot ng Malak"
},
"project-type.mod.plural": {
"message": "Mga Pambago"
},
"project-type.mod.singular": {
"message": "Pambago"
},
"project-type.plugin.singular": {
"message": "Pansaksak"
},
"project-type.resourcepack.plural": {
"message": "Mga Balot ng Mapagkukunan"
},
"project-type.resourcepack.singular": {
"message": "Balot ng Mapagkukunan"
},
"project-type.shader.singular": {
"message": "Tagalilom"
},
"project.about.details.updated": {
"message": "Naisapanahon {date}"
},
"project.download.game-version": {
"message": "Bersiyon ng laro: {version}"
},
"project.download.install-with-app": {
"message": "Ikabit gamit ang Modrinth App"
},
"project.download.no-app": {
"message": "Wala kang Modrinth App?"
},
"project.download.platform": {
"message": "Plataporma: {platform}"
"message": "Batyawan: {platform}"
},
"project.download.search-game-versions": {
"message": "Maghanap ng mga bersiyon ng laro..."
@@ -239,6 +443,9 @@
"project.download.select-game-version": {
"message": "Piliin ang lahat ng bersiyon ng laro"
},
"project.download.select-platform": {
"message": "Pumili ng batyawan"
},
"project.download.show-all-versions": {
"message": "Ipakita ang lahat ng bersiyon"
},
@@ -272,40 +479,112 @@
"project.settings.environment.notice.review-options.description": {
"message": "Kakaunlad lang ng aming kaayusan sa Mga Kapaligiran sa Modrinth at magagamit na ngayon ang mga bagong pagpipilian. Mangyaring suriin na tama ang napili sa ibaba at pindutin ang 'Patunayan' kapag tapos ka na!"
},
"project.settings.environment.verification.verify-button": {
"message": "Patunayan"
},
"project.settings.general.name.title": {
"message": "Pangalan"
},
"project.settings.general.url.title": {
"message": "URL"
},
"project.settings.title": {
"message": "Mga Kagustuhan"
},
"project.stats.downloads-label": {
"message": "dalamba {count, plural, one {} other {}}"
},
"servers.backups.item.failed-to-prepare-backup": {
"message": "Bigong maihanda ang dalamba"
"scopes.performAnalytics.description": {
"message": "Buhata ang mga kalihokan sa analitika"
},
"servers.backups.item.prepare-download": {
"message": "Ihanda ang dalamba"
"servers.backups.item.lock": {
"message": "Ikandado"
},
"servers.backups.item.prepare-download-again": {
"message": "Muling subukan ang paghahanda"
"servers.backups.item.locked": {
"message": "Kinandado"
},
"servers.backups.item.preparing-download": {
"message": "Hinahanda ang dalamba..."
"servers.backups.item.rename": {
"message": "Palitan ang pangalan"
},
"servers.backups.item.retry": {
"message": "Subukan muli"
},
"servers.backups.item.unlock": {
"message": "Buksan"
},
"servers.notice.actions": {
"message": "Mga Kilos"
},
"servers.notice.begins": {
"message": "Magsisimula"
},
"servers.notice.id": {
"message": "ID"
},
"servers.notice.level": {
"message": "Antas"
},
"servers.plan.large.name": {
"message": "Malaki"
},
"servers.plan.medium.name": {
"message": "Katamtaman"
},
"servers.plan.small.name": {
"message": "Maliit"
},
"settings.billing.payment_method_type.eftpos": {
"message": "EFTPOS"
},
"settings.billing.payment_method_type.jcb": {
"message": "JCB"
},
"settings.billing.payment_method_type.paypal": {
"message": "PayPal"
},
"settings.billing.payment_method_type.unknown": {
"message": "Hindi kilalang paraan ng pagbabayad"
},
"settings.billing.payment_method_type.visa": {
"message": "Visa"
},
"settings.display.flags.description": {
"message": "Magpagana o huwag magpagana ng mga tiyak na tampok sa iyong pakasam."
},
"settings.display.project-list-layouts.datapack": {
"message": "Pahina ng mga Balot ng Malak"
"message": "Pahina ng Mga Balot ng Malak"
},
"settings.display.project-list-layouts.description": {
"message": "Pumili ng iyong ninanais na pag-aayos ng bawat pahinang magpapakita sa mga tala ng panukala sa iyong pakasam."
"message": "Pumili ng iyong ninanais na ayos ng bawat pahinang magpapakita sa mga tala ng panukala sa iyong pakasam."
},
"settings.display.project-list-layouts.resourcepack": {
"message": "Pahina ng mga Balot ng Mapagkukunan"
"message": "Pahina ng Mga Balot ng Mapagkukunan"
},
"settings.display.project-list-layouts.title": {
"message": "Mga ayos ng talaan ng panukala"
},
"settings.display.theme.description": {
"message": "Pumili ng iyong gugustohing paksang-kulay para sa Modrinth ng nitong pakasam."
},
"settings.language.languages.search-field.placeholder": {
"message": "Maghanap ng wika..."
},
"settings.pats.modal.create.name.label": {
"message": "Pangalan"
},
"settings.profile.bio.title": {
"message": "Talambuhay"
},
"settings.profile.profile-picture.reset": {
"message": "Isauli"
},
"settings.sessions.description": {
"message": "Narito ang lahat ng mga pakasam na kasalukuyang nakalog-in sa iyong Modrinth account. Maaari mong maisaisang ma-logout ang bawat isa.\n\nKung makakita ka ng isang hindi mo nakikilala, maglog-out sa pakasam na iyon at agarang palitan ang lihim na salita ng iyong akawnt sa Modrinth."
},
"settings.sessions.unknown-os": {
"message": "Hindi kilalang OS"
},
"settings.sessions.unknown-platform": {
"message": "Hindi kilalang batyawan"
}
}

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