Add translation keys for Pats page (#1590)

* Begin Work

* More work

* Fix lint error

* More work on label

* Fix mistake

* Finish adding  delete pat modal keys

* More label and button

* More label keys

* Fix lint error

* Description key

* Finish page

* Forgot this

* Fix lint error

* Add to navstack

* Apply suggestions from brawaru

* Normalization

* Re-organize PATs page messages (#10)

- Group messages by their usage
- Fix spelling mistakes in some of the property names and keys
- Change some of the keys to conform to keying conventions
- Change variable name in token.expires-in message to inTime

* Regenrate index.json

---------

Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
This commit is contained in:
Mysterious_Dev
2024-01-28 19:58:23 +01:00
committed by GitHub
parent 4bfccba4c0
commit 4973ee555b
4 changed files with 262 additions and 34 deletions

View File

@@ -167,6 +167,9 @@
"button.save": { "button.save": {
"message": "Save" "message": "Save"
}, },
"button.save-changes": {
"message": "Save changes"
},
"collection.button.delete-icon": { "collection.button.delete-icon": {
"message": "Delete icon" "message": "Delete icon"
}, },
@@ -266,6 +269,9 @@
"label.collections": { "label.collections": {
"message": "Collections" "message": "Collections"
}, },
"label.created-ago": {
"message": "Created {ago}"
},
"label.delete": { "label.delete": {
"message": "Delete" "message": "Delete"
}, },
@@ -284,6 +290,9 @@
"label.rejected": { "label.rejected": {
"message": "Rejected" "message": "Rejected"
}, },
"label.scopes": {
"message": "Scopes"
},
"label.title": { "label.title": {
"message": "Title" "message": "Title"
}, },
@@ -695,6 +704,63 @@
"settings.language.title": { "settings.language.title": {
"message": "Language" "message": "Language"
}, },
"settings.pats.action.create": {
"message": "Create a PAT"
},
"settings.pats.description": {
"message": "PATs can be used to access Modrinth's API. For more information, see <doc-link>Modrinth's API documentation</doc-link>. They can be created and revoked at any time."
},
"settings.pats.modal.create.action": {
"message": "Create PAT"
},
"settings.pats.modal.create.expires.label": {
"message": "Expires"
},
"settings.pats.modal.create.name.label": {
"message": "Name"
},
"settings.pats.modal.create.name.placeholder": {
"message": "Enter the PAT's name..."
},
"settings.pats.modal.create.title": {
"message": "Create personal access token"
},
"settings.pats.modal.delete.action": {
"message": "Delete this token"
},
"settings.pats.modal.delete.description": {
"message": "This will remove this token forever (like really forever)."
},
"settings.pats.modal.delete.title": {
"message": "Are you sure you want to delete this token?"
},
"settings.pats.modal.edit.title": {
"message": "Edit personal access token"
},
"settings.pats.title": {
"message": "PATs"
},
"settings.pats.title.long": {
"message": "Personal Access Tokens"
},
"settings.pats.token.action.edit": {
"message": "Edit token"
},
"settings.pats.token.action.revoke": {
"message": "Revoke token"
},
"settings.pats.token.expired-ago": {
"message": "Expired {ago}"
},
"settings.pats.token.expires-in": {
"message": "Expires {inTime}"
},
"settings.pats.token.last-used": {
"message": "Last used {ago}"
},
"settings.pats.token.never-used": {
"message": "Never used"
},
"settings.sessions.action.revoke-session": { "settings.sessions.action.revoke-session": {
"message": "Revoke session" "message": "Revoke session"
}, },

View File

@@ -24,7 +24,7 @@
</template> </template>
<template v-if="auth.user"> <template v-if="auth.user">
<h3>Developer Settings</h3> <h3>Developer Settings</h3>
<NavStackItem link="/settings/pats" label="PATs"> <NavStackItem link="/settings/pats" :label="formatMessage(messages.patsTitle)">
<KeyIcon /> <KeyIcon />
</NavStackItem> </NavStackItem>
<NavStackItem link="/settings/applications" label="Applications"> <NavStackItem link="/settings/applications" label="Applications">
@@ -57,6 +57,10 @@ const messages = defineMessages({
id: 'settings.sessions.title', id: 'settings.sessions.title',
defaultMessage: 'Sessions', defaultMessage: 'Sessions',
}, },
patsTitle: {
id: 'settings.pats.title',
defaultMessage: 'PATs',
},
}) })
const route = useRoute() const route = useRoute()

