diff --git a/.vscode/settings.json b/.vscode/settings.json index 03926a7..b201e30 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -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" } diff --git a/Cargo.lock b/Cargo.lock index b437dc7..b1177d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/package.json b/package.json index 284eff2..ecb29c6 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be84994..770c91f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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 diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 98cb309..21a4be1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -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"] } diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index f8a746d..5e8f5a7 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -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" ] } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index d97435c..3b43b11 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -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(); diff --git a/src/App.vue b/src/App.vue index 3631eef..a90bea0 100644 --- a/src/App.vue +++ b/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) => {