fix: i18n string problems (#6131)

* fix: apply non-json i18n fixes

* fix: pruning

* fix: prepr

* fix: run.mjs

* fix: lint
This commit is contained in:
Calum H.
2026-05-29 15:55:39 +00:00
committed by GitHub
parent 5c1ffd9ff2
commit 047b8c3bf7
165 changed files with 1283 additions and 5626 deletions
@@ -14,7 +14,7 @@ import ProjectCardList from '#ui/components/project/ProjectCardList.vue'
import SearchFilterControl from '#ui/components/search/SearchFilterControl.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { useStickyObserver } from '#ui/composables/sticky-observer'
import { commonMessages } from '#ui/utils/common-messages'
import { commonMessages, formatProjectTypeSentence } from '#ui/utils/common-messages'
import type { SortType } from '#ui/utils/search'
import SelectedProjectsFloatingBar from './components/SelectedProjectsFloatingBar.vue'
@@ -47,8 +47,7 @@ const maxResultsOptions = computed<ComboboxOption<number>[]>(() =>
const messages = defineMessages({
searchPlaceholder: {
id: 'browse.search.placeholder',
defaultMessage:
'Search {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} server {servers} other {projects}}...',
defaultMessage: 'Search {projectType}...',
},
viewPrefix: {
id: 'browse.view-prefix',
@@ -88,7 +87,11 @@ const messages = defineMessages({
:icon="SearchIcon"
type="text"
autocomplete="off"
:placeholder="formatMessage(messages.searchPlaceholder, { projectType: ctx.projectType.value })"
:placeholder="
formatMessage(messages.searchPlaceholder, {
projectType: formatProjectTypeSentence(formatMessage, ctx.projectType.value, 2),
})
"
clearable
wrapper-class="w-full"
:input-class="ctx.variant === 'web' ? '!h-12' : 'h-12'"
@@ -6,7 +6,7 @@ import Avatar from '#ui/components/base/Avatar.vue'
import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
import FloatingActionBar from '#ui/components/base/FloatingActionBar.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { commonMessages } from '#ui/utils/common-messages'
import { commonMessages, formatContentTypeSentence } from '#ui/utils/common-messages'
import type { BulkOperationType } from '../composables/bulk-operations'
import type { ContentItem } from '../types'
@@ -16,7 +16,7 @@ const { formatMessage } = useVIntl()
const messages = defineMessages({
selectedCount: {
id: 'content.selection-bar.selected-count',
defaultMessage: '{count} {contentType} selected',
defaultMessage: '{count, number} {contentType} selected',
},
selectedCountSimple: {
id: 'content.selection-bar.selected-count-simple',
@@ -116,7 +116,7 @@ const selectedCountText = computed(() => {
if (props.contentTypeLabel) {
return formatMessage(messages.selectedCount, {
count,
contentType: `${props.contentTypeLabel}${count === 1 ? '' : 's'}`,
contentType: formatContentTypeSentence(formatMessage, props.contentTypeLabel, count),
})
}
return formatMessage(messages.selectedCountSimple, { count })
@@ -124,9 +124,6 @@ const selectedCountText = computed(() => {
const bulkProgressMessage = computed(() => {
if (!props.bulkOperation) return ''
const contentType = props.contentTypeLabel
? `${props.contentTypeLabel}${props.bulkTotal === 1 ? '' : 's'}`
: 'items'
const messageMap = {
enable: props.bulkWaiting ? messages.bulkEnablingWaiting : messages.bulkEnabling,
disable: props.bulkWaiting ? messages.bulkDisablingWaiting : messages.bulkDisabling,
@@ -136,7 +133,7 @@ const bulkProgressMessage = computed(() => {
return formatMessage(messageMap[props.bulkOperation], {
progress: props.bulkProgress,
total: props.bulkTotal,
contentType,
contentType: formatContentTypeSentence(formatMessage, props.contentTypeLabel, props.bulkTotal),
})
})
</script>
@@ -1,7 +1,11 @@
<template>
<NewModal
ref="modal"
:header="formatMessage(messages.header, { count, itemType })"
:header="
formatMessage(messages.header, {
itemType: formatContentTypeSentence(formatMessage, itemType, count),
})
"
:fade="variant === 'server' ? 'warning' : 'danger'"
max-width="500px"
:on-hide="() => backupCreator?.cancelBackup()"
@@ -31,7 +35,12 @@
<ButtonStyled :color="variant === 'server' ? 'orange' : 'red'">
<button :disabled="buttonsDisabled" @click="confirm">
<TrashIcon />
{{ formatMessage(messages.deleteButton, { count, itemType }) }}
{{
formatMessage(messages.deleteButton, {
count,
itemType: formatContentTypeSentence(formatMessage, itemType, count),
})
}}
</button>
</ButtonStyled>
</div>
@@ -47,7 +56,7 @@ import Admonition from '#ui/components/base/Admonition.vue'
import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
import NewModal from '#ui/components/modal/NewModal.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { commonMessages } from '#ui/utils/common-messages'
import { commonMessages, formatContentTypeSentence } from '#ui/utils/common-messages'
import InlineBackupCreator from './InlineBackupCreator.vue'
@@ -56,7 +65,7 @@ const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'content.confirm-deletion.header',
defaultMessage: 'Delete {itemType}{count, plural, one {} other {s}}',
defaultMessage: 'Delete {itemType}',
},
admonitionHeader: {
id: 'content.confirm-deletion.admonition-header',
@@ -69,7 +78,7 @@ const messages = defineMessages({
},
deleteButton: {
id: 'content.confirm-deletion.delete-button',
defaultMessage: 'Delete {count} {itemType}{count, plural, one {} other {s}}',
defaultMessage: 'Delete {count, number} {itemType}',
},
})
@@ -1,11 +1,15 @@
<template>
<NewModal
ref="modal"
:header="formatMessage(messages.header, { type: server ? 'server' : 'instance' })"
:header="
formatMessage(messages.header, {
type: formatMessage(server ? messages.serverLabel : messages.instanceLabel),
})
"
max-width="500px"
>
<span class="text-primary">
{{ formatMessage(messages.body, { type: server ? 'server' : 'instance' }) }}
{{ formatMessage(server ? messages.serverBody : messages.instanceBody) }}
</span>
<template #actions>
@@ -45,17 +49,30 @@ const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'instance.confirm-repair.header',
defaultMessage: 'Repair {type, select, server {server} other {instance}}',
defaultMessage: 'Repair {type}',
},
body: {
id: 'instance.confirm-repair.body',
instanceBody: {
id: 'instance.confirm-repair.body.instance',
defaultMessage:
'Repairing reinstalls the loader and Minecraft dependencies without deleting your content. This may resolve issues if your {type, select, server {server is not starting correctly} other {game is not launching due to launcher-related errors}}.',
'Repairing reinstalls the loader and Minecraft dependencies without deleting your content. This may resolve issues if your game is not launching due to launcher-related errors.',
},
serverBody: {
id: 'instance.confirm-repair.body.server',
defaultMessage:
'Repairing reinstalls the loader and Minecraft dependencies without deleting your content. This may resolve issues if your server is not starting correctly.',
},
repairButton: {
id: 'instance.confirm-repair.repair-button',
defaultMessage: 'Repair',
},
instanceLabel: {
id: 'instance.confirm-repair.instance-label',
defaultMessage: 'instance',
},
serverLabel: {
id: 'instance.confirm-repair.server-label',
defaultMessage: 'server',
},
})
const emit = defineEmits<{
@@ -28,7 +28,7 @@
<ButtonStyled color="orange">
<button :disabled="buttonsDisabled" @click="confirm">
<UnlinkIcon />
{{ formatMessage(server ? messages.header : messages.unlinkButton) }}
{{ formatMessage(messages.unlinkButton) }}
</button>
</ButtonStyled>
</div>
@@ -49,7 +49,13 @@
<span class="font-semibold text-contrast">
{{ formatMessage(messages.instanceType) }}
</span>
<Chips v-model="tab" :items="tabs" :format-label="formatTabLabel" :never-empty="true" />
<Chips
v-model="tab"
:items="tabs"
:format-label="formatTabLabel"
:never-empty="true"
:capitalize="false"
/>
</div>
<div class="h-px bg-divider" />
@@ -1,7 +1,11 @@
<template>
<div class="flex flex-col gap-3">
<span class="text-primary">
{{ formatMessage(messages.warningBody, { type: backup.isServer ? 'server' : 'instance' }) }}
{{
formatMessage(messages.warningBody, {
type: formatMessage(backup.isServer ? messages.worldLabel : messages.instanceLabel),
})
}}
</span>
<div v-if="backup.available" class="flex items-center gap-2">
@@ -88,7 +92,15 @@ const messages = defineMessages({
warningBody: {
id: 'content.inline-backup.warning-body',
defaultMessage:
'We recommend creating a backup before proceeding so you can restore your {type, select, server {world} other {instance}} if anything breaks.',
'We recommend creating a backup before proceeding so you can restore your {type} if anything breaks.',
},
worldLabel: {
id: 'content.inline-backup.world-label',
defaultMessage: 'world',
},
instanceLabel: {
id: 'content.inline-backup.instance-label',
defaultMessage: 'instance',
},
createBackup: {
id: 'content.inline-backup.create-backup',
@@ -26,7 +26,7 @@ import OverflowMenu from '#ui/components/base/OverflowMenu.vue'
import StyledInput from '#ui/components/base/StyledInput.vue'
import { useDebugLogger } from '#ui/composables/debug-logger'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { commonMessages } from '#ui/utils/common-messages'
import { commonMessages, formatContentTypeSentence } from '#ui/utils/common-messages'
import ContentCardTable from './components/ContentCardTable.vue'
import ContentModpackCard from './components/ContentModpackCard.vue'
@@ -73,7 +73,7 @@ const messages = defineMessages({
},
searchPlaceholder: {
id: 'content.page-layout.search-placeholder',
defaultMessage: 'Search {count} {contentType}...',
defaultMessage: 'Search {count, number} {contentType}...',
},
browseContent: {
id: 'content.page-layout.browse-content',
@@ -562,7 +562,11 @@ const confirmUnlinkModal = ref<InstanceType<typeof ConfirmUnlinkModal>>()
:placeholder="
formatMessage(messages.searchPlaceholder, {
count: tableItems.length,
contentType: `${ctx.contentTypeLabel.value}${tableItems.length === 1 ? '' : 's'}`,
contentType: formatContentTypeSentence(
formatMessage,
ctx.contentTypeLabel.value,
tableItems.length,
),
})
"
/>
@@ -717,7 +721,12 @@ const confirmUnlinkModal = ref<InstanceType<typeof ConfirmUnlinkModal>>()
ctx.modpack.value
? formatMessage(messages.emptyModpackHint)
: formatMessage(messages.emptyHint, {
contentType: `${ctx.contentTypeLabel.value}s`,
contentType: formatContentTypeSentence(
formatMessage,
ctx.contentTypeLabel.value,
2,
'content',
),
})
}}
</template>
@@ -1,5 +1,13 @@
<template>
<NewModal ref="modal" :header="formatMessage(messages.header, { type })" max-width="500px">
<NewModal
ref="modal"
:header="
formatMessage(messages.header, {
type: formatFileItemType(formatMessage, type),
})
"
max-width="500px"
>
<form class="space-y-6 md:min-w-[400px]" @submit.prevent="handleSubmit">
<label class="flex flex-col gap-2">
<span class="font-semibold text-contrast">{{
@@ -29,7 +37,11 @@
<ButtonStyled color="brand">
<button :disabled="!!error && submitted" @click="handleSubmit">
<PlusIcon class="h-5 w-5" />
{{ formatMessage(messages.createButton, { type }) }}
{{
formatMessage(messages.createButton, {
type: formatFileItemType(formatMessage, type),
})
}}
</button>
</ButtonStyled>
</div>
@@ -45,7 +57,7 @@ import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
import StyledInput from '#ui/components/base/StyledInput.vue'
import NewModal from '#ui/components/modal/NewModal.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { commonMessages } from '#ui/utils/common-messages'
import { commonMessages, formatFileItemType } from '#ui/utils/common-messages'
import { fileValidationMessages } from './file-validation-messages'
@@ -54,7 +66,7 @@ const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'files.create-modal.header',
defaultMessage: 'Create a {type, select, directory {folder} other {file}}',
defaultMessage: 'Create a {type}',
},
placeholderFile: {
id: 'files.create-modal.placeholder-file',
@@ -66,7 +78,7 @@ const messages = defineMessages({
},
createButton: {
id: 'files.create-modal.create-button',
defaultMessage: 'Create {type, select, directory {folder} other {file}}',
defaultMessage: 'Create {type}',
},
})
@@ -2,7 +2,11 @@
<NewModal ref="modal" fade="danger" :header="formatMessage(messages.header)" max-width="500px">
<Admonition type="critical" class="md:min-w-[400px]">
<template #header>{{ formatMessage(messages.deletingName, { name: item?.name }) }}</template>
{{ formatMessage(messages.deleteWarning, { type: item?.type }) }}
{{
formatMessage(
item?.type === 'directory' ? messages.deleteFolderWarning : messages.deleteFileWarning,
)
}}
</Admonition>
<template #actions>
<div class="flex gap-2 justify-end">
@@ -46,10 +50,14 @@ const messages = defineMessages({
id: 'files.delete-modal.deleting-name',
defaultMessage: 'Deleting "{name}"',
},
deleteWarning: {
id: 'files.delete-modal.warning',
deleteFileWarning: {
id: 'files.delete-modal.warning.file',
defaultMessage: 'This file will be permanently deleted. This action cannot be undone.',
},
deleteFolderWarning: {
id: 'files.delete-modal.warning.folder',
defaultMessage:
'{type, select, directory {This folder and all its contents will be permanently deleted. This action cannot be undone.} other {This file will be permanently deleted. This action cannot be undone.}}',
'This folder and all its contents will be permanently deleted. This action cannot be undone.',
},
})
@@ -1,7 +1,11 @@
<template>
<NewModal
ref="modal"
:header="formatMessage(messages.header, { type: item?.type })"
:header="
formatMessage(messages.header, {
type: formatFileItemType(formatMessage, item?.type),
})
"
max-width="500px"
>
<form class="space-y-6 md:min-w-[400px]" @submit.prevent="handleSubmit">
@@ -50,7 +54,7 @@ import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
import StyledInput from '#ui/components/base/StyledInput.vue'
import NewModal from '#ui/components/modal/NewModal.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { commonMessages } from '#ui/utils/common-messages'
import { commonMessages, formatFileItemType } from '#ui/utils/common-messages'
import type { FileItem } from '../../types'
@@ -59,7 +63,7 @@ const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'files.move-modal.header',
defaultMessage: '{type, select, directory {Move folder} other {Move file}}',
defaultMessage: 'Move {type}',
},
currentLocation: {
id: 'files.move-modal.current-location',
@@ -28,7 +28,7 @@
<div
v-for="(file, index) in files"
:key="file"
class="grid grid-cols-[auto_auto_1fr] items-center min-h-10 h-10 gap-2"
class="grid grid-cols-[auto_minmax(0,1fr)] items-center min-h-10 h-10 gap-2"
>
<div class="flex flex-col items-center justify-between">
<div class="w-[1px] h-2"></div>
@@ -38,14 +38,17 @@
class="w-[1px] h-2 relative top-1"
></div>
</div>
<span class="text-sm shrink-0 whitespace-nowrap">{{
formatMessage(messages.overwrittenLabel)
}}</span>
<span
v-tooltip="file"
class="text-sm text-contrast font-medium whitespace-nowrap overflow-hidden text-ellipsis"
>
{{ file }}
<span class="flex min-w-0 text-sm whitespace-nowrap overflow-hidden">
<IntlFormatted :message-id="messages.overwriteFileLabel" :values="{ path: file }">
<template #file-path="{ children }">
<span
v-tooltip="file"
class="min-w-0 text-contrast font-medium whitespace-nowrap overflow-hidden text-ellipsis"
>
<component :is="() => children" />
</span>
</template>
</IntlFormatted>
</span>
</div>
</div>
@@ -76,6 +79,7 @@ import { computed, ref } from 'vue'
import Admonition from '#ui/components/base/Admonition.vue'
import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
import IntlFormatted from '#ui/components/base/IntlFormatted.vue'
import NewModal from '#ui/components/modal/NewModal.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { commonMessages } from '#ui/utils/common-messages'
@@ -105,9 +109,9 @@ const messages = defineMessages({
id: 'files.conflict-modal.overwritten-count',
defaultMessage: '{count} overwritten',
},
overwrittenLabel: {
id: 'files.conflict-modal.overwritten-label',
defaultMessage: 'Overwritten',
overwriteFileLabel: {
id: 'files.conflict-modal.overwrite-file-label',
defaultMessage: 'Will overwrite <file-path>{path}</file-path>',
},
overwriteButton: {
id: 'files.conflict-modal.overwrite-button',
@@ -18,7 +18,7 @@
<p class="mt-2 text-xl">
{{
formatMessage(messages.dropToUpload, {
type: type ? type.toLocaleLowerCase() : undefined,
type: formatFileItemType(formatMessage, type?.toLocaleLowerCase(), true),
})
}}
</p>
@@ -32,6 +32,7 @@ import { UploadIcon } from '@modrinth/assets'
import { ref } from 'vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { formatFileItemType } from '#ui/utils/common-messages'
const { formatMessage } = useVIntl()
@@ -47,7 +48,7 @@ defineProps<{
const messages = defineMessages({
dropToUpload: {
id: 'files.upload.drag-and-drop.drop-to-upload',
defaultMessage: 'Drop {type, select, undefined {files} other {{type}s}} here to upload',
defaultMessage: 'Drop {type} here to upload',
},
})
@@ -186,7 +186,7 @@ defineExpose({
const messages = defineMessages({
linkedInstanceTitle: {
id: 'installation-settings.linked-instance.title',
defaultMessage: 'Linked {projectType, select, server {server project} other {modpack}}',
defaultMessage: 'Linked {projectType}',
},
reinstallModpackTitle: {
id: 'installation-settings.reinstall-modpack.title',
@@ -195,7 +195,7 @@ const messages = defineMessages({
reinstallModpackDescription: {
id: 'installation-settings.reinstall-modpack.description',
defaultMessage:
"Re-installing the modpack resets the {type, select, server {server's} other {instance's}} content to its original state, removing any mods or content you have added.",
'Re-installing the modpack resets the {type} content to its original state, removing any mods or content you have added.',
},
editInstallationTitle: {
id: 'installation-settings.edit-installation.title',
@@ -204,7 +204,7 @@ const messages = defineMessages({
unlinkDescription: {
id: 'installation-settings.unlink.description',
defaultMessage:
"Unlinking permanently disconnects this {type, select, server {server} other {instance}} from the {projectType, select, server {server} other {modpack}} project, allowing you to change the loader and Minecraft version, but you won't receive future updates.",
"Unlinking permanently disconnects this {type} from the {projectType} project, allowing you to change the loader and Minecraft version, but you won't receive future updates.",
},
repairInstanceTitle: {
id: 'installation-settings.repair.instance-title',
@@ -229,6 +229,30 @@ const messages = defineMessages({
defaultMessage:
"We don't recommend editing your installation settings after installing content. If you want to edit them, be cautious as it may cause issues.",
},
serverProjectLabel: {
id: 'installation-settings.linked.server-project',
defaultMessage: 'server project',
},
modpackLabel: {
id: 'installation-settings.linked.modpack',
defaultMessage: 'modpack',
},
serverLabel: {
id: 'installation-settings.type.server',
defaultMessage: 'server',
},
instanceLabel: {
id: 'installation-settings.type.instance',
defaultMessage: 'instance',
},
serverPossessiveLabel: {
id: 'installation-settings.type.server-possessive',
defaultMessage: "server's",
},
instancePossessiveLabel: {
id: 'installation-settings.type.instance-possessive',
defaultMessage: "instance's",
},
editWarningServer: {
id: 'installation-settings.edit.warning-server',
defaultMessage:
@@ -405,7 +429,9 @@ const messages = defineMessages({
<span class="text-lg font-semibold text-contrast">
{{
formatMessage(messages.linkedInstanceTitle, {
projectType: showModpackVersionActions ? 'modpack' : 'server',
projectType: formatMessage(
showModpackVersionActions ? messages.modpackLabel : messages.serverProjectLabel,
),
})
}}
</span>
@@ -430,8 +456,10 @@ const messages = defineMessages({
<span class="text-primary">
{{
formatMessage(messages.unlinkDescription, {
type: ctx.isServer ? 'server' : 'instance',
projectType: showModpackVersionActions ? 'modpack' : 'server',
type: formatMessage(ctx.isServer ? messages.serverLabel : messages.instanceLabel),
projectType: formatMessage(
showModpackVersionActions ? messages.modpackLabel : messages.serverLabel,
),
})
}}
</span>
@@ -464,7 +492,9 @@ const messages = defineMessages({
<span class="text-primary">
{{
formatMessage(messages.reinstallModpackDescription, {
type: ctx.isServer ? 'server' : 'instance',
type: formatMessage(
ctx.isServer ? messages.serverPossessiveLabel : messages.instancePossessiveLabel,
),
})
}}
</span>