添加国际化支持:在多个页面和组件中引入 vue-i18n

This commit is contained in:
jxxghp
2025-04-27 20:27:45 +08:00
parent 733d74ac36
commit f809c8e538
12 changed files with 300 additions and 105 deletions

View File

@@ -14,7 +14,7 @@ export default {
inputMessage: 'Enter message or command',
send: 'Send',
noData: 'No Data',
noContent: 'No content found',
noContent: 'No Content Found',
},
theme: {
light: 'Light',
@@ -22,7 +22,7 @@ export default {
auto: 'Auto',
transparent: 'Transparent',
purple: 'Purple',
custom: 'Custom',
custom: 'Custom Theme',
},
app: {
moviepilot: 'MoviePilot',
@@ -228,5 +228,83 @@ export default {
addFailed: 'Failed to add {name}: {message}!',
cancelSuccess: 'Subscription cancelled!',
cancelFailed: 'Failed to cancel subscription: {message}!',
filterSubscriptions: 'Filter Subscriptions',
name: 'Name',
searchShares: 'Search Subscription Shares',
keyword: 'Keyword',
},
recommend: {
all: 'All',
categoryMovie: 'Movies',
categoryTV: 'TV Shows',
categoryAnime: 'Anime',
categoryRankings: 'Rankings',
trendingNow: 'Trending Now',
nowShowing: 'Now Showing',
bangumiDaily: 'Bangumi Daily',
tmdbHotMovies: 'TMDB Hot Movies',
tmdbHotTVShows: 'TMDB Hot TV Shows',
doubanHotMovies: 'Douban Hot Movies',
doubanHotTVShows: 'Douban Hot TV Shows',
doubanHotAnime: 'Douban Hot Anime',
doubanNewMovies: 'Douban New Movies',
doubanNewTVShows: 'Douban New TV Shows',
doubanTop250: 'Douban Movie TOP250',
doubanChineseTVRankings: 'Douban Chinese TV Rankings',
doubanGlobalTVRankings: 'Douban Global TV Rankings',
noCategoryContent: 'No content to display in this category',
configureContent: 'Configure Content',
customizeContent: 'Customize Content',
selectContentToDisplay: 'Select the content you want to display',
selectAll: 'Select All',
selectNone: 'Select None',
},
discover: {
setTabOrder: 'Set Tab Order',
dragToReorder: 'Drag to reorder tabs',
},
downloading: {
noDownloader: 'No Downloaders',
configureDownloader: 'Please configure and enable downloaders in settings first.',
},
resource: {
searchResults: 'Resource Search Results',
keyword: 'Keyword',
title: 'Title',
year: 'Year',
season: 'Season',
switchingView: 'Switching View',
backToHome: 'Back to Home',
searching: 'Searching, please wait...',
noData: 'No Data',
noResourceFound: 'No resources found',
},
browse: {
actor: 'Actor',
},
appcenter: {
others: 'Others',
},
notFound: {
title: 'Page Not Found ⚠️',
description: 'The page you are trying to access does not exist. Please check the URL.',
backButton: 'Back',
},
torrent: {
sortDefault: 'Default',
sortSite: 'Site',
sortSize: 'Size',
sortSeeder: 'Seeders',
filterSite: 'Site',
filterSeason: 'Season',
filterFreeState: 'Promotion',
filterVideoCode: 'Video Code',
filterEdition: 'Quality',
filterResolution: 'Resolution',
filterReleaseGroup: 'Release Group',
clearFilters: 'Clear',
selectAll: 'Select All',
loadMore: 'Load More',
noMatchingResults: 'No matching results',
},
}

View File

@@ -228,5 +228,83 @@ export default {
addFailed: '添加{name}失败:{message}',
cancelSuccess: '已取消订阅!',
cancelFailed: '取消订阅失败:{message}',
filterSubscriptions: '筛选订阅',
name: '名称',
searchShares: '搜索订阅分享',
keyword: '关键词',
},
recommend: {
all: '全部',
categoryMovie: '电影',
categoryTV: '电视剧',
categoryAnime: '动漫',
categoryRankings: '榜单',
trendingNow: '流行趋势',
nowShowing: '正在热映',
bangumiDaily: 'Bangumi每日放送',
tmdbHotMovies: 'TMDB热门电影',
tmdbHotTVShows: 'TMDB热门电视剧',
doubanHotMovies: '豆瓣热门电影',
doubanHotTVShows: '豆瓣热门电视剧',
doubanHotAnime: '豆瓣热门动漫',
doubanNewMovies: '豆瓣最新电影',
doubanNewTVShows: '豆瓣最新电视剧',
doubanTop250: '豆瓣电影TOP250',
doubanChineseTVRankings: '豆瓣国产剧集榜',
doubanGlobalTVRankings: '豆瓣全球剧集榜',
noCategoryContent: '当前分类下没有可显示的内容',
configureContent: '设置显示内容',
customizeContent: '自定义内容',
selectContentToDisplay: '选择您想在页面显示的内容',
selectAll: '全选',
selectNone: '全不选',
},
discover: {
setTabOrder: '设置标签顺序',
dragToReorder: '拖动对标签页进行排序',
},
downloading: {
noDownloader: '没有下载器',
configureDownloader: '请先在设置中正确配置并启用下载器。',
},
resource: {
searchResults: '资源搜索结果',
keyword: '关键词',
title: '标题',
year: '年份',
season: '季',
switchingView: '切换视图',
backToHome: '返回首页',
searching: '正在搜索,请稍候...',
noData: '没有数据',
noResourceFound: '未搜索到任何资源',
},
browse: {
actor: '演员',
},
appcenter: {
others: '其他',
},
notFound: {
title: '页面不存在 ⚠️',
description: '您想要访问的页面不存在,请检查地址是否正确。',
backButton: '返回',
},
torrent: {
sortDefault: '默认',
sortSite: '站点',
sortSize: '大小',
sortSeeder: '做种数',
filterSite: '站点',
filterSeason: '季集',
filterFreeState: '促销状态',
filterVideoCode: '视频编码',
filterEdition: '质量',
filterResolution: '分辨率',
filterReleaseGroup: '制作组',
clearFilters: '清除',
selectAll: '全选',
loadMore: '加载更多',
noMatchingResults: '没有匹配的结果',
},
}

