diff --git a/package.json b/package.json index e56d3f9..55498e6 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-sql": "~2", "vue": "^3.5.21", + "vue-i18n": "^11.1.12", "vue-router": "^4.5.1", "vuetify": "^3.10.1", "zod": "^4.1.12" diff --git a/src/App.vue b/src/App.vue index 45266a3..015c40a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -14,7 +14,7 @@ @@ -29,16 +29,20 @@ > + > + + @@ -54,8 +58,11 @@ diff --git a/src/components.d.ts b/src/components.d.ts index 0f05f44..6fb335c 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -10,6 +10,7 @@ declare module 'vue' { export interface GlobalComponents { AddGroup: typeof import('./components/nodeEdit/addGroup.vue')['default'] AddNode: typeof import('./components/nodeEdit/addNode.vue')['default'] + LanguageSwitcher: typeof import('./components/LanguageSwitcher.vue')['default'] NodeList: typeof import('./components/nodeEdit/nodeList.vue')['default'] NodesFloatButton: typeof import('./components/nodeEdit/nodesFloatButton.vue')['default'] NotificationProvider: typeof import('./components/notify/notificationProvider.vue')['default'] diff --git a/src/components/LanguageSwitcher.vue b/src/components/LanguageSwitcher.vue new file mode 100644 index 0000000..e6c09ca --- /dev/null +++ b/src/components/LanguageSwitcher.vue @@ -0,0 +1,48 @@ + + + \ No newline at end of file diff --git a/src/components/index/spary.vue b/src/components/index/spary.vue index 11776b6..27932c1 100644 --- a/src/components/index/spary.vue +++ b/src/components/index/spary.vue @@ -2,7 +2,7 @@
diff --git a/src/components/nodeEdit/addGroup.vue b/src/components/nodeEdit/addGroup.vue index 47c0bbf..c8bd8c5 100644 --- a/src/components/nodeEdit/addGroup.vue +++ b/src/components/nodeEdit/addGroup.vue @@ -1,14 +1,17 @@ @@ -15,13 +17,13 @@ const router = useRouter() - add group + {{ $t('nodesFloatButton.addGroup') }} - add node + {{ $t('nodesFloatButton.addNode') }}
diff --git a/src/locales/en.json b/src/locales/en.json new file mode 100644 index 0000000..2835cb6 --- /dev/null +++ b/src/locales/en.json @@ -0,0 +1,56 @@ +{ + "app": { + "title": "Spary", + "nodes": "Nodes", + "settings": "Settings", + "add": "Add", + "group": "Group", + "node": "Node" + }, + "spary": { + "functionStatus": { + "on": "On", + "off": "Off" + } + }, + "nodeList": { + "add": "add", + "usage": "usage: {traffic}", + "noNodes": "No nodes available" + }, + "nodesFloatButton": { + "addGroup": "add group", + "addNode": "add node" + }, + "addGroup": { + "title": "Add Group", + "groupName": "Group name", + "groupNameRule": "Group name must be between 1 and 15 characters.", + "subscribeUrl": "Subscribe URL", + "urlInvalid": "URL is not valid.", + "arguments": "Arguments", + "addGroupButton": "Add", + "groupExists": "Group already exists.", + "groupAdded": "Group added." + }, + "addNode": { + "title": "Add Node", + "group": "Group", + "nodeAlias": "Node alias", + "arguments": "Arguments", + "addNodeButton": "Add", + "nodeAddedSuccess": "Node added successfully" + }, + "common": { + "save": "Save", + "cancel": "Cancel", + "delete": "Delete", + "edit": "Edit", + "confirm": "Confirm", + "darkModeOn": "Dark Mode On", + "darkModeOff": "Dark Mode Off", + "language": "Language", + "english": "English", + "chinese": "Chinese" + } +} \ No newline at end of file diff --git a/src/locales/zh.json b/src/locales/zh.json new file mode 100644 index 0000000..3a5610d --- /dev/null +++ b/src/locales/zh.json @@ -0,0 +1,56 @@ +{ + "app": { + "title": "Spary", + "nodes": "节点", + "settings": "设置", + "add": "添加", + "group": "组", + "node": "节点" + }, + "spary": { + "functionStatus": { + "on": "开", + "off": "关" + } + }, + "nodeList": { + "add": "添加", + "usage": "使用量: {traffic}", + "noNodes": "没有可用节点" + }, + "nodesFloatButton": { + "addGroup": "添加组", + "addNode": "添加节点" + }, + "addGroup": { + "title": "添加组", + "groupName": "组名称", + "groupNameRule": "组名称必须在1到15个字符之间。", + "subscribeUrl": "订阅链接", + "urlInvalid": "URL无效。", + "arguments": "参数", + "addGroupButton": "添加", + "groupExists": "组已存在。", + "groupAdded": "组已添加。" + }, + "addNode": { + "title": "添加节点", + "group": "组", + "nodeAlias": "节点别名", + "arguments": "参数", + "addNodeButton": "添加", + "nodeAddedSuccess": "节点添加成功" + }, + "common": { + "save": "保存", + "cancel": "取消", + "delete": "删除", + "edit": "编辑", + "confirm": "确认", + "darkModeOn": "深色模式开", + "darkModeOff": "深色模式关", + "language": "语言", + "english": "英语", + "chinese": "中文" + } +} \ No newline at end of file diff --git a/src/pages/settings.vue b/src/pages/settings.vue index 50d4cd2..f3a1e7f 100644 --- a/src/pages/settings.vue +++ b/src/pages/settings.vue @@ -1,7 +1,53 @@ diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts new file mode 100644 index 0000000..df8f7a9 --- /dev/null +++ b/src/plugins/i18n.ts @@ -0,0 +1,17 @@ +import { createI18n } from 'vue-i18n' +import en from '@/locales/en.json' +import zh from '@/locales/zh.json' + +const messages = { + en: en, + zh: zh +} + +const i18n = createI18n({ + legacy: false, // Use composition API mode + locale: 'en', // Default locale + fallbackLocale: 'en', // Fallback locale + messages +}) + +export default i18n \ No newline at end of file diff --git a/src/plugins/index.ts b/src/plugins/index.ts index d3c748a..bf08b51 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -7,6 +7,7 @@ // Plugins import vuetify from './vuetify' import router from '../router' +import i18n from './i18n' // Types import type { App } from 'vue' @@ -15,4 +16,5 @@ export function registerPlugins (app: App) { app .use(vuetify) .use(router) + .use(i18n) } diff --git a/src/vue-i18n.d.ts b/src/vue-i18n.d.ts new file mode 100644 index 0000000..bc74ee0 --- /dev/null +++ b/src/vue-i18n.d.ts @@ -0,0 +1,7 @@ +/* eslint-disable */ +import Vue from "vue"; +declare module "@vue/runtime-core" { + export interface ComponentCustomProperties { + $t: (key: string, ...args: any[]) => string; + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 02ece3d..ae9e541 100644 --- a/yarn.lock +++ b/yarn.lock @@ -304,6 +304,27 @@ resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz" integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== +"@intlify/core-base@11.1.12": + version "11.1.12" + resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-11.1.12.tgz#e02529021a4e69f8a1adcca5ce61963c71cd72ba" + integrity sha512-whh0trqRsSqVLNEUCwU59pyJZYpU8AmSWl8M3Jz2Mv5ESPP6kFh4juas2NpZ1iCvy7GlNRffUD1xr84gceimjg== + dependencies: + "@intlify/message-compiler" "11.1.12" + "@intlify/shared" "11.1.12" + +"@intlify/message-compiler@11.1.12": + version "11.1.12" + resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-11.1.12.tgz#27e69790b711a92cddb07175187dd09a7b270b55" + integrity sha512-Fv9iQSJoJaXl4ZGkOCN1LDM3trzze0AS2zRz2EHLiwenwL6t0Ki9KySYlyr27yVOj5aVz0e55JePO+kELIvfdQ== + dependencies: + "@intlify/shared" "11.1.12" + source-map-js "^1.0.2" + +"@intlify/shared@11.1.12": + version "11.1.12" + resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-11.1.12.tgz#ab41083e017d622cf63c7dc88a0ee0bc27f4127a" + integrity sha512-Om86EjuQtA69hdNj3GQec9ZC0L0vPSAnXzB3gP/gyJ7+mA7t06d9aOAiqMZ+xEOsumGP4eEBlfl8zF2LOTzf2A== + "@jridgewell/gen-mapping@^0.3.5": version "0.3.13" resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz" @@ -877,7 +898,7 @@ "@vue/compiler-dom" "3.5.22" "@vue/shared" "3.5.22" -"@vue/devtools-api@^6.6.4": +"@vue/devtools-api@^6.5.0", "@vue/devtools-api@^6.6.4": version "6.6.4" resolved "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz" integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g== @@ -2429,7 +2450,7 @@ sisteransi@^1.0.5: resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.1: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -2688,6 +2709,15 @@ vue-eslint-parser@^10.2.0: esquery "^1.6.0" semver "^7.6.3" +vue-i18n@^11.1.12: + version "11.1.12" + resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-11.1.12.tgz#230b21d65dd89343ebd40d19c9e3cfb13db8c1fd" + integrity sha512-BnstPj3KLHLrsqbVU2UOrPmr0+Mv11bsUZG0PyCOzsawCivk8W00GMXHeVUWIDOgNaScCuZah47CZFE+Wnl8mw== + dependencies: + "@intlify/core-base" "11.1.12" + "@intlify/shared" "11.1.12" + "@vue/devtools-api" "^6.5.0" + vue-router@^4.5.1: version "4.5.1" resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz"