improve labels

This commit is contained in:
Prospector
2026-08-07 15:41:29 -07:00
parent 1626c9b436
commit 8197841bc5
15 changed files with 73 additions and 67 deletions
@@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { MegaphoneIcon } from '@modrinth/assets' import { MegaphoneIcon } from '@modrinth/assets'
import { import {
commonMessages,
defineMessages, defineMessages,
IntlFormatted, IntlFormatted,
normalizeChildren, normalizeChildren,
@@ -33,11 +34,6 @@ const messages = defineMessages({
id: 'project.settings.disclosures.advertising.description.2', id: 'project.settings.disclosures.advertising.description.2',
defaultMessage: `If the promotion has no direct monetary value <emphasis>and</emphasis> it is for something that the average person would consider <italic>relevant</italic> and <italic>unobtrusive</italic> (such as a link to your Modrinth profile in the corner of the settings page for your own mod), we would not consider that an advertisement.`, defaultMessage: `If the promotion has no direct monetary value <emphasis>and</emphasis> it is for something that the average person would consider <italic>relevant</italic> and <italic>unobtrusive</italic> (such as a link to your Modrinth profile in the corner of the settings page for your own mod), we would not consider that an advertisement.`,
}, },
noteDescription: {
id: 'project.settings.disclosures.advertising.note-description',
defaultMessage:
'Please explain how your project utilizes advertising so that users can know what to expect.',
},
notePlaceholder: { notePlaceholder: {
id: 'project.settings.disclosures.advertising.note-placeholder', id: 'project.settings.disclosures.advertising.note-placeholder',
defaultMessage: 'e.g. Adds the Modrinth SMP server to your server list automatically.', defaultMessage: 'e.g. Adds the Modrinth SMP server to your server list automatically.',
@@ -69,7 +65,7 @@ const messages = defineMessages({
</p> </p>
<template #expanded> <template #expanded>
<SettingsFormGroup <SettingsFormGroup
:title="formatMessage(messages.noteDescription)" :title="formatMessage(commonMessages.explanationLabel)"
title-for="advertising-disclosure-note" title-for="advertising-disclosure-note"
> >
<StyledInput <StyledInput
@@ -2,6 +2,7 @@
import { SparklesIcon } from '@modrinth/assets' import { SparklesIcon } from '@modrinth/assets'
import { import {
Checkbox, Checkbox,
commonMessages,
defineMessages, defineMessages,
IntlFormatted, IntlFormatted,
normalizeChildren, normalizeChildren,
@@ -42,7 +43,7 @@ const messages = defineMessages({
}, },
typesDescription: { typesDescription: {
id: 'project.settings.disclosures.ai.types-description', id: 'project.settings.disclosures.ai.types-description',
defaultMessage: 'Select what this project uses generative AI for.', defaultMessage: 'What is generative AI being used for?',
}, },
typeCode: { typeCode: {
id: 'project.settings.disclosures.ai.types-code', id: 'project.settings.disclosures.ai.types-code',
@@ -60,11 +61,6 @@ const messages = defineMessages({
id: 'project.settings.disclosures.ai.types-functionality', id: 'project.settings.disclosures.ai.types-functionality',
defaultMessage: 'Functionality', defaultMessage: 'Functionality',
}, },
noteDescription: {
id: 'project.settings.disclosures.ai.note-description',
defaultMessage:
'You may optionally provide a note to explain how you use generative AI in this project.',
},
notePlaceholder: { notePlaceholder: {
id: 'project.settings.disclosures.ai.note-placeholder', id: 'project.settings.disclosures.ai.note-placeholder',
defaultMessage: 'e.g. The Chinese and Arabic translations are AI-generated.', defaultMessage: 'e.g. The Chinese and Arabic translations are AI-generated.',
@@ -129,8 +125,9 @@ function setUse(use: AiUsage, enabled: boolean) {
</div> </div>
</SettingsFormGroup> </SettingsFormGroup>
<SettingsFormGroup <SettingsFormGroup
:title="formatMessage(messages.noteDescription)" :title="formatMessage(commonMessages.explanationLabel)"
title-for="ai-disclosure-note" title-for="ai-disclosure-note"
optional
> >
<StyledInput <StyledInput
id="ai-disclosure-note" id="ai-disclosure-note"
@@ -2,6 +2,7 @@
import { ArchiveIcon } from '@modrinth/assets' import { ArchiveIcon } from '@modrinth/assets'
import { import {
ArchivedProjectBanner, ArchivedProjectBanner,
commonMessages,
defineMessages, defineMessages,
SettingsFormGroup, SettingsFormGroup,
SettingsToggleCard, SettingsToggleCard,
@@ -33,11 +34,7 @@ const messages = defineMessages({
description2: { description2: {
id: 'project.settings.disclosures.archived.description.2', id: 'project.settings.disclosures.archived.description.2',
defaultMessage: defaultMessage:
'Archived projects remain discoverable when their visibility is set to Public. If you wish to de-list your project, set its visibility to Unlisted', 'Archived projects remain discoverable when their visibility is set to Public. If you wish to de-list your project, set its visibility to Unlisted.',
},
noteLabel: {
id: 'project.settings.disclosures.archived.note-label',
defaultMessage: 'Optionally explain why this project is archived.',
}, },
notePlaceholder: { notePlaceholder: {
id: 'project.settings.disclosures.archived.note-placeholder', id: 'project.settings.disclosures.archived.note-placeholder',
@@ -61,8 +58,9 @@ const messages = defineMessages({
<p>{{ formatMessage(messages.description2) }}</p> <p>{{ formatMessage(messages.description2) }}</p>
<template #expanded> <template #expanded>
<SettingsFormGroup <SettingsFormGroup
:title="formatMessage(messages.noteLabel)" :title="formatMessage(commonMessages.explanationLabel)"
title-for="archived-disclosure-note" title-for="archived-disclosure-note"
optional
> >
<StyledInput <StyledInput
id="archived-disclosure-note" id="archived-disclosure-note"
@@ -49,7 +49,7 @@ const messages = defineMessages({
}, },
noteLabel: { noteLabel: {
id: 'project.settings.disclosures.derivative.note-label', id: 'project.settings.disclosures.derivative.note-label',
defaultMessage: 'Please explain how your project is based on the original work', defaultMessage: 'Explain how your project is based on the original work',
}, },
}) })
@@ -34,7 +34,7 @@ const messages = defineMessages({
}, },
featuresDescription: { featuresDescription: {
id: 'project.settings.disclosures.paid-features.features-description', id: 'project.settings.disclosures.paid-features.features-description',
defaultMessage: 'What kinds of paid features does it add?', defaultMessage: 'List the types of paid features',
}, },
featurePlaceholder: { featurePlaceholder: {
id: 'project.settings.disclosures.paid-features.feature-placeholder', id: 'project.settings.disclosures.paid-features.feature-placeholder',
@@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { EyeIcon } from '@modrinth/assets' import { EyeIcon } from '@modrinth/assets'
import { import {
commonMessages,
defineMessages, defineMessages,
SettingsFormGroup, SettingsFormGroup,
SettingsToggleCard, SettingsToggleCard,
@@ -28,10 +29,6 @@ const messages = defineMessages({
defaultMessage: defaultMessage:
'Enable this if your project contains anything that you think may be dangerous to certain people who are sensitive to flashing lights or patterns.', 'Enable this if your project contains anything that you think may be dangerous to certain people who are sensitive to flashing lights or patterns.',
}, },
noteLabel: {
id: 'project.settings.disclosures.photosensitivity.note-label',
defaultMessage: 'Please briefly describe why your project has a photosensitivity warning.',
},
notePlaceholder: { notePlaceholder: {
id: 'project.settings.disclosures.photosensitivity.note-placeholder', id: 'project.settings.disclosures.photosensitivity.note-placeholder',
defaultMessage: defaultMessage:
@@ -50,7 +47,7 @@ const messages = defineMessages({
> >
<template #expanded> <template #expanded>
<SettingsFormGroup <SettingsFormGroup
:title="formatMessage(messages.noteLabel)" :title="formatMessage(commonMessages.explanationLabel)"
title-for="photosensitivity-disclosure-note" title-for="photosensitivity-disclosure-note"
> >
<StyledInput <StyledInput
@@ -30,8 +30,7 @@ const messages = defineMessages({
}, },
noteLabel: { noteLabel: {
id: 'project.settings.disclosures.system-interactions.note-label', id: 'project.settings.disclosures.system-interactions.note-label',
defaultMessage: defaultMessage: 'Describe the external system interactions',
'Please describe the external system interactions in the mod so users can know what to expect.',
}, },
notePlaceholder: { notePlaceholder: {
id: 'project.settings.disclosures.system-interactions.note-placeholder', id: 'project.settings.disclosures.system-interactions.note-placeholder',
@@ -56,7 +56,7 @@ const messages = defineMessages({
}, },
dataLabel: { dataLabel: {
id: 'project.settings.disclosures.telemetry.data-label', id: 'project.settings.disclosures.telemetry.data-label',
defaultMessage: 'What data is being collected?', defaultMessage: 'What data is collected?',
}, },
dataDescription: { dataDescription: {
id: 'project.settings.disclosures.telemetry.data-description', id: 'project.settings.disclosures.telemetry.data-description',
+6 -18
View File
@@ -3782,9 +3782,6 @@
"project.settings.disclosures.advertising.description.2": { "project.settings.disclosures.advertising.description.2": {
"message": "If the promotion has no direct monetary value <emphasis>and</emphasis> it is for something that the average person would consider <italic>relevant</italic> and <italic>unobtrusive</italic> (such as a link to your Modrinth profile in the corner of the settings page for your own mod), we would not consider that an advertisement." "message": "If the promotion has no direct monetary value <emphasis>and</emphasis> it is for something that the average person would consider <italic>relevant</italic> and <italic>unobtrusive</italic> (such as a link to your Modrinth profile in the corner of the settings page for your own mod), we would not consider that an advertisement."
}, },
"project.settings.disclosures.advertising.note-description": {
"message": "Please explain how your project utilizes advertising so that users can know what to expect."
},
"project.settings.disclosures.advertising.note-placeholder": { "project.settings.disclosures.advertising.note-placeholder": {
"message": "e.g. Adds the Modrinth SMP server to your server list automatically." "message": "e.g. Adds the Modrinth SMP server to your server list automatically."
}, },
@@ -3797,9 +3794,6 @@
"project.settings.disclosures.ai.description": { "project.settings.disclosures.ai.description": {
"message": "You must enable this if this project contains a substantial amount of AI-generated code, any\n\t\t\t\tassets that are substantially AI-generated, the project's functionality relies on the use of\n\t\t\t\tgenerative AI, or if any element of your project's page such as description or publishing\n\t\t\t\trelies on generative AI." "message": "You must enable this if this project contains a substantial amount of AI-generated code, any\n\t\t\t\tassets that are substantially AI-generated, the project's functionality relies on the use of\n\t\t\t\tgenerative AI, or if any element of your project's page such as description or publishing\n\t\t\t\trelies on generative AI."
}, },
"project.settings.disclosures.ai.note-description": {
"message": "You may optionally provide a note to explain how you use generative AI in this project."
},
"project.settings.disclosures.ai.note-placeholder": { "project.settings.disclosures.ai.note-placeholder": {
"message": "e.g. The Chinese and Arabic translations are AI-generated." "message": "e.g. The Chinese and Arabic translations are AI-generated."
}, },
@@ -3813,7 +3807,7 @@
"message": "Code" "message": "Code"
}, },
"project.settings.disclosures.ai.types-description": { "project.settings.disclosures.ai.types-description": {
"message": "Select what this project uses generative AI for." "message": "What is generative AI being used for?"
}, },
"project.settings.disclosures.ai.types-functionality": { "project.settings.disclosures.ai.types-functionality": {
"message": "Functionality" "message": "Functionality"
@@ -3828,10 +3822,7 @@
"message": "Mark your project as archived to let users know that you are no longer working on it." "message": "Mark your project as archived to let users know that you are no longer working on it."
}, },
"project.settings.disclosures.archived.description.2": { "project.settings.disclosures.archived.description.2": {
"message": "Archived projects remain discoverable when their visibility is set to Public. If you wish to de-list your project, set its visibility to Unlisted" "message": "Archived projects remain discoverable when their visibility is set to Public. If you wish to de-list your project, set its visibility to Unlisted."
},
"project.settings.disclosures.archived.note-label": {
"message": "Optionally explain why this project is archived."
}, },
"project.settings.disclosures.archived.note-placeholder": { "project.settings.disclosures.archived.note-placeholder": {
"message": "e.g. I don't have time to maintain this project anymore, feel free to fork it!" "message": "e.g. I don't have time to maintain this project anymore, feel free to fork it!"
@@ -3858,7 +3849,7 @@
"message": "Example project" "message": "Example project"
}, },
"project.settings.disclosures.derivative.note-label": { "project.settings.disclosures.derivative.note-label": {
"message": "Please explain how your project is based on the original work" "message": "Explain how your project is based on the original work"
}, },
"project.settings.disclosures.derivative.title": { "project.settings.disclosures.derivative.title": {
"message": "Contains derivative content" "message": "Contains derivative content"
@@ -3873,7 +3864,7 @@
"message": "e.g. Cosmetics available as Patreon reward" "message": "e.g. Cosmetics available as Patreon reward"
}, },
"project.settings.disclosures.paid-features.features-description": { "project.settings.disclosures.paid-features.features-description": {
"message": "What kinds of paid features does it add?" "message": "List the types of paid features"
}, },
"project.settings.disclosures.paid-features.title": { "project.settings.disclosures.paid-features.title": {
"message": "Contains paid features" "message": "Contains paid features"
@@ -3881,9 +3872,6 @@
"project.settings.disclosures.photosensitivity.description": { "project.settings.disclosures.photosensitivity.description": {
"message": "Enable this if your project contains anything that you think may be dangerous to certain people who are sensitive to flashing lights or patterns." "message": "Enable this if your project contains anything that you think may be dangerous to certain people who are sensitive to flashing lights or patterns."
}, },
"project.settings.disclosures.photosensitivity.note-label": {
"message": "Please briefly describe why your project has a photosensitivity warning."
},
"project.settings.disclosures.photosensitivity.note-placeholder": { "project.settings.disclosures.photosensitivity.note-placeholder": {
"message": "e.g. It adds a flashlight item that has a strobe mode. It can be disabled in Accessibility settings in-game." "message": "e.g. It adds a flashlight item that has a strobe mode. It can be disabled in Accessibility settings in-game."
}, },
@@ -3918,7 +3906,7 @@
"message": "You must enable this if your project reads or edits things on the user's system outside of the game." "message": "You must enable this if your project reads or edits things on the user's system outside of the game."
}, },
"project.settings.disclosures.system-interactions.note-label": { "project.settings.disclosures.system-interactions.note-label": {
"message": "Please describe the external system interactions in the mod so users can know what to expect." "message": "Describe the external system interactions"
}, },
"project.settings.disclosures.system-interactions.note-placeholder": { "project.settings.disclosures.system-interactions.note-placeholder": {
"message": "e.g. It adds a file to the desktop called wake_up.txt" "message": "e.g. It adds a file to the desktop called wake_up.txt"
@@ -3942,7 +3930,7 @@
"message": "You can either add a privacy policy, or a list of types of data that are collected. Remember to mention if it is anonymous or contains personally identifiable information (PII)." "message": "You can either add a privacy policy, or a list of types of data that are collected. Remember to mention if it is anonymous or contains personally identifiable information (PII)."
}, },
"project.settings.disclosures.telemetry.data-label": { "project.settings.disclosures.telemetry.data-label": {
"message": "What data is being collected?" "message": "What data is collected?"
}, },
"project.settings.disclosures.telemetry.data-placeholder": { "project.settings.disclosures.telemetry.data-placeholder": {
"message": "e.g. Anonymous launch analytics to track Minecraft version and mod loader usage." "message": "e.g. Anonymous launch analytics to track Minecraft version and mod loader usage."
@@ -145,7 +145,7 @@ const groupDescriptionMessages: Record<string, MessageDescriptor> = {
const { projectV2: project, projectV3, patchProject } = injectProjectPageContext() const { projectV2: project, projectV3, patchProject } = injectProjectPageContext()
useProjectSettingsHeadTitle(messages.tagsTitle) useProjectSettingsHeadTitle(messages.title)
const formatCategoryName = (categoryName: string) => formatCategory(formatMessage, categoryName) const formatCategoryName = (categoryName: string) => formatCategory(formatMessage, categoryName)
@@ -392,10 +392,10 @@ const toggleFeatured = (tag: string) => {
:key="group.id" :key="group.id"
class="rounded-2xl border border-solid border-surface-4 bg-surface-3 p-4" class="rounded-2xl border border-solid border-surface-4 bg-surface-3 p-4"
> >
<h3 class="mb-1 mt-0 text-base font-semibold text-contrast"> <h3 class="mb-1 mt-0 text-lg font-semibold text-contrast">
{{ group.title }} {{ group.title }}
</h3> </h3>
<p v-if="group.description" class="mb-3 mt-0 text-sm"> <p v-if="group.description" class="mb-3 mt-0">
{{ group.description }} {{ group.description }}
</p> </p>
<div class="grid grid-cols-2 gap-x-4 gap-y-2 sm:grid-cols-4"> <div class="grid grid-cols-2 gap-x-4 gap-y-2 sm:grid-cols-4">
@@ -415,7 +415,7 @@ const toggleFeatured = (tag: string) => {
<div class="rounded-2xl border border-solid border-surface-4 bg-surface-3 p-4"> <div class="rounded-2xl border border-solid border-surface-4 bg-surface-3 p-4">
<div class="mb-1 flex items-center gap-2"> <div class="mb-1 flex items-center gap-2">
<h3 class="m-0 text-base font-semibold text-contrast"> <h3 class="m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.featuredTags) }} {{ formatMessage(messages.featuredTags) }}
</h3> </h3>
<TagItem <TagItem
@@ -429,10 +429,10 @@ const toggleFeatured = (tag: string) => {
{{ current.featuredTags.length }}/{{ MAX_FEATURED_TAGS }} {{ current.featuredTags.length }}/{{ MAX_FEATURED_TAGS }}
</TagItem> </TagItem>
</div> </div>
<p class="mb-3 mt-0 text-sm"> <p class="mb-3 mt-0">
{{ formatMessage(messages.featuredTagsDescription) }} {{ formatMessage(messages.featuredTagsDescription) }}
</p> </p>
<p v-if="current.selectedTags.length < 1" class="m-0 text-sm text-secondary"> <p v-if="current.selectedTags.length < 1" class="m-0 text-secondary">
{{ formatMessage(messages.selectAtLeastOneCategory) }} {{ formatMessage(messages.selectAtLeastOneCategory) }}
</p> </p>
<div v-else class="grid grid-cols-2 gap-x-4 gap-y-2 sm:grid-cols-4"> <div v-else class="grid grid-cols-2 gap-x-4 gap-y-2 sm:grid-cols-4">
@@ -1,9 +1,23 @@
<script setup lang="ts"> <script setup lang="ts">
defineProps<{ import { defineMessage, useVIntl } from '../../composables/i18n'
title?: string const { formatMessage } = useVIntl()
titleFor?: string
description?: string withDefaults(
}>() defineProps<{
title?: string
titleFor?: string
description?: string
optional?: boolean
}>(),
{
optional: false,
},
)
const optionalMessage = defineMessage({
id: 'settings.form.group.optional',
defaultMessage: '(optional)',
})
</script> </script>
<template> <template>
@@ -12,11 +26,21 @@ defineProps<{
v-if="title || description || $slots.title || $slots.description" v-if="title || description || $slots.title || $slots.description"
:class="description || $slots.description ? 'flex flex-col gap-1' : undefined" :class="description || $slots.description ? 'flex flex-col gap-1' : undefined"
> >
<label v-if="title && titleFor" :for="titleFor" class="m-0 leading-normal text-contrast"> <label
v-if="title && titleFor"
:for="titleFor"
class="m-0 leading-normal text-contrast font-semibold"
>
{{ title }} {{ title }}
<span v-if="optional" class="text-secondary font-normal">
{{ formatMessage(optionalMessage) }}
</span>
</label> </label>
<p v-else-if="title" class="m-0 leading-normal text-contrast"> <p v-else-if="title" class="m-0 leading-normal text-contrast font-semibold">
{{ title }} {{ title }}
<span v-if="optional" class="text-secondary font-normal">
{{ formatMessage(optionalMessage) }}
</span>
</p> </p>
<slot name="title" /> <slot name="title" />
<p v-if="description" class="m-0 leading-normal text-primary"> <p v-if="description" class="m-0 leading-normal text-primary">
@@ -13,13 +13,13 @@ defineProps<{
class="grid w-full grid-cols-[1fr_auto] items-center gap-6 p-4 rounded-2xl border border-solid border-surface-4 bg-surface-3" class="grid w-full grid-cols-[1fr_auto] items-center gap-6 p-4 rounded-2xl border border-solid border-surface-4 bg-surface-3"
> >
<div> <div>
<h3 class="mb-1 mt-0 flex items-center gap-2 text-base font-semibold text-contrast"> <h3 class="mb-1 mt-0 flex items-center gap-2 text-lg font-semibold text-contrast">
<component :is="icon" v-if="icon" class="size-5 shrink-0 text-primary" aria-hidden="true" /> <component :is="icon" v-if="icon" class="size-5 shrink-0 text-primary" aria-hidden="true" />
{{ title }} {{ title }}
</h3> </h3>
<div <div
v-if="description || $slots.default" v-if="description || $slots.default"
class="flex flex-col gap-2 text-sm leading-normal [&>p]:m-0" class="flex flex-col gap-2 leading-normal [&>p]:m-0"
> >
<p v-if="description">{{ description }}</p> <p v-if="description">{{ description }}</p>
<slot /> <slot />
@@ -15,14 +15,11 @@ const enabled = defineModel<boolean>({ required: true })
<template> <template>
<ToggleCard v-model="enabled" :disabled="disabled"> <ToggleCard v-model="enabled" :disabled="disabled">
<h3 class="mb-1 mt-0 flex items-center gap-2 text-base font-semibold text-contrast"> <h3 class="mb-1 mt-0 flex items-center gap-2 text-lg font-semibold text-contrast">
<component :is="icon" v-if="icon" class="size-5 shrink-0 text-primary" aria-hidden="true" /> <component :is="icon" v-if="icon" class="size-5 shrink-0 text-primary" aria-hidden="true" />
{{ title }} {{ title }}
</h3> </h3>
<div <div v-if="description || $slots.default" class="flex flex-col gap-2 leading-normal [&>p]:m-0">
v-if="description || $slots.default"
class="flex flex-col gap-2 text-sm leading-normal [&>p]:m-0"
>
<p v-if="description">{{ description }}</p> <p v-if="description">{{ description }}</p>
<slot /> <slot />
</div> </div>
+6
View File
@@ -2261,6 +2261,9 @@
"label.error": { "label.error": {
"defaultMessage": "Error" "defaultMessage": "Error"
}, },
"label.explanation": {
"defaultMessage": "Explanation"
},
"label.extract-failed": { "label.extract-failed": {
"defaultMessage": "Extract failed" "defaultMessage": "Extract failed"
}, },
@@ -5315,6 +5318,9 @@
"settings.feature-flags.title": { "settings.feature-flags.title": {
"defaultMessage": "Feature flags" "defaultMessage": "Feature flags"
}, },
"settings.form.group.optional": {
"defaultMessage": "(optional)"
},
"settings.language.categories.default": { "settings.language.categories.default": {
"defaultMessage": "Standard languages" "defaultMessage": "Standard languages"
}, },
+4
View File
@@ -147,6 +147,10 @@ export const commonMessages = defineMessages({
id: 'notification.error.title', id: 'notification.error.title',
defaultMessage: 'An error occurred', defaultMessage: 'An error occurred',
}, },
explanationLabel: {
id: 'label.explanation',
defaultMessage: 'Explanation',
},
filterByLabel: { filterByLabel: {
id: 'label.filter-by', id: 'label.filter-by',
defaultMessage: 'Filter by', defaultMessage: 'Filter by',