diff --git a/src/i18n/index.ts b/src/i18n/index.ts
new file mode 100644
index 0000000..a330980
--- /dev/null
+++ b/src/i18n/index.ts
@@ -0,0 +1,18 @@
+import { createI18n } from 'vue-i18n'
+import zhCN from './locales/zh-CN/index'
+import enUS from './locales/en-US/index'
+
+export type { LanguageType } from '@/stores/modules/language'
+
+// 创建 i18n 实例
+const i18n = createI18n({
+ legacy: false, // 使用 Composition API 模式
+ locale: localStorage.getItem('lang') || 'zh-CN', // 默认语言
+ fallbackLocale: 'zh-CN', // 回退语言
+ messages: {
+ 'zh-CN': zhCN,
+ 'en-US': enUS
+ }
+})
+
+export default i18n
diff --git a/src/i18n/locales/en-US/index.ts b/src/i18n/locales/en-US/index.ts
new file mode 100644
index 0000000..f6ba2ba
--- /dev/null
+++ b/src/i18n/locales/en-US/index.ts
@@ -0,0 +1,101 @@
+// English translation file
+export default {
+ // Common
+ common: {
+ loading: 'Loading...',
+ submit: 'Submit',
+ cancel: 'Cancel',
+ confirm: 'Confirm',
+ edit: 'Edit',
+ delete: 'Delete',
+ save: 'Save',
+ close: 'Close',
+ search: 'Search',
+ reset: 'Reset',
+ pleaseInput: 'Please enter',
+ pleaseSelect: 'Please select',
+ operation: 'Operation',
+ status: 'Status',
+ createTime: 'Create Time',
+ updateTime: 'Update Time',
+ remark: 'Remark',
+ success: 'Operation successful',
+ error: 'Operation failed',
+ warning: 'Warning',
+ info: 'Info'
+ },
+ // Personal Center
+ personalCenter: {
+ pageTitle: 'Account Information',
+ username: 'Username',
+ email: 'Email',
+ mobile: 'Mobile',
+ password: 'Password',
+ language: 'Language',
+ languageDesc: 'Select your preferred communication language',
+ lastLogin: 'Last Login',
+ notSet: 'Not set',
+ notBound: 'Not bound',
+ bound: 'Bound',
+ goToBind: 'Go to bind',
+ bind: 'Bind',
+ modify: 'Modify',
+ bindEmail: 'Bind Email',
+ bindMobile: 'Bind Mobile',
+ rebindMobile: 'Rebind Mobile',
+ modifyUsername: 'Modify Username',
+ modifyPassword: 'Modify Password',
+ verifyMethod: 'Verification Method',
+ verifyAccount: 'Verification Account',
+ mobileVerify: 'Mobile Verification',
+ emailVerify: 'Email Verification',
+ newPassword: 'New Password',
+ confirmPassword: 'Confirm Password',
+ passwordPlaceholder: '6-12 characters, including uppercase, lowercase and special characters',
+ confirmPasswordPlaceholder: 'Please enter new password again',
+ // Validation messages
+ pleaseInputEmail: 'Please enter email',
+ emailFormatError: 'Email format is incorrect',
+ pleaseInputMobile: 'Please enter mobile number',
+ mobileFormatError: 'Mobile number format is incorrect',
+ pleaseInputUsername: 'Please enter username',
+ usernameLengthError: 'Username length must be 2-20 characters',
+ pleaseSelectVerifyMethod: 'Please select verification method',
+ pleaseInputNewPassword: 'Please enter new password',
+ passwordLengthError: 'Length must be 6-12 characters',
+ passwordComplexityError: 'Must include uppercase, lowercase and special characters',
+ pleaseConfirmNewPassword: 'Please confirm new password',
+ passwordMismatchError: 'Passwords do not match',
+ // Message prompts
+ pleaseBindMobileOrEmail: 'Please bind mobile or email first',
+ pleaseInputVerifyAccount: 'Please bind verification account first',
+ pleaseInputReceiverAccount: 'Please enter the account to receive verification code',
+ getUserInfoFailed: 'Failed to get user information',
+ languageChangeFailed: 'Failed to change language'
+ },
+ // Agent User Detail
+ agentUser: {
+ phone: 'Phone',
+ accountBalance: 'Account Balance',
+ depositAmount: 'Deposit Amount',
+ email: 'Email',
+ registerTime: 'Register Time',
+ historyTradeAmount: 'History Trade Amount',
+ tradeAccount: 'Trade Account',
+ accountName: 'Account Name',
+ balance: 'Balance',
+ tradeLeverage: 'Trade Leverage',
+ historyTradeVolume: 'History Trade Volume',
+ addTime: 'Add Time',
+ loadDetailFailed: 'Failed to load detail',
+ operateAccount: 'Operate Account',
+ role: {
+ 1: 'Platform',
+ 2: 'Contractor',
+ 3: 'Special Market Maker',
+ 4: 'Ordinary Market Maker',
+ 5: 'Agent',
+ 6: 'User'
+ }
+ }
+}
diff --git a/src/i18n/locales/zh-CN/index.ts b/src/i18n/locales/zh-CN/index.ts
new file mode 100644
index 0000000..c930a96
--- /dev/null
+++ b/src/i18n/locales/zh-CN/index.ts
@@ -0,0 +1,101 @@
+// 中文翻译文件
+export default {
+ // 通用
+ common: {
+ loading: '加载中...',
+ submit: '提交',
+ cancel: '取消',
+ confirm: '确认',
+ edit: '修改',
+ delete: '删除',
+ save: '保存',
+ close: '关闭',
+ search: '搜索',
+ reset: '重置',
+ pleaseInput: '请输入',
+ pleaseSelect: '请选择',
+ operation: '操作',
+ status: '状态',
+ createTime: '创建时间',
+ updateTime: '更新时间',
+ remark: '备注',
+ success: '操作成功',
+ error: '操作失败',
+ warning: '警告',
+ info: '提示'
+ },
+ // 个人中心
+ personalCenter: {
+ pageTitle: '账户信息',
+ username: '用户名',
+ email: '邮箱',
+ mobile: '手机号',
+ password: '密码',
+ language: '语言',
+ languageDesc: '选择您偏好的通讯语言',
+ lastLogin: '最后登录',
+ notSet: '未设置',
+ notBound: '未绑定',
+ bound: '已绑定',
+ goToBind: '去绑定',
+ bind: '绑定',
+ modify: '修改',
+ bindEmail: '绑定邮箱',
+ bindMobile: '绑定手机号',
+ rebindMobile: '重新绑定手机号',
+ modifyUsername: '修改用户名',
+ modifyPassword: '修改密码',
+ verifyMethod: '验证方式',
+ verifyAccount: '验证账号',
+ mobileVerify: '手机验证',
+ emailVerify: '邮箱验证',
+ newPassword: '新密码',
+ confirmPassword: '确认密码',
+ passwordPlaceholder: '6-12位,含大小写+特殊字符',
+ confirmPasswordPlaceholder: '请再次输入新密码',
+ // 验证规则提示
+ pleaseInputEmail: '请输入邮箱',
+ emailFormatError: '邮箱格式不正确',
+ pleaseInputMobile: '请输入手机号',
+ mobileFormatError: '手机号格式不正确',
+ pleaseInputUsername: '请输入用户名',
+ usernameLengthError: '用户名长度 2-20 位',
+ pleaseSelectVerifyMethod: '请选择验证方式',
+ pleaseInputNewPassword: '请输入新密码',
+ passwordLengthError: '长度 6-12 位',
+ passwordComplexityError: '必须包含大小写+特殊字符',
+ pleaseConfirmNewPassword: '请确认新密码',
+ passwordMismatchError: '两次密码不一致',
+ // 消息提示
+ pleaseBindMobileOrEmail: '请先绑定手机或邮箱',
+ pleaseInputVerifyAccount: '请先绑定验证账号',
+ pleaseInputReceiverAccount: '请输入接收验证码的账号',
+ getUserInfoFailed: '获取用户信息失败',
+ languageChangeFailed: '语言切换失败'
+ },
+ // 代理用户详情
+ agentUser: {
+ phone: '手机号',
+ accountBalance: '账户余额',
+ depositAmount: '存款金额',
+ email: '邮箱',
+ registerTime: '注册时间',
+ historyTradeAmount: '历史交易金额',
+ tradeAccount: '交易账号',
+ accountName: '账户名称',
+ balance: '余额',
+ tradeLeverage: '交易杠杆',
+ historyTradeVolume: '历史交易量',
+ addTime: '添加时间',
+ loadDetailFailed: '加载详情失败',
+ operateAccount: '操作账户',
+ role: {
+ 1: '平台',
+ 2: '承包商',
+ 3: '特殊做市商',
+ 4: '普通做市商',
+ 5: '代理',
+ 6: '用户'
+ }
+ }
+}
diff --git a/src/main.ts b/src/main.ts
index 1e4f87c..afa257f 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -5,12 +5,14 @@ import 'element-plus/dist/index.css'
//语言配置
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
+import en from 'element-plus/dist/locale/en.mjs'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
+import i18n from './i18n'
import {setupAuthDirective} from './directives/auth'
import { setStorage } from '@/utils/storage'
import '@imengyu/vue3-context-menu/lib/vue3-context-menu.css'
@@ -22,9 +24,13 @@ const app = createApp(App)
setupAuthDirective(app)
app.use(createPinia())
app.use(router)
+app.use(i18n)
app.use(ContextMenu)
app.use(ElementPlus, {
locale: zhCn,
})
app.mount('#app')
+
+// 导出 app 实例以便在其他地方使用
+export default app
diff --git a/src/stores/modules/language.ts b/src/stores/modules/language.ts
index af9fc6e..5e8085b 100644
--- a/src/stores/modules/language.ts
+++ b/src/stores/modules/language.ts
@@ -14,16 +14,11 @@ export const useLanguageStore = defineStore('language', () => {
if (!getStorage('lang')) {
setStorage('lang', initLang)
}
- // const setHtmlLang = (currentLang: LanguageType) => {
- // document.documentElement.lang = langMap[currentLang]
- // }
-
- // setHtmlLang(lang.value)
const changeLang = (newLang: LanguageType) => {
lang.value = newLang
setStorage('lang', newLang)
- // setHtmlLang(newLang)
+ // i18n 的 locale 会通过 watch 自动同步
}
return { lang, changeLang }
diff --git a/src/views/agent/user/default.vue b/src/views/agent/user/default.vue
index 40088cb..13f3be6 100644
--- a/src/views/agent/user/default.vue
+++ b/src/views/agent/user/default.vue
@@ -23,7 +23,7 @@
- 手机号
+ {{ t('agentUser.phone') }}
{{ userInfo.phone || '-' }}
@@ -32,7 +32,7 @@
- 账户余额
+ {{ t('agentUser.accountBalance') }}
@@ -43,7 +43,7 @@
-
存款金额
+
{{ t('agentUser.depositAmount') }}
@@ -54,7 +54,7 @@
-
邮箱
+
{{ t('agentUser.email') }}
{{ userInfo.email || '-' }}
@@ -63,7 +63,7 @@
- 注册时间
+ {{ t('agentUser.registerTime') }}
{{ userInfo.registerTime || '-' }}
@@ -72,7 +72,7 @@
- 历史交易金额
+ {{ t('agentUser.historyTradeAmount') }}
@@ -98,9 +98,11 @@ defineOptions({
})
import { ref, watch, computed } from 'vue'
import { ElAvatar, ElIcon, ElDrawer, ElButton, ElMessage } from 'element-plus'
+import { useI18n } from 'vue-i18n'
import { UserFilled, Phone, Message, Money, Wallet, Clock, CreditCard } from '@element-plus/icons-vue'
import CustomerListTable from '@/components/common/Table.vue'
import { getCustomerDetailApi } from '@/api/modules/agent/customerDetail'
+import { useLanguageStore } from '@/stores/modules/language'
import dayjs from 'dayjs'
import AnimatedNumber from './AnimatedNumber.vue'
@@ -115,14 +117,18 @@ import type {
TableColumn
} from '@/api/types/agent'
-const roleMap: Record
= {
- 1: '平台',
- 2: '承包商',
- 3: '特殊做市商',
- 4: '普通做市商',
- 5: '代理',
- 6: '用户',
-}
+const { t, locale } = useI18n()
+const languageStore = useLanguageStore()
+
+// 使用 computed 动态生成角色映射,支持语言切换
+const roleMap = computed>(() => ({
+ 1: t('agentUser.role.1'),
+ 2: t('agentUser.role.2'),
+ 3: t('agentUser.role.3'),
+ 4: t('agentUser.role.4'),
+ 5: t('agentUser.role.5'),
+ 6: t('agentUser.role.6'),
+}))
// 接收父组件传值
const props = defineProps<{
@@ -165,13 +171,15 @@ const userInfo = ref({
// 表格
const tableData = ref([])
-const tableColumnsOptions = ref([
- { label: '交易账号', prop: 'tradeAccount' },
- { label: '账户名称', prop: 'accountName' },
- { label: '余额', prop: 'balance', sortable: true },
- { label: '交易杠杆', prop: 'leverage' },
- { label: '历史交易量', prop: 'tradeVolume' },
- { label: '添加时间', prop: 'addTime', width: 180 }
+
+// 动态生成表格列配置,支持语言切换
+const tableColumnsOptions = computed(() => [
+ { label: t('agentUser.tradeAccount'), prop: 'tradeAccount' },
+ { label: t('agentUser.accountName'), prop: 'accountName' },
+ { label: t('agentUser.balance'), prop: 'balance', sortable: true },
+ { label: t('agentUser.tradeLeverage'), prop: 'leverage' },
+ { label: t('agentUser.historyTradeVolume'), prop: 'tradeVolume' },
+ { label: t('agentUser.addTime'), prop: 'addTime', width: 180 }
])
@@ -187,7 +195,7 @@ const loadDetailData = async (id: string | number) => {
userInfo.value = {
name: user.email || user.mobile || '-',
id: user.id,
- role: roleMap[user.role_id] || '-',
+ role: roleMap.value[user.role_id] || '-',
phone: user.mobile || '-',
email: user.email || '-',
balance: Number(user.capital_amount) || 0,
@@ -207,7 +215,7 @@ const loadDetailData = async (id: string | number) => {
}))
} catch (err) {
console.error('加载详情失败:', err);
- ElMessage.error('加载详情失败')
+ ElMessage.error(t('agentUser.loadDetailFailed'))
} finally {
loading.value = false
tableLoading.value = false
@@ -224,9 +232,18 @@ watch(
{ immediate: true }
)
+// 监听语言切换,同步更新 i18n 的 locale
+watch(
+ () => languageStore.lang,
+ (newLang) => {
+ locale.value = newLang
+ },
+ { immediate: true }
+)
+
// 账户操作
const handleAccount = (row: TableDataRow) => {
- ElMessage.success('操作账户:' + row.tradeAccount)
+ ElMessage.success(t('agentUser.operateAccount') + ':' + row.tradeAccount)
}
diff --git a/src/views/profile/personalCenter/index.vue b/src/views/profile/personalCenter/index.vue
index 623ecf0..9e36fa2 100644
--- a/src/views/profile/personalCenter/index.vue
+++ b/src/views/profile/personalCenter/index.vue
@@ -1,7 +1,7 @@
@@ -17,9 +17,9 @@
{{ userInfo.username }}
- 修改
+ {{ t('personalCenter.modify') }}
-
最后登录:{{ userInfo.last_login }}
+
{{ t('personalCenter.lastLogin') }}:{{ userInfo.last_login }}
@@ -27,35 +27,35 @@
- 邮箱
- {{ userInfo.email || '未设置' }}
+ {{ t('personalCenter.email') }}
+ {{ userInfo.email || t('personalCenter.notSet') }}
- 去绑定
+ {{ t('personalCenter.goToBind') }}
- 已绑定
+ {{ t('personalCenter.bound') }}
- 手机号
- {{ userInfo.mobile || '未绑定' }}
+ {{ t('personalCenter.mobile') }}
+ {{ userInfo.mobile || t('personalCenter.notBound') }}
- 绑定
+ {{ t('personalCenter.bind') }}
- 已绑定
+ {{ t('personalCenter.bound') }}
- 密码
- 修改
+ {{ t('personalCenter.password') }}
+ {{ t('personalCenter.modify') }}
- 语言
- 选择您偏好的通讯语言
+ {{ t('personalCenter.language') }}
+ {{ t('personalCenter.languageDesc') }}
@@ -70,7 +70,7 @@
@cancel="handleEditDialogReset" @close="handleEditDialogReset">
-
@@ -80,20 +80,20 @@
-