mirror of
https://github.com/modrinth/code.git
synced 2026-08-28 10:34:53 +00:00
chore(frontend): i18n pass on mostly-translated frontend components (#6786)
* i18n pass on mostly-translated frontend components * Run prepr * Fix SRV-records text and unescape tooltip braces * Fix changed wording * Remove unneeded strings * Use ICU-safe placeholder
This commit is contained in:
@@ -3,19 +3,21 @@
|
||||
<ConfirmLeaveModal ref="confirmLeaveModal" />
|
||||
<section class="universal-card">
|
||||
<div class="flex flex-col gap-6">
|
||||
<div class="text-2xl font-semibold text-contrast">Server details</div>
|
||||
<div class="text-2xl font-semibold text-contrast">
|
||||
{{ formatMessage(messages.serverDetailsHeading) }}
|
||||
</div>
|
||||
|
||||
<!-- Region -->
|
||||
<div class="max-w-[600px]">
|
||||
<label for="server-region">
|
||||
<span class="label__title">Region</span>
|
||||
<span class="label__title">{{ formatMessage(messages.regionLabel) }}</span>
|
||||
</label>
|
||||
<Combobox
|
||||
id="server-region"
|
||||
v-model="region"
|
||||
:options="regionOptions"
|
||||
searchable
|
||||
placeholder="Select region"
|
||||
:placeholder="formatMessage(messages.selectRegionPlaceholder)"
|
||||
:disabled="!hasPermission"
|
||||
/>
|
||||
</div>
|
||||
@@ -24,7 +26,10 @@
|
||||
<div class="max-w-[600px]">
|
||||
<label for="server-language">
|
||||
<span class="label__title"
|
||||
>Languages <span class="font-normal text-secondary">(optional)</span></span
|
||||
>{{ formatMessage(messages.languagesLabel) }}
|
||||
<span class="font-normal text-secondary"
|
||||
>({{ formatMessage(messages.optionalLabel) }})</span
|
||||
></span
|
||||
>
|
||||
</label>
|
||||
<MultiSelect
|
||||
@@ -34,7 +39,7 @@
|
||||
searchable
|
||||
include-select-all-option
|
||||
:max-tag-rows="2"
|
||||
placeholder="Select languages"
|
||||
:placeholder="formatMessage(messages.selectLanguagesPlaceholder)"
|
||||
:disabled="!hasPermission"
|
||||
/>
|
||||
</div>
|
||||
@@ -43,7 +48,9 @@
|
||||
<div class="max-w-[600px]">
|
||||
<div class="flex items-center justify-between">
|
||||
<label for="java-address">
|
||||
<span class="label__title !m-0 !text-contrast">Java address</span>
|
||||
<span class="label__title !m-0 !text-contrast">{{
|
||||
formatMessage(messages.javaAddressLabel)
|
||||
}}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -58,7 +65,7 @@
|
||||
<StyledInput
|
||||
id="java-address"
|
||||
v-model="javaAddress"
|
||||
placeholder="Enter address"
|
||||
:placeholder="formatMessage(messages.enterAddressPlaceholder)"
|
||||
:disabled="!hasPermission"
|
||||
wrapper-class="flex-grow"
|
||||
autocomplete="off"
|
||||
@@ -80,7 +87,7 @@
|
||||
color="oranges"
|
||||
>
|
||||
<button
|
||||
v-tooltip="'Refresh ping'"
|
||||
v-tooltip="formatMessage(messages.refreshPingTooltip)"
|
||||
:disabled="javaPingLoading"
|
||||
@click="pingJavaServer"
|
||||
>
|
||||
@@ -92,34 +99,35 @@
|
||||
v-if="javaPingResult !== null && !javaPingLoading && javaPingResult.online"
|
||||
class="mt-0.5 flex items-center gap-1.5 text-green"
|
||||
>
|
||||
Server is online!
|
||||
{{ formatMessage(messages.serverOnline) }}
|
||||
<template v-if="javaPingResult.latency">
|
||||
Latency: {{ javaPingResult.latency }}ms
|
||||
{{ formatMessage(messages.latencyLabel, { latency: javaPingResult.latency }) }}
|
||||
</template>
|
||||
</div>
|
||||
<div v-else-if="javaPingResult !== null && !javaPingLoading" class="mt-0.5 text-orange">
|
||||
We couldn’t ping this server. It may be blocked by your host so try refreshing a few
|
||||
times. If it still doesn’t respond please
|
||||
<a
|
||||
class="inline underline"
|
||||
href="https://support.modrinth.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
contact support</a
|
||||
>.
|
||||
<IntlFormatted :message-id="messages.pingFailedMessage">
|
||||
<template #support-link="{ children }">
|
||||
<a
|
||||
class="inline underline"
|
||||
href="https://support.modrinth.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
><component :is="() => normalizeChildren(children)"
|
||||
/></a>
|
||||
</template>
|
||||
</IntlFormatted>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="mt-2 text-sm">
|
||||
If you have [SRV records]
|
||||
<InfoIcon
|
||||
v-tooltip="{
|
||||
content:
|
||||
'The address you enter here may have DNS SRV records _minecraft._tcp.{your domain} which point to your Minecraft server address and port.',
|
||||
popperClass: 'max-w-xs',
|
||||
}"
|
||||
/>, you do not need to add a port. Otherwise if you have a port which isn't 25565, you
|
||||
can include it as :12345
|
||||
<IntlFormatted :message-id="messages.srvRecordsHint">
|
||||
<template #srv-tooltip="{ children }"
|
||||
><component :is="() => normalizeChildren(children)" /><InfoIcon
|
||||
v-tooltip="{
|
||||
content: formatMessage(messages.srvRecordsTooltip),
|
||||
popperClass: 'max-w-xs',
|
||||
}"
|
||||
/></template>
|
||||
</IntlFormatted>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -127,15 +135,17 @@
|
||||
<div class="max-w-[600px]">
|
||||
<label for="bedrock-address">
|
||||
<span class="label__title !text-contrast"
|
||||
>Bedrock address
|
||||
<span class="font-normal text-secondary">(optional)</span>
|
||||
>{{ formatMessage(messages.bedrockAddressLabel) }}
|
||||
<span class="font-normal text-secondary"
|
||||
>({{ formatMessage(messages.optionalLabel) }})</span
|
||||
>
|
||||
</span>
|
||||
</label>
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<StyledInput
|
||||
id="bedrock-address"
|
||||
v-model="bedrockAddress"
|
||||
placeholder="Enter address"
|
||||
:placeholder="formatMessage(messages.enterAddressPlaceholder)"
|
||||
:disabled="!hasPermission"
|
||||
wrapper-class="flex-grow"
|
||||
autocomplete="off"
|
||||
@@ -163,10 +173,13 @@ import {
|
||||
ButtonStyled,
|
||||
Combobox,
|
||||
ConfirmLeaveModal,
|
||||
defineMessages,
|
||||
injectModrinthClient,
|
||||
injectNotificationManager,
|
||||
injectProjectPageContext,
|
||||
IntlFormatted,
|
||||
MultiSelect,
|
||||
normalizeChildren,
|
||||
SERVER_LANGUAGES,
|
||||
SERVER_REGIONS,
|
||||
StyledInput,
|
||||
@@ -181,6 +194,81 @@ const PING_TIMEOUT_MS = 5000
|
||||
|
||||
const { formatMessage, locale } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
serverDetailsHeading: {
|
||||
id: 'project.settings.server.details-heading',
|
||||
defaultMessage: 'Server details',
|
||||
},
|
||||
regionLabel: {
|
||||
id: 'project.settings.server.region-label',
|
||||
defaultMessage: 'Region',
|
||||
},
|
||||
selectRegionPlaceholder: {
|
||||
id: 'project.settings.server.select-region-placeholder',
|
||||
defaultMessage: 'Select region',
|
||||
},
|
||||
languagesLabel: {
|
||||
id: 'project.settings.server.languages-label',
|
||||
defaultMessage: 'Languages',
|
||||
},
|
||||
optionalLabel: {
|
||||
id: 'project.settings.server.optional-label',
|
||||
defaultMessage: 'optional',
|
||||
},
|
||||
selectLanguagesPlaceholder: {
|
||||
id: 'project.settings.server.select-languages-placeholder',
|
||||
defaultMessage: 'Select languages',
|
||||
},
|
||||
javaAddressLabel: {
|
||||
id: 'project.settings.server.java-address-label',
|
||||
defaultMessage: 'Java address',
|
||||
},
|
||||
enterAddressPlaceholder: {
|
||||
id: 'project.settings.server.enter-address-placeholder',
|
||||
defaultMessage: 'Enter address',
|
||||
},
|
||||
refreshPingTooltip: {
|
||||
id: 'project.settings.server.refresh-ping-tooltip',
|
||||
defaultMessage: 'Refresh ping',
|
||||
},
|
||||
serverOnline: {
|
||||
id: 'project.settings.server.server-online',
|
||||
defaultMessage: 'Server is online!',
|
||||
},
|
||||
latencyLabel: {
|
||||
id: 'project.settings.server.latency-label',
|
||||
defaultMessage: 'Latency: {latency}ms',
|
||||
},
|
||||
pingFailedMessage: {
|
||||
id: 'project.settings.server.ping-failed-message',
|
||||
defaultMessage:
|
||||
"We couldn't ping this server. It may be blocked by your host so try refreshing a few times. If it still doesn't respond please <support-link>contact support</support-link>.",
|
||||
},
|
||||
srvRecordsHint: {
|
||||
id: 'project.settings.server.srv-records-hint',
|
||||
defaultMessage:
|
||||
"If you have <srv-tooltip>[SRV records]</srv-tooltip>, you do not need to add a port. Otherwise if you have a port which isn't 25565, you can include it as :12345",
|
||||
},
|
||||
srvRecordsTooltip: {
|
||||
id: 'project.settings.server.srv-records-tooltip',
|
||||
defaultMessage:
|
||||
'The address you enter here may have DNS SRV records _minecraft._tcp.(your domain) which point to your Minecraft server address and port.',
|
||||
},
|
||||
bedrockAddressLabel: {
|
||||
id: 'project.settings.server.bedrock-address-label',
|
||||
defaultMessage: 'Bedrock address',
|
||||
},
|
||||
cannotSaveTitle: {
|
||||
id: 'project.settings.server.cannot-save-title',
|
||||
defaultMessage: 'Cannot save',
|
||||
},
|
||||
cannotSaveText: {
|
||||
id: 'project.settings.server.cannot-save-text',
|
||||
defaultMessage:
|
||||
'The Java server must be reachable before saving. Please ensure the ping succeeds.',
|
||||
},
|
||||
})
|
||||
|
||||
const client = injectModrinthClient()
|
||||
const { addNotification } = injectNotificationManager()
|
||||
const { projectV3, currentMember, patchProjectV3 } = injectProjectPageContext()
|
||||
@@ -391,8 +479,8 @@ function resetChanges() {
|
||||
async function handleSave() {
|
||||
if (javaAddress.value.trim() && !javaPingResult.value?.online) {
|
||||
addNotification({
|
||||
title: 'Cannot save',
|
||||
text: 'The Java server must be reachable before saving. Please ensure the ping succeeds.',
|
||||
title: formatMessage(messages.cannotSaveTitle),
|
||||
text: formatMessage(messages.cannotSaveText),
|
||||
type: 'error',
|
||||
})
|
||||
return
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<section class="universal-card">
|
||||
<div class="label">
|
||||
<h3>
|
||||
<span class="label__title size-card-header">Tags</span>
|
||||
<span class="label__title size-card-header">{{ formatMessage(messages.tagsTitle) }}</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
@@ -27,16 +27,18 @@
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Accurate tagging is important to help people find your
|
||||
{{ formatProjectType(project.project_type).toLowerCase() }}. Make sure to select all tags
|
||||
that apply.
|
||||
{{
|
||||
formatMessage(messages.taggingImportanceDescription, {
|
||||
type: formatProjectType(project.project_type).toLowerCase(),
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
|
||||
<p
|
||||
v-if="project.versions.length === 0 && projectV3?.minecraft_server == null"
|
||||
class="known-errors"
|
||||
>
|
||||
Please upload a version first in order to select tags!
|
||||
{{ formatMessage(messages.uploadVersionFirst) }}
|
||||
</p>
|
||||
<template v-else>
|
||||
<template v-for="header in Object.keys(categoryLists)" :key="`categories-${header}`">
|
||||
@@ -46,22 +48,32 @@
|
||||
</h4>
|
||||
<span class="label__description">
|
||||
<template v-if="header === 'categories'">
|
||||
Select all categories that reflect the themes or function of your
|
||||
{{ formatProjectType(project.project_type).toLowerCase() }}.
|
||||
{{
|
||||
formatMessage(messages.categoriesDescription, {
|
||||
type: formatProjectType(project.project_type).toLowerCase(),
|
||||
})
|
||||
}}
|
||||
</template>
|
||||
<template v-else-if="header === 'features'">
|
||||
Select all of the features that your
|
||||
{{ formatProjectType(project.project_type).toLowerCase() }} makes use of.
|
||||
{{
|
||||
formatMessage(messages.featuresDescription, {
|
||||
type: formatProjectType(project.project_type).toLowerCase(),
|
||||
})
|
||||
}}
|
||||
</template>
|
||||
<template v-else-if="header === 'resolutions'">
|
||||
Select the resolution(s) of textures in your
|
||||
{{ formatProjectType(project.project_type).toLowerCase() }}.
|
||||
{{
|
||||
formatMessage(messages.resolutionsDescription, {
|
||||
type: formatProjectType(project.project_type).toLowerCase(),
|
||||
})
|
||||
}}
|
||||
</template>
|
||||
<template v-else-if="header === 'performance impact'">
|
||||
Select the realistic performance impact of your
|
||||
{{ formatProjectType(project.project_type).toLowerCase() }}. Select multiple if the
|
||||
{{ formatProjectType(project.project_type).toLowerCase() }} is configurable to
|
||||
different levels of performance impact.
|
||||
{{
|
||||
formatMessage(messages.performanceImpactDescription, {
|
||||
type: formatProjectType(project.project_type).toLowerCase(),
|
||||
})
|
||||
}}
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
@@ -90,15 +102,16 @@
|
||||
</template>
|
||||
<div class="label">
|
||||
<h4>
|
||||
<span class="label__title"><StarIcon /> Featured tags</span>
|
||||
<span class="label__title"
|
||||
><StarIcon /> {{ formatMessage(messages.featuredTags) }}</span
|
||||
>
|
||||
</h4>
|
||||
<span class="label__description">
|
||||
You can feature up to 3 of your most relevant tags. Other tags may be promoted to
|
||||
featured if you do not select all 3.
|
||||
</span>
|
||||
<span class="label__description">{{
|
||||
formatMessage(messages.featuredTagsDescription)
|
||||
}}</span>
|
||||
</div>
|
||||
<p v-if="current.selectedTags.length < 1">
|
||||
Select at least one category in order to feature a category.
|
||||
{{ formatMessage(messages.selectAtLeastOneCategory) }}
|
||||
</p>
|
||||
<div class="category-list input-div">
|
||||
<Checkbox
|
||||
@@ -145,6 +158,7 @@ import {
|
||||
import {
|
||||
Checkbox,
|
||||
ConfirmLeaveModal,
|
||||
defineMessages,
|
||||
formatCategory,
|
||||
formatCategoryHeader,
|
||||
FormattedTag,
|
||||
@@ -167,6 +181,77 @@ interface Category {
|
||||
const tags = useGeneratedState()
|
||||
const { formatMessage, locale } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
tagsTitle: {
|
||||
id: 'project.settings.tags.title',
|
||||
defaultMessage: 'Tags',
|
||||
},
|
||||
taggingImportanceDescription: {
|
||||
id: 'project.settings.tags.tagging-importance-description',
|
||||
defaultMessage:
|
||||
'Accurate tagging is important to help people find your {type}. Make sure to select all tags that apply.',
|
||||
},
|
||||
uploadVersionFirst: {
|
||||
id: 'project.settings.tags.upload-version-first',
|
||||
defaultMessage: 'Please upload a version first in order to select tags!',
|
||||
},
|
||||
categoriesDescription: {
|
||||
id: 'project.settings.tags.categories-description',
|
||||
defaultMessage: 'Select all categories that reflect the themes or function of your {type}.',
|
||||
},
|
||||
featuresDescription: {
|
||||
id: 'project.settings.tags.features-description',
|
||||
defaultMessage: 'Select all of the features that your {type} makes use of.',
|
||||
},
|
||||
resolutionsDescription: {
|
||||
id: 'project.settings.tags.resolutions-description',
|
||||
defaultMessage: 'Select the resolution(s) of textures in your {type}.',
|
||||
},
|
||||
performanceImpactDescription: {
|
||||
id: 'project.settings.tags.performance-impact-description',
|
||||
defaultMessage:
|
||||
'Select the realistic performance impact of your {type}. Select multiple if the {type} is configurable to different levels of performance impact.',
|
||||
},
|
||||
featuredTags: {
|
||||
id: 'project.settings.tags.featured-tags',
|
||||
defaultMessage: 'Featured tags',
|
||||
},
|
||||
featuredTagsDescription: {
|
||||
id: 'project.settings.tags.featured-tags-description',
|
||||
defaultMessage:
|
||||
'You can feature up to 3 of your most relevant tags. Other tags may be promoted to featured if you do not select all 3.',
|
||||
},
|
||||
selectAtLeastOneCategory: {
|
||||
id: 'project.settings.tags.select-at-least-one-category',
|
||||
defaultMessage: 'Select at least one category in order to feature a category.',
|
||||
},
|
||||
tooManyTagsServerHardWarning: {
|
||||
id: 'project.settings.tags.too-many-tags-server-hard-warning',
|
||||
defaultMessage:
|
||||
"You've selected {count} tags. Please reduce to 18 or fewer to keep your server focused and easier to discover.",
|
||||
},
|
||||
tooManyTagsServerSoftWarning: {
|
||||
id: 'project.settings.tags.too-many-tags-server-soft-warning',
|
||||
defaultMessage:
|
||||
"You've selected {count} tags. Consider reducing to 12 or fewer to keep your server focused and easier to discover.",
|
||||
},
|
||||
tooManyTagsProjectWarning: {
|
||||
id: 'project.settings.tags.too-many-tags-project-warning',
|
||||
defaultMessage:
|
||||
"You've selected {count} tags. Consider reducing to 8 or fewer to keep your project focused and easier to discover.",
|
||||
},
|
||||
multipleResolutionTagsWarning: {
|
||||
id: 'project.settings.tags.multiple-resolution-tags-warning',
|
||||
defaultMessage:
|
||||
"You've selected {count} resolution tags ({tags}). Resource packs should typically only have one resolution tag.",
|
||||
},
|
||||
allTagsSelectedWarning: {
|
||||
id: 'project.settings.tags.all-tags-selected-warning',
|
||||
defaultMessage:
|
||||
"You've selected all {count} available tags. Please select only the tags that truly apply to your project.",
|
||||
},
|
||||
})
|
||||
|
||||
const { projectV2: project, projectV3, patchProject } = injectProjectPageContext()
|
||||
|
||||
const formatCategoryName = (categoryName: string) => {
|
||||
@@ -268,12 +353,12 @@ const tooManyTagsWarning = computed(() => {
|
||||
const tagCount = current.value.selectedTags.length
|
||||
if (projectV3?.value?.minecraft_server != null) {
|
||||
if (tagCount > 18) {
|
||||
return `You've selected ${tagCount} tags. Please reduce to 18 or fewer to keep your server focused and easier to discover.`
|
||||
return formatMessage(messages.tooManyTagsServerHardWarning, { count: tagCount })
|
||||
} else if (tagCount > 12) {
|
||||
return `You've selected ${tagCount} tags. Consider reducing to 12 or fewer to keep your server focused and easier to discover.`
|
||||
return formatMessage(messages.tooManyTagsServerSoftWarning, { count: tagCount })
|
||||
}
|
||||
} else if (tagCount > 8) {
|
||||
return `You've selected ${tagCount} tags. Consider reducing to 8 or fewer to keep your project focused and easier to discover.`
|
||||
return formatMessage(messages.tooManyTagsProjectWarning, { count: tagCount })
|
||||
}
|
||||
return null
|
||||
})
|
||||
@@ -286,14 +371,15 @@ const multipleResolutionTagsWarning = computed(() => {
|
||||
)
|
||||
|
||||
if (resolutionTags.length > 1) {
|
||||
return `You've selected ${resolutionTags.length} resolution tags (${resolutionTags
|
||||
const tagsList = resolutionTags
|
||||
.map((t) => t.name)
|
||||
.join(', ')
|
||||
.replace('8x-', '8x or lower')
|
||||
.replace(
|
||||
'512x+',
|
||||
'512x or higher',
|
||||
)}). Resource packs should typically only have one resolution tag.`
|
||||
.replace('512x+', '512x or higher')
|
||||
return formatMessage(messages.multipleResolutionTagsWarning, {
|
||||
count: resolutionTags.length,
|
||||
tags: tagsList,
|
||||
})
|
||||
}
|
||||
return null
|
||||
})
|
||||
@@ -310,7 +396,9 @@ const allTagsSelectedWarning = computed(() => {
|
||||
totalSelectedTags === categoriesForProjectType.length &&
|
||||
categoriesForProjectType.length > 0
|
||||
) {
|
||||
return `You've selected all ${categoriesForProjectType.length} available tags. Please select only the tags that truly apply to your project.`
|
||||
return formatMessage(messages.allTagsSelectedWarning, {
|
||||
count: categoriesForProjectType.length,
|
||||
})
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
<ConfirmModal
|
||||
v-if="currentMember"
|
||||
ref="deleteVersionModal"
|
||||
title="Are you sure you want to delete this version?"
|
||||
description="This will remove this version forever (like really forever)."
|
||||
:title="formatMessage(messages.deleteVersionConfirmTitle)"
|
||||
:description="formatMessage(messages.deleteVersionConfirmDescription)"
|
||||
:has-to-type="false"
|
||||
proceed-label="Delete"
|
||||
:proceed-label="formatMessage(messages.deleteButton)"
|
||||
@proceed="deleteVersion()"
|
||||
/>
|
||||
<Admonition
|
||||
@@ -69,7 +69,7 @@
|
||||
<template #actions="{ version }">
|
||||
<ButtonStyled circular type="transparent">
|
||||
<OverflowMenu
|
||||
v-tooltip="'Edit version'"
|
||||
v-tooltip="formatMessage(messages.editVersionTooltip)"
|
||||
class="hover:!bg-button-bg [&>svg]:!text-green"
|
||||
:dropdown-id="`${baseDropdownId}-edit-${version.id}`"
|
||||
:options="[
|
||||
@@ -86,26 +86,26 @@
|
||||
action: () => handleOpenEditVersionModal(version.id, project.id, 'add-files'),
|
||||
},
|
||||
]"
|
||||
aria-label="Edit version"
|
||||
:aria-label="formatMessage(messages.editVersionTooltip)"
|
||||
>
|
||||
<EditIcon aria-hidden="true" />
|
||||
<template #edit-files>
|
||||
<FileIcon aria-hidden="true" />
|
||||
Edit files
|
||||
{{ formatMessage(messages.editFilesOption) }}
|
||||
</template>
|
||||
<template #edit-details>
|
||||
<InfoIcon aria-hidden="true" />
|
||||
Edit details
|
||||
{{ formatMessage(messages.editDetailsOption) }}
|
||||
</template>
|
||||
<template #edit-metadata>
|
||||
<BoxIcon aria-hidden="true" />
|
||||
Edit metadata
|
||||
{{ formatMessage(messages.editMetadataOption) }}
|
||||
</template>
|
||||
</OverflowMenu>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled circular type="transparent">
|
||||
<OverflowMenu
|
||||
v-tooltip="'More options'"
|
||||
v-tooltip="formatMessage(commonMessages.moreOptionsButton)"
|
||||
class="hover:!bg-button-bg"
|
||||
:dropdown-id="`${baseDropdownId}-${version.id}`"
|
||||
:options="[
|
||||
@@ -192,52 +192,52 @@
|
||||
shown: !!currentMember,
|
||||
},
|
||||
]"
|
||||
aria-label="More options"
|
||||
:aria-label="formatMessage(commonMessages.moreOptionsButton)"
|
||||
>
|
||||
<MoreVerticalIcon aria-hidden="true" />
|
||||
<template #download>
|
||||
<DownloadIcon aria-hidden="true" />
|
||||
Download
|
||||
{{ formatMessage(commonMessages.downloadButton) }}
|
||||
</template>
|
||||
<template #new-tab>
|
||||
<ExternalIcon aria-hidden="true" />
|
||||
Open in new tab
|
||||
{{ formatMessage(messages.openInNewTabOption) }}
|
||||
</template>
|
||||
<template #copy-link>
|
||||
<LinkIcon aria-hidden="true" />
|
||||
Copy link
|
||||
{{ formatMessage(messages.copyLinkOption) }}
|
||||
</template>
|
||||
<template #share>
|
||||
<ShareIcon aria-hidden="true" />
|
||||
Share
|
||||
{{ formatMessage(messages.shareOption) }}
|
||||
</template>
|
||||
<template #report>
|
||||
<ReportIcon aria-hidden="true" />
|
||||
Report
|
||||
{{ formatMessage(commonMessages.reportButton) }}
|
||||
</template>
|
||||
<template #edit-files>
|
||||
<FileIcon aria-hidden="true" />
|
||||
Edit files
|
||||
{{ formatMessage(messages.editFilesOption) }}
|
||||
</template>
|
||||
<template #edit-details>
|
||||
<InfoIcon aria-hidden="true" />
|
||||
Edit details
|
||||
{{ formatMessage(messages.editDetailsOption) }}
|
||||
</template>
|
||||
<template #edit-metadata>
|
||||
<BoxIcon aria-hidden="true" />
|
||||
Edit metadata
|
||||
{{ formatMessage(messages.editMetadataOption) }}
|
||||
</template>
|
||||
<template #delete>
|
||||
<TrashIcon aria-hidden="true" />
|
||||
Delete
|
||||
{{ formatMessage(commonMessages.deleteLabel) }}
|
||||
</template>
|
||||
<template #copy-id>
|
||||
<ClipboardCopyIcon aria-hidden="true" />
|
||||
Copy ID
|
||||
{{ formatMessage(messages.copyIdOption) }}
|
||||
</template>
|
||||
<template #copy-maven>
|
||||
<ClipboardCopyIcon aria-hidden="true" />
|
||||
Copy Maven coordinates
|
||||
{{ formatMessage(messages.copyMavenCoordinatesOption) }}
|
||||
</template>
|
||||
</OverflowMenu>
|
||||
</ButtonStyled>
|
||||
@@ -336,6 +336,7 @@ import {
|
||||
import {
|
||||
Admonition,
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
commonProjectSettingsMessages,
|
||||
ConfirmModal,
|
||||
defineMessages,
|
||||
@@ -444,13 +445,13 @@ async function deleteVersion() {
|
||||
await client.labrinth.versions_v3.deleteVersion(id)
|
||||
|
||||
addNotification({
|
||||
title: 'Version deleted',
|
||||
text: 'The version has been successfully deleted.',
|
||||
title: formatMessage(messages.versionDeletedTitle),
|
||||
text: formatMessage(messages.versionDeletedText),
|
||||
type: 'success',
|
||||
})
|
||||
} catch (err: any) {
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||
text: err.data ? err.data.description : err,
|
||||
type: 'error',
|
||||
})
|
||||
@@ -477,5 +478,61 @@ const messages = defineMessages({
|
||||
defaultMessage:
|
||||
'{count, plural, one {This version is} other {These versions are}} currently withheld and not publicly listed. Please provide proof that you have permission to redistribute certain files included in the modpack {count, plural, one {version} other {versions}}.',
|
||||
},
|
||||
deleteVersionConfirmTitle: {
|
||||
id: 'project.versions.delete-confirm.title',
|
||||
defaultMessage: 'Are you sure you want to delete this version?',
|
||||
},
|
||||
deleteVersionConfirmDescription: {
|
||||
id: 'project.versions.delete-confirm.description',
|
||||
defaultMessage: 'This will remove this version forever (like really forever).',
|
||||
},
|
||||
deleteButton: {
|
||||
id: 'project.versions.delete-button',
|
||||
defaultMessage: 'Delete',
|
||||
},
|
||||
editVersionTooltip: {
|
||||
id: 'project.versions.edit-version-tooltip',
|
||||
defaultMessage: 'Edit version',
|
||||
},
|
||||
editFilesOption: {
|
||||
id: 'project.versions.edit-files-option',
|
||||
defaultMessage: 'Edit files',
|
||||
},
|
||||
editDetailsOption: {
|
||||
id: 'project.versions.edit-details-option',
|
||||
defaultMessage: 'Edit details',
|
||||
},
|
||||
editMetadataOption: {
|
||||
id: 'project.versions.edit-metadata-option',
|
||||
defaultMessage: 'Edit metadata',
|
||||
},
|
||||
openInNewTabOption: {
|
||||
id: 'project.versions.open-in-new-tab-option',
|
||||
defaultMessage: 'Open in new tab',
|
||||
},
|
||||
copyLinkOption: {
|
||||
id: 'project.versions.copy-link-option',
|
||||
defaultMessage: 'Copy link',
|
||||
},
|
||||
shareOption: {
|
||||
id: 'project.versions.share-option',
|
||||
defaultMessage: 'Share',
|
||||
},
|
||||
copyIdOption: {
|
||||
id: 'project.versions.copy-id-option',
|
||||
defaultMessage: 'Copy ID',
|
||||
},
|
||||
copyMavenCoordinatesOption: {
|
||||
id: 'project.versions.copy-maven-coordinates-option',
|
||||
defaultMessage: 'Copy Maven coordinates',
|
||||
},
|
||||
versionDeletedTitle: {
|
||||
id: 'project.versions.version-deleted-title',
|
||||
defaultMessage: 'Version deleted',
|
||||
},
|
||||
versionDeletedText: {
|
||||
id: 'project.versions.version-deleted-text',
|
||||
defaultMessage: 'The version has been successfully deleted.',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -832,8 +832,8 @@ const deleteVersionMutation = useMutation({
|
||||
mutationFn: () => client.labrinth.versions_v3.deleteVersion(version.value!.id),
|
||||
onSuccess: async () => {
|
||||
addNotification({
|
||||
title: 'Version deleted',
|
||||
text: 'The version has been successfully deleted.',
|
||||
title: formatMessage(messages.versionDeletedTitle),
|
||||
text: formatMessage(messages.versionDeletedText),
|
||||
type: 'success',
|
||||
})
|
||||
await invalidate()
|
||||
@@ -841,7 +841,7 @@ const deleteVersionMutation = useMutation({
|
||||
},
|
||||
onError: (err: { data?: { description?: string } }) => {
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||
text: err.data?.description ?? String(err),
|
||||
type: 'error',
|
||||
})
|
||||
@@ -894,8 +894,8 @@ const createDataPackVersionMutation = useMutation({
|
||||
packageModal.value?.hide()
|
||||
|
||||
addNotification({
|
||||
title: 'Packaging Success',
|
||||
text: 'Your data pack was successfully packaged as a mod! Make sure to playtest to check for errors.',
|
||||
title: formatMessage(messages.packagingSuccessTitle),
|
||||
text: formatMessage(messages.packagingSuccessText),
|
||||
type: 'success',
|
||||
})
|
||||
|
||||
@@ -906,7 +906,7 @@ const createDataPackVersionMutation = useMutation({
|
||||
},
|
||||
onError: (err: { data?: { description?: string } }) => {
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||
text: err.data?.description ?? String(err),
|
||||
type: 'error',
|
||||
})
|
||||
@@ -939,6 +939,23 @@ const messages = defineMessages({
|
||||
id: 'version.download.no-primary-file',
|
||||
defaultMessage: 'Error: No primary file found',
|
||||
},
|
||||
versionDeletedTitle: {
|
||||
id: 'version.notification.deleted-title',
|
||||
defaultMessage: 'Version deleted',
|
||||
},
|
||||
versionDeletedText: {
|
||||
id: 'version.notification.deleted-text',
|
||||
defaultMessage: 'The version has been successfully deleted.',
|
||||
},
|
||||
packagingSuccessTitle: {
|
||||
id: 'version.notification.packaging-success-title',
|
||||
defaultMessage: 'Packaging Success',
|
||||
},
|
||||
packagingSuccessText: {
|
||||
id: 'version.notification.packaging-success-text',
|
||||
defaultMessage:
|
||||
'Your data pack was successfully packaged as a mod! Make sure to playtest to check for errors.',
|
||||
},
|
||||
downloadVersion: {
|
||||
id: 'version.download.version',
|
||||
defaultMessage: 'Download {version} ({size})',
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
:show-icon="false"
|
||||
accept="image/png,image/jpeg,image/gif,image/webp"
|
||||
class="hidden"
|
||||
aria-label="Upload icon"
|
||||
:aria-label="formatMessage(messages.uploadIconAriaLabel)"
|
||||
@change="showPreviewImage"
|
||||
/>
|
||||
</div>
|
||||
@@ -371,7 +371,7 @@
|
||||
<ButtonStyled v-if="auth.user && auth.user.id === creator.id" color="brand">
|
||||
<nuxt-link class="mx-auto w-min" to="/discover/mods">
|
||||
<CompassIcon class="size-5" />
|
||||
Discover mods
|
||||
{{ formatMessage(messages.discoverModsButton) }}
|
||||
</nuxt-link>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
@@ -534,6 +534,14 @@ const messages = defineMessages({
|
||||
id: 'collection.label.no-projects',
|
||||
defaultMessage: 'No projects in collection yet',
|
||||
},
|
||||
discoverModsButton: {
|
||||
id: 'collection.button.discover-mods',
|
||||
defaultMessage: 'Discover mods',
|
||||
},
|
||||
uploadIconAriaLabel: {
|
||||
id: 'collection.aria-label.upload-icon',
|
||||
defaultMessage: 'Upload icon',
|
||||
},
|
||||
projectsCountLabel: {
|
||||
id: 'collection.label.projects-count',
|
||||
defaultMessage: '{count, plural, =0 {No projects yet} other {<stat>{count}</stat> {type}}}',
|
||||
|
||||
@@ -680,6 +680,31 @@ const formatPrice = useFormatPrice()
|
||||
const flags = useFeatureFlags()
|
||||
|
||||
const messages = defineMessages({
|
||||
errorFetchingPaymentDataTitle: {
|
||||
id: 'hosting-marketing.notification.error-fetching-payment-data-title',
|
||||
defaultMessage: 'Error fetching payment data',
|
||||
},
|
||||
unexpectedErrorText: {
|
||||
id: 'hosting-marketing.notification.unexpected-error-text',
|
||||
defaultMessage: 'An unexpected error occurred',
|
||||
},
|
||||
serverCapacityFullTitle: {
|
||||
id: 'hosting-marketing.notification.server-capacity-full-title',
|
||||
defaultMessage: 'Server Capacity Full',
|
||||
},
|
||||
serverCapacityFullText: {
|
||||
id: 'hosting-marketing.notification.server-capacity-full-text',
|
||||
defaultMessage: 'We are currently at capacity. Please try again later.',
|
||||
},
|
||||
invalidProductTitle: {
|
||||
id: 'hosting-marketing.notification.invalid-product-title',
|
||||
defaultMessage: 'Invalid product',
|
||||
},
|
||||
invalidProductText: {
|
||||
id: 'hosting-marketing.notification.invalid-product-text',
|
||||
defaultMessage:
|
||||
'The selected product was found but lacks necessary data. Please contact support.',
|
||||
},
|
||||
hostWithModrinth: {
|
||||
id: 'hosting-marketing.hero.host-with-modrinth',
|
||||
defaultMessage: 'Host your next server with Modrinth Hosting',
|
||||
@@ -1106,7 +1131,7 @@ const startTyping = () => {
|
||||
|
||||
const handleError = (err) => {
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||
type: 'error',
|
||||
text: err.message ?? (err.data ? err.data.description : err),
|
||||
})
|
||||
@@ -1124,9 +1149,9 @@ async function fetchPaymentData() {
|
||||
} catch (error) {
|
||||
console.error('Error fetching payment data:', error)
|
||||
addNotification({
|
||||
title: 'Error fetching payment data',
|
||||
title: formatMessage(messages.errorFetchingPaymentDataTitle),
|
||||
type: 'error',
|
||||
text: error.message || 'An unexpected error occurred',
|
||||
text: error.message || formatMessage(messages.unexpectedErrorText),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1177,9 +1202,9 @@ const selectProduct = async (product) => {
|
||||
|
||||
if ((product === 'custom' && isCustomAtCapacity.value) || isAtCapacity.value) {
|
||||
addNotification({
|
||||
title: 'Server Capacity Full',
|
||||
title: formatMessage(messages.serverCapacityFullTitle),
|
||||
type: 'error',
|
||||
text: 'We are currently at capacity. Please try again later.',
|
||||
text: formatMessage(messages.serverCapacityFullText),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -1192,9 +1217,9 @@ const selectProduct = async (product) => {
|
||||
(product !== 'custom' && !selectedPlan.metadata)
|
||||
) {
|
||||
addNotification({
|
||||
title: 'Invalid product',
|
||||
title: formatMessage(messages.invalidProductTitle),
|
||||
type: 'error',
|
||||
text: 'The selected product was found but lacks necessary data. Please contact support.',
|
||||
text: formatMessage(messages.invalidProductText),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -205,11 +205,16 @@
|
||||
<UpToDate class="icon" />
|
||||
<br />
|
||||
<span class="preserve-lines text">
|
||||
This organization doesn't have any projects yet.
|
||||
<template v-if="isPermission(currentMember?.permissions, 1 << 4)">
|
||||
Would you like to
|
||||
<a class="link" @click="modal_creation?.show()">create one</a>?
|
||||
<IntlFormatted :message-id="messages.noProjectsWithCreatePrompt">
|
||||
<template #create-link="{ children }">
|
||||
<a class="link" @click="modal_creation?.show()"
|
||||
><component :is="() => normalizeChildren(children)"
|
||||
/></a>
|
||||
</template>
|
||||
</IntlFormatted>
|
||||
</template>
|
||||
<template v-else>{{ formatMessage(messages.noProjects) }}</template>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -233,8 +238,11 @@ import {
|
||||
Avatar,
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
defineMessages,
|
||||
injectModrinthClient,
|
||||
IntlFormatted,
|
||||
NavTabs,
|
||||
normalizeChildren,
|
||||
PROJECT_DEP_MARKER_QUERY,
|
||||
ProjectCard,
|
||||
ProjectCardList,
|
||||
@@ -266,6 +274,18 @@ type ProjectV3 = Labrinth.Projects.v3.Project & {
|
||||
const vintl = useVIntl()
|
||||
const { formatMessage } = vintl
|
||||
|
||||
const messages = defineMessages({
|
||||
noProjects: {
|
||||
id: 'organization.projects.none',
|
||||
defaultMessage: "This organization doesn't have any projects yet.",
|
||||
},
|
||||
noProjectsWithCreatePrompt: {
|
||||
id: 'organization.projects.none-with-create-prompt',
|
||||
defaultMessage:
|
||||
"This organization doesn't have any projects yet. Would you like to <create-link>create one</create-link>?",
|
||||
},
|
||||
})
|
||||
|
||||
const { formatCompactNumber } = useCompactNumber()
|
||||
|
||||
const auth: { user: any } & any = await useAuth()
|
||||
|
||||
@@ -288,6 +288,7 @@ import {
|
||||
AutoLink,
|
||||
Avatar,
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
defineMessage,
|
||||
defineMessages,
|
||||
formatReportItemType,
|
||||
@@ -480,7 +481,7 @@ const submitReport = async () => {
|
||||
|
||||
if (error instanceof Error) {
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||
text: error.message,
|
||||
type: 'error',
|
||||
})
|
||||
@@ -505,7 +506,7 @@ const submitReport = async () => {
|
||||
|
||||
if (error instanceof Error) {
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||
text: error.message,
|
||||
type: 'error',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user