1
0

fix: #4568 & i18n on user page (#4572)

* fix: #4568

* fix: lint
This commit is contained in:
Calum H.
2025-10-20 01:23:06 +01:00
committed by GitHub
parent ad3b5aec69
commit 0e17427a58
2 changed files with 160 additions and 45 deletions

View File

@@ -1112,6 +1112,12 @@
"moderation.technical.search.placeholder": {
"message": "Search tech reviews..."
},
"profile.bio.fallback.creator": {
"message": "A Modrinth creator."
},
"profile.bio.fallback.user": {
"message": "A Modrinth user."
},
"profile.button.billing": {
"message": "Manage user billing"
},
@@ -1124,18 +1130,48 @@
"profile.button.manage-projects": {
"message": "Manage projects"
},
"profile.details.label.auth-providers": {
"message": "Auth providers"
},
"profile.details.label.email": {
"message": "Email"
},
"profile.details.label.has-password": {
"message": "Has password"
},
"profile.details.label.has-totp": {
"message": "Has TOTP"
},
"profile.details.label.payment-methods": {
"message": "Payment methods"
},
"profile.details.tooltip.email-not-verified": {
"message": "Email not verified"
},
"profile.details.tooltip.email-verified": {
"message": "Email verified"
},
"profile.error.not-found": {
"message": "User not found"
},
"profile.joined-at": {
"message": "Joined <date>{ago}</date>"
},
"profile.label.badges": {
"message": "Badges"
},
"profile.label.collection": {
"message": "Collection"
},
"profile.label.details": {
"message": "Details"
},
"profile.label.downloads": {
"message": "{count} {count, plural, one {download} other {downloads}}"
},
"profile.label.joined": {
"message": "Joined"
},
"profile.label.no": {
"message": "No"
},
"profile.label.no-collections": {
"message": "This user has no collections!"
},
@@ -1151,18 +1187,21 @@
"profile.label.organizations": {
"message": "Organizations"
},
"profile.label.projects": {
"message": "{count} {count, plural, one {project} other {projects}}"
},
"profile.label.saving": {
"message": "Saving..."
},
"profile.label.yes": {
"message": "Yes"
},
"profile.meta.description": {
"message": "Download {username}'s projects on Modrinth"
},
"profile.meta.description-with-bio": {
"message": "{bio} - Download {username}'s projects on Modrinth"
},
"profile.stats.downloads": {
"message": "{count, plural, one {<stat>{count}</stat> project download} other {<stat>{count}</stat> project downloads}}"
},
"profile.stats.projects": {
"message": "{count, plural, one {<stat>{count}</stat> project} other {<stat>{count}</stat> projects}}"
},
"profile.stats.projects-followers": {
"message": "{count, plural, one {<stat>{count}</stat> project follower} other {<stat>{count}</stat> project followers}}"
},

View File

