feat(SPA): i18n internationzalization, english and french
This commit is contained in:
1 parent
7f1e8e572d
commit
721311a643
88 files changed
+4438
-1148
No files matched your search
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { t } from '@/i18n'
|
||||
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { useOverlay, useToast } from '@nuxt/ui/composables'
|
||||
import { useLocalizedOverlay, useLocalizedToast } from '@/i18n/presentation'
|
||||
import ConfirmDialog from '@/components/ConfirmDialog.vue'
|
||||
import DashboardShell from '@/components/DashboardShell.vue'
|
||||
import RestartOverlay from '@/components/RestartOverlay.vue'
|
||||
@@ -22,17 +24,25 @@ const RESTART_FAILED_COPY =
|
||||
const RESTART_WARNING =
|
||||
"Your site will be unavailable for about 10 seconds. This page reloads on its own when the site is back. Save anything you're editing first."
|
||||
const PLAIN_RESTART_DIALOG = {
|
||||
title: 'Restart the site?',
|
||||
description: RESTART_WARNING,
|
||||
confirmLabel: 'Restart site',
|
||||
cancelLabel: 'Cancel',
|
||||
get title() {
|
||||
return t('Restart the site?')
|
||||
},
|
||||
get description() {
|
||||
return t(RESTART_WARNING)
|
||||
},
|
||||
get confirmLabel() {
|
||||
return t('Restart site')
|
||||
},
|
||||
get cancelLabel() {
|
||||
return t('Cancel')
|
||||
},
|
||||
}
|
||||
|
||||
type LoadState = 'loading' | 'ready' | 'error'
|
||||
|
||||
const { getSettings } = useSettings()
|
||||
const toast = useToast()
|
||||
const overlay = useOverlay()
|
||||
const toast = useLocalizedToast()
|
||||
const overlay = useLocalizedOverlay()
|
||||
const session = useSessionStore()
|
||||
const update = useUpdateStore()
|
||||
const retry = useRetryAfter()
|
||||
@@ -108,12 +118,16 @@ async function reloadAfterRoleChange() {
|
||||
}
|
||||
|
||||
function notifyOnlyOwner() {
|
||||
toast.add({
|
||||
toast.add(() => ({
|
||||
color: 'error',
|
||||
icon: 'i-lucide-circle-x',
|
||||
title: 'Only the owner can do this',
|
||||
description: 'Ask the owner of this site to update RenewCMS.',
|
||||
})
|
||||
get title() {
|
||||
return t('Only the owner can do this')
|
||||
},
|
||||
get description() {
|
||||
return t('Ask the owner of this site to update RenewCMS.')
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
async function onUpdate() {
|
||||
@@ -127,24 +141,32 @@ async function onUpdate() {
|
||||
return
|
||||
}
|
||||
if (result === 'nothing') {
|
||||
toast.add({
|
||||
toast.add(() => ({
|
||||
color: 'info',
|
||||
icon: 'i-lucide-info',
|
||||
title: 'Nothing to update',
|
||||
description: 'You already have the latest version.',
|
||||
})
|
||||
get title() {
|
||||
return t('Nothing to update')
|
||||
},
|
||||
get description() {
|
||||
return t('You already have the latest version.')
|
||||
},
|
||||
}))
|
||||
await update.load()
|
||||
return
|
||||
}
|
||||
if (result === 'conflict') {
|
||||
await update.load()
|
||||
if (update.jobRunning) {
|
||||
toast.add({
|
||||
toast.add(() => ({
|
||||
color: 'info',
|
||||
icon: 'i-lucide-info',
|
||||
title: 'An update is already running',
|
||||
description: 'Another owner started it. Progress shows here.',
|
||||
})
|
||||
get title() {
|
||||
return t('An update is already running')
|
||||
},
|
||||
get description() {
|
||||
return t('Another owner started it. Progress shows here.')
|
||||
},
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,10 +183,21 @@ async function onCheck() {
|
||||
function installRestartDialog() {
|
||||
const version = displayVersion(update.status?.latest ?? '')
|
||||
return {
|
||||
title: 'Restart to finish the update?',
|
||||
description: `RenewCMS will install version ${version} and restart. ${RESTART_WARNING}`,
|
||||
confirmLabel: 'Restart now',
|
||||
cancelLabel: 'Restart later',
|
||||
get title() {
|
||||
return t('Restart to finish the update?')
|
||||
},
|
||||
get description() {
|
||||
return t('RenewCMS will install version {0} and restart. {1}', [
|
||||
version,
|
||||
t(RESTART_WARNING),
|
||||
])
|
||||
},
|
||||
get confirmLabel() {
|
||||
return t('Restart now')
|
||||
},
|
||||
get cancelLabel() {
|
||||
return t('Restart later')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,12 +208,14 @@ async function onRestart(kind: RestartKind) {
|
||||
.create(ConfirmDialog, {
|
||||
props: {
|
||||
...dialog,
|
||||
pendingLabel: 'Restarting…',
|
||||
get pendingLabel() {
|
||||
return t('Restarting…')
|
||||
},
|
||||
tone: 'neutral',
|
||||
action: async () => {
|
||||
attempt.result = await update.requestRestart(kind)
|
||||
if (attempt.result === 'failed') {
|
||||
throw new Error(RESTART_FAILED_COPY)
|
||||
throw new Error(t(RESTART_FAILED_COPY))
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -209,12 +244,16 @@ async function settleRefusedRestart(result: RestartRequestResult) {
|
||||
}
|
||||
await update.load()
|
||||
if (update.jobRunning || update.restarting) {
|
||||
toast.add({
|
||||
toast.add(() => ({
|
||||
color: 'info',
|
||||
icon: 'i-lucide-info',
|
||||
title: 'An update is already running',
|
||||
description: 'Another owner started it. Progress shows here.',
|
||||
})
|
||||
get title() {
|
||||
return t('An update is already running')
|
||||
},
|
||||
get description() {
|
||||
return t('Another owner started it. Progress shows here.')
|
||||
},
|
||||
}))
|
||||
}
|
||||
update.resumeRestart()
|
||||
}
|
||||
@@ -223,26 +262,40 @@ const OUTCOME_TOASTS = {
|
||||
updated: () => ({
|
||||
color: 'success' as const,
|
||||
icon: 'i-lucide-circle-check',
|
||||
title: 'Update installed',
|
||||
description: `RenewCMS is now on version ${displayVersion(update.status?.current ?? '')}.`,
|
||||
get title() {
|
||||
return t('Update installed')
|
||||
},
|
||||
get description() {
|
||||
return t('RenewCMS is now on version {0}.', [
|
||||
displayVersion(update.status?.current ?? ''),
|
||||
])
|
||||
},
|
||||
}),
|
||||
'rolled-back': () => ({
|
||||
color: 'error' as const,
|
||||
icon: 'i-lucide-circle-x',
|
||||
title: "The update didn't install",
|
||||
description: `Your site is back on ${update.status?.current ?? ''}.`,
|
||||
get title() {
|
||||
return t("The update didn't install")
|
||||
},
|
||||
get description() {
|
||||
return t('Your site is back on {0}.', [update.status?.current ?? ''])
|
||||
},
|
||||
duration: 0,
|
||||
}),
|
||||
restarted: () => ({
|
||||
color: 'success' as const,
|
||||
icon: 'i-lucide-circle-check',
|
||||
title: 'Site restarted',
|
||||
description: 'Your site is running again.',
|
||||
get title() {
|
||||
return t('Site restarted')
|
||||
},
|
||||
get description() {
|
||||
return t('Your site is running again.')
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
async function announceRestartOutcome(outcome: RestartOutcome) {
|
||||
toast.add(OUTCOME_TOASTS[outcome]())
|
||||
toast.add(() => OUTCOME_TOASTS[outcome]())
|
||||
await nextTick()
|
||||
updatesCard.value?.focusHeading()
|
||||
}
|
||||
@@ -330,8 +383,10 @@ onBeforeUnmount(() => {
|
||||
/>
|
||||
<div class="flex max-w-164 flex-col gap-5" :inert="update.restartRun !== null">
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<h1 class="text-xl font-semibold text-highlighted">Settings</h1>
|
||||
<p class="text-muted">Workspace information.</p>
|
||||
<h1 class="text-xl font-semibold text-highlighted">
|
||||
{{ t('Settings') }}
|
||||
</h1>
|
||||
<p class="text-muted">{{ t('Workspace information.') }}</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -347,7 +402,7 @@ onBeforeUnmount(() => {
|
||||
orientation="vertical"
|
||||
:close="false"
|
||||
icon="i-lucide-circle-x"
|
||||
:description="UNREACHABLE_COPY"
|
||||
:description="t(UNREACHABLE_COPY)"
|
||||
:ui="{ actions: 'mt-2' }"
|
||||
>
|
||||
<template #actions>
|
||||
@@ -359,13 +414,13 @@ onBeforeUnmount(() => {
|
||||
:ui="{ leadingIcon: 'size-3.5' }"
|
||||
@click="loadSettings"
|
||||
>
|
||||
Try again
|
||||
{{ t('Try again') }}
|
||||
</UButton>
|
||||
</template>
|
||||
</UAlert>
|
||||
|
||||
<div v-else class="flex items-center justify-between gap-4">
|
||||
<span class="text-lg font-semibold text-highlighted">Version</span>
|
||||
<span class="text-lg font-semibold text-highlighted">{{ t('Version') }}</span>
|
||||
<USkeleton
|
||||
v-if="loadState === 'loading' && showSkeleton"
|
||||
data-testid="settings-skeleton"
|
||||
|
||||
Reference in new issue
Block a user