更新国际化支持:为Bangumi和TMDB相关组件添加多语言文本,提升用户体验

This commit is contained in:
jxxghp
2025-04-29 08:25:20 +08:00
parent 2ae843fb3e
commit ce90ed84f6
7 changed files with 324 additions and 81 deletions

View File

@@ -2057,4 +2057,81 @@ export default {
syncLibrariesHint: 'Only selected libraries will be synchronized', syncLibrariesHint: 'Only selected libraries will be synchronized',
nameExists: '【{name}】 already exists, please use a different name', nameExists: '【{name}】 already exists, please use a different name',
}, },
bangumi: {
category: 'Category',
sort: 'Sort',
year: 'Year',
cat: {
other: 'Other',
tv: 'TV',
ova: 'OVA',
movie: 'Movie',
web: 'WEB',
},
sortType: {
rank: 'Rank',
date: 'Date',
},
},
tmdb: {
type: 'Type',
sort: 'Sort',
genre: 'Genre',
language: 'Language',
rating: 'Rating',
sortType: {
popularityDesc: 'Popularity Descending',
popularityAsc: 'Popularity Ascending',
releaseDateDesc: 'Release Date Descending',
releaseDateAsc: 'Release Date Ascending',
firstAirDateDesc: 'First Air Date Descending',
firstAirDateAsc: 'First Air Date Ascending',
voteAverageDesc: 'Vote Average Descending',
voteAverageAsc: 'Vote Average Ascending',
},
genreType: {
action: 'Action',
adventure: 'Adventure',
animation: 'Animation',
comedy: 'Comedy',
crime: 'Crime',
documentary: 'Documentary',
drama: 'Drama',
family: 'Family',
fantasy: 'Fantasy',
history: 'History',
horror: 'Horror',
music: 'Music',
mystery: 'Mystery',
romance: 'Romance',
scienceFiction: 'Science Fiction',
tvMovie: 'TV Movie',
thriller: 'Thriller',
war: 'War',
western: 'Western',
actionAdventure: 'Action & Adventure',
kids: 'Kids',
news: 'News',
reality: 'Reality',
sciFiFantasy: 'Sci-Fi & Fantasy',
soap: 'Soap',
talk: 'Talk',
warPolitics: 'War & Politics',
},
languageType: {
zh: 'Chinese',
en: 'English',
ja: 'Japanese',
ko: 'Korean',
fr: 'French',
de: 'German',
es: 'Spanish',
it: 'Italian',
ru: 'Russian',
pt: 'Portuguese',
ar: 'Arabic',
hi: 'Hindi',
th: 'Thai',
},
},
} }

View File

@@ -2008,4 +2008,81 @@ export default {
syncLibrariesHint: '只有选中的媒体库才会被同步', syncLibrariesHint: '只有选中的媒体库才会被同步',
nameExists: '【{name}】已存在,请替换为其他名称', nameExists: '【{name}】已存在,请替换为其他名称',
}, },
bangumi: {
category: '类别',
sort: '排序',
year: '年份',
cat: {
other: '其他',
tv: 'TV',
ova: 'OVA',
movie: 'Movie',
web: 'WEB',
},
sortType: {
rank: '排名',
date: '日期',
},
},
tmdb: {
type: '类型',
sort: '排序',
genre: '风格',
language: '语言',
rating: '评分',
sortType: {
popularityDesc: '热度降序',
popularityAsc: '热度升序',
releaseDateDesc: '上映日期降序',
releaseDateAsc: '上映日期升序',
firstAirDateDesc: '首播日期降序',
firstAirDateAsc: '首播日期升序',
voteAverageDesc: '评分降序',
voteAverageAsc: '评分升序',
},
genreType: {
action: '动作',
adventure: '冒险',
animation: '动画',
comedy: '喜剧',
crime: '犯罪',
documentary: '纪录片',
drama: '剧情',
family: '家庭',
fantasy: '奇幻',
history: '历史',
horror: '恐怖',
music: '音乐',
mystery: '悬疑',
romance: '爱情',
scienceFiction: '科幻',
tvMovie: '电视电影',
thriller: '惊悚',
war: '战争',
western: '西部',
actionAdventure: '动作冒险',
kids: '儿童',
news: '新闻',
reality: '真人秀',
sciFiFantasy: '科幻奇幻',
soap: '肥皂剧',
talk: '戏剧',
warPolitics: '战争政治',
},
languageType: {
zh: '中文',
en: '英语',
ja: '日语',
ko: '韩语',
fr: '法语',
de: '德语',
es: '西班牙语',
it: '意大利语',
ru: '俄语',
pt: '葡萄牙语',
ar: '阿拉伯语',
hi: '印地语',
th: '泰语',
},
},
} }

