Merge pull request #325 from umbors/3.1-dev

Add i18n support for zh-CN
This commit is contained in:
Estrella Pan
2023-06-13 22:34:30 +08:00
committed by GitHub
26 changed files with 666 additions and 247 deletions

View File

@@ -24,6 +24,7 @@
"naive-ui": "^2.34.4",
"pinia": "^2.1.3",
"vue": "^3.3.4",
"vue-i18n": "^9.2.2",
"vue-router": "^4.2.1"
},
"devDependencies": {

55
webui/pnpm-lock.yaml generated
View File

@@ -26,6 +26,9 @@ dependencies:
vue:
specifier: ^3.3.4
version: 3.3.4
vue-i18n:
specifier: ^9.2.2
version: 9.2.2(vue@3.3.4)
vue-router:
specifier: ^4.2.1
version: 4.2.1(vue@3.3.4)
@@ -1844,6 +1847,44 @@ packages:
- supports-color
dev: true
/@intlify/core-base@9.2.2:
resolution: {integrity: sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==}
engines: {node: '>= 14'}
dependencies:
'@intlify/devtools-if': 9.2.2
'@intlify/message-compiler': 9.2.2
'@intlify/shared': 9.2.2
'@intlify/vue-devtools': 9.2.2
dev: false
/@intlify/devtools-if@9.2.2:
resolution: {integrity: sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==}
engines: {node: '>= 14'}
dependencies:
'@intlify/shared': 9.2.2
dev: false
/@intlify/message-compiler@9.2.2:
resolution: {integrity: sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==}
engines: {node: '>= 14'}
dependencies:
'@intlify/shared': 9.2.2
source-map: 0.6.1
dev: false
/@intlify/shared@9.2.2:
resolution: {integrity: sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==}
engines: {node: '>= 14'}
dev: false
/@intlify/vue-devtools@9.2.2:
resolution: {integrity: sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==}
engines: {node: '>= 14'}
dependencies:
'@intlify/core-base': 9.2.2
'@intlify/shared': 9.2.2
dev: false
/@istanbuljs/load-nyc-config@1.1.0:
resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
engines: {node: '>=8'}
@@ -8260,7 +8301,6 @@ packages:
/source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
dev: true
/sourcemap-codec@1.4.8:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
@@ -9232,6 +9272,19 @@ packages:
- supports-color
dev: true
/vue-i18n@9.2.2(vue@3.3.4):
resolution: {integrity: sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==}
engines: {node: '>= 14'}
peerDependencies:
vue: ^3.0.0
dependencies:
'@intlify/core-base': 9.2.2
'@intlify/shared': 9.2.2
'@intlify/vue-devtools': 9.2.2
'@vue/devtools-api': 6.5.0
vue: 3.3.4
dev: false
/vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.3.4):
resolution: {integrity: sha512-K3wt3iVmNGaFEOUR4JIThQRWfqokxLfnPslD41FDZB2ajXp789+wCqJyGYlIFsvEQ2P61PInw6/ph5iiqg51gg==}
peerDependencies:

View File

@@ -111,22 +111,22 @@ async function subscribe() {
</script>
<template>
<ab-popup v-model:show="show" title="Add Bangumi" css="w-360px">
<ab-popup v-model:show="show" :title="$t('topbar.add.title')" css="w-360px">
<div v-if="!analysis.next" space-y-12px>
<ab-setting
v-model:data="rss"
label="RSS Link"
:label="$t('topbar.add.rsslink')"
type="input"
:prop="{
placeholder: 'Please enter the RSS link',
placeholder: $t('topbar.add.placeholder'),
}"
:bottom-line="true"
></ab-setting>
<div flex="~ justify-end">
<ab-button size="small" :loading="analysis.loading" @click="analyser"
>Analyse</ab-button
>
<ab-button size="small" :loading="analysis.loading" @click="analyser">{{
$t('topbar.add.analyse')
}}</ab-button>
</div>
</div>

View File

@@ -7,22 +7,26 @@ const { user, update } = useAuth();
</script>
<template>
<ab-popup v-model:show="show" title="Change Account" css="w-365px">
<ab-popup
v-model:show="show"
:title="$t('topbar.profile.poptitle')"
css="w-365px"
>
<div space-y-16px>
<ab-label label="Username">
<ab-label :label="$t('topbar.profile.username')">
<input
v-model="user.username"
type="text"
placeholder="username"
:placeholder="$t('topbar.profile.username')"
ab-input
/>
</ab-label>
<ab-label label="Password">
<ab-label :label="$t('topbar.profile.password')">
<input
v-model="user.password"
type="password"
placeholder="password"
:placeholder="$t('topbar.profile.password')"
ab-input
/>
</ab-label>
@@ -30,7 +34,9 @@ const { user, update } = useAuth();
<div line></div>
<div flex="~ justify-end">
<ab-button size="small" @click="update">Update</ab-button>
<ab-button size="small" @click="update">{{
$t('topbar.profile.updatebtn')
}}</ab-button>
</div>
</div>
</ab-popup>

View File

