diff --git a/user-frontend/package-lock.json b/user-frontend/package-lock.json
index 129618a..75118fd 100644
--- a/user-frontend/package-lock.json
+++ b/user-frontend/package-lock.json
@@ -14,6 +14,7 @@
"element-plus": "^2.9.1",
"pinia": "^2.3.0",
"vue": "^3.5.13",
+ "vue-i18n": "^9.14.4",
"vue-router": "^4.5.0"
},
"devDependencies": {
@@ -553,6 +554,50 @@
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
"license": "MIT"
},
+ "node_modules/@intlify/core-base": {
+ "version": "9.14.4",
+ "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.14.4.tgz",
+ "integrity": "sha512-vtZCt7NqWhKEtHa3SD/322DlgP5uR9MqWxnE0y8Q0tjDs9H5Lxhss+b5wv8rmuXRoHKLESNgw9d+EN9ybBbj9g==",
+ "license": "MIT",
+ "dependencies": {
+ "@intlify/message-compiler": "9.14.4",
+ "@intlify/shared": "9.14.4"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
+ "node_modules/@intlify/message-compiler": {
+ "version": "9.14.4",
+ "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.14.4.tgz",
+ "integrity": "sha512-vcyCLiVRN628U38c3PbahrhbbXrckrM9zpy0KZVlDk2Z0OnGwv8uQNNXP3twwGtfLsCf4gu3ci6FMIZnPaqZsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@intlify/shared": "9.14.4",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
+ "node_modules/@intlify/shared": {
+ "version": "9.14.4",
+ "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.14.4.tgz",
+ "integrity": "sha512-P9zv6i1WvMc9qDBWvIgKkymjY2ptIiQ065PjDv7z7fDqH3J/HBRBN5IoiR46r/ujRcU7hCuSIZWvCAFCyuOYZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
@@ -1990,6 +2035,26 @@
}
}
},
+ "node_modules/vue-i18n": {
+ "version": "9.14.4",
+ "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.14.4.tgz",
+ "integrity": "sha512-B934C8yUyWLT0EMud3DySrwSUJI7ZNiWYsEEz2gknTthqKiG4dzWE/WSa8AzCuSQzwBEv4HtG1jZDhgzPfWSKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@intlify/core-base": "9.14.4",
+ "@intlify/shared": "9.14.4",
+ "@vue/devtools-api": "^6.5.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ },
+ "peerDependencies": {
+ "vue": "^3.0.0"
+ }
+ },
"node_modules/vue-router": {
"version": "4.6.4",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz",
diff --git a/user-frontend/package.json b/user-frontend/package.json
index 5bd60a1..d39d1a7 100644
--- a/user-frontend/package.json
+++ b/user-frontend/package.json
@@ -15,6 +15,7 @@
"element-plus": "^2.9.1",
"pinia": "^2.3.0",
"vue": "^3.5.13",
+ "vue-i18n": "^9.14.4",
"vue-router": "^4.5.0"
},
"devDependencies": {
diff --git a/user-frontend/src/i18n.js b/user-frontend/src/i18n.js
new file mode 100644
index 0000000..0dfb8c4
--- /dev/null
+++ b/user-frontend/src/i18n.js
@@ -0,0 +1,22 @@
+import { createI18n } from 'vue-i18n'
+import zhCN from './locales/zh-CN.json'
+import en from './locales/en.json'
+
+const savedLang = localStorage.getItem('lang') || 'zh-CN'
+
+const i18n = createI18n({
+ legacy: false,
+ locale: savedLang,
+ fallbackLocale: 'zh-CN',
+ messages: {
+ 'zh-CN': zhCN,
+ 'en': en,
+ },
+})
+
+export function switchLang(lang) {
+ i18n.global.locale.value = lang
+ localStorage.setItem('lang', lang)
+}
+
+export default i18n
diff --git a/user-frontend/src/layouts/UserLayout.vue b/user-frontend/src/layouts/UserLayout.vue
index bb25f1a..aaa8228 100644
--- a/user-frontend/src/layouts/UserLayout.vue
+++ b/user-frontend/src/layouts/UserLayout.vue
@@ -16,16 +16,16 @@
:collapse-transition="false"
@select="showMobileMenu = false"
>
-