View File

@@ -2020,4 +2020,81 @@ export default {
syncLibrariesHint: '只有選中的媒體庫才會被同步', syncLibrariesHint: '只有選中的媒體庫才會被同步',
nameExists: '【{name}】已存在,請替換為其他名稱', nameExists: '【{name}】已存在,請替換為其他名稱',
}, },
bangumi: {
category: '類別',
sort: '排序',
year: '年份',
cat: {
other: '其他',
tv: 'TV',
ova: 'OVA',
movie: 'Movie',
web: 'WEB',
},
sortType: {
rank: '排名',
date: '日期',
},
},
tmdb: {
type: '類型',
sort: '排序',
genre: '風格',
language: '語言',
rating: '評分',
sortType: {
popularityDesc: '熱度降序',
popularityAsc: '熱度升序',
releaseDateDesc: '上映日期降序',
releaseDateAsc: '上映日期升序',
firstAirDateDesc: '首播日期降序',
firstAirDateAsc: '首播日期升序',
voteAverageDesc: '評分降序',
voteAverageAsc: '評分升序',
},
genreType: {
action: '動作',
adventure: '冒險',
animation: '動畫',
comedy: '喜劇',
crime: '犯罪',
documentary: '紀錄片',
drama: '劇情',
family: '家庭',
fantasy: '奇幻',
history: '歷史',
horror: '恐怖',
music: '音樂',
mystery: '懸疑',
romance: '愛情',
scienceFiction: '科幻',
tvMovie: '電視電影',
thriller: '驚悚',
war: '戰爭',
western: '西部',
actionAdventure: '動作冒險',
kids: '兒童',
news: '新聞',
reality: '真人秀',
sciFiFantasy: '科幻奇幻',
soap: '肥皂劇',
talk: '戲劇',
warPolitics: '戰爭政治',
},
languageType: {
zh: '中文',
en: '英語',
ja: '日語',
ko: '韓語',
fr: '法語',
de: '德語',
es: '西班牙語',
it: '意大利語',
ru: '俄語',
pt: '葡萄牙語',
ar: '阿拉伯語',
hi: '印地語',
th: '泰語',
},
},
} }

View File

