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 @@
-
+
+
+ {{ $t('app.settings') }}
+
+
+
+
+ {{ darkMode ? $t('common.darkModeOff') : $t('common.darkModeOn') }}
+
+
+
+ {{ $t('common.language') }}
+
+ {{ $t('common.english') }}
+ {{ $t('common.chinese') }}
+
+
+
+
+
+
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"