mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-27 19:29:52 +08:00
更新国际化支持:为媒体服务器卡片和相关组件添加多语言文本,提升用户体验
This commit is contained in:
@@ -7,6 +7,10 @@ import plex_image from '@images/logos/plex.png'
|
||||
import trimemedia_image from '@images/logos/trimemedia.png'
|
||||
import api from '@/api'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 获取i18n实例
|
||||
const { t } = useI18n()
|
||||
|
||||
// 定义输入
|
||||
const props = defineProps({
|
||||
@@ -32,17 +36,17 @@ const emit = defineEmits(['close', 'done', 'change'])
|
||||
const infoItems = ref([
|
||||
{
|
||||
avatar: 'mdi-movie-roll',
|
||||
title: '电影',
|
||||
title: t('mediaType.movie'),
|
||||
amount: '0',
|
||||
},
|
||||
{
|
||||
avatar: 'mdi-television-box',
|
||||
title: '电视剧',
|
||||
title: t('mediaType.tv'),
|
||||
amount: '0',
|
||||
},
|
||||
{
|
||||
avatar: 'mdi-account',
|
||||
title: '用户',
|
||||
title: t('common.user'),
|
||||
amount: '0',
|
||||
},
|
||||
])
|
||||
@@ -50,7 +54,7 @@ const infoItems = ref([
|
||||
// 同步媒体库选项
|
||||
const librariesOptions = ref<{ title: string; value: string | undefined }[]>([
|
||||
{
|
||||
title: '全部',
|
||||
title: t('common.all'),
|
||||
value: 'all',
|
||||
},
|
||||
])
|
||||
@@ -81,12 +85,12 @@ function openMediaServerInfoDialog() {
|
||||
function saveMediaServerInfo() {
|
||||
// 为空不保存,跳出警告框
|
||||
if (!mediaServerInfo.value.name) {
|
||||
$toast.error('名称不能为空,请输入后再确定')
|
||||
$toast.error(t('common.nameRequired'))
|
||||
return
|
||||
}
|
||||
// 重名判断
|
||||
if (props.mediaservers.some(item => item.name === mediaServerInfo.value.name && item !== props.mediaserver)) {
|
||||
$toast.error(`【${mediaServerInfo.value.name}】已存在,请替换为其他名称`)
|
||||
$toast.error(t('common.nameExists', { name: mediaServerInfo.value.name }))
|
||||
return
|
||||
}
|
||||
// 执行保存
|
||||
@@ -127,17 +131,17 @@ async function loadMediaStatistic() {
|
||||
infoItems.value = [
|
||||
{
|
||||
avatar: 'mdi-movie-roll',
|
||||
title: '电影',
|
||||
title: t('mediaType.movie'),
|
||||
amount: res.movie_count.toLocaleString(),
|
||||
},
|
||||
{
|
||||
avatar: 'mdi-television-box',
|
||||
title: '电视剧',
|
||||
title: t('mediaType.tv'),
|
||||
amount: res.tv_count.toLocaleString(),
|
||||
},
|
||||
{
|
||||
avatar: 'mdi-account',
|
||||
title: '用户',
|
||||
title: t('common.user'),
|
||||
amount: res.user_count.toLocaleString(),
|
||||
},
|
||||
]
|
||||
@@ -160,7 +164,7 @@ async function loadLibrary(server: string) {
|
||||
librariesOptions.value = []
|
||||
}
|
||||
librariesOptions.value.unshift({
|
||||
title: '全部',
|
||||
title: t('common.all'),
|
||||
value: 'all',
|
||||
})
|
||||
} catch (e) {
|
||||
@@ -189,23 +193,23 @@ onMounted(() => {
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<VDialog v-if="mediaServerInfoDialog" v-model="mediaServerInfoDialog" scrollable max-width="40rem" persistent>
|
||||
<VCard :title="`${props.mediaserver.name} - 配置`" class="rounded-t">
|
||||
<VCard :title="`${props.mediaserver.name} - ${t('common.config')}`" class="rounded-t">
|
||||
<VDialogCloseBtn v-model="mediaServerInfoDialog" />
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<VForm>
|
||||
<VRow>
|
||||
<VCol cols="12" md="6">
|
||||
<VSwitch v-model="mediaServerInfo.enabled" label="启用媒体服务器" />
|
||||
<VSwitch v-model="mediaServerInfo.enabled" :label="t('mediaserver.enableMediaServer')" />
|
||||
</VCol>
|
||||
</VRow>
|
||||
<VRow v-if="mediaServerInfo.type == 'emby'">
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.name"
|
||||
label="名称"
|
||||
placeholder="必填;不可与其他名称重名"
|
||||
hint="媒体服务器的别名"
|
||||
:label="t('common.name')"
|
||||
:placeholder="t('mediaserver.nameRequired')"
|
||||
:hint="t('mediaserver.serverAlias')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -213,9 +217,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.host"
|
||||
label="地址"
|
||||
placeholder="http(s)://ip:port"
|
||||
hint="服务端地址,格式:http(s)://ip:port"
|
||||
:label="t('mediaserver.host')"
|
||||
:placeholder="t('mediaserver.hostPlaceholder')"
|
||||
:hint="t('mediaserver.hostHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -223,9 +227,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.play_host"
|
||||
label="外网播放地址"
|
||||
placeholder="http(s)://domain:port"
|
||||
hint="跳转播放页面使用的地址,格式:http(s)://domain:port"
|
||||
:label="t('mediaserver.playHost')"
|
||||
:placeholder="t('mediaserver.playHostPlaceholder')"
|
||||
:hint="t('mediaserver.playHostHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -233,8 +237,8 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.apikey"
|
||||
label="API密钥"
|
||||
hint="Emby设置->高级->API密钥中生成的密钥"
|
||||
:label="t('mediaserver.apiKey')"
|
||||
:hint="t('mediaserver.embyApiKeyHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -244,9 +248,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.name"
|
||||
label="名称"
|
||||
placeholder="必填;不可与其他名称重名"
|
||||
hint="媒体服务器的别名"
|
||||
:label="t('common.name')"
|
||||
:placeholder="t('mediaserver.nameRequired')"
|
||||
:hint="t('mediaserver.serverAlias')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -254,9 +258,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.host"
|
||||
label="地址"
|
||||
placeholder="http(s)://ip:port"
|
||||
hint="服务端地址,格式:http(s)://ip:port"
|
||||
:label="t('mediaserver.host')"
|
||||
:placeholder="t('mediaserver.hostPlaceholder')"
|
||||
:hint="t('mediaserver.hostHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -264,9 +268,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.play_host"
|
||||
label="外网播放地址"
|
||||
placeholder="http(s)://domain:port"
|
||||
hint="跳转播放页面使用的地址,格式:http(s)://domain:port"
|
||||
:label="t('mediaserver.playHost')"
|
||||
:placeholder="t('mediaserver.playHostPlaceholder')"
|
||||
:hint="t('mediaserver.playHostHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -274,8 +278,8 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.apikey"
|
||||
label="API密钥"
|
||||
hint="Jellyfin设置->高级->API密钥中生成的密钥"
|
||||
:label="t('mediaserver.apiKey')"
|
||||
:hint="t('mediaserver.jellyfinApiKeyHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -285,9 +289,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.name"
|
||||
label="名称"
|
||||
placeholder="必填;不可与其他名称重名"
|
||||
hint="媒体服务器的别名"
|
||||
:label="t('common.name')"
|
||||
:placeholder="t('mediaserver.nameRequired')"
|
||||
:hint="t('mediaserver.serverAlias')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -295,9 +299,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.host"
|
||||
label="地址"
|
||||
placeholder="http(s)://ip:port"
|
||||
hint="服务端地址,格式:http(s)://ip:port"
|
||||
:label="t('mediaserver.host')"
|
||||
:placeholder="t('mediaserver.hostPlaceholder')"
|
||||
:hint="t('mediaserver.hostHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -305,27 +309,32 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.play_host"
|
||||
label="外网播放地址"
|
||||
placeholder="http(s)://domain:port"
|
||||
hint="跳转播放页面使用的地址,格式:http(s)://domain:port"
|
||||
:label="t('mediaserver.playHost')"
|
||||
:placeholder="t('mediaserver.playHostPlaceholder')"
|
||||
:hint="t('mediaserver.playHostHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="mediaServerInfo.config.username" label="用户名" active />
|
||||
<VTextField v-model="mediaServerInfo.config.username" :label="t('mediaserver.username')" active />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField type="password" v-model="mediaServerInfo.config.password" label="密码" active />
|
||||
<VTextField
|
||||
type="password"
|
||||
v-model="mediaServerInfo.config.password"
|
||||
:label="t('mediaserver.password')"
|
||||
active
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
<VRow v-if="mediaServerInfo.type == 'plex'">
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.name"
|
||||
label="名称"
|
||||
placeholder="必填;不可与其他名称重名"
|
||||
hint="媒体服务器的别名"
|
||||
:label="t('common.name')"
|
||||
:placeholder="t('mediaserver.nameRequired')"
|
||||
:hint="t('mediaserver.serverAlias')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -333,9 +342,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.host"
|
||||
label="地址"
|
||||
placeholder="http(s)://ip:port"
|
||||
hint="服务端地址,格式:http(s)://ip:port"
|
||||
:label="t('mediaserver.host')"
|
||||
:placeholder="t('mediaserver.hostPlaceholder')"
|
||||
:hint="t('mediaserver.hostHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -343,9 +352,9 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.play_host"
|
||||
label="外网播放地址"
|
||||
placeholder="http(s)://domain:port"
|
||||
hint="跳转播放页面使用的地址,格式:http(s)://domain:port"
|
||||
:label="t('mediaserver.playHost')"
|
||||
:placeholder="t('mediaserver.playHostPlaceholder')"
|
||||
:hint="t('mediaserver.playHostHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -353,8 +362,8 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="mediaServerInfo.config.token"
|
||||
label="X-Plex-Token"
|
||||
hint="浏览器F12->网络,从Plex请求URL中获取的X-Plex-Token"
|
||||
:label="t('mediaserver.plexToken')"
|
||||
:hint="t('mediaserver.plexTokenHint')"
|
||||
persistent-hint
|
||||
active
|
||||
/>
|
||||
@@ -364,12 +373,12 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VSelect
|
||||
v-model="mediaServerInfo.sync_libraries"
|
||||
label="同步媒体库"
|
||||
:label="t('mediaserver.syncLibraries')"
|
||||
:items="librariesOptions"
|
||||
chips
|
||||
multiple
|
||||
clearable
|
||||
hint="只有选中的媒体库才会被同步"
|
||||
:hint="t('mediaserver.syncLibrariesHint')"
|
||||
persistent-hint
|
||||
active
|
||||
append-inner-icon="mdi-refresh"
|
||||
@@ -381,7 +390,7 @@ onMounted(() => {
|
||||
</VCardText>
|
||||
<VCardActions class="pt-3">
|
||||
<VBtn @click="saveMediaServerInfo" variant="elevated" prepend-icon="mdi-content-save" class="px-5">
|
||||
确定
|
||||
{{ t('common.confirm') }}
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
|
||||
@@ -42,11 +42,6 @@ function handleFlow(item: Workflow) {
|
||||
flowDialog.value = true
|
||||
}
|
||||
|
||||
// 计算已完成的动作数
|
||||
function resolveDoneActions(item: Workflow) {
|
||||
return item.current_action?.split(',').length || 0
|
||||
}
|
||||
|
||||
// 编辑完成
|
||||
function editDone() {
|
||||
editDialog.value = false
|
||||
|
||||
@@ -25,6 +25,29 @@ export default {
|
||||
language: 'Language',
|
||||
pleaseWait: 'Please wait...',
|
||||
viewDetails: 'View Details',
|
||||
user: 'User',
|
||||
config: 'Configuration',
|
||||
},
|
||||
mediaserver: {
|
||||
enableMediaServer: 'Enable Media Server',
|
||||
nameRequired: 'Required; cannot be duplicated',
|
||||
serverAlias: 'Media server alias',
|
||||
host: 'Host',
|
||||
hostPlaceholder: 'http(s)://ip:port',
|
||||
hostHint: 'Server address, format: http(s)://ip:port',
|
||||
playHost: 'External Playback URL',
|
||||
playHostPlaceholder: 'http(s)://domain:port',
|
||||
playHostHint: 'URL for playback page redirection, format: http(s)://domain:port',
|
||||
apiKey: 'API Key',
|
||||
embyApiKeyHint: 'API key generated in Emby Settings -> Advanced -> API Keys',
|
||||
jellyfinApiKeyHint: 'API key generated in Jellyfin Settings -> Advanced -> API Keys',
|
||||
plexToken: 'X-Plex-Token',
|
||||
plexTokenHint: 'X-Plex-Token obtained from Plex request URL in browser F12 -> Network',
|
||||
username: 'Username',
|
||||
password: 'Password',
|
||||
syncLibraries: 'Sync Libraries',
|
||||
syncLibrariesHint: 'Only selected libraries will be synchronized',
|
||||
nameExists: '【{name}】 already exists, please use a different name',
|
||||
},
|
||||
mediaType: {
|
||||
movie: 'Movie',
|
||||
|
||||
@@ -25,6 +25,29 @@ export default {
|
||||
language: '语言',
|
||||
pleaseWait: '请稍候...',
|
||||
viewDetails: '查看详情',
|
||||
user: '用户',
|
||||
config: '配置',
|
||||
},
|
||||
mediaserver: {
|
||||
enableMediaServer: '启用媒体服务器',
|
||||
nameRequired: '必填;不可与其他名称重名',
|
||||
serverAlias: '媒体服务器的别名',
|
||||
host: '地址',
|
||||
hostPlaceholder: 'http(s)://ip:port',
|
||||
hostHint: '服务端地址,格式:http(s)://ip:port',
|
||||
playHost: '外网播放地址',
|
||||
playHostPlaceholder: 'http(s)://domain:port',
|
||||
playHostHint: '跳转播放页面使用的地址,格式:http(s)://domain:port',
|
||||
apiKey: 'API密钥',
|
||||
embyApiKeyHint: 'Emby设置->高级->API密钥中生成的密钥',
|
||||
jellyfinApiKeyHint: 'Jellyfin设置->高级->API密钥中生成的密钥',
|
||||
plexToken: 'X-Plex-Token',
|
||||
plexTokenHint: '浏览器F12->网络,从Plex请求URL中获取的X-Plex-Token',
|
||||
username: '用户名',
|
||||
password: '密码',
|
||||
syncLibraries: '同步媒体库',
|
||||
syncLibrariesHint: '只有选中的媒体库才会被同步',
|
||||
nameExists: '【{name}】已存在,请替换为其他名称',
|
||||
},
|
||||
mediaType: {
|
||||
movie: '电影',
|
||||
@@ -235,6 +258,38 @@ export default {
|
||||
dragToCanvas: '拖动到画布',
|
||||
tapComponentHint: '点击组件添加到画布',
|
||||
dragComponentHint: '拖动组件到画布',
|
||||
task: {
|
||||
edit: '编辑任务',
|
||||
continue: '继续执行',
|
||||
restart: '重新执行',
|
||||
run: '立即执行',
|
||||
reset: '重置任务',
|
||||
delete: '删除任务',
|
||||
confirmDelete: '是否确认删除任务 {name} ?',
|
||||
confirmReset: '是否确认重置任务 {name} ?',
|
||||
deleteSuccess: '删除任务成功!',
|
||||
deleteFailed: '删除任务失败:{message}',
|
||||
enableSuccess: '启用任务成功!',
|
||||
enableFailed: '启用任务失败:{message}',
|
||||
pauseSuccess: '停用任务成功!',
|
||||
pauseFailed: '停用任务失败:{message}',
|
||||
runSuccess: '任务执行完成!',
|
||||
runFailed: '任务执行失败:{message}',
|
||||
resetSuccess: '重置任务成功!',
|
||||
resetFailed: '重置任务失败:{message}',
|
||||
status: {
|
||||
success: '成功',
|
||||
running: '运行中',
|
||||
failed: '失败',
|
||||
paused: '暂停',
|
||||
waiting: '等待'
|
||||
},
|
||||
info: {
|
||||
timer: '定时',
|
||||
status: '状态',
|
||||
actionCount: '动作数',
|
||||
runCount: '已执行次数',
|
||||
progress: '进度',
|
||||
},
|
||||
dashboard: {
|
||||
storage: '存储空间',
|
||||
|
||||
@@ -25,6 +25,29 @@ export default {
|
||||
language: '語言',
|
||||
pleaseWait: '請稍候...',
|
||||
viewDetails: '查看詳情',
|
||||
user: '用戶',
|
||||
config: '配置',
|
||||
},
|
||||
mediaserver: {
|
||||
enableMediaServer: '啟用媒體伺服器',
|
||||
nameRequired: '必填;不可與其他名稱重名',
|
||||
serverAlias: '媒體伺服器的別名',
|
||||
host: '地址',
|
||||
hostPlaceholder: 'http(s)://ip:port',
|
||||
hostHint: '服務端地址,格式:http(s)://ip:port',
|
||||
playHost: '外網播放地址',
|
||||
playHostPlaceholder: 'http(s)://domain:port',
|
||||
playHostHint: '跳轉播放頁面使用的地址,格式:http(s)://domain:port',
|
||||
apiKey: 'API密鑰',
|
||||
embyApiKeyHint: 'Emby設置->高級->API密鑰中生成的密鑰',
|
||||
jellyfinApiKeyHint: 'Jellyfin設置->高級->API密鑰中生成的密鑰',
|
||||
plexToken: 'X-Plex-Token',
|
||||
plexTokenHint: '瀏覽器F12->網絡,從Plex請求URL中獲取的X-Plex-Token',
|
||||
username: '用戶名',
|
||||
password: '密碼',
|
||||
syncLibraries: '同步媒體庫',
|
||||
syncLibrariesHint: '只有選中的媒體庫才會被同步',
|
||||
nameExists: '【{name}】已存在,請替換為其他名稱',
|
||||
},
|
||||
mediaType: {
|
||||
movie: '電影',
|
||||
|
||||
Reference in New Issue
Block a user