@@ -1,5 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import MediaCardListView from '@/views/discover/MediaCardListView.vue' import MediaCardListView from '@/views/discover/MediaCardListView.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
// 过滤参数 // 过滤参数
const filterParams = reactive({ const filterParams = reactive({
@@ -18,17 +21,17 @@ const filterParams = reactive({
5 为 WEB 5 为 WEB
*/ */
const bangumiCatDict = { const bangumiCatDict = {
'0': '其他', '0': t('bangumi.cat.other'),
'1': 'TV', '1': t('bangumi.cat.tv'),
'2': 'OVA', '2': t('bangumi.cat.ova'),
'3': 'Movie', '3': t('bangumi.cat.movie'),
'5': 'WEB', '5': t('bangumi.cat.web'),
} }
// Bangumi排序字典 // Bangumi排序字典
const bangumiSortDict = { const bangumiSortDict = {
'rank': '排名', 'rank': t('bangumi.sortType.rank'),
'date': '日期', 'date': t('bangumi.sortType.date'),
} }
// 年份字典自动生成最近10年 // 年份字典自动生成最近10年
@@ -51,7 +54,7 @@ watch([filterParams], () => {
<div class="px-3"> <div class="px-3">
<div class="flex justify-start align-center"> <div class="flex justify-start align-center">
<div class="mr-5"> <div class="mr-5">
<VLabel>类别</VLabel> <VLabel>{{ t('bangumi.category') }}</VLabel>
</div> </div>
<VChipGroup v-model="filterParams.cat"> <VChipGroup v-model="filterParams.cat">
<VChip <VChip
@@ -68,7 +71,7 @@ watch([filterParams], () => {
</div> </div>
<div class="flex justify-start align-center"> <div class="flex justify-start align-center">
<div class="mr-5"> <div class="mr-5">
<VLabel>排序</VLabel> <VLabel>{{ t('bangumi.sort') }}</VLabel>
</div> </div>
<VChipGroup v-model="filterParams.sort"> <VChipGroup v-model="filterParams.sort">
<VChip <VChip
@@ -85,7 +88,7 @@ watch([filterParams], () => {
</div> </div>
<div class="flex justify-start align-center"> <div class="flex justify-start align-center">
<div class="mr-5"> <div class="mr-5">
<VLabel>年份</VLabel> <VLabel>{{ t('bangumi.year') }}</VLabel>
</div> </div>
<VChipGroup v-model="filterParams.year"> <VChipGroup v-model="filterParams.year">
<VChip <VChip

View File

@@ -3,6 +3,9 @@ import api from '@/api'
import type { MediaInfo } from '@/api/types' import type { MediaInfo } from '@/api/types'
import MediaCard from '@/components/cards/MediaCard.vue' import MediaCard from '@/components/cards/MediaCard.vue'
import NoDataFound from '@/components/NoDataFound.vue' import NoDataFound from '@/components/NoDataFound.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
@@ -118,8 +121,8 @@ async function fetchData({ done }: { done: any }) {
<NoDataFound <NoDataFound
v-if="dataList.length === 0 && isRefreshed" v-if="dataList.length === 0 && isRefreshed"
error-code="404" error-code="404"
error-title="没有数据" :error-title="t('common.noData')"
error-description="无法获取到媒体信息" :error-description="t('error.networkError')"
/> />
</VInfiniteScroll> </VInfiniteScroll>
</template> </template>

View File

@@ -2,6 +2,9 @@
import api from '@/api' import api from '@/api'
import PersonCard from '@/components/cards/PersonCard.vue' import PersonCard from '@/components/cards/PersonCard.vue'
import NoDataFound from '@/components/NoDataFound.vue' import NoDataFound from '@/components/NoDataFound.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
@@ -119,8 +122,8 @@ async function fetchData({ done }: { done: any }) {
<NoDataFound <NoDataFound
v-if="dataList.length === 0 && isRefreshed" v-if="dataList.length === 0 && isRefreshed"
error-code="404" error-code="404"
error-title="没有数据" :error-title="t('common.noData')"
error-description="无法获取到媒体信息" :error-description="t('error.networkError')"
/> />
</VInfiniteScroll> </VInfiniteScroll>
</template> </template>

View File

@@ -1,5 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import MediaCardListView from '@/views/discover/MediaCardListView.vue' import MediaCardListView from '@/views/discover/MediaCardListView.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
// 电影或者电视剧 movies/tvs // 电影或者电视剧 movies/tvs
const type = ref('movies') const type = ref('movies')
@@ -18,82 +21,82 @@ const filterParams = reactive({
// TMDB 电影排序字典 // TMDB 电影排序字典
const tmdbSortDict: Record<string, string> = { const tmdbSortDict: Record<string, string> = {
'popularity.desc': '热度降序', 'popularity.desc': t('tmdb.sortType.popularityDesc'),
'popularity.asc': '热度升序', 'popularity.asc': t('tmdb.sortType.popularityAsc'),
'release_date.desc': '上映日期降序', 'release_date.desc': t('tmdb.sortType.releaseDateDesc'),
'release_date.asc': '上映日期升序', 'release_date.asc': t('tmdb.sortType.releaseDateAsc'),
'vote_average.desc': '评分降序', 'vote_average.desc': t('tmdb.sortType.voteAverageDesc'),
'vote_average.asc': '评分升序', 'vote_average.asc': t('tmdb.sortType.voteAverageAsc'),
} }
// TMDB 电视剧排序字典 // TMDB 电视剧排序字典
const tmdbTvSortDict: Record<string, string> = { const tmdbTvSortDict: Record<string, string> = {
'popularity.desc': '热度降序', 'popularity.desc': t('tmdb.sortType.popularityDesc'),
'popularity.asc': '热度升序', 'popularity.asc': t('tmdb.sortType.popularityAsc'),
'first_air_date.desc': '首播日期降序', 'first_air_date.desc': t('tmdb.sortType.firstAirDateDesc'),
'first_air_date.asc': '首播日期升序', 'first_air_date.asc': t('tmdb.sortType.firstAirDateAsc'),
'vote_average.desc': '评分降序', 'vote_average.desc': t('tmdb.sortType.voteAverageDesc'),
'vote_average.asc': '评分升序', 'vote_average.asc': t('tmdb.sortType.voteAverageAsc'),
} }
// TMDB电影风格字典 // TMDB电影风格字典
const tmdbMovieGenreDict: Record<string, string> = { const tmdbMovieGenreDict: Record<string, string> = {
'28': '动作', '28': t('tmdb.genreType.action'),
'12': '冒险', '12': t('tmdb.genreType.adventure'),
'16': '动画', '16': t('tmdb.genreType.animation'),
'35': '喜剧', '35': t('tmdb.genreType.comedy'),
'80': '犯罪', '80': t('tmdb.genreType.crime'),
'99': '纪录片', '99': t('tmdb.genreType.documentary'),
'18': '剧情', '18': t('tmdb.genreType.drama'),
'10751': '家庭', '10751': t('tmdb.genreType.family'),
'14': '奇幻', '14': t('tmdb.genreType.fantasy'),
'36': '历史', '36': t('tmdb.genreType.history'),
'27': '恐怖', '27': t('tmdb.genreType.horror'),
'10402': '音乐', '10402': t('tmdb.genreType.music'),
'9648': '悬疑', '9648': t('tmdb.genreType.mystery'),
'10749': '爱情', '10749': t('tmdb.genreType.romance'),
'878': '科幻', '878': t('tmdb.genreType.scienceFiction'),
'10770': '电视电影', '10770': t('tmdb.genreType.tvMovie'),
'53': '惊悚', '53': t('tmdb.genreType.thriller'),
'10752': '战争', '10752': t('tmdb.genreType.war'),
'37': '西部', '37': t('tmdb.genreType.western'),
} }
// TMDB电视剧风格字典 // TMDB电视剧风格字典
const tmdbTvGenreDict: Record<string, string> = { const tmdbTvGenreDict: Record<string, string> = {
'10759': '动作冒险', '10759': t('tmdb.genreType.actionAdventure'),
'16': '动画', '16': t('tmdb.genreType.animation'),
'35': '喜剧', '35': t('tmdb.genreType.comedy'),
'80': '犯罪', '80': t('tmdb.genreType.crime'),
'99': '纪录片', '99': t('tmdb.genreType.documentary'),
'18': '剧情', '18': t('tmdb.genreType.drama'),
'10751': '家庭', '10751': t('tmdb.genreType.family'),
'10762': '儿童', '10762': t('tmdb.genreType.kids'),
'9648': '悬疑', '9648': t('tmdb.genreType.mystery'),
'10763': '新闻', '10763': t('tmdb.genreType.news'),
'10764': '真人秀', '10764': t('tmdb.genreType.reality'),
'10765': '科幻奇幻', '10765': t('tmdb.genreType.sciFiFantasy'),
'10766': '肥皂剧', '10766': t('tmdb.genreType.soap'),
'10767': '戏剧', '10767': t('tmdb.genreType.talk'),
'10768': '战争政治', '10768': t('tmdb.genreType.warPolitics'),
'37': '西部', '37': t('tmdb.genreType.western'),
} }
// TMDB原始语言字典主要语言 // TMDB原始语言字典主要语言
const tmdbLanguageDict = { const tmdbLanguageDict = {
'zh': '中文', 'zh': t('tmdb.languageType.zh'),
'en': '英语', 'en': t('tmdb.languageType.en'),
'ja': '日语', 'ja': t('tmdb.languageType.ja'),
'ko': '韩语', 'ko': t('tmdb.languageType.ko'),
'fr': '法语', 'fr': t('tmdb.languageType.fr'),
'de': '德语', 'de': t('tmdb.languageType.de'),
'es': '西班牙语', 'es': t('tmdb.languageType.es'),
'it': '意大利语', 'it': t('tmdb.languageType.it'),
'ru': '俄语', 'ru': t('tmdb.languageType.ru'),
'pt': '葡萄牙语', 'pt': t('tmdb.languageType.pt'),
'ar': '阿拉伯语', 'ar': t('tmdb.languageType.ar'),
'hi': '印地语', 'hi': t('tmdb.languageType.hi'),
'th': '泰语', 'th': t('tmdb.languageType.th'),
} }
// 当前Key // 当前Key
@@ -136,16 +139,16 @@ watch(filterParams, () => {
<div class="px-3"> <div class="px-3">
<div class="flex justify-start align-center"> <div class="flex justify-start align-center">
<div class="mr-5"> <div class="mr-5">
<VLabel>类型</VLabel> <VLabel>{{ t('tmdb.type') }}</VLabel>
</div> </div>
<VChipGroup v-model="type"> <VChipGroup v-model="type">
<VChip :color="type == 'movies' ? 'primary' : ''" filter tile value="movies">电影</VChip> <VChip :color="type == 'movies' ? 'primary' : ''" filter tile value="movies">{{ t('mediaType.movie') }}</VChip>
<VChip :color="type == 'tvs' ? 'primary' : ''" filter tile value="tvs">电视剧</VChip> <VChip :color="type == 'tvs' ? 'primary' : ''" filter tile value="tvs">{{ t('mediaType.tv') }}</VChip>
</VChipGroup> </VChipGroup>
</div> </div>
<div class="flex justify-start align-center"> <div class="flex justify-start align-center">
<div class="mr-5"> <div class="mr-5">
<VLabel>排序</VLabel> <VLabel>{{ t('tmdb.sort') }}</VLabel>
</div> </div>
<VChipGroup v-model="filterParams.sort_by"> <VChipGroup v-model="filterParams.sort_by">
<VChip <VChip
@@ -162,7 +165,7 @@ watch(filterParams, () => {
</div> </div>
<div class="flex justify-start align-center"> <div class="flex justify-start align-center">
<div class="mr-5"> <div class="mr-5">
<VLabel>风格</VLabel> <VLabel>{{ t('tmdb.genre') }}</VLabel>
</div> </div>
<VChipGroup v-model="filterParams.with_genres"> <VChipGroup v-model="filterParams.with_genres">
<VChip <VChip
@@ -179,7 +182,7 @@ watch(filterParams, () => {
</div> </div>
<div class="flex justify-start align-center"> <div class="flex justify-start align-center">
<div class="mr-5"> <div class="mr-5">
<VLabel>语言</VLabel> <VLabel>{{ t('tmdb.language') }}</VLabel>
</div> </div>
<VChipGroup v-model="filterParams.with_original_language"> <VChipGroup v-model="filterParams.with_original_language">
<VChip <VChip
@@ -196,7 +199,7 @@ watch(filterParams, () => {
</div> </div>
<div class="flex justify-start align-center"> <div class="flex justify-start align-center">
<div class="mr-5"> <div class="mr-5">
<VLabel>评分</VLabel> <VLabel>{{ t('tmdb.rating') }}</VLabel>
</div> </div>
<VSlider <VSlider
v-model="filterParams.vote_average" v-model="filterParams.vote_average"