diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 4f47aa9a..9a7d7590 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -20,6 +20,7 @@
"dbaeumer.vscode-eslint",
"Nuxtr.nuxtr-vscode",
"Prisma.prisma",
+ "lokalise.i18n-ally",
// Do not install Prettier. It will conflict with eslint.
"-esbenp.prettier-vscode"
]
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 13590514..1d6aa34d 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -13,11 +13,16 @@
"eslint.options": {
"overrideConfigFile": "./eslint.config.js"
},
- "eslint.experimental.useFlatConfig": true,
+ "eslint.useFlatConfig": true,
"eslint.lintTask.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"editor.insertSpaces": true,
- "editor.tabSize": 2
+ "editor.tabSize": 2,
+ "i18n-ally.localesPaths": [
+ "locales"
+ ],
+ "i18n-ally.enabledParsers": ["js", "ts", "json"],
+ "i18n-ally.enabledFrameworks": ["vue-sfc", "vue"]
}
diff --git a/components/custom/sidebar.vue b/components/custom/sidebar.vue
index 9282508b..955483c2 100644
--- a/components/custom/sidebar.vue
+++ b/components/custom/sidebar.vue
@@ -4,8 +4,10 @@ import { cn } from '@/lib/utils'
import { useClerk } from 'vue-clerk'
import type { AllClubs } from '~/types/api/user/all_clubs'
+const { t } = useI18n({
+ useScope: 'local',
+})
const clerk = useClerk()
-
const route = useRoute()
const isPresidentOrVicePresident = ref(false)
@@ -31,33 +33,33 @@ if (import.meta.client) {
- 学校事务
+ {{ t('school_affairs') }}
- 社团信息
+ {{ t('cas_information') }}
@@ -70,44 +72,44 @@ if (import.meta.client) {
- CAS管理
+ {{ t('manage') }}
- 信息
+ {{ t('info') }}
@@ -115,3 +117,38 @@ if (import.meta.client) {
+
+
+{
+ "zh": {
+ "home": "首页",
+ "school_affairs": "校务",
+ "forms": "表格",
+ "cas_information": "CAS信息",
+ "clubs": "社团",
+ "rating": "期末评价",
+ "manage": "CAS管理",
+ "reservation": "预约教室",
+ "manage_reservation": "管理预约",
+ "statuses": "教室状态",
+ "record": "活动签到",
+ "info": "信息",
+ "about": "关于 Enspire"
+ },
+ "en": {
+ "home": "Home",
+ "school_affairs": "School Affairs",
+ "forms": "Forms",
+ "cas_information": "CAS Information",
+ "clubs": "Clubs",
+ "rating": "Rating",
+ "manage": "CAS Management",
+ "reservation": "Reservation",
+ "manage_reservation": "Manage Reservation",
+ "statuses": "Statuses",
+ "record": "Record",
+ "info": "Info",
+ "about": "About Enspire"
+ }
+}
+
diff --git a/i18n.config.ts b/i18n.config.ts
new file mode 100644
index 00000000..92028679
--- /dev/null
+++ b/i18n.config.ts
@@ -0,0 +1,12 @@
+import en from './locales/en.json'
+import zh from './locales/zh.json'
+
+export default defineI18nConfig(() => ({
+ legacy: false,
+ locale: 'en',
+ fallbackLocale: 'zh',
+ messages: {
+ zh,
+ en,
+ },
+}))
diff --git a/locales/en.json b/locales/en.json
new file mode 100644
index 00000000..0db3279e
--- /dev/null
+++ b/locales/en.json
@@ -0,0 +1,3 @@
+{
+
+}
diff --git a/locales/zh.json b/locales/zh.json
new file mode 100644
index 00000000..0db3279e
--- /dev/null
+++ b/locales/zh.json
@@ -0,0 +1,3 @@
+{
+
+}
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 30187629..ed2693f0 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -24,6 +24,7 @@ export default defineNuxtConfig({
'@sentry/nuxt/module',
'@nuxt/image',
'dayjs-nuxt',
+ '@nuxtjs/i18n',
],
build: {
@@ -71,5 +72,22 @@ export default defineNuxtConfig({
},
},
+ future: {
+ compatibilityVersion: 4,
+ },
+
+ i18n: {
+ vueI18n: './i18n.config.ts',
+ detectBrowserLanguage: {
+ useCookie: true,
+ cookieKey: 'i18n_redirected',
+ redirectOn: 'root',
+ },
+ },
+
compatibilityDate: '2024-08-31',
+
+ devtools: {
+ enabled: true,
+ },
})
diff --git a/package.json b/package.json
index f6e74ba7..2db19c84 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"@netlify/integrations": "^0.5.4",
"@netlify/sentry": "^0.0.10",
"@nuxt/content": "^2.13.4",
+ "@nuxtjs/i18n": "^9.1.0",
"@radix-icons/vue": "^1.0.0",
"@sentry/nuxt": "^8.34.0",
"@tanstack/vue-table": "^8.20.5",
@@ -88,5 +89,11 @@
},
"prisma": {
"schema": "db/schema.prisma"
+ },
+ "pnpm": {
+ "overrides": {
+ "@intlify/core": "10.0.5",
+ "@intlify/shared": "10.0.5"
+ }
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d4026f1e..eafaf569 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17187,11 +17187,14 @@ snapshots:
vue-router@4.4.5(vue@3.5.12(typescript@5.6.3)):
dependencies:
+ '@intlify/core-base': 10.0.5
+ '@intlify/shared': 10.0.5
'@vue/devtools-api': 6.6.4
vue: 3.5.12(typescript@5.6.3)
vue-screen-utils@1.0.0-beta.13(vue@3.5.12(typescript@5.6.3)):
dependencies:
+ '@vue/devtools-api': 6.6.4
vue: 3.5.12(typescript@5.6.3)
vue-tsc@2.1.6(typescript@5.6.3):