diff --git a/apps/frontend/AGENTS.md b/apps/frontend/AGENTS.md index b677a79f9b4..72033833c7b 100644 --- a/apps/frontend/AGENTS.md +++ b/apps/frontend/AGENTS.md @@ -28,6 +28,10 @@ Nuxt 3 with SSR — pages are server-rendered and hydrated on the client. Uses ` Rule of thumb: if it doesn't depend on Nuxt-specific APIs or website-only features, it should be in `packages/ui`. +### Project Review Language + +Project-review code is English-only. Do not add i18n message definitions, translation keys, or translation helpers to project-review routes, components, providers, or supporting code, including review-only components outside `src/components/project-review/`. Use plain English strings, ordinary interpolation and plural handling, and English date/number formatting. This exception also applies during i18n passes. Preserve localization in shared components used elsewhere. + ### Project Review Popout Windows Project review panels can be displayed in multiple browser documents while sharing the main window's Vue application and JavaScript context. Use an anchor, panel, or event target's `ownerDocument` for DOM queries and its `defaultView` for window behavior. Global `document` and `window` still identify the main window after a panel moves. diff --git a/apps/frontend/src/components/project-review/description/index.vue b/apps/frontend/src/components/project-review/description/index.vue index e117c609936..abfcc933af0 100644 --- a/apps/frontend/src/components/project-review/description/index.vue +++ b/apps/frontend/src/components/project-review/description/index.vue @@ -16,9 +16,7 @@ />
-

- {{ formatMessage(messages.empty) }} -

-

- {{ formatMessage(messages.loading) }} -

+

No project selected

+

Loading...

-

{{ formatMessage(messages.loadError) }}

- +

Could not load project data

+
-

- {{ formatMessage(messages.emptyDescription) }} -

+

No description

diff --git a/apps/frontend/src/components/project-review/issue-list/issue-card.vue b/apps/frontend/src/components/project-review/issue-list/issue-card.vue index 93b4f4f9bfe..b79b1dd6c9b 100644 --- a/apps/frontend/src/components/project-review/issue-list/issue-card.vue +++ b/apps/frontend/src/components/project-review/issue-list/issue-card.vue @@ -12,15 +12,8 @@ :aria-controls="contentId" @click="expanded = !expanded" > - - + + @@ -34,16 +27,18 @@
- {{ formatMessage(messages.edited) }} + (Edited)

- {{ formatMessage(messages.requiredFields, { count: missingRequiredFieldCount }) }} + {{ + missingRequiredFieldCount === 1 ? 'Missing required field' : 'Missing required fields' + }}

- +
@@ -231,7 +215,7 @@ size="xs" type="quiet" class="!h-auto !min-h-0 !rounded-full !bg-surface-3 !px-2.5 !py-1 !text-xs !font-medium hover:!bg-surface-4" - :aria-label="formatMessage(messages.openPanel, { panel: binding.panel.title })" + :aria-label="`Open ${binding.panel.title} review panel`" @click="revealPanel(binding.key)" >

- {{ formatMessage(messages.chooseOption) }} + Choose at least one option for this issue.

@@ -269,17 +253,7 @@ import { } from '@modrinth/assets' import { moderationSettings } from '@modrinth/moderation' import { IssuePriority } from '@modrinth/moderation/src/data/issues' -import { issueTargetLabels } from '@modrinth/moderation/src/data/issues/component-builders/targets' -import { - Button, - Combobox, - commonMessages, - defineMessages, - Input, - MultiSelect, - Tooltip, - useVIntl, -} from '@modrinth/ui' +import { Button, Combobox, Input, MultiSelect, Tooltip } from '@modrinth/ui' import { computed, nextTick, ref, useId, watch } from 'vue' import TemplateMarkdownEditor from '~/components/project-review/message-thread/template-markdown-editor.vue' @@ -294,6 +268,7 @@ import { } from '~/providers/project-review/review-panels' import { injectReviewPreviousIssues } from '~/providers/project-review/review-previous-issues' import { injectReviewSubmission } from '~/providers/project-review/review-submission' +import { issueTargetLabels } from '~/providers/project-review/review-target-labels' import { injectReviewContext } from '../review-panel/context' import Controls from '../review-panel/controls/index.vue' @@ -323,7 +298,7 @@ const previousIssue = computed(() => { const issue = computed(() => 'controls' in props.issue ? props.issue : previousIssues.cardIssue(props.issue), ) -const issueTitle = computed(() => issue.value.title || formatMessage(messages.customIssue)) +const issueTitle = computed(() => issue.value.title || 'Custom issue') const active = computed(() => panels.activeIssues.value.some((entry) => entry.id === issue.value.id), ) @@ -378,80 +353,7 @@ watch( if (disabled) editingMessage.value = false }, ) -const { formatMessage } = useVIntl() -const messages = defineMessages({ - customIssue: { id: 'project-review.issues.custom', defaultMessage: 'Custom issue' }, - customTitle: { id: 'project-review.issues.custom-title', defaultMessage: 'Title' }, - customTitlePlaceholder: { - id: 'project-review.issues.custom-title-placeholder', - defaultMessage: 'Enter title...', - }, - issueMessage: { id: 'project-review.issues.issue-message', defaultMessage: 'Message' }, - customPriority: { id: 'project-review.issues.custom-priority', defaultMessage: 'Priority' }, - customPlaceholder: { - id: 'project-review.issues.custom-placeholder', - defaultMessage: 'Enter custom issue message...', - }, - requiredFields: { - id: 'project-review.issues.required-fields', - defaultMessage: - '{count, plural, one {Missing required field} other {Missing required fields}}', - }, - acknowledgeCheckbox: { - id: 'project-review.issues.custom-acknowledge-checkbox', - defaultMessage: 'Acknowledge checkbox', - }, - acknowledgeReply: { - id: 'project-review.issues.custom-acknowledge-reply', - defaultMessage: 'Acknowledge reply', - }, - searchFacets: { - id: 'project-review.issues.custom-search-facets', - defaultMessage: 'Search actions…', - }, - actions: { id: 'project-review.issues.custom-actions', defaultMessage: 'Actions' }, - addFacets: { id: 'project-review.issues.custom-add-facets', defaultMessage: 'Mark as addressed' }, - notResolved: { - id: 'project-review.issues.not-resolved', - defaultMessage: 'Not resolved', - }, - reReview: { - id: 'project-review.previous-issues.re-review', - defaultMessage: 'Re-review', - }, - openPanel: { - id: 'project-review.issues.open-panel', - defaultMessage: 'Open {panel} review panel', - }, - edited: { - id: 'project-review.issues.edited', - defaultMessage: '(Edited)', - }, - editedTooltip: { - id: 'project-review.issues.edited-tooltip', - defaultMessage: 'Issue message has been edited', - }, - remove: { - id: 'project-review.issues.remove', - defaultMessage: 'Remove issue', - }, - add: { - id: 'project-review.issues.add', - defaultMessage: 'Add {issue}', - }, - message: { - id: 'project-review.issues.message', - defaultMessage: 'Message for {issue}', - }, - reset: { - id: 'project-review.issues.reset-message', - defaultMessage: 'Reset message', - }, - chooseOption: { - id: 'project-review.issues.choose-option', - defaultMessage: 'Choose at least one option for this issue.', - }, -}) + const priorityOptions = Object.keys(IssuePriority).map((value) => ({ value, label: value.charAt(0).toUpperCase() + value.slice(1).toLowerCase(), @@ -462,13 +364,12 @@ const facetOptions = computed(() => .filter((type) => type !== 'modify_server_languages' || panels.hasServer.value) .map((value) => ({ value, - label: formatMessage( + label: value === 'acknowledge_checkbox' - ? messages.acknowledgeCheckbox + ? 'Acknowledge checkbox' : value === 'acknowledge_reply' - ? messages.acknowledgeReply + ? 'Acknowledge reply' : issueTargetLabels[value as keyof typeof issueTargetLabels], - ), })), ) const customTitleMissing = computed(() => !!issue.value.custom && !issue.value.custom.title.trim()) @@ -479,7 +380,7 @@ const facetLabels = computed(() => { [] return [...new Set(facets.map(({ what }) => what.type))] .filter((type) => type !== 'mark_addressed') - .map((type) => ({ type, label: formatMessage(issueTargetLabels[type]) })) + .map((type) => ({ type, label: issueTargetLabels[type] })) }) const displayMessage = computed(() => { if (props.disabled && props.previewMessage !== undefined) return props.previewMessage diff --git a/apps/frontend/src/components/project-review/issue-list/issue-picker.vue b/apps/frontend/src/components/project-review/issue-list/issue-picker.vue index b69d2d67c34..d54866c0c54 100644 --- a/apps/frontend/src/components/project-review/issue-list/issue-picker.vue +++ b/apps/frontend/src/components/project-review/issue-list/issue-picker.vue @@ -6,9 +6,9 @@ :max-tag-rows="3" :disabled="pending" :searchable="true" - :search-placeholder="formatMessage(messages.search)" - :no-options-message="formatMessage(messages.empty)" - :no-results-message="formatMessage(messages.empty)" + search-placeholder="Search issues…" + no-options-message="No matching issues." + no-results-message="No matching issues." :dropdown-width="288" dropdown-align="right" :max-height="440" @@ -26,7 +26,7 @@ @@ -34,7 +34,7 @@ diff --git a/apps/frontend/src/components/project-review/layout/empty-popout.vue b/apps/frontend/src/components/project-review/layout/empty-popout.vue index 7b5cd6ddef2..82117dea478 100644 --- a/apps/frontend/src/components/project-review/layout/empty-popout.vue +++ b/apps/frontend/src/components/project-review/layout/empty-popout.vue @@ -1,17 +1,13 @@ diff --git a/apps/frontend/src/components/project-review/layout/index.client.vue b/apps/frontend/src/components/project-review/layout/index.client.vue index 36a1c410d44..de13b833a4d 100644 --- a/apps/frontend/src/components/project-review/layout/index.client.vue +++ b/apps/frontend/src/components/project-review/layout/index.client.vue @@ -1,7 +1,7 @@