View File

@@ -2,25 +2,33 @@
<div class="universal-card"> <div class="universal-card">
<ConfirmModal <ConfirmModal
ref="modal_confirm" ref="modal_confirm"
title="Are you sure you want to delete this token?" :title="formatMessage(deleteModalMessages.title)"
description="This will remove this token forever (like really forever)." :description="formatMessage(deleteModalMessages.description)"
proceed-label="Delete this token" :proceed-label="formatMessage(deleteModalMessages.action)"
@proceed="removePat(deletePatIndex)" @proceed="removePat(deletePatIndex)"
/> />
<Modal <Modal
ref="patModal" ref="patModal"
:header="`${editPatIndex !== null ? 'Edit' : 'Create'} personal access token`" :header="
editPatIndex !== null
? formatMessage(createModalMessages.editTitle)
: formatMessage(createModalMessages.createTitle)
"
> >
<div class="universal-modal"> <div class="universal-modal">
<label for="pat-name"><span class="label__title">Name</span> </label> <label for="pat-name">
<span class="label__title">{{ formatMessage(createModalMessages.nameLabel) }}</span>
</label>
<input <input
id="pat-name" id="pat-name"
v-model="name" v-model="name"
maxlength="2048" maxlength="2048"
type="email" type="email"
placeholder="Enter the PAT's name..." :placeholder="formatMessage(createModalMessages.namePlaceholder)"
/> />
<label for="pat-scopes"><span class="label__title">Scopes</span> </label> <label for="pat-scopes">
<span class="label__title">{{ formatMessage(commonMessages.scopesLabel) }}</span>
</label>
<div id="pat-scopes" class="checkboxes"> <div id="pat-scopes" class="checkboxes">
<Checkbox <Checkbox
v-for="scope in scopeList" v-for="scope in scopeList"
@@ -30,13 +38,15 @@
@update:model-value="scopesVal = toggleScope(scopesVal, scope)" @update:model-value="scopesVal = toggleScope(scopesVal, scope)"
/> />
</div> </div>
<label for="pat-name"><span class="label__title">Expires</span> </label> <label for="pat-name">
<span class="label__title">{{ formatMessage(createModalMessages.expiresLabel) }}</span>
</label>
<input id="pat-name" v-model="expires" type="date" /> <input id="pat-name" v-model="expires" type="date" />
<p></p> <p></p>
<div class="input-group push-right"> <div class="input-group push-right">
<button class="iconified-button" @click="$refs.patModal.hide()"> <button class="iconified-button" @click="$refs.patModal.hide()">
<XIcon /> <XIcon />
Cancel {{ formatMessage(commonMessages.cancelButton) }}
</button> </button>
<button <button
v-if="editPatIndex !== null" v-if="editPatIndex !== null"
@@ -46,7 +56,7 @@
@click="editPat" @click="editPat"
> >
<SaveIcon /> <SaveIcon />
Save changes {{ formatMessage(commonMessages.saveChangesButton) }}
</button> </button>
<button <button
v-else v-else
@@ -56,7 +66,7 @@
@click="createPat" @click="createPat"
> >
<PlusIcon /> <PlusIcon />
Create PAT {{ formatMessage(createModalMessages.action) }}
</button> </button>
</div> </div>
</div> </div>
@@ -64,7 +74,7 @@
<div class="header__row"> <div class="header__row">
<div class="header__title"> <div class="header__title">
<h2>Personal Access Tokens</h2> <h2>{{ formatMessage(messages.longTitle) }}</h2>
</div> </div>
<button <button
class="btn btn-primary" class="btn btn-primary"
@@ -78,13 +88,17 @@
} }
" "
> >
<PlusIcon /> Create a PAT <PlusIcon /> {{ formatMessage(messages.create) }}
</button> </button>
</div> </div>
<p> <p>
PATs can be used to access Modrinth's API. For more information, see <IntlFormatted :message-id="messages.description">
<a class="text-link" href="https://docs.modrinth.com">Modrinth's API documentation</a>. They <template #doc-link="{ children }">
can be created and revoked at any time. <a class="text-link" href="https://docs.modrinth.com">
<component :is="() => children" />
</a>
</template>
</IntlFormatted>
</p> </p>
<div v-for="(pat, index) in pats" :key="pat.id" class="universal-card recessed token"> <div v-for="(pat, index) in pats" :key="pat.id" class="universal-card recessed token">
<div> <div>
@@ -98,22 +112,61 @@
<template v-else> <template v-else>
<span <span
v-tooltip=" v-tooltip="
pat.last_used ? $dayjs(pat.last_login).format('MMMM D, YYYY [at] h:mm A') : null pat.last_used
? formatMessage(commonMessages.dateAtTimeTooltip, {
date: new Date(pat.last_used),
time: new Date(pat.last_used),
})
: null
" "
> >
<template v-if="pat.last_used">Last used {{ fromNow(pat.last_used) }}</template> <template v-if="pat.last_used">
<template v-else>Never used</template> {{
</span> formatMessage(tokenMessages.lastUsed, {
ago: formatRelativeTime(pat.last_used),
<span v-tooltip="$dayjs(pat.expires).format('MMMM D, YYYY [at] h:mm A')"> })
<template v-if="new Date(pat.expires) > new Date()"> }}
Expires {{ fromNow(pat.expires) }}
</template> </template>
<template v-else> Expired {{ fromNow(pat.expires) }} </template> <template v-else>{{ formatMessage(tokenMessages.neverUsed) }}</template>
</span> </span>
<span v-tooltip="$dayjs(pat.created).format('MMMM D, YYYY [at] h:mm A')"> <span
Created {{ fromNow(pat.created) }} v-tooltip="
formatMessage(commonMessages.dateAtTimeTooltip, {
date: new Date(pat.expires),
time: new Date(pat.expires),
})
"
>
<template v-if="new Date(pat.expires) > new Date()">
{{
formatMessage(tokenMessages.expiresIn, {
inTime: formatRelativeTime(pat.expires),
})
}}
</template>
<template v-else>
{{
formatMessage(tokenMessages.expiredAgo, {
ago: formatRelativeTime(pat.expires),
})
}}
</template>
</span>
<span
v-tooltip="
formatMessage(commonMessages.dateAtTimeTooltip, {
date: new Date(pat.created),
time: new Date(pat.created),
})
"
>
{{
formatMessage(commonMessages.createdAgoLabel, {
ago: formatRelativeTime(pat.created),
})
}}
</span> </span>
</template> </template>
</div> </div>
@@ -131,7 +184,7 @@
} }
" "
> >
<EditIcon /> Edit token <EditIcon /> {{ formatMessage(tokenMessages.edit) }}
</button> </button>
<button <button
class="iconified-button raised-button" class="iconified-button raised-button"
@@ -142,7 +195,7 @@
} }
" "
> >
<TrashIcon /> Revoke token <TrashIcon /> {{ formatMessage(tokenMessages.revoke) }}
</button> </button>
</div> </div>
</div> </div>
@@ -162,12 +215,105 @@ import {
import CopyCode from '~/components/ui/CopyCode.vue' import CopyCode from '~/components/ui/CopyCode.vue'
import Modal from '~/components/ui/Modal.vue' import Modal from '~/components/ui/Modal.vue'
const { formatMessage } = useVIntl()
const formatRelativeTime = useRelativeTime()
const createModalMessages = defineMessages({
createTitle: {
id: 'settings.pats.modal.create.title',
defaultMessage: 'Create personal access token',
},
editTitle: {
id: 'settings.pats.modal.edit.title',
defaultMessage: 'Edit personal access token',
},
nameLabel: {
id: 'settings.pats.modal.create.name.label',
defaultMessage: 'Name',
},
namePlaceholder: {
id: 'settings.pats.modal.create.name.placeholder',
defaultMessage: "Enter the PAT's name...",
},
expiresLabel: {
id: 'settings.pats.modal.create.expires.label',
defaultMessage: 'Expires',
},
action: {
id: 'settings.pats.modal.create.action',
defaultMessage: 'Create PAT',
},
})
const deleteModalMessages = defineMessages({
title: {
id: 'settings.pats.modal.delete.title',
defaultMessage: 'Are you sure you want to delete this token?',
},
description: {
id: 'settings.pats.modal.delete.description',
defaultMessage: 'This will remove this token forever (like really forever).',
},
action: {
id: 'settings.pats.modal.delete.action',
defaultMessage: 'Delete this token',
},
})
const messages = defineMessages({
title: {
id: 'settings.pats.title',
defaultMessage: 'PATs',
},
longTitle: {
id: 'settings.pats.title.long',
defaultMessage: 'Personal Access Tokens',
},
description: {
id: 'settings.pats.description',
defaultMessage:
"PATs can be used to access Modrinth's API. For more information, see <doc-link>Modrinth's API documentation</doc-link>. They can be created and revoked at any time.",
},
create: {
id: 'settings.pats.action.create',
defaultMessage: 'Create a PAT',
},
})
const tokenMessages = defineMessages({
edit: {
id: 'settings.pats.token.action.edit',
defaultMessage: 'Edit token',
},
revoke: {
id: 'settings.pats.token.action.revoke',
defaultMessage: 'Revoke token',
},
lastUsed: {
id: 'settings.pats.token.last-used',
defaultMessage: 'Last used {ago}',
},
neverUsed: {
id: 'settings.pats.token.never-used',
defaultMessage: 'Never used',
},
expiresIn: {
id: 'settings.pats.token.expires-in',
defaultMessage: 'Expires {inTime}',
},
expiredAgo: {
id: 'settings.pats.token.expired-ago',
defaultMessage: 'Expired {ago}',
},
})
definePageMeta({ definePageMeta({
middleware: 'auth', middleware: 'auth',
}) })
useHead({ useHead({
title: 'PATs - Modrinth', title: `${formatMessage(messages.title)} - Modrinth`,
}) })
const data = useNuxtApp() const data = useNuxtApp()
@@ -203,7 +349,7 @@ async function createPat() {
} catch (err) { } catch (err) {
data.$notify({ data.$notify({
group: 'main', group: 'main',
title: 'An error occurred', title: formatMessage(commonMessages.errorNotificationTitle),
text: err.data ? err.data.description : err, text: err.data ? err.data.description : err,
type: 'error', type: 'error',
}) })
@@ -229,7 +375,7 @@ async function editPat() {
} catch (err) { } catch (err) {
data.$notify({ data.$notify({
group: 'main', group: 'main',
title: 'An error occurred', title: formatMessage(commonMessages.errorNotificationTitle),
text: err.data ? err.data.description : err, text: err.data ? err.data.description : err,
type: 'error', type: 'error',
}) })
@@ -249,7 +395,7 @@ async function removePat(id) {
} catch (err) { } catch (err) {
data.$notify({ data.$notify({
group: 'main', group: 'main',
title: 'An error occurred', title: formatMessage(commonMessages.errorNotificationTitle),
text: err.data ? err.data.description : err, text: err.data ? err.data.description : err,
type: 'error', type: 'error',
}) })

View File

@@ -15,6 +15,10 @@ export const commonMessages = defineMessages({
id: 'button.continue', id: 'button.continue',
defaultMessage: 'Continue', defaultMessage: 'Continue',
}, },
createdAgoLabel: {
id: 'label.created-ago',
defaultMessage: 'Created {ago}',
},
dateAtTimeTooltip: { dateAtTimeTooltip: {
id: 'tooltip.date-at-time', id: 'tooltip.date-at-time',
defaultMessage: '{date, date, long} at {time, time, short}', defaultMessage: '{date, date, long} at {time, time, short}',
@@ -71,6 +75,14 @@ export const commonMessages = defineMessages({
id: 'button.save', id: 'button.save',
defaultMessage: 'Save', defaultMessage: 'Save',
}, },
saveChangesButton: {
id: 'button.save-changes',
defaultMessage: 'Save changes',
},
scopesLabel: {
id: 'label.scopes',
defaultMessage: 'Scopes',
},
titleLabel: { titleLabel: {
id: 'label.title', id: 'label.title',
defaultMessage: 'Title', defaultMessage: 'Title',