diff --git a/apps/app-frontend/src/components/ui/world/WorldItem.vue b/apps/app-frontend/src/components/ui/world/WorldItem.vue index f9b4470003..ba4597bd58 100644 --- a/apps/app-frontend/src/components/ui/world/WorldItem.vue +++ b/apps/app-frontend/src/components/ui/world/WorldItem.vue @@ -244,7 +244,7 @@ const messages = defineMessages({
@@ -198,11 +198,13 @@ import { ButtonStyled, Chips, Combobox, + defineMessages, injectNotificationManager, NewModal, StyledInput, TagItem, Toggle, + useVIntl, } from '@modrinth/ui' import dayjs from 'dayjs' import { computed, ref } from 'vue' @@ -214,6 +216,18 @@ const emit = defineEmits<{ }>() const { addNotification } = injectNotificationManager() +const { formatMessage } = useVIntl() + +const messages = defineMessages({ + selectedServers: { + id: 'admin.transfer-modal.selected-servers', + defaultMessage: '{count, plural, one {# server selected} other {# servers selected}}', + }, + unknownNodes: { + id: 'admin.transfer-modal.unknown-nodes', + defaultMessage: '{count, plural, one {Unknown node} other {Unknown nodes}}', + }, +}) const modal = ref>() @@ -303,7 +317,7 @@ function addNodes() { if (unknownNodes.length > 0) { addNotification({ - title: `Unknown node${unknownNodes.length > 1 ? 's' : ''}`, + title: formatMessage(messages.unknownNodes, { count: unknownNodes.length }), text: unknownNodes.join(', '), type: 'error', }) diff --git a/apps/frontend/src/components/ui/moderation/ModerationTechRevCard.vue b/apps/frontend/src/components/ui/moderation/ModerationTechRevCard.vue index 07991f83d4..9f0af6ba00 100644 --- a/apps/frontend/src/components/ui/moderation/ModerationTechRevCard.vue +++ b/apps/frontend/src/components/ui/moderation/ModerationTechRevCard.vue @@ -23,6 +23,7 @@ import { ButtonStyled, Collapsible, CollapsibleRegion, + defineMessages, getProjectTypeIcon, injectModrinthClient, injectNotificationManager, @@ -30,6 +31,7 @@ import { type OverflowMenuOption, useFormatBytes, useFormatDateTime, + useVIntl, } from '@modrinth/ui' import { NavTabs } from '@modrinth/ui' import { @@ -58,6 +60,15 @@ const formatDateTimeUtc = useFormatDateTime({ timeZone: 'UTC', }) const formatBytes = useFormatBytes() +const { formatMessage } = useVIntl() + +const messages = defineMessages({ + otherTracesAlsoMarked: { + id: 'moderation.tech-review.other-traces-also-marked', + defaultMessage: + '({count, plural, one {# other trace also marked} other {# other traces also marked}})', + }, +}) type FlattenedFileReport = Labrinth.TechReview.Internal.FileReport & { id: string @@ -531,7 +542,7 @@ async function updateDetailStatus(detailId: string, verdict: 'safe' | 'unsafe') const otherText = otherMatchedCount > 0 - ? ` (${otherMatchedCount} other trace${otherMatchedCount === 1 ? '' : 's'} also marked)` + ? ` ${formatMessage(messages.otherTracesAlsoMarked, { count: otherMatchedCount })}` : '' if (verdict === 'safe') { diff --git a/apps/frontend/src/components/ui/servers/marketing/ServerPlanSelector.vue b/apps/frontend/src/components/ui/servers/marketing/ServerPlanSelector.vue index 9a3111a0fc..0079c3dffe 100644 --- a/apps/frontend/src/components/ui/servers/marketing/ServerPlanSelector.vue +++ b/apps/frontend/src/components/ui/servers/marketing/ServerPlanSelector.vue @@ -27,6 +27,11 @@ const messages = defineMessages({ id: 'hosting.plan.select-plan', defaultMessage: 'Select plan', }, + billedInterval: { + id: 'servers.purchase.step.plan.billed', + defaultMessage: + 'billed {interval, select, monthly {monthly} quarterly {quarterly} yearly {yearly} other {{interval}}}', + }, }) const plans: Record< @@ -132,7 +137,9 @@ const billingMonths = computed(() => { {{ formatPrice(price / billingMonths, currency, true) }} - / month + / month

{{ formatMessage(plans[plan].description) }}

diff --git a/apps/frontend/src/composables/auth/scopes.ts b/apps/frontend/src/composables/auth/scopes.ts index 15e78f7da2..dc9747e540 100644 --- a/apps/frontend/src/composables/auth/scopes.ts +++ b/apps/frontend/src/composables/auth/scopes.ts @@ -199,7 +199,7 @@ export const scopeMessages = defineMessages({ }, patCreateDescription: { id: 'scopes.patCreate.description', - defaultMessage: 'Create personal API tokens', + defaultMessage: 'Create personal access tokens', }, patReadLabel: { id: 'scopes.patRead.label', @@ -207,7 +207,7 @@ export const scopeMessages = defineMessages({ }, patReadDescription: { id: 'scopes.patRead.description', - defaultMessage: 'View created API tokens', + defaultMessage: 'View created personal access tokens', }, patWriteLabel: { id: 'scopes.patWrite.label', @@ -215,7 +215,7 @@ export const scopeMessages = defineMessages({ }, patWriteDescription: { id: 'scopes.patWrite.description', - defaultMessage: 'Edit personal API tokens', + defaultMessage: 'Edit personal access tokens', }, patDeleteLabel: { id: 'scopes.patDelete.label', @@ -223,7 +223,7 @@ export const scopeMessages = defineMessages({ }, patDeleteDescription: { id: 'scopes.patDelete.description', - defaultMessage: 'Delete your personal API tokens', + defaultMessage: 'Delete your personal access tokens', }, sessionReadLabel: { id: 'scopes.sessionRead.label', diff --git a/apps/frontend/src/composables/use-server-install-content.ts b/apps/frontend/src/composables/use-server-install-content.ts index 75b3c0d232..248b7896ac 100644 --- a/apps/frontend/src/composables/use-server-install-content.ts +++ b/apps/frontend/src/composables/use-server-install-content.ts @@ -61,7 +61,7 @@ export interface UseServerInstallContentOptions { const messages = defineMessages({ unsupportedContentType: { id: 'discover.install.error.unsupported-content-type', - defaultMessage: 'This content type cannot be installed to a server from browse.', + defaultMessage: 'This content type cannot be installed to a server from Discover.', }, noServerWorld: { id: 'discover.install.error.no-server-world', diff --git a/apps/frontend/src/locales/en-US/index.json b/apps/frontend/src/locales/en-US/index.json index 4638aaf646..e603705f19 100644 --- a/apps/frontend/src/locales/en-US/index.json +++ b/apps/frontend/src/locales/en-US/index.json @@ -5,9 +5,24 @@ "action.continue": { "message": "Continue" }, + "admin.affiliates.affiliate-code-count": { + "message": "{count, plural, one {# affiliate code} other {# affiliate codes}}" + }, + "admin.batch-credit.email-preview.subscription-days": { + "message": "To make up for it, we've added {days, plural, one {# day} other {# days}} to your Modrinth Servers subscription." + }, "admin.billing.error.not-found": { "message": "User not found" }, + "admin.server-transfers.transfer-count": { + "message": "{count, plural, one {# transfer} other {# transfers}}" + }, + "admin.transfer-modal.selected-servers": { + "message": "{count, plural, one {# server selected} other {# servers selected}}" + }, + "admin.transfer-modal.unknown-nodes": { + "message": "{count, plural, one {Unknown node} other {Unknown nodes}}" + }, "app-marketing.download.description": { "message": "Our desktop app is available across all platforms, choose your desired version." }, @@ -123,7 +138,7 @@ "message": "∞ MB" }, "app-marketing.features.performance.infinite-times-infinite-mb": { - "message": "∞ * ∞ MB" + "message": "∞ × ∞ MB" }, "app-marketing.features.performance.less-than-150mb": { "message": "< 150 MB" @@ -1067,6 +1082,9 @@ "dashboard.projects.links.discord-invite.label": { "message": "Discord invite" }, + "dashboard.projects.links.header.edit": { + "message": "Edit links" + }, "dashboard.projects.links.issue-tracker.description": { "message": "A place for users to report bugs, issues, and concerns about your project." }, @@ -1092,7 +1110,7 @@ "message": "Source code" }, "dashboard.projects.links.wiki-page.description": { - "message": "A page containing information, documentation, and help for the project." + "message": "A page containing information, documentation, and help for the project" }, "dashboard.projects.links.wiki-page.label": { "message": "Wiki page" @@ -1356,19 +1374,19 @@ "message": "No server world is available for install." }, "discover.install.error.unsupported-content-type": { - "message": "This content type cannot be installed to a server from browse." + "message": "This content type cannot be installed to a server from Discover." }, "discover.install.heading.reset-modpack": { "message": "Selecting modpack to install after reset" }, "discover.seo.description": { - "message": "Search and browse thousands of Minecraft {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}} on Modrinth with instant, accurate search results. Our filters help you quickly find the best Minecraft {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}}." + "message": "Search and browse thousands of Minecraft {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} server {servers} other {projects}} on Modrinth with instant, accurate search results. Our filters help you quickly find the best Minecraft {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} server {servers} other {projects}}." }, "discover.seo.title": { - "message": "Search {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}}" + "message": "Search {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} server {servers} other {projects}}" }, "discover.seo.title-with-query": { - "message": "Search {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} other {projects}} | {query}" + "message": "Search {projectType, select, mod {mods} modpack {modpacks} resourcepack {resource packs} shader {shaders} plugin {plugins} datapack {datapacks} server {servers} other {projects}} | {query}" }, "error.collection.404.list_item.1": { "message": "You may have mistyped the collection's URL." @@ -2090,6 +2108,9 @@ "moderation.page.technicalReview": { "message": "Tech review" }, + "moderation.tech-review.other-traces-also-marked": { + "message": "({count, plural, one {# other trace also marked} other {# other traces also marked}})" + }, "muralpay.account-type.checking": { "message": "Checking" }, @@ -2357,6 +2378,9 @@ "muralpay.warning.wallet-address": { "message": "Double-check your wallet address. Funds sent to an incorrect address cannot be recovered." }, + "organization.settings.projects.edit-links.affected-projects": { + "message": "Changes will be applied to {count, plural, one {# project} other {# projects}}." + }, "profile.bio.fallback.creator": { "message": "A Modrinth creator." }, @@ -2381,6 +2405,9 @@ "profile.button.set-affiliate": { "message": "Set as affiliate" }, + "profile.collection.projects-count": { + "message": "{count, plural, one {# project} other {# projects}}" + }, "profile.details.label.auth-providers": { "message": "Auth providers" }, @@ -2898,10 +2925,10 @@ "message": "Visit projects dashboard" }, "project.stats.downloads-label": { - "message": "download{count, plural, one {} other {s}}" + "message": "{count, plural, one {download} other {downloads}}" }, "project.stats.followers-label": { - "message": "follower{count, plural, one {} other {s}}" + "message": "{count, plural, one {follower} other {followers}}" }, "project.status.archived.message": { "message": "{title} has been archived. {title} will not receive any further updates unless the author decides to unarchive the project." @@ -3099,25 +3126,25 @@ "message": "Write organizations" }, "scopes.patCreate.description": { - "message": "Create personal API tokens" + "message": "Create personal access tokens" }, "scopes.patCreate.label": { "message": "Create PATs" }, "scopes.patDelete.description": { - "message": "Delete your personal API tokens" + "message": "Delete your personal access tokens" }, "scopes.patDelete.label": { "message": "Delete PATs" }, "scopes.patRead.description": { - "message": "View created API tokens" + "message": "View created personal access tokens" }, "scopes.patRead.label": { "message": "Read PATs" }, "scopes.patWrite.description": { - "message": "Edit personal API tokens" + "message": "Edit personal access tokens" }, "scopes.patWrite.label": { "message": "Write PATs" @@ -3326,6 +3353,9 @@ "servers.plan.small.description": { "message": "Perfect for 1–5 friends with a few light mods." }, + "servers.purchase.step.plan.billed": { + "message": "billed {interval, select, monthly {monthly} quarterly {quarterly} yearly {yearly} other {{interval}}}" + }, "settings.account.button.complete-setup": { "message": "Complete setup" }, @@ -3488,6 +3518,12 @@ "settings.account.security.two-factor.description": { "message": "Add an additional layer of security to your account during login." }, + "settings.account.security.two-factor.modal.remove.header": { + "message": "Remove 2FA" + }, + "settings.account.security.two-factor.modal.setup.header": { + "message": "Setup 2FA" + }, "settings.account.security.two-factor.title": { "message": "Two-factor authentication" }, @@ -3665,21 +3701,12 @@ "settings.billing.interval.month": { "message": "month" }, - "settings.billing.interval.monthly": { - "message": "monthly" - }, "settings.billing.interval.quarter": { "message": "quarter" }, - "settings.billing.interval.quarterly.adjective": { - "message": "quarterly" - }, "settings.billing.interval.year": { "message": "year" }, - "settings.billing.interval.yearly": { - "message": "yearly" - }, "settings.billing.midas.benefits.ad-free": { "message": "Ad-free browsing on modrinth.com and Modrinth App" }, @@ -3764,9 +3791,6 @@ "settings.billing.price.per-interval": { "message": "{price} / {interval}" }, - "settings.billing.price.slash-interval": { - "message": "/{interval}" - }, "settings.billing.pyro.cpu": { "message": "{shared} Shared CPUs (Bursts up to {bursts} CPUs)" }, @@ -3834,16 +3858,16 @@ "message": "Subscriptions" }, "settings.billing.switch.switching-to-interval": { - "message": "Switching to {interval}" + "message": "Switching to {interval, select, monthly {monthly} yearly {yearly} other {{interval}}}" }, "settings.billing.switch.to-interval": { - "message": "Switch to {interval}" + "message": "Switch to {interval, select, monthly {monthly} yearly {yearly} other {{interval}}}" }, "settings.billing.switch.tooltip.monthly-additional-per-year": { "message": "Monthly billing will cost you an additional {amount} per year" }, "settings.billing.switches-to-billing-on": { - "message": "Switches to {interval} billing on {date}" + "message": "Switches to {interval, select, monthly {monthly} yearly {yearly} other {{interval}}} billing on {date}" }, "settings.billing.update-method": { "message": "Update method" diff --git a/apps/frontend/src/pages/[type]/[id].vue b/apps/frontend/src/pages/[type]/[id].vue index 0e4ae85771..bd1d122fda 100644 --- a/apps/frontend/src/pages/[type]/[id].vue +++ b/apps/frontend/src/pages/[type]/[id].vue @@ -1368,7 +1368,7 @@ const messages = defineMessages({ }, downloadsStat: { id: 'project.stats.downloads-label', - defaultMessage: 'download{count, plural, one {} other {s}}', + defaultMessage: '{count, plural, one {download} other {downloads}}', }, errorLoadingProject: { id: 'project.error.loading', @@ -1398,7 +1398,7 @@ const messages = defineMessages({ }, followersStat: { id: 'project.stats.followers-label', - defaultMessage: 'follower{count, plural, one {} other {s}}', + defaultMessage: '{count, plural, one {follower} other {followers}}', }, galleryTab: { id: 'project.gallery.title', diff --git a/apps/frontend/src/pages/admin/affiliates.vue b/apps/frontend/src/pages/admin/affiliates.vue index 92925757ce..aa7ac40e48 100644 --- a/apps/frontend/src/pages/admin/affiliates.vue +++ b/apps/frontend/src/pages/admin/affiliates.vue @@ -61,8 +61,10 @@ {{ userGroup.user.username }} - {{ userGroup.affiliates.length }} affiliate code{{ - userGroup.affiliates.length === 1 ? '' : 's' + {{ + formatMessage(messages.affiliateCodeCount, { + count: userGroup.affiliates.length, + }) }} @@ -92,9 +94,11 @@ import { Avatar, ButtonStyled, ConfirmModal, + defineMessages, injectModrinthClient, injectNotificationManager, StyledInput, + useVIntl, } from '@modrinth/ui' import type { User } from '@modrinth/utils' import { useQuery } from '@tanstack/vue-query' @@ -102,6 +106,14 @@ import { computed, ref } from 'vue' const client = injectModrinthClient() const { handleError } = injectNotificationManager() +const { formatMessage } = useVIntl() + +const messages = defineMessages({ + affiliateCodeCount: { + id: 'admin.affiliates.affiliate-code-count', + defaultMessage: '{count, plural, one {# affiliate code} other {# affiliate codes}}', + }, +}) type UserGroup = { user: User diff --git a/apps/frontend/src/pages/admin/servers/transfers.vue b/apps/frontend/src/pages/admin/servers/transfers.vue index 04627f4885..f8665953ff 100644 --- a/apps/frontend/src/pages/admin/servers/transfers.vue +++ b/apps/frontend/src/pages/admin/servers/transfers.vue @@ -65,7 +65,7 @@ - {{ batch.log_count }} transfer{{ batch.log_count === 1 ? '' : 's' }} + {{ formatMessage(messages.transferCount, { count: batch.log_count }) }} diff --git a/packages/ui/src/layouts/shared/content-tab/components/modals/ContentInstallModal.vue b/packages/ui/src/layouts/shared/content-tab/components/modals/ContentInstallModal.vue index 946d80c76f..8a351a180f 100644 --- a/packages/ui/src/layouts/shared/content-tab/components/modals/ContentInstallModal.vue +++ b/packages/ui/src/layouts/shared/content-tab/components/modals/ContentInstallModal.vue @@ -49,7 +49,13 @@ {{ formatMessage(messages.instanceType) }} - +
diff --git a/packages/ui/src/layouts/shared/content-tab/components/modals/ModpackContentModal.vue b/packages/ui/src/layouts/shared/content-tab/components/modals/ModpackContentModal.vue index f7461df3ab..699c0dc317 100644 --- a/packages/ui/src/layouts/shared/content-tab/components/modals/ModpackContentModal.vue +++ b/packages/ui/src/layouts/shared/content-tab/components/modals/ModpackContentModal.vue @@ -146,7 +146,7 @@ const filterOptions = computed(() => { commonProjectTypeCategoryMessages[type as keyof typeof commonProjectTypeCategoryMessages] return { id: type, - label: msg ? formatMessage(msg) : type.charAt(0).toUpperCase() + type.slice(1) + 's', + label: msg ? formatMessage(msg) : type.charAt(0).toUpperCase() + type.slice(1), } }) diff --git a/packages/ui/src/layouts/shared/content-tab/composables/content-filtering.ts b/packages/ui/src/layouts/shared/content-tab/composables/content-filtering.ts index 0e10446e54..bd87d7260d 100644 --- a/packages/ui/src/layouts/shared/content-tab/composables/content-filtering.ts +++ b/packages/ui/src/layouts/shared/content-tab/composables/content-filtering.ts @@ -53,7 +53,7 @@ export function useContentFilters(items: Ref, config?: ContentFil for (const type of types) { const msg = commonProjectTypeCategoryMessages[type as keyof typeof commonProjectTypeCategoryMessages] - const label = msg ? formatMessage(msg) : type.charAt(0).toUpperCase() + type.slice(1) + 's' + const label = msg ? formatMessage(msg) : type.charAt(0).toUpperCase() + type.slice(1) options.push({ id: type, label }) } } diff --git a/packages/ui/src/layouts/shared/content-tab/layout.vue b/packages/ui/src/layouts/shared/content-tab/layout.vue index bb95744091..50342075b2 100644 --- a/packages/ui/src/layouts/shared/content-tab/layout.vue +++ b/packages/ui/src/layouts/shared/content-tab/layout.vue @@ -73,7 +73,8 @@ const messages = defineMessages({ }, searchPlaceholder: { id: 'content.page-layout.search-placeholder', - defaultMessage: 'Search {count} {contentType}...', + defaultMessage: + 'Search {count, plural, one {# {contentType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}}} other {# {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}}}...', }, browseContent: { id: 'content.page-layout.browse-content', @@ -117,7 +118,8 @@ const messages = defineMessages({ }, emptyHint: { id: 'content.page-layout.empty.hint', - defaultMessage: 'Browse or upload {contentType} to get started', + defaultMessage: + 'Browse or upload {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {content}} to get started', }, shareProjectNames: { id: 'content.page-layout.share.project-names', @@ -555,7 +557,7 @@ const confirmUnlinkModal = ref>() :placeholder=" formatMessage(messages.searchPlaceholder, { count: tableItems.length, - contentType: `${ctx.contentTypeLabel.value}${tableItems.length === 1 ? '' : 's'}`, + contentType: ctx.contentTypeLabel.value, }) " /> @@ -710,7 +712,7 @@ const confirmUnlinkModal = ref>() ctx.modpack.value ? formatMessage(messages.emptyModpackHint) : formatMessage(messages.emptyHint, { - contentType: `${ctx.contentTypeLabel.value}s`, + contentType: ctx.contentTypeLabel.value, }) }} diff --git a/packages/ui/src/layouts/shared/files-tab/components/modals/FileUploadConflictModal.vue b/packages/ui/src/layouts/shared/files-tab/components/modals/FileUploadConflictModal.vue index 1e3d7fb3dc..61e7f43c94 100644 --- a/packages/ui/src/layouts/shared/files-tab/components/modals/FileUploadConflictModal.vue +++ b/packages/ui/src/layouts/shared/files-tab/components/modals/FileUploadConflictModal.vue @@ -28,7 +28,7 @@
@@ -38,14 +38,17 @@ class="w-[1px] h-2 relative top-1" >
- {{ - formatMessage(messages.overwrittenLabel) - }} - - {{ file }} + + + +
@@ -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 {path}', }, overwriteButton: { id: 'files.conflict-modal.overwrite-button', diff --git a/packages/ui/src/layouts/shared/server-settings/pages/general.vue b/packages/ui/src/layouts/shared/server-settings/pages/general.vue index 9dbf021341..998459526a 100644 --- a/packages/ui/src/layouts/shared/server-settings/pages/general.vue +++ b/packages/ui/src/layouts/shared/server-settings/pages/general.vue @@ -145,6 +145,7 @@ import { computed, ref, watch } from 'vue' import { CopyCode, StyledInput, Toggle } from '#ui/components' import EditServerIcon from '#ui/components/servers/edit-server-icon/EditServerIcon.vue' import SaveBanner from '#ui/components/servers/SaveBanner.vue' +import { defineMessages, useVIntl } from '#ui/composables/i18n' import { injectModrinthClient, injectModrinthServerContext, @@ -153,11 +154,20 @@ import { } from '#ui/providers' const { addNotification } = injectNotificationManager() +const { formatMessage } = useVIntl() const client = injectModrinthClient() const { server: data, serverId, busyReasons } = injectModrinthServerContext() const { featureFlags } = injectPageContext() const queryClient = useQueryClient() +const messages = defineMessages({ + sharedCpuSpec: { + id: 'servers.settings.general.specs.shared-cpu', + defaultMessage: + '{sharedCpus, plural, one {# Shared CPU} other {# Shared CPUs}} (Bursts up to {burstCpus, plural, one {# CPU} other {# CPUs}})', + }, +}) + const serverName = ref(data.value?.name) const serverSubdomain = ref(data.value?.net?.domain ?? '') @@ -324,7 +334,10 @@ const infoProperties = computed(() => [ type: 'specs', lines: serverSpecs.value ? [ - `${serverSpecs.value.sharedCpus} Shared CPU${Number(serverSpecs.value.sharedCpus) > 1 ? 's' : ''} (Bursts up to ${serverSpecs.value.burstCpus} CPUs)`, + formatMessage(messages.sharedCpuSpec, { + sharedCpus: Number(serverSpecs.value.sharedCpus), + burstCpus: Number(serverSpecs.value.burstCpus), + }), `${serverSpecs.value.ramGb} GB RAM`, `${serverSpecs.value.swapGb} GB Swap`, `${serverSpecs.value.storageGb} GB SSD`, diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/backups.vue b/packages/ui/src/layouts/wrapped/hosting/manage/backups.vue index a453547956..7deba35809 100644 --- a/packages/ui/src/layouts/wrapped/hosting/manage/backups.vue +++ b/packages/ui/src/layouts/wrapped/hosting/manage/backups.vue @@ -324,6 +324,10 @@ const messages = defineMessages({ id: 'servers.backups.bulk-bar.deleting', defaultMessage: 'Deleting {total, plural, one {# backup} other {# backups}}...', }, + failedBulkDelete: { + id: 'servers.backups.bulk-delete.failed', + defaultMessage: 'Failed to delete {count, plural, one {# backup} other {# backups}}', + }, }) const { addNotification } = injectNotificationManager() @@ -529,7 +533,7 @@ async function bulkDelete(toRemove: Archon.BackupsQueue.v1.BackupQueueBackup[]) } catch (err) { addNotification({ type: 'error', - title: `Failed to delete ${toRemove.length} backup${toRemove.length === 1 ? '' : 's'}`, + title: formatMessage(messages.failedBulkDelete, { count: toRemove.length }), text: err instanceof Error ? err.message : String(err), }) } finally { diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json index 2083686ccd..81d5aa52b5 100644 --- a/packages/ui/src/locales/en-US/index.json +++ b/packages/ui/src/locales/en-US/index.json @@ -65,17 +65,8 @@ "billing.resubscribe-modal.failed-load": { "defaultMessage": "Failed to load subscription details." }, - "billing.resubscribe-modal.interval.five-days": { - "defaultMessage": "/5 days" - }, - "billing.resubscribe-modal.interval.monthly": { - "defaultMessage": "/month" - }, - "billing.resubscribe-modal.interval.quarterly": { - "defaultMessage": "/quarter" - }, - "billing.resubscribe-modal.interval.yearly": { - "defaultMessage": "/year" + "billing.resubscribe-modal.interval": { + "defaultMessage": "{intervalOption, select, fiveDays {/5 days} monthly {/month} quarterly {/quarter} yearly {/year} other {{interval}}}" }, "billing.resubscribe-modal.next-charge": { "defaultMessage": "Your next charge will be on {date}." @@ -323,6 +314,9 @@ "collections.label.private": { "defaultMessage": "Private" }, + "console.crash-analysis.problems-detected": { + "defaultMessage": "{count, plural, one {# problem detected} other {# problems detected}}" + }, "content.card.select-project": { "defaultMessage": "Select {project}" }, @@ -348,10 +342,10 @@ "defaultMessage": "Deletion warning" }, "content.confirm-deletion.delete-button": { - "defaultMessage": "Delete {count} {itemType}{count, plural, one {} other {s}}" + "defaultMessage": "Delete {count, plural, one {# {itemType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}}} other {# {itemType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}}}" }, "content.confirm-deletion.header": { - "defaultMessage": "Delete {itemType}{count, plural, one {} other {s}}" + "defaultMessage": "{count, plural, one {Delete {itemType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}}} other {Delete {itemType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}}}" }, "content.confirm-modpack-update.admonition-body": { "defaultMessage": "{action, select, downgrade {Downgrading} other {Updating}} may cause compatibility issues. Mods or content you added on top of the modpack will be kept, but may not be compatible with the new version." @@ -441,7 +435,7 @@ "defaultMessage": "Please wait for the operation to complete before editing content." }, "content.page-layout.empty.hint": { - "defaultMessage": "Browse or upload {contentType} to get started" + "defaultMessage": "Browse or upload {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {content}} to get started" }, "content.page-layout.empty.modpack-hint": { "defaultMessage": "Add additional content on top of this modpack" @@ -465,7 +459,7 @@ "defaultMessage": "Please wait" }, "content.page-layout.search-placeholder": { - "defaultMessage": "Search {count} {contentType}..." + "defaultMessage": "Search {count, plural, one {# {contentType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}}} other {# {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}}}..." }, "content.page-layout.share.file-names": { "defaultMessage": "File names" @@ -507,31 +501,31 @@ "defaultMessage": "All selected content is already enabled" }, "content.selection-bar.bulk.deleting": { - "defaultMessage": "Deleting {progress}/{total} {contentType}..." + "defaultMessage": "Deleting {progress}/{total} {total, plural, one {{contentType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}}} other {{contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}}}..." }, "content.selection-bar.bulk.deleting-waiting": { - "defaultMessage": "Deleting {contentType}..." + "defaultMessage": "Deleting {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}..." }, "content.selection-bar.bulk.disabling": { - "defaultMessage": "Disabling {progress}/{total} {contentType}..." + "defaultMessage": "Disabling {progress}/{total} {total, plural, one {{contentType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}}} other {{contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}}}..." }, "content.selection-bar.bulk.disabling-waiting": { - "defaultMessage": "Disabling {contentType}..." + "defaultMessage": "Disabling {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}..." }, "content.selection-bar.bulk.enabling": { - "defaultMessage": "Enabling {progress}/{total} {contentType}..." + "defaultMessage": "Enabling {progress}/{total} {total, plural, one {{contentType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}}} other {{contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}}}..." }, "content.selection-bar.bulk.enabling-waiting": { - "defaultMessage": "Enabling {contentType}..." + "defaultMessage": "Enabling {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}..." }, "content.selection-bar.bulk.updating": { - "defaultMessage": "Updating {progress}/{total} {contentType}..." + "defaultMessage": "Updating {progress}/{total} {total, plural, one {{contentType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}}} other {{contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}}}..." }, "content.selection-bar.bulk.updating-waiting": { - "defaultMessage": "Updating {contentType}..." + "defaultMessage": "Updating {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}}..." }, "content.selection-bar.selected-count": { - "defaultMessage": "{count} {contentType} selected" + "defaultMessage": "{count, plural, one {# {contentType, select, datapack {data pack} mod {mod} modpack {modpack} plugin {plugin} project {project} resourcepack {resource pack} server {server} shader {shader} other {item}} selected} other {# {contentType, select, datapack {data packs} mod {mods} modpack {modpacks} plugin {plugins} project {projects} resourcepack {resource packs} server {servers} shader {shaders} other {items}} selected}}" }, "content.selection-bar.selected-count-simple": { "defaultMessage": "{count, number} selected" @@ -830,6 +824,9 @@ "files.conflict-modal.overwrite-button": { "defaultMessage": "Overwrite" }, + "files.conflict-modal.overwrite-file-label": { + "defaultMessage": "Will overwrite {path}" + }, "files.conflict-modal.overwrite-many-warning": { "defaultMessage": "Over 100 files will be overwritten if you proceed with extraction; here are some of them." }, @@ -839,9 +836,6 @@ "files.conflict-modal.overwritten-count": { "defaultMessage": "{count} overwritten" }, - "files.conflict-modal.overwritten-label": { - "defaultMessage": "Overwritten" - }, "files.conflict-modal.warning-header": { "defaultMessage": "Files will be overwritten" }, @@ -2331,7 +2325,7 @@ "defaultMessage": "JCB" }, "payment-method.mastercard": { - "defaultMessage": "MasterCard" + "defaultMessage": "Mastercard" }, "payment-method.paypal": { "defaultMessage": "PayPal" @@ -3266,6 +3260,9 @@ "servers.backups.bulk-bar.selected-count": { "defaultMessage": "{count, plural, one {# backup selected} other {# backups selected}}" }, + "servers.backups.bulk-delete.failed": { + "defaultMessage": "Failed to delete {count, plural, one {# backup} other {# backups}}" + }, "servers.backups.delete-modal.admonition-body": { "defaultMessage": "Once deleted, {count, plural, one {this backup cannot} other {these backups cannot}} be recovered. Deletion is permanent." }, @@ -3405,7 +3402,7 @@ "defaultMessage": "No servers yet" }, "servers.list-empty.one-click-mod-installs-description": { - "defaultMessage": "Pick your favourite mods and we handle the rest." + "defaultMessage": "Pick your favorite mods and we handle the rest." }, "servers.list-empty.one-click-mod-installs-title": { "defaultMessage": "One-click mod installs" @@ -3444,16 +3441,16 @@ "defaultMessage": "New" }, "servers.listing.notice.files-kept-for-download": { - "defaultMessage": "Your files will be kept for {daysRemaining} more {daysRemaining, plural, one {day} other {days} }. Contact support to download the files before they are deleted. " + "defaultMessage": "Your files will be kept for {daysRemaining} more {daysRemaining, plural, one {day} other {days}}. Contact support to download the files before they are deleted." }, "servers.listing.notice.files-preserved-after-cancellation": { "defaultMessage": "Your files will be preserved for 30 days after cancellation." }, "servers.listing.notice.moderated": { - "defaultMessage": "Your server has been suspended by moderation action. " + "defaultMessage": "Your server has been suspended by moderation action." }, "servers.listing.notice.pending-change": { - "defaultMessage": "Your server will {verb} to the {planSize} Plan on {formattedDate}. " + "defaultMessage": "Your server will {verb, select, downgrade {downgrade} other {upgrade}} to the {planSize} Plan on {formattedDate}." }, "servers.listing.notice.provisioning": { "defaultMessage": "Please wait while we set up your server. This can take up to 10 minutes." @@ -3462,7 +3459,7 @@ "defaultMessage": "Your subscription was cancelled." }, "servers.listing.notice.subscription-cancelled-on-date": { - "defaultMessage": "Your subscription was cancelled on {formattedDate}. " + "defaultMessage": "Your subscription was cancelled on {formattedDate}." }, "servers.listing.notice.subscription-cancelled-payment-failed": { "defaultMessage": "Your subscription was cancelled due to payment failure." @@ -3635,6 +3632,9 @@ "servers.purchase.notification.success.title": { "defaultMessage": "Purchase success" }, + "servers.purchase.review.invoice.prorated-hosting-title": { + "defaultMessage": "Modrinth Hosting ({planName}) — prorated for {days, plural, one {# day} other {# days}}" + }, "servers.purchase.step.payment.description": { "defaultMessage": "You won't be charged yet." }, @@ -3644,6 +3644,9 @@ "servers.purchase.step.payment.title": { "defaultMessage": "Payment method" }, + "servers.purchase.step.plan.billed": { + "defaultMessage": "billed {interval, select, monthly {monthly} quarterly {quarterly} yearly {yearly} other {{interval}}}" + }, "servers.purchase.step.plan.billing-subtitle": { "defaultMessage": "Available in North America, Europe, and Southeast Asia." }, @@ -3716,6 +3719,9 @@ "servers.region.western-europe": { "defaultMessage": "Western Europe" }, + "servers.settings.general.specs.shared-cpu": { + "defaultMessage": "{sharedCpus, plural, one {# Shared CPU} other {# Shared CPUs}} (Bursts up to {burstCpus, plural, one {# CPU} other {# CPUs}})" + }, "servers.setup.onboarding.installation-failed.text": { "defaultMessage": "An unexpected error occurred while installing. Please try again later." }, @@ -3779,6 +3785,18 @@ "servers.setup.uploading-modpack.header": { "defaultMessage": "Uploading modpack" }, + "servers.uptime.verbose.days": { + "defaultMessage": "{count, plural, one {# day} other {# days}}" + }, + "servers.uptime.verbose.hours": { + "defaultMessage": "{count, plural, one {# hour} other {# hours}}" + }, + "servers.uptime.verbose.minutes": { + "defaultMessage": "{count, plural, one {# minute} other {# minutes}}" + }, + "servers.uptime.verbose.seconds": { + "defaultMessage": "{count, plural, one {# second} other {# seconds}}" + }, "settings.account.title": { "defaultMessage": "Account and security" }, diff --git a/packages/ui/src/utils/common-messages.ts b/packages/ui/src/utils/common-messages.ts index 2c5fc25b02..525539b4cf 100644 --- a/packages/ui/src/utils/common-messages.ts +++ b/packages/ui/src/utils/common-messages.ts @@ -1083,7 +1083,7 @@ export const paymentMethodMessages = defineMessages({ }, mastercard: { id: 'payment-method.mastercard', - defaultMessage: 'MasterCard', + defaultMessage: 'Mastercard', }, paypal: { id: 'payment-method.paypal', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6373263bbc..b34f6590af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,6 +25,9 @@ importers: '@types/node': specifier: ^24 version: 24.12.2 + '@typescript-eslint/typescript-estree': + specifier: ^8.59.2 + version: 8.59.2(typescript@5.9.3) '@vue/compiler-dom': specifier: ^3.5.26 version: 3.5.27 @@ -170,7 +173,7 @@ importers: devDependencies: '@eslint/compat': specifier: ^1.1.1 - version: 1.4.1(eslint@9.39.2(jiti@1.21.7)) + version: 1.4.1(eslint@9.39.2(jiti@2.6.1)) '@formatjs/cli': specifier: ^6.2.12 version: 6.12.2(@vue/compiler-core@3.5.27)(vue@3.5.27(typescript@5.9.3)) @@ -179,22 +182,22 @@ importers: version: link:../../packages/tooling-config '@nuxt/eslint-config': specifier: ^0.5.6 - version: 0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + version: 0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@taijased/vue-render-tracker': specifier: ^1.0.7 version: 1.0.7(vue@3.5.27(typescript@5.9.3)) '@vitejs/plugin-vue': specifier: ^6.0.3 - version: 6.0.4(vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) + version: 6.0.4(vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) autoprefixer: specifier: ^10.4.19 version: 10.4.24(postcss@8.5.6) eslint: specifier: ^9.9.1 - version: 9.39.2(jiti@1.21.7) + version: 9.39.2(jiti@2.6.1) eslint-plugin-turbo: specifier: ^2.5.4 - version: 2.8.2(eslint@9.39.2(jiti@1.21.7))(turbo@2.8.2) + version: 2.8.2(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.2) postcss: specifier: ^8.4.39 version: 8.5.6 @@ -212,7 +215,7 @@ importers: version: 5.9.3 vite: specifier: ^8.0.0 - version: 8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + version: 8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) vue-component-type-helpers: specifier: ^3.1.8 version: 3.2.4 @@ -775,7 +778,7 @@ importers: version: 5.2.4(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))(vue@3.5.27(typescript@5.9.3)) eslint-plugin-storybook: specifier: ^10.1.10 - version: 10.2.4(eslint@9.39.2(jiti@2.6.1))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3) + version: 10.2.4(eslint@9.39.2(jiti@1.21.7))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3) storybook: specifier: ^10.1.10 version: 10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -4548,6 +4551,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.59.2': + resolution: {integrity: sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/scope-manager@8.54.0': resolution: {integrity: sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4558,6 +4567,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/tsconfig-utils@8.59.2': + resolution: {integrity: sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.54.0': resolution: {integrity: sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4569,12 +4584,22 @@ packages: resolution: {integrity: sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.59.2': + resolution: {integrity: sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.54.0': resolution: {integrity: sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/typescript-estree@8.59.2': + resolution: {integrity: sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.54.0': resolution: {integrity: sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4586,6 +4611,10 @@ packages: resolution: {integrity: sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.59.2': + resolution: {integrity: sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -5249,6 +5278,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + bare-events@2.8.2: resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} peerDependencies: @@ -5299,6 +5332,10 @@ packages: brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + engines: {node: 18 || 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -6112,6 +6149,10 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint@9.39.2: resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -7505,6 +7546,10 @@ packages: resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} engines: {node: 20 || >=22} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -9171,6 +9216,12 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} @@ -11125,12 +11176,6 @@ snapshots: '@eslint-community/regexpp@4.12.2': {} - '@eslint/compat@1.4.1(eslint@9.39.2(jiti@1.21.7))': - dependencies: - '@eslint/core': 0.17.0 - optionalDependencies: - eslint: 9.39.2(jiti@1.21.7) - '@eslint/compat@1.4.1(eslint@9.39.2(jiti@2.6.1))': dependencies: '@eslint/core': 0.17.0 @@ -11756,31 +11801,6 @@ snapshots: - utf-8-validate - vue - '@nuxt/eslint-config@0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@eslint/js': 9.39.2 - '@nuxt/eslint-plugin': 0.5.7(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@stylistic/eslint-plugin': 2.13.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.2(jiti@1.21.7) - eslint-config-flat-gitignore: 0.3.0(eslint@9.39.2(jiti@1.21.7)) - eslint-flat-config-utils: 0.4.0 - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-jsdoc: 50.8.0(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-regexp: 2.10.0(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-unicorn: 55.0.0(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-vue: 9.33.0(eslint@9.39.2(jiti@1.21.7)) - globals: 15.15.0 - local-pkg: 0.5.1 - pathe: 1.1.2 - vue-eslint-parser: 9.4.3(eslint@9.39.2(jiti@1.21.7)) - transitivePeerDependencies: - - '@typescript-eslint/utils' - - eslint-import-resolver-node - - supports-color - - typescript - '@nuxt/eslint-config@0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint/js': 9.39.2 @@ -11806,15 +11826,6 @@ snapshots: - supports-color - typescript - '@nuxt/eslint-plugin@0.5.7(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.2(jiti@1.21.7) - transitivePeerDependencies: - - supports-color - - typescript - '@nuxt/eslint-plugin@0.5.7(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.54.0 @@ -13289,18 +13300,6 @@ snapshots: '@stripe/stripe-js@7.9.0': {} - '@stylistic/eslint-plugin@2.13.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.2(jiti@1.21.7) - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - estraverse: 5.3.0 - picomatch: 4.0.3 - transitivePeerDependencies: - - supports-color - - typescript - '@stylistic/eslint-plugin@2.13.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) @@ -13713,22 +13712,6 @@ snapshots: dependencies: '@types/node': 24.12.2 - '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 - eslint: 9.39.2(jiti@1.21.7) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -13745,34 +13728,31 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/types': 8.54.0 '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.54.0 debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) + eslint: 9.39.2(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/project-service@8.54.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.54.0 + '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.54.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.59.2(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) - '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/tsconfig-utils': 8.59.2(typescript@5.9.3) + '@typescript-eslint/types': 8.59.2 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: @@ -13787,17 +13767,9 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.59.2(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) - ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 - transitivePeerDependencies: - - supports-color '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: @@ -13813,6 +13785,8 @@ snapshots: '@typescript-eslint/types@8.54.0': {} + '@typescript-eslint/types@8.59.2': {} + '@typescript-eslint/typescript-estree@8.54.0(typescript@5.9.3)': dependencies: '@typescript-eslint/project-service': 8.54.0(typescript@5.9.3) @@ -13828,6 +13802,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.59.2(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.59.2(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.59.2(typescript@5.9.3) + '@typescript-eslint/types': 8.59.2 + '@typescript-eslint/visitor-keys': 8.59.2 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.7.4 + tinyglobby: 0.2.15 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) @@ -13855,6 +13844,11 @@ snapshots: '@typescript-eslint/types': 8.54.0 eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.59.2': + dependencies: + '@typescript-eslint/types': 8.59.2 + eslint-visitor-keys: 5.0.1 + '@ungap/structured-clone@1.3.0': {} '@unhead/vue@2.1.2(vue@3.5.27(typescript@5.9.3))': @@ -13969,12 +13963,6 @@ snapshots: vite: 7.3.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) vue: 3.5.27(typescript@5.9.3) - '@vitejs/plugin-vue@6.0.4(vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': - dependencies: - '@rolldown/pluginutils': 1.0.0-rc.2 - vite: 8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) - vue: 3.5.27(typescript@5.9.3) - '@vitejs/plugin-vue@6.0.4(vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.2 @@ -14716,6 +14704,8 @@ snapshots: balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + bare-events@2.8.2: {} base-64@1.0.0: {} @@ -14764,6 +14754,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.6: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -15504,12 +15498,6 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-flat-gitignore@0.3.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@eslint/compat': 1.4.1(eslint@9.39.2(jiti@1.21.7)) - eslint: 9.39.2(jiti@1.21.7) - find-up-simple: 1.0.1 - eslint-config-flat-gitignore@0.3.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint/compat': 1.4.1(eslint@9.39.2(jiti@2.6.1)) @@ -15531,23 +15519,6 @@ snapshots: optionalDependencies: unrs-resolver: 1.11.1 - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@typescript-eslint/types': 8.54.0 - comment-parser: 1.4.5 - debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) - eslint-import-context: 0.1.9(unrs-resolver@1.11.1) - is-glob: 4.0.3 - minimatch: 10.1.2 - semver: 7.7.3 - stable-hash-x: 0.2.0 - unrs-resolver: 1.11.1 - optionalDependencies: - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): dependencies: '@typescript-eslint/types': 8.54.0 @@ -15565,22 +15536,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-jsdoc@50.8.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@es-joy/jsdoccomment': 0.50.2 - are-docs-informative: 0.0.2 - comment-parser: 1.4.1 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint: 9.39.2(jiti@1.21.7) - espree: 10.4.0 - esquery: 1.7.0 - parse-imports-exports: 0.2.4 - semver: 7.7.3 - spdx-expression-parse: 4.0.0 - transitivePeerDependencies: - - supports-color - eslint-plugin-jsdoc@50.8.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@es-joy/jsdoccomment': 0.50.2 @@ -15606,17 +15561,6 @@ snapshots: optionalDependencies: eslint-config-prettier: 10.1.8(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-regexp@2.10.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) - '@eslint-community/regexpp': 4.12.2 - comment-parser: 1.4.5 - eslint: 9.39.2(jiti@1.21.7) - jsdoc-type-pratt-parser: 4.8.0 - refa: 0.12.1 - regexp-ast-analysis: 0.7.1 - scslre: 0.3.0 - eslint-plugin-regexp@2.10.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) @@ -15632,47 +15576,21 @@ snapshots: dependencies: eslint: 9.39.2(jiti@2.6.1) - eslint-plugin-storybook@10.2.4(eslint@9.39.2(jiti@2.6.1))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3): + eslint-plugin-storybook@10.2.4(eslint@9.39.2(jiti@1.21.7))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint: 9.39.2(jiti@1.21.7) storybook: 10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-turbo@2.8.2(eslint@9.39.2(jiti@1.21.7))(turbo@2.8.2): - dependencies: - dotenv: 16.0.3 - eslint: 9.39.2(jiti@1.21.7) - turbo: 2.8.2 - eslint-plugin-turbo@2.8.2(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.2): dependencies: dotenv: 16.0.3 eslint: 9.39.2(jiti@2.6.1) turbo: 2.8.2 - eslint-plugin-unicorn@55.0.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) - ci-info: 4.4.0 - clean-regexp: 1.0.0 - core-js-compat: 3.48.0 - eslint: 9.39.2(jiti@1.21.7) - esquery: 1.7.0 - globals: 15.15.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.1.0 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.7.3 - strip-indent: 3.0.0 - eslint-plugin-unicorn@55.0.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -15707,20 +15625,6 @@ snapshots: '@stylistic/eslint-plugin': 2.13.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint-plugin-vue@9.33.0(eslint@9.39.2(jiti@1.21.7)): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) - eslint: 9.39.2(jiti@1.21.7) - globals: 13.24.0 - natural-compare: 1.4.0 - nth-check: 2.1.1 - postcss-selector-parser: 6.1.2 - semver: 7.7.3 - vue-eslint-parser: 9.4.3(eslint@9.39.2(jiti@1.21.7)) - xml-name-validator: 4.0.0 - transitivePeerDependencies: - - supports-color - eslint-plugin-vue@9.33.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) @@ -15749,6 +15653,8 @@ snapshots: eslint-visitor-keys@4.2.1: {} + eslint-visitor-keys@5.0.1: {} + eslint@9.39.2(jiti@1.21.7): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) @@ -17571,6 +17477,10 @@ snapshots: dependencies: '@isaacs/brace-expansion': 5.0.1 + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.6 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 @@ -19677,6 +19587,10 @@ snapshots: dependencies: typescript: 5.9.3 + ts-api-utils@2.5.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + ts-dedent@2.2.0: {} ts-interface-checker@0.1.13: {} @@ -20142,22 +20056,6 @@ snapshots: terser: 5.46.0 yaml: 2.8.2 - vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.8 - rolldown: 1.0.0-rc.12 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.12.2 - esbuild: 0.27.3 - fsevents: 2.3.3 - jiti: 1.21.7 - sass: 1.97.3 - terser: 5.46.0 - yaml: 2.8.2 - vite@8.0.3(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): dependencies: lightningcss: 1.32.0 @@ -20334,19 +20232,6 @@ snapshots: transitivePeerDependencies: - supports-color - vue-eslint-parser@9.4.3(eslint@9.39.2(jiti@1.21.7)): - dependencies: - debug: 4.4.3 - eslint: 9.39.2(jiti@1.21.7) - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.7.0 - lodash: 4.17.23 - semver: 7.7.3 - transitivePeerDependencies: - - supports-color - vue-eslint-parser@9.4.3(eslint@9.39.2(jiti@2.6.1)): dependencies: debug: 4.4.3 diff --git a/scripts/coverage-i18n.ts b/scripts/coverage-i18n.ts index 499e904193..c28636ed99 100644 --- a/scripts/coverage-i18n.ts +++ b/scripts/coverage-i18n.ts @@ -1,18 +1,18 @@ -import { parse as parseVue } from '@vue/compiler-sfc' +import type { TSESTree } from '@typescript-eslint/typescript-estree' +import { AST_NODE_TYPES, parse as parseTs } from '@typescript-eslint/typescript-estree' import { - parse as parseTemplate, NodeTypes, + parse as parseTemplate, + type AttributeNode, + type ElementNode, type RootNode, type TemplateChildNode, - type ElementNode, - type AttributeNode, type TextNode, } from '@vue/compiler-dom' -import { parse as parseTs, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree' -import type { TSESTree } from '@typescript-eslint/typescript-estree' +import { parse as parseVue } from '@vue/compiler-sfc' import chalk from 'chalk' -import * as fs from 'fs' -import * as path from 'path' +import * as fs from 'node:fs' +import * as path from 'node:path' interface FileResult { path: string @@ -77,7 +77,13 @@ const TRANSLATABLE_ATTRS = new Set([ ]) // i18n symbols that indicate i18n usage -const I18N_SYMBOLS = ['useVIntl', 'defineMessage', 'defineMessages', 'IntlFormatted', 'useI18n'] as const +const I18N_SYMBOLS = [ + 'useVIntl', + 'defineMessage', + 'defineMessages', + 'IntlFormatted', + 'useI18n', +] as const const I18N_CALL_PATTERNS = ['formatMessage', '$t'] as const function findVueFiles(dir: string): string[] { @@ -88,7 +94,11 @@ function findVueFiles(dir: string): string[] { for (const entry of entries) { const fullPath = path.join(currentDir, entry.name) if (entry.isDirectory()) { - if (!entry.name.startsWith('.') && entry.name !== 'node_modules' && entry.name !== 'legal') { + if ( + !entry.name.startsWith('.') && + entry.name !== 'node_modules' && + entry.name !== 'legal' + ) { walk(fullPath) } } else if (entry.isFile() && entry.name.endsWith('.vue')) { @@ -207,8 +217,13 @@ function countI18nCallsInExpression(expression: string): number { } } // Also handle this.formatMessage() or intl.formatMessage() - if (callee.type === AST_NODE_TYPES.MemberExpression && callee.property.type === AST_NODE_TYPES.Identifier) { - if (I18N_CALL_PATTERNS.includes(callee.property.name as (typeof I18N_CALL_PATTERNS)[number])) { + if ( + callee.type === AST_NODE_TYPES.MemberExpression && + callee.property.type === AST_NODE_TYPES.Identifier + ) { + if ( + I18N_CALL_PATTERNS.includes(callee.property.name as (typeof I18N_CALL_PATTERNS)[number]) + ) { count++ } } @@ -553,11 +568,7 @@ function main() { const rootDir = path.resolve(__dirname, '..') // Directories to scan for Vue files - const scanDirs = [ - 'apps/frontend/src', - 'apps/app-frontend/src', - 'packages/ui/src', - ] + const scanDirs = ['apps/frontend/src', 'apps/app-frontend/src', 'packages/ui/src'] if (!jsonOutput) { console.log()