View File

@@ -1,19 +1,16 @@
<script setup lang="ts">
import NoDataFound from '@/components/NoDataFound.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
</script>
<template>
<NoDataFound
error-code="404"
error-title="页面不存在 "
error-description="您想要访问的页面不存在请检查地址是否正确"
>
<NoDataFound error-code="404" :error-title="t('notFound.title')" :error-description="t('notFound.description')">
<template #button>
<VBtn
to="/"
class="mt-10"
>
返回
<VBtn to="/" class="mt-10">
{{ t('notFound.backButton') }}
</VBtn>
</template>
</NoDataFound>

View File

@@ -2,6 +2,10 @@
import { NavMenu } from '@/@layouts/types'
import { getNavMenus } from '@/router/i18n-menu'
import { useUserStore } from '@/stores'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 从 Store 中获取superuser信息
const superUser = useUserStore().superUser
@@ -18,7 +22,7 @@ function categorizeApps() {
const groupedMenus: Record<string, NavMenu[]> = {}
menus.forEach(menu => {
const header = menu.header || '其他'
const header = menu.header || t('appcenter.others')
if (!groupedMenus[header]) {
groupedMenus[header] = []
}

View File

@@ -1,6 +1,10 @@
<script setup lang="ts">
import MediaCardListView from '@/views/discover/MediaCardListView.vue'
import PersonCardListView from '@/views/discover/PersonCardListView.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 输入参数
const props = defineProps({
@@ -16,7 +20,7 @@ let title = route.query?.title?.toString()
// 类型
const type = route.query?.type?.toString()
if (type === 'person') title = '演员:' + title
if (type === 'person') title = t('browse.actor') + ': ' + title
// 计算API路径
function getApiPath(paths: string[] | string) {

View File

@@ -7,6 +7,10 @@ import BangumiView from '@/views/discover/BangumiView.vue'
import ExtraSourceView from '@/views/discover/ExtraSourceView.vue'
import { DiscoverSource } from '@/api/types'
import api from '@/api'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
const activeTab = ref('')
@@ -180,13 +184,13 @@ onActivated(async () => {
<VCardItem>
<VCardTitle>
<VIcon icon="mdi-order-alphabetical-ascending" size="small" class="me-2" />
设置标签顺序
{{ t('discover.setTabOrder') }}
</VCardTitle>
<VDialogCloseBtn @click="orderConfigDialog = false" />
</VCardItem>
<VDivider />
<VCardText>
<p class="settings-hint">拖动对标签页进行排序</p>
<p class="settings-hint">{{ t('discover.dragToReorder') }}</p>
<draggable
v-model="discoverTabs"
handle=".cursor-move"
@@ -210,7 +214,7 @@ onActivated(async () => {
<template #prepend>
<VIcon icon="mdi-content-save" />
</template>
保存
{{ t('common.save') }}
</VBtn>
</VCardText>
</VCard>

View File

@@ -3,6 +3,10 @@ import api from '@/api'
import { DownloaderConf } from '@/api/types'
import DownloadingListView from '@/views/reorganize/DownloadingListView.vue'
import NoDataFound from '@/components/NoDataFound.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
const route = useRoute()
const activeTab = ref(route.query.tab)
@@ -54,7 +58,7 @@ onActivated(async () => {
<NoDataFound
v-else
error-code="404"
error-title="没有下载器"
error-description="请先在设置中正确配置并启用下载器"
:error-title="t('downloading.noDownloader')"
:error-description="t('downloading.configureDownloader')"
/>
</template>

View File

@@ -2,94 +2,98 @@
import api from '@/api'
import { RecommendSource } from '@/api/types'
import MediaCardSlideView from '@/views/discover/MediaCardSlideView.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 当前选择的分类
const currentCategory = ref('全部')
const currentCategory = ref(t('recommend.all'))
const viewList = reactive<{ apipath: string; linkurl: string; title: string; type: string }[]>([
{
apipath: 'recommend/tmdb_trending',
linkurl: '/browse/recommend/tmdb_trending?title=流行趋势',
title: '流行趋势',
type: '榜单',
linkurl: '/browse/recommend/tmdb_trending?title=' + t('recommend.trendingNow'),
title: t('recommend.trendingNow'),
type: t('recommend.categoryRankings'),
},
{
apipath: 'recommend/douban_showing',
linkurl: '/browse/recommend/douban_showing?title=正在热映',
title: '正在热映',
type: '电影',
linkurl: '/browse/recommend/douban_showing?title=' + t('recommend.nowShowing'),
title: t('recommend.nowShowing'),
type: t('recommend.categoryMovie'),
},
{
apipath: 'recommend/bangumi_calendar',
linkurl: '/browse/recommend/bangumi_calendar?title=Bangumi每日放送',
title: 'Bangumi每日放送',
type: '动漫',
linkurl: '/browse/recommend/bangumi_calendar?title=' + t('recommend.bangumiDaily'),
title: t('recommend.bangumiDaily'),
type: t('recommend.categoryAnime'),
},
{
apipath: 'recommend/tmdb_movies',
linkurl: '/browse/recommend/tmdb_movies?title=TMDB热门电影',
title: 'TMDB热门电影',
type: '电影',
linkurl: '/browse/recommend/tmdb_movies?title=' + t('recommend.tmdbHotMovies'),
title: t('recommend.tmdbHotMovies'),
type: t('recommend.categoryMovie'),
},
{
apipath: 'recommend/tmdb_tvs?with_original_language=zh|en|ja|ko',
linkurl: '/browse/recommend/tmdb_tvs??with_original_language=zh|en|ja|ko&title=TMDB热门电视剧',
title: 'TMDB热门电视剧',
type: '电视剧',
linkurl: '/browse/recommend/tmdb_tvs??with_original_language=zh|en|ja|ko&title=' + t('recommend.tmdbHotTVShows'),
title: t('recommend.tmdbHotTVShows'),
type: t('recommend.categoryTV'),
},
{
apipath: 'recommend/douban_movie_hot',
linkurl: '/browse/recommend/douban_movie_hot?title=豆瓣热门电影',
title: '豆瓣热门电影',
type: '电影',
linkurl: '/browse/recommend/douban_movie_hot?title=' + t('recommend.doubanHotMovies'),
title: t('recommend.doubanHotMovies'),
type: t('recommend.categoryMovie'),
},
{
apipath: 'recommend/douban_tv_hot',
linkurl: '/browse/recommend/douban_tv_hot?title=豆瓣热门电视剧',
title: '豆瓣热门电视剧',
type: '电视剧',
linkurl: '/browse/recommend/douban_tv_hot?title=' + t('recommend.doubanHotTVShows'),
title: t('recommend.doubanHotTVShows'),
type: t('recommend.categoryTV'),
},
{
apipath: 'recommend/douban_tv_animation',
linkurl: '/browse/recommend/douban_tv_animation?title=豆瓣热门动漫',
title: '豆瓣热门动漫',
type: '动漫',
linkurl: '/browse/recommend/douban_tv_animation?title=' + t('recommend.doubanHotAnime'),
title: t('recommend.doubanHotAnime'),
type: t('recommend.categoryAnime'),
},
{
apipath: 'recommend/douban_movies',
linkurl: '/browse/recommend/douban_movies?title=豆瓣最新电影',
title: '豆瓣最新电影',
type: '电影',
linkurl: '/browse/recommend/douban_movies?title=' + t('recommend.doubanNewMovies'),
title: t('recommend.doubanNewMovies'),
type: t('recommend.categoryMovie'),
},
{
apipath: 'recommend/douban_tvs',
linkurl: '/browse/recommend/douban_tvs?title=豆瓣最新电视剧',
title: '豆瓣最新电视剧',
type: '电视剧',
linkurl: '/browse/recommend/douban_tvs?title=' + t('recommend.doubanNewTVShows'),
title: t('recommend.doubanNewTVShows'),
type: t('recommend.categoryTV'),
},
{
apipath: 'recommend/douban_movie_top250',
linkurl: '/browse/recommend/douban_movie_top250?title=电影TOP250',
title: '豆瓣电影TOP250',
type: '榜单',
linkurl: '/browse/recommend/douban_movie_top250?title=' + t('recommend.doubanTop250'),
title: t('recommend.doubanTop250'),
type: t('recommend.categoryRankings'),
},
{
apipath: 'recommend/douban_tv_weekly_chinese',
linkurl: '/browse/recommend/douban_tv_weekly_chinese?title=豆瓣国产剧集榜',
title: '豆瓣国产剧集榜',
type: '榜单',
linkurl: '/browse/recommend/douban_tv_weekly_chinese?title=' + t('recommend.doubanChineseTVRankings'),
title: t('recommend.doubanChineseTVRankings'),
type: t('recommend.categoryRankings'),
},
{
apipath: 'recommend/douban_tv_weekly_global',
linkurl: '/browse/recommend/douban_tv_weekly_global?title=豆瓣全球剧集榜',
title: '豆瓣全球剧集榜',
type: '榜单',
linkurl: '/browse/recommend/douban_tv_weekly_global?title=' + t('recommend.doubanGlobalTVRankings'),
title: t('recommend.doubanGlobalTVRankings'),
type: t('recommend.categoryRankings'),
},
])
// 计算当前分类下显示的视图
const filteredViews = computed(() => {
if (currentCategory.value === '全部') {
if (currentCategory.value === t('recommend.all')) {
return viewList.filter(item => enableConfig.value[item.title])
}
return viewList.filter(item => enableConfig.value[item.title] && item.type === currentCategory.value)
@@ -158,29 +162,29 @@ async function saveConfig() {
// 标签图标映射
const categoryItems: Record<string, string>[] = [
{
title: '全部',
title: t('recommend.all'),
icon: 'mdi-filmstrip-box-multiple',
tab: '全部',
tab: t('recommend.all'),
},
{
title: '电影',
title: t('recommend.categoryMovie'),
icon: 'mdi-movie',
tab: '电影',
tab: t('recommend.categoryMovie'),
},
{
title: '电视剧',
title: t('recommend.categoryTV'),
icon: 'mdi-television-classic',
tab: '电视剧',
tab: t('recommend.categoryTV'),
},
{
title: '动漫',
title: t('recommend.categoryAnime'),
icon: 'mdi-animation',
tab: '动漫',
tab: t('recommend.categoryAnime'),
},
{
title: '榜单',
title: t('recommend.categoryRankings'),
icon: 'mdi-trophy',
tab: '榜单',
tab: t('recommend.categoryRankings'),
},
]
@@ -221,8 +225,10 @@ onActivated(async () => {
<div v-if="filteredViews.length === 0" class="empty-category">
<VIcon icon="mdi-alert-circle-outline" size="large" class="empty-icon" />
<p class="empty-text">当前分类下没有可显示的内容</p>
<VBtn color="primary" variant="tonal" size="small" @click="dialog = true"> 设置显示内容 </VBtn>
<p class="empty-text">{{ t('recommend.noCategoryContent') }}</p>
<VBtn color="primary" variant="tonal" size="small" @click="dialog = true">
{{ t('recommend.configureContent') }}
</VBtn>
</div>
</div>
@@ -232,13 +238,13 @@ onActivated(async () => {
<VCardItem class="settings-card-header">
<VCardTitle>
<VIcon icon="mdi-tune" size="small" class="me-2" />
自定义内容
{{ t('recommend.customizeContent') }}
</VCardTitle>
<VDialogCloseBtn @click="dialog = false" />
</VCardItem>
<VDivider />
<VCardText>
<p class="settings-hint">选择您想在页面显示的内容</p>
<p class="settings-hint">{{ t('recommend.selectContentToDisplay') }}</p>
<div class="settings-grid">
<div
v-for="(item, index) in viewList"
@@ -266,17 +272,17 @@ onActivated(async () => {
<VDivider />
<VCardActions class="pt-5">
<VBtn variant="text" @click="Object.keys(enableConfig).forEach(key => (enableConfig[key] = true))">
全选
{{ t('recommend.selectAll') }}
</VBtn>
<VBtn variant="text" @click="Object.keys(enableConfig).forEach(key => (enableConfig[key] = false))">
全不选
{{ t('recommend.selectNone') }}
</VBtn>
<VSpacer />
<VBtn @click="saveConfig" variant="elevated" color="primary" class="px-5">
<template #prepend>
<VIcon icon="mdi-content-save" />
</template>
保存
{{ t('common.save') }}
</VBtn>
</VCardActions>
</VCard>

View File

@@ -4,6 +4,10 @@ import api from '@/api'
import type { Context } from '@/api/types'
import TorrentCardListView from '@/views/torrent/TorrentCardListView.vue'
import TorrentRowListView from '@/views/torrent/TorrentRowListView.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
// 路由参数
const route = useRoute()
@@ -51,14 +55,14 @@ const progressValue = ref(0)
const progressEventSource = ref<EventSource>()
// 错误标题
const errorTitle = ref('没有数据')
const errorTitle = ref(t('resource.noData'))
// 错误描述
const errorDescription = ref('未搜索到任何资源')
const errorDescription = ref(t('resource.noResourceFound'))
// 使用SSE监听加载进度
function startLoadingProgress() {
progressText.value = '正在搜索,请稍候...'
progressText.value = t('resource.searching')
progressValue.value = 10 // 初始进度设为10%,确保进度条显示
progressEventSource.value = new EventSource(`${import.meta.env.VITE_API_BASE_URL}system/progress/search`)
progressEventSource.value.onmessage = event => {
@@ -199,14 +203,20 @@ onUnmounted(() => {
<!-- 精简标题栏 -->
<VCard v-if="isRefreshed" class="search-header d-flex align-center mb-3">
<div class="search-info-container d-flex align-center flex-wrap">
<div class="search-title text-primary">资源搜索结果</div>
<div class="search-title text-primary">{{ t('resource.searchResults') }}</div>
<div class="search-tags d-flex flex-wrap">
<VChip v-if="keyword" class="search-tag" color="primary" size="small" variant="flat">
关键词: {{ keyword }}
{{ t('resource.keyword') }}: {{ keyword }}
</VChip>
<VChip v-if="title" class="search-tag" color="primary" size="small" variant="flat">
{{ t('resource.title') }}: {{ title }}
</VChip>
<VChip v-if="year" class="search-tag" color="primary" size="small" variant="flat">
{{ t('resource.year') }}: {{ year }}
</VChip>
<VChip v-if="season" class="search-tag" color="primary" size="small" variant="flat">
{{ t('resource.season') }}: {{ season }}
</VChip>
<VChip v-if="title" class="search-tag" color="primary" size="small" variant="flat"> 标题: {{ title }} </VChip>
<VChip v-if="year" class="search-tag" color="primary" size="small" variant="flat"> 年份: {{ year }} </VChip>
<VChip v-if="season" class="search-tag" color="primary" size="small" variant="flat"> : {{ season }} </VChip>
</div>
</div>
<VSpacer />
@@ -232,7 +242,7 @@ onUnmounted(() => {
<div class="pulse-circle"></div>
<div class="pulse-circle"></div>
</div>
<div class="view-changing-text">切换视图</div>
<div class="view-changing-text">{{ t('resource.switchingView') }}</div>
</div>
</div>
</VFadeTransition>
@@ -257,7 +267,7 @@ onUnmounted(() => {
<!-- 无数据显示 -->
<div v-else-if="isRefreshed && !isViewChanging" class="d-flex flex-column align-center justify-center py-8">
<NoDataFound :errorTitle="errorTitle" :errorDescription="errorDescription" />
<VBtn class="mt-4" color="primary" prepend-icon="mdi-magnify" to="/"> 返回首页 </VBtn>
<VBtn class="mt-4" color="primary" prepend-icon="mdi-magnify" to="/">{{ t('resource.backToHome') }}</VBtn>
</div>
<!-- 初始加载状态 -->
@@ -269,7 +279,7 @@ onUnmounted(() => {
<div class="wave-dot"></div>
<div class="wave-dot"></div>
</div>
<div class="initial-loading-text">搜索中</div>
<div class="initial-loading-text">{{ t('resource.searching') }}</div>
</div>
</div>
<!-- 滚动到顶部按钮 -->

View File

@@ -3,9 +3,13 @@ import SubscribeListView from '@/views/subscribe/SubscribeListView.vue'
import SubscribePopularView from '@/views/subscribe/SubscribePopularView.vue'
import SubscribeShareView from '@/views/subscribe/SubscribeShareView.vue'
import SubscribeEditDialog from '@/components/dialog/SubscribeEditDialog.vue'
import { useI18n } from 'vue-i18n'
import { getSubscribeMovieTabs, getSubscribeTvTabs } from '@/router/i18n-menu'
// 国际化
const { t } = useI18n()
const route = useRoute()
const subType = route.meta.subType?.toString()
@@ -69,12 +73,12 @@ const searchShares = () => {
<VCardItem>
<VCardTitle>
<VIcon icon="mdi-filter-multiple-outline" class="mr-2" />
筛选订阅
{{ t('subscribe.filterSubscriptions') }}
</VCardTitle>
<VDialogCloseBtn @click="filterSubscribeDialog = false" />
</VCardItem>
<VCardText>
<VTextField v-model="subscribeFilter" label="名称" clearable density="comfortable" />
<VTextField v-model="subscribeFilter" :label="t('subscribe.name')" clearable density="comfortable" />
</VCardText>
</VCard>
</VMenu>
@@ -99,14 +103,14 @@ const searchShares = () => {
<VCardItem>
<VCardTitle>
<VIcon icon="mdi-movie-search-outline" class="mr-2" />
搜索订阅分享
{{ t('subscribe.searchShares') }}
</VCardTitle>
<VDialogCloseBtn @click="searchShareDialog = false" />
</VCardItem>
<VCardText>
<VTextField v-model="shareKeyword" label="关键词" clearable density="comfortable">
<VTextField v-model="shareKeyword" :label="t('subscribe.keyword')" clearable density="comfortable">
<template #append>
<VBtn prepend-icon="mdi-magnify" color="primary" @click="searchShares">搜索</VBtn>
<VBtn prepend-icon="mdi-magnify" color="primary" @click="searchShares">{{ t('common.search') }}</VBtn>
</template>
</VTextField>
</VCardText>

View File

@@ -2,6 +2,10 @@
import { cloneDeepWith } from 'lodash-es'
import type { Context } from '@/api/types'
import TorrentCard from '@/components/cards/TorrentCard.vue'
import { useI18n } from 'vue-i18n'
// 国际化
const { t } = useI18n()
interface SearchTorrent extends Context {
more?: Array<Context>
@@ -34,21 +38,21 @@ const filterForm: Record<string, string[]> = reactive({
// 排序选项
const sortField = ref('default')
const sortTitles: Record<string, string> = {
default: '默认',
site: '站点',
size: '大小',
seeder: '做种数',
default: t('torrent.sortDefault'),
site: t('torrent.sortSite'),
size: t('torrent.sortSize'),
seeder: t('torrent.sortSeeder'),
}
// 过滤项映射(保持中文标题)
// 过滤项映射
const filterTitles: Record<string, string> = {
site: '站点',
season: '季集',
freeState: '促销状态',
videoCode: '视频编码',
edition: '质量',
resolution: '分辨率',
releaseGroup: '制作组',
site: t('torrent.filterSite'),
season: t('torrent.filterSeason'),
freeState: t('torrent.filterFreeState'),
videoCode: t('torrent.filterVideoCode'),
edition: t('torrent.filterEdition'),
resolution: t('torrent.filterResolution'),
releaseGroup: t('torrent.filterReleaseGroup'),
}
// 统一存储过滤选项