refactor: reconstruct language files into multi-file structures (#4683)
* refactor: reconstruct language files into multi-file structures * chore: typopull/48/MERGE
							parent
							
								
									d1ca09c7bb
								
							
						
					
					
						commit
						0df8c5c02c
					
				|  | @ -197,11 +197,14 @@ | |||
|     "playground/src/locales/langs", | ||||
|     "apps/*/src/locales/langs" | ||||
|   ], | ||||
|   "i18n-ally.pathMatcher": "{locale}.json", | ||||
|   "i18n-ally.enabledParsers": ["json", "ts", "js", "yaml"], | ||||
|   "i18n-ally.pathMatcher": "{locale}/{namespace}.{ext}", | ||||
|   "i18n-ally.enabledParsers": ["json"], | ||||
|   "i18n-ally.sourceLanguage": "en", | ||||
|   "i18n-ally.displayLanguage": "zh-CN", | ||||
|   "i18n-ally.enabledFrameworks": ["vue", "react"], | ||||
|   "i18n-ally.keystyle": "nested", | ||||
|   "i18n-ally.sortKeys": true, | ||||
|   "i18n-ally.namespace": true, | ||||
| 
 | ||||
|   // 控制相关文件嵌套展示 | ||||
|   "explorer.fileNesting.enabled": true, | ||||
|  | @ -216,7 +219,6 @@ | |||
|     "tailwind.config.mjs": "postcss.*" | ||||
|   }, | ||||
|   "commentTranslate.hover.enabled": false, | ||||
|   "i18n-ally.keystyle": "nested", | ||||
|   "commentTranslate.multiLineMerge": true, | ||||
|   "vue.server.hybridMode": true, | ||||
|   "typescript.tsdk": "node_modules/typescript/lib" | ||||
|  |  | |||
|  | @ -86,7 +86,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { | |||
|       component: '/demos/access/admin-visible', | ||||
|       meta: { | ||||
|         icon: 'mdi:button-cursor', | ||||
|         title: 'page.demos.access.adminVisible', | ||||
|         title: 'demos.access.adminVisible', | ||||
|       }, | ||||
|       name: 'AccessAdminVisibleDemo', | ||||
|       path: '/demos/access/admin-visible', | ||||
|  | @ -95,7 +95,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { | |||
|       component: '/demos/access/super-visible', | ||||
|       meta: { | ||||
|         icon: 'mdi:button-cursor', | ||||
|         title: 'page.demos.access.superVisible', | ||||
|         title: 'demos.access.superVisible', | ||||
|       }, | ||||
|       name: 'AccessSuperVisibleDemo', | ||||
|       path: '/demos/access/super-visible', | ||||
|  | @ -104,7 +104,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { | |||
|       component: '/demos/access/user-visible', | ||||
|       meta: { | ||||
|         icon: 'mdi:button-cursor', | ||||
|         title: 'page.demos.access.userVisible', | ||||
|         title: 'demos.access.userVisible', | ||||
|       }, | ||||
|       name: 'AccessUserVisibleDemo', | ||||
|       path: '/demos/access/user-visible', | ||||
|  | @ -118,7 +118,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { | |||
|         icon: 'ic:baseline-view-in-ar', | ||||
|         keepAlive: true, | ||||
|         order: 1000, | ||||
|         title: 'page.demos.title', | ||||
|         title: 'demos.title', | ||||
|       }, | ||||
|       name: 'Demos', | ||||
|       path: '/demos', | ||||
|  | @ -129,7 +129,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { | |||
|           path: '/demosaccess', | ||||
|           meta: { | ||||
|             icon: 'mdi:cloud-key-outline', | ||||
|             title: 'page.demos.access.backendPermissions', | ||||
|             title: 'demos.access.backendPermissions', | ||||
|           }, | ||||
|           redirect: '/demos/access/page-control', | ||||
|           children: [ | ||||
|  | @ -139,7 +139,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { | |||
|               component: '/demos/access/index', | ||||
|               meta: { | ||||
|                 icon: 'mdi:page-previous-outline', | ||||
|                 title: 'page.demos.access.pageAccess', | ||||
|                 title: 'demos.access.pageAccess', | ||||
|               }, | ||||
|             }, | ||||
|             { | ||||
|  | @ -148,7 +148,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { | |||
|               component: '/demos/access/button-control', | ||||
|               meta: { | ||||
|                 icon: 'mdi:button-cursor', | ||||
|                 title: 'page.demos.access.buttonControl', | ||||
|                 title: 'demos.access.buttonControl', | ||||
|               }, | ||||
|             }, | ||||
|             { | ||||
|  | @ -159,7 +159,7 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { | |||
|                 authority: ['no-body'], | ||||
|                 icon: 'mdi:button-cursor', | ||||
|                 menuVisibleWithForbidden: true, | ||||
|                 title: 'page.demos.access.menuVisible403', | ||||
|                 title: 'demos.access.menuVisible403', | ||||
|               }, | ||||
|             }, | ||||
|             roleWithMenus[role], | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ const withDefaultPlaceholder = <T extends Component>( | |||
|   type: 'input' | 'select', | ||||
| ) => { | ||||
|   return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => { | ||||
|     const placeholder = props?.placeholder || $t(`placeholder.${type}`); | ||||
|     const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`); | ||||
|     return h(component, { ...props, ...attrs, placeholder }, slots); | ||||
|   }; | ||||
| }; | ||||
|  |  | |||
|  | @ -25,14 +25,14 @@ setupVbenForm<ComponentType>({ | |||
|     // 输入项目必填国际化适配
 | ||||
|     required: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null || value.length === 0) { | ||||
|         return $t('formRules.required', [ctx.label]); | ||||
|         return $t('ui.formRules.required', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|     // 选择项目必填国际化适配
 | ||||
|     selectRequired: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null) { | ||||
|         return $t('formRules.selectRequired', [ctx.label]); | ||||
|         return $t('ui.formRules.selectRequired', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ const menus = computed(() => [ | |||
|       }); | ||||
|     }, | ||||
|     icon: BookOpenText, | ||||
|     text: $t('widgets.document'), | ||||
|     text: $t('ui.widgets.document'), | ||||
|   }, | ||||
|   { | ||||
|     handler: () => { | ||||
|  | @ -86,7 +86,7 @@ const menus = computed(() => [ | |||
|       }); | ||||
|     }, | ||||
|     icon: CircleHelp, | ||||
|     text: $t('widgets.qa'), | ||||
|     text: $t('ui.widgets.qa'), | ||||
|   }, | ||||
| ]); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,11 @@ import type { Locale } from 'ant-design-vue/es/locale'; | |||
| import type { App } from 'vue'; | ||||
| import { ref } from 'vue'; | ||||
| 
 | ||||
| import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales'; | ||||
| import { | ||||
|   $t, | ||||
|   setupI18n as coreSetup, | ||||
|   loadLocalesMapFromDir, | ||||
| } from '@vben/locales'; | ||||
| import { preferences } from '@vben/preferences'; | ||||
| 
 | ||||
| import antdEnLocale from 'ant-design-vue/es/locale/en_US'; | ||||
|  | @ -13,10 +17,12 @@ import dayjs from 'dayjs'; | |||
| 
 | ||||
| const antdLocale = ref<Locale>(antdDefaultLocale); | ||||
| 
 | ||||
| const modules = import.meta.glob('./langs/*.json'); | ||||
| 
 | ||||
| const localesMap = loadLocalesMap(modules); | ||||
| const modules = import.meta.glob('./langs/**/*.json'); | ||||
| 
 | ||||
| const localesMap = loadLocalesMapFromDir( | ||||
|   /\.\/langs\/([^/]+)\/(.*)\.json$/, | ||||
|   modules, | ||||
| ); | ||||
| /** | ||||
|  * 加载应用特有的语言包 | ||||
|  * 这里也可以改造为从服务端获取翻译数据 | ||||
|  |  | |||
|  | @ -1,8 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "demos": { | ||||
|       "title": "Demos", | ||||
|       "antd": "Ant Design Vue" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,12 @@ | |||
| { | ||||
|   "title": "Demos", | ||||
|   "antd": "Ant Design Vue", | ||||
|   "vben": { | ||||
|     "title": "Project", | ||||
|     "about": "About", | ||||
|     "document": "Document", | ||||
|     "antdv": "Ant Design Vue Version", | ||||
|     "naive-ui": "Naive UI Version", | ||||
|     "element-plus": "Element Plus Version" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "auth": { | ||||
|     "login": "Login", | ||||
|     "register": "Register", | ||||
|     "codeLogin": "Code Login", | ||||
|     "qrcodeLogin": "Qr Code Login", | ||||
|     "forgetPassword": "Forget Password" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "title": "Dashboard", | ||||
|     "analytics": "Analytics", | ||||
|     "workspace": "Workspace" | ||||
|   } | ||||
| } | ||||
|  | @ -1,8 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "demos": { | ||||
|       "title": "演示", | ||||
|       "antd": "Ant Design Vue" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,12 @@ | |||
| { | ||||
|   "title": "演示", | ||||
|   "antd": "Ant Design Vue", | ||||
|   "vben": { | ||||
|     "title": "项目", | ||||
|     "about": "关于", | ||||
|     "document": "文档", | ||||
|     "antdv": "Ant Design Vue 版本", | ||||
|     "naive-ui": "Naive UI 版本", | ||||
|     "element-plus": "Element Plus 版本" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "auth": { | ||||
|     "login": "登陆", | ||||
|     "register": "注册", | ||||
|     "codeLogin": "验证码登陆", | ||||
|     "qrcodeLogin": "二维码登陆", | ||||
|     "forgetPassword": "忘记密码" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "title": "概览", | ||||
|     "analytics": "分析页", | ||||
|     "workspace": "工作台" | ||||
|   } | ||||
| } | ||||
|  | @ -43,7 +43,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'login', | ||||
|         component: Login, | ||||
|         meta: { | ||||
|           title: $t('page.core.login'), | ||||
|           title: $t('page.auth.login'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -51,7 +51,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'code-login', | ||||
|         component: () => import('#/views/_core/authentication/code-login.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.codeLogin'), | ||||
|           title: $t('page.auth.codeLogin'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -60,7 +60,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         component: () => | ||||
|           import('#/views/_core/authentication/qrcode-login.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.qrcodeLogin'), | ||||
|           title: $t('page.auth.qrcodeLogin'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -69,7 +69,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         component: () => | ||||
|           import('#/views/_core/authentication/forget-password.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.forgetPassword'), | ||||
|           title: $t('page.auth.forgetPassword'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -77,7 +77,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'register', | ||||
|         component: () => import('#/views/_core/authentication/register.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.register'), | ||||
|           title: $t('page.auth.register'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  |  | |||
|  | @ -10,14 +10,14 @@ const routes: RouteRecordRaw[] = [ | |||
|       icon: 'ic:baseline-view-in-ar', | ||||
|       keepAlive: true, | ||||
|       order: 1000, | ||||
|       title: $t('page.demos.title'), | ||||
|       title: $t('demos.title'), | ||||
|     }, | ||||
|     name: 'Demos', | ||||
|     path: '/demos', | ||||
|     children: [ | ||||
|       { | ||||
|         meta: { | ||||
|           title: $t('page.demos.antd'), | ||||
|           title: $t('demos.antd'), | ||||
|         }, | ||||
|         name: 'AntDesignDemos', | ||||
|         path: '/demos/ant-design', | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       badgeType: 'dot', | ||||
|       icon: VBEN_LOGO_URL, | ||||
|       order: 9999, | ||||
|       title: $t('page.vben.title'), | ||||
|       title: $t('demos.vben.title'), | ||||
|     }, | ||||
|     name: 'VbenProject', | ||||
|     path: '/vben-admin', | ||||
|  | @ -29,7 +29,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         component: () => import('#/views/_core/about/index.vue'), | ||||
|         meta: { | ||||
|           icon: 'lucide:copyright', | ||||
|           title: $t('page.vben.about'), | ||||
|           title: $t('demos.vben.about'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -39,7 +39,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         meta: { | ||||
|           icon: 'lucide:book-open-text', | ||||
|           link: VBEN_DOC_URL, | ||||
|           title: $t('page.vben.document'), | ||||
|           title: $t('demos.vben.document'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -60,7 +60,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: 'logos:naiveui', | ||||
|           link: VBEN_NAIVE_PREVIEW_URL, | ||||
|           title: $t('page.vben.naive-ui'), | ||||
|           title: $t('demos.vben.naive-ui'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -71,7 +71,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: 'logos:element', | ||||
|           link: VBEN_ELE_PREVIEW_URL, | ||||
|           title: $t('page.vben.element-plus'), | ||||
|           title: $t('demos.vben.element-plus'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ const withDefaultPlaceholder = <T extends Component>( | |||
|   type: 'input' | 'select', | ||||
| ) => { | ||||
|   return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => { | ||||
|     const placeholder = props?.placeholder || $t(`placeholder.${type}`); | ||||
|     const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`); | ||||
|     return h(component, { ...props, ...attrs, placeholder }, slots); | ||||
|   }; | ||||
| }; | ||||
|  |  | |||
|  | @ -17,13 +17,13 @@ setupVbenForm<ComponentType>({ | |||
|   defineRules: { | ||||
|     required: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null || value.length === 0) { | ||||
|         return $t('formRules.required', [ctx.label]); | ||||
|         return $t('ui.formRules.required', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|     selectRequired: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null) { | ||||
|         return $t('formRules.selectRequired', [ctx.label]); | ||||
|         return $t('ui.formRules.selectRequired', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ const menus = computed(() => [ | |||
|       }); | ||||
|     }, | ||||
|     icon: BookOpenText, | ||||
|     text: $t('widgets.document'), | ||||
|     text: $t('ui.widgets.document'), | ||||
|   }, | ||||
|   { | ||||
|     handler: () => { | ||||
|  | @ -86,7 +86,7 @@ const menus = computed(() => [ | |||
|       }); | ||||
|     }, | ||||
|     icon: CircleHelp, | ||||
|     text: $t('widgets.qa'), | ||||
|     text: $t('ui.widgets.qa'), | ||||
|   }, | ||||
| ]); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,11 @@ import type { Language } from 'element-plus/es/locale'; | |||
| import type { App } from 'vue'; | ||||
| import { ref } from 'vue'; | ||||
| 
 | ||||
| import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales'; | ||||
| import { | ||||
|   $t, | ||||
|   setupI18n as coreSetup, | ||||
|   loadLocalesMapFromDir, | ||||
| } from '@vben/locales'; | ||||
| import { preferences } from '@vben/preferences'; | ||||
| 
 | ||||
| import dayjs from 'dayjs'; | ||||
|  | @ -13,10 +17,12 @@ import defaultLocale from 'element-plus/es/locale/lang/zh-cn'; | |||
| 
 | ||||
| const elementLocale = ref<Language>(defaultLocale); | ||||
| 
 | ||||
| const modules = import.meta.glob('./langs/*.json'); | ||||
| 
 | ||||
| const localesMap = loadLocalesMap(modules); | ||||
| const modules = import.meta.glob('./langs/**/*.json'); | ||||
| 
 | ||||
| const localesMap = loadLocalesMapFromDir( | ||||
|   /\.\/langs\/([^/]+)\/(.*)\.json$/, | ||||
|   modules, | ||||
| ); | ||||
| /** | ||||
|  * 加载应用特有的语言包 | ||||
|  * 这里也可以改造为从服务端获取翻译数据 | ||||
|  |  | |||
|  | @ -1,8 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "demos": { | ||||
|       "title": "Demos", | ||||
|       "element-plus": "Element Plus" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,12 @@ | |||
| { | ||||
|   "title": "Demos", | ||||
|   "elementPlus": "Element Plus", | ||||
|   "vben": { | ||||
|     "title": "Project", | ||||
|     "about": "About", | ||||
|     "document": "Document", | ||||
|     "antdv": "Ant Design Vue Version", | ||||
|     "naive-ui": "Naive UI Version", | ||||
|     "element-plus": "Element Plus Version" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "auth": { | ||||
|     "login": "Login", | ||||
|     "register": "Register", | ||||
|     "codeLogin": "Code Login", | ||||
|     "qrcodeLogin": "Qr Code Login", | ||||
|     "forgetPassword": "Forget Password" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "title": "Dashboard", | ||||
|     "analytics": "Analytics", | ||||
|     "workspace": "Workspace" | ||||
|   } | ||||
| } | ||||
|  | @ -1,8 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "demos": { | ||||
|       "title": "演示", | ||||
|       "element-plus": "Element Plus" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,12 @@ | |||
| { | ||||
|   "title": "演示", | ||||
|   "elementPlus": "Element Plus", | ||||
|   "vben": { | ||||
|     "title": "项目", | ||||
|     "about": "关于", | ||||
|     "document": "文档", | ||||
|     "antdv": "Ant Design Vue 版本", | ||||
|     "naive-ui": "Naive UI 版本", | ||||
|     "element-plus": "Element Plus 版本" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "auth": { | ||||
|     "login": "登陆", | ||||
|     "register": "注册", | ||||
|     "codeLogin": "验证码登陆", | ||||
|     "qrcodeLogin": "二维码登陆", | ||||
|     "forgetPassword": "忘记密码" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "title": "概览", | ||||
|     "analytics": "分析页", | ||||
|     "workspace": "工作台" | ||||
|   } | ||||
| } | ||||
|  | @ -43,7 +43,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'login', | ||||
|         component: Login, | ||||
|         meta: { | ||||
|           title: $t('page.core.login'), | ||||
|           title: $t('page.auth.login'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -51,7 +51,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'code-login', | ||||
|         component: () => import('#/views/_core/authentication/code-login.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.codeLogin'), | ||||
|           title: $t('page.auth.codeLogin'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -60,7 +60,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         component: () => | ||||
|           import('#/views/_core/authentication/qrcode-login.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.qrcodeLogin'), | ||||
|           title: $t('page.auth.qrcodeLogin'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -69,7 +69,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         component: () => | ||||
|           import('#/views/_core/authentication/forget-password.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.forgetPassword'), | ||||
|           title: $t('page.auth.forgetPassword'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -77,7 +77,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'register', | ||||
|         component: () => import('#/views/_core/authentication/register.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.register'), | ||||
|           title: $t('page.auth.register'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  |  | |||
|  | @ -10,14 +10,14 @@ const routes: RouteRecordRaw[] = [ | |||
|       icon: 'ic:baseline-view-in-ar', | ||||
|       keepAlive: true, | ||||
|       order: 1000, | ||||
|       title: $t('page.demos.title'), | ||||
|       title: $t('demos.title'), | ||||
|     }, | ||||
|     name: 'Demos', | ||||
|     path: '/demos', | ||||
|     children: [ | ||||
|       { | ||||
|         meta: { | ||||
|           title: $t('page.demos.element-plus'), | ||||
|           title: $t('demos.elementPlus'), | ||||
|         }, | ||||
|         name: 'NaiveDemos', | ||||
|         path: '/demos/element', | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       badgeType: 'dot', | ||||
|       icon: VBEN_LOGO_URL, | ||||
|       order: 9999, | ||||
|       title: $t('page.vben.title'), | ||||
|       title: $t('demos.vben.title'), | ||||
|     }, | ||||
|     name: 'VbenProject', | ||||
|     path: '/vben-admin', | ||||
|  | @ -30,7 +30,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         component: () => import('#/views/_core/about/index.vue'), | ||||
|         meta: { | ||||
|           icon: 'lucide:copyright', | ||||
|           title: $t('page.vben.about'), | ||||
|           title: $t('demos.vben.about'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -40,7 +40,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         meta: { | ||||
|           icon: 'lucide:book-open-text', | ||||
|           link: VBEN_DOC_URL, | ||||
|           title: $t('page.vben.document'), | ||||
|           title: $t('demos.vben.document'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -61,7 +61,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: 'logos:naiveui', | ||||
|           link: VBEN_NAIVE_PREVIEW_URL, | ||||
|           title: $t('page.vben.naive-ui'), | ||||
|           title: $t('demos.vben.naive-ui'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -72,7 +72,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: SvgAntdvLogoIcon, | ||||
|           link: VBEN_ANT_PREVIEW_URL, | ||||
|           title: $t('page.vben.antdv'), | ||||
|           title: $t('demos.vben.antdv'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ const withDefaultPlaceholder = <T extends Component>( | |||
|   type: 'input' | 'select', | ||||
| ) => { | ||||
|   return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => { | ||||
|     const placeholder = props?.placeholder || $t(`placeholder.${type}`); | ||||
|     const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`); | ||||
|     return h(component, { ...props, ...attrs, placeholder }, slots); | ||||
|   }; | ||||
| }; | ||||
|  |  | |||
|  | @ -24,13 +24,13 @@ setupVbenForm<ComponentType>({ | |||
|   defineRules: { | ||||
|     required: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null || value.length === 0) { | ||||
|         return $t('formRules.required', [ctx.label]); | ||||
|         return $t('ui.formRules.required', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|     selectRequired: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null) { | ||||
|         return $t('formRules.selectRequired', [ctx.label]); | ||||
|         return $t('ui.formRules.selectRequired', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ const menus = computed(() => [ | |||
|       }); | ||||
|     }, | ||||
|     icon: BookOpenText, | ||||
|     text: $t('widgets.document'), | ||||
|     text: $t('ui.widgets.document'), | ||||
|   }, | ||||
|   { | ||||
|     handler: () => { | ||||
|  | @ -86,7 +86,7 @@ const menus = computed(() => [ | |||
|       }); | ||||
|     }, | ||||
|     icon: CircleHelp, | ||||
|     text: $t('widgets.qa'), | ||||
|     text: $t('ui.widgets.qa'), | ||||
|   }, | ||||
| ]); | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,12 +2,19 @@ import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; | |||
| 
 | ||||
| import type { App } from 'vue'; | ||||
| 
 | ||||
| import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales'; | ||||
| import { | ||||
|   $t, | ||||
|   setupI18n as coreSetup, | ||||
|   loadLocalesMapFromDir, | ||||
| } from '@vben/locales'; | ||||
| import { preferences } from '@vben/preferences'; | ||||
| 
 | ||||
| const modules = import.meta.glob('./langs/*.json'); | ||||
| const modules = import.meta.glob('./langs/**/*.json'); | ||||
| 
 | ||||
| const localesMap = loadLocalesMap(modules); | ||||
| const localesMap = loadLocalesMapFromDir( | ||||
|   /\.\/langs\/([^/]+)\/(.*)\.json$/, | ||||
|   modules, | ||||
| ); | ||||
| 
 | ||||
| /** | ||||
|  * 加载应用特有的语言包 | ||||
|  |  | |||
|  | @ -1,9 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "demos": { | ||||
|       "title": "Demos", | ||||
|       "naive": "Naive UI", | ||||
|       "table": "Table" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| { | ||||
|   "title": "Demos", | ||||
|   "naive": "Naive UI", | ||||
|   "table": "Table", | ||||
|   "vben": { | ||||
|     "title": "Project", | ||||
|     "about": "About", | ||||
|     "document": "Document", | ||||
|     "antdv": "Ant Design Vue Version", | ||||
|     "naive-ui": "Naive UI Version", | ||||
|     "element-plus": "Element Plus Version" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "auth": { | ||||
|     "login": "Login", | ||||
|     "register": "Register", | ||||
|     "codeLogin": "Code Login", | ||||
|     "qrcodeLogin": "Qr Code Login", | ||||
|     "forgetPassword": "Forget Password" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "title": "Dashboard", | ||||
|     "analytics": "Analytics", | ||||
|     "workspace": "Workspace" | ||||
|   } | ||||
| } | ||||
|  | @ -1,9 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "demos": { | ||||
|       "title": "演示", | ||||
|       "naive": "Naive UI", | ||||
|       "table": "Table" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| { | ||||
|   "title": "演示", | ||||
|   "naive": "Naive UI", | ||||
|   "table": "Table", | ||||
|   "vben": { | ||||
|     "title": "项目", | ||||
|     "about": "关于", | ||||
|     "document": "文档", | ||||
|     "antdv": "Ant Design Vue 版本", | ||||
|     "naive-ui": "Naive UI 版本", | ||||
|     "element-plus": "Element Plus 版本" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "auth": { | ||||
|     "login": "登陆", | ||||
|     "register": "注册", | ||||
|     "codeLogin": "验证码登陆", | ||||
|     "qrcodeLogin": "二维码登陆", | ||||
|     "forgetPassword": "忘记密码" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "title": "概览", | ||||
|     "analytics": "分析页", | ||||
|     "workspace": "工作台" | ||||
|   } | ||||
| } | ||||
|  | @ -43,7 +43,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'login', | ||||
|         component: Login, | ||||
|         meta: { | ||||
|           title: $t('page.core.login'), | ||||
|           title: $t('page.auth.login'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -51,7 +51,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'code-login', | ||||
|         component: () => import('#/views/_core/authentication/code-login.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.codeLogin'), | ||||
|           title: $t('page.auth.codeLogin'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -60,7 +60,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         component: () => | ||||
|           import('#/views/_core/authentication/qrcode-login.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.qrcodeLogin'), | ||||
|           title: $t('page.auth.qrcodeLogin'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -69,7 +69,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         component: () => | ||||
|           import('#/views/_core/authentication/forget-password.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.forgetPassword'), | ||||
|           title: $t('page.auth.forgetPassword'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -77,7 +77,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'register', | ||||
|         component: () => import('#/views/_core/authentication/register.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.register'), | ||||
|           title: $t('page.auth.register'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  |  | |||
|  | @ -10,14 +10,14 @@ const routes: RouteRecordRaw[] = [ | |||
|       icon: 'ic:baseline-view-in-ar', | ||||
|       keepAlive: true, | ||||
|       order: 1000, | ||||
|       title: $t('page.demos.title'), | ||||
|       title: $t('demos.title'), | ||||
|     }, | ||||
|     name: 'Demos', | ||||
|     path: '/demos', | ||||
|     children: [ | ||||
|       { | ||||
|         meta: { | ||||
|           title: $t('page.demos.naive'), | ||||
|           title: $t('demos.naive'), | ||||
|         }, | ||||
|         name: 'NaiveDemos', | ||||
|         path: '/demos/naive', | ||||
|  | @ -25,7 +25,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       }, | ||||
|       { | ||||
|         meta: { | ||||
|           title: $t('page.demos.table'), | ||||
|           title: $t('demos.table'), | ||||
|         }, | ||||
|         name: 'Table', | ||||
|         path: '/demos/table', | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       badgeType: 'dot', | ||||
|       icon: VBEN_LOGO_URL, | ||||
|       order: 9999, | ||||
|       title: $t('page.vben.title'), | ||||
|       title: $t('demos.vben.title'), | ||||
|     }, | ||||
|     name: 'VbenProject', | ||||
|     path: '/vben-admin', | ||||
|  | @ -30,7 +30,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         component: () => import('#/views/_core/about/index.vue'), | ||||
|         meta: { | ||||
|           icon: 'lucide:copyright', | ||||
|           title: $t('page.vben.about'), | ||||
|           title: $t('demos.vben.about'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -40,7 +40,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         meta: { | ||||
|           icon: 'lucide:book-open-text', | ||||
|           link: VBEN_DOC_URL, | ||||
|           title: $t('page.vben.document'), | ||||
|           title: $t('demos.vben.document'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -61,7 +61,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: SvgAntdvLogoIcon, | ||||
|           link: VBEN_ANT_PREVIEW_URL, | ||||
|           title: $t('page.vben.antdv'), | ||||
|           title: $t('demos.vben.antdv'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -72,7 +72,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: 'logos:element', | ||||
|           link: VBEN_ELE_PREVIEW_URL, | ||||
|           title: $t('page.vben.element-plus'), | ||||
|           title: $t('demos.vben.element-plus'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ const withDefaultPlaceholder = <T extends Component>( | |||
|   type: 'input' | 'select', | ||||
| ) => { | ||||
|   return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => { | ||||
|     const placeholder = props?.placeholder || $t(`placeholder.${type}`); | ||||
|     const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`); | ||||
|     return h(component, { ...props, ...attrs, placeholder }, slots); | ||||
|   }; | ||||
| }; | ||||
|  |  | |||
|  | @ -28,13 +28,13 @@ setupVbenForm<ComponentType>({ | |||
|   defineRules: { | ||||
|     required: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null || value.length === 0) { | ||||
|         return $t('formRules.required', [ctx.label]); | ||||
|         return $t('ui.formRules.required', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|     selectRequired: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null) { | ||||
|         return $t('formRules.selectRequired', [ctx.label]); | ||||
|         return $t('ui.formRules.selectRequired', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|  |  | |||
|  | @ -53,7 +53,7 @@ Drawer 内的内容一般业务中,会比较复杂,所以我们可以将 dra | |||
| ::: info 注意 | ||||
| 
 | ||||
| - `VbenDrawer` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenDrawer参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 | ||||
| - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenDrawer`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onComfirm`,那么以内部的 `onComfirm` 为准。`onOpenChange`事件除外,内外都会触发。 | ||||
| - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenDrawer`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。 | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
|  |  | |||
|  | @ -51,14 +51,14 @@ setupVbenForm<ComponentType>({ | |||
|     // 输入项目必填国际化适配 | ||||
|     required: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null || value.length === 0) { | ||||
|         return $t('formRules.required', [ctx.label]); | ||||
|         return $t('ui.formRules.required', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|     // 选择项目必填国际化适配 | ||||
|     selectRequired: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null) { | ||||
|         return $t('formRules.selectRequired', [ctx.label]); | ||||
|         return $t('ui.formRules.selectRequired', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|  | @ -120,7 +120,7 @@ const withDefaultPlaceholder = <T extends Component>( | |||
|   type: 'input' | 'select', | ||||
| ) => { | ||||
|   return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => { | ||||
|     const placeholder = props?.placeholder || $t(`placeholder.${type}`); | ||||
|     const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`); | ||||
|     return h(component, { ...props, ...attrs, placeholder }, slots); | ||||
|   }; | ||||
| }; | ||||
|  |  | |||
|  | @ -59,7 +59,7 @@ Modal 内的内容一般业务中,会比较复杂,所以我们可以将 moda | |||
| ::: info 注意 | ||||
| 
 | ||||
| - `VbenModal` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenModal参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 | ||||
| - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onComfirm`,那么以内部的 `onComfirm` 为准。`onOpenChange`事件除外,内外都会触发。 | ||||
| - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。 | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
|  |  | |||
|  | @ -106,7 +106,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       icon: 'ic:baseline-view-in-ar', | ||||
|       keepAlive: true, | ||||
|       order: 1000, | ||||
|       title: $t('page.demos.title'), | ||||
|       title: $t('demos.title'), | ||||
|     }, | ||||
|     name: 'Demos', | ||||
|     path: '/demos', | ||||
|  | @ -116,7 +116,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       { | ||||
|         meta: { | ||||
|           icon: 'ic:round-menu', | ||||
|           title: $t('page.demos.nested.title'), | ||||
|           title: $t('demos.nested.title'), | ||||
|         }, | ||||
|         name: 'NestedDemos', | ||||
|         path: '/demos/nested', | ||||
|  | @ -129,7 +129,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               keepAlive: true, | ||||
|               title: $t('page.demos.nested.menu1'), | ||||
|               title: $t('demos.nested.menu1'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -138,7 +138,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               keepAlive: true, | ||||
|               title: $t('page.demos.nested.menu2'), | ||||
|               title: $t('demos.nested.menu2'), | ||||
|             }, | ||||
|             redirect: '/demos/nested/menu2/menu2-1', | ||||
|             children: [ | ||||
|  | @ -149,7 +149,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   keepAlive: true, | ||||
|                   title: $t('page.demos.nested.menu2_1'), | ||||
|                   title: $t('demos.nested.menu2_1'), | ||||
|                 }, | ||||
|               }, | ||||
|             ], | ||||
|  | @ -159,7 +159,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/demos/nested/menu3', | ||||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               title: $t('page.demos.nested.menu3'), | ||||
|               title: $t('demos.nested.menu3'), | ||||
|             }, | ||||
|             redirect: '/demos/nested/menu3/menu3-1', | ||||
|             children: [ | ||||
|  | @ -170,7 +170,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   keepAlive: true, | ||||
|                   title: $t('page.demos.nested.menu3_1'), | ||||
|                   title: $t('demos.nested.menu3_1'), | ||||
|                 }, | ||||
|               }, | ||||
|               { | ||||
|  | @ -178,7 +178,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 path: 'menu3-2', | ||||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   title: $t('page.demos.nested.menu3_2'), | ||||
|                   title: $t('demos.nested.menu3_2'), | ||||
|                 }, | ||||
|                 redirect: '/demos/nested/menu3/menu3-2/menu3-2-1', | ||||
|                 children: [ | ||||
|  | @ -190,7 +190,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                     meta: { | ||||
|                       icon: 'ic:round-menu', | ||||
|                       keepAlive: true, | ||||
|                       title: $t('page.demos.nested.menu3_2_1'), | ||||
|                       title: $t('demos.nested.menu3_2_1'), | ||||
|                     }, | ||||
|                   }, | ||||
|                 ], | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ updateLocale('en-US'); | |||
| 
 | ||||
| To add new translation texts, simply find `src/locales/langs/` in the corresponding application and add the texts accordingly, for example: | ||||
| 
 | ||||
| **src/locales/langs/zh-CN.ts** | ||||
| **src/locales/langs/zh-CN/\*.json** | ||||
| 
 | ||||
| ````ts | ||||
| ```json | ||||
|  |  | |||
|  | @ -105,7 +105,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       icon: 'ic:baseline-view-in-ar', | ||||
|       keepAlive: true, | ||||
|       order: 1000, | ||||
|       title: $t('page.demos.title'), | ||||
|       title: $t('demos.title'), | ||||
|     }, | ||||
|     name: 'Demos', | ||||
|     path: '/demos', | ||||
|  | @ -115,7 +115,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       { | ||||
|         meta: { | ||||
|           icon: 'ic:round-menu', | ||||
|           title: $t('page.demos.nested.title'), | ||||
|           title: $t('demos.nested.title'), | ||||
|         }, | ||||
|         name: 'NestedDemos', | ||||
|         path: '/demos/nested', | ||||
|  | @ -128,7 +128,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               keepAlive: true, | ||||
|               title: $t('page.demos.nested.menu1'), | ||||
|               title: $t('demos.nested.menu1'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -137,7 +137,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               keepAlive: true, | ||||
|               title: $t('page.demos.nested.menu2'), | ||||
|               title: $t('demos.nested.menu2'), | ||||
|             }, | ||||
|             redirect: '/demos/nested/menu2/menu2-1', | ||||
|             children: [ | ||||
|  | @ -148,7 +148,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   keepAlive: true, | ||||
|                   title: $t('page.demos.nested.menu2_1'), | ||||
|                   title: $t('demos.nested.menu2_1'), | ||||
|                 }, | ||||
|               }, | ||||
|             ], | ||||
|  | @ -158,7 +158,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/demos/nested/menu3', | ||||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               title: $t('page.demos.nested.menu3'), | ||||
|               title: $t('demos.nested.menu3'), | ||||
|             }, | ||||
|             redirect: '/demos/nested/menu3/menu3-1', | ||||
|             children: [ | ||||
|  | @ -169,7 +169,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   keepAlive: true, | ||||
|                   title: $t('page.demos.nested.menu3_1'), | ||||
|                   title: $t('demos.nested.menu3_1'), | ||||
|                 }, | ||||
|               }, | ||||
|               { | ||||
|  | @ -177,7 +177,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 path: 'menu3-2', | ||||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   title: $t('page.demos.nested.menu3_2'), | ||||
|                   title: $t('demos.nested.menu3_2'), | ||||
|                 }, | ||||
|                 redirect: '/demos/nested/menu3/menu3-2/menu3-2-1', | ||||
|                 children: [ | ||||
|  | @ -189,7 +189,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                     meta: { | ||||
|                       icon: 'ic:round-menu', | ||||
|                       keepAlive: true, | ||||
|                       title: $t('page.demos.nested.menu3_2_1'), | ||||
|                       title: $t('demos.nested.menu3_2_1'), | ||||
|                     }, | ||||
|                   }, | ||||
|                 ], | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ updateLocale('en-US'); | |||
| 
 | ||||
| 新增翻译文本,只需要在对应的应用内,找到 `src/locales/langs/`,新增对应的文本即可,例: | ||||
| 
 | ||||
| **src/locales/langs/zh-CN.ts** | ||||
| **src/locales/langs/zh-CN/\*.json** | ||||
| 
 | ||||
| ````ts | ||||
| ```json | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| { | ||||
|   "name": "vben-admin-pro", | ||||
|   "name": "vben-admin-monorepo", | ||||
|   "version": "5.4.1", | ||||
|   "private": true, | ||||
|   "keywords": [ | ||||
|  |  | |||
|  | @ -40,7 +40,6 @@ | |||
|     "@vben-core/composables": "workspace:*", | ||||
|     "@vben-core/icons": "workspace:*", | ||||
|     "@vben-core/shadcn-ui": "workspace:*", | ||||
|     "@vben-core/shared": "workspace:*", | ||||
|     "@vben-core/typings": "workspace:*", | ||||
|     "@vueuse/core": "catalog:", | ||||
|     "vue": "catalog:" | ||||
|  |  | |||
|  | @ -40,19 +40,19 @@ const titleText = computed(() => { | |||
| 
 | ||||
|   switch (props.status) { | ||||
|     case '403': { | ||||
|       return $t('fallback.forbidden'); | ||||
|       return $t('ui.fallback.forbidden'); | ||||
|     } | ||||
|     case '404': { | ||||
|       return $t('fallback.pageNotFound'); | ||||
|       return $t('ui.fallback.pageNotFound'); | ||||
|     } | ||||
|     case '500': { | ||||
|       return $t('fallback.internalError'); | ||||
|       return $t('ui.fallback.internalError'); | ||||
|     } | ||||
|     case 'coming-soon': { | ||||
|       return $t('fallback.comingSoon'); | ||||
|       return $t('ui.fallback.comingSoon'); | ||||
|     } | ||||
|     case 'offline': { | ||||
|       return $t('fallback.offlineError'); | ||||
|       return $t('ui.fallback.offlineError'); | ||||
|     } | ||||
|     default: { | ||||
|       return ''; | ||||
|  | @ -66,16 +66,16 @@ const descText = computed(() => { | |||
|   } | ||||
|   switch (props.status) { | ||||
|     case '403': { | ||||
|       return $t('fallback.forbiddenDesc'); | ||||
|       return $t('ui.fallback.forbiddenDesc'); | ||||
|     } | ||||
|     case '404': { | ||||
|       return $t('fallback.pageNotFoundDesc'); | ||||
|       return $t('ui.fallback.pageNotFoundDesc'); | ||||
|     } | ||||
|     case '500': { | ||||
|       return $t('fallback.internalErrorDesc'); | ||||
|       return $t('ui.fallback.internalErrorDesc'); | ||||
|     } | ||||
|     case 'offline': { | ||||
|       return $t('fallback.offlineErrorDesc'); | ||||
|       return $t('ui.fallback.offlineErrorDesc'); | ||||
|     } | ||||
|     default: { | ||||
|       return ''; | ||||
|  |  | |||
|  | @ -123,12 +123,12 @@ onUnmounted(() => { | |||
|     :cancel-text="$t('common.cancel')" | ||||
|     :confirm-text="$t('common.refresh')" | ||||
|     :fullscreen-button="false" | ||||
|     :title="$t('widgets.checkUpdatesTitle')" | ||||
|     :title="$t('ui.widgets.checkUpdatesTitle')" | ||||
|     centered | ||||
|     content-class="px-8 min-h-10" | ||||
|     footer-class="border-none mb-3 mr-3" | ||||
|     header-class="border-none" | ||||
|   > | ||||
|     {{ $t('widgets.checkUpdatesDescription') }} | ||||
|     {{ $t('ui.widgets.checkUpdatesDescription') }} | ||||
|   </UpdateNoticeModal> | ||||
| </template> | ||||
|  |  | |||
|  | @ -102,7 +102,7 @@ onMounted(() => { | |||
|           <input | ||||
|             ref="searchInputRef" | ||||
|             v-model="keyword" | ||||
|             :placeholder="$t('widgets.search.searchNavigate')" | ||||
|             :placeholder="$t('ui.widgets.search.searchNavigate')" | ||||
|             class="ring-none placeholder:text-muted-foreground w-[80%] rounded-md border border-none bg-transparent p-2 pl-0 text-sm font-normal outline-none ring-0 ring-offset-transparent focus-visible:ring-transparent" | ||||
|           /> | ||||
|         </div> | ||||
|  | @ -113,16 +113,16 @@ onMounted(() => { | |||
|         <div class="flex w-full justify-start text-xs"> | ||||
|           <div class="mr-2 flex items-center"> | ||||
|             <CornerDownLeft class="mr-1 size-3" /> | ||||
|             {{ $t('widgets.search.select') }} | ||||
|             {{ $t('ui.widgets.search.select') }} | ||||
|           </div> | ||||
|           <div class="mr-2 flex items-center"> | ||||
|             <ArrowUp class="mr-1 size-3" /> | ||||
|             <ArrowDown class="mr-1 size-3" /> | ||||
|             {{ $t('widgets.search.navigate') }} | ||||
|             {{ $t('ui.widgets.search.navigate') }} | ||||
|           </div> | ||||
|           <div class="flex items-center"> | ||||
|             <MdiKeyboardEsc class="mr-1 size-3" /> | ||||
|             {{ $t('widgets.search.close') }} | ||||
|             {{ $t('ui.widgets.search.close') }} | ||||
|           </div> | ||||
|         </div> | ||||
|       </template> | ||||
|  | @ -137,7 +137,7 @@ onMounted(() => { | |||
|       <span | ||||
|         class="text-muted-foreground group-hover:text-foreground hidden text-xs duration-300 md:block" | ||||
|       > | ||||
|         {{ $t('widgets.search.title') }} | ||||
|         {{ $t('ui.widgets.search.title') }} | ||||
|       </span> | ||||
|       <span | ||||
|         v-if="enableShortcutKey" | ||||
|  |  | |||
|  | @ -230,7 +230,7 @@ onMounted(() => { | |||
|       > | ||||
|         <SearchX class="mx-auto mt-4 size-12" /> | ||||
|         <p class="mb-10 mt-6 text-xs"> | ||||
|           {{ $t('widgets.search.noResults') }} | ||||
|           {{ $t('ui.widgets.search.noResults') }} | ||||
|           <span class="text-foreground text-sm font-medium"> | ||||
|             "{{ keyword }}" | ||||
|           </span> | ||||
|  | @ -242,7 +242,7 @@ onMounted(() => { | |||
|         class="text-muted-foreground text-center" | ||||
|       > | ||||
|         <p class="my-10 text-xs"> | ||||
|           {{ $t('widgets.search.noRecent') }} | ||||
|           {{ $t('ui.widgets.search.noRecent') }} | ||||
|         </p> | ||||
|       </div> | ||||
| 
 | ||||
|  | @ -251,7 +251,7 @@ onMounted(() => { | |||
|           v-if="searchHistory.length > 0 && !keyword" | ||||
|           class="text-muted-foreground mb-2 text-xs" | ||||
|         > | ||||
|           {{ $t('widgets.search.recent') }} | ||||
|           {{ $t('ui.widgets.search.recent') }} | ||||
|         </li> | ||||
|         <li | ||||
|           v-for="(item, index) in uniqueByField(searchResults, 'path')" | ||||
|  |  | |||
|  | @ -42,14 +42,14 @@ const [Form, { resetForm, validate }] = useVbenForm( | |||
|       { | ||||
|         component: 'VbenInputPassword' as const, | ||||
|         componentProps: { | ||||
|           placeholder: $t('widgets.lockScreen.placeholder'), | ||||
|           placeholder: $t('ui.widgets.lockScreen.placeholder'), | ||||
|         }, | ||||
|         fieldName: 'lockScreenPassword', | ||||
|         formFieldProps: { validateOnBlur: false }, | ||||
|         label: $t('authentication.password'), | ||||
|         rules: z | ||||
|           .string() | ||||
|           .min(1, { message: $t('widgets.lockScreen.placeholder') }), | ||||
|           .min(1, { message: $t('ui.widgets.lockScreen.placeholder') }), | ||||
|       }, | ||||
|     ]), | ||||
|     showDefaultActions: false, | ||||
|  | @ -79,7 +79,7 @@ async function handleSubmit() { | |||
|   <Modal | ||||
|     :footer="false" | ||||
|     :fullscreen-button="false" | ||||
|     :title="$t('widgets.lockScreen.title')" | ||||
|     :title="$t('ui.widgets.lockScreen.title')" | ||||
|   > | ||||
|     <div | ||||
|       class="mb-10 flex w-full flex-col items-center px-10" | ||||
|  | @ -98,7 +98,7 @@ async function handleSubmit() { | |||
|         </div> | ||||
|         <Form /> | ||||
|         <VbenButton class="mt-1 w-full" @click="handleSubmit"> | ||||
|           {{ $t('widgets.lockScreen.screenButton') }} | ||||
|           {{ $t('ui.widgets.lockScreen.screenButton') }} | ||||
|         </VbenButton> | ||||
|       </div> | ||||
|     </div> | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ const [Form, { form, validate }] = useVbenForm( | |||
|       { | ||||
|         component: 'VbenInputPassword' as const, | ||||
|         componentProps: { | ||||
|           placeholder: $t('widgets.lockScreen.placeholder'), | ||||
|           placeholder: $t('ui.widgets.lockScreen.placeholder'), | ||||
|         }, | ||||
|         fieldName: 'password', | ||||
|         label: $t('authentication.password'), | ||||
|  | @ -90,7 +90,7 @@ useScrollLock(); | |||
|           <LockKeyhole | ||||
|             class="size-5 transition-all duration-300 group-hover:scale-125" | ||||
|           /> | ||||
|           <span>{{ $t('widgets.lockScreen.unlock') }}</span> | ||||
|           <span>{{ $t('ui.widgets.lockScreen.unlock') }}</span> | ||||
|         </div> | ||||
|         <div class="flex h-full justify-center px-[10%]"> | ||||
|           <div | ||||
|  | @ -123,14 +123,14 @@ useScrollLock(); | |||
|             <Form /> | ||||
|           </div> | ||||
|           <VbenButton class="enter-x w-full" @click="handleSubmit"> | ||||
|             {{ $t('widgets.lockScreen.entry') }} | ||||
|             {{ $t('ui.widgets.lockScreen.entry') }} | ||||
|           </VbenButton> | ||||
|           <VbenButton | ||||
|             class="enter-x my-2 w-full" | ||||
|             variant="ghost" | ||||
|             @click="$emit('toLogin')" | ||||
|           > | ||||
|             {{ $t('widgets.lockScreen.backToLogin') }} | ||||
|             {{ $t('ui.widgets.lockScreen.backToLogin') }} | ||||
|           </VbenButton> | ||||
|           <VbenButton | ||||
|             class="enter-x mr-2 w-full" | ||||
|  |  | |||
|  | @ -79,10 +79,10 @@ function handleClick(item: NotificationItem) { | |||
| 
 | ||||
|     <div class="relative"> | ||||
|       <div class="flex items-center justify-between p-4 py-3"> | ||||
|         <div class="text-foreground">{{ $t('widgets.notifications') }}</div> | ||||
|         <div class="text-foreground">{{ $t('ui.widgets.notifications') }}</div> | ||||
|         <VbenIconButton | ||||
|           :disabled="notifications.length <= 0" | ||||
|           :tooltip="$t('widgets.markAllAsRead')" | ||||
|           :tooltip="$t('ui.widgets.markAllAsRead')" | ||||
|           @click="handleMakeAll" | ||||
|         > | ||||
|           <MailCheck class="size-4" /> | ||||
|  | @ -138,10 +138,10 @@ function handleClick(item: NotificationItem) { | |||
|           variant="ghost" | ||||
|           @click="handleClear" | ||||
|         > | ||||
|           {{ $t('widgets.clearNotifications') }} | ||||
|           {{ $t('ui.widgets.clearNotifications') }} | ||||
|         </VbenButton> | ||||
|         <VbenButton size="sm" @click="handleViewAll"> | ||||
|           {{ $t('widgets.viewAll') }} | ||||
|           {{ $t('ui.widgets.viewAll') }} | ||||
|         </VbenButton> | ||||
|       </div> | ||||
|     </div> | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ const altView = computed(() => (isWindowsOs() ? 'Alt' : '⌥')); | |||
|     <template #shortcut> {{ altView }} , </template> | ||||
|   </SwitchItem> --> | ||||
|   <SwitchItem v-model="shortcutKeysLockScreen" :disabled="!shortcutKeysEnable"> | ||||
|     {{ $t('widgets.lockScreen.title') }} | ||||
|     {{ $t('ui.widgets.lockScreen.title') }} | ||||
|     <template #shortcut> {{ altView }} L </template> | ||||
|   </SwitchItem> | ||||
| </template> | ||||
|  |  | |||
|  | @ -152,7 +152,7 @@ if (enableShortcutKey.value) { | |||
|     footer-class="border-none mb-3 mr-3" | ||||
|     header-class="border-none" | ||||
|   > | ||||
|     {{ $t('widgets.logoutTip') }} | ||||
|     {{ $t('ui.widgets.logoutTip') }} | ||||
|   </LogoutModal> | ||||
| 
 | ||||
|   <DropdownMenu> | ||||
|  | @ -206,7 +206,7 @@ if (enableShortcutKey.value) { | |||
|         @click="handleOpenLock" | ||||
|       > | ||||
|         <LockKeyhole class="mr-2 size-4" /> | ||||
|         {{ $t('widgets.lockScreen.title') }} | ||||
|         {{ $t('ui.widgets.lockScreen.title') }} | ||||
|         <DropdownMenuShortcut v-if="enableLockScreenShortcutKey"> | ||||
|           {{ altView }} L | ||||
|         </DropdownMenuShortcut> | ||||
|  |  | |||
|  | @ -82,9 +82,9 @@ export const errorMessageResponseInterceptor = ( | |||
|       const err: string = error?.toString?.() ?? ''; | ||||
|       let errMsg = ''; | ||||
|       if (err?.includes('Network Error')) { | ||||
|         errMsg = $t('fallback.http.networkError'); | ||||
|         errMsg = $t('ui.fallback.http.networkError'); | ||||
|       } else if (error?.message?.includes?.('timeout')) { | ||||
|         errMsg = $t('fallback.http.requestTimeout'); | ||||
|         errMsg = $t('ui.fallback.http.requestTimeout'); | ||||
|       } | ||||
|       if (errMsg) { | ||||
|         makeErrorMessage?.(errMsg, error); | ||||
|  | @ -96,27 +96,27 @@ export const errorMessageResponseInterceptor = ( | |||
| 
 | ||||
|       switch (status) { | ||||
|         case 400: { | ||||
|           errorMessage = $t('fallback.http.badRequest'); | ||||
|           errorMessage = $t('ui.fallback.http.badRequest'); | ||||
|           break; | ||||
|         } | ||||
|         case 401: { | ||||
|           errorMessage = $t('fallback.http.unauthorized'); | ||||
|           errorMessage = $t('ui.fallback.http.unauthorized'); | ||||
|           break; | ||||
|         } | ||||
|         case 403: { | ||||
|           errorMessage = $t('fallback.http.forbidden'); | ||||
|           errorMessage = $t('ui.fallback.http.forbidden'); | ||||
|           break; | ||||
|         } | ||||
|         case 404: { | ||||
|           errorMessage = $t('fallback.http.notFound'); | ||||
|           errorMessage = $t('ui.fallback.http.notFound'); | ||||
|           break; | ||||
|         } | ||||
|         case 408: { | ||||
|           errorMessage = $t('fallback.http.requestTimeout'); | ||||
|           errorMessage = $t('ui.fallback.http.requestTimeout'); | ||||
|           break; | ||||
|         } | ||||
|         default: { | ||||
|           errorMessage = $t('fallback.http.internalServerError'); | ||||
|           errorMessage = $t('ui.fallback.http.internalServerError'); | ||||
|         } | ||||
|       } | ||||
|       makeErrorMessage?.(errorMessage, error); | ||||
|  |  | |||
|  | @ -19,12 +19,14 @@ const i18n = createI18n({ | |||
|   messages: {}, | ||||
| }); | ||||
| 
 | ||||
| const modules = import.meta.glob('./langs/*.json'); | ||||
| const modules = import.meta.glob('./langs/**/*.json'); | ||||
| 
 | ||||
| const { setSimpleLocale } = useSimpleLocale(); | ||||
| 
 | ||||
| const localesMap = loadLocalesMap(modules); | ||||
| 
 | ||||
| const localesMap = loadLocalesMapFromDir( | ||||
|   /\.\/langs\/([^/]+)\/(.*)\.json$/, | ||||
|   modules, | ||||
| ); | ||||
| let loadMessages: LoadMessageFn; | ||||
| 
 | ||||
| /** | ||||
|  | @ -40,6 +42,48 @@ function loadLocalesMap(modules: Record<string, () => Promise<unknown>>) { | |||
|       localesMap[key] = loadLocale as ImportLocaleFn; | ||||
|     } | ||||
|   } | ||||
|   return localesMap; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Load locale modules with directory structure | ||||
|  * @param regexp - Regular expression to match language and file names | ||||
|  * @param modules - The modules object containing paths and import functions | ||||
|  * @returns A map of locales to their corresponding import functions | ||||
|  */ | ||||
| function loadLocalesMapFromDir( | ||||
|   regexp: RegExp, | ||||
|   modules: Record<string, () => Promise<unknown>>, | ||||
| ): Record<Locale, ImportLocaleFn> { | ||||
|   const localesRaw: Record<Locale, Record<string, () => Promise<unknown>>> = {}; | ||||
|   const localesMap: Record<Locale, ImportLocaleFn> = {}; | ||||
| 
 | ||||
|   // Iterate over the modules to extract language and file names
 | ||||
|   for (const path in modules) { | ||||
|     const match = path.match(regexp); | ||||
|     if (match) { | ||||
|       const [_, locale, fileName] = match; | ||||
|       if (locale && fileName) { | ||||
|         if (!localesRaw[locale]) { | ||||
|           localesRaw[locale] = {}; | ||||
|         } | ||||
|         if (modules[path]) { | ||||
|           localesRaw[locale][fileName] = modules[path]; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // Convert raw locale data into async import functions
 | ||||
|   for (const [locale, files] of Object.entries(localesRaw)) { | ||||
|     localesMap[locale] = async () => { | ||||
|       const messages: Record<string, any> = {}; | ||||
|       for (const [fileName, importFn] of Object.entries(files)) { | ||||
|         messages[fileName] = ((await importFn()) as any)?.default; | ||||
|       } | ||||
|       return { default: messages }; | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   return localesMap; | ||||
| } | ||||
|  | @ -93,4 +137,10 @@ async function loadLocaleMessages(lang: SupportedLanguagesType) { | |||
|   return setI18nLanguage(lang); | ||||
| } | ||||
| 
 | ||||
| export { i18n, loadLocaleMessages, loadLocalesMap, setupI18n }; | ||||
| export { | ||||
|   i18n, | ||||
|   loadLocaleMessages, | ||||
|   loadLocalesMap, | ||||
|   loadLocalesMapFromDir, | ||||
|   setupI18n, | ||||
| }; | ||||
|  |  | |||
|  | @ -1,8 +1,21 @@ | |||
| import { i18n, loadLocaleMessages, loadLocalesMap, setupI18n } from './i18n'; | ||||
| import { | ||||
|   i18n, | ||||
|   loadLocaleMessages, | ||||
|   loadLocalesMap, | ||||
|   loadLocalesMapFromDir, | ||||
|   setupI18n, | ||||
| } from './i18n'; | ||||
| 
 | ||||
| const $t = i18n.global.t; | ||||
| 
 | ||||
| export { $t, i18n, loadLocaleMessages, loadLocalesMap, setupI18n }; | ||||
| export { | ||||
|   $t, | ||||
|   i18n, | ||||
|   loadLocaleMessages, | ||||
|   loadLocalesMap, | ||||
|   loadLocalesMapFromDir, | ||||
|   setupI18n, | ||||
| }; | ||||
| export { | ||||
|   type ImportLocaleFn, | ||||
|   type LocaleSetupOptions, | ||||
|  |  | |||
|  | @ -1,339 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "core": { | ||||
|       "login": "Login", | ||||
|       "register": "Register", | ||||
|       "codeLogin": "Code Login", | ||||
|       "qrcodeLogin": "Qr Code Login", | ||||
|       "forgetPassword": "Forget Password" | ||||
|     }, | ||||
|     "dashboard": { | ||||
|       "title": "Dashboard", | ||||
|       "analytics": "Analytics", | ||||
|       "workspace": "Workspace" | ||||
|     }, | ||||
|     "vben": { | ||||
|       "title": "Project", | ||||
|       "about": "About", | ||||
|       "document": "Document", | ||||
|       "antdv": "Ant Design Vue Version", | ||||
|       "naive-ui": "Naive UI Version", | ||||
|       "element-plus": "Element Plus Version" | ||||
|     } | ||||
|   }, | ||||
|   "common": { | ||||
|     "back": "Back", | ||||
|     "backToHome": "Back To Home", | ||||
|     "login": "Login", | ||||
|     "logout": "Logout", | ||||
|     "prompt": "Prompt", | ||||
|     "cancel": "Cancel", | ||||
|     "confirm": "Comfirm", | ||||
|     "noData": "No Data", | ||||
|     "refresh": "Refresh", | ||||
|     "loadingMenu": "Loading Menu", | ||||
|     "query": "Search" | ||||
|   }, | ||||
|   "fallback": { | ||||
|     "pageNotFound": "Oops! Page Not Found", | ||||
|     "pageNotFoundDesc": "Sorry, we couldn't find the page you were looking for.", | ||||
|     "forbidden": "Oops! Access Denied", | ||||
|     "forbiddenDesc": "Sorry, but you don't have permission to access this page.", | ||||
|     "internalError": "Oops! Something Went Wrong", | ||||
|     "internalErrorDesc": "Sorry, but the server encountered an error.", | ||||
|     "offline": "Offline Page", | ||||
|     "offlineError": "Oops! Network Error", | ||||
|     "offlineErrorDesc": "Sorry, can't connect to the internet. Check your connection.", | ||||
|     "comingSoon": "Coming Soon", | ||||
|     "http": { | ||||
|       "requestTimeout": "The request timed out. Please try again later.", | ||||
|       "networkError": "A network error occurred. Please check your internet connection and try again.", | ||||
|       "badRequest": "Bad Request. Please check your input and try again.", | ||||
|       "unauthorized": "Unauthorized. Please log in to continue.", | ||||
|       "forbidden": "Forbidden. You do not have permission to access this resource.", | ||||
|       "notFound": "Not Found. The requested resource could not be found.", | ||||
|       "internalServerError": "Internal Server Error. Something went wrong on our end. Please try again later." | ||||
|     } | ||||
|   }, | ||||
|   "formRules": { | ||||
|     "required": "Please enter {0}", | ||||
|     "selectRequired": "Please select {0}" | ||||
|   }, | ||||
|   "placeholder": { | ||||
|     "input": "Please enter", | ||||
|     "select": "Please select" | ||||
|   }, | ||||
|   "widgets": { | ||||
|     "document": "Document", | ||||
|     "qa": "Q&A", | ||||
|     "setting": "Settings", | ||||
|     "logoutTip": "Do you want to logout?", | ||||
|     "viewAll": "View All Messages", | ||||
|     "notifications": "Notifications", | ||||
|     "markAllAsRead": "Make All as Read", | ||||
|     "clearNotifications": "Clear", | ||||
|     "checkUpdatesTitle": "New Version Available", | ||||
|     "checkUpdatesDescription": "Click to refresh and get the latest version", | ||||
|     "search": { | ||||
|       "title": "Search", | ||||
|       "searchNavigate": "Search Navigation", | ||||
|       "select": "Select", | ||||
|       "navigate": "Navigate", | ||||
|       "close": "Close", | ||||
|       "noResults": "No Search Results Found", | ||||
|       "noRecent": "No Search History", | ||||
|       "recent": "Search History" | ||||
|     }, | ||||
|     "lockScreen": { | ||||
|       "title": "Lock Screen", | ||||
|       "screenButton": "Locking", | ||||
|       "password": "Password", | ||||
|       "placeholder": "Please enter password", | ||||
|       "unlock": "Click to unlock", | ||||
|       "errorPasswordTip": "Password error, please re-enter", | ||||
|       "backToLogin": "Back to login", | ||||
|       "entry": "Enter the system" | ||||
|     } | ||||
|   }, | ||||
|   "authentication": { | ||||
|     "welcomeBack": "Welcome Back", | ||||
|     "pageTitle": "Plug-and-play Admin system", | ||||
|     "pageDesc": "Efficient, versatile frontend template", | ||||
|     "loginSuccess": "Login Successful", | ||||
|     "loginSuccessDesc": "Welcome Back", | ||||
|     "loginSubtitle": "Enter your account details to manage your projects", | ||||
|     "selectAccount": "Quick Select Account", | ||||
|     "username": "Username", | ||||
|     "password": "Password", | ||||
|     "usernameTip": "Please enter username", | ||||
|     "passwordErrorTip": "Password is incorrect", | ||||
|     "passwordTip": "Please enter password", | ||||
|     "verifyRequiredTip": "Please complete the verification first", | ||||
|     "rememberMe": "Remember Me", | ||||
|     "createAnAccount": "Create an Account", | ||||
|     "createAccount": "Create Account", | ||||
|     "alreadyHaveAccount": "Already have an account?", | ||||
|     "accountTip": "Don't have an account?", | ||||
|     "signUp": "Sign Up", | ||||
|     "signUpSubtitle": "Make managing your applications simple and fun", | ||||
|     "confirmPassword": "Comfirm Password", | ||||
|     "confirmPasswordTip": "The passwords do not match", | ||||
|     "agree": "I agree to", | ||||
|     "privacyPolicy": "Privacy-policy", | ||||
|     "terms": "Terms", | ||||
|     "agreeTip": "Please agree to the Privacy Policy and Terms", | ||||
|     "goToLogin": "Login instead", | ||||
|     "passwordStrength": "Use 8 or more characters with a mix of letters, numbers & symbols", | ||||
|     "forgetPassword": "Forget Password?", | ||||
|     "forgetPasswordSubtitle": "Enter your email and we'll send you instructions to reset your password", | ||||
|     "emailTip": "Please enter email", | ||||
|     "emailValidErrorTip": "The email format you entered is incorrect", | ||||
|     "sendResetLink": "Send Reset Link", | ||||
|     "email": "Email", | ||||
|     "qrcodeSubtitle": "Scan the QR code with your phone to login", | ||||
|     "qrcodePrompt": "Click 'Confirm' after scanning to complete login", | ||||
|     "qrcodeLogin": "QR Code Login", | ||||
|     "codeSubtitle": "Enter your phone number to start managing your project", | ||||
|     "code": "Security code", | ||||
|     "codeTip": "Security code is required", | ||||
|     "mobile": "Mobile", | ||||
|     "mobileLogin": "Mobile Login", | ||||
|     "mobileTip": "Please enter mobile number", | ||||
|     "mobileErrortip": "The phone number format is incorrect", | ||||
|     "sendCode": "Get Security code", | ||||
|     "sendText": "Resend in {0}s", | ||||
|     "thirdPartyLogin": "Or continue with", | ||||
|     "loginAgainTitle": "Please Log In Again", | ||||
|     "loginAgainSubTitle": "Your login session has expired. Please log in again to continue.", | ||||
|     "layout": { | ||||
|       "center": "Align Center", | ||||
|       "alignLeft": "Align Left", | ||||
|       "alignRight": "Align Right" | ||||
|     } | ||||
|   }, | ||||
|   "preferences": { | ||||
|     "title": "Preferences", | ||||
|     "subtitle": "Customize Preferences & Preview in Real Time", | ||||
|     "resetTip": "Data has changed, click to reset", | ||||
|     "resetTitle": "Reset Preferences", | ||||
|     "resetSuccess": "Preferences reset successfully", | ||||
|     "appearance": "Appearance", | ||||
|     "layout": "Layout", | ||||
|     "content": "Content", | ||||
|     "other": "Other", | ||||
|     "wide": "Wide", | ||||
|     "compact": "Fixed", | ||||
|     "followSystem": "Follow System", | ||||
|     "vertical": "Vertical", | ||||
|     "verticalTip": "Side vertical menu mode", | ||||
|     "horizontal": "Horizontal", | ||||
|     "horizontalTip": "Horizontal menu mode, all menus displayed at the top", | ||||
|     "twoColumn": "Two Column", | ||||
|     "twoColumnTip": "Vertical Two Column Menu Mode", | ||||
|     "mixedMenu": "Mixed Menu", | ||||
|     "mixedMenuTip": "Vertical & Horizontal Menu Co-exists", | ||||
|     "fullContent": "Full Content", | ||||
|     "fullContentTip": "Only display content body, hide all menus", | ||||
|     "normal": "Normal", | ||||
|     "plain": "Plain", | ||||
|     "rounded": "Rounded", | ||||
|     "copyPreferences": "Copy Preferences", | ||||
|     "copyPreferencesSuccessTitle": "Copy successful", | ||||
|     "copyPreferencesSuccess": "Copy successful, please override in `src/preferences.ts` under app", | ||||
|     "clearAndLogout": "Clear Cache & Logout", | ||||
|     "mode": "Mode", | ||||
|     "general": "General", | ||||
|     "language": "Language", | ||||
|     "dynamicTitle": "Dynamic Title", | ||||
|     "watermark": "Watermark", | ||||
|     "checkUpdates": "Periodic update check", | ||||
|     "position": { | ||||
|       "title": "Preferences Postion", | ||||
|       "header": "Header", | ||||
|       "auto": "Auto", | ||||
|       "fixed": "Fixed" | ||||
|     }, | ||||
|     "sidebar": { | ||||
|       "title": "Sidebar", | ||||
|       "width": "Width", | ||||
|       "visible": "Show Sidebar", | ||||
|       "collapsed": "Collpase Menu", | ||||
|       "collapsedShowTitle": "Show Menu Title" | ||||
|     }, | ||||
|     "tabbar": { | ||||
|       "title": "Tabbar", | ||||
|       "enable": "Enable Tab Bar", | ||||
|       "icon": "Show Tabbar Icon", | ||||
|       "showMore": "Show More Button", | ||||
|       "showMaximize": "Show Maximize Button", | ||||
|       "persist": "Persist Tabs", | ||||
|       "draggable": "Enable Draggable Sort", | ||||
|       "styleType": { | ||||
|         "title": "Tabs Style", | ||||
|         "chrome": "Chrome", | ||||
|         "card": "Card", | ||||
|         "plain": "Plain", | ||||
|         "brisk": "Brisk" | ||||
|       }, | ||||
|       "contextMenu": { | ||||
|         "reload": "Reload", | ||||
|         "close": "Close", | ||||
|         "pin": "Pin", | ||||
|         "unpin": "Unpin", | ||||
|         "closeLeft": "Close Left Tabs", | ||||
|         "closeRight": "Close Right Tabs", | ||||
|         "closeOther": "Close Other Tabs", | ||||
|         "closeAll": "Close All Tabs", | ||||
|         "openInNewWindow": "Open in New Window", | ||||
|         "maximize": "Maximize", | ||||
|         "restoreMaximize": "Restore" | ||||
|       } | ||||
|     }, | ||||
|     "navigationMenu": { | ||||
|       "title": "Navigation Menu", | ||||
|       "style": "Navigation Menu Style", | ||||
|       "accordion": "Sidebar Accordion Menu", | ||||
|       "split": "Navigation Menu Separation", | ||||
|       "splitTip": "When enabled, the sidebar displays the top bar's submenu" | ||||
|     }, | ||||
|     "breadcrumb": { | ||||
|       "title": "Breadcrumb", | ||||
|       "home": "Show Home Button", | ||||
|       "enable": "Enable Breadcrumb", | ||||
|       "icon": "Show Breadcrumb Icon", | ||||
|       "background": "background", | ||||
|       "style": "Breadcrumb Style", | ||||
|       "hideOnlyOne": "Hidden when only one" | ||||
|     }, | ||||
|     "animation": { | ||||
|       "title": "Animation", | ||||
|       "loading": "Page Loading", | ||||
|       "transition": "Page Transition", | ||||
|       "progress": "Page Progress" | ||||
|     }, | ||||
|     "theme": { | ||||
|       "title": "Theme", | ||||
|       "radius": "Radius", | ||||
|       "light": "Light", | ||||
|       "dark": "Dark", | ||||
|       "darkSidebar": "Semi Dark Sidebar", | ||||
|       "darkHeader": "Semi Dark Header", | ||||
|       "weakMode": "Weak Mode", | ||||
|       "grayMode": "Gray Mode", | ||||
|       "builtin": { | ||||
|         "title": "Built-in", | ||||
|         "default": "Default", | ||||
|         "violet": "Violet", | ||||
|         "pink": "Pink", | ||||
|         "rose": "Rose", | ||||
|         "skyBlue": "Sky Blue", | ||||
|         "deepBlue": "Deep Blue", | ||||
|         "green": "Green", | ||||
|         "deepGreen": "Deep Green", | ||||
|         "orange": "Orange", | ||||
|         "yellow": "Yellow", | ||||
|         "zinc": "Zinc", | ||||
|         "neutral": "Neutral", | ||||
|         "slate": "Slate", | ||||
|         "gray": "Gray", | ||||
|         "custom": "Custom" | ||||
|       } | ||||
|     }, | ||||
|     "header": { | ||||
|       "title": "Header", | ||||
|       "visible": "Show Header", | ||||
|       "modeStatic": "Static", | ||||
|       "modeFixed": "Fixed", | ||||
|       "modeAuto": "Auto hide & Show", | ||||
|       "modeAutoScroll": "Scroll to Hide & Show" | ||||
|     }, | ||||
|     "footer": { | ||||
|       "title": "Footer", | ||||
|       "visible": "Show Footer", | ||||
|       "fixed": "Fixed at Bottom" | ||||
|     }, | ||||
|     "copyright": { | ||||
|       "title": "Copyright", | ||||
|       "enable": "Enable Copyright", | ||||
|       "companyName": "Company Name", | ||||
|       "companySiteLink": "Company Site Link", | ||||
|       "date": "Date", | ||||
|       "icp": "ICP License Number", | ||||
|       "icpLink": "ICP Site Link" | ||||
|     }, | ||||
|     "shortcutKeys": { | ||||
|       "title": "Shortcut Keys", | ||||
|       "global": "Global", | ||||
|       "search": "Global Search", | ||||
|       "logout": "Logout", | ||||
|       "preferences": "Preferences" | ||||
|     }, | ||||
|     "widget": { | ||||
|       "title": "Widget", | ||||
|       "globalSearch": "Enable Global Search", | ||||
|       "fullscreen": "Enable Fullscreen", | ||||
|       "themeToggle": "Enable Theme Toggle", | ||||
|       "languageToggle": "Enable Language Toggle", | ||||
|       "notification": "Enable Notification", | ||||
|       "sidebarToggle": "Enable Sidebar Toggle", | ||||
|       "lockScreen": "Enable Lock Screen", | ||||
|       "refresh": "Enable Refresh" | ||||
|     } | ||||
|   }, | ||||
|   "ui": { | ||||
|     "captcha": { | ||||
|       "title": "Please complete the security verification", | ||||
|       "sliderSuccessText": "Passed", | ||||
|       "sliderDefaultText": "Slider and drag", | ||||
|       "alt": "Supports img tag src attribute value", | ||||
|       "sliderRotateDefaultTip": "Click picture to refresh", | ||||
|       "sliderRotateFailTip": "Validation failed", | ||||
|       "sliderRotateSuccessTip": "Validation successful, time {0} seconds", | ||||
|       "refreshAriaLabel": "Refresh captcha", | ||||
|       "confirmAriaLabel": "Confirm selection", | ||||
|       "confirm": "Confirm", | ||||
|       "pointAriaLabel": "Click point", | ||||
|       "clickInOrder": "Please click in order" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,56 @@ | |||
| { | ||||
|   "welcomeBack": "Welcome Back", | ||||
|   "pageTitle": "Plug-and-play Admin system", | ||||
|   "pageDesc": "Efficient, versatile frontend template", | ||||
|   "loginSuccess": "Login Successful", | ||||
|   "loginSuccessDesc": "Welcome Back", | ||||
|   "loginSubtitle": "Enter your account details to manage your projects", | ||||
|   "selectAccount": "Quick Select Account", | ||||
|   "username": "Username", | ||||
|   "password": "Password", | ||||
|   "usernameTip": "Please enter username", | ||||
|   "passwordErrorTip": "Password is incorrect", | ||||
|   "passwordTip": "Please enter password", | ||||
|   "verifyRequiredTip": "Please complete the verification first", | ||||
|   "rememberMe": "Remember Me", | ||||
|   "createAnAccount": "Create an Account", | ||||
|   "createAccount": "Create Account", | ||||
|   "alreadyHaveAccount": "Already have an account?", | ||||
|   "accountTip": "Don't have an account?", | ||||
|   "signUp": "Sign Up", | ||||
|   "signUpSubtitle": "Make managing your applications simple and fun", | ||||
|   "confirmPassword": "Confirm Password", | ||||
|   "confirmPasswordTip": "The passwords do not match", | ||||
|   "agree": "I agree to", | ||||
|   "privacyPolicy": "Privacy-policy", | ||||
|   "terms": "Terms", | ||||
|   "agreeTip": "Please agree to the Privacy Policy and Terms", | ||||
|   "goToLogin": "Login instead", | ||||
|   "passwordStrength": "Use 8 or more characters with a mix of letters, numbers & symbols", | ||||
|   "forgetPassword": "Forget Password?", | ||||
|   "forgetPasswordSubtitle": "Enter your email and we'll send you instructions to reset your password", | ||||
|   "emailTip": "Please enter email", | ||||
|   "emailValidErrorTip": "The email format you entered is incorrect", | ||||
|   "sendResetLink": "Send Reset Link", | ||||
|   "email": "Email", | ||||
|   "qrcodeSubtitle": "Scan the QR code with your phone to login", | ||||
|   "qrcodePrompt": "Click 'Confirm' after scanning to complete login", | ||||
|   "qrcodeLogin": "QR Code Login", | ||||
|   "codeSubtitle": "Enter your phone number to start managing your project", | ||||
|   "code": "Security code", | ||||
|   "codeTip": "Security code is required", | ||||
|   "mobile": "Mobile", | ||||
|   "mobileLogin": "Mobile Login", | ||||
|   "mobileTip": "Please enter mobile number", | ||||
|   "mobileErrortip": "The phone number format is incorrect", | ||||
|   "sendCode": "Get Security code", | ||||
|   "sendText": "Resend in {0}s", | ||||
|   "thirdPartyLogin": "Or continue with", | ||||
|   "loginAgainTitle": "Please Log In Again", | ||||
|   "loginAgainSubTitle": "Your login session has expired. Please log in again to continue.", | ||||
|   "layout": { | ||||
|     "center": "Align Center", | ||||
|     "alignLeft": "Align Left", | ||||
|     "alignRight": "Align Right" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| { | ||||
|   "back": "Back", | ||||
|   "backToHome": "Back To Home", | ||||
|   "login": "Login", | ||||
|   "logout": "Logout", | ||||
|   "prompt": "Prompt", | ||||
|   "cancel": "Cancel", | ||||
|   "confirm": "Confirm", | ||||
|   "noData": "No Data", | ||||
|   "refresh": "Refresh", | ||||
|   "loadingMenu": "Loading Menu", | ||||
|   "query": "Search" | ||||
| } | ||||
|  | @ -0,0 +1,169 @@ | |||
| { | ||||
|   "title": "Preferences", | ||||
|   "subtitle": "Customize Preferences & Preview in Real Time", | ||||
|   "resetTip": "Data has changed, click to reset", | ||||
|   "resetTitle": "Reset Preferences", | ||||
|   "resetSuccess": "Preferences reset successfully", | ||||
|   "appearance": "Appearance", | ||||
|   "layout": "Layout", | ||||
|   "content": "Content", | ||||
|   "other": "Other", | ||||
|   "wide": "Wide", | ||||
|   "compact": "Fixed", | ||||
|   "followSystem": "Follow System", | ||||
|   "vertical": "Vertical", | ||||
|   "verticalTip": "Side vertical menu mode", | ||||
|   "horizontal": "Horizontal", | ||||
|   "horizontalTip": "Horizontal menu mode, all menus displayed at the top", | ||||
|   "twoColumn": "Two Column", | ||||
|   "twoColumnTip": "Vertical Two Column Menu Mode", | ||||
|   "mixedMenu": "Mixed Menu", | ||||
|   "mixedMenuTip": "Vertical & Horizontal Menu Co-exists", | ||||
|   "fullContent": "Full Content", | ||||
|   "fullContentTip": "Only display content body, hide all menus", | ||||
|   "normal": "Normal", | ||||
|   "plain": "Plain", | ||||
|   "rounded": "Rounded", | ||||
|   "copyPreferences": "Copy Preferences", | ||||
|   "copyPreferencesSuccessTitle": "Copy successful", | ||||
|   "copyPreferencesSuccess": "Copy successful, please override in `src/preferences.ts` under app", | ||||
|   "clearAndLogout": "Clear Cache & Logout", | ||||
|   "mode": "Mode", | ||||
|   "general": "General", | ||||
|   "language": "Language", | ||||
|   "dynamicTitle": "Dynamic Title", | ||||
|   "watermark": "Watermark", | ||||
|   "checkUpdates": "Periodic update check", | ||||
|   "position": { | ||||
|     "title": "Preferences Postion", | ||||
|     "header": "Header", | ||||
|     "auto": "Auto", | ||||
|     "fixed": "Fixed" | ||||
|   }, | ||||
|   "sidebar": { | ||||
|     "title": "Sidebar", | ||||
|     "width": "Width", | ||||
|     "visible": "Show Sidebar", | ||||
|     "collapsed": "Collpase Menu", | ||||
|     "collapsedShowTitle": "Show Menu Title" | ||||
|   }, | ||||
|   "tabbar": { | ||||
|     "title": "Tabbar", | ||||
|     "enable": "Enable Tab Bar", | ||||
|     "icon": "Show Tabbar Icon", | ||||
|     "showMore": "Show More Button", | ||||
|     "showMaximize": "Show Maximize Button", | ||||
|     "persist": "Persist Tabs", | ||||
|     "draggable": "Enable Draggable Sort", | ||||
|     "styleType": { | ||||
|       "title": "Tabs Style", | ||||
|       "chrome": "Chrome", | ||||
|       "card": "Card", | ||||
|       "plain": "Plain", | ||||
|       "brisk": "Brisk" | ||||
|     }, | ||||
|     "contextMenu": { | ||||
|       "reload": "Reload", | ||||
|       "close": "Close", | ||||
|       "pin": "Pin", | ||||
|       "unpin": "Unpin", | ||||
|       "closeLeft": "Close Left Tabs", | ||||
|       "closeRight": "Close Right Tabs", | ||||
|       "closeOther": "Close Other Tabs", | ||||
|       "closeAll": "Close All Tabs", | ||||
|       "openInNewWindow": "Open in New Window", | ||||
|       "maximize": "Maximize", | ||||
|       "restoreMaximize": "Restore" | ||||
|     } | ||||
|   }, | ||||
|   "navigationMenu": { | ||||
|     "title": "Navigation Menu", | ||||
|     "style": "Navigation Menu Style", | ||||
|     "accordion": "Sidebar Accordion Menu", | ||||
|     "split": "Navigation Menu Separation", | ||||
|     "splitTip": "When enabled, the sidebar displays the top bar's submenu" | ||||
|   }, | ||||
|   "breadcrumb": { | ||||
|     "title": "Breadcrumb", | ||||
|     "home": "Show Home Button", | ||||
|     "enable": "Enable Breadcrumb", | ||||
|     "icon": "Show Breadcrumb Icon", | ||||
|     "background": "background", | ||||
|     "style": "Breadcrumb Style", | ||||
|     "hideOnlyOne": "Hidden when only one" | ||||
|   }, | ||||
|   "animation": { | ||||
|     "title": "Animation", | ||||
|     "loading": "Page Loading", | ||||
|     "transition": "Page Transition", | ||||
|     "progress": "Page Progress" | ||||
|   }, | ||||
|   "theme": { | ||||
|     "title": "Theme", | ||||
|     "radius": "Radius", | ||||
|     "light": "Light", | ||||
|     "dark": "Dark", | ||||
|     "darkSidebar": "Semi Dark Sidebar", | ||||
|     "darkHeader": "Semi Dark Header", | ||||
|     "weakMode": "Weak Mode", | ||||
|     "grayMode": "Gray Mode", | ||||
|     "builtin": { | ||||
|       "title": "Built-in", | ||||
|       "default": "Default", | ||||
|       "violet": "Violet", | ||||
|       "pink": "Pink", | ||||
|       "rose": "Rose", | ||||
|       "skyBlue": "Sky Blue", | ||||
|       "deepBlue": "Deep Blue", | ||||
|       "green": "Green", | ||||
|       "deepGreen": "Deep Green", | ||||
|       "orange": "Orange", | ||||
|       "yellow": "Yellow", | ||||
|       "zinc": "Zinc", | ||||
|       "neutral": "Neutral", | ||||
|       "slate": "Slate", | ||||
|       "gray": "Gray", | ||||
|       "custom": "Custom" | ||||
|     } | ||||
|   }, | ||||
|   "header": { | ||||
|     "title": "Header", | ||||
|     "visible": "Show Header", | ||||
|     "modeStatic": "Static", | ||||
|     "modeFixed": "Fixed", | ||||
|     "modeAuto": "Auto hide & Show", | ||||
|     "modeAutoScroll": "Scroll to Hide & Show" | ||||
|   }, | ||||
|   "footer": { | ||||
|     "title": "Footer", | ||||
|     "visible": "Show Footer", | ||||
|     "fixed": "Fixed at Bottom" | ||||
|   }, | ||||
|   "copyright": { | ||||
|     "title": "Copyright", | ||||
|     "enable": "Enable Copyright", | ||||
|     "companyName": "Company Name", | ||||
|     "companySiteLink": "Company Site Link", | ||||
|     "date": "Date", | ||||
|     "icp": "ICP License Number", | ||||
|     "icpLink": "ICP Site Link" | ||||
|   }, | ||||
|   "shortcutKeys": { | ||||
|     "title": "Shortcut Keys", | ||||
|     "global": "Global", | ||||
|     "search": "Global Search", | ||||
|     "logout": "Logout", | ||||
|     "preferences": "Preferences" | ||||
|   }, | ||||
|   "widget": { | ||||
|     "title": "Widget", | ||||
|     "globalSearch": "Enable Global Search", | ||||
|     "fullscreen": "Enable Fullscreen", | ||||
|     "themeToggle": "Enable Theme Toggle", | ||||
|     "languageToggle": "Enable Language Toggle", | ||||
|     "notification": "Enable Notification", | ||||
|     "sidebarToggle": "Enable Sidebar Toggle", | ||||
|     "lockScreen": "Enable Lock Screen", | ||||
|     "refresh": "Enable Refresh" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,77 @@ | |||
| { | ||||
|   "formRules": { | ||||
|     "required": "Please enter {0}", | ||||
|     "selectRequired": "Please select {0}" | ||||
|   }, | ||||
|   "placeholder": { | ||||
|     "input": "Please enter", | ||||
|     "select": "Please select" | ||||
|   }, | ||||
|   "captcha": { | ||||
|     "title": "Please complete the security verification", | ||||
|     "sliderSuccessText": "Passed", | ||||
|     "sliderDefaultText": "Slider and drag", | ||||
|     "alt": "Supports img tag src attribute value", | ||||
|     "sliderRotateDefaultTip": "Click picture to refresh", | ||||
|     "sliderRotateFailTip": "Validation failed", | ||||
|     "sliderRotateSuccessTip": "Validation successful, time {0} seconds", | ||||
|     "refreshAriaLabel": "Refresh captcha", | ||||
|     "confirmAriaLabel": "Confirm selection", | ||||
|     "confirm": "Confirm", | ||||
|     "pointAriaLabel": "Click point", | ||||
|     "clickInOrder": "Please click in order" | ||||
|   }, | ||||
|   "fallback": { | ||||
|     "pageNotFound": "Oops! Page Not Found", | ||||
|     "pageNotFoundDesc": "Sorry, we couldn't find the page you were looking for.", | ||||
|     "forbidden": "Oops! Access Denied", | ||||
|     "forbiddenDesc": "Sorry, but you don't have permission to access this page.", | ||||
|     "internalError": "Oops! Something Went Wrong", | ||||
|     "internalErrorDesc": "Sorry, but the server encountered an error.", | ||||
|     "offline": "Offline Page", | ||||
|     "offlineError": "Oops! Network Error", | ||||
|     "offlineErrorDesc": "Sorry, can't connect to the internet. Check your connection.", | ||||
|     "comingSoon": "Coming Soon", | ||||
|     "http": { | ||||
|       "requestTimeout": "The request timed out. Please try again later.", | ||||
|       "networkError": "A network error occurred. Please check your internet connection and try again.", | ||||
|       "badRequest": "Bad Request. Please check your input and try again.", | ||||
|       "unauthorized": "Unauthorized. Please log in to continue.", | ||||
|       "forbidden": "Forbidden. You do not have permission to access this resource.", | ||||
|       "notFound": "Not Found. The requested resource could not be found.", | ||||
|       "internalServerError": "Internal Server Error. Something went wrong on our end. Please try again later." | ||||
|     } | ||||
|   }, | ||||
|   "widgets": { | ||||
|     "document": "Document", | ||||
|     "qa": "Q&A", | ||||
|     "setting": "Settings", | ||||
|     "logoutTip": "Do you want to logout?", | ||||
|     "viewAll": "View All Messages", | ||||
|     "notifications": "Notifications", | ||||
|     "markAllAsRead": "Make All as Read", | ||||
|     "clearNotifications": "Clear", | ||||
|     "checkUpdatesTitle": "New Version Available", | ||||
|     "checkUpdatesDescription": "Click to refresh and get the latest version", | ||||
|     "search": { | ||||
|       "title": "Search", | ||||
|       "searchNavigate": "Search Navigation", | ||||
|       "select": "Select", | ||||
|       "navigate": "Navigate", | ||||
|       "close": "Close", | ||||
|       "noResults": "No Search Results Found", | ||||
|       "noRecent": "No Search History", | ||||
|       "recent": "Search History" | ||||
|     }, | ||||
|     "lockScreen": { | ||||
|       "title": "Lock Screen", | ||||
|       "screenButton": "Locking", | ||||
|       "password": "Password", | ||||
|       "placeholder": "Please enter password", | ||||
|       "unlock": "Click to unlock", | ||||
|       "errorPasswordTip": "Password error, please re-enter", | ||||
|       "backToLogin": "Back to login", | ||||
|       "entry": "Enter the system" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -1,339 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "core": { | ||||
|       "login": "登陆", | ||||
|       "register": "注册", | ||||
|       "codeLogin": "验证码登陆", | ||||
|       "qrcodeLogin": "二维码登陆", | ||||
|       "forgetPassword": "忘记密码" | ||||
|     }, | ||||
|     "dashboard": { | ||||
|       "title": "概览", | ||||
|       "analytics": "分析页", | ||||
|       "workspace": "工作台" | ||||
|     }, | ||||
|     "vben": { | ||||
|       "title": "项目", | ||||
|       "about": "关于", | ||||
|       "document": "文档", | ||||
|       "antdv": "Ant Design Vue 版本", | ||||
|       "naive-ui": "Naive UI 版本", | ||||
|       "element-plus": "Element Plus 版本" | ||||
|     } | ||||
|   }, | ||||
|   "common": { | ||||
|     "back": "返回", | ||||
|     "backToHome": "返回首页", | ||||
|     "login": "登录", | ||||
|     "logout": "退出登录", | ||||
|     "prompt": "提示", | ||||
|     "cancel": "取消", | ||||
|     "confirm": "确认", | ||||
|     "noData": "暂无数据", | ||||
|     "refresh": "刷新", | ||||
|     "loadingMenu": "加载菜单中", | ||||
|     "query": "查询" | ||||
|   }, | ||||
|   "fallback": { | ||||
|     "pageNotFound": "哎呀!未找到页面", | ||||
|     "pageNotFoundDesc": "抱歉,我们无法找到您要找的页面。", | ||||
|     "forbidden": "哎呀!访问被拒绝", | ||||
|     "forbiddenDesc": "抱歉,您没有权限访问此页面。", | ||||
|     "internalError": "哎呀!出错了", | ||||
|     "internalErrorDesc": "抱歉,服务器遇到错误。", | ||||
|     "offline": "离线页面", | ||||
|     "offlineError": "哎呀!网络错误", | ||||
|     "offlineErrorDesc": "抱歉,无法连接到互联网,请检查您的网络连接并重试。", | ||||
|     "comingSoon": "即将推出", | ||||
|     "http": { | ||||
|       "requestTimeout": "请求超时,请稍后再试。", | ||||
|       "networkError": "网络异常,请检查您的网络连接后重试。", | ||||
|       "badRequest": "请求错误。请检查您的输入并重试。", | ||||
|       "unauthorized": "登录认证过期,请重新登录后继续。", | ||||
|       "forbidden": "禁止访问, 您没有权限访问此资源。", | ||||
|       "notFound": "未找到, 请求的资源不存在。", | ||||
|       "internalServerError": "内部服务器错误,请稍后再试。" | ||||
|     } | ||||
|   }, | ||||
|   "formRules": { | ||||
|     "required": "请输入{0}", | ||||
|     "selectRequired": "请选择{0}" | ||||
|   }, | ||||
|   "placeholder": { | ||||
|     "input": "请输入", | ||||
|     "select": "请选择" | ||||
|   }, | ||||
|   "widgets": { | ||||
|     "document": "文档", | ||||
|     "qa": "问题 & 帮助", | ||||
|     "setting": "设置", | ||||
|     "logoutTip": "是否退出登录?", | ||||
|     "viewAll": "查看所有消息", | ||||
|     "notifications": "通知", | ||||
|     "markAllAsRead": "全部标记为已读", | ||||
|     "clearNotifications": "清空", | ||||
|     "checkUpdatesTitle": "新版本可用", | ||||
|     "checkUpdatesDescription": "点击刷新以获取最新版本", | ||||
|     "search": { | ||||
|       "title": "搜索", | ||||
|       "searchNavigate": "搜索导航菜单", | ||||
|       "select": "选择", | ||||
|       "navigate": "导航", | ||||
|       "close": "关闭", | ||||
|       "noResults": "未找到搜索结果", | ||||
|       "noRecent": "没有搜索历史", | ||||
|       "recent": "搜索历史" | ||||
|     }, | ||||
|     "lockScreen": { | ||||
|       "title": "锁定屏幕", | ||||
|       "screenButton": "锁定", | ||||
|       "password": "密码", | ||||
|       "placeholder": "请输入锁屏密码", | ||||
|       "unlock": "点击解锁", | ||||
|       "errorPasswordTip": "密码错误,请重新输入", | ||||
|       "backToLogin": "返回登录", | ||||
|       "entry": "进入系统" | ||||
|     } | ||||
|   }, | ||||
|   "authentication": { | ||||
|     "welcomeBack": "欢迎回来", | ||||
|     "pageTitle": "开箱即用的大型中后台管理系统", | ||||
|     "pageDesc": "工程化、高性能、跨组件库的前端模版", | ||||
|     "loginSuccess": "登录成功", | ||||
|     "loginSuccessDesc": "欢迎回来", | ||||
|     "loginSubtitle": "请输入您的帐户信息以开始管理您的项目", | ||||
|     "selectAccount": "快速选择账号", | ||||
|     "username": "账号", | ||||
|     "password": "密码", | ||||
|     "usernameTip": "请输入用户名", | ||||
|     "passwordTip": "请输入密码", | ||||
|     "verifyRequiredTip": "请先完成验证", | ||||
|     "passwordErrorTip": "密码错误", | ||||
|     "rememberMe": "记住账号", | ||||
|     "createAnAccount": "创建一个账号", | ||||
|     "createAccount": "创建账号", | ||||
|     "alreadyHaveAccount": "已经有账号了?", | ||||
|     "accountTip": "还没有账号?", | ||||
|     "signUp": "注册", | ||||
|     "signUpSubtitle": "让您的应用程序管理变得简单而有趣", | ||||
|     "confirmPassword": "确认密码", | ||||
|     "confirmPasswordTip": "两次输入的密码不一致", | ||||
|     "agree": "我同意", | ||||
|     "privacyPolicy": "隐私政策", | ||||
|     "terms": "条款", | ||||
|     "agreeTip": "请同意隐私政策和条款", | ||||
|     "goToLogin": "去登录", | ||||
|     "passwordStrength": "使用 8 个或更多字符,混合字母、数字和符号", | ||||
|     "forgetPassword": "忘记密码?", | ||||
|     "forgetPasswordSubtitle": "输入您的电子邮件,我们将向您发送重置密码的连接", | ||||
|     "emailTip": "请输入邮箱", | ||||
|     "emailValidErrorTip": "你输入的邮箱格式不正确", | ||||
|     "sendResetLink": "发送重置链接", | ||||
|     "email": "邮箱", | ||||
|     "qrcodeSubtitle": "请用手机扫描二维码登录", | ||||
|     "qrcodePrompt": "扫码后点击 '确认',即可完成登录", | ||||
|     "qrcodeLogin": "扫码登录", | ||||
|     "codeSubtitle": "请输入您的手机号码以开始管理您的项目", | ||||
|     "code": "验证码", | ||||
|     "codeTip": "请输入验证码", | ||||
|     "mobile": "手机号码", | ||||
|     "mobileTip": "请输入手机号", | ||||
|     "mobileErrortip": "手机号码格式错误", | ||||
|     "mobileLogin": "手机号登录", | ||||
|     "sendCode": "获取验证码", | ||||
|     "sendText": "{0}秒后重新获取", | ||||
|     "thirdPartyLogin": "其他登录方式", | ||||
|     "loginAgainTitle": "重新登录", | ||||
|     "loginAgainSubTitle": "您的登录状态已过期,请重新登录以继续。", | ||||
|     "layout": { | ||||
|       "center": "居中", | ||||
|       "alignLeft": "居左", | ||||
|       "alignRight": "居右" | ||||
|     } | ||||
|   }, | ||||
|   "preferences": { | ||||
|     "title": "偏好设置", | ||||
|     "subtitle": "自定义偏好设置 & 实时预览", | ||||
|     "resetTitle": "重置偏好设置", | ||||
|     "resetTip": "数据有变化,点击可进行重置", | ||||
|     "resetSuccess": "重置偏好设置成功", | ||||
|     "appearance": "外观", | ||||
|     "layout": "布局", | ||||
|     "content": "内容", | ||||
|     "other": "其它", | ||||
|     "wide": "流式", | ||||
|     "compact": "定宽", | ||||
|     "followSystem": "跟随系统", | ||||
|     "vertical": "垂直", | ||||
|     "verticalTip": "侧边垂直菜单模式", | ||||
|     "horizontal": "水平", | ||||
|     "horizontalTip": "水平菜单模式,菜单全部显示在顶部", | ||||
|     "twoColumn": "双列菜单", | ||||
|     "twoColumnTip": "垂直双列菜单模式", | ||||
|     "mixedMenu": "混合菜单", | ||||
|     "mixedMenuTip": "垂直水平菜单共存", | ||||
|     "fullContent": "内容全屏", | ||||
|     "fullContentTip": "不显示任何菜单,只显示内容主体", | ||||
|     "normal": "常规", | ||||
|     "plain": "朴素", | ||||
|     "rounded": "圆润", | ||||
|     "copyPreferences": "复制偏好设置", | ||||
|     "copyPreferencesSuccessTitle": "复制成功", | ||||
|     "copyPreferencesSuccess": "复制成功,请在 app 下的 `src/preferences.ts`内进行覆盖", | ||||
|     "clearAndLogout": "清空缓存 & 退出登录", | ||||
|     "mode": "模式", | ||||
|     "general": "通用", | ||||
|     "language": "语言", | ||||
|     "dynamicTitle": "动态标题", | ||||
|     "watermark": "水印", | ||||
|     "checkUpdates": "定时检查更新", | ||||
|     "position": { | ||||
|       "title": "偏好设置位置", | ||||
|       "header": "顶栏", | ||||
|       "auto": "自动", | ||||
|       "fixed": "固定" | ||||
|     }, | ||||
|     "sidebar": { | ||||
|       "title": "侧边栏", | ||||
|       "width": "宽度", | ||||
|       "visible": "显示侧边栏", | ||||
|       "collapsed": "折叠菜单", | ||||
|       "collapsedShowTitle": "折叠显示菜单名" | ||||
|     }, | ||||
|     "tabbar": { | ||||
|       "title": "标签栏", | ||||
|       "enable": "启用标签栏", | ||||
|       "icon": "显示标签栏图标", | ||||
|       "showMore": "显示更多按钮", | ||||
|       "showMaximize": "显示最大化按钮", | ||||
|       "persist": "持久化标签页", | ||||
|       "draggable": "启动拖拽排序", | ||||
|       "styleType": { | ||||
|         "title": "标签页风格", | ||||
|         "chrome": "谷歌", | ||||
|         "card": "卡片", | ||||
|         "plain": "朴素", | ||||
|         "brisk": "轻快" | ||||
|       }, | ||||
|       "contextMenu": { | ||||
|         "reload": "重新加载", | ||||
|         "close": "关闭", | ||||
|         "pin": "固定", | ||||
|         "unpin": "取消固定", | ||||
|         "closeLeft": "关闭左侧标签页", | ||||
|         "closeRight": "关闭右侧标签页", | ||||
|         "closeOther": "关闭其它标签页", | ||||
|         "closeAll": "关闭全部标签页", | ||||
|         "openInNewWindow": "在新窗口打开", | ||||
|         "maximize": "最大化", | ||||
|         "restoreMaximize": "还原" | ||||
|       } | ||||
|     }, | ||||
|     "navigationMenu": { | ||||
|       "title": "导航菜单", | ||||
|       "style": "导航菜单风格", | ||||
|       "accordion": "侧边导航菜单手风琴模式", | ||||
|       "split": "导航菜单分离", | ||||
|       "splitTip": "开启时,侧边栏显示顶栏对应菜单的子菜单" | ||||
|     }, | ||||
|     "breadcrumb": { | ||||
|       "title": "面包屑导航", | ||||
|       "enable": "开启面包屑导航", | ||||
|       "icon": "显示面包屑图标", | ||||
|       "home": "显示首页按钮", | ||||
|       "style": "面包屑风格", | ||||
|       "hideOnlyOne": "仅有一个时隐藏", | ||||
|       "background": "背景" | ||||
|     }, | ||||
|     "animation": { | ||||
|       "title": "动画", | ||||
|       "loading": "页面切换 Loading", | ||||
|       "transition": "页面切换动画", | ||||
|       "progress": "页面切换进度条" | ||||
|     }, | ||||
|     "theme": { | ||||
|       "title": "主题", | ||||
|       "radius": "圆角", | ||||
|       "light": "浅色", | ||||
|       "dark": "深色", | ||||
|       "darkSidebar": "深色侧边栏", | ||||
|       "darkHeader": "深色顶栏", | ||||
|       "weakMode": "色弱模式", | ||||
|       "grayMode": "灰色模式", | ||||
|       "builtin": { | ||||
|         "title": "内置主题", | ||||
|         "default": "默认", | ||||
|         "violet": "紫罗兰", | ||||
|         "pink": "樱花粉", | ||||
|         "rose": "玫瑰红", | ||||
|         "skyBlue": "天蓝色", | ||||
|         "deepBlue": "深蓝色", | ||||
|         "green": "浅绿色", | ||||
|         "deepGreen": "深绿色", | ||||
|         "orange": "橙黄色", | ||||
|         "yellow": "柠檬黄", | ||||
|         "zinc": "锌色灰", | ||||
|         "neutral": "中性色", | ||||
|         "slate": "石板灰", | ||||
|         "gray": "中灰色", | ||||
|         "custom": "自定义" | ||||
|       } | ||||
|     }, | ||||
|     "header": { | ||||
|       "title": "顶栏", | ||||
|       "modeStatic": "静止", | ||||
|       "modeFixed": "固定", | ||||
|       "modeAuto": "自动隐藏和显示", | ||||
|       "modeAutoScroll": "滚动隐藏和显示", | ||||
|       "visible": "显示顶栏" | ||||
|     }, | ||||
|     "footer": { | ||||
|       "title": "底栏", | ||||
|       "visible": "显示底栏", | ||||
|       "fixed": "固定在底部" | ||||
|     }, | ||||
|     "copyright": { | ||||
|       "title": "版权", | ||||
|       "enable": "启用版权", | ||||
|       "companyName": "公司名", | ||||
|       "companySiteLink": "公司主页", | ||||
|       "date": "日期", | ||||
|       "icp": "ICP 备案号", | ||||
|       "icpLink": "ICP 网站链接" | ||||
|     }, | ||||
|     "shortcutKeys": { | ||||
|       "title": "快捷键", | ||||
|       "global": "全局", | ||||
|       "search": "全局搜索", | ||||
|       "logout": "退出登录", | ||||
|       "preferences": "偏好设置" | ||||
|     }, | ||||
|     "widget": { | ||||
|       "title": "小部件", | ||||
|       "globalSearch": "启用全局搜索", | ||||
|       "fullscreen": "启用全屏", | ||||
|       "themeToggle": "启用主题切换", | ||||
|       "languageToggle": "启用语言切换", | ||||
|       "notification": "启用通知", | ||||
|       "sidebarToggle": "启用侧边栏切换", | ||||
|       "lockScreen": "启用锁屏", | ||||
|       "refresh": "启用刷新" | ||||
|     } | ||||
|   }, | ||||
|   "ui": { | ||||
|     "captcha": { | ||||
|       "title": "请完成安全验证", | ||||
|       "sliderSuccessText": "验证通过", | ||||
|       "sliderDefaultText": "请按住滑块拖动", | ||||
|       "sliderRotateDefaultTip": "点击图片可刷新", | ||||
|       "sliderRotateFailTip": "验证失败", | ||||
|       "sliderRotateSuccessTip": "验证成功,耗时{0}秒", | ||||
|       "alt": "支持img标签src属性值", | ||||
|       "refreshAriaLabel": "刷新验证码", | ||||
|       "confirmAriaLabel": "确认选择", | ||||
|       "confirm": "确认", | ||||
|       "pointAriaLabel": "点击点", | ||||
|       "clickInOrder": "请依次点击" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,56 @@ | |||
| { | ||||
|   "welcomeBack": "欢迎回来", | ||||
|   "pageTitle": "开箱即用的大型中后台管理系统", | ||||
|   "pageDesc": "工程化、高性能、跨组件库的前端模版", | ||||
|   "loginSuccess": "登录成功", | ||||
|   "loginSuccessDesc": "欢迎回来", | ||||
|   "loginSubtitle": "请输入您的帐户信息以开始管理您的项目", | ||||
|   "selectAccount": "快速选择账号", | ||||
|   "username": "账号", | ||||
|   "password": "密码", | ||||
|   "usernameTip": "请输入用户名", | ||||
|   "passwordTip": "请输入密码", | ||||
|   "verifyRequiredTip": "请先完成验证", | ||||
|   "passwordErrorTip": "密码错误", | ||||
|   "rememberMe": "记住账号", | ||||
|   "createAnAccount": "创建一个账号", | ||||
|   "createAccount": "创建账号", | ||||
|   "alreadyHaveAccount": "已经有账号了?", | ||||
|   "accountTip": "还没有账号?", | ||||
|   "signUp": "注册", | ||||
|   "signUpSubtitle": "让您的应用程序管理变得简单而有趣", | ||||
|   "confirmPassword": "确认密码", | ||||
|   "confirmPasswordTip": "两次输入的密码不一致", | ||||
|   "agree": "我同意", | ||||
|   "privacyPolicy": "隐私政策", | ||||
|   "terms": "条款", | ||||
|   "agreeTip": "请同意隐私政策和条款", | ||||
|   "goToLogin": "去登录", | ||||
|   "passwordStrength": "使用 8 个或更多字符,混合字母、数字和符号", | ||||
|   "forgetPassword": "忘记密码?", | ||||
|   "forgetPasswordSubtitle": "输入您的电子邮件,我们将向您发送重置密码的连接", | ||||
|   "emailTip": "请输入邮箱", | ||||
|   "emailValidErrorTip": "你输入的邮箱格式不正确", | ||||
|   "sendResetLink": "发送重置链接", | ||||
|   "email": "邮箱", | ||||
|   "qrcodeSubtitle": "请用手机扫描二维码登录", | ||||
|   "qrcodePrompt": "扫码后点击 '确认',即可完成登录", | ||||
|   "qrcodeLogin": "扫码登录", | ||||
|   "codeSubtitle": "请输入您的手机号码以开始管理您的项目", | ||||
|   "code": "验证码", | ||||
|   "codeTip": "请输入验证码", | ||||
|   "mobile": "手机号码", | ||||
|   "mobileTip": "请输入手机号", | ||||
|   "mobileErrortip": "手机号码格式错误", | ||||
|   "mobileLogin": "手机号登录", | ||||
|   "sendCode": "获取验证码", | ||||
|   "sendText": "{0}秒后重新获取", | ||||
|   "thirdPartyLogin": "其他登录方式", | ||||
|   "loginAgainTitle": "重新登录", | ||||
|   "loginAgainSubTitle": "您的登录状态已过期,请重新登录以继续。", | ||||
|   "layout": { | ||||
|     "center": "居中", | ||||
|     "alignLeft": "居左", | ||||
|     "alignRight": "居右" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| { | ||||
|   "back": "返回", | ||||
|   "backToHome": "返回首页", | ||||
|   "login": "登录", | ||||
|   "logout": "退出登录", | ||||
|   "prompt": "提示", | ||||
|   "cancel": "取消", | ||||
|   "confirm": "确认", | ||||
|   "noData": "暂无数据", | ||||
|   "refresh": "刷新", | ||||
|   "loadingMenu": "加载菜单中", | ||||
|   "query": "查询" | ||||
| } | ||||
|  | @ -0,0 +1,169 @@ | |||
| { | ||||
|   "title": "偏好设置", | ||||
|   "subtitle": "自定义偏好设置 & 实时预览", | ||||
|   "resetTitle": "重置偏好设置", | ||||
|   "resetTip": "数据有变化,点击可进行重置", | ||||
|   "resetSuccess": "重置偏好设置成功", | ||||
|   "appearance": "外观", | ||||
|   "layout": "布局", | ||||
|   "content": "内容", | ||||
|   "other": "其它", | ||||
|   "wide": "流式", | ||||
|   "compact": "定宽", | ||||
|   "followSystem": "跟随系统", | ||||
|   "vertical": "垂直", | ||||
|   "verticalTip": "侧边垂直菜单模式", | ||||
|   "horizontal": "水平", | ||||
|   "horizontalTip": "水平菜单模式,菜单全部显示在顶部", | ||||
|   "twoColumn": "双列菜单", | ||||
|   "twoColumnTip": "垂直双列菜单模式", | ||||
|   "mixedMenu": "混合菜单", | ||||
|   "mixedMenuTip": "垂直水平菜单共存", | ||||
|   "fullContent": "内容全屏", | ||||
|   "fullContentTip": "不显示任何菜单,只显示内容主体", | ||||
|   "normal": "常规", | ||||
|   "plain": "朴素", | ||||
|   "rounded": "圆润", | ||||
|   "copyPreferences": "复制偏好设置", | ||||
|   "copyPreferencesSuccessTitle": "复制成功", | ||||
|   "copyPreferencesSuccess": "复制成功,请在 app 下的 `src/preferences.ts`内进行覆盖", | ||||
|   "clearAndLogout": "清空缓存 & 退出登录", | ||||
|   "mode": "模式", | ||||
|   "general": "通用", | ||||
|   "language": "语言", | ||||
|   "dynamicTitle": "动态标题", | ||||
|   "watermark": "水印", | ||||
|   "checkUpdates": "定时检查更新", | ||||
|   "position": { | ||||
|     "title": "偏好设置位置", | ||||
|     "header": "顶栏", | ||||
|     "auto": "自动", | ||||
|     "fixed": "固定" | ||||
|   }, | ||||
|   "sidebar": { | ||||
|     "title": "侧边栏", | ||||
|     "width": "宽度", | ||||
|     "visible": "显示侧边栏", | ||||
|     "collapsed": "折叠菜单", | ||||
|     "collapsedShowTitle": "折叠显示菜单名" | ||||
|   }, | ||||
|   "tabbar": { | ||||
|     "title": "标签栏", | ||||
|     "enable": "启用标签栏", | ||||
|     "icon": "显示标签栏图标", | ||||
|     "showMore": "显示更多按钮", | ||||
|     "showMaximize": "显示最大化按钮", | ||||
|     "persist": "持久化标签页", | ||||
|     "draggable": "启动拖拽排序", | ||||
|     "styleType": { | ||||
|       "title": "标签页风格", | ||||
|       "chrome": "谷歌", | ||||
|       "card": "卡片", | ||||
|       "plain": "朴素", | ||||
|       "brisk": "轻快" | ||||
|     }, | ||||
|     "contextMenu": { | ||||
|       "reload": "重新加载", | ||||
|       "close": "关闭", | ||||
|       "pin": "固定", | ||||
|       "unpin": "取消固定", | ||||
|       "closeLeft": "关闭左侧标签页", | ||||
|       "closeRight": "关闭右侧标签页", | ||||
|       "closeOther": "关闭其它标签页", | ||||
|       "closeAll": "关闭全部标签页", | ||||
|       "openInNewWindow": "在新窗口打开", | ||||
|       "maximize": "最大化", | ||||
|       "restoreMaximize": "还原" | ||||
|     } | ||||
|   }, | ||||
|   "navigationMenu": { | ||||
|     "title": "导航菜单", | ||||
|     "style": "导航菜单风格", | ||||
|     "accordion": "侧边导航菜单手风琴模式", | ||||
|     "split": "导航菜单分离", | ||||
|     "splitTip": "开启时,侧边栏显示顶栏对应菜单的子菜单" | ||||
|   }, | ||||
|   "breadcrumb": { | ||||
|     "title": "面包屑导航", | ||||
|     "enable": "开启面包屑导航", | ||||
|     "icon": "显示面包屑图标", | ||||
|     "home": "显示首页按钮", | ||||
|     "style": "面包屑风格", | ||||
|     "hideOnlyOne": "仅有一个时隐藏", | ||||
|     "background": "背景" | ||||
|   }, | ||||
|   "animation": { | ||||
|     "title": "动画", | ||||
|     "loading": "页面切换 Loading", | ||||
|     "transition": "页面切换动画", | ||||
|     "progress": "页面切换进度条" | ||||
|   }, | ||||
|   "theme": { | ||||
|     "title": "主题", | ||||
|     "radius": "圆角", | ||||
|     "light": "浅色", | ||||
|     "dark": "深色", | ||||
|     "darkSidebar": "深色侧边栏", | ||||
|     "darkHeader": "深色顶栏", | ||||
|     "weakMode": "色弱模式", | ||||
|     "grayMode": "灰色模式", | ||||
|     "builtin": { | ||||
|       "title": "内置主题", | ||||
|       "default": "默认", | ||||
|       "violet": "紫罗兰", | ||||
|       "pink": "樱花粉", | ||||
|       "rose": "玫瑰红", | ||||
|       "skyBlue": "天蓝色", | ||||
|       "deepBlue": "深蓝色", | ||||
|       "green": "浅绿色", | ||||
|       "deepGreen": "深绿色", | ||||
|       "orange": "橙黄色", | ||||
|       "yellow": "柠檬黄", | ||||
|       "zinc": "锌色灰", | ||||
|       "neutral": "中性色", | ||||
|       "slate": "石板灰", | ||||
|       "gray": "中灰色", | ||||
|       "custom": "自定义" | ||||
|     } | ||||
|   }, | ||||
|   "header": { | ||||
|     "title": "顶栏", | ||||
|     "modeStatic": "静止", | ||||
|     "modeFixed": "固定", | ||||
|     "modeAuto": "自动隐藏和显示", | ||||
|     "modeAutoScroll": "滚动隐藏和显示", | ||||
|     "visible": "显示顶栏" | ||||
|   }, | ||||
|   "footer": { | ||||
|     "title": "底栏", | ||||
|     "visible": "显示底栏", | ||||
|     "fixed": "固定在底部" | ||||
|   }, | ||||
|   "copyright": { | ||||
|     "title": "版权", | ||||
|     "enable": "启用版权", | ||||
|     "companyName": "公司名", | ||||
|     "companySiteLink": "公司主页", | ||||
|     "date": "日期", | ||||
|     "icp": "ICP 备案号", | ||||
|     "icpLink": "ICP 网站链接" | ||||
|   }, | ||||
|   "shortcutKeys": { | ||||
|     "title": "快捷键", | ||||
|     "global": "全局", | ||||
|     "search": "全局搜索", | ||||
|     "logout": "退出登录", | ||||
|     "preferences": "偏好设置" | ||||
|   }, | ||||
|   "widget": { | ||||
|     "title": "小部件", | ||||
|     "globalSearch": "启用全局搜索", | ||||
|     "fullscreen": "启用全屏", | ||||
|     "themeToggle": "启用主题切换", | ||||
|     "languageToggle": "启用语言切换", | ||||
|     "notification": "启用通知", | ||||
|     "sidebarToggle": "启用侧边栏切换", | ||||
|     "lockScreen": "启用锁屏", | ||||
|     "refresh": "启用刷新" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,77 @@ | |||
| { | ||||
|   "formRules": { | ||||
|     "required": "请输入{0}", | ||||
|     "selectRequired": "请选择{0}" | ||||
|   }, | ||||
|   "placeholder": { | ||||
|     "input": "请输入", | ||||
|     "select": "请选择" | ||||
|   }, | ||||
|   "captcha": { | ||||
|     "title": "请完成安全验证", | ||||
|     "sliderSuccessText": "验证通过", | ||||
|     "sliderDefaultText": "请按住滑块拖动", | ||||
|     "sliderRotateDefaultTip": "点击图片可刷新", | ||||
|     "sliderRotateFailTip": "验证失败", | ||||
|     "sliderRotateSuccessTip": "验证成功,耗时{0}秒", | ||||
|     "alt": "支持img标签src属性值", | ||||
|     "refreshAriaLabel": "刷新验证码", | ||||
|     "confirmAriaLabel": "确认选择", | ||||
|     "confirm": "确认", | ||||
|     "pointAriaLabel": "点击点", | ||||
|     "clickInOrder": "请依次点击" | ||||
|   }, | ||||
|   "fallback": { | ||||
|     "pageNotFound": "哎呀!未找到页面", | ||||
|     "pageNotFoundDesc": "抱歉,我们无法找到您要找的页面。", | ||||
|     "forbidden": "哎呀!访问被拒绝", | ||||
|     "forbiddenDesc": "抱歉,您没有权限访问此页面。", | ||||
|     "internalError": "哎呀!出错了", | ||||
|     "internalErrorDesc": "抱歉,服务器遇到错误。", | ||||
|     "offline": "离线页面", | ||||
|     "offlineError": "哎呀!网络错误", | ||||
|     "offlineErrorDesc": "抱歉,无法连接到互联网,请检查您的网络连接并重试。", | ||||
|     "comingSoon": "即将推出", | ||||
|     "http": { | ||||
|       "requestTimeout": "请求超时,请稍后再试。", | ||||
|       "networkError": "网络异常,请检查您的网络连接后重试。", | ||||
|       "badRequest": "请求错误。请检查您的输入并重试。", | ||||
|       "unauthorized": "登录认证过期,请重新登录后继续。", | ||||
|       "forbidden": "禁止访问, 您没有权限访问此资源。", | ||||
|       "notFound": "未找到, 请求的资源不存在。", | ||||
|       "internalServerError": "内部服务器错误,请稍后再试。" | ||||
|     } | ||||
|   }, | ||||
|   "widgets": { | ||||
|     "document": "文档", | ||||
|     "qa": "问题 & 帮助", | ||||
|     "setting": "设置", | ||||
|     "logoutTip": "是否退出登录?", | ||||
|     "viewAll": "查看所有消息", | ||||
|     "notifications": "通知", | ||||
|     "markAllAsRead": "全部标记为已读", | ||||
|     "clearNotifications": "清空", | ||||
|     "checkUpdatesTitle": "新版本可用", | ||||
|     "checkUpdatesDescription": "点击刷新以获取最新版本", | ||||
|     "search": { | ||||
|       "title": "搜索", | ||||
|       "searchNavigate": "搜索导航菜单", | ||||
|       "select": "选择", | ||||
|       "navigate": "导航", | ||||
|       "close": "关闭", | ||||
|       "noResults": "未找到搜索结果", | ||||
|       "noRecent": "没有搜索历史", | ||||
|       "recent": "搜索历史" | ||||
|     }, | ||||
|     "lockScreen": { | ||||
|       "title": "锁定屏幕", | ||||
|       "screenButton": "锁定", | ||||
|       "password": "密码", | ||||
|       "placeholder": "请输入锁屏密码", | ||||
|       "unlock": "点击解锁", | ||||
|       "errorPasswordTip": "密码错误,请重新输入", | ||||
|       "backToLogin": "返回登录", | ||||
|       "entry": "进入系统" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -41,7 +41,7 @@ const withDefaultPlaceholder = <T extends Component>( | |||
|   type: 'input' | 'select', | ||||
| ) => { | ||||
|   return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => { | ||||
|     const placeholder = props?.placeholder || $t(`placeholder.${type}`); | ||||
|     const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`); | ||||
|     return h(component, { ...props, ...attrs, placeholder }, slots); | ||||
|   }; | ||||
| }; | ||||
|  |  | |||
|  | @ -24,14 +24,14 @@ setupVbenForm<ComponentType>({ | |||
|     // 输入项目必填国际化适配
 | ||||
|     required: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null || value.length === 0) { | ||||
|         return $t('formRules.required', [ctx.label]); | ||||
|         return $t('ui.formRules.required', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|     // 选择项目必填国际化适配
 | ||||
|     selectRequired: (value, _params, ctx) => { | ||||
|       if (value === undefined || value === null) { | ||||
|         return $t('formRules.selectRequired', [ctx.label]); | ||||
|         return $t('ui.formRules.selectRequired', [ctx.label]); | ||||
|       } | ||||
|       return true; | ||||
|     }, | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ const menus = computed(() => [ | |||
|       }); | ||||
|     }, | ||||
|     icon: BookOpenText, | ||||
|     text: $t('widgets.document'), | ||||
|     text: $t('ui.widgets.document'), | ||||
|   }, | ||||
|   { | ||||
|     handler: () => { | ||||
|  | @ -86,7 +86,7 @@ const menus = computed(() => [ | |||
|       }); | ||||
|     }, | ||||
|     icon: CircleHelp, | ||||
|     text: $t('widgets.qa'), | ||||
|     text: $t('ui.widgets.qa'), | ||||
|   }, | ||||
| ]); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,11 @@ import type { Locale } from 'ant-design-vue/es/locale'; | |||
| import type { App } from 'vue'; | ||||
| import { ref } from 'vue'; | ||||
| 
 | ||||
| import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales'; | ||||
| import { | ||||
|   $t, | ||||
|   setupI18n as coreSetup, | ||||
|   loadLocalesMapFromDir, | ||||
| } from '@vben/locales'; | ||||
| import { preferences } from '@vben/preferences'; | ||||
| 
 | ||||
| import antdEnLocale from 'ant-design-vue/es/locale/en_US'; | ||||
|  | @ -13,10 +17,12 @@ import dayjs from 'dayjs'; | |||
| 
 | ||||
| const antdLocale = ref<Locale>(antdDefaultLocale); | ||||
| 
 | ||||
| const modules = import.meta.glob('./langs/*.json'); | ||||
| 
 | ||||
| const localesMap = loadLocalesMap(modules); | ||||
| const modules = import.meta.glob('./langs/**/*.json'); | ||||
| 
 | ||||
| const localesMap = loadLocalesMapFromDir( | ||||
|   /\.\/langs\/([^/]+)\/(.*)\.json$/, | ||||
|   modules, | ||||
| ); | ||||
| /** | ||||
|  * 加载应用特有的语言包 | ||||
|  * 这里也可以改造为从服务端获取翻译数据 | ||||
|  |  | |||
|  | @ -1,125 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "demos": { | ||||
|       "title": "Demos", | ||||
|       "access": { | ||||
|         "frontendPermissions": "Frontend Permissions", | ||||
|         "backendPermissions": "Backend Permissions", | ||||
|         "pageAccess": "Page Access", | ||||
|         "buttonControl": "Button Control", | ||||
|         "menuVisible403": "Menu Visible(403)", | ||||
|         "superVisible": "Visible to Super", | ||||
|         "adminVisible": "Visible to Admin", | ||||
|         "userVisible": "Visible to User" | ||||
|       }, | ||||
|       "nested": { | ||||
|         "title": "Nested Menu", | ||||
|         "menu1": "Menu 1", | ||||
|         "menu2": "Menu 2", | ||||
|         "menu2_1": "Menu 2-1", | ||||
|         "menu3": "Menu 3", | ||||
|         "menu3_1": "Menu 3-1", | ||||
|         "menu3_2": "Menu 3-2", | ||||
|         "menu3_2_1": "Menu 3-2-1" | ||||
|       }, | ||||
|       "outside": { | ||||
|         "title": "External Pages", | ||||
|         "embedded": "Embedded", | ||||
|         "externalLink": "External Link" | ||||
|       }, | ||||
|       "badge": { | ||||
|         "title": "Menu Badge", | ||||
|         "dot": "Dot Badge", | ||||
|         "text": "Text Badge", | ||||
|         "color": "Badge Color" | ||||
|       }, | ||||
|       "activeIcon": { | ||||
|         "title": "Active Menu Icon", | ||||
|         "children": "Children Active Icon" | ||||
|       }, | ||||
|       "fallback": { | ||||
|         "title": "Fallback Page" | ||||
|       }, | ||||
|       "features": { | ||||
|         "title": "Features", | ||||
|         "hideChildrenInMenu": "Hide Menu Children", | ||||
|         "loginExpired": "Login Expired", | ||||
|         "icons": "Icons", | ||||
|         "watermark": "Watermark", | ||||
|         "tabs": "Tabs", | ||||
|         "tabDetail": "Tab Detail Page", | ||||
|         "fullScreen": { | ||||
|           "title": "FullScreen" | ||||
|         }, | ||||
|         "clipboard": "Clipboard" | ||||
|       }, | ||||
|       "breadcrumb": { | ||||
|         "navigation": "Breadcrumb Navigation", | ||||
|         "lateral": "Lateral Mode", | ||||
|         "lateralDetail": "Lateral Mode Detail", | ||||
|         "level": "Level Mode", | ||||
|         "levelDetail": "Level Mode Detail" | ||||
|       } | ||||
|     }, | ||||
|     "examples": { | ||||
|       "title": "Examples", | ||||
|       "modal": { | ||||
|         "title": "Modal" | ||||
|       }, | ||||
|       "drawer": { | ||||
|         "title": "Drawer" | ||||
|       }, | ||||
|       "ellipsis": { | ||||
|         "title": "EllipsisText" | ||||
|       }, | ||||
|       "form": { | ||||
|         "title": "Form", | ||||
|         "basic": "Basic Form", | ||||
|         "query": "Query Form", | ||||
|         "rules": "Form Rules", | ||||
|         "dynamic": "Dynamic Form", | ||||
|         "custom": "Custom Component", | ||||
|         "api": "Api", | ||||
|         "merge": "Merge Form" | ||||
|       }, | ||||
|       "vxeTable": { | ||||
|         "title": "Vxe Table", | ||||
|         "basic": "Basic Table", | ||||
|         "remote": "Remote Load", | ||||
|         "tree": "Tree Table", | ||||
|         "fixed": "Fixed Header/Column", | ||||
|         "virtual": "Virtual Scroll", | ||||
|         "editCell": "Edit Cell", | ||||
|         "editRow": "Edit Row", | ||||
|         "custom-cell": "Custom Cell", | ||||
|         "form": "Form Table" | ||||
|       }, | ||||
|       "captcha": { | ||||
|         "title": "Captcha", | ||||
|         "pointSelection": "Point Selection Captcha", | ||||
|         "sliderCaptcha": "Slider Captcha", | ||||
|         "sliderRotateCaptcha": "Rotate Captcha", | ||||
|         "captchaCardTitle": "Please complete the security verification", | ||||
|         "pageDescription": "Verify user identity by clicking on specific locations in the image.", | ||||
|         "pageTitle": "Captcha Component Example", | ||||
|         "basic": "Basic Usage", | ||||
|         "titlePlaceholder": "Captcha Title Text", | ||||
|         "captchaImageUrlPlaceholder": "Captcha Image (supports img tag src attribute value)", | ||||
|         "hintImage": "Hint Image", | ||||
|         "hintText": "Hint Text", | ||||
|         "hintImagePlaceholder": "Hint Image (supports img tag src attribute value)", | ||||
|         "hintTextPlaceholder": "Hint Text", | ||||
|         "showConfirm": "Show Confirm", | ||||
|         "hideConfirm": "Hide Confirm", | ||||
|         "widthPlaceholder": "Captcha Image Width Default 300px", | ||||
|         "heightPlaceholder": "Captcha Image Height Default 220px", | ||||
|         "paddingXPlaceholder": "Horizontal Padding Default 12px", | ||||
|         "paddingYPlaceholder": "Vertical Padding Default 16px", | ||||
|         "index": "Index:", | ||||
|         "timestamp": "Timestamp:", | ||||
|         "x": "x:", | ||||
|         "y": "y:" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,69 @@ | |||
| { | ||||
|   "title": "Demos", | ||||
|   "access": { | ||||
|     "frontendPermissions": "Frontend Permissions", | ||||
|     "backendPermissions": "Backend Permissions", | ||||
|     "pageAccess": "Page Access", | ||||
|     "buttonControl": "Button Control", | ||||
|     "menuVisible403": "Menu Visible(403)", | ||||
|     "superVisible": "Visible to Super", | ||||
|     "adminVisible": "Visible to Admin", | ||||
|     "userVisible": "Visible to User" | ||||
|   }, | ||||
|   "nested": { | ||||
|     "title": "Nested Menu", | ||||
|     "menu1": "Menu 1", | ||||
|     "menu2": "Menu 2", | ||||
|     "menu2_1": "Menu 2-1", | ||||
|     "menu3": "Menu 3", | ||||
|     "menu3_1": "Menu 3-1", | ||||
|     "menu3_2": "Menu 3-2", | ||||
|     "menu3_2_1": "Menu 3-2-1" | ||||
|   }, | ||||
|   "outside": { | ||||
|     "title": "External Pages", | ||||
|     "embedded": "Embedded", | ||||
|     "externalLink": "External Link" | ||||
|   }, | ||||
|   "badge": { | ||||
|     "title": "Menu Badge", | ||||
|     "dot": "Dot Badge", | ||||
|     "text": "Text Badge", | ||||
|     "color": "Badge Color" | ||||
|   }, | ||||
|   "activeIcon": { | ||||
|     "title": "Active Menu Icon", | ||||
|     "children": "Children Active Icon" | ||||
|   }, | ||||
|   "fallback": { | ||||
|     "title": "Fallback Page" | ||||
|   }, | ||||
|   "features": { | ||||
|     "title": "Features", | ||||
|     "hideChildrenInMenu": "Hide Menu Children", | ||||
|     "loginExpired": "Login Expired", | ||||
|     "icons": "Icons", | ||||
|     "watermark": "Watermark", | ||||
|     "tabs": "Tabs", | ||||
|     "tabDetail": "Tab Detail Page", | ||||
|     "fullScreen": { | ||||
|       "title": "FullScreen" | ||||
|     }, | ||||
|     "clipboard": "Clipboard" | ||||
|   }, | ||||
|   "breadcrumb": { | ||||
|     "navigation": "Breadcrumb Navigation", | ||||
|     "lateral": "Lateral Mode", | ||||
|     "lateralDetail": "Lateral Mode Detail", | ||||
|     "level": "Level Mode", | ||||
|     "levelDetail": "Level Mode Detail" | ||||
|   }, | ||||
|   "vben": { | ||||
|     "title": "Project", | ||||
|     "about": "About", | ||||
|     "document": "Document", | ||||
|     "antdv": "Ant Design Vue Version", | ||||
|     "naive-ui": "Naive UI Version", | ||||
|     "element-plus": "Element Plus Version" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,60 @@ | |||
| { | ||||
|   "title": "Examples", | ||||
|   "modal": { | ||||
|     "title": "Modal" | ||||
|   }, | ||||
|   "drawer": { | ||||
|     "title": "Drawer" | ||||
|   }, | ||||
|   "ellipsis": { | ||||
|     "title": "EllipsisText" | ||||
|   }, | ||||
|   "form": { | ||||
|     "title": "Form", | ||||
|     "basic": "Basic Form", | ||||
|     "query": "Query Form", | ||||
|     "rules": "Form Rules", | ||||
|     "dynamic": "Dynamic Form", | ||||
|     "custom": "Custom Component", | ||||
|     "api": "Api", | ||||
|     "merge": "Merge Form" | ||||
|   }, | ||||
|   "vxeTable": { | ||||
|     "title": "Vxe Table", | ||||
|     "basic": "Basic Table", | ||||
|     "remote": "Remote Load", | ||||
|     "tree": "Tree Table", | ||||
|     "fixed": "Fixed Header/Column", | ||||
|     "virtual": "Virtual Scroll", | ||||
|     "editCell": "Edit Cell", | ||||
|     "editRow": "Edit Row", | ||||
|     "custom-cell": "Custom Cell", | ||||
|     "form": "Form Table" | ||||
|   }, | ||||
|   "captcha": { | ||||
|     "title": "Captcha", | ||||
|     "pointSelection": "Point Selection Captcha", | ||||
|     "sliderCaptcha": "Slider Captcha", | ||||
|     "sliderRotateCaptcha": "Rotate Captcha", | ||||
|     "captchaCardTitle": "Please complete the security verification", | ||||
|     "pageDescription": "Verify user identity by clicking on specific locations in the image.", | ||||
|     "pageTitle": "Captcha Component Example", | ||||
|     "basic": "Basic Usage", | ||||
|     "titlePlaceholder": "Captcha Title Text", | ||||
|     "captchaImageUrlPlaceholder": "Captcha Image (supports img tag src attribute value)", | ||||
|     "hintImage": "Hint Image", | ||||
|     "hintText": "Hint Text", | ||||
|     "hintImagePlaceholder": "Hint Image (supports img tag src attribute value)", | ||||
|     "hintTextPlaceholder": "Hint Text", | ||||
|     "showConfirm": "Show Confirm", | ||||
|     "hideConfirm": "Hide Confirm", | ||||
|     "widthPlaceholder": "Captcha Image Width Default 300px", | ||||
|     "heightPlaceholder": "Captcha Image Height Default 220px", | ||||
|     "paddingXPlaceholder": "Horizontal Padding Default 12px", | ||||
|     "paddingYPlaceholder": "Vertical Padding Default 16px", | ||||
|     "index": "Index:", | ||||
|     "timestamp": "Timestamp:", | ||||
|     "x": "x:", | ||||
|     "y": "y:" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "auth": { | ||||
|     "login": "Login", | ||||
|     "register": "Register", | ||||
|     "codeLogin": "Code Login", | ||||
|     "qrcodeLogin": "Qr Code Login", | ||||
|     "forgetPassword": "Forget Password" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "title": "Dashboard", | ||||
|     "analytics": "Analytics", | ||||
|     "workspace": "Workspace" | ||||
|   } | ||||
| } | ||||
|  | @ -1,125 +0,0 @@ | |||
| { | ||||
|   "page": { | ||||
|     "demos": { | ||||
|       "title": "演示", | ||||
|       "access": { | ||||
|         "frontendPermissions": "前端权限", | ||||
|         "backendPermissions": "后端权限", | ||||
|         "pageAccess": "页面访问", | ||||
|         "buttonControl": "按钮控制", | ||||
|         "menuVisible403": "菜单可见(403)", | ||||
|         "superVisible": "Super 可见", | ||||
|         "adminVisible": "Admin 可见", | ||||
|         "userVisible": "User 可见" | ||||
|       }, | ||||
|       "nested": { | ||||
|         "title": "嵌套菜单", | ||||
|         "menu1": "菜单 1", | ||||
|         "menu2": "菜单 2", | ||||
|         "menu2_1": "菜单 2-1", | ||||
|         "menu3": "菜单 3", | ||||
|         "menu3_1": "菜单 3-1", | ||||
|         "menu3_2": "菜单 3-2", | ||||
|         "menu3_2_1": "菜单 3-2-1" | ||||
|       }, | ||||
|       "outside": { | ||||
|         "title": "外部页面", | ||||
|         "embedded": "内嵌", | ||||
|         "externalLink": "外链" | ||||
|       }, | ||||
|       "badge": { | ||||
|         "title": "菜单徽标", | ||||
|         "dot": "点徽标", | ||||
|         "text": "文本徽标", | ||||
|         "color": "徽标颜色" | ||||
|       }, | ||||
|       "activeIcon": { | ||||
|         "title": "菜单激活图标", | ||||
|         "children": "子级激活图标" | ||||
|       }, | ||||
|       "fallback": { | ||||
|         "title": "缺省页" | ||||
|       }, | ||||
|       "features": { | ||||
|         "title": "功能", | ||||
|         "hideChildrenInMenu": "隐藏子菜单", | ||||
|         "loginExpired": "登录过期", | ||||
|         "icons": "图标", | ||||
|         "watermark": "水印", | ||||
|         "tabs": "标签页", | ||||
|         "tabDetail": "标签详情页", | ||||
|         "fullScreen": { | ||||
|           "title": "全屏" | ||||
|         }, | ||||
|         "clipboard": "剪贴板" | ||||
|       }, | ||||
|       "breadcrumb": { | ||||
|         "navigation": "面包屑导航", | ||||
|         "lateral": "平级模式", | ||||
|         "level": "层级模式", | ||||
|         "levelDetail": "层级模式详情", | ||||
|         "lateralDetail": "平级模式详情" | ||||
|       } | ||||
|     }, | ||||
|     "examples": { | ||||
|       "title": "示例", | ||||
|       "modal": { | ||||
|         "title": "弹窗" | ||||
|       }, | ||||
|       "drawer": { | ||||
|         "title": "抽屉" | ||||
|       }, | ||||
|       "ellipsis": { | ||||
|         "title": "文本省略" | ||||
|       }, | ||||
|       "form": { | ||||
|         "title": "表单", | ||||
|         "basic": "基础表单", | ||||
|         "query": "查询表单", | ||||
|         "rules": "表单校验", | ||||
|         "dynamic": "动态表单", | ||||
|         "custom": "自定义组件", | ||||
|         "api": "Api", | ||||
|         "merge": "合并表单" | ||||
|       }, | ||||
|       "vxeTable": { | ||||
|         "title": "Vxe 表格", | ||||
|         "basic": "基础表格", | ||||
|         "remote": "远程加载", | ||||
|         "tree": "树形表格", | ||||
|         "fixed": "固定表头/列", | ||||
|         "virtual": "虚拟滚动", | ||||
|         "editCell": "单元格编辑", | ||||
|         "editRow": "行编辑", | ||||
|         "custom-cell": "自定义单元格", | ||||
|         "form": "搜索表单" | ||||
|       }, | ||||
|       "captcha": { | ||||
|         "title": "验证码", | ||||
|         "pointSelection": "点选验证", | ||||
|         "sliderCaptcha": "滑块验证", | ||||
|         "sliderRotateCaptcha": "旋转验证", | ||||
|         "captchaCardTitle": "请完成安全验证", | ||||
|         "pageDescription": "通过点击图片中的特定位置来验证用户身份。", | ||||
|         "pageTitle": "验证码组件示例", | ||||
|         "basic": "基本使用", | ||||
|         "titlePlaceholder": "验证码标题文案", | ||||
|         "captchaImageUrlPlaceholder": "验证码图片(支持img标签src属性值)", | ||||
|         "hintImage": "提示图片", | ||||
|         "hintText": "提示文本", | ||||
|         "hintImagePlaceholder": "提示图片(支持img标签src属性值)", | ||||
|         "hintTextPlaceholder": "提示文本", | ||||
|         "showConfirm": "展示确认", | ||||
|         "hideConfirm": "隐藏确认", | ||||
|         "widthPlaceholder": "验证码图片宽度 默认300px", | ||||
|         "heightPlaceholder": "验证码图片高度 默认220px", | ||||
|         "paddingXPlaceholder": "水平内边距 默认12px", | ||||
|         "paddingYPlaceholder": "垂直内边距 默认16px", | ||||
|         "index": "索引:", | ||||
|         "timestamp": "时间戳:", | ||||
|         "x": "x:", | ||||
|         "y": "y:" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,69 @@ | |||
| { | ||||
|   "title": "演示", | ||||
|   "access": { | ||||
|     "frontendPermissions": "前端权限", | ||||
|     "backendPermissions": "后端权限", | ||||
|     "pageAccess": "页面访问", | ||||
|     "buttonControl": "按钮控制", | ||||
|     "menuVisible403": "菜单可见(403)", | ||||
|     "superVisible": "Super 可见", | ||||
|     "adminVisible": "Admin 可见", | ||||
|     "userVisible": "User 可见" | ||||
|   }, | ||||
|   "nested": { | ||||
|     "title": "嵌套菜单", | ||||
|     "menu1": "菜单 1", | ||||
|     "menu2": "菜单 2", | ||||
|     "menu2_1": "菜单 2-1", | ||||
|     "menu3": "菜单 3", | ||||
|     "menu3_1": "菜单 3-1", | ||||
|     "menu3_2": "菜单 3-2", | ||||
|     "menu3_2_1": "菜单 3-2-1" | ||||
|   }, | ||||
|   "outside": { | ||||
|     "title": "外部页面", | ||||
|     "embedded": "内嵌", | ||||
|     "externalLink": "外链" | ||||
|   }, | ||||
|   "badge": { | ||||
|     "title": "菜单徽标", | ||||
|     "dot": "点徽标", | ||||
|     "text": "文本徽标", | ||||
|     "color": "徽标颜色" | ||||
|   }, | ||||
|   "activeIcon": { | ||||
|     "title": "菜单激活图标", | ||||
|     "children": "子级激活图标" | ||||
|   }, | ||||
|   "fallback": { | ||||
|     "title": "缺省页" | ||||
|   }, | ||||
|   "features": { | ||||
|     "title": "功能", | ||||
|     "hideChildrenInMenu": "隐藏子菜单", | ||||
|     "loginExpired": "登录过期", | ||||
|     "icons": "图标", | ||||
|     "watermark": "水印", | ||||
|     "tabs": "标签页", | ||||
|     "tabDetail": "标签详情页", | ||||
|     "fullScreen": { | ||||
|       "title": "全屏" | ||||
|     }, | ||||
|     "clipboard": "剪贴板" | ||||
|   }, | ||||
|   "breadcrumb": { | ||||
|     "navigation": "面包屑导航", | ||||
|     "lateral": "平级模式", | ||||
|     "level": "层级模式", | ||||
|     "levelDetail": "层级模式详情", | ||||
|     "lateralDetail": "平级模式详情" | ||||
|   }, | ||||
|   "vben": { | ||||
|     "title": "项目", | ||||
|     "about": "关于", | ||||
|     "document": "文档", | ||||
|     "antdv": "Ant Design Vue 版本", | ||||
|     "naive-ui": "Naive UI 版本", | ||||
|     "element-plus": "Element Plus 版本" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,60 @@ | |||
| { | ||||
|   "title": "示例", | ||||
|   "modal": { | ||||
|     "title": "弹窗" | ||||
|   }, | ||||
|   "drawer": { | ||||
|     "title": "抽屉" | ||||
|   }, | ||||
|   "ellipsis": { | ||||
|     "title": "文本省略" | ||||
|   }, | ||||
|   "form": { | ||||
|     "title": "表单", | ||||
|     "basic": "基础表单", | ||||
|     "query": "查询表单", | ||||
|     "rules": "表单校验", | ||||
|     "dynamic": "动态表单", | ||||
|     "custom": "自定义组件", | ||||
|     "api": "Api", | ||||
|     "merge": "合并表单" | ||||
|   }, | ||||
|   "vxeTable": { | ||||
|     "title": "Vxe 表格", | ||||
|     "basic": "基础表格", | ||||
|     "remote": "远程加载", | ||||
|     "tree": "树形表格", | ||||
|     "fixed": "固定表头/列", | ||||
|     "virtual": "虚拟滚动", | ||||
|     "editCell": "单元格编辑", | ||||
|     "editRow": "行编辑", | ||||
|     "custom-cell": "自定义单元格", | ||||
|     "form": "搜索表单" | ||||
|   }, | ||||
|   "captcha": { | ||||
|     "title": "验证码", | ||||
|     "pointSelection": "点选验证", | ||||
|     "sliderCaptcha": "滑块验证", | ||||
|     "sliderRotateCaptcha": "旋转验证", | ||||
|     "captchaCardTitle": "请完成安全验证", | ||||
|     "pageDescription": "通过点击图片中的特定位置来验证用户身份。", | ||||
|     "pageTitle": "验证码组件示例", | ||||
|     "basic": "基本使用", | ||||
|     "titlePlaceholder": "验证码标题文案", | ||||
|     "captchaImageUrlPlaceholder": "验证码图片(支持img标签src属性值)", | ||||
|     "hintImage": "提示图片", | ||||
|     "hintText": "提示文本", | ||||
|     "hintImagePlaceholder": "提示图片(支持img标签src属性值)", | ||||
|     "hintTextPlaceholder": "提示文本", | ||||
|     "showConfirm": "展示确认", | ||||
|     "hideConfirm": "隐藏确认", | ||||
|     "widthPlaceholder": "验证码图片宽度 默认300px", | ||||
|     "heightPlaceholder": "验证码图片高度 默认220px", | ||||
|     "paddingXPlaceholder": "水平内边距 默认12px", | ||||
|     "paddingYPlaceholder": "垂直内边距 默认16px", | ||||
|     "index": "索引:", | ||||
|     "timestamp": "时间戳:", | ||||
|     "x": "x:", | ||||
|     "y": "y:" | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|   "auth": { | ||||
|     "login": "登陆", | ||||
|     "register": "注册", | ||||
|     "codeLogin": "验证码登陆", | ||||
|     "qrcodeLogin": "二维码登陆", | ||||
|     "forgetPassword": "忘记密码" | ||||
|   }, | ||||
|   "dashboard": { | ||||
|     "title": "概览", | ||||
|     "analytics": "分析页", | ||||
|     "workspace": "工作台" | ||||
|   } | ||||
| } | ||||
|  | @ -43,7 +43,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'login', | ||||
|         component: Login, | ||||
|         meta: { | ||||
|           title: $t('page.core.login'), | ||||
|           title: $t('page.auth.login'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -51,7 +51,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'code-login', | ||||
|         component: () => import('#/views/_core/authentication/code-login.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.codeLogin'), | ||||
|           title: $t('page.auth.codeLogin'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -60,7 +60,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         component: () => | ||||
|           import('#/views/_core/authentication/qrcode-login.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.qrcodeLogin'), | ||||
|           title: $t('page.auth.qrcodeLogin'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -69,7 +69,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         component: () => | ||||
|           import('#/views/_core/authentication/forget-password.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.forgetPassword'), | ||||
|           title: $t('page.auth.forgetPassword'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -77,7 +77,7 @@ const coreRoutes: RouteRecordRaw[] = [ | |||
|         path: 'register', | ||||
|         component: () => import('#/views/_core/authentication/register.vue'), | ||||
|         meta: { | ||||
|           title: $t('page.core.register'), | ||||
|           title: $t('page.auth.register'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       icon: 'ic:baseline-view-in-ar', | ||||
|       keepAlive: true, | ||||
|       order: 1000, | ||||
|       title: $t('page.demos.title'), | ||||
|       title: $t('demos.title'), | ||||
|     }, | ||||
|     name: 'Demos', | ||||
|     path: '/demos', | ||||
|  | @ -19,7 +19,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       { | ||||
|         meta: { | ||||
|           icon: 'mdi:shield-key-outline', | ||||
|           title: $t('page.demos.access.frontendPermissions'), | ||||
|           title: $t('demos.access.frontendPermissions'), | ||||
|         }, | ||||
|         name: 'AccessDemos', | ||||
|         path: '/demos/access', | ||||
|  | @ -30,7 +30,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => import('#/views/demos/access/index.vue'), | ||||
|             meta: { | ||||
|               icon: 'mdi:page-previous-outline', | ||||
|               title: $t('page.demos.access.pageAccess'), | ||||
|               title: $t('demos.access.pageAccess'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -39,7 +39,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => import('#/views/demos/access/button-control.vue'), | ||||
|             meta: { | ||||
|               icon: 'mdi:button-cursor', | ||||
|               title: $t('page.demos.access.buttonControl'), | ||||
|               title: $t('demos.access.buttonControl'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -51,7 +51,7 @@ const routes: RouteRecordRaw[] = [ | |||
|               authority: ['no-body'], | ||||
|               icon: 'mdi:button-cursor', | ||||
|               menuVisibleWithForbidden: true, | ||||
|               title: $t('page.demos.access.menuVisible403'), | ||||
|               title: $t('demos.access.menuVisible403'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -61,7 +61,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               authority: ['super'], | ||||
|               icon: 'mdi:button-cursor', | ||||
|               title: $t('page.demos.access.superVisible'), | ||||
|               title: $t('demos.access.superVisible'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -71,7 +71,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               authority: ['admin'], | ||||
|               icon: 'mdi:button-cursor', | ||||
|               title: $t('page.demos.access.adminVisible'), | ||||
|               title: $t('demos.access.adminVisible'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -81,7 +81,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               authority: ['user'], | ||||
|               icon: 'mdi:button-cursor', | ||||
|               title: $t('page.demos.access.userVisible'), | ||||
|               title: $t('demos.access.userVisible'), | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|  | @ -90,7 +90,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       { | ||||
|         meta: { | ||||
|           icon: 'mdi:feature-highlight', | ||||
|           title: $t('page.demos.features.title'), | ||||
|           title: $t('demos.features.title'), | ||||
|         }, | ||||
|         name: 'FeaturesDemos', | ||||
|         path: '/demos/features', | ||||
|  | @ -102,7 +102,7 @@ const routes: RouteRecordRaw[] = [ | |||
|               import('#/views/demos/features/login-expired/index.vue'), | ||||
|             meta: { | ||||
|               icon: 'mdi:encryption-expiration', | ||||
|               title: $t('page.demos.features.loginExpired'), | ||||
|               title: $t('demos.features.loginExpired'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -111,7 +111,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => import('#/views/demos/features/icons/index.vue'), | ||||
|             meta: { | ||||
|               icon: 'lucide:annoyed', | ||||
|               title: $t('page.demos.features.icons'), | ||||
|               title: $t('demos.features.icons'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -121,7 +121,7 @@ const routes: RouteRecordRaw[] = [ | |||
|               import('#/views/demos/features/watermark/index.vue'), | ||||
|             meta: { | ||||
|               icon: 'lucide:tags', | ||||
|               title: $t('page.demos.features.watermark'), | ||||
|               title: $t('demos.features.watermark'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -130,7 +130,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => import('#/views/demos/features/tabs/index.vue'), | ||||
|             meta: { | ||||
|               icon: 'lucide:app-window', | ||||
|               title: $t('page.demos.features.tabs'), | ||||
|               title: $t('demos.features.tabs'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -142,7 +142,7 @@ const routes: RouteRecordRaw[] = [ | |||
|               activePath: '/demos/features/tabs', | ||||
|               hideInMenu: true, | ||||
|               maxNumOfOpenTab: 3, | ||||
|               title: $t('page.demos.features.tabDetail'), | ||||
|               title: $t('demos.features.tabDetail'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -153,7 +153,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               hideChildrenInMenu: true, | ||||
|               icon: 'ic:round-menu', | ||||
|               title: $t('page.demos.features.hideChildrenInMenu'), | ||||
|               title: $t('demos.features.hideChildrenInMenu'), | ||||
|             }, | ||||
|             children: [ | ||||
|               { | ||||
|  | @ -163,7 +163,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                   import( | ||||
|                     '#/views/demos/features/hide-menu-children/children.vue' | ||||
|                   ), | ||||
|                 meta: { title: $t('page.demos.features.hideChildrenInMenu') }, | ||||
|                 meta: { title: $t('demos.features.hideChildrenInMenu') }, | ||||
|               }, | ||||
|             ], | ||||
|           }, | ||||
|  | @ -174,7 +174,7 @@ const routes: RouteRecordRaw[] = [ | |||
|               import('#/views/demos/features/full-screen/index.vue'), | ||||
|             meta: { | ||||
|               icon: 'lucide:fullscreen', | ||||
|               title: $t('page.demos.features.fullScreen.title'), | ||||
|               title: $t('demos.features.fullScreen.title'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -184,7 +184,7 @@ const routes: RouteRecordRaw[] = [ | |||
|               import('#/views/demos/features/clipboard/index.vue'), | ||||
|             meta: { | ||||
|               icon: 'lucide:copy', | ||||
|               title: $t('page.demos.features.clipboard'), | ||||
|               title: $t('demos.features.clipboard'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -205,7 +205,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         path: '/demos/breadcrumb', | ||||
|         meta: { | ||||
|           icon: 'lucide:navigation', | ||||
|           title: $t('page.demos.breadcrumb.navigation'), | ||||
|           title: $t('demos.breadcrumb.navigation'), | ||||
|         }, | ||||
|         children: [ | ||||
|           { | ||||
|  | @ -214,7 +214,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => import('#/views/demos/breadcrumb/lateral.vue'), | ||||
|             meta: { | ||||
|               icon: 'lucide:navigation', | ||||
|               title: $t('page.demos.breadcrumb.lateral'), | ||||
|               title: $t('demos.breadcrumb.lateral'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -225,7 +225,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               activePath: '/demos/breadcrumb/lateral', | ||||
|               hideInMenu: true, | ||||
|               title: $t('page.demos.breadcrumb.lateralDetail'), | ||||
|               title: $t('demos.breadcrumb.lateralDetail'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -233,7 +233,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/demos/breadcrumb/level', | ||||
|             meta: { | ||||
|               icon: 'lucide:navigation', | ||||
|               title: $t('page.demos.breadcrumb.level'), | ||||
|               title: $t('demos.breadcrumb.level'), | ||||
|             }, | ||||
|             children: [ | ||||
|               { | ||||
|  | @ -242,7 +242,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 component: () => | ||||
|                   import('#/views/demos/breadcrumb/level-detail.vue'), | ||||
|                 meta: { | ||||
|                   title: $t('page.demos.breadcrumb.levelDetail'), | ||||
|                   title: $t('demos.breadcrumb.levelDetail'), | ||||
|                 }, | ||||
|               }, | ||||
|             ], | ||||
|  | @ -253,7 +253,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       { | ||||
|         meta: { | ||||
|           icon: 'mdi:lightbulb-error-outline', | ||||
|           title: $t('page.demos.fallback.title'), | ||||
|           title: $t('demos.fallback.title'), | ||||
|         }, | ||||
|         name: 'FallbackDemos', | ||||
|         path: '/demos/fallback', | ||||
|  | @ -292,7 +292,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => import('#/views/_core/fallback/offline.vue'), | ||||
|             meta: { | ||||
|               icon: 'mdi:offline', | ||||
|               title: $t('fallback.offline'), | ||||
|               title: $t('ui.fallback.offline'), | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|  | @ -303,7 +303,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           badgeVariants: 'destructive', | ||||
|           icon: 'lucide:circle-dot', | ||||
|           title: $t('page.demos.badge.title'), | ||||
|           title: $t('demos.badge.title'), | ||||
|         }, | ||||
|         name: 'BadgeDemos', | ||||
|         path: '/demos/badge', | ||||
|  | @ -315,7 +315,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               badgeType: 'dot', | ||||
|               icon: 'lucide:square-dot', | ||||
|               title: $t('page.demos.badge.dot'), | ||||
|               title: $t('demos.badge.dot'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -325,7 +325,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               badge: '10', | ||||
|               icon: 'lucide:square-dot', | ||||
|               title: $t('page.demos.badge.text'), | ||||
|               title: $t('demos.badge.text'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -336,7 +336,7 @@ const routes: RouteRecordRaw[] = [ | |||
|               badge: 'Hot', | ||||
|               badgeVariants: 'destructive', | ||||
|               icon: 'lucide:square-dot', | ||||
|               title: $t('page.demos.badge.color'), | ||||
|               title: $t('demos.badge.color'), | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|  | @ -346,7 +346,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         meta: { | ||||
|           activeIcon: 'fluent-emoji:radioactive', | ||||
|           icon: 'bi:radioactive', | ||||
|           title: $t('page.demos.activeIcon.title'), | ||||
|           title: $t('demos.activeIcon.title'), | ||||
|         }, | ||||
|         name: 'ActiveIconDemos', | ||||
|         path: '/demos/active-icon', | ||||
|  | @ -358,7 +358,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               activeIcon: 'fluent-emoji:radioactive', | ||||
|               icon: 'bi:radioactive', | ||||
|               title: $t('page.demos.activeIcon.children'), | ||||
|               title: $t('demos.activeIcon.children'), | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|  | @ -367,7 +367,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       { | ||||
|         meta: { | ||||
|           icon: 'ic:round-settings-input-composite', | ||||
|           title: $t('page.demos.outside.title'), | ||||
|           title: $t('demos.outside.title'), | ||||
|         }, | ||||
|         name: 'OutsideDemos', | ||||
|         path: '/demos/outside', | ||||
|  | @ -377,7 +377,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/demos/outside/iframe', | ||||
|             meta: { | ||||
|               icon: 'mdi:newspaper-variant-outline', | ||||
|               title: $t('page.demos.outside.embedded'), | ||||
|               title: $t('demos.outside.embedded'), | ||||
|             }, | ||||
|             children: [ | ||||
|               { | ||||
|  | @ -409,7 +409,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/demos/outside/external-link', | ||||
|             meta: { | ||||
|               icon: 'mdi:newspaper-variant-multiple-outline', | ||||
|               title: $t('page.demos.outside.externalLink'), | ||||
|               title: $t('demos.outside.externalLink'), | ||||
|             }, | ||||
|             children: [ | ||||
|               { | ||||
|  | @ -440,7 +440,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       { | ||||
|         meta: { | ||||
|           icon: 'ic:round-menu', | ||||
|           title: $t('page.demos.nested.title'), | ||||
|           title: $t('demos.nested.title'), | ||||
|         }, | ||||
|         name: 'NestedDemos', | ||||
|         path: '/demos/nested', | ||||
|  | @ -452,7 +452,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               keepAlive: true, | ||||
|               title: $t('page.demos.nested.menu1'), | ||||
|               title: $t('demos.nested.menu1'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -461,7 +461,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               keepAlive: true, | ||||
|               title: $t('page.demos.nested.menu2'), | ||||
|               title: $t('demos.nested.menu2'), | ||||
|             }, | ||||
|             children: [ | ||||
|               { | ||||
|  | @ -471,7 +471,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   keepAlive: true, | ||||
|                   title: $t('page.demos.nested.menu2_1'), | ||||
|                   title: $t('demos.nested.menu2_1'), | ||||
|                 }, | ||||
|               }, | ||||
|             ], | ||||
|  | @ -481,7 +481,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/demos/nested/menu3', | ||||
|             meta: { | ||||
|               icon: 'ic:round-menu', | ||||
|               title: $t('page.demos.nested.menu3'), | ||||
|               title: $t('demos.nested.menu3'), | ||||
|             }, | ||||
|             children: [ | ||||
|               { | ||||
|  | @ -491,7 +491,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   keepAlive: true, | ||||
|                   title: $t('page.demos.nested.menu3_1'), | ||||
|                   title: $t('demos.nested.menu3_1'), | ||||
|                 }, | ||||
|               }, | ||||
|               { | ||||
|  | @ -499,7 +499,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                 path: 'menu3-2', | ||||
|                 meta: { | ||||
|                   icon: 'ic:round-menu', | ||||
|                   title: $t('page.demos.nested.menu3_2'), | ||||
|                   title: $t('demos.nested.menu3_2'), | ||||
|                 }, | ||||
|                 children: [ | ||||
|                   { | ||||
|  | @ -510,7 +510,7 @@ const routes: RouteRecordRaw[] = [ | |||
|                     meta: { | ||||
|                       icon: 'ic:round-menu', | ||||
|                       keepAlive: true, | ||||
|                       title: $t('page.demos.nested.menu3_2_1'), | ||||
|                       title: $t('demos.nested.menu3_2_1'), | ||||
|                     }, | ||||
|                   }, | ||||
|                 ], | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       icon: 'ion:layers-outline', | ||||
|       keepAlive: true, | ||||
|       order: 1000, | ||||
|       title: $t('page.examples.title'), | ||||
|       title: $t('examples.title'), | ||||
|     }, | ||||
|     name: 'Examples', | ||||
|     path: '/examples', | ||||
|  | @ -21,7 +21,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         component: () => import('#/views/examples/modal/index.vue'), | ||||
|         meta: { | ||||
|           icon: 'system-uicons:window-content', | ||||
|           title: $t('page.examples.modal.title'), | ||||
|           title: $t('examples.modal.title'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -30,7 +30,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         component: () => import('#/views/examples/drawer/index.vue'), | ||||
|         meta: { | ||||
|           icon: 'iconoir:drawer', | ||||
|           title: $t('page.examples.drawer.title'), | ||||
|           title: $t('examples.drawer.title'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -39,7 +39,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         component: () => import('#/views/examples/ellipsis/index.vue'), | ||||
|         meta: { | ||||
|           icon: 'ion:ellipsis-horizontal', | ||||
|           title: $t('page.examples.ellipsis.title'), | ||||
|           title: $t('examples.ellipsis.title'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -47,7 +47,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         path: '/examples/form', | ||||
|         meta: { | ||||
|           icon: 'mdi:form-select', | ||||
|           title: $t('page.examples.form.title'), | ||||
|           title: $t('examples.form.title'), | ||||
|         }, | ||||
|         children: [ | ||||
|           { | ||||
|  | @ -55,7 +55,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/form/basic', | ||||
|             component: () => import('#/views/examples/form/basic.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.form.basic'), | ||||
|               title: $t('examples.form.basic'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -63,7 +63,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/form/query', | ||||
|             component: () => import('#/views/examples/form/query.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.form.query'), | ||||
|               title: $t('examples.form.query'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -71,7 +71,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/form/rules', | ||||
|             component: () => import('#/views/examples/form/rules.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.form.rules'), | ||||
|               title: $t('examples.form.rules'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -79,7 +79,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/form/dynamic', | ||||
|             component: () => import('#/views/examples/form/dynamic.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.form.dynamic'), | ||||
|               title: $t('examples.form.dynamic'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -87,7 +87,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/form/custom', | ||||
|             component: () => import('#/views/examples/form/custom.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.form.custom'), | ||||
|               title: $t('examples.form.custom'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -95,7 +95,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/form/api', | ||||
|             component: () => import('#/views/examples/form/api.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.form.api'), | ||||
|               title: $t('examples.form.api'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -103,7 +103,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/form/merge', | ||||
|             component: () => import('#/views/examples/form/merge.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.form.merge'), | ||||
|               title: $t('examples.form.merge'), | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|  | @ -113,7 +113,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         path: '/examples/vxe-table', | ||||
|         meta: { | ||||
|           icon: 'lucide:table', | ||||
|           title: $t('page.examples.vxeTable.title'), | ||||
|           title: $t('examples.vxeTable.title'), | ||||
|         }, | ||||
|         children: [ | ||||
|           { | ||||
|  | @ -121,7 +121,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/vxe-table/basic', | ||||
|             component: () => import('#/views/examples/vxe-table/basic.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.basic'), | ||||
|               title: $t('examples.vxeTable.basic'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -129,7 +129,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/vxe-table/remote', | ||||
|             component: () => import('#/views/examples/vxe-table/remote.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.remote'), | ||||
|               title: $t('examples.vxeTable.remote'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -137,7 +137,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/vxe-table/tree', | ||||
|             component: () => import('#/views/examples/vxe-table/tree.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.tree'), | ||||
|               title: $t('examples.vxeTable.tree'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -145,7 +145,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/vxe-table/fixed', | ||||
|             component: () => import('#/views/examples/vxe-table/fixed.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.fixed'), | ||||
|               title: $t('examples.vxeTable.fixed'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -154,7 +154,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => | ||||
|               import('#/views/examples/vxe-table/custom-cell.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.custom-cell'), | ||||
|               title: $t('examples.vxeTable.custom-cell'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -162,7 +162,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/vxe-table/form', | ||||
|             component: () => import('#/views/examples/vxe-table/form.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.form'), | ||||
|               title: $t('examples.vxeTable.form'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -170,7 +170,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/vxe-table/edit-cell', | ||||
|             component: () => import('#/views/examples/vxe-table/edit-cell.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.editCell'), | ||||
|               title: $t('examples.vxeTable.editCell'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -178,7 +178,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/vxe-table/edit-row', | ||||
|             component: () => import('#/views/examples/vxe-table/edit-row.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.editRow'), | ||||
|               title: $t('examples.vxeTable.editRow'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -186,7 +186,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             path: '/examples/vxe-table/virtual', | ||||
|             component: () => import('#/views/examples/vxe-table/virtual.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.vxeTable.virtual'), | ||||
|               title: $t('examples.vxeTable.virtual'), | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|  | @ -196,7 +196,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         path: '/examples/captcha', | ||||
|         meta: { | ||||
|           icon: 'logos:recaptcha', | ||||
|           title: $t('page.examples.captcha.title'), | ||||
|           title: $t('examples.captcha.title'), | ||||
|         }, | ||||
|         children: [ | ||||
|           { | ||||
|  | @ -205,7 +205,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => | ||||
|               import('#/views/examples/captcha/slider-captcha.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.captcha.sliderCaptcha'), | ||||
|               title: $t('examples.captcha.sliderCaptcha'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -214,7 +214,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => | ||||
|               import('#/views/examples/captcha/slider-rotate-captcha.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.captcha.sliderRotateCaptcha'), | ||||
|               title: $t('examples.captcha.sliderRotateCaptcha'), | ||||
|             }, | ||||
|           }, | ||||
|           { | ||||
|  | @ -223,7 +223,7 @@ const routes: RouteRecordRaw[] = [ | |||
|             component: () => | ||||
|               import('#/views/examples/captcha/point-selection-captcha.vue'), | ||||
|             meta: { | ||||
|               title: $t('page.examples.captcha.pointSelection'), | ||||
|               title: $t('examples.captcha.pointSelection'), | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ const routes: RouteRecordRaw[] = [ | |||
|       badgeType: 'dot', | ||||
|       icon: VBEN_LOGO_URL, | ||||
|       order: 9999, | ||||
|       title: $t('page.vben.title'), | ||||
|       title: $t('demos.vben.title'), | ||||
|     }, | ||||
|     name: 'VbenProject', | ||||
|     path: '/vben-admin', | ||||
|  | @ -31,7 +31,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         component: () => import('#/views/_core/about/index.vue'), | ||||
|         meta: { | ||||
|           icon: 'lucide:copyright', | ||||
|           title: $t('page.vben.about'), | ||||
|           title: $t('demos.vben.about'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -41,7 +41,7 @@ const routes: RouteRecordRaw[] = [ | |||
|         meta: { | ||||
|           icon: 'lucide:book-open-text', | ||||
|           link: VBEN_DOC_URL, | ||||
|           title: $t('page.vben.document'), | ||||
|           title: $t('demos.vben.document'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -62,7 +62,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: SvgAntdvLogoIcon, | ||||
|           link: VBEN_ANT_PREVIEW_URL, | ||||
|           title: $t('page.vben.antdv'), | ||||
|           title: $t('demos.vben.antdv'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -73,7 +73,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: 'logos:naiveui', | ||||
|           link: VBEN_NAIVE_PREVIEW_URL, | ||||
|           title: $t('page.vben.naive-ui'), | ||||
|           title: $t('demos.vben.naive-ui'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -84,7 +84,7 @@ const routes: RouteRecordRaw[] = [ | |||
|           badgeType: 'dot', | ||||
|           icon: 'logos:element', | ||||
|           link: VBEN_ELE_PREVIEW_URL, | ||||
|           title: $t('page.vben.element-plus'), | ||||
|           title: $t('demos.vben.element-plus'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  |  | |||
|  | @ -47,47 +47,44 @@ const handleClick = (point: CaptchaPoint) => { | |||
| 
 | ||||
| <template> | ||||
|   <Page | ||||
|     :description="$t('page.examples.captcha.pageDescription')" | ||||
|     :title="$t('page.examples.captcha.pageTitle')" | ||||
|     :description="$t('examples.captcha.pageDescription')" | ||||
|     :title="$t('examples.captcha.pageTitle')" | ||||
|   > | ||||
|     <Card | ||||
|       :title="$t('page.examples.captcha.basic')" | ||||
|       class="mb-4 overflow-x-auto" | ||||
|     > | ||||
|     <Card :title="$t('examples.captcha.basic')" class="mb-4 overflow-x-auto"> | ||||
|       <div class="mb-3 flex items-center justify-start"> | ||||
|         <Input | ||||
|           v-model:value="params.title" | ||||
|           :placeholder="$t('page.examples.captcha.titlePlaceholder')" | ||||
|           :placeholder="$t('examples.captcha.titlePlaceholder')" | ||||
|           class="w-64" | ||||
|         /> | ||||
|         <Input | ||||
|           v-model:value="params.captchaImageUrl" | ||||
|           :placeholder="$t('page.examples.captcha.captchaImageUrlPlaceholder')" | ||||
|           :placeholder="$t('examples.captcha.captchaImageUrlPlaceholder')" | ||||
|           class="ml-8 w-64" | ||||
|         /> | ||||
|         <div class="ml-8 flex w-96 items-center"> | ||||
|           <Switch | ||||
|             v-model:checked="params.showHintImage" | ||||
|             :checked-children="$t('page.examples.captcha.hintImage')" | ||||
|             :un-checked-children="$t('page.examples.captcha.hintText')" | ||||
|             :checked-children="$t('examples.captcha.hintImage')" | ||||
|             :un-checked-children="$t('examples.captcha.hintText')" | ||||
|             class="mr-4 w-40" | ||||
|           /> | ||||
|           <Input | ||||
|             v-show="params.showHintImage" | ||||
|             v-model:value="params.hintImageUrl" | ||||
|             :placeholder="$t('page.examples.captcha.hintImagePlaceholder')" | ||||
|             :placeholder="$t('examples.captcha.hintImagePlaceholder')" | ||||
|           /> | ||||
|           <Input | ||||
|             v-show="!params.showHintImage" | ||||
|             v-model:value="params.hintText" | ||||
|             :placeholder="$t('page.examples.captcha.hintTextPlaceholder')" | ||||
|             :placeholder="$t('examples.captcha.hintTextPlaceholder')" | ||||
|           /> | ||||
|         </div> | ||||
| 
 | ||||
|         <Switch | ||||
|           v-model:checked="params.showConfirm" | ||||
|           :checked-children="$t('page.examples.captcha.showConfirm')" | ||||
|           :un-checked-children="$t('page.examples.captcha.hideConfirm')" | ||||
|           :checked-children="$t('examples.captcha.showConfirm')" | ||||
|           :un-checked-children="$t('examples.captcha.hideConfirm')" | ||||
|           class="ml-8 w-28" | ||||
|         /> | ||||
|       </div> | ||||
|  | @ -96,7 +93,7 @@ const handleClick = (point: CaptchaPoint) => { | |||
|           <InputNumber | ||||
|             v-model:value="params.width" | ||||
|             :min="1" | ||||
|             :placeholder="$t('page.examples.captcha.widthPlaceholder')" | ||||
|             :placeholder="$t('examples.captcha.widthPlaceholder')" | ||||
|             :precision="0" | ||||
|             :step="1" | ||||
|             class="w-64" | ||||
|  | @ -108,7 +105,7 @@ const handleClick = (point: CaptchaPoint) => { | |||
|           <InputNumber | ||||
|             v-model:value="params.height" | ||||
|             :min="1" | ||||
|             :placeholder="$t('page.examples.captcha.heightPlaceholder')" | ||||
|             :placeholder="$t('examples.captcha.heightPlaceholder')" | ||||
|             :precision="0" | ||||
|             :step="1" | ||||
|             class="w-64" | ||||
|  | @ -120,7 +117,7 @@ const handleClick = (point: CaptchaPoint) => { | |||
|           <InputNumber | ||||
|             v-model:value="params.paddingX" | ||||
|             :min="1" | ||||
|             :placeholder="$t('page.examples.captcha.paddingXPlaceholder')" | ||||
|             :placeholder="$t('examples.captcha.paddingXPlaceholder')" | ||||
|             :precision="0" | ||||
|             :step="1" | ||||
|             class="w-64" | ||||
|  | @ -132,7 +129,7 @@ const handleClick = (point: CaptchaPoint) => { | |||
|           <InputNumber | ||||
|             v-model:value="params.paddingY" | ||||
|             :min="1" | ||||
|             :placeholder="$t('page.examples.captcha.paddingYPlaceholder')" | ||||
|             :placeholder="$t('examples.captcha.paddingYPlaceholder')" | ||||
|             :precision="0" | ||||
|             :step="1" | ||||
|             class="w-64" | ||||
|  | @ -159,23 +156,23 @@ const handleClick = (point: CaptchaPoint) => { | |||
|         @refresh="handleRefresh" | ||||
|       > | ||||
|         <template #title> | ||||
|           {{ params.title || $t('page.examples.captcha.captchaCardTitle') }} | ||||
|           {{ params.title || $t('examples.captcha.captchaCardTitle') }} | ||||
|         </template> | ||||
|       </PointSelectionCaptcha> | ||||
| 
 | ||||
|       <ol class="float-left p-5"> | ||||
|         <li v-for="point in selectedPoints" :key="point.i" class="flex"> | ||||
|           <span class="mr-3 w-16">{{ | ||||
|             $t('page.examples.captcha.index') + point.i | ||||
|             $t('examples.captcha.index') + point.i | ||||
|           }}</span> | ||||
|           <span class="mr-3 w-52">{{ | ||||
|             $t('page.examples.captcha.timestamp') + point.t | ||||
|             $t('examples.captcha.timestamp') + point.t | ||||
|           }}</span> | ||||
|           <span class="mr-3 w-16">{{ | ||||
|             $t('page.examples.captcha.x') + point.x | ||||
|             $t('examples.captcha.x') + point.x | ||||
|           }}</span> | ||||
|           <span class="mr-3 w-16">{{ | ||||
|             $t('page.examples.captcha.y') + point.y | ||||
|             $t('examples.captcha.y') + point.y | ||||
|           }}</span> | ||||
|         </li> | ||||
|       </ol> | ||||
|  |  | |||
							
								
								
									
										541
									
								
								pnpm-lock.yaml
								
								
								
								
							
							
						
						
									
										541
									
								
								pnpm-lock.yaml
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -20,7 +20,7 @@ catalog: | |||
|   '@commitlint/cli': ^19.5.0 | ||||
|   '@commitlint/config-conventional': ^19.5.0 | ||||
|   '@ctrl/tinycolor': ^4.1.0 | ||||
|   '@eslint/js': ^9.12.0 | ||||
|   '@eslint/js': ^9.13.0 | ||||
|   '@faker-js/faker': ^9.0.3 | ||||
|   '@iconify/json': ^2.2.261 | ||||
|   '@iconify/tailwind': ^1.1.3 | ||||
|  | @ -43,14 +43,14 @@ catalog: | |||
|   '@types/html-minifier-terser': ^7.0.2 | ||||
|   '@types/jsonwebtoken': ^9.0.7 | ||||
|   '@types/lodash.clonedeep': ^4.5.9 | ||||
|   '@types/node': ^22.7.6 | ||||
|   '@types/node': ^22.7.7 | ||||
|   '@types/nprogress': ^0.2.3 | ||||
|   '@types/postcss-import': ^14.0.3 | ||||
|   '@types/qrcode': ^1.5.5 | ||||
|   '@types/sortablejs': ^1.15.8 | ||||
|   '@typescript-eslint/eslint-plugin': ^8.10.0 | ||||
|   '@typescript-eslint/parser': ^8.10.0 | ||||
|   '@vee-validate/zod': ^4.13.2 | ||||
|   '@vee-validate/zod': ^4.14.3 | ||||
|   '@vite-pwa/vitepress': ^0.5.3 | ||||
|   '@vitejs/plugin-vue': ^5.1.4 | ||||
|   '@vitejs/plugin-vue-jsx': ^4.0.1 | ||||
|  | @ -83,8 +83,8 @@ catalog: | |||
|   dotenv: ^16.4.5 | ||||
|   echarts: ^5.5.1 | ||||
|   element-plus: ^2.8.6 | ||||
|   eslint: ^9.12.0 | ||||
|   eslint-config-turbo: ^2.1.3 | ||||
|   eslint: ^9.13.0 | ||||
|   eslint-config-turbo: ^2.2.0 | ||||
|   eslint-plugin-command: ^0.2.6 | ||||
|   eslint-plugin-eslint-comments: ^3.2.0 | ||||
|   eslint-plugin-import-x: ^4.3.1 | ||||
|  | @ -138,7 +138,7 @@ catalog: | |||
|   rimraf: ^6.0.1 | ||||
|   rollup: ^4.24.0 | ||||
|   rollup-plugin-visualizer: ^5.12.0 | ||||
|   sass: ^1.80.2 | ||||
|   sass: ^1.80.3 | ||||
|   sortablejs: ^1.15.3 | ||||
|   stylelint: ^16.10.0 | ||||
|   stylelint-config-recess-order: ^5.1.1 | ||||
|  | @ -153,11 +153,11 @@ catalog: | |||
|   tailwindcss: ^3.4.14 | ||||
|   tailwindcss-animate: ^1.0.7 | ||||
|   theme-colors: ^0.1.0 | ||||
|   turbo: ^2.1.3 | ||||
|   turbo: ^2.2.0 | ||||
|   typescript: ^5.6.3 | ||||
|   unbuild: ^2.0.0 | ||||
|   unplugin-element-plus: ^0.8.0 | ||||
|   vee-validate: ^4.13.2 | ||||
|   vee-validate: ^4.14.3 | ||||
|   vite: ^5.4.9 | ||||
|   vite-plugin-compression: ^0.5.1 | ||||
|   vite-plugin-dts: 4.2.1 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Vben
						Vben