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

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
+28 -6
View File
@@ -10,10 +10,10 @@ export default {
loading: 'Loading', loading: 'Loading',
success: 'Success', success: 'Success',
error: 'Error', error: 'Error',
openInNewWindow: 'Open in New Window', openInNewWindow: 'Open in new window',
inputMessage: 'Enter message or command', inputMessage: 'Enter message or command',
send: 'Send', send: 'Send',
noData: 'No Data', noData: 'No data',
noContent: 'No relevant content found', noContent: 'No relevant content found',
all: 'All', all: 'All',
default: 'Default', default: 'Default',
@@ -24,6 +24,7 @@ export default {
theme: 'Theme', theme: 'Theme',
language: 'Language', language: 'Language',
pleaseWait: 'Please wait...', pleaseWait: 'Please wait...',
viewDetails: 'View Details',
}, },
mediaType: { mediaType: {
movie: 'Movie', movie: 'Movie',
@@ -236,10 +237,10 @@ export default {
dragComponentHint: 'Drag component to canvas', dragComponentHint: 'Drag component to canvas',
}, },
dashboard: { dashboard: {
storage: 'Storage Space', storage: 'Storage',
mediaStatistic: 'Media Statistics', mediaStatistic: 'Media Statistics',
weeklyOverview: 'Recent Additions', weeklyOverview: 'Recent Imports',
speed: 'Real-time Speed', realTimeSpeed: 'Real-time Speed',
scheduler: 'Background Tasks', scheduler: 'Background Tasks',
cpu: 'CPU', cpu: 'CPU',
memory: 'Memory', memory: 'Memory',
@@ -247,8 +248,29 @@ export default {
playing: 'Continue Watching', playing: 'Continue Watching',
latest: 'Recently Added', latest: 'Recently Added',
settings: 'Dashboard Settings', settings: 'Dashboard Settings',
chooseContent: 'Choose content you want to display on the page', chooseContent: 'Choose content to display',
adaptiveHeight: 'Adaptive Component Height', 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: { media: {
status: { status: {
+23 -1
View File
@@ -24,6 +24,7 @@ export default {
theme: '主题', theme: '主题',
language: '语言', language: '语言',
pleaseWait: '请稍候...', pleaseWait: '请稍候...',
viewDetails: '查看详情',
}, },
mediaType: { mediaType: {
movie: '电影', movie: '电影',
@@ -239,7 +240,7 @@ export default {
storage: '存储空间', storage: '存储空间',
mediaStatistic: '媒体统计', mediaStatistic: '媒体统计',
weeklyOverview: '最近入库', weeklyOverview: '最近入库',
speed: '实时速率', realTimeSpeed: '实时速率',
scheduler: '后台任务', scheduler: '后台任务',
cpu: 'CPU', cpu: 'CPU',
memory: '内存', memory: '内存',
@@ -249,6 +250,27 @@ export default {
settings: '设置仪表板', settings: '设置仪表板',
chooseContent: '选择您想在页面显示的内容', chooseContent: '选择您想在页面显示的内容',
adaptiveHeight: '自适应组件高度', adaptiveHeight: '自适应组件高度',
current: '当前',
episodes: '剧集',
users: '用户',
noSchedulers: '没有后台服务',
weeklyOverviewDescription: '最近一周入库了 {count} 部影片',
speed: {
totalUpload: '总上传量',
totalDownload: '总下载量',
freeSpace: '磁盘剩余空间',
},
processes: {
title: '系统进程',
pid: '进程ID',
name: '进程名称',
runtime: '运行时间',
memory: '内存占用',
},
errors: {
loadMediaServer: '加载媒体服务器设置失败:',
loadLatest: '加载媒体服务器 "{server}" 的最近入库失败:',
},
}, },
media: { media: {
status: { status: {
+23 -1
View File
@@ -24,6 +24,7 @@ export default {
theme: '主題', theme: '主題',
language: '語言', language: '語言',
pleaseWait: '請稍候...', pleaseWait: '請稍候...',
viewDetails: '查看詳情',
}, },
mediaType: { mediaType: {
movie: '電影', movie: '電影',
@@ -239,7 +240,7 @@ export default {
storage: '存儲空間', storage: '存儲空間',
mediaStatistic: '媒體統計', mediaStatistic: '媒體統計',
weeklyOverview: '最近入庫', weeklyOverview: '最近入庫',
speed: '實時速率', realTimeSpeed: '實時速率',
scheduler: '後台任務', scheduler: '後台任務',
cpu: 'CPU', cpu: 'CPU',
memory: '內存', memory: '內存',
@@ -249,6 +250,27 @@ export default {
settings: '設置儀表板', settings: '設置儀表板',
chooseContent: '選擇您想在頁面顯示的內容', chooseContent: '選擇您想在頁面顯示的內容',
adaptiveHeight: '自適應組件高度', adaptiveHeight: '自適應組件高度',
current: '當前',
episodes: '劇集',
users: '用戶',
noSchedulers: '沒有後台服務',
weeklyOverviewDescription: '最近一週入庫了 {count} 部影片',
speed: {
totalUpload: '總上傳量',
totalDownload: '總下載量',
freeSpace: '磁盤剩餘空間',
},
processes: {
title: '系統進程',
pid: '進程ID',
name: '進程名稱',
runtime: '運行時間',
memory: '內存佔用',
},
errors: {
loadMediaServer: '加載媒體服務器設置失敗:',
loadLatest: '加載媒體服務器 "{server}" 的最近入庫失敗:',
},
}, },
media: { media: {
status: { status: {
+1 -1
View File
@@ -81,7 +81,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
}, },
{ {
id: 'speed', id: 'speed',
name: t('dashboard.speed'), name: t('dashboard.realTimeSpeed'),
key: '', key: '',
attrs: {}, attrs: {},
cols: { cols: 12, md: 4 }, cols: { cols: 12, md: 4 },
+5 -1
View File
@@ -2,6 +2,10 @@
import { useTheme } from 'vuetify' import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils' import { hexToRgb } from '@layouts/utils'
import api from '@/api' import api from '@/api'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
@@ -149,7 +153,7 @@ onActivated(() => {
</VCardItem> </VCardItem>
<VCardText> <VCardText>
<VApexChart :key="chartKey" type="line" :options="chartOptions" :series="series" :height="150" /> <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> </VCardText>
</VCard> </VCard>
</template> </template>
@@ -1,6 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import api from '@/api' import api from '@/api'
import type { MediaStatistic } from '@/api/types' import type { MediaStatistic } from '@/api/types'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
const statistics = ref<{ [key: string]: string }[]>([]) const statistics = ref<{ [key: string]: string }[]>([])
@@ -11,25 +15,25 @@ async function loadMediaStatistic() {
statistics.value = [ statistics.value = [
{ {
title: '电影', title: t('mediaType.movie'),
stats: res.movie_count.toLocaleString(), stats: res.movie_count.toLocaleString(),
icon: 'mdi-movie-roll', icon: 'mdi-movie-roll',
color: 'primary', color: 'primary',
}, },
{ {
title: '电视剧', title: t('mediaType.tv'),
stats: res.tv_count.toLocaleString(), stats: res.tv_count.toLocaleString(),
icon: 'mdi-television-box', icon: 'mdi-television-box',
color: 'success', color: 'success',
}, },
{ {
title: '剧集', title: t('dashboard.episodes'),
stats: res.episode_count.toLocaleString(), stats: res.episode_count.toLocaleString(),
icon: 'mdi-television-classic', icon: 'mdi-television-classic',
color: 'warning', color: 'warning',
}, },
{ {
title: '用户', title: t('dashboard.users'),
stats: res.user_count.toLocaleString(), stats: res.user_count.toLocaleString(),
icon: 'mdi-account', icon: 'mdi-account',
color: 'info', color: 'info',
@@ -57,7 +61,7 @@ onActivated(() => {
<template #append> <template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon> <VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template> </template>
<VCardTitle>媒体统计</VCardTitle> <VCardTitle>{{ t('dashboard.mediaStatistic') }}</VCardTitle>
</VCardItem> </VCardItem>
<VCardText> <VCardText>
+6 -2
View File
@@ -3,6 +3,10 @@ import { useTheme } from 'vuetify'
import { hexToRgb } from '@layouts/utils' import { hexToRgb } from '@layouts/utils'
import api from '@/api' import api from '@/api'
import { formatBytes } from '@/@core/utils/formatters' import { formatBytes } from '@/@core/utils/formatters'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
@@ -151,11 +155,11 @@ onActivated(() => {
<template #append> <template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon> <VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template> </template>
<VCardTitle>内存</VCardTitle> <VCardTitle>{{ t('dashboard.memory') }}</VCardTitle>
</VCardItem> </VCardItem>
<VCardText> <VCardText>
<VApexChart :key="chartKey" type="area" :options="chartOptions" :series="series" :height="150" /> <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> </VCardText>
</VCard> </VCard>
</template> </template>
+11 -2
View File
@@ -2,9 +2,18 @@
import { formatSeconds } from '@/@core/utils/formatters' import { formatSeconds } from '@/@core/utils/formatters'
import api from '@/api' import api from '@/api'
import type { Process } from '@/api/types' 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[]>([]) const processList = ref<Process[]>([])
@@ -47,7 +56,7 @@ onUnmounted(() => {
<template #append> <template #append>
<VIcon class="cursor-move">mdi-drag</VIcon> <VIcon class="cursor-move">mdi-drag</VIcon>
</template> </template>
<VCardTitle>系统进程</VCardTitle> <VCardTitle>{{ t('dashboard.processes.title') }}</VCardTitle>
</VCardItem> </VCardItem>
<VTable item-key="fullName" class="table-rounded" hide-default-footer disable-sort> <VTable item-key="fullName" class="table-rounded" hide-default-footer disable-sort>
<thead> <thead>
+6 -2
View File
@@ -1,6 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import api from '@/api' import api from '@/api'
import type { ScheduleInfo } from '@/api/types' import type { ScheduleInfo } from '@/api/types'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
@@ -57,7 +61,7 @@ onUnmounted(() => {
<template #append> <template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon> <VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template> </template>
<VCardTitle>后台任务</VCardTitle> <VCardTitle>{{ t('dashboard.scheduler') }}</VCardTitle>
</VCardItem> </VCardItem>
<VCardText> <VCardText>
@@ -86,7 +90,7 @@ onUnmounted(() => {
</template> </template>
</VListItem> </VListItem>
<VListItem v-if="schedulerList.length === 0"> <VListItem v-if="schedulerList.length === 0">
<VListItemTitle class="text-center"> 没有后台服务 </VListItemTitle> <VListItemTitle class="text-center"> {{ t('dashboard.noSchedulers') }} </VListItemTitle>
</VListItem> </VListItem>
</VList> </VList>
</VCardText> </VCardText>
+8 -4
View File
@@ -2,6 +2,10 @@
import { formatFileSize } from '@/@core/utils/formatters' import { formatFileSize } from '@/@core/utils/formatters'
import api from '@/api' import api from '@/api'
import type { DownloaderInfo } from '@/api/types' import type { DownloaderInfo } from '@/api/types'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
@@ -55,17 +59,17 @@ async function loadDownloaderInfo() {
infoItems.value = [ infoItems.value = [
{ {
avatar: 'mdi-cloud-upload', avatar: 'mdi-cloud-upload',
title: '总上传量', title: t('dashboard.speed.totalUpload'),
amount: formatFileSize(res.upload_size), amount: formatFileSize(res.upload_size),
}, },
{ {
avatar: 'mdi-download-box', avatar: 'mdi-download-box',
title: '总下载量', title: t('dashboard.speed.totalDownload'),
amount: formatFileSize(res.download_size), amount: formatFileSize(res.download_size),
}, },
{ {
avatar: 'mdi-content-save', avatar: 'mdi-content-save',
title: '磁盘剩余空间', title: t('dashboard.speed.freeSpace'),
amount: formatFileSize(res.free_space), amount: formatFileSize(res.free_space),
}, },
] ]
@@ -100,7 +104,7 @@ onUnmounted(() => {
<template #append> <template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon> <VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template> </template>
<VCardTitle>实时速率</VCardTitle> <VCardTitle>{{ t('dashboard.realTimeSpeed') }}</VCardTitle>
</VCardItem> </VCardItem>
<VCardText class="pt-4"> <VCardText class="pt-4">
@@ -3,6 +3,10 @@ import { useTheme } from 'vuetify'
import api from '@/api' import api from '@/api'
import { hexToRgb } from '@layouts/utils' import { hexToRgb } from '@layouts/utils'
import { useUserStore } from '@/stores' import { useUserStore } from '@/stores'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
const vuetifyTheme = useTheme() const vuetifyTheme = useTheme()
@@ -127,7 +131,7 @@ onActivated(() => {
<template #append> <template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon> <VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template> </template>
<VCardTitle>最近入库</VCardTitle> <VCardTitle>{{ t('dashboard.weeklyOverview') }}</VCardTitle>
</VCardItem> </VCardItem>
<VCardText> <VCardText>
@@ -136,10 +140,10 @@ onActivated(() => {
<h5 class="text-h5 me-4"> <h5 class="text-h5 me-4">
{{ totalCount }} {{ totalCount }}
</h5> </h5>
<p>最近一周入库了 {{ totalCount }} 部影片 😎</p> <p>{{ t('dashboard.weeklyOverviewDescription', { count: totalCount }) }} 😎</p>
</div> </div>
<VBtn v-if="superUser" block to="/history"> 查看详情 </VBtn> <VBtn v-if="superUser" block to="/history"> {{ t('common.viewDetails') }} </VBtn>
</VCardText> </VCardText>
</VCard> </VCard>
</template> </template>
+7 -3
View File
@@ -3,6 +3,10 @@ import { ref, onMounted } from 'vue'
import api from '@/api' import api from '@/api'
import type { MediaServerConf, MediaServerPlayItem } from '@/api/types' import type { MediaServerConf, MediaServerPlayItem } from '@/api/types'
import PosterCard from '@/components/cards/PosterCard.vue' import PosterCard from '@/components/cards/PosterCard.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 最近入库列表 // 最近入库列表
const latestList = ref<{ [key: string]: MediaServerPlayItem[] }>({}) const latestList = ref<{ [key: string]: MediaServerPlayItem[] }>({})
@@ -16,7 +20,7 @@ async function loadMediaServerSetting() {
const response: { data: { value: MediaServerConf[] } } = await api.get('system/setting/MediaServers') const response: { data: { value: MediaServerConf[] } } = await api.get('system/setting/MediaServers')
mediaServers.value = response.data?.value ?? [] mediaServers.value = response.data?.value ?? []
} catch (error) { } 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 latestList.value[server] = response
} }
} catch (e) { } catch (e) {
console.log(`加载媒体服务器 "${server}" 的最近入库失败:`, e) console.log(t('dashboard.errors.loadLatest', { server }), e)
} }
} }
@@ -60,7 +64,7 @@ onActivated(() => {
<template #append> <template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon> <VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template> </template>
<VCardTitle>最近添加 - {{ name }}</VCardTitle> <VCardTitle>{{ t('dashboard.latest') }} - {{ name }}</VCardTitle>
</VCardItem> </VCardItem>
<div class="grid gap-4 grid-media-card mx-3 mb-3" tabindex="0"> <div class="grid gap-4 grid-media-card mx-3 mb-3" tabindex="0">
+5 -1
View File
@@ -2,6 +2,10 @@
import api from '@/api' import api from '@/api'
import type { MediaServerConf, MediaServerPlayItem } from '@/api/types' import type { MediaServerConf, MediaServerPlayItem } from '@/api/types'
import BackdropCard from '@/components/cards/BackdropCard.vue' import BackdropCard from '@/components/cards/BackdropCard.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 继续播放列表 // 继续播放列表
const playingList = ref<MediaServerPlayItem[]>([]) const playingList = ref<MediaServerPlayItem[]>([])
@@ -63,7 +67,7 @@ onActivated(() => {
<template #append> <template #append>
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon> <VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
</template> </template>
<VCardTitle>继续观看</VCardTitle> <VCardTitle>{{ t('dashboard.playing') }}</VCardTitle>
</VCardItem> </VCardItem>
<div class="grid gap-4 grid-backdrop-card mx-3" tabindex="0"> <div class="grid gap-4 grid-backdrop-card mx-3" tabindex="0">