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

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

@@ -10,10 +10,10 @@ export default {
loading: 'Loading',
success: 'Success',
error: 'Error',
openInNewWindow: 'Open in New Window',
openInNewWindow: 'Open in new window',
inputMessage: 'Enter message or command',
send: 'Send',
noData: 'No Data',
noData: 'No data',
noContent: 'No relevant content found',
all: 'All',
default: 'Default',
@@ -24,6 +24,7 @@ export default {
theme: 'Theme',
language: 'Language',
pleaseWait: 'Please wait...',
viewDetails: 'View Details',
},
mediaType: {
movie: 'Movie',
@@ -236,10 +237,10 @@ export default {
dragComponentHint: 'Drag component to canvas',
},
dashboard: {
storage: 'Storage Space',
storage: 'Storage',
mediaStatistic: 'Media Statistics',
weeklyOverview: 'Recent Additions',
speed: 'Real-time Speed',
weeklyOverview: 'Recent Imports',
realTimeSpeed: 'Real-time Speed',
scheduler: 'Background Tasks',
cpu: 'CPU',
memory: 'Memory',
@@ -247,8 +248,29 @@ export default {
playing: 'Continue Watching',
latest: 'Recently Added',
settings: 'Dashboard Settings',
chooseContent: 'Choose content you want to display on the page',
chooseContent: 'Choose content to display',
adaptiveHeight: 'Adaptive Component Height',
current: 'Current',
episodes: 'Episodes',
users: 'Users',
noSchedulers: 'No Background Services',
weeklyOverviewDescription: 'Added {count} media in the last week',
speed: {
totalUpload: 'Total Upload',
totalDownload: 'Total Download',
freeSpace: 'Free Disk Space',
},
processes: {
title: 'System Processes',
pid: 'Process ID',
name: 'Process Name',
runtime: 'Runtime',
memory: 'Memory Usage',
},
errors: {
loadMediaServer: 'Failed to load media server settings:',
loadLatest: 'Failed to load recently added from media server "{server}":',
},
},
media: {
status: {

View File

@@ -24,6 +24,7 @@ export default {
theme: '主题',
language: '语言',
pleaseWait: '请稍候...',
viewDetails: '查看详情',
},
mediaType: {
movie: '电影',
@@ -239,7 +240,7 @@ export default {
storage: '存储空间',
mediaStatistic: '媒体统计',
weeklyOverview: '最近入库',
speed: '实时速率',
realTimeSpeed: '实时速率',
scheduler: '后台任务',
cpu: 'CPU',
memory: '内存',
@@ -249,6 +250,27 @@ export default {
settings: '设置仪表板',
chooseContent: '选择您想在页面显示的内容',
adaptiveHeight: '自适应组件高度',
current: '当前',
episodes: '剧集',
users: '用户',
noSchedulers: '没有后台服务',
weeklyOverviewDescription: '最近一周入库了 {count} 部影片',
speed: {
totalUpload: '总上传量',
totalDownload: '总下载量',
freeSpace: '磁盘剩余空间',
},
processes: {
title: '系统进程',
pid: '进程ID',
name: '进程名称',
runtime: '运行时间',
memory: '内存占用',
},
errors: {
loadMediaServer: '加载媒体服务器设置失败:',
loadLatest: '加载媒体服务器 "{server}" 的最近入库失败:',
},
},
media: {
status: {

View File

@@ -24,6 +24,7 @@ export default {
theme: '主題',
language: '語言',
pleaseWait: '請稍候...',
viewDetails: '查看詳情',
},
mediaType: {
movie: '電影',
@@ -239,7 +240,7 @@ export default {
storage: '存儲空間',
mediaStatistic: '媒體統計',
weeklyOverview: '最近入庫',
speed: '實時速率',
realTimeSpeed: '實時速率',
scheduler: '後台任務',
cpu: 'CPU',
memory: '內存',
@@ -249,6 +250,27 @@ export default {
settings: '設置儀表板',
chooseContent: '選擇您想在頁面顯示的內容',
adaptiveHeight: '自適應組件高度',
current: '當前',
episodes: '劇集',
users: '用戶',
noSchedulers: '沒有後台服務',
weeklyOverviewDescription: '最近一週入庫了 {count} 部影片',
speed: {
totalUpload: '總上傳量',
totalDownload: '總下載量',
freeSpace: '磁盤剩餘空間',
},
processes: {
title: '系統進程',
pid: '進程ID',
name: '進程名稱',
runtime: '運行時間',
memory: '內存佔用',
},
errors: {
loadMediaServer: '加載媒體服務器設置失敗:',
loadLatest: '加載媒體服務器 "{server}" 的最近入庫失敗:',
},
},
media: {
status: {

View File

@@ -81,7 +81,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
},
{
id: 'speed',
name: t('dashboard.speed'),
name: t('dashboard.realTimeSpeed'),
key: '',
attrs: {},
cols: { cols: 12, md: 4 },

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">