mirror of
https://github.com/ayangweb/BongoCat.git
synced 2026-03-12 17:51:48 +08:00
feat: 新增「通用设置 > 外观设置 > 语言」配置项 (#645)
This commit is contained in:
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -51,5 +51,9 @@
|
||||
],
|
||||
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"typescript.tsdk": "./node_modules/typescript/lib"
|
||||
"typescript.tsdk": "./node_modules/typescript/lib",
|
||||
|
||||
"i18n-ally.localesPaths": ["src/locales"],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.displayLanguage": "zh-CN"
|
||||
}
|
||||
|
||||
26
Cargo.lock
generated
26
Cargo.lock
generated
@@ -466,6 +466,7 @@ dependencies = [
|
||||
"tauri-plugin-dialog",
|
||||
"tauri-plugin-fs",
|
||||
"tauri-plugin-global-shortcut",
|
||||
"tauri-plugin-locale",
|
||||
"tauri-plugin-log",
|
||||
"tauri-plugin-macos-permissions",
|
||||
"tauri-plugin-opener",
|
||||
@@ -972,6 +973,18 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "current_locale"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0be8ddcccda8be68d8e31a421ceea7c79857404daa052434ae30ce2f402cd10"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.11"
|
||||
@@ -5018,6 +5031,19 @@ dependencies = [
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-locale"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5686c1fe8fb748c45ba0b516db42f78dd6fde91b16bc5248de438eff8d2e6abd"
|
||||
dependencies = [
|
||||
"current_locale",
|
||||
"serde",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-log"
|
||||
version = "2.4.0"
|
||||
|
||||
@@ -43,8 +43,10 @@
|
||||
"pinia": "^3.0.3",
|
||||
"pixi-live2d-display": "^0.4.0",
|
||||
"pixi.js": "^6.5.10",
|
||||
"tauri-plugin-locale-api": "^2.0.1",
|
||||
"tauri-plugin-macos-permissions-api": "^2.3.0",
|
||||
"vue": "^3.5.16",
|
||||
"vue-i18n": "^11.1.12",
|
||||
"vue-markdown-render": "^2.2.1",
|
||||
"vue-router": "^4.5.1",
|
||||
"vue3-masonry-css": "^1.0.7"
|
||||
|
||||
50
pnpm-lock.yaml
generated
50
pnpm-lock.yaml
generated
@@ -74,12 +74,18 @@ importers:
|
||||
pixi.js:
|
||||
specifier: ^6.5.10
|
||||
version: 6.5.10
|
||||
tauri-plugin-locale-api:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
tauri-plugin-macos-permissions-api:
|
||||
specifier: ^2.3.0
|
||||
version: 2.3.0
|
||||
vue:
|
||||
specifier: ^3.5.16
|
||||
version: 3.5.16(typescript@5.6.3)
|
||||
vue-i18n:
|
||||
specifier: ^11.1.12
|
||||
version: 11.1.12(vue@3.5.16(typescript@5.6.3))
|
||||
vue-markdown-render:
|
||||
specifier: ^2.2.1
|
||||
version: 2.2.1(vue@3.5.16(typescript@5.6.3))
|
||||
@@ -733,6 +739,18 @@ packages:
|
||||
'@types/node':
|
||||
optional: true
|
||||
|
||||
'@intlify/core-base@11.1.12':
|
||||
resolution: {integrity: sha512-whh0trqRsSqVLNEUCwU59pyJZYpU8AmSWl8M3Jz2Mv5ESPP6kFh4juas2NpZ1iCvy7GlNRffUD1xr84gceimjg==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/message-compiler@11.1.12':
|
||||
resolution: {integrity: sha512-Fv9iQSJoJaXl4ZGkOCN1LDM3trzze0AS2zRz2EHLiwenwL6t0Ki9KySYlyr27yVOj5aVz0e55JePO+kELIvfdQ==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/shared@11.1.12':
|
||||
resolution: {integrity: sha512-Om86EjuQtA69hdNj3GQec9ZC0L0vPSAnXzB3gP/gyJ7+mA7t06d9aOAiqMZ+xEOsumGP4eEBlfl8zF2LOTzf2A==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.8':
|
||||
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
@@ -4411,6 +4429,9 @@ packages:
|
||||
resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
tauri-plugin-locale-api@2.0.1:
|
||||
resolution: {integrity: sha512-kiNcbP6ZKUpPbFseePrR9eb8kTRw8tSJ0ZBpQk4mDyGcbK3xGu0/dy7Cx8lBfC/p2MlmnyO4uRVIwta7FoV6eQ==}
|
||||
|
||||
tauri-plugin-macos-permissions-api@2.3.0:
|
||||
resolution: {integrity: sha512-pZp0jmDySysBqrGueknd1a7Rr4XEO9aXpMv9TNrT2PDHP0MSH20njieOagsFYJ5MCVb8A+wcaK0cIkjUC2dOww==}
|
||||
|
||||
@@ -4652,6 +4673,12 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.4.37
|
||||
|
||||
vue-i18n@11.1.12:
|
||||
resolution: {integrity: sha512-BnstPj3KLHLrsqbVU2UOrPmr0+Mv11bsUZG0PyCOzsawCivk8W00GMXHeVUWIDOgNaScCuZah47CZFE+Wnl8mw==}
|
||||
engines: {node: '>= 16'}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
vue-markdown-render@2.2.1:
|
||||
resolution: {integrity: sha512-XkYnC0PMdbs6Vy6j/gZXSvCuOS0787Se5COwXlepRqiqPiunyCIeTPQAO2XnB4Yl04EOHXwLx5y6IuszMWSgyQ==}
|
||||
peerDependencies:
|
||||
@@ -5354,6 +5381,18 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/node': 22.15.29
|
||||
|
||||
'@intlify/core-base@11.1.12':
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 11.1.12
|
||||
'@intlify/shared': 11.1.12
|
||||
|
||||
'@intlify/message-compiler@11.1.12':
|
||||
dependencies:
|
||||
'@intlify/shared': 11.1.12
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@intlify/shared@11.1.12': {}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.8':
|
||||
dependencies:
|
||||
'@jridgewell/set-array': 1.2.1
|
||||
@@ -9437,6 +9476,10 @@ snapshots:
|
||||
|
||||
tapable@2.2.2: {}
|
||||
|
||||
tauri-plugin-locale-api@2.0.1:
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.5.0
|
||||
|
||||
tauri-plugin-macos-permissions-api@2.3.0:
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.5.0
|
||||
@@ -9710,6 +9753,13 @@ snapshots:
|
||||
dependencies:
|
||||
vue: 3.5.16(typescript@5.6.3)
|
||||
|
||||
vue-i18n@11.1.12(vue@3.5.16(typescript@5.6.3)):
|
||||
dependencies:
|
||||
'@intlify/core-base': 11.1.12
|
||||
'@intlify/shared': 11.1.12
|
||||
'@vue/devtools-api': 6.6.4
|
||||
vue: 3.5.16(typescript@5.6.3)
|
||||
|
||||
vue-markdown-render@2.2.1(vue@3.5.16(typescript@5.6.3)):
|
||||
dependencies:
|
||||
markdown-it: 13.0.2
|
||||
|
||||
@@ -37,6 +37,7 @@ tauri-plugin-fs = "2"
|
||||
fs_extra = "1"
|
||||
tauri-plugin-clipboard-manager = "2"
|
||||
tauri-plugin-global-shortcut = "2"
|
||||
tauri-plugin-locale = "2"
|
||||
rdev = { git = "https://github.com/kunkunsh/rdev" }
|
||||
gilrs = { git = "https://github.com/ayangweb/gilrs", default-features = false, features = ["xinput"] }
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
"clipboard-manager:allow-write-text",
|
||||
"global-shortcut:allow-is-registered",
|
||||
"global-shortcut:allow-register",
|
||||
"global-shortcut:allow-unregister"
|
||||
"global-shortcut:allow-unregister",
|
||||
"locale:default"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_clipboard_manager::init())
|
||||
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
|
||||
.plugin(tauri_plugin_locale::init())
|
||||
.on_window_event(|window, event| match event {
|
||||
WindowEvent::CloseRequested { api, .. } => {
|
||||
let _ = window.hide();
|
||||
|
||||
17
src/App.vue
17
src/App.vue
@@ -4,16 +4,17 @@ import { error } from '@tauri-apps/plugin-log'
|
||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { ConfigProvider, theme } from 'ant-design-vue'
|
||||
import zhCN from 'ant-design-vue/es/locale/zh_CN'
|
||||
import { isString } from 'es-toolkit'
|
||||
import isURL from 'is-url'
|
||||
import { onMounted } from 'vue'
|
||||
import { onMounted, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { RouterView } from 'vue-router'
|
||||
|
||||
import { useTauriListen } from './composables/useTauriListen'
|
||||
import { useThemeVars } from './composables/useThemeVars'
|
||||
import { useWindowState } from './composables/useWindowState'
|
||||
import { LISTEN_KEY } from './constants'
|
||||
import { LANGUAGE, LISTEN_KEY } from './constants'
|
||||
import { getAntdLocale } from './locales/index.ts'
|
||||
import { hideWindow, showWindow } from './plugins/window'
|
||||
import { useAppStore } from './stores/app'
|
||||
import { useCatStore } from './stores/cat'
|
||||
@@ -30,6 +31,7 @@ const shortcutStore = useShortcutStore()
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
const { isRestored, restoreState } = useWindowState()
|
||||
const { darkAlgorithm, defaultAlgorithm } = theme
|
||||
const { locale } = useI18n()
|
||||
|
||||
onMounted(async () => {
|
||||
generateColorVars()
|
||||
@@ -39,10 +41,15 @@ onMounted(async () => {
|
||||
await modelStore.$tauri.start()
|
||||
await modelStore.init()
|
||||
await catStore.$tauri.start()
|
||||
catStore.init()
|
||||
await generalStore.$tauri.start()
|
||||
await generalStore.init()
|
||||
await shortcutStore.$tauri.start()
|
||||
await restoreState()
|
||||
catStore.init()
|
||||
})
|
||||
|
||||
watch(() => generalStore.appearance.language, (value) => {
|
||||
locale.value = value ?? LANGUAGE.EN_US
|
||||
})
|
||||
|
||||
useTauriListen(LISTEN_KEY.SHOW_WINDOW, ({ payload }) => {
|
||||
@@ -82,7 +89,7 @@ useEventListener('click', (event) => {
|
||||
|
||||
<template>
|
||||
<ConfigProvider
|
||||
:locale="zhCN"
|
||||
:locale="getAntdLocale(generalStore.appearance.language)"
|
||||
:theme="{
|
||||
algorithm: generalStore.appearance.isDark ? darkAlgorithm : defaultAlgorithm,
|
||||
}"
|
||||
|
||||
@@ -110,7 +110,7 @@ function handleKeyUp(event: KeyboardEvent) {
|
||||
@mouseover="isHovering = true"
|
||||
>
|
||||
<span v-if="pressedKeys.length === 0">
|
||||
{{ isFocusing ? '按下录制快捷键' : '点击录制快捷键' }}
|
||||
{{ isFocusing ? $t('components.proShortcut.hints.pressRecordShortcut') : $t('components.proShortcut.hints.clickRecordShortcut') }}
|
||||
</span>
|
||||
|
||||
<span class="text-primary font-bold">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CheckMenuItem, MenuItem, PredefinedMenuItem, Submenu } from '@tauri-apps/api/menu'
|
||||
import { range } from 'es-toolkit'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { showWindow } from '@/plugins/window'
|
||||
import { useCatStore } from '@/stores/cat'
|
||||
@@ -7,13 +8,14 @@ import { isMac } from '@/utils/platform'
|
||||
|
||||
export function useSharedMenu() {
|
||||
const catStore = useCatStore()
|
||||
const { t } = useI18n()
|
||||
|
||||
const getScaleMenuItems = async () => {
|
||||
const options = range(50, 151, 25)
|
||||
|
||||
const items = options.map((item) => {
|
||||
return CheckMenuItem.new({
|
||||
text: item === 100 ? '默认' : `${item}%`,
|
||||
text: `${item}%`,
|
||||
checked: catStore.window.scale === item,
|
||||
action: () => {
|
||||
catStore.window.scale = item
|
||||
@@ -59,30 +61,30 @@ export function useSharedMenu() {
|
||||
const getSharedMenu = async () => {
|
||||
return await Promise.all([
|
||||
MenuItem.new({
|
||||
text: '偏好设置...',
|
||||
text: t('composables.useSharedMenu.labels.preference'),
|
||||
accelerator: isMac ? 'Cmd+,' : '',
|
||||
action: () => showWindow('preference'),
|
||||
}),
|
||||
MenuItem.new({
|
||||
text: catStore.window.visible ? '隐藏猫咪' : '显示猫咪',
|
||||
text: catStore.window.visible ? t('composables.useSharedMenu.labels.hideCat') : t('composables.useSharedMenu.labels.showCat'),
|
||||
action: () => {
|
||||
catStore.window.visible = !catStore.window.visible
|
||||
},
|
||||
}),
|
||||
PredefinedMenuItem.new({ item: 'Separator' }),
|
||||
CheckMenuItem.new({
|
||||
text: '窗口穿透',
|
||||
text: t('composables.useSharedMenu.labels.passThrough'),
|
||||
checked: catStore.window.passThrough,
|
||||
action: () => {
|
||||
catStore.window.passThrough = !catStore.window.passThrough
|
||||
},
|
||||
}),
|
||||
Submenu.new({
|
||||
text: '窗口尺寸',
|
||||
text: t('composables.useSharedMenu.labels.windowSize'),
|
||||
items: await getScaleMenuItems(),
|
||||
}),
|
||||
Submenu.new({
|
||||
text: '不透明度',
|
||||
text: t('composables.useSharedMenu.labels.opacity'),
|
||||
items: await getOpacityMenuItems(),
|
||||
}),
|
||||
])
|
||||
|
||||
@@ -9,6 +9,7 @@ import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
import { exit, relaunch } from '@tauri-apps/plugin-process'
|
||||
import { watchDebounced } from '@vueuse/core'
|
||||
import { watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { GITHUB_LINK, LISTEN_KEY } from '../constants'
|
||||
import { showWindow } from '../plugins/window'
|
||||
@@ -17,14 +18,17 @@ import { isMac } from '../utils/platform'
|
||||
import { useSharedMenu } from './useSharedMenu'
|
||||
|
||||
import { useCatStore } from '@/stores/cat'
|
||||
import { useGeneralStore } from '@/stores/general'
|
||||
|
||||
const TRAY_ID = 'BONGO_CAT_TRAY'
|
||||
|
||||
export function useTray() {
|
||||
const catStore = useCatStore()
|
||||
const generalStore = useGeneralStore()
|
||||
const { getSharedMenu } = useSharedMenu()
|
||||
const { t } = useI18n()
|
||||
|
||||
watch([() => catStore.window.visible, () => catStore.window.passThrough], () => {
|
||||
watch([() => catStore.window.visible, () => catStore.window.passThrough, () => generalStore.appearance.language], () => {
|
||||
updateTrayMenu()
|
||||
})
|
||||
|
||||
@@ -68,7 +72,7 @@ export function useTray() {
|
||||
...await getSharedMenu(),
|
||||
PredefinedMenuItem.new({ item: 'Separator' }),
|
||||
MenuItem.new({
|
||||
text: '检查更新',
|
||||
text: t('composables.useTray.checkUpdate'),
|
||||
action: () => {
|
||||
showWindow()
|
||||
|
||||
@@ -76,20 +80,20 @@ export function useTray() {
|
||||
},
|
||||
}),
|
||||
MenuItem.new({
|
||||
text: '开源地址',
|
||||
text: t('composables.useTray.openSource'),
|
||||
action: () => openUrl(GITHUB_LINK),
|
||||
}),
|
||||
PredefinedMenuItem.new({ item: 'Separator' }),
|
||||
MenuItem.new({
|
||||
text: `版本 ${appVersion}`,
|
||||
text: `${t('composables.useTray.version')} ${appVersion}`,
|
||||
enabled: false,
|
||||
}),
|
||||
MenuItem.new({
|
||||
text: '重启应用',
|
||||
text: t('composables.useTray.restartApp'),
|
||||
action: relaunch,
|
||||
}),
|
||||
MenuItem.new({
|
||||
text: '退出应用',
|
||||
text: t('composables.useTray.quitApp'),
|
||||
accelerator: isMac ? 'Cmd+Q' : '',
|
||||
action: () => exit(0),
|
||||
}),
|
||||
|
||||
@@ -16,3 +16,9 @@ export const INVOKE_KEY = {
|
||||
START_GAMEPAD_LISTING: 'start_gamepad_listing',
|
||||
STOP_GAMEPAD_LISTING: 'stop_gamepad_listing',
|
||||
}
|
||||
|
||||
export const LANGUAGE = {
|
||||
ZH_CN: 'zh-CN',
|
||||
EN_US: 'en-US',
|
||||
VI_VN: 'vi-VN',
|
||||
} as const
|
||||
|
||||
14
src/locales/en-US.json
Normal file
14
src/locales/en-US.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"pages": {
|
||||
"main": {
|
||||
"hints": {
|
||||
"redrawing": "Redrawing..."
|
||||
}
|
||||
},
|
||||
"preference": {}
|
||||
},
|
||||
"hooks": {},
|
||||
"components": {
|
||||
|
||||
}
|
||||
}
|
||||
34
src/locales/index.ts
Normal file
34
src/locales/index.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { Language } from '@/stores/general'
|
||||
import type { Locale as AntdLocale } from 'ant-design-vue/es/locale'
|
||||
|
||||
import antdEnUS from 'ant-design-vue/locale/en_US'
|
||||
import antdViVN from 'ant-design-vue/locale/vi_VN'
|
||||
import antdZhCN from 'ant-design-vue/locale/zh_CN'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
import enUS from './en-US.json'
|
||||
import viVN from './vi-VN.json'
|
||||
import zhCN from './zh-CN.json'
|
||||
|
||||
import { LANGUAGE } from '@/constants'
|
||||
|
||||
export const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: LANGUAGE.EN_US,
|
||||
fallbackLocale: LANGUAGE.EN_US,
|
||||
messages: {
|
||||
[LANGUAGE.ZH_CN]: zhCN,
|
||||
[LANGUAGE.EN_US]: enUS,
|
||||
[LANGUAGE.VI_VN]: viVN,
|
||||
},
|
||||
})
|
||||
|
||||
export function getAntdLocale(language: Language = LANGUAGE.EN_US) {
|
||||
const antdLanguage: Record<Language, AntdLocale> = {
|
||||
[LANGUAGE.ZH_CN]: antdZhCN,
|
||||
[LANGUAGE.EN_US]: antdEnUS,
|
||||
[LANGUAGE.VI_VN]: antdViVN,
|
||||
}
|
||||
|
||||
return antdLanguage[language]
|
||||
}
|
||||
14
src/locales/vi-VN.json
Normal file
14
src/locales/vi-VN.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"pages": {
|
||||
"main": {
|
||||
"hints": {
|
||||
"redrawing": "Redrawing..."
|
||||
}
|
||||
},
|
||||
"preference": {}
|
||||
},
|
||||
"hooks": {},
|
||||
"components": {
|
||||
|
||||
}
|
||||
}
|
||||
144
src/locales/zh-CN.json
Normal file
144
src/locales/zh-CN.json
Normal file
@@ -0,0 +1,144 @@
|
||||
{
|
||||
"pages": {
|
||||
"main": {
|
||||
"hints": {
|
||||
"redrawing": "重绘中..."
|
||||
}
|
||||
},
|
||||
"preference": {
|
||||
"cat": {
|
||||
"title": "猫咪设置",
|
||||
"labels": {
|
||||
"modelSettings": "模型设置",
|
||||
"mirrorMode": "镜像模式",
|
||||
"singleMode": "单键模式",
|
||||
"mouseMirror": "鼠标镜像",
|
||||
"windowSettings": "窗口设置",
|
||||
"passThrough": "窗口穿透",
|
||||
"alwaysOnTop": "窗口置顶",
|
||||
"windowSize": "窗口尺寸",
|
||||
"windowRadius": "窗口圆角",
|
||||
"opacity": "不透明度"
|
||||
},
|
||||
"hints": {
|
||||
"mirrorMode": "启用后,模型将水平镜像翻转。",
|
||||
"singleMode": "启用后,每只手只显示最后按下的一个按键。",
|
||||
"mouseMirror": "启用后,鼠标将镜像跟随手部移动。",
|
||||
"passThrough": "启用后,窗口不影响对其他应用程序的操作。",
|
||||
"alwaysOnTop": "启用后,窗口始终显示在其他应用程序上方。",
|
||||
"windowSize": "将鼠标移至窗口边缘,或按住 Shift 并右键拖动,也可以调整窗口大小。"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"title": "通用设置",
|
||||
"labels": {
|
||||
"appSettings": "应用设置",
|
||||
"launchOnStartup": "开机自启动",
|
||||
"showTaskbarIcon": "显示任务栏图标",
|
||||
"appearanceSettings": "外观设置",
|
||||
"themeMode": "主题模式",
|
||||
"language": "语言",
|
||||
"updateSettings": "更新设置",
|
||||
"autoCheckUpdate": "自动检查更新",
|
||||
"permissionsSettings": "权限设置",
|
||||
"inputMonitoringPermission": "输入监控权限"
|
||||
},
|
||||
"options": {
|
||||
"auto": "跟随系统",
|
||||
"lightMode": "亮色模式",
|
||||
"darkMode": "暗色模式"
|
||||
},
|
||||
"hints": {
|
||||
"showTaskbarIcon": "启用后,即可通过 OBS Studio 捕获窗口。",
|
||||
"inputMonitoringPermission": "开启输入监控权限,以便接收系统的键盘和鼠标事件来响应你的操作。"
|
||||
},
|
||||
"status": {
|
||||
"authorized": "已授权",
|
||||
"authorize": "去授权"
|
||||
}
|
||||
},
|
||||
"model": {
|
||||
"title": "模型管理",
|
||||
"labels": {
|
||||
"deleteModel": "删除模型"
|
||||
},
|
||||
"hints": {
|
||||
"deleteSuccess": "删除成功",
|
||||
"deleteModel": "你确定要删除此模型吗?",
|
||||
"importSuccess": "导入成功",
|
||||
"clickOrDragToImport": "点击或拖动至此区域导入"
|
||||
},
|
||||
"tooltips": {
|
||||
"createModel": "制作模型",
|
||||
"convertModel": "转换模型",
|
||||
"moreModels": "更多模型"
|
||||
}
|
||||
},
|
||||
"shortcut": {
|
||||
"title": "快捷键",
|
||||
"labels": {
|
||||
"toggleCat": "打开猫咪",
|
||||
"togglePreferences": "打开偏好设置",
|
||||
"mirrorMode": "镜像模式",
|
||||
"passThrough": "窗口穿透",
|
||||
"alwaysOnTop": "窗口置顶"
|
||||
},
|
||||
"hints": {
|
||||
"toggleCat": "切换猫咪窗口的显示与隐藏。",
|
||||
"togglePreferences": "切换偏好设置窗口的显示与隐藏。",
|
||||
"mirrorMode": "切换猫咪的镜像模式。",
|
||||
"passThrough": "切换猫咪窗口是否可穿透。",
|
||||
"alwaysOnTop": "切换猫咪窗口是否置顶。"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"title": "关于",
|
||||
"labels": {
|
||||
"aboutApp": "关于软件",
|
||||
"appLog": "软件日志",
|
||||
"version": "版本:",
|
||||
"appInfo": "软件信息",
|
||||
"openSourceAddress": "开源地址"
|
||||
},
|
||||
"hints": {
|
||||
"appInfo": "复制软件信息并提供给 Bug Issue。",
|
||||
"copySuccess": "复制成功"
|
||||
},
|
||||
"buttons": {
|
||||
"checkUpdate": "检查更新",
|
||||
"copy": "复制",
|
||||
"feedbackIssues": "反馈问题",
|
||||
"viewLog": "查看日志"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"proShortcut": {
|
||||
"hints": {
|
||||
"pressRecordShortcut": "按下录制快捷键",
|
||||
"clickRecordShortcut": "点击录制快捷键"
|
||||
},
|
||||
"updateApp": {}
|
||||
}
|
||||
},
|
||||
"composables": {
|
||||
"useSharedMenu": {
|
||||
"labels": {
|
||||
"preference": "偏好设置...",
|
||||
"hideCat": "隐藏猫咪",
|
||||
"showCat": "显示猫咪",
|
||||
"passThrough": "窗口穿透",
|
||||
"windowSize": "窗口尺寸",
|
||||
"opacity": "不透明度"
|
||||
}
|
||||
},
|
||||
"useTray": {
|
||||
"checkUpdate": "检查更新",
|
||||
"openSource": "开源地址",
|
||||
"version": "版本",
|
||||
"restartApp": "重启应用",
|
||||
"quitApp": "退出应用"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,9 @@ import { createPinia } from 'pinia'
|
||||
import { createApp } from 'vue'
|
||||
|
||||
import App from './App.vue'
|
||||
import { i18n } from './locales'
|
||||
import router from './router'
|
||||
|
||||
import 'virtual:uno.css'
|
||||
import 'ant-design-vue/dist/reset.css'
|
||||
import './assets/css/global.scss'
|
||||
@@ -11,4 +13,4 @@ import './assets/css/global.scss'
|
||||
const pinia = createPinia()
|
||||
pinia.use(createPlugin({ saveOnChange: true }))
|
||||
|
||||
createApp(App).use(router).use(pinia).mount('#app')
|
||||
createApp(App).use(router).use(pinia).use(i18n).mount('#app')
|
||||
|
||||
@@ -174,8 +174,8 @@ function handleMouseMove(event: MouseEvent) {
|
||||
v-show="resizing"
|
||||
class="flex items-center justify-center bg-black"
|
||||
>
|
||||
<span class="text-center text-5xl text-white">
|
||||
重绘中...
|
||||
<span class="text-center text-10vw text-white">
|
||||
{{ $t('pages.main.hints.redrawing') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { openPath, openUrl } from '@tauri-apps/plugin-opener'
|
||||
import { arch, platform, version } from '@tauri-apps/plugin-os'
|
||||
import { Button, message } from 'ant-design-vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import ProList from '@/components/pro-list/index.vue'
|
||||
import ProListItem from '@/components/pro-list-item/index.vue'
|
||||
@@ -15,6 +16,7 @@ import { useAppStore } from '@/stores/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const logDir = ref('')
|
||||
const { t } = useI18n()
|
||||
|
||||
onMounted(async () => {
|
||||
logDir.value = await appLogDir()
|
||||
@@ -36,7 +38,7 @@ async function copyInfo() {
|
||||
|
||||
await writeText(JSON.stringify(info, null, 2))
|
||||
|
||||
message.success('复制成功')
|
||||
message.success(t('pages.preference.about.hints.copySuccess'))
|
||||
}
|
||||
|
||||
function feedbackIssue() {
|
||||
@@ -45,16 +47,16 @@ function feedbackIssue() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProList title="关于软件">
|
||||
<ProList :title="$t('pages.preference.about.labels.aboutApp')">
|
||||
<ProListItem
|
||||
:description="`版本:v${appStore.version}`"
|
||||
:description="`${$t('pages.preference.about.labels.version')}v${appStore.version}`"
|
||||
:title="appStore.name"
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
@click="handleUpdate"
|
||||
>
|
||||
检查更新
|
||||
{{ $t('pages.preference.about.buttons.checkUpdate') }}
|
||||
</Button>
|
||||
|
||||
<template #icon>
|
||||
@@ -68,20 +70,20 @@ function feedbackIssue() {
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
description="复制软件信息并提供给 Bug Issue。"
|
||||
title="软件信息"
|
||||
:description="$t('pages.preference.about.hints.appInfo')"
|
||||
:title="$t('pages.preference.about.labels.appInfo')"
|
||||
>
|
||||
<Button @click="copyInfo">
|
||||
复制
|
||||
{{ $t('pages.preference.about.buttons.copy') }}
|
||||
</Button>
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem title="开源地址">
|
||||
<ProListItem :title="$t('pages.preference.about.labels.openSourceAddress')">
|
||||
<Button
|
||||
danger
|
||||
@click="feedbackIssue"
|
||||
>
|
||||
反馈问题
|
||||
{{ $t('pages.preference.about.buttons.feedbackIssues') }}
|
||||
</Button>
|
||||
|
||||
<template #description>
|
||||
@@ -93,10 +95,10 @@ function feedbackIssue() {
|
||||
|
||||
<ProListItem
|
||||
:description="logDir"
|
||||
title="软件日志"
|
||||
:title="$t('pages.preference.about.labels.appLog')"
|
||||
>
|
||||
<Button @click="openPath(logDir)">
|
||||
查看日志
|
||||
{{ $t('pages.preference.about.buttons.viewLog') }}
|
||||
</Button>
|
||||
</ProListItem>
|
||||
</ProList>
|
||||
|
||||
@@ -9,47 +9,47 @@ const catStore = useCatStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProList title="模型设置">
|
||||
<ProList :title="$t('pages.preference.cat.labels.modelSettings')">
|
||||
<ProListItem
|
||||
description="启用后,模型将水平镜像翻转。"
|
||||
title="镜像模式"
|
||||
:description="$t('pages.preference.cat.hints.mirrorMode')"
|
||||
:title="$t('pages.preference.cat.labels.mirrorMode')"
|
||||
>
|
||||
<Switch v-model:checked="catStore.model.mirror" />
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
description="启用后,每只手只显示最后按下的一个按键。"
|
||||
title="单键模式"
|
||||
:description="$t('pages.preference.cat.hints.singleMode')"
|
||||
:title="$t('pages.preference.cat.labels.singleMode')"
|
||||
>
|
||||
<Switch v-model:checked="catStore.model.single" />
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
description="启用后,鼠标将镜像跟随手部移动。"
|
||||
title="鼠标镜像"
|
||||
:description="$t('pages.preference.cat.hints.mouseMirror')"
|
||||
:title="$t('pages.preference.cat.labels.mouseMirror')"
|
||||
>
|
||||
<Switch v-model:checked="catStore.model.mouseMirror" />
|
||||
</ProListItem>
|
||||
</ProList>
|
||||
|
||||
<ProList title="窗口设置">
|
||||
<ProList :title="$t('pages.preference.cat.labels.windowSettings')">
|
||||
<ProListItem
|
||||
description="启用后,窗口不影响对其他应用程序的操作。"
|
||||
title="窗口穿透"
|
||||
:description="$t('pages.preference.cat.hints.passThrough')"
|
||||
:title="$t('pages.preference.cat.labels.passThrough')"
|
||||
>
|
||||
<Switch v-model:checked="catStore.window.passThrough" />
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
description="启用后,窗口始终显示在其他应用程序上方。"
|
||||
title="窗口置顶"
|
||||
:description="$t('pages.preference.cat.hints.alwaysOnTop')"
|
||||
:title="$t('pages.preference.cat.labels.alwaysOnTop')"
|
||||
>
|
||||
<Switch v-model:checked="catStore.window.alwaysOnTop" />
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
description="将鼠标移至窗口边缘,或按住 Shift 并右键拖动,也可以调整窗口大小。"
|
||||
title="窗口尺寸"
|
||||
:description="$t('pages.preference.cat.hints.windowSize')"
|
||||
:title="$t('pages.preference.cat.labels.windowSize')"
|
||||
>
|
||||
<InputNumber
|
||||
v-model:value="catStore.window.scale"
|
||||
@@ -59,7 +59,7 @@ const catStore = useCatStore()
|
||||
/>
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem title="窗口圆角">
|
||||
<ProListItem :title="$t('pages.preference.cat.labels.windowRadius')">
|
||||
<InputNumber
|
||||
v-model:value="catStore.window.radius"
|
||||
addon-after="%"
|
||||
@@ -69,7 +69,7 @@ const catStore = useCatStore()
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
title="不透明度"
|
||||
:title="$t('pages.preference.cat.labels.opacity')"
|
||||
vertical
|
||||
>
|
||||
<Slider
|
||||
|
||||
@@ -35,11 +35,11 @@ onMounted(async () => {
|
||||
<template>
|
||||
<ProList
|
||||
v-if="isMac"
|
||||
title="权限设置"
|
||||
:title="$t('pages.preference.general.labels.permissionsSettings')"
|
||||
>
|
||||
<ProListItem
|
||||
description="开启输入监控权限,以便接收系统的键盘和鼠标事件来响应你的操作。"
|
||||
title="输入监控权限"
|
||||
:description="$t('pages.preference.general.hints.inputMonitoringPermission')"
|
||||
:title="$t('pages.preference.general.labels.inputMonitoringPermission')"
|
||||
>
|
||||
<Space
|
||||
v-if="authorized"
|
||||
@@ -48,7 +48,7 @@ onMounted(async () => {
|
||||
>
|
||||
<div class="i-solar:verified-check-bold text-4.5" />
|
||||
|
||||
<span>已授权</span>
|
||||
<span>{{ $t('pages.preference.general.status.authorized') }}</span>
|
||||
</Space>
|
||||
|
||||
<Space
|
||||
@@ -59,7 +59,7 @@ onMounted(async () => {
|
||||
>
|
||||
<div class="i-solar:round-arrow-right-bold text-4.5" />
|
||||
|
||||
<span>去授权</span>
|
||||
<span>{{ $t('pages.preference.general.status.authorize') }}</span>
|
||||
</Space>
|
||||
</ProListItem>
|
||||
</ProList>
|
||||
|
||||
@@ -37,16 +37,16 @@ watch(() => generalStore.appearance.isDark, (value) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProListItem title="主题模式">
|
||||
<ProListItem :title="$t('pages.preference.general.labels.themeMode')">
|
||||
<Select v-model:value="generalStore.appearance.theme">
|
||||
<SelectOption value="auto">
|
||||
跟随系统
|
||||
{{ $t('pages.preference.general.options.auto') }}
|
||||
</SelectOption>
|
||||
<SelectOption value="light">
|
||||
亮色模式
|
||||
{{ $t('pages.preference.general.options.lightMode') }}
|
||||
</SelectOption>
|
||||
<SelectOption value="dark">
|
||||
暗色模式
|
||||
{{ $t('pages.preference.general.options.darkMode') }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
</ProListItem>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { disable, enable, isEnabled } from '@tauri-apps/plugin-autostart'
|
||||
import { Switch } from 'ant-design-vue'
|
||||
import { Select, Switch } from 'ant-design-vue'
|
||||
import { watch } from 'vue'
|
||||
|
||||
import MacosPermissions from './components/macos-permissions/index.vue'
|
||||
@@ -28,25 +28,39 @@ watch(() => generalStore.app.autostart, async (value) => {
|
||||
<template>
|
||||
<MacosPermissions />
|
||||
|
||||
<ProList title="应用设置">
|
||||
<ProListItem title="开机自启动">
|
||||
<ProList :title="$t('pages.preference.general.labels.appSettings')">
|
||||
<ProListItem :title="$t('pages.preference.general.labels.launchOnStartup')">
|
||||
<Switch v-model:checked="generalStore.app.autostart" />
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
description="启用后,即可通过 OBS Studio 捕获窗口。"
|
||||
title="显示任务栏图标"
|
||||
:description="$t('pages.preference.general.hints.showTaskbarIcon')"
|
||||
:title="$t('pages.preference.general.labels.showTaskbarIcon')"
|
||||
>
|
||||
<Switch v-model:checked="generalStore.app.taskbarVisible" />
|
||||
</ProListItem>
|
||||
</ProList>
|
||||
|
||||
<ProList title="外观设置">
|
||||
<ProList :title="$t('pages.preference.general.labels.appearanceSettings')">
|
||||
<ThemeMode />
|
||||
|
||||
<ProListItem :title="$t('pages.preference.general.labels.language')">
|
||||
<Select v-model:value="generalStore.appearance.language">
|
||||
<Select.Option value="zh-CN">
|
||||
简体中文
|
||||
</Select.Option>
|
||||
<Select.Option value="en-US">
|
||||
English
|
||||
</Select.Option>
|
||||
<Select.Option value="vi-VN">
|
||||
Tiếng Việt
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</ProListItem>
|
||||
</ProList>
|
||||
|
||||
<ProList title="更新设置">
|
||||
<ProListItem title="自动检查更新">
|
||||
<ProList :title="$t('pages.preference.general.labels.updateSettings')">
|
||||
<ProListItem :title="$t('pages.preference.general.labels.autoCheckUpdate')">
|
||||
<Switch v-model:checked="generalStore.update.autoCheck" />
|
||||
</ProListItem>
|
||||
</ProList>
|
||||
|
||||
@@ -15,7 +15,7 @@ import { FloatButton, FloatButtonGroup } from 'ant-design-vue'
|
||||
</template>
|
||||
|
||||
<FloatButton
|
||||
tooltip="制作模型"
|
||||
:tooltip="$t('pages.preference.model.tooltips.createModel')"
|
||||
@click="openUrl('https://juejin.cn/post/7509872655802269731')"
|
||||
>
|
||||
<template #icon>
|
||||
@@ -24,7 +24,7 @@ import { FloatButton, FloatButtonGroup } from 'ant-design-vue'
|
||||
</FloatButton>
|
||||
|
||||
<FloatButton
|
||||
tooltip="转换模型"
|
||||
:tooltip="$t('pages.preference.model.tooltips.convertModel')"
|
||||
@click="openUrl('https://bongocat.vteamer.cc')"
|
||||
>
|
||||
<template #icon>
|
||||
@@ -33,7 +33,7 @@ import { FloatButton, FloatButtonGroup } from 'ant-design-vue'
|
||||
</FloatButton>
|
||||
|
||||
<FloatButton
|
||||
tooltip="更多模型"
|
||||
:tooltip="$t('pages.preference.model.tooltips.moreModels')"
|
||||
@click="openUrl('https://github.com/ayangweb/Awesome-BongoCat')"
|
||||
>
|
||||
<template #icon>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { readDir } from '@tauri-apps/plugin-fs'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { onMounted, ref, useTemplateRef, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { INVOKE_KEY } from '@/constants'
|
||||
import { useModelStore } from '@/stores/model'
|
||||
@@ -18,6 +19,7 @@ const dropRef = useTemplateRef('drop')
|
||||
const dragenter = ref(false)
|
||||
const selectPaths = ref<string[]>([])
|
||||
const modelStore = useModelStore()
|
||||
const { t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
@@ -87,7 +89,7 @@ watch(selectPaths, async (paths) => {
|
||||
isPreset: false,
|
||||
})
|
||||
|
||||
message.success('导入成功')
|
||||
message.success(t('pages.preference.model.hints.importSuccess'))
|
||||
} catch (error) {
|
||||
message.error(String(error))
|
||||
}
|
||||
@@ -104,6 +106,6 @@ watch(selectPaths, async (paths) => {
|
||||
>
|
||||
<div class="i-solar:upload-square-outline text-12 text-primary" />
|
||||
|
||||
<span>点击或拖动至此区域导入</span>
|
||||
<span>{{ $t('pages.preference.model.hints.clickOrDragToImport') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { revealItemInDir } from '@tauri-apps/plugin-opener'
|
||||
import { useElementSize } from '@vueuse/core'
|
||||
import { Card, message, Popconfirm } from 'ant-design-vue'
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { MasonryGrid, MasonryGridItem } from 'vue3-masonry-css'
|
||||
|
||||
import FloatMenu from './components/float-menu/index.vue'
|
||||
@@ -18,8 +19,8 @@ import { join } from '@/utils/path'
|
||||
|
||||
const modelStore = useModelStore()
|
||||
const firstItemRef = ref<HTMLElement>()
|
||||
|
||||
const { height } = useElementSize(firstItemRef)
|
||||
const { t } = useI18n()
|
||||
|
||||
function setFirstItemRef(el: Element | ComponentPublicInstance | null, index: number) {
|
||||
if (!el || index > 0) return
|
||||
@@ -39,7 +40,7 @@ async function handleDelete(item: Model) {
|
||||
try {
|
||||
await remove(path, { recursive: true })
|
||||
|
||||
message.success('删除成功')
|
||||
message.success(t('pages.preference.model.hints.deleteSuccess'))
|
||||
} catch (error) {
|
||||
message.error(String(error))
|
||||
} finally {
|
||||
@@ -91,9 +92,9 @@ async function handleDelete(item: Model) {
|
||||
|
||||
<template v-if="!item.isPreset">
|
||||
<Popconfirm
|
||||
description="你确定要删除此模型吗?"
|
||||
:description="$t('pages.preference.model.hints.deleteModel')"
|
||||
placement="topRight"
|
||||
title="删除模型"
|
||||
:title="$t('pages.preference.model.labels.deleteModel')"
|
||||
@confirm="handleDelete(item)"
|
||||
>
|
||||
<i
|
||||
|
||||
@@ -34,35 +34,35 @@ useTauriShortcut(alwaysOnTop, () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProList title="快捷键">
|
||||
<ProList :title="$t('pages.preference.shortcut.title')">
|
||||
<ProShortcut
|
||||
v-model="shortcutStore.visibleCat"
|
||||
description="切换猫咪窗口的显示与隐藏。"
|
||||
title="打开猫咪"
|
||||
:description="$t('pages.preference.shortcut.hints.toggleCat')"
|
||||
:title="$t('pages.preference.shortcut.labels.toggleCat')"
|
||||
/>
|
||||
|
||||
<ProShortcut
|
||||
v-model="shortcutStore.visiblePreference"
|
||||
description="切换偏好设置窗口的显示与隐藏。"
|
||||
title="打开偏好设置"
|
||||
:description="$t('pages.preference.shortcut.hints.togglePreferences')"
|
||||
:title="$t('pages.preference.shortcut.labels.togglePreferences')"
|
||||
/>
|
||||
|
||||
<ProShortcut
|
||||
v-model="shortcutStore.mirrorMode"
|
||||
description="切换猫咪的镜像模式。"
|
||||
title="镜像模式"
|
||||
:description="$t('pages.preference.shortcut.hints.mirrorMode')"
|
||||
:title="$t('pages.preference.shortcut.labels.mirrorMode')"
|
||||
/>
|
||||
|
||||
<ProShortcut
|
||||
v-model="shortcutStore.penetrable"
|
||||
description="切换猫咪窗口是否可穿透。"
|
||||
title="窗口穿透"
|
||||
:description="$t('pages.preference.shortcut.hints.passThrough')"
|
||||
:title="$t('pages.preference.shortcut.labels.passThrough')"
|
||||
/>
|
||||
|
||||
<ProShortcut
|
||||
v-model="shortcutStore.alwaysOnTop"
|
||||
description="切换猫咪窗口是否置顶。"
|
||||
title="窗口置顶"
|
||||
:description="$t('pages.preference.shortcut.hints.alwaysOnTop')"
|
||||
:title="$t('pages.preference.shortcut.labels.alwaysOnTop')"
|
||||
/>
|
||||
</ProList>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Flex } from 'ant-design-vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import About from './components/about/index.vue'
|
||||
import Cat from './components/cat/index.vue'
|
||||
@@ -16,38 +17,39 @@ import { isMac } from '@/utils/platform'
|
||||
const { createTray } = useTray()
|
||||
const appStore = useAppStore()
|
||||
const current = ref(0)
|
||||
const { t } = useI18n()
|
||||
|
||||
onMounted(async () => {
|
||||
createTray()
|
||||
})
|
||||
|
||||
const menus = [
|
||||
const menus = computed(() => [
|
||||
{
|
||||
label: '猫咪设置',
|
||||
label: t('pages.preference.cat.title'),
|
||||
icon: 'i-solar:cat-bold',
|
||||
component: Cat,
|
||||
},
|
||||
{
|
||||
label: '通用设置',
|
||||
label: t('pages.preference.general.title'),
|
||||
icon: 'i-solar:settings-minimalistic-bold',
|
||||
component: General,
|
||||
},
|
||||
{
|
||||
label: '模型管理',
|
||||
label: t('pages.preference.model.title'),
|
||||
icon: 'i-solar:magic-stick-3-bold',
|
||||
component: Model,
|
||||
},
|
||||
{
|
||||
label: '快捷键',
|
||||
label: t('pages.preference.shortcut.title'),
|
||||
icon: 'i-solar:keyboard-bold',
|
||||
component: Shortcut,
|
||||
},
|
||||
{
|
||||
label: '关于',
|
||||
label: t('pages.preference.about.title'),
|
||||
icon: 'i-solar:info-circle-bold',
|
||||
component: About,
|
||||
},
|
||||
]
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import type { Theme } from '@tauri-apps/api/window'
|
||||
|
||||
import { defineStore } from 'pinia'
|
||||
import { getLocale } from 'tauri-plugin-locale-api'
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
import { LANGUAGE } from '@/constants'
|
||||
|
||||
export type Language = typeof LANGUAGE[keyof typeof LANGUAGE]
|
||||
|
||||
export interface GeneralStore {
|
||||
app: {
|
||||
autostart: boolean
|
||||
@@ -11,6 +16,7 @@ export interface GeneralStore {
|
||||
appearance: {
|
||||
theme: 'auto' | Theme
|
||||
isDark: boolean
|
||||
language?: Language
|
||||
}
|
||||
update: {
|
||||
autoCheck: boolean
|
||||
@@ -49,7 +55,17 @@ export const useGeneralStore = defineStore('general', () => {
|
||||
autoCheck: false,
|
||||
})
|
||||
|
||||
const init = () => {
|
||||
const getLanguage = async () => {
|
||||
const locale = await getLocale<Language>()
|
||||
|
||||
if (Object.values(LANGUAGE).includes(locale)) {
|
||||
return locale
|
||||
}
|
||||
|
||||
return LANGUAGE.EN_US
|
||||
}
|
||||
|
||||
const init = async () => {
|
||||
app.autostart = autostart.value
|
||||
app.taskbarVisible = taskbarVisibility.value
|
||||
|
||||
@@ -57,6 +73,8 @@ export const useGeneralStore = defineStore('general', () => {
|
||||
appearance.isDark = isDark.value
|
||||
|
||||
update.autoCheck = autoCheckUpdate.value
|
||||
|
||||
appearance.language ??= await getLanguage()
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user