更新国际化支持:为仪表板各组件添加多语言文本,优化用户体验

This commit is contained in:
jxxghp
2025-04-28 16:57:06 +08:00
parent f3af10e93e
commit 6f78e8196b
13 changed files with 139 additions and 32 deletions

View File

@@ -2,6 +2,10 @@
import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
import api from '@/api'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数
const props = defineProps({
@@ -149,7 +153,7 @@ onActivated(() => {
</VCardItem>
<VCardText>
<VApexChart :key="chartKey" type="line" :options="chartOptions" :series="series" :height="150" />
<p class="text-center font-weight-medium mb-0">当前{{ current }}%</p>
<p class="text-center font-weight-medium mb-0">{{ t('dashboard.current') }}{{ current }}%</p>
</VCardText>
</VCard>
</template>

View File

@@ -1,6 +1,10 @@
<script setup lang="ts">
import api from '@/api'
import type { MediaStatistic } from '@/api/types'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
const statistics = ref<{ [key: string]: string }[]>([])
@@ -11,25 +15,25 @@ async function loadMediaStatistic() {
statistics.value = [
{
title: '电影',
title: t('mediaType.movie'),
stats: res.movie_count.toLocaleString(),
icon: 'mdi-movie-roll',
color: 'primary',
},
{
title: '电视剧',
title: t('mediaType.tv'),
stats: res.tv_count.toLocaleString(),
icon: 'mdi-television-box',
color: 'success',
},
{
title: '剧集',
title: t('dashboard.episodes'),
stats: res.episode_count.toLocaleString(),
icon: 'mdi-television-classic',
color: 'warning',
},
{
title: '用户',
title: t('dashboard.users'),
stats: res.user_count.toLocaleString(),
icon: 'mdi-account',
color: 'info',
@@ -57,7 +61,7 @@ onActivated(() => {
<template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template>
<VCardTitle>媒体统计</VCardTitle>
<VCardTitle>{{ t('dashboard.mediaStatistic') }}</VCardTitle>
</VCardItem>
<VCardText>

View File

@@ -3,6 +3,10 @@ import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils'
import api from '@/api'
import { formatBytes } from '@/@core/utils/formatters'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数
const props = defineProps({
@@ -151,11 +155,11 @@ onActivated(() => {
<template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template>
<VCardTitle>内存</VCardTitle>
<VCardTitle>{{ t('dashboard.memory') }}</VCardTitle>
</VCardItem>
<VCardText>
<VApexChart :key="chartKey" type="area" :options="chartOptions" :series="series" :height="150" />
<p class="text-center font-weight-medium mb-0">当前{{ formatBytes(usedMemory) }}</p>
<p class="text-center font-weight-medium mb-0">{{ t('dashboard.current') }}{{ formatBytes(usedMemory) }}</p>
</VCardText>
</VCard>
</template>

View File

@@ -2,9 +2,18 @@
import { formatSeconds } from '@/@core/utils/formatters'
import api from '@/api'
import type { Process } from '@/api/types'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 表头
const headers = ['进程ID', '进程名称', '运行时间', '内存占用']
const headers = [
t('dashboard.processes.pid'),
t('dashboard.processes.name'),
t('dashboard.processes.runtime'),
t('dashboard.processes.memory'),
]
// 数据列表
const processList = ref<Process[]>([])
@@ -47,7 +56,7 @@ onUnmounted(() => {
<template #append>
<VIcon class="cursor-move">mdi-drag</VIcon>
</template>
<VCardTitle>系统进程</VCardTitle>
<VCardTitle>{{ t('dashboard.processes.title') }}</VCardTitle>
</VCardItem>
<VTable item-key="fullName" class="table-rounded" hide-default-footer disable-sort>
<thead>

View File

@@ -1,6 +1,10 @@
<script setup lang="ts">
import api from '@/api'
import type { ScheduleInfo } from '@/api/types'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数
const props = defineProps({
@@ -57,7 +61,7 @@ onUnmounted(() => {
<template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template>
<VCardTitle>后台任务</VCardTitle>
<VCardTitle>{{ t('dashboard.scheduler') }}</VCardTitle>
</VCardItem>
<VCardText>
@@ -86,7 +90,7 @@ onUnmounted(() => {
</template>
</VListItem>
<VListItem v-if="schedulerList.length === 0">
<VListItemTitle class="text-center"> 没有后台服务 </VListItemTitle>
<VListItemTitle class="text-center"> {{ t('dashboard.noSchedulers') }} </VListItemTitle>
</VListItem>
</VList>
</VCardText>

View File

@@ -2,6 +2,10 @@
import { formatFileSize } from '@/@core/utils/formatters'
import api from '@/api'
import type { DownloaderInfo } from '@/api/types'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数
const props = defineProps({
@@ -55,17 +59,17 @@ async function loadDownloaderInfo() {
infoItems.value = [
{
avatar: 'mdi-cloud-upload',
title: '总上传量',
title: t('dashboard.speed.totalUpload'),
amount: formatFileSize(res.upload_size),
},
{
avatar: 'mdi-download-box',
title: '总下载量',
title: t('dashboard.speed.totalDownload'),
amount: formatFileSize(res.download_size),
},
{
avatar: 'mdi-content-save',
title: '磁盘剩余空间',
title: t('dashboard.speed.freeSpace'),
amount: formatFileSize(res.free_space),
},
]
@@ -100,7 +104,7 @@ onUnmounted(() => {
<template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template>
<VCardTitle>实时速率</VCardTitle>
<VCardTitle>{{ t('dashboard.realTimeSpeed') }}</VCardTitle>
</VCardItem>
<VCardText class="pt-4">

View File

@@ -3,6 +3,10 @@ import { useTheme } from 'vuetify'
import api from '@/api'
import { hexToRgb } from '@layouts/utils'
import { useUserStore } from '@/stores'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
const vuetifyTheme = useTheme()
@@ -127,7 +131,7 @@ onActivated(() => {
<template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template>
<VCardTitle>最近入库</VCardTitle>
<VCardTitle>{{ t('dashboard.weeklyOverview') }}</VCardTitle>
</VCardItem>
<VCardText>
@@ -136,10 +140,10 @@ onActivated(() => {
<h5 class="text-h5 me-4">
{{ totalCount }}
</h5>
<p>最近一周入库了 {{ totalCount }} 部影片 😎</p>
<p>{{ t('dashboard.weeklyOverviewDescription', { count: totalCount }) }} 😎</p>
</div>
<VBtn v-if="superUser" block to="/history"> 查看详情 </VBtn>
<VBtn v-if="superUser" block to="/history"> {{ t('common.viewDetails') }} </VBtn>
</VCardText>
</VCard>
</template>

View File

@@ -3,6 +3,10 @@ import { ref, onMounted } from 'vue'
import api from '@/api'
import type { MediaServerConf, MediaServerPlayItem } from '@/api/types'
import PosterCard from '@/components/cards/PosterCard.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 最近入库列表
const latestList = ref<{ [key: string]: MediaServerPlayItem[] }>({})
@@ -16,7 +20,7 @@ async function loadMediaServerSetting() {
const response: { data: { value: MediaServerConf[] } } = await api.get('system/setting/MediaServers')
mediaServers.value = response.data?.value ?? []
} catch (error) {
console.log('加载媒体服务器设置失败:', error)
console.log(t('dashboard.errors.loadMediaServer'), error)
}
}
@@ -29,7 +33,7 @@ async function loadLatest(server: string) {
latestList.value[server] = response
}
} catch (e) {
console.log(`加载媒体服务器 "${server}" 的最近入库失败:`, e)
console.log(t('dashboard.errors.loadLatest', { server }), e)
}
}
@@ -60,7 +64,7 @@ onActivated(() => {
<template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template>
<VCardTitle>最近添加 - {{ name }}</VCardTitle>
<VCardTitle>{{ t('dashboard.latest') }} - {{ name }}</VCardTitle>
</VCardItem>
<div class="grid gap-4 grid-media-card mx-3 mb-3" tabindex="0">

View File

@@ -2,6 +2,10 @@
import api from '@/api'
import type { MediaServerConf, MediaServerPlayItem } from '@/api/types'
import BackdropCard from '@/components/cards/BackdropCard.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 继续播放列表
const playingList = ref<MediaServerPlayItem[]>([])
@@ -63,7 +67,7 @@ onActivated(() => {
<template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template>
<VCardTitle>继续观看</VCardTitle>
<VCardTitle>{{ t('dashboard.playing') }}</VCardTitle>
</VCardItem>
<div class="grid gap-4 grid-backdrop-card mx-3" tabindex="0">