@@ -16,7 +16,7 @@
<ButtonStyled>
<button @click="cancelRoleEdit">
<XIcon />
Cancel
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="brand">
@@ -25,9 +25,11 @@
@click="saveRoleEdit"
>
<template v-if="isSavingRole">
<SpinnerIcon class="animate-spin" /> Saving...
<SpinnerIcon class="animate-spin" /> {{ formatMessage(messages.savingLabel) }}
</template>
<template v-else>
<SaveIcon /> {{ formatMessage(commonMessages.saveChangesButton) }}
</template>
<template v-else> <SaveIcon /> Save changes </template>
</button>
</ButtonStyled>
</div>
@@ -36,10 +38,16 @@
<NewModal v-if="auth.user && isStaff(auth.user)" ref="userDetailsModal" header="User details">
<div class="flex flex-col gap-3">
<div class="flex flex-col gap-1">
<span class="text-lg font-bold text-primary">Email</span>
<span class="text-lg font-bold text-primary">{{
formatMessage(messages.emailLabel)
}}</span>
<div>
<span
v-tooltip="user.email_verified ? 'Email verified' : 'Email not verified'"
v-tooltip="
user.email_verified
? formatMessage(messages.emailVerifiedTooltip)
: formatMessage(messages.emailNotVerifiedTooltip)
"
class="flex w-fit items-center gap-1"
>
<span>{{ user.email }}</span>
@@ -50,12 +58,16 @@
</div>
<div class="flex flex-col gap-1">
<span class="text-lg font-bold text-primary"> Auth providers </span>
<span class="text-lg font-bold text-primary">{{
formatMessage(messages.authProvidersLabel)
}}</span>
<span>{{ user.auth_providers.join(', ') }}</span>
</div>
<div class="flex flex-col gap-1">
<span class="text-lg font-bold text-primary"> Payment methods</span>
<span class="text-lg font-bold text-primary">{{
formatMessage(messages.paymentMethodsLabel)
}}</span>
<span>
<template v-if="user.payout_data?.paypal_address">
Paypal ({{ user.payout_data.paypal_address }} - {{ user.payout_data.paypal_country }})
@@ -70,16 +82,22 @@
</div>
<div class="flex flex-col gap-1">
<span class="text-lg font-bold text-primary"> Has password </span>
<span class="text-lg font-bold text-primary">{{
formatMessage(messages.hasPasswordLabel)
}}</span>
<span>
{{ user.has_password ? 'Yes' : 'No' }}
{{
user.has_password ? formatMessage(messages.yesLabel) : formatMessage(messages.noLabel)
}}
</span>
</div>
<div class="flex flex-col gap-1">
<span class="text-lg font-bold text-primary"> Has TOTP </span>
<span class="text-lg font-bold text-primary">{{
formatMessage(messages.hasTotpLabel)
}}</span>
<span>
{{ user.has_totp ? 'Yes' : 'No' }}
{{ user.has_totp ? formatMessage(messages.yesLabel) : formatMessage(messages.noLabel) }}
</span>
</div>
</div>
@@ -98,8 +116,8 @@
user.bio
? user.bio
: projects.length === 0
? 'A Modrinth user.'
: 'A Modrinth creator.'
? formatMessage(messages.bioFallbackUser)
: formatMessage(messages.bioFallbackCreator)
}}
</template>
<template #stats>
@@ -107,16 +125,22 @@
class="flex items-center gap-2 border-0 border-r border-solid border-divider pr-4 font-semibold"
>
<BoxIcon class="h-6 w-6 text-secondary" />
{{ formatCompactNumber(projects?.length || 0) }}
projects
{{
formatMessage(messages.profileProjectsLabel, {
count: formatCompactNumber(projects?.length || 0),
})
}}
</div>
<div
v-tooltip="sumDownloads.toLocaleString()"
class="flex items-center gap-2 border-0 border-r border-solid border-divider pr-4 font-semibold"
>
<DownloadIcon class="h-6 w-6 text-secondary" />
{{ formatCompactNumber(sumDownloads) }}
downloads
{{
formatMessage(messages.profileDownloadsLabel, {
count: formatCompactNumber(sumDownloads),
})
}}
</div>
<div
v-tooltip="
@@ -128,7 +152,7 @@
class="flex items-center gap-2 font-semibold"
>
<CalendarIcon class="h-6 w-6 text-secondary" />
Joined
{{ formatMessage(messages.profileJoinedLabel) }}
{{ formatRelativeTime(user.created) }}
</div>
</template>
@@ -287,7 +311,7 @@
<h2 class="title">{{ collection.name }}</h2>
<div class="stats">
<LibraryIcon aria-hidden="true" />
Collection
{{ formatMessage(messages.collectionLabel) }}
</div>
</div>
</div>
@@ -298,25 +322,27 @@
<div class="stats">
<BoxIcon />
{{
`${$formatNumber(collection.projects?.length || 0, false)} project${(collection.projects?.length || 0) !== 1 ? 's' : ''}`
`${$formatNumber(collection.projects?.length || 0, false)} project${
(collection.projects?.length || 0) !== 1 ? 's' : ''
}`
}}
</div>
<div class="stats">
<template v-if="collection.status === 'listed'">
<GlobeIcon />
<span> Public </span>
<span> {{ formatMessage(commonMessages.publicLabel) }} </span>
</template>
<template v-else-if="collection.status === 'unlisted'">
<LinkIcon />
<span> Unlisted </span>
<span> {{ formatMessage(commonMessages.unlistedLabel) }} </span>
</template>
<template v-else-if="collection.status === 'private'">
<LockIcon />
<span> Private </span>
<span> {{ formatMessage(commonMessages.privateLabel) }} </span>
</template>
<template v-else-if="collection.status === 'rejected'">
<XIcon />
<span> Rejected </span>
<span> {{ formatMessage(commonMessages.rejectedLabel) }} </span>
</template>
</div>
</div>
@@ -450,25 +476,75 @@ const formatRelativeTime = useRelativeTime()
const { addNotification } = injectNotificationManager()
const messages = defineMessages({
profileProjectsStats: {
id: 'profile.stats.projects',
defaultMessage:
'{count, plural, one {<stat>{count}</stat> project} other {<stat>{count}</stat> projects}}',
profileProjectsLabel: {
id: 'profile.label.projects',
defaultMessage: '{count} {count, plural, one {project} other {projects}}',
},
profileDownloadsStats: {
id: 'profile.stats.downloads',
defaultMessage:
'{count, plural, one {<stat>{count}</stat> project download} other {<stat>{count}</stat> project downloads}}',
profileDownloadsLabel: {
id: 'profile.label.downloads',
defaultMessage: '{count} {count, plural, one {download} other {downloads}}',
},
profileJoinedLabel: {
id: 'profile.label.joined',
defaultMessage: 'Joined',
},
savingLabel: {
id: 'profile.label.saving',
defaultMessage: 'Saving...',
},
emailLabel: {
id: 'profile.details.label.email',
defaultMessage: 'Email',
},
emailVerifiedTooltip: {
id: 'profile.details.tooltip.email-verified',
defaultMessage: 'Email verified',
},
emailNotVerifiedTooltip: {
id: 'profile.details.tooltip.email-not-verified',
defaultMessage: 'Email not verified',
},
authProvidersLabel: {
id: 'profile.details.label.auth-providers',
defaultMessage: 'Auth providers',
},
paymentMethodsLabel: {
id: 'profile.details.label.payment-methods',
defaultMessage: 'Payment methods',
},
hasPasswordLabel: {
id: 'profile.details.label.has-password',
defaultMessage: 'Has password',
},
hasTotpLabel: {
id: 'profile.details.label.has-totp',
defaultMessage: 'Has TOTP',
},
yesLabel: {
id: 'profile.label.yes',
defaultMessage: 'Yes',
},
noLabel: {
id: 'profile.label.no',
defaultMessage: 'No',
},
bioFallbackUser: {
id: 'profile.bio.fallback.user',
defaultMessage: 'A Modrinth user.',
},
bioFallbackCreator: {
id: 'profile.bio.fallback.creator',
defaultMessage: 'A Modrinth creator.',
},
collectionLabel: {
id: 'profile.label.collection',
defaultMessage: 'Collection',
},
profileProjectsFollowersStats: {
id: 'profile.stats.projects-followers',
defaultMessage:
'{count, plural, one {<stat>{count}</stat> project follower} other {<stat>{count}</stat> project followers}}',
},
profileJoinedAt: {
id: 'profile.joined-at',
defaultMessage: 'Joined <date>{ago}</date>',
},
profileUserId: {
id: 'profile.user-id',
defaultMessage: 'User ID: {id}',