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,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { t } from '@/i18n'
|
||||
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import ArticleStatusBadge from '@/components/ArticleStatusBadge.vue'
|
||||
@@ -27,10 +29,37 @@ const columnWidths =
|
||||
const sorting = ref([{ id: 'updated_at', desc: true }])
|
||||
|
||||
const columns = [
|
||||
{ accessorKey: 'title', header: 'Title', enableSorting: true },
|
||||
{ accessorKey: 'is_online', header: 'Status', size: 110, enableSorting: true },
|
||||
{ accessorKey: 'created_at', header: 'Created', size: 130, enableSorting: true },
|
||||
{ accessorKey: 'updated_at', header: 'Updated', size: 140, enableSorting: true },
|
||||
{
|
||||
accessorKey: 'title',
|
||||
get header() {
|
||||
return t('Title')
|
||||
},
|
||||
enableSorting: true,
|
||||
},
|
||||
{
|
||||
accessorKey: 'is_online',
|
||||
get header() {
|
||||
return t('Status')
|
||||
},
|
||||
size: 110,
|
||||
enableSorting: true,
|
||||
},
|
||||
{
|
||||
accessorKey: 'created_at',
|
||||
get header() {
|
||||
return t('Created')
|
||||
},
|
||||
size: 130,
|
||||
enableSorting: true,
|
||||
},
|
||||
{
|
||||
accessorKey: 'updated_at',
|
||||
get header() {
|
||||
return t('Updated')
|
||||
},
|
||||
size: 140,
|
||||
enableSorting: true,
|
||||
},
|
||||
{ id: 'actions', header: '', size: 44 },
|
||||
]
|
||||
|
||||
@@ -64,12 +93,16 @@ function actionsFor(article: Article) {
|
||||
return [
|
||||
[
|
||||
{
|
||||
label: 'Edit',
|
||||
get label() {
|
||||
return t('Edit')
|
||||
},
|
||||
icon: 'i-lucide-pencil',
|
||||
onSelect: () => router.push(editPath(article)),
|
||||
},
|
||||
{
|
||||
label: article.is_online ? 'Unpublish' : 'Publish',
|
||||
get label() {
|
||||
return article.is_online ? t('Unpublish') : t('Publish')
|
||||
},
|
||||
icon: article.is_online ? 'i-lucide-globe-lock' : 'i-lucide-globe',
|
||||
disabled: isBusy(article),
|
||||
onSelect: () => {
|
||||
@@ -81,14 +114,18 @@ function actionsFor(article: Article) {
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Copy API URL',
|
||||
get label() {
|
||||
return t('Copy API URL')
|
||||
},
|
||||
icon: 'i-lucide-link',
|
||||
onSelect: () => emit('copy-url', article.id),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
label: 'Delete…',
|
||||
get label() {
|
||||
return t('Delete…')
|
||||
},
|
||||
icon: 'i-lucide-trash-2',
|
||||
color: 'error' as const,
|
||||
onSelect: () => emit('delete', article),
|
||||
@@ -104,7 +141,7 @@ function onSelect(_event: Event, row: { original: Article }) {
|
||||
|
||||
<template>
|
||||
<div v-if="loading" aria-busy="true" class="hidden border border-default bg-default md:block">
|
||||
<span role="status" class="sr-only">Loading articles</span>
|
||||
<span role="status" class="sr-only">{{ t('Loading articles') }}</span>
|
||||
<div
|
||||
v-for="n in 5"
|
||||
:key="n"
|
||||
@@ -131,7 +168,9 @@ function onSelect(_event: Event, row: { original: Article }) {
|
||||
>
|
||||
<template #caption>
|
||||
<caption class="sr-only">
|
||||
Articles, sorted by last updated, newest first
|
||||
{{
|
||||
t('Articles, sorted by last updated, newest first')
|
||||
}}
|
||||
</caption>
|
||||
</template>
|
||||
|
||||
@@ -141,7 +180,7 @@ function onSelect(_event: Event, row: { original: Article }) {
|
||||
class="inline-flex items-center gap-1 text-highlighted"
|
||||
@click.stop="column.toggleSorting()"
|
||||
>
|
||||
Title
|
||||
{{ t('Title') }}
|
||||
<UIcon v-if="sortIcon(column)" :name="sortIcon(column)!" class="size-3" />
|
||||
</button>
|
||||
</template>
|
||||
@@ -152,7 +191,7 @@ function onSelect(_event: Event, row: { original: Article }) {
|
||||
class="inline-flex items-center gap-1 text-highlighted"
|
||||
@click.stop="column.toggleSorting()"
|
||||
>
|
||||
Status
|
||||
{{ t('Status') }}
|
||||
<UIcon v-if="sortIcon(column)" :name="sortIcon(column)!" class="size-3" />
|
||||
</button>
|
||||
</template>
|
||||
@@ -163,7 +202,7 @@ function onSelect(_event: Event, row: { original: Article }) {
|
||||
class="inline-flex items-center gap-1 text-highlighted"
|
||||
@click.stop="column.toggleSorting()"
|
||||
>
|
||||
Created
|
||||
{{ t('Created') }}
|
||||
<UIcon v-if="sortIcon(column)" :name="sortIcon(column)!" class="size-3" />
|
||||
</button>
|
||||
</template>
|
||||
@@ -174,7 +213,7 @@ function onSelect(_event: Event, row: { original: Article }) {
|
||||
class="inline-flex items-center gap-1 text-highlighted"
|
||||
@click.stop="column.toggleSorting()"
|
||||
>
|
||||
Updated
|
||||
{{ t('Updated') }}
|
||||
<UIcon v-if="sortIcon(column)" :name="sortIcon(column)!" class="size-3" />
|
||||
</button>
|
||||
</template>
|
||||
@@ -217,7 +256,7 @@ function onSelect(_event: Event, row: { original: Article }) {
|
||||
icon="i-lucide-ellipsis"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
:aria-label="`Actions for ${row.original.title}`"
|
||||
:aria-label="t('Actions for {0}', [row.original.title])"
|
||||
class="size-8 justify-center text-toned"
|
||||
@click.stop
|
||||
/>
|
||||
|
||||
Reference in new issue
Block a user