mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 07:28:37 +08:00
添加国际化支持:在多个组件中引入 vue-i18n,更新文本以实现多语言显示
This commit is contained in:
@@ -1,4 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -28,12 +33,12 @@ interface Props {
|
|||||||
|
|
||||||
<!-- 标题 -->
|
<!-- 标题 -->
|
||||||
<div class="error-title">
|
<div class="error-title">
|
||||||
{{ props.errorTitle || '暂无数据' }}
|
{{ props.errorTitle || t('common.noData') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 描述 -->
|
<!-- 描述 -->
|
||||||
<div class="error-description">
|
<div class="error-description">
|
||||||
{{ props.errorDescription || '没有找到相关内容' }}
|
{{ props.errorDescription || t('common.noContent') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 按钮插槽 -->
|
<!-- 按钮插槽 -->
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MediaServerPlayItem } from '@/api/types'
|
import type { MediaServerPlayItem } from '@/api/types'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import { useUserStore } from '@/stores'
|
|||||||
import SubscribeEditDialog from '../dialog/SubscribeEditDialog.vue'
|
import SubscribeEditDialog from '../dialog/SubscribeEditDialog.vue'
|
||||||
import SearchSiteDialog from '@/components/dialog/SearchSiteDialog.vue'
|
import SearchSiteDialog from '@/components/dialog/SearchSiteDialog.vue'
|
||||||
import SubscribeSeasonDialog from '../dialog/SubscribeSeasonDialog.vue'
|
import SubscribeSeasonDialog from '../dialog/SubscribeSeasonDialog.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -114,14 +118,14 @@ function getMediaId() {
|
|||||||
|
|
||||||
// 角标颜色
|
// 角标颜色
|
||||||
function getChipColor(type: string) {
|
function getChipColor(type: string) {
|
||||||
if (type === '电影') return 'border-blue-500 bg-blue-600'
|
if (type === t('media.movie')) return 'border-blue-500 bg-blue-600'
|
||||||
else if (type === '电视剧') return ' bg-indigo-500 border-indigo-600'
|
else if (type === t('media.tv')) return ' bg-indigo-500 border-indigo-600'
|
||||||
else return 'border-purple-600 bg-purple-600'
|
else return 'border-purple-600 bg-purple-600'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加订阅处理
|
// 添加订阅处理
|
||||||
async function handleAddSubscribe() {
|
async function handleAddSubscribe() {
|
||||||
if (props.media?.type === '电视剧') {
|
if (props.media?.type === t('media.tv')) {
|
||||||
// 弹出季选择列表,支持多选
|
// 弹出季选择列表,支持多选
|
||||||
seasonsSelected.value = []
|
seasonsSelected.value = []
|
||||||
subscribeSeasonDialog.value = true
|
subscribeSeasonDialog.value = true
|
||||||
@@ -137,7 +141,7 @@ async function addSubscribe(season: number = 0, best_version: number = 0) {
|
|||||||
startNProgress()
|
startNProgress()
|
||||||
try {
|
try {
|
||||||
// 是否洗版
|
// 是否洗版
|
||||||
if (!best_version && props.media?.type == '电影') best_version = isExists.value ? 1 : 0
|
if (!best_version && props.media?.type == t('media.movie')) best_version = isExists.value ? 1 : 0
|
||||||
// 请求API
|
// 请求API
|
||||||
const result: { [key: string]: any } = await api.post('subscribe/', {
|
const result: { [key: string]: any } = await api.post('subscribe/', {
|
||||||
name: props.media?.title,
|
name: props.media?.title,
|
||||||
@@ -180,11 +184,11 @@ async function addSubscribe(season: number = 0, best_version: number = 0) {
|
|||||||
function showSubscribeAddToast(result: boolean, title: string, season: number, message: string, best_version: number) {
|
function showSubscribeAddToast(result: boolean, title: string, season: number, message: string, best_version: number) {
|
||||||
if (season) title = `${title} ${formatSeason(season.toString())}`
|
if (season) title = `${title} ${formatSeason(season.toString())}`
|
||||||
|
|
||||||
let subname = '订阅'
|
let subname = t('subscribe.normalSub')
|
||||||
if (best_version > 0) subname = '洗版订阅'
|
if (best_version > 0) subname = t('subscribe.versionSub')
|
||||||
|
|
||||||
if (result) $toast.success(`${title} 添加${subname}成功!`)
|
if (result) $toast.success(`${title} ${t('subscribe.addSuccess', { name: subname })}`)
|
||||||
else if (!result) $toast.error(`${title} 添加${subname}失败:${message}!`)
|
else if (!result) $toast.error(`${title} ${t('subscribe.addFailed', { name: subname, message: message })}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用API取消订阅
|
// 调用API取消订阅
|
||||||
@@ -202,9 +206,9 @@ async function removeSubscribe() {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
isSubscribed.value = false
|
isSubscribed.value = false
|
||||||
$toast.success(`${props.media?.title} 已取消订阅!`)
|
$toast.success(`${props.media?.title} ${t('subscribe.cancelSuccess')}`)
|
||||||
} else {
|
} else {
|
||||||
$toast.error(`${props.media?.title} 取消订阅失败:${result.message}!`)
|
$toast.error(`${props.media?.title} ${t('subscribe.cancelFailed', { message: result.message })}`)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
@@ -275,7 +279,7 @@ async function queryDefaultSubscribeConfig() {
|
|||||||
if (!userStore.superUser) return false
|
if (!userStore.superUser) return false
|
||||||
try {
|
try {
|
||||||
let subscribe_config_url = ''
|
let subscribe_config_url = ''
|
||||||
if (props.media?.type === '电影') subscribe_config_url = 'system/setting/DefaultMovieSubscribeConfig'
|
if (props.media?.type === t('media.movie')) subscribe_config_url = 'system/setting/DefaultMovieSubscribeConfig'
|
||||||
else subscribe_config_url = 'system/setting/DefaultTvSubscribeConfig'
|
else subscribe_config_url = 'system/setting/DefaultTvSubscribeConfig'
|
||||||
const result: { [key: string]: any } = await api.get(subscribe_config_url)
|
const result: { [key: string]: any } = await api.get(subscribe_config_url)
|
||||||
if (result.data?.value) return result.data.value.show_edit_dialog
|
if (result.data?.value) return result.data.value.show_edit_dialog
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ export default {
|
|||||||
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',
|
||||||
|
noContent: 'No content found',
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
light: 'Light',
|
light: 'Light',
|
||||||
@@ -200,4 +202,31 @@ export default {
|
|||||||
tapComponentHint: 'Tap component to add to canvas',
|
tapComponentHint: 'Tap component to add to canvas',
|
||||||
dragComponentHint: 'Drag components to canvas',
|
dragComponentHint: 'Drag components to canvas',
|
||||||
},
|
},
|
||||||
|
dashboard: {
|
||||||
|
storage: 'Storage Space',
|
||||||
|
mediaStatistic: 'Media Statistics',
|
||||||
|
weeklyOverview: 'Recent Additions',
|
||||||
|
speed: 'Real-time Speed',
|
||||||
|
scheduler: 'Background Tasks',
|
||||||
|
cpu: 'CPU',
|
||||||
|
memory: 'Memory',
|
||||||
|
library: 'My Media Library',
|
||||||
|
playing: 'Continue Watching',
|
||||||
|
latest: 'Recently Added',
|
||||||
|
settings: 'Dashboard Settings',
|
||||||
|
chooseContent: 'Choose content you want to display on the page',
|
||||||
|
adaptiveHeight: 'Adaptive Component Height',
|
||||||
|
},
|
||||||
|
media: {
|
||||||
|
movie: 'Movie',
|
||||||
|
tv: 'TV Show',
|
||||||
|
},
|
||||||
|
subscribe: {
|
||||||
|
normalSub: 'Subscription',
|
||||||
|
versionSub: 'Version Upgrade',
|
||||||
|
addSuccess: '{name} added successfully!',
|
||||||
|
addFailed: 'Failed to add {name}: {message}!',
|
||||||
|
cancelSuccess: 'Subscription cancelled!',
|
||||||
|
cancelFailed: 'Failed to cancel subscription: {message}!',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ export default {
|
|||||||
openInNewWindow: '在新窗口中打开',
|
openInNewWindow: '在新窗口中打开',
|
||||||
inputMessage: '输入消息或命令',
|
inputMessage: '输入消息或命令',
|
||||||
send: '发送',
|
send: '发送',
|
||||||
|
noData: '暂无数据',
|
||||||
|
noContent: '没有找到相关内容',
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
light: '浅色',
|
light: '浅色',
|
||||||
@@ -200,4 +202,31 @@ export default {
|
|||||||
tapComponentHint: '点击组件添加到画布',
|
tapComponentHint: '点击组件添加到画布',
|
||||||
dragComponentHint: '拖动组件到画布',
|
dragComponentHint: '拖动组件到画布',
|
||||||
},
|
},
|
||||||
|
dashboard: {
|
||||||
|
storage: '存储空间',
|
||||||
|
mediaStatistic: '媒体统计',
|
||||||
|
weeklyOverview: '最近入库',
|
||||||
|
speed: '实时速率',
|
||||||
|
scheduler: '后台任务',
|
||||||
|
cpu: 'CPU',
|
||||||
|
memory: '内存',
|
||||||
|
library: '我的媒体库',
|
||||||
|
playing: '继续观看',
|
||||||
|
latest: '最近添加',
|
||||||
|
settings: '设置仪表板',
|
||||||
|
chooseContent: '选择您想在页面显示的内容',
|
||||||
|
adaptiveHeight: '自适应组件高度',
|
||||||
|
},
|
||||||
|
media: {
|
||||||
|
movie: '电影',
|
||||||
|
tv: '电视剧',
|
||||||
|
},
|
||||||
|
subscribe: {
|
||||||
|
normalSub: '订阅',
|
||||||
|
versionSub: '洗版订阅',
|
||||||
|
addSuccess: '添加{name}成功!',
|
||||||
|
addFailed: '添加{name}失败:{message}!',
|
||||||
|
cancelSuccess: '已取消订阅!',
|
||||||
|
cancelFailed: '取消订阅失败:{message}!',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-14
@@ -7,6 +7,10 @@ import { useUserStore } from '@/stores'
|
|||||||
import DashboardElement from '@/components/misc/DashboardElement.vue'
|
import DashboardElement from '@/components/misc/DashboardElement.vue'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import { useDynamicButton } from '@/composables/useDynamicButton'
|
import { useDynamicButton } from '@/composables/useDynamicButton'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// APP
|
// APP
|
||||||
const display = useDisplay()
|
const display = useDisplay()
|
||||||
@@ -53,7 +57,7 @@ const orderConfig = ref<{ id: string; key: string }[]>([])
|
|||||||
const dashboardConfigs = ref<DashboardItem[]>([
|
const dashboardConfigs = ref<DashboardItem[]>([
|
||||||
{
|
{
|
||||||
id: 'storage',
|
id: 'storage',
|
||||||
name: '存储空间',
|
name: t('dashboard.storage'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12, md: 4 },
|
cols: { cols: 12, md: 4 },
|
||||||
@@ -61,7 +65,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'mediaStatistic',
|
id: 'mediaStatistic',
|
||||||
name: '媒体统计',
|
name: t('dashboard.mediaStatistic'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12, md: 8 },
|
cols: { cols: 12, md: 8 },
|
||||||
@@ -69,7 +73,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'weeklyOverview',
|
id: 'weeklyOverview',
|
||||||
name: '最近入库',
|
name: t('dashboard.weeklyOverview'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12, md: 4 },
|
cols: { cols: 12, md: 4 },
|
||||||
@@ -77,7 +81,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'speed',
|
id: 'speed',
|
||||||
name: '实时速率',
|
name: t('dashboard.speed'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12, md: 4 },
|
cols: { cols: 12, md: 4 },
|
||||||
@@ -85,7 +89,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'scheduler',
|
id: 'scheduler',
|
||||||
name: '后台任务',
|
name: t('dashboard.scheduler'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12, md: 4 },
|
cols: { cols: 12, md: 4 },
|
||||||
@@ -93,7 +97,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'cpu',
|
id: 'cpu',
|
||||||
name: 'CPU',
|
name: t('dashboard.cpu'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12, md: 6 },
|
cols: { cols: 12, md: 6 },
|
||||||
@@ -101,7 +105,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'memory',
|
id: 'memory',
|
||||||
name: '内存',
|
name: t('dashboard.memory'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12, md: 6 },
|
cols: { cols: 12, md: 6 },
|
||||||
@@ -109,7 +113,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'library',
|
id: 'library',
|
||||||
name: '我的媒体库',
|
name: t('dashboard.library'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12 },
|
cols: { cols: 12 },
|
||||||
@@ -117,7 +121,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'playing',
|
id: 'playing',
|
||||||
name: '继续观看',
|
name: t('dashboard.playing'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12 },
|
cols: { cols: 12 },
|
||||||
@@ -125,7 +129,7 @@ const dashboardConfigs = ref<DashboardItem[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'latest',
|
id: 'latest',
|
||||||
name: '最近添加',
|
name: t('dashboard.latest'),
|
||||||
key: '',
|
key: '',
|
||||||
attrs: {},
|
attrs: {},
|
||||||
cols: { cols: 12 },
|
cols: { cols: 12 },
|
||||||
@@ -354,13 +358,13 @@ onDeactivated(() => {
|
|||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VCardTitle>
|
<VCardTitle>
|
||||||
<VIcon icon="mdi-tune" size="small" class="me-2" />
|
<VIcon icon="mdi-tune" size="small" class="me-2" />
|
||||||
设置仪表板
|
{{ t('dashboard.settings') }}
|
||||||
</VCardTitle>
|
</VCardTitle>
|
||||||
<VDialogCloseBtn @click="dialog = false" />
|
<VDialogCloseBtn @click="dialog = false" />
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
<VDivider />
|
||||||
<VCardText>
|
<VCardText>
|
||||||
<p class="settings-hint">选择您想在页面显示的内容</p>
|
<p class="settings-hint">{{ t('dashboard.chooseContent') }}</p>
|
||||||
<div class="settings-grid">
|
<div class="settings-grid">
|
||||||
<div
|
<div
|
||||||
v-for="item in dashboardConfigs"
|
v-for="item in dashboardConfigs"
|
||||||
@@ -389,7 +393,7 @@ onDeactivated(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-3">
|
<p class="mt-3">
|
||||||
<VSwitch v-model="isElevated" label="自适应组件高度" />
|
<VSwitch v-model="isElevated" :label="t('dashboard.adaptiveHeight')" />
|
||||||
</p>
|
</p>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
<VDivider />
|
<VDivider />
|
||||||
@@ -399,7 +403,7 @@ onDeactivated(() => {
|
|||||||
<template #prepend>
|
<template #prepend>
|
||||||
<VIcon icon="mdi-content-save" />
|
<VIcon icon="mdi-content-save" />
|
||||||
</template>
|
</template>
|
||||||
保存
|
{{ t('common.save') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|||||||
Reference in New Issue
Block a user