@@ -1,4 +1,5 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import type { BangumiRule } from '#/bangumi';
const emit = defineEmits<{
@@ -10,7 +11,7 @@ const emit = defineEmits<{
opts: { id: number; deleteFile: boolean }
): void;
}>();
const { t } = useI18n({ useScope: 'global' });
const show = defineModel('show', { default: false });
const rule = defineModel<BangumiRule>('rule', {
required: true,
@@ -52,9 +53,9 @@ function emitEnable() {
const popupTitle = computed(() => {
if (rule.value.deleted) {
return 'Enable Rule';
return t('homepage.rule.enablerule');
} else {
return 'Edit Rule';
return t('homepage.rule.editrule');
}
});
@@ -70,15 +71,17 @@ const boxSize = computed(() => {
<template>
<ab-popup v-model:show="show" :title="popupTitle" :css="boxSize">
<div v-if="rule.deleted">
<div>Do you want to enable this rule?</div>
<div>{{ $t('homepage.rule.enablehit') }}</div>
<div line my-8px></div>
<div fx-cer justify-center space-x-10px>
<ab-button size="small" type="warn" @click="() => emitEnable()"
>Yes</ab-button
>
<ab-button size="small" @click="() => close()">No</ab-button>
<ab-button size="small" type="warn" @click="() => emitEnable()">{{
$t('homepage.rule.yesbtn')
}}</ab-button>
<ab-button size="small" @click="() => close()">{{
$t('homepage.rule.nobtn')
}}</ab-button>
</div>
</div>
@@ -90,29 +93,37 @@ const boxSize = computed(() => {
size="small"
type="warn"
@click="() => showDeleteFileDialog('disable')"
>Disable</ab-button
>{{ $t('homepage.rule.disable') }}</ab-button
>
<ab-button
size="small"
type="warn"
@click="() => showDeleteFileDialog('delete')"
>Delete</ab-button
>{{ $t('homepage.rule.delete') }}</ab-button
>
<ab-button size="small" @click="emitApply">Apply</ab-button>
<ab-button size="small" @click="emitApply">{{
$t('homepage.rule.apply')
}}</ab-button>
</div>
</div>
<ab-popup v-model:show="deleteFileDialog.show" title="Delete">
<div>Delete Local File?</div>
<ab-popup
v-model:show="deleteFileDialog.show"
:title="$t('homepage.rule.delete')"
>
<div>{{ $t('homepage.rule.deletehit') }}</div>
<div line my-8px></div>
<div fx-cer justify-center space-x-10px>
<ab-button size="small" type="warn" @click="() => emitdeleteFile(true)"
>Yes</ab-button
>
<ab-button size="small" @click="() => emitdeleteFile(false)"
>No</ab-button
<ab-button
size="small"
type="warn"
@click="() => emitdeleteFile(true)"
>{{ $t('homepage.rule.yesbtn') }}</ab-button
>
<ab-button size="small" @click="() => emitdeleteFile(false)">{{
$t('homepage.rule.nobtn')
}}</ab-button>
</div>
</ab-popup>
</ab-popup>

View File

@@ -1,7 +1,9 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import type { BangumiRule } from '#/bangumi';
import type { SettingItem } from '#/components';
const { t } = useI18n({ useScope: 'global' });
const rule = defineModel<BangumiRule>('rule', {
required: true,
});
@@ -9,7 +11,7 @@ const rule = defineModel<BangumiRule>('rule', {
const items: SettingItem<BangumiRule>[] = [
{
configKey: 'official_title',
label: 'Officical Ttile',
label: t('homepage.rule.officaltitle'),
type: 'input',
prop: {
type: 'text',
@@ -17,7 +19,7 @@ const items: SettingItem<BangumiRule>[] = [
},
{
configKey: 'year',
label: 'Year',
label: t('homepage.rule.year'),
type: 'input',
css: 'w-72px',
prop: {
@@ -26,7 +28,7 @@ const items: SettingItem<BangumiRule>[] = [
},
{
configKey: 'season',
label: 'Season',
label: t('homepage.rule.season'),
type: 'input',
css: 'w-72px',
prop: {
@@ -36,7 +38,7 @@ const items: SettingItem<BangumiRule>[] = [
},
{
configKey: 'offset',
label: 'Offset',
label: t('homepage.rule.offset'),
type: 'input',
css: 'w-72px',
prop: {
@@ -45,7 +47,7 @@ const items: SettingItem<BangumiRule>[] = [
},
{
configKey: 'filter',
label: 'Exclude',
label: t('homepage.rule.exclude'),
type: 'dynamic-tags',
bottomLine: true,
},

View File

@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue';
import { AddOne, More } from '@icon-park/vue-next';
import { AddOne, Earth, More } from '@icon-park/vue-next';
withDefaults(
defineProps<{
@@ -17,13 +17,22 @@ withDefaults(
}
);
defineEmits(['clickAdd']);
defineEmits(['clickAdds']);
</script>
<template>
<Menu>
<div rel>
<div fx-cer space-x-16px>
<Earth
theme="outline"
size="24"
fill="#fff"
is-btn
btn-click
@click="() => $emit('changeLang')"
/>
<AddOne
theme="outline"
size="24"

View File

@@ -9,6 +9,7 @@ import {
Play,
SettingTwo,
} from '@icon-park/vue-next';
import { useI18n } from 'vue-i18n';
const props = withDefaults(
defineProps<{
@@ -18,7 +19,7 @@ const props = withDefaults(
open: false,
}
);
const { t } = useI18n({ useScope: 'global' });
const show = ref(props.open);
const toggle = () => (show.value = !show.value);
const route = useRoute();
@@ -28,39 +29,39 @@ const items = [
{
id: 1,
icon: Home,
label: 'HomePage',
label: t('sidebar.homepage'),
path: '/bangumi',
},
{
id: 2,
icon: Calendar,
label: 'Calendar',
label: t('sidebar.calendar'),
path: '/calendar',
hidden: true,
},
{
id: 3,
icon: Play,
label: 'Player',
label: t('sidebar.player'),
path: '/player',
},
{
id: 4,
icon: Download,
label: 'Downloader',
label: t('sidebar.downloader'),
path: '/downloader',
hidden: true,
},
{
id: 5,
icon: Log,
label: 'Log',
label: t('sidebar.log'),
path: '/log',
},
{
id: 6,
icon: SettingTwo,
label: 'Config',
label: t('sidebar.config'),
path: '/config',
},
];
@@ -88,7 +89,7 @@ const items = [
@click="toggle"
>
<div :class="[!show && 'abs opacity-0']" transition-opacity>
<div text-h1>Menu</div>
<div text-h1>{{ $t('sidebar.title') }}</div>
</div>
<MenuUnfold
@@ -138,7 +139,7 @@ const items = [
@click="logout"
>
<Logout :size="24" />
<div text-h2>Logout</div>
<div text-h2>{{ $t('sidebar.logout') }}</div>
</div>
</div>
</div>

View File

@@ -7,7 +7,9 @@ import {
Power,
Refresh,
} from '@icon-park/vue-next';
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n({ useScope: 'global' });
const search = ref('');
const show = ref(false);
const showAdd = ref(false);
@@ -19,37 +21,37 @@ const { running } = storeToRefs(useProgramStore());
const items = [
{
id: 1,
label: 'Start',
label: t('topbar.start'),
icon: PlayOne,
handle: start,
},
{
id: 2,
label: 'Pause',
label: t('topbar.pause'),
icon: Pause,
handle: pause,
},
{
id: 3,
label: 'Restart',
label: t('topbar.restart'),
icon: Refresh,
handle: restart,
},
{
id: 4,
label: 'Shutdown',
label: t('topbar.shutdown'),
icon: Power,
handle: shutdown,
},
{
id: 5,
label: 'Reset Rule',
label: t('topbar.resetrule'),
icon: Format,
handle: resetRule,
},
{
id: 6,
label: 'Profile',
label: t('topbar.profile.title'),
icon: Me,
handle: () => {
show.value = true;
@@ -64,6 +66,20 @@ onBeforeMount(() => {
onUnmounted(() => {
offUpdate();
});
function changeLocale() {
if (localStorage.getItem('lang') === 'zh-CN') {
const newLang = 'en-US';
locale.value = newLang;
localStorage.setItem('lang', newLang);
location.reload();
} else {
const newLang = 'zh-CN';
locale.value = newLang;
localStorage.setItem('lang', newLang);
location.reload();
}
}
</script>
<template>
@@ -80,6 +96,7 @@ onUnmounted(() => {
:items="items"
:running="running"
@click-add="() => (showAdd = true)"
@change-lang="() => changeLocale()"
></ab-status-bar>
</div>

View File

@@ -1,7 +1,9 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import type { Downloader, DownloaderType } from '#/config';
import type { SettingItem } from '#/components';
const { t } = useI18n({ useScope: 'global' });
const { getSettingGroup } = useConfigStore();
const downloader = getSettingGroup('downloader');
@@ -10,7 +12,7 @@ const downloaderType: DownloaderType = ['qbittorrent'];
const items: SettingItem<Downloader>[] = [
{
configKey: 'type',
label: 'Downloader Type',
label: t('config.downloaderset.type'),
type: 'select',
css: 'w-115px',
prop: {
@@ -19,7 +21,7 @@ const items: SettingItem<Downloader>[] = [
},
{
configKey: 'host',
label: 'Host',
label: t('config.downloaderset.host'),
type: 'input',
prop: {
type: 'text',
@@ -28,7 +30,7 @@ const items: SettingItem<Downloader>[] = [
},
{
configKey: 'username',
label: 'Username',
label: t('config.downloaderset.username'),
type: 'input',
prop: {
type: 'text',
@@ -37,7 +39,7 @@ const items: SettingItem<Downloader>[] = [
},
{
configKey: 'password',
label: 'Password',
label: t('config.downloaderset.password'),
type: 'input',
prop: {
type: 'text',
@@ -47,7 +49,7 @@ const items: SettingItem<Downloader>[] = [
},
{
configKey: 'path',
label: 'Download Path',
label: t('config.downloaderset.path'),
type: 'input',
prop: {
type: 'text',
@@ -56,14 +58,14 @@ const items: SettingItem<Downloader>[] = [
},
{
configKey: 'ssl',
label: 'SSL',
label: t('config.downloaderset.ssl'),
type: 'switch',
},
];
</script>
<template>
<ab-fold-panel title="Downloader Setting">
<ab-fold-panel :title="$t('config.downloaderset.title')">
<div space-y-12px>
<ab-setting
v-for="i in items"

View File

@@ -1,7 +1,9 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import type { BangumiManage, RenameMethod } from '#/config';
import type { SettingItem } from '#/components';
const { t } = useI18n({ useScope: 'global' });
const { getSettingGroup } = useConfigStore();
const manage = getSettingGroup('bangumi_manage');
@@ -10,12 +12,12 @@ const renameMethod: RenameMethod = ['normal', 'pn', 'advance', 'none'];
const items: SettingItem<BangumiManage>[] = [
{
configKey: 'enable',
label: 'Enable',
label: t('config.manageset.enable'),
type: 'switch',
},
{
configKey: 'rename_method',
label: 'Rename Method',
label: t('config.manageset.method'),
type: 'select',
prop: {
items: renameMethod,
@@ -24,24 +26,24 @@ const items: SettingItem<BangumiManage>[] = [
},
{
configKey: 'eps_complete',
label: 'Eps complete',
label: t('config.manageset.eps'),
type: 'switch',
},
{
configKey: 'group_tag',
label: 'Add Group Tag',
label: t('config.manageset.grouptag'),
type: 'switch',
},
{
configKey: 'remove_bad_torrent',
label: 'Delete Bad Torrent',
label: t('config.manageset.deletebadtorr'),
type: 'switch',
},
];
</script>
<template>
<ab-fold-panel title="Manage Setting">
<ab-fold-panel :title="$t('config.manageset.title')">
<div space-y-12px>
<ab-setting
v-for="i in items"

View File

@@ -1,7 +1,9 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import type { Log, Program } from '#/config';
import type { SettingItem } from '#/components';
const { t } = useI18n({ useScope: 'global' });
const { getSettingGroup } = useConfigStore();
const program = getSettingGroup('program');
@@ -10,7 +12,7 @@ const log = getSettingGroup('log');
const programItems: SettingItem<Program>[] = [
{
configKey: 'rss_time',
label: 'Interval Time of Rss',
label: t('config.normalset.rssintvl'),
type: 'input',
css: 'w-72px',
prop: {
@@ -20,7 +22,7 @@ const programItems: SettingItem<Program>[] = [
},
{
configKey: 'rename_time',
label: 'Interval Time of Rename',
label: t('config.normalset.renameintvl'),
type: 'input',
css: 'w-72px',
prop: {
@@ -30,7 +32,7 @@ const programItems: SettingItem<Program>[] = [
},
{
configKey: 'webui_port',
label: 'WebUI Port',
label: t('config.normalset.webport'),
type: 'input',
css: 'w-72px',
prop: {
@@ -43,13 +45,13 @@ const programItems: SettingItem<Program>[] = [
const logItems: SettingItem<Log> = {
configKey: 'debug_enable',
label: 'Debug',
label: t('config.normalset.debug'),
type: 'switch',
};
</script>
<template>
<ab-fold-panel title="Normal Setting">
<ab-fold-panel :title="$t('config.normalset.title')">
<div space-y-12px>
<ab-setting
v-for="i in programItems"

View File

@@ -1,7 +1,9 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import type { Notification, NotificationType } from '#/config';
import type { SettingItem } from '#/components';
const { t } = useI18n({ useScope: 'global' });
const { getSettingGroup } = useConfigStore();
const notification = getSettingGroup('notification');
@@ -15,13 +17,13 @@ const notificationType: NotificationType = [
const items: SettingItem<Notification>[] = [
{
configKey: 'enable',
label: 'Enable',
label: t('config.notificationset.enable'),
type: 'switch',
bottomLine: true,
},
{
configKey: 'type',
label: 'Type',
label: t('config.notificationset.type'),
type: 'select',
css: 'w-140px',
prop: {
@@ -30,7 +32,7 @@ const items: SettingItem<Notification>[] = [
},
{
configKey: 'token',
label: 'Token',
label: t('config.notificationset.token'),
type: 'input',
prop: {
type: 'text',
@@ -39,7 +41,7 @@ const items: SettingItem<Notification>[] = [
},
{
configKey: 'chat_id',
label: 'Chat ID',
label: t('config.notificationset.chatid'),
type: 'input',
prop: {
type: 'text',
@@ -50,7 +52,7 @@ const items: SettingItem<Notification>[] = [
</script>
<template>
<ab-fold-panel title="Notification Setting">
<ab-fold-panel :title="$t('config.notificationset.title')">
<div space-y-12px>
<ab-setting
v-for="i in items"

View File

@@ -1,4 +1,5 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import type {
RssParser,
RssParserLang,
@@ -7,6 +8,7 @@ import type {
} from '#/config';
import type { SettingItem } from '#/components';
const { t } = useI18n({ useScope: 'global' });
const { getSettingGroup } = useConfigStore();
const parser = getSettingGroup('rss_parser');
@@ -19,12 +21,12 @@ const parserMethods: RssParserMethodType = ['tmdb', 'mikan', 'parser'];
const items: SettingItem<RssParser>[] = [
{
configKey: 'enable',
label: 'Enable',
label: t('config.parserset.enable'),
type: 'switch',
},
{
configKey: 'type',
label: 'Source',
label: t('config.parserset.source'),
type: 'select',
css: 'w-115px',
prop: {
@@ -33,7 +35,7 @@ const items: SettingItem<RssParser>[] = [
},
{
configKey: 'token',
label: 'Token',
label: t('config.parserset.token'),
type: 'input',
prop: {
type: 'text',
@@ -42,7 +44,7 @@ const items: SettingItem<RssParser>[] = [
},
{
configKey: 'custom_url',
label: 'Custom Url',
label: t('config.parserset.url'),
type: 'input',
prop: {
type: 'text',
@@ -52,7 +54,7 @@ const items: SettingItem<RssParser>[] = [
},
{
configKey: 'language',
label: 'Language',
label: t('config.parserset.language'),
type: 'select',
prop: {
items: langs,
@@ -60,7 +62,7 @@ const items: SettingItem<RssParser>[] = [
},
{
configKey: 'parser_type',
label: 'Parser Type',
label: t('config.parserset.type'),
type: 'select',
prop: {
items: parserMethods,
@@ -68,14 +70,14 @@ const items: SettingItem<RssParser>[] = [
},
{
configKey: 'filter',
label: 'Exclude',
label: t('config.parserset.exclude'),
type: 'dynamic-tags',
},
];
</script>
<template>
<ab-fold-panel title="Parser Setting">
<ab-fold-panel :title="$t('config.parserset.title')">
<div space-y-12px>
<ab-setting
v-for="i in items"

View File

@@ -3,19 +3,19 @@ const { types, type, url } = storeToRefs(usePlayerStore());
</script>
<template>
<ab-fold-panel title="Media Player Setting">
<ab-fold-panel :title="$t('config.mediaplayerset.title')">
<div space-y-12px>
<ab-setting
v-model:data="type"
type="select"
label="type"
:label="$t('config.mediaplayerset.type')"
:prop="{ items: types }"
></ab-setting>
<ab-setting
v-model:data="url"
type="input"
label="url"
:label="$t('config.mediaplayerset.url')"
:prop="{ placeholder: 'media player url' }"
></ab-setting>
</div>

View File

@@ -1,7 +1,9 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import type { Proxy, ProxyType } from '#/config';
import type { SettingItem } from '#/components';
const { t } = useI18n({ useScope: 'global' });
const { getSettingGroup } = useConfigStore();
const proxy = getSettingGroup('proxy');
@@ -10,12 +12,12 @@ const proxyType: ProxyType = ['http', 'https', 'socks5'];
const items: SettingItem<Proxy>[] = [
{
configKey: 'enable',
label: 'Enable',
label: t('config.proxyset.enable'),
type: 'switch',
},
{
configKey: 'type',
label: 'Proxy Type',
label: t('config.proxyset.type'),
type: 'select',
prop: {
items: proxyType,
@@ -24,7 +26,7 @@ const items: SettingItem<Proxy>[] = [
},
{
configKey: 'host',
label: 'Host',
label: t('config.proxyset.host'),
type: 'input',
prop: {
type: 'text',
@@ -33,7 +35,7 @@ const items: SettingItem<Proxy>[] = [
},
{
configKey: 'port',
label: 'Port',
label: t('config.proxyset.port'),
type: 'input',
prop: {
type: 'text',
@@ -42,7 +44,7 @@ const items: SettingItem<Proxy>[] = [
},
{
configKey: 'username',
label: 'Username',
label: t('config.proxyset.username'),
type: 'input',
prop: {
type: 'text',
@@ -51,7 +53,7 @@ const items: SettingItem<Proxy>[] = [
},
{
configKey: 'password',
label: 'Password',
label: t('config.proxyset.password'),
type: 'input',
prop: {
type: 'text',
@@ -62,7 +64,7 @@ const items: SettingItem<Proxy>[] = [
</script>
<template>
<ab-fold-panel title="Proxy Setting">
<ab-fold-panel :title="$t('config.proxyset.title')">
<div space-y-12px>
<ab-setting
v-for="i in items"

View File

@@ -0,0 +1,28 @@
import { createI18n } from 'vue-i18n';
import enUS from './lang/en-US.json';
import zhCN from './lang/zh-CN.json';
const messages = {
'en-US': enUS,
'zh-CN': zhCN,
};
// Default language is the same as last setting (undefined is browser language)
let lang = localStorage.getItem('lang');
if (lang === null) {
const navLang = navigator.language;
const localLang = navLang || false;
lang = localLang || 'en-US';
}
localStorage.setItem('lang', lang);
const i18n = createI18n({
legacy: false,
locale: lang,
globalInjection: true,
silentTranslationWarn: true,
globalInstall: true,
messages,
});
export default i18n;

View File

@@ -0,0 +1,132 @@
{
"login": {
"title": "Login",
"username": "Username",
"password": "Password",
"loginbtn": "Login",
"default": "Default"
},
"sidebar": {
"title": "Menu",
"homepage": "HomePage",
"player": "Player",
"log": "Log",
"config": "Config",
"logout": "Logout",
"downloader": "Downloader",
"calendar": "Calendar"
},
"topbar": {
"start": "Start",
"pause": "Pause",
"restart": "Restart",
"shutdown": "Shutdown",
"resetrule": "Reset Rule",
"profile": {
"title": "Profile",
"poptitle": "Change Account",
"username": "Username",
"password": "Password",
"updatebtn": "Update"
},
"add": {
"title": "Add Bangumi",
"rsslink": "RSS Link",
"placeholder": "Please enter the RSS link",
"analyse": "Analyse"
}
},
"homepage": {
"title": "Bangumi List",
"rule": {
"officaltitle": "Official Title",
"year": "Year",
"season": "Season",
"offset": "Offset",
"exclude": "Exclude",
"enable": "Enable",
"disable": "Disable",
"delete": "Delete",
"apply": "Apply",
"yesbtn": "Yes",
"nobtn": "No",
"enablehit": "Do you want to enable this rule?",
"deletehit": "Delete Local File?",
"enablerule": "Enable Rule",
"editrule": "Edit Rule"
}
},
"player": {
"title": "Player",
"hit": "Please set up the media player"
},
"log": {
"title": "Log",
"reset": "Reset",
"copy": "Copy",
"contactinfo": "Contact Infomation",
"go": "Go",
"join": "Join",
"bugrepo": "Bug Report"
},
"config": {
"title": "Config",
"normalset": {
"title": "Normal Setting",
"rssintvl": "Interval Time of Rss",
"renameintvl": "Interval Time of Rename",
"webport": "WebUI Port",
"debug": "Debug"
},
"parserset": {
"title": "Parser Setting",
"enable": "Enable",
"source": "Source",
"token": "Token",
"url": "Custom Url",
"language": "Language",
"type": "Parser Type",
"exclude": "Exclude"
},
"downloaderset": {
"title": "Downloader Setting",
"type": "Downloader Type",
"host": "Host",
"username": "Username",
"password": "Password",
"path": "Download Path",
"ssl": "SSL"
},
"manageset": {
"title": "Manage Setting",
"enable": "Enable",
"method": "Rename Method",
"eps": "EPS complete",
"grouptag": "Add Group Tag",
"deletebadtorr": "Delete Bad Torrent"
},
"notificationset": {
"title": "Notification Setting",
"enable": "Enable",
"type": "Type",
"token": "Token",
"chatid": "Chat ID"
},
"proxyset": {
"title": "Proxy Setting",
"enable": "Enable",
"type": "Proxy Type",
"host": "Host",
"port": "Port",
"username": "Username",
"password": "Password"
},
"mediaplayerset": {
"title": "Media Player Setting",
"type": "type",
"url": "url"
},
"cancel": "Cancel",
"apply": "Apply"
}
}

View File

@@ -0,0 +1,132 @@
{
"login": {
"title": "登录",
"username": "用户名",
"password": "密码",
"loginbtn": "登录",
"default": "默认账号密码 "
},
"sidebar": {
"title": "菜单",
"homepage": "主页",
"player": "播放器",
"log": "日志",
"config": "设置",
"logout": "退出",
"calendar": "日历",
"downloader": "下载器"
},
"topbar": {
"start": "启动",
"pause": "暂停",
"restart": "重启",
"shutdown": "关闭",
"resetrule": "重置规则",
"profile": {
"title": "账户资料",
"poptitle": "修改账户信息",
"username": "用户名",
"password": "密码",
"updatebtn": "更新"
},
"add": {
"title": "添加番剧",
"rsslink": "RSS链接",
"placeholder": "请输入RSS链接",
"analyse": "分析"
}
},
"homepage": {
"title": "番剧列表",
"rule": {
"officaltitle": "官方名称",
"year": "年份",
"season": "季度",
"offset": "偏移",
"exclude": "排除",
"enable": "启用",
"disable": "禁用",
"delete": "删除",
"apply": "应用",
"yesbtn": "是",
"nobtn": "否",
"enablehit": "确定要让规则生效吗?",
"deletehit": "删除本地文件?",
"enablerule": "启用规则",
"editrule": "编辑规则"
}
},
"player": {
"title": "播放器",
"hit": "请设置播放器地址"
},
"log": {
"title": "日志",
"reset": "重置",
"copy": "复制",
"contactinfo": "联系方式",
"go": "访问",
"join": "加入",
"bugrepo": "Bug反馈"
},
"config": {
"title": "系统设置",
"normalset": {
"title": "一般设置",
"rssintvl": "RSS间隔",
"renameintvl": "重命名间隔",
"webport": "网页端口",
"debug": "调试"
},
"parserset": {
"title": "解析设置",
"enable": "启用",
"source": "数据源",
"token": "Token",
"url": "自定义网址",
"language": "语言",
"type": "解析类型",
"exclude": "排除"
},
"downloaderset": {
"title": "下载设置",
"type": "下载器类型",
"host": "下载器地址",
"username": "用户名",
"password": "密码",
"path": "下载地址",
"ssl": "SSL"
},
"manageset": {
"title": "番剧管理设置",
"enable": "启用",
"method": "重命名方式",
"eps": "EPS完成",
"grouptag": "添加组标签",
"deletebadtorr": "删除坏种"
},
"notificationset": {
"title": "推送设置",
"enable": "启用",
"type": "类型",
"token": "Token",
"chatid": "Chat ID"
},
"proxyset": {
"title": "代理设置",
"enable": "启用",
"type": "类型",
"host": "地址",
"port": "端口",
"username": "用户名",
"password": "密码"
},
"mediaplayerset": {
"title": "播放器设置",
"type": "类型",
"url": "播放器地址"
},
"cancel": "取消",
"apply": "应用"
}
}

View File

@@ -1,6 +1,7 @@
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import { router } from './router';
import i18n from './locales';
import App from './App.vue';
import '@unocss/reset/tailwind-compat.css';
@@ -11,4 +12,5 @@ const pinia = createPinia();
const app = createApp(App);
app.use(router);
app.use(pinia);
app.use(i18n);
app.mount('#app');

View File

@@ -13,15 +13,11 @@ definePage({
<ab-sidebar />
<div layout-content>
<ab-page-title :title="$route.name"></ab-page-title>
<div overflow-auto mt-12px flex-grow>
<RouterView v-slot="{ Component }">
<KeepAlive>
<component :is="Component" />
</KeepAlive>
</RouterView>
</div>
<RouterView v-slot="{ Component }">
<KeepAlive>
<component :is="Component" />
</KeepAlive>
</RouterView>
</div>
</main>
</div>

View File

@@ -93,25 +93,28 @@ definePage({
</script>
<template>
<div flex="~ wrap" gap-y-12px gap-x-50px>
<ab-bangumi-card
v-for="i in data"
:key="i.id"
:class="[i.deleted && 'grayscale']"
:poster="i.poster_link ?? ''"
:name="i.official_title"
:season="i.season"
@click="() => open(i)"
></ab-bangumi-card>
<ab-page-title :title="$t('homepage.title')"></ab-page-title>
<div overflow-auto mt-12px flex-grow>
<div flex="~ wrap" gap-y-12px gap-x-50px>
<ab-bangumi-card
v-for="i in data"
:key="i.id"
:class="[i.deleted && 'grayscale']"
:poster="i.poster_link ?? ''"
:name="i.official_title"
:season="i.season"
@click="() => open(i)"
></ab-bangumi-card>
<ab-edit-rule
v-model:show="editRule.show"
v-model:rule="editRule.item"
@enable="(id) => enableRule(id)"
@delete-file="
(type, { id, deleteFile }) => ruleManage(type, id, deleteFile)
"
@apply="(rule) => updateRule(rule)"
></ab-edit-rule>
<ab-edit-rule
v-model:show="editRule.show"
v-model:rule="editRule.item"
@enable="(id) => enableRule(id)"
@delete-file="
(type, { id, deleteFile }) => ruleManage(type, id, deleteFile)
"
@apply="(rule) => updateRule(rule)"
></ab-edit-rule>
</div>
</div>
</template>

View File

@@ -9,30 +9,35 @@ definePage({
</script>
<template>
<div h-full flex="~ col">
<div grid="~ cols-2" gap-20px mb-auto>
<div space-y-20px>
<config-normal></config-normal>
<ab-page-title :title="$t('config.title')"></ab-page-title>
<div overflow-auto mt-12px flex-grow>
<div h-full flex="~ col">
<div grid="~ cols-2" gap-20px mb-auto>
<div space-y-20px>
<config-normal></config-normal>
<config-parser></config-parser>
<config-parser></config-parser>
<config-download></config-download>
<config-download></config-download>
<config-manage></config-manage>
<config-manage></config-manage>
</div>
<div space-y-20px>
<config-notification></config-notification>
<config-proxy></config-proxy>
<config-player></config-player>
</div>
</div>
<div space-y-20px>
<config-notification></config-notification>
<config-proxy></config-proxy>
<config-player></config-player>
<div fx-cer justify-end gap-8px mt-20px>
<ab-button type="warn" @click="getConfig">{{
$t('config.cancel')
}}</ab-button>
<ab-button @click="setConfig">{{ $t('config.apply') }}</ab-button>
</div>
</div>
<div fx-cer justify-end gap-8px mt-20px>
<ab-button type="warn" @click="getConfig">Cancel</ab-button>
<ab-button @click="setConfig">Apply</ab-button>
</div>
</div>
</template>

View File

@@ -16,96 +16,101 @@ definePage({
</script>
<template>
<div flex="~ wrap" gap-12px>
<ab-container title="Log" w-660px grow>
<div
rounded-10px
border="1px solid black"
overflow-auto
p-10px
max-h-60vh
>
<pre text-main>{{ log }}</pre>
</div>
<ab-page-title :title="$t('log.title')"></ab-page-title>
<div overflow-auto mt-12px flex-grow>
<div flex="~ wrap" gap-12px>
<ab-container :title="$t('log.title')" w-660px grow>
<div
rounded-10px
border="1px solid black"
overflow-auto
p-10px
max-h-60vh
>
<pre text-main>{{ log }}</pre>
</div>
<div flex="~ justify-end" space-x-10px mt-12px>
<ab-button type="warn" size="small" @click="reset">Reset</ab-button>
<ab-button size="small" @click="copy">Copy</ab-button>
</div>
</ab-container>
<div grow w-500px space-y-20px>
<ab-container title="Contact Infomation">
<div space-y-12px>
<ab-label label="Github">
<ab-button
size="small"
link="https://github.com/EstrellaXD/Auto_Bangumi"
target="_blank"
>
Go
</ab-button>
</ab-label>
<ab-label label="WebUI Repo">
<ab-button
size="small"
link="https://github.com/Rewrite0/Auto_Bangumi_WebUI"
target="_blank"
>
Go
</ab-button>
</ab-label>
<div line></div>
<ab-label label="Twitter">
<ab-button
size="small"
link="https://twitter.com/Estrella_Pan"
target="_blank"
>
Go
</ab-button>
</ab-label>
<ab-label label="Telegram Group">
<ab-button
size="small"
link="https://t.me/autobangumi"
target="_blank"
>
Join
</ab-button>
</ab-label>
<div flex="~ justify-end" space-x-10px mt-12px>
<ab-button type="warn" size="small" @click="reset">{{
$t('log.reset')
}}</ab-button>
<ab-button size="small" @click="copy">{{ $t('log.copy') }}</ab-button>
</div>
</ab-container>
<ab-container title="Bug Report">
<div space-y-12px>
<ab-button
mx-auto
text-16px
w-300px
h-46px
rounded-10px
link="https://github.com/EstrellaXD/Auto_Bangumi/issues"
>Github Issue</ab-button
>
<div grow w-500px space-y-20px>
<ab-container :title="$t('log.contactinfo')">
<div space-y-12px>
<ab-label label="Github">
<ab-button
size="small"
link="https://github.com/EstrellaXD/Auto_Bangumi"
target="_blank"
>
{{ $t('log.go') }}
</ab-button>
</ab-label>
<div line></div>
<ab-label label="WebUI Repo">
<ab-button
size="small"
link="https://github.com/Rewrite0/Auto_Bangumi_WebUI"
target="_blank"
>
{{ $t('log.go') }}
</ab-button>
</ab-label>
<ab-button
mx-auto
text-16px
w-300px
h-46px
rounded-10px
link="mailto:estrellaxd05@gmail.com"
>Email Contact</ab-button
>
</div>
</ab-container>
<div line></div>
<ab-label label="Twitter">
<ab-button
size="small"
link="https://twitter.com/Estrella_Pan"
target="_blank"
>
{{ $t('log.go') }}
</ab-button>
</ab-label>
<ab-label label="Telegram Group">
<ab-button
size="small"
link="https://t.me/autobangumi"
target="_blank"
>
{{ $t('log.join') }}
</ab-button>
</ab-label>
</div>
</ab-container>
<ab-container :title="$t('log.bugrepo')">
<div space-y-12px>
<ab-button
mx-auto
text-16px
w-300px
h-46px
rounded-10px
link="https://github.com/EstrellaXD/Auto_Bangumi/issues"
>Github Issue</ab-button
>
<div line></div>
<ab-button
mx-auto
text-16px
w-300px
h-46px
rounded-10px
link="mailto:estrellaxd05@gmail.com"
>Email Contact</ab-button
>
</div>
</ab-container>
</div>
</div>
</div>
</template>

View File

@@ -7,22 +7,24 @@ const { url } = storeToRefs(usePlayerStore());
</script>
<template>
<template v-if="url === ''">
<div wh-full f-cer text-h1 text-primary>
<RouterLink to="/config" hover:underline
>Please set up the media player</RouterLink
>
</div>
</template>
<iframe
v-else
:src="url"
frameborder="0"
allowfullscreen="true"
w-full
h-full
flex-1
rounded-12px
></iframe>
<ab-page-title :title="$t('player.title')"></ab-page-title>
<div overflow-auto mt-12px flex-grow>
<template v-if="url === ''">
<div wh-full f-cer text-h1 text-primary>
<RouterLink to="/config" hover:underline>{{
$t('player.hit')
}}</RouterLink>
</div>
</template>
<iframe
v-else
:src="url"
frameborder="0"
allowfullscreen="true"
w-full
h-full
flex-1
rounded-12px
></iframe>
</div>
</template>

View File

@@ -8,9 +8,9 @@ definePage({
<template>
<div f-cer layout-container>
<ab-container title="Login" w-365px>
<ab-container :title="$t('login.title')" w-365px>
<div space-y-16px>
<ab-label label="Username">
<ab-label :label="$t('login.username')">
<input
v-model="user.username"
type="text"
@@ -19,7 +19,7 @@ definePage({
/>
</ab-label>
<ab-label label="Password">
<ab-label :label="$t('login.password')">
<input
v-model="user.password"
type="password"
@@ -32,13 +32,15 @@ definePage({
<div line></div>
<div flex="~ justify-end">
<ab-button size="small" @click="login">Login</ab-button>
<ab-button size="small" @click="login">{{
$t('login.loginbtn')
}}</ab-button>
</div>
</div>
</ab-container>
<div bg="#C7C4AB" text-white rounded-4px py-4px px-2em text-main>
<div>Default: admin adminadmin</div>
<div>{{ $t('login.default') }}: admin adminadmin</div>
</div>
</div>
</template>