This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import type { DropdownOption } from 'tdesign-vue-next';
|
||||
import en_US from 'tdesign-vue-next/es/locale/en_US';
|
||||
import zh_CN from 'tdesign-vue-next/es/locale/zh_CN';
|
||||
import { computed } from 'vue';
|
||||
import type { I18nOptions } from 'vue-i18n';
|
||||
import { createI18n } from 'vue-i18n';
|
||||
|
||||
export const localeConfigKey = 'tdesign-starter-locale';
|
||||
|
||||
// 定义支持的语言列表,添加新语言时只需在此处添加
|
||||
export const supportedLocales = ['zh_CN', 'en_US'] as const;
|
||||
export type SupportedLocale = (typeof supportedLocales)[number];
|
||||
|
||||
// 多语言标题类型,用于路由 meta.title 等场景
|
||||
export type LocalizedTitle = Record<SupportedLocale, string>;
|
||||
|
||||
const tdesignLocaleMap: Record<SupportedLocale, typeof zh_CN | typeof en_US> = { zh_CN, en_US };
|
||||
|
||||
const langModules = import.meta.glob<{ default: Record<string, unknown> }>('./lang/*.json', { eager: true });
|
||||
|
||||
const langCode: SupportedLocale[] = [];
|
||||
const messages: I18nOptions['messages'] = {};
|
||||
const langList: DropdownOption[] = [];
|
||||
|
||||
Object.entries(langModules).forEach(([path, module]) => {
|
||||
const code = path.match(/\.\/lang\/([^.]+)\.json$/)?.[1] as SupportedLocale | undefined;
|
||||
if (!code || !supportedLocales.includes(code)) return;
|
||||
langCode.push(code);
|
||||
messages[code] = { ...module.default, componentsLocale: tdesignLocaleMap[code] };
|
||||
langList.push({ content: module.default.lang as string, value: code });
|
||||
});
|
||||
|
||||
export { langCode };
|
||||
|
||||
// 获取初始语言:优先本地存储,其次浏览器偏好,最后默认中文
|
||||
const getInitialLocale = (): SupportedLocale => {
|
||||
const stored = localStorage.getItem(localeConfigKey);
|
||||
if (stored && supportedLocales.includes(stored as SupportedLocale)) {
|
||||
return stored as SupportedLocale;
|
||||
}
|
||||
const preferred = navigator.languages?.[0]?.replace(/-/g, '_');
|
||||
if (preferred && supportedLocales.includes(preferred as SupportedLocale)) {
|
||||
return preferred as SupportedLocale;
|
||||
}
|
||||
return 'zh_CN';
|
||||
};
|
||||
|
||||
const initialLocale = getInitialLocale();
|
||||
|
||||
export const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: initialLocale,
|
||||
fallbackLocale: 'zh_CN',
|
||||
messages,
|
||||
globalInjection: true,
|
||||
});
|
||||
|
||||
export const languageList = computed(() => langList);
|
||||
export const { t } = i18n.global;
|
||||
export default i18n;
|
||||
@@ -0,0 +1,219 @@
|
||||
{
|
||||
"lang": "English",
|
||||
"common": {
|
||||
"appName": "Kaidi Finance Base System",
|
||||
"copyright": "Kaidi Finance Base System",
|
||||
"conjunction": "and",
|
||||
"admin": "admin"
|
||||
},
|
||||
"components": {
|
||||
"isSetup": {
|
||||
"on": "Enabled",
|
||||
"off": "Disabled"
|
||||
},
|
||||
"manage": "Manage",
|
||||
"delete": "Delete",
|
||||
"deleteSuccess": "Deleted successfully",
|
||||
"copySuccess": "Copied successfully",
|
||||
"copyFail": "Copy failed",
|
||||
"submitSuccess": "Submitted successfully"
|
||||
},
|
||||
"layout": {
|
||||
"header": {
|
||||
"code": "Code Repository",
|
||||
"help": "Document",
|
||||
"user": "Profile",
|
||||
"signOut": "Sign Out",
|
||||
"setting": "Setting"
|
||||
},
|
||||
"notice": {
|
||||
"title": "Notification Center",
|
||||
"clear": "Clear",
|
||||
"setRead": "Set Read",
|
||||
"empty": "Empty",
|
||||
"emptyNotice": "No Notice",
|
||||
"viewAll": "View All"
|
||||
},
|
||||
"tagTabs": {
|
||||
"closeOther": "close other",
|
||||
"closeLeft": "close left",
|
||||
"closeRight": "close right",
|
||||
"refresh": "refresh"
|
||||
},
|
||||
"searchPlaceholder": "Enter search content",
|
||||
"search": {
|
||||
"placeholder": "Enter search content"
|
||||
},
|
||||
"setting": {
|
||||
"title": "Setting",
|
||||
"theme": {
|
||||
"mode": "Theme Mode",
|
||||
"color": "Theme Color",
|
||||
"options": {
|
||||
"light": "Light",
|
||||
"dark": "Dark ",
|
||||
"auto": "Follow System"
|
||||
}
|
||||
},
|
||||
"navigationLayout": "Navigation Layout",
|
||||
"sideMode": "Side Menu Mode",
|
||||
"splitMenu": "Split Menu (Only Mix mode)",
|
||||
"fixedSidebar": "Fixed Sidebar",
|
||||
"element": {
|
||||
"title": "Element Switch",
|
||||
"showHeader": "Show Header",
|
||||
"showBreadcrumb": "Show Breadcrumb",
|
||||
"showFooter": "Show Footer",
|
||||
"useTagTabs": "Use Tag Tabs",
|
||||
"menuAutoCollapsed": "Menu Auto Collapsed"
|
||||
},
|
||||
"tips": "Please copy and manually modify the configuration file: /src/config/style.ts",
|
||||
"copy": {
|
||||
"title": "Copy",
|
||||
"success": "copied",
|
||||
"fail": "fail to copy"
|
||||
}
|
||||
}
|
||||
},
|
||||
"constants": {
|
||||
"contract": {
|
||||
"name": "Name",
|
||||
"status": "Status",
|
||||
"num": "Number",
|
||||
"type": "Type",
|
||||
"typePlaceholder": "Please enter type",
|
||||
"payType": "Pay Type",
|
||||
"amount": "Amount",
|
||||
"amountPlaceholder": "Please enter amount",
|
||||
"signDate": "Sign Date",
|
||||
"effectiveDate": "Effective Date",
|
||||
"endDate": "End Date",
|
||||
"createDate": "Create Date",
|
||||
"attachment": "Attachment",
|
||||
"company": "Company",
|
||||
"employee": "Employee",
|
||||
"pay": "pay",
|
||||
"receive": "received",
|
||||
"remark": "remark",
|
||||
"statusOptions": {
|
||||
"fail": "Failure",
|
||||
"auditPending": "Pending audit",
|
||||
"execPending": "Pending performance",
|
||||
"executing": "Successful",
|
||||
"finish": "Finish"
|
||||
},
|
||||
"typeOptions": {
|
||||
"main": "Master contract",
|
||||
"sub": "Subcontract",
|
||||
"supplement": "Supplementary contract"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pages": {
|
||||
"notification": {
|
||||
"contract": "Contract Updates",
|
||||
"invoice": "Invoice Updates",
|
||||
"meeting": "Meeting Notification",
|
||||
"msg1": "The example project has passed review.",
|
||||
"msg2": "Third Quarter Raw Material Procurement Project invoicing successful!",
|
||||
"msg3": "Meeting 【State Grid Offline Signing】at 2021-01-01 10:00 is about to start, please arrive at Conference Room 1 10 minutes early for check-in!",
|
||||
"msg4": "First Quarter Raw Material Procurement Project invoicing successful!"
|
||||
},
|
||||
"login": {
|
||||
"loginTitle": "Login in",
|
||||
"noAccount": "No Account?",
|
||||
"createAccount": "Create Account",
|
||||
"remember": "Remember Account",
|
||||
"forget": "Forget Account",
|
||||
"signIn": "Sign in",
|
||||
"existAccount": "Exist Account?",
|
||||
"register": {
|
||||
"phonePlaceholder": "Please enter your phone number",
|
||||
"emailPlaceholder": "Please enter your email",
|
||||
"passwordPlaceholder": "Please enter your password",
|
||||
"verifyCodePlaceholder": "Please enter verification code",
|
||||
"sendVerifyCode": "Send verification code",
|
||||
"resendCountdown": "Resend in {count} seconds",
|
||||
"agreeTerms": "I have read and agree to",
|
||||
"serviceTerms": "TDesign Service Terms",
|
||||
"privacyStatement": "TDesign Privacy Statement",
|
||||
"registerBtn": "Register",
|
||||
"useEmailRegister": "Register with email",
|
||||
"usePhoneRegister": "Register with phone",
|
||||
"validation": {
|
||||
"phone": "Phone number is required",
|
||||
"email": "Email is required",
|
||||
"emailFormat": "Please enter a valid email",
|
||||
"password": "Password is required",
|
||||
"verifyCode": "Verification code is required",
|
||||
"agreeTerms": "You must agree to the service terms and privacy statement"
|
||||
},
|
||||
"messages": {
|
||||
"registerSuccess": "Registration successful"
|
||||
}
|
||||
},
|
||||
"refresh": "refresh",
|
||||
"wechatLogin": "Login with WeChat",
|
||||
"accountLogin": "Login with Account",
|
||||
"phoneLogin": "Login with Mobile Phone",
|
||||
"loginSuccess": "Login successful",
|
||||
"countdown": "Resend after {count} seconds",
|
||||
"input": {
|
||||
"account": "please enter account",
|
||||
"password": "please enter password",
|
||||
"phone": "please enter phone",
|
||||
"verification": "please enter verification code"
|
||||
},
|
||||
"required": {
|
||||
"account": "account is required",
|
||||
"phone": "phone is required",
|
||||
"password": "password is required",
|
||||
"verification": "verification code is require"
|
||||
},
|
||||
"sendVerification": "send"
|
||||
},
|
||||
"result": {
|
||||
"403": {
|
||||
"tips": "sorry, you don not have permission to access this page. Please contact the creator through WeCom",
|
||||
"back": "Back to homepage"
|
||||
},
|
||||
"404": {
|
||||
"subtitle": "Sorry, the page is not found",
|
||||
"back": "Back to homepage"
|
||||
},
|
||||
"500": {
|
||||
"subtitle": "Sorry, the server is error",
|
||||
"back": "Back to homepage"
|
||||
},
|
||||
"fail": {
|
||||
"title": "Create fail",
|
||||
"subtitle": "Sorry, your project creation has failed",
|
||||
"back": "Back to homepage",
|
||||
"modify": "Back to modify"
|
||||
},
|
||||
"success": {
|
||||
"title": "Project is created",
|
||||
"subtitle": "Contact the person in charge of distributing the application",
|
||||
"back": "Back to homepage",
|
||||
"progress": "Check Progress"
|
||||
},
|
||||
"maintenance": {
|
||||
"title": "System maintenance",
|
||||
"subtitle": "Please try again later",
|
||||
"back": "Back to homepage"
|
||||
},
|
||||
"browserIncompatible": {
|
||||
"title": "browser is incompatible",
|
||||
"subtitle": "the browser version you are using is too outdated to open the current webpage.",
|
||||
"back": "Back to homepage",
|
||||
"recommend": "TDesign Starter recommend the following browser"
|
||||
},
|
||||
"networkError": {
|
||||
"title": "Network Error",
|
||||
"subtitle": "Network error, please try again later",
|
||||
"back": "Back to homepage",
|
||||
"reload": "Reload"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
{
|
||||
"lang": "简体中文",
|
||||
"common": {
|
||||
"appName": "财务系统",
|
||||
"copyright": "财务系统",
|
||||
"conjunction": "和",
|
||||
"admin": "admin"
|
||||
},
|
||||
"components": {
|
||||
"isSetup": {
|
||||
"on": "已启用",
|
||||
"off": "已停用"
|
||||
},
|
||||
"manage": "管理",
|
||||
"delete": "删除",
|
||||
"deleteSuccess": "删除成功",
|
||||
"copySuccess": "复制成功",
|
||||
"copyFail": "复制失败",
|
||||
"submitSuccess": "提交成功"
|
||||
},
|
||||
"layout": {
|
||||
"header": {
|
||||
"code": "代码仓库",
|
||||
"help": "帮助文档",
|
||||
"user": "个人中心",
|
||||
"signOut": "退出登录",
|
||||
"setting": "系统设置"
|
||||
},
|
||||
"notice": {
|
||||
"title": "通知中心",
|
||||
"clear": "清空",
|
||||
"setRead": "设为已读",
|
||||
"empty": "空",
|
||||
"emptyNotice": "暂无通知",
|
||||
"viewAll": "查看全部"
|
||||
},
|
||||
"searchPlaceholder": "请输入搜索内容",
|
||||
"search": {
|
||||
"placeholder": "输入要搜索内容"
|
||||
},
|
||||
"tagTabs": {
|
||||
"closeOther": "关闭其他",
|
||||
"closeLeft": "关闭左侧",
|
||||
"closeRight": "关闭右侧",
|
||||
"refresh": "刷新"
|
||||
},
|
||||
"setting": {
|
||||
"title": "页面配置",
|
||||
"theme": {
|
||||
"mode": "主题模式",
|
||||
"color": "主题色",
|
||||
"options": {
|
||||
"light": "明亮",
|
||||
"dark": "深色",
|
||||
"auto": "跟随系统"
|
||||
}
|
||||
},
|
||||
"navigationLayout": "导航布局",
|
||||
"sideMode": "侧边栏模式",
|
||||
"splitMenu": "分割菜单(混合模式下有效)",
|
||||
"fixedSidebar": "固定侧边栏",
|
||||
"element": {
|
||||
"title": "元素开关",
|
||||
"showHeader": "显示顶栏",
|
||||
"showBreadcrumb": "显示面包屑",
|
||||
"showFooter": "显示页脚",
|
||||
"useTagTabs": "展示多标签Tab页",
|
||||
"menuAutoCollapsed": "菜单自动折叠"
|
||||
},
|
||||
"tips": "请复制后手动修改配置文件: /src/config/style.ts",
|
||||
"copy": {
|
||||
"title": "复制配置项",
|
||||
"success": "复制成功",
|
||||
"fail": "复制失败"
|
||||
}
|
||||
}
|
||||
},
|
||||
"constants": {
|
||||
"contract": {
|
||||
"name": "合同名称",
|
||||
"status": "合同状态",
|
||||
"num": "合同编号",
|
||||
"type": "合同类型",
|
||||
"typePlaceholder": "请输入类型",
|
||||
"payType": "合同收支类型",
|
||||
"amount": "合同金额",
|
||||
"amountPlaceholder": "请输入金额",
|
||||
"signDate": "合同签订日期",
|
||||
"effectiveDate": "合同生效日期",
|
||||
"endDate": "合同结束日期",
|
||||
"createDate": "合同创建时间",
|
||||
"company": "甲方",
|
||||
"employee": "乙方",
|
||||
"pay": "付款",
|
||||
"receive": "收款",
|
||||
"remark": "备注",
|
||||
"attachment": "附件",
|
||||
"statusOptions": {
|
||||
"fail": "审核失败",
|
||||
"auditPending": "待审核",
|
||||
"execPending": "待履行",
|
||||
"executing": "审核成功",
|
||||
"finish": "已完成"
|
||||
},
|
||||
"typeOptions": {
|
||||
"main": "主合同",
|
||||
"sub": "子合同",
|
||||
"supplement": "补充合同"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pages": {
|
||||
"notification": {
|
||||
"contract": "合同动态",
|
||||
"invoice": "票务动态",
|
||||
"meeting": "会议通知",
|
||||
"msg1": "示例项目已通过审核",
|
||||
"msg2": "三季度生产原材料采购项目 开票成功!",
|
||||
"msg3": "2021-01-01 10:00的【国家电网线下签约】会议即将开始,请提前10分钟前往 会议室1 进行签到!",
|
||||
"msg4": "一季度生产原材料采购项目 开票成功!"
|
||||
},
|
||||
"login": {
|
||||
"loginTitle": "登录到",
|
||||
"noAccount": "没有账号吗?",
|
||||
"existAccount": "已有账号?",
|
||||
"createAccount": "注册新账号",
|
||||
"remember": "记住账号",
|
||||
"forget": "忘记账号",
|
||||
"signIn": "登录",
|
||||
"register": {
|
||||
"phonePlaceholder": "请输入您的手机号",
|
||||
"emailPlaceholder": "请输入您的邮箱",
|
||||
"passwordPlaceholder": "请输入登录密码",
|
||||
"verifyCodePlaceholder": "请输入验证码",
|
||||
"sendVerifyCode": "发送验证码",
|
||||
"resendCountdown": "{count}秒后可重发",
|
||||
"agreeTerms": "我已阅读并同意",
|
||||
"serviceTerms": "TDesign服务协议",
|
||||
"privacyStatement": "TDesign 隐私声明",
|
||||
"registerBtn": "注册",
|
||||
"useEmailRegister": "使用邮箱注册",
|
||||
"usePhoneRegister": "使用手机号注册",
|
||||
"validation": {
|
||||
"phone": "手机号必填",
|
||||
"email": "邮箱必填",
|
||||
"emailFormat": "请输入正确的邮箱",
|
||||
"password": "密码必填",
|
||||
"verifyCode": "验证码必填",
|
||||
"agreeTerms": "请同意TDesign服务协议和TDesign 隐私声明"
|
||||
},
|
||||
"messages": {
|
||||
"registerSuccess": "注册成功"
|
||||
}
|
||||
},
|
||||
"refresh": "刷新",
|
||||
"wechatLogin": "使用微信扫一扫登录",
|
||||
"accountLogin": "使用账号登录",
|
||||
"phoneLogin": "使用手机号登录",
|
||||
"loginSuccess": "登录成功",
|
||||
"countdown": "{count}秒后可重发",
|
||||
"input": {
|
||||
"account": "请输入账号",
|
||||
"password": "请输入登录密码",
|
||||
"phone": "请输入手机号",
|
||||
"verification": "请输入验证码"
|
||||
},
|
||||
"required": {
|
||||
"account": "账号必填",
|
||||
"phone": "手机号必填",
|
||||
"password": "密码必填",
|
||||
"verification": "验证码必填"
|
||||
},
|
||||
"sendVerification": "发送验证码"
|
||||
},
|
||||
"result": {
|
||||
"403": {
|
||||
"tips": "当前工作身份没有访问此页面的权限,请切换身份或联系系统管理员。",
|
||||
"back": "返回首页"
|
||||
},
|
||||
"404": {
|
||||
"subtitle": "抱歉,您访问的页面不存在",
|
||||
"back": "返回首页"
|
||||
},
|
||||
"500": {
|
||||
"subtitle": "抱歉,服务器出错啦",
|
||||
"back": "返回首页"
|
||||
},
|
||||
"fail": {
|
||||
"title": "创建失败",
|
||||
"subtitle": "操作未完成,请根据提示检查权限和填写内容后重试。",
|
||||
"back": "回到首页",
|
||||
"modify": "返回修改"
|
||||
},
|
||||
"success": {
|
||||
"title": "项目已创建成功",
|
||||
"subtitle": "可以联系负责人分发应用",
|
||||
"back": "回到首页",
|
||||
"progress": "查看进度"
|
||||
},
|
||||
"maintenance": {
|
||||
"title": "系统维护中",
|
||||
"subtitle": "系统维护中,请稍后再试",
|
||||
"back": "回到首页"
|
||||
},
|
||||
"browserIncompatible": {
|
||||
"title": "浏览器不兼容",
|
||||
"subtitle": "抱歉,您正在使用的浏览器版本过低,无法打开当前网页。",
|
||||
"back": "回到首页",
|
||||
"recommend": "TDesign Starter 推荐以下主流浏览器"
|
||||
},
|
||||
"networkError": {
|
||||
"title": "网络异常",
|
||||
"subtitle": "网络异常, 请稍后重试",
|
||||
"back": "回到首页",
|
||||
"reload": "重新加载"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { useLocalStorage } from '@vueuse/core';
|
||||
import type { GlobalConfigProvider } from 'tdesign-vue-next';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import type { SupportedLocale } from '@/locales/index';
|
||||
import { i18n, localeConfigKey, supportedLocales } from '@/locales/index';
|
||||
import { useNotificationStore } from '@/store/modules/notification';
|
||||
|
||||
export function useLocale() {
|
||||
const locale = computed({
|
||||
get: () => i18n.global.locale.value,
|
||||
set: (val: string) => {
|
||||
i18n.global.locale.value = val;
|
||||
},
|
||||
});
|
||||
const storedLocale = useLocalStorage<SupportedLocale>(localeConfigKey, 'zh_CN');
|
||||
|
||||
const changeLocale = (lang: string) => {
|
||||
const validLang = supportedLocales.includes(lang as SupportedLocale) ? (lang as SupportedLocale) : 'zh_CN';
|
||||
locale.value = validLang;
|
||||
storedLocale.value = validLang;
|
||||
// 刷新持久化的翻译数据
|
||||
useNotificationStore().refreshMsgData();
|
||||
};
|
||||
|
||||
const getComponentsLocale = computed(() => {
|
||||
return (i18n.global.getLocaleMessage(locale.value) as Record<string, any>).componentsLocale as GlobalConfigProvider;
|
||||
});
|
||||
|
||||
return {
|
||||
changeLocale,
|
||||
getComponentsLocale,
|
||||
locale,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user