This commit is contained in:
dap
2024-10-19 21:29:20 +08:00
105 changed files with 1512 additions and 1559 deletions

View File

@@ -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,
"vitest.disableWorkspaceWarning": true,

View File

@@ -21,7 +21,7 @@ export default defineEventHandler(async (event) => {
if (!findUser) {
clearRefreshTokenCookie(event);
return forbiddenResponse(event);
return forbiddenResponse(event, 'Username or password is incorrect.');
}
const accessToken = generateAccessToken(findUser);

View File

@@ -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],

View File

@@ -39,9 +39,12 @@ export function useResponseError(message: string, error: any = null) {
};
}
export function forbiddenResponse(event: H3Event<EventHandlerRequest>) {
export function forbiddenResponse(
event: H3Event<EventHandlerRequest>,
message = 'Forbidden Exception',
) {
setResponseStatus(event, 403);
return useResponseError('Forbidden Exception', 'Forbidden Exception');
return useResponseError(message, message);
}
export function unAuthorizedResponse(event: H3Event<EventHandlerRequest>) {

View File

@@ -44,7 +44,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);
};
};

View File

@@ -28,7 +28,7 @@ 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;
},
@@ -38,7 +38,7 @@ setupVbenForm<ComponentType>({
[false, null, undefined].includes(value) ||
(isArray(value) && value.length === 0)
) {
return $t('formRules.selectRequired', [ctx.label]);
return $t('ui.formRules.selectRequired', [ctx.label]);
}
return true;
},

View File

@@ -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,
);
/**
* 加载应用特有的语言包
* 这里也可以改造为从服务端获取翻译数据

View File

@@ -1,141 +0,0 @@
{
"page": {
"demos": {
"title": "Demos",
"antd": "Ant Design Vue"
}
},
"component": {
"cropper": {
"selectImage": "Select Image",
"uploadSuccess": "Uploaded success!",
"imageTooBig": "Image too big",
"modalTitle": "Avatar upload",
"okText": "Confirm and upload",
"btn_reset": "Reset",
"btn_rotate_left": "Counterclockwise rotation",
"btn_rotate_right": "Clockwise rotation",
"btn_scale_x": "Flip horizontal",
"btn_scale_y": "Flip vertical",
"btn_zoom_in": "Zoom in",
"btn_zoom_out": "Zoom out",
"preview": "Preview"
},
"tenantToggle": {
"placeholder": "Please select a tenant",
"switch": "Switch to tenant: ",
"reset": "Reset to default tenant"
},
"notice": {
"title": "Notice",
"received": "You have received a new message"
},
"upload": {
"save": "Save",
"upload": "Upload",
"imgUpload": "ImageUpload",
"uploaded": "Uploaded",
"operating": "Operating",
"del": "Delete",
"download": "download",
"saveWarn": "Please wait for the file to upload and save!",
"saveError": "There is no file successfully uploaded and cannot be saved!",
"preview": "Preview",
"choose": "Select the file",
"accept": "Support {0} format",
"acceptUpload": "Only upload files in {0} format",
"maxSize": "A single file does not exceed {0}MB ",
"maxSizeMultiple": "Only upload files up to {0}MB!",
"maxNumber": "Only upload up to {0} files",
"legend": "Legend",
"fileName": "File name",
"fileSize": "File size",
"fileStatue": "File status",
"pending": "Pending",
"startUpload": "Start upload",
"uploadSuccess": "Upload successfully",
"uploadError": "Upload failed",
"uploading": "Uploading",
"uploadWait": "Please wait for the file upload to finish",
"reUploadFailed": "Re-upload failed files"
}
},
"pages": {
"common": {
"add": "Add",
"edit": "Edit",
"delete": "Delete",
"more": "More",
"search": "Search",
"reset": "Reset",
"import": "Import",
"export": "Export",
"expand": "Expand",
"collapse": "Collapse",
"info": "Info",
"clear": "Clear",
"unlock": "Unlock",
"download": "Download",
"sync": "Sync",
"refresh": "Refresh",
"generate": "Generate",
"downloadLoading": "Downloading... Please wait.",
"preview": "Preview"
}
},
"menu": {
"root": "Root",
"system": {
"root": "System",
"user": "User",
"role": "Role",
"menu": "Menu",
"dept": "Department",
"post": "Post",
"dict": "Dictionary",
"config": "Parameter Settings",
"notice": "Notifications",
"log": {
"root": "Log",
"operation": "Operation Log",
"login": "Login Log"
},
"oss": "File",
"client": "Client"
},
"tenant": {
"root": "Tenant",
"package": "Package"
},
"monitor": {
"root": "System Monitoring",
"online": "Online Users",
"cache": "Cache Monitoring",
"admin": "Admin Monitoring",
"job": "Task Scheduling Center"
},
"tool": {
"root": "System Tools",
"gen": "Code Generation"
},
"workflow": {
"root": "Workflow",
"category": "Process Category",
"model": "Model",
"define": "Process Definition",
"monitor": {
"root": "Process Monitoring",
"instance": "Process Instance",
"todo": "Pending Tasks"
},
"form": "Form"
},
"task": {
"root": "My Tasks",
"apply": "My Initiated Tasks",
"todo": "My Pending Tasks",
"done": "My Completed Tasks",
"cc": "My CC"
}
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -1,141 +0,0 @@
{
"page": {
"demos": {
"title": "演示",
"antd": "Ant Design Vue"
}
},
"component": {
"cropper": {
"selectImage": "选择图片",
"uploadSuccess": "上传成功",
"imageTooBig": "图片超限",
"modalTitle": "头像上传",
"okText": "确认并上传",
"btn_reset": "重置",
"btn_rotate_left": "逆时针旋转",
"btn_rotate_right": "顺时针旋转",
"btn_scale_x": "水平翻转",
"btn_scale_y": "垂直翻转",
"btn_zoom_in": "放大",
"btn_zoom_out": "缩小",
"preview": "预览"
},
"tenantToggle": {
"placeholder": "选择租户",
"switch": "切换当前租户为: ",
"reset": "还原为默认租户"
},
"notice": {
"title": "消息",
"received": "收到新消息"
},
"upload": {
"save": "保存",
"upload": "上传",
"imgUpload": "图片上传",
"uploaded": "已上传",
"operating": "操作",
"del": "删除",
"download": "下载",
"saveWarn": "请等待文件上传后,保存!",
"saveError": "没有上传成功的文件,无法保存!",
"preview": "预览",
"choose": "选择文件",
"accept": "支持{0}格式",
"acceptUpload": "只能上传{0}格式文件",
"maxSize": "单个文件不超过{0}MB",
"maxSizeMultiple": "只能上传不超过{0}MB的文件!",
"maxNumber": "最多只能上传{0}个文件",
"legend": "略缩图",
"fileName": "文件名",
"fileSize": "文件大小",
"fileStatue": "状态",
"pending": "待上传",
"startUpload": "开始上传",
"uploadSuccess": "上传成功",
"uploadError": "上传失败",
"uploading": "上传中",
"uploadWait": "请等待文件上传结束后操作",
"reUploadFailed": "重新上传失败文件"
}
},
"pages": {
"common": {
"add": "新增",
"edit": "编辑",
"delete": "删除",
"more": "更多",
"search": "搜索",
"reset": "重置",
"import": "导入",
"export": "导出",
"expand": "展开",
"collapse": "收起",
"info": "详情",
"clear": "清空",
"unlock": "解锁",
"download": "下载",
"sync": "同步",
"refresh": "刷新",
"generate": "生成",
"downloadLoading": "下载中, 请稍后...",
"preview": "预览"
}
},
"menu": {
"root": "根目录",
"system": {
"root": "系统管理",
"user": "用户管理",
"role": "角色管理",
"menu": "菜单管理",
"dept": "部门管理",
"post": "岗位管理",
"dict": "字典管理",
"config": "参数设置",
"notice": "通知公告",
"log": {
"root": "日志管理",
"operation": "操作日志",
"login": "登录日志"
},
"oss": "文件管理",
"client": "客户端管理"
},
"tenant": {
"root": "租户管理",
"package": "套餐管理"
},
"monitor": {
"root": "系统监控",
"online": "在线用户",
"cache": "缓存监控",
"admin": "Admin监控",
"job": "任务调度中心"
},
"tool": {
"root": "系统工具",
"gen": "代码生成"
},
"workflow": {
"root": "工作流",
"category": "流程分类",
"model": "模型管理",
"define": "流程定义",
"monitor": {
"root": "流程监控",
"instance": "流程实例",
"todo": "待办任务"
},
"form": "表单管理"
},
"task": {
"root": "我的任务",
"apply": "我发起的",
"todo": "我的待办",
"done": "我的已办",
"cc": "我的抄送"
}
}
}

View File

@@ -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 版本"
}
}

View File

@@ -0,0 +1,14 @@
{
"auth": {
"login": "登陆",
"register": "注册",
"codeLogin": "验证码登陆",
"qrcodeLogin": "二维码登陆",
"forgetPassword": "忘记密码"
},
"dashboard": {
"title": "概览",
"analytics": "分析页",
"workspace": "工作台"
}
}

View File

@@ -51,7 +51,7 @@ const coreRoutes: RouteRecordRaw[] = [
path: 'login',
component: Login,
meta: {
title: $t('page.core.login'),
title: $t('page.auth.login'),
},
},
{
@@ -59,7 +59,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'),
},
},
{
@@ -68,7 +68,7 @@ const coreRoutes: RouteRecordRaw[] = [
component: () =>
import('#/views/_core/authentication/qrcode-login.vue'),
meta: {
title: $t('page.core.qrcodeLogin'),
title: $t('page.auth.qrcodeLogin'),
},
},
{
@@ -77,7 +77,7 @@ const coreRoutes: RouteRecordRaw[] = [
component: () =>
import('#/views/_core/authentication/forget-password.vue'),
meta: {
title: $t('page.core.forgetPassword'),
title: $t('page.auth.forgetPassword'),
},
},
{
@@ -85,7 +85,7 @@ const coreRoutes: RouteRecordRaw[] = [
path: 'register',
component: () => import('#/views/_core/authentication/register.vue'),
meta: {
title: $t('page.core.register'),
title: $t('page.auth.register'),
},
},
],

View File

@@ -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',

View File

@@ -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'),
},
},
],

View File

@@ -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);
};
};

View File

@@ -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;
},

View File

@@ -78,8 +78,7 @@ function createRequestClient(baseURL: string) {
if (status >= 200 && status < 400 && code === 0) {
return data;
}
const error = { response };
throw error;
throw Object.assign({}, response, { response });
},
});

View File

@@ -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'),
},
]);

View File

@@ -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,
);
/**
* 加载应用特有的语言包
* 这里也可以改造为从服务端获取翻译数据

View File

@@ -1,8 +0,0 @@
{
"page": {
"demos": {
"title": "Demos",
"element-plus": "Element Plus"
}
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -1,8 +0,0 @@
{
"page": {
"demos": {
"title": "演示",
"element-plus": "Element Plus"
}
}
}

View File

@@ -0,0 +1,12 @@
{
"title": "演示",
"elementPlus": "Element Plus",
"vben": {
"title": "项目",
"about": "关于",
"document": "文档",
"antdv": "Ant Design Vue 版本",
"naive-ui": "Naive UI 版本",
"element-plus": "Element Plus 版本"
}
}

View File

@@ -0,0 +1,14 @@
{
"auth": {
"login": "登陆",
"register": "注册",
"codeLogin": "验证码登陆",
"qrcodeLogin": "二维码登陆",
"forgetPassword": "忘记密码"
},
"dashboard": {
"title": "概览",
"analytics": "分析页",
"workspace": "工作台"
}
}

View File

@@ -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'),
},
},
],

View File

@@ -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',

View File

@@ -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'),
},
},
],

View File

@@ -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);
};
};

View File

@@ -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;
},

View File

@@ -77,8 +77,7 @@ function createRequestClient(baseURL: string) {
if (status >= 200 && status < 400 && code === 0) {
return data;
}
const error = { response };
throw error;
throw Object.assign({}, response, { response });
},
});

View File

@@ -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'),
},
]);

View File

@@ -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,
);
/**
* 加载应用特有的语言包

View File

@@ -1,9 +0,0 @@
{
"page": {
"demos": {
"title": "Demos",
"naive": "Naive UI",
"table": "Table"
}
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -1,9 +0,0 @@
{
"page": {
"demos": {
"title": "演示",
"naive": "Naive UI",
"table": "Table"
}
}
}

View File

@@ -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 版本"
}
}

View File

@@ -0,0 +1,14 @@
{
"auth": {
"login": "登陆",
"register": "注册",
"codeLogin": "验证码登陆",
"qrcodeLogin": "二维码登陆",
"forgetPassword": "忘记密码"
},
"dashboard": {
"title": "概览",
"analytics": "分析页",
"workspace": "工作台"
}
}

View File

@@ -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'),
},
},
],

View File

@@ -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',

View File

@@ -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'),
},
},
],

View File

@@ -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);
};
};

View File

@@ -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;
},

View File

@@ -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`事件除外,内外都会触发。
:::

View File

@@ -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);
};
};

View File

@@ -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`事件除外,内外都会触发。
:::
@@ -104,6 +104,7 @@ const [Modal, modalApi] = useVbenModal({
| contentClass | modal内容区域的class | `string` | - |
| footerClass | modal底部区域的class | `string` | - |
| headerClass | modal顶部区域的class | `string` | - |
| bordered | 是否显示border | `boolean` | `false` |
### Event

View File

@@ -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'),
},
},
],

View File

@@ -238,8 +238,7 @@ function createRequestClient(baseURL: string) {
if (status >= 200 && status < 400 && code === 0) {
return data;
}
const error = { response };
throw error;
throw Object.assign({}, response, { response });
},
});

View File

@@ -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

View File

@@ -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'),
},
},
],
@@ -386,6 +386,10 @@ interface RouteMeta {
* 用于路由->菜单排序
*/
order?: number;
/**
* 菜单所携带的参数
*/
query?: Recordable;
/**
* 标题名称
*/
@@ -542,6 +546,15 @@ interface RouteMeta {
用于配置页面的排序,用于路由到菜单排序。
_注意:_ 排序仅针对一级菜单有效,二级菜单的排序需要在对应的一级菜单中按代码顺序设置。
### query
- 类型:`Recordable`
- 默认值:`{}`
用于配置页面的菜单参数,会在菜单中传递给页面。
## 路由刷新
路由刷新方式如下:

View File

@@ -241,8 +241,7 @@ function createRequestClient(baseURL: string) {
if (status >= 200 && status < 400 && code === 0) {
return data;
}
const error = { response };
throw error;
throw Object.assign({}, response, { response });
},
});

View File

@@ -58,7 +58,7 @@ updateLocale('en-US');
新增翻译文本,只需要在对应的应用内,找到 `src/locales/langs/`,新增对应的文本即可,例:
**src/locales/langs/zh-CN.ts**
**src/locales/langs/zh-CN/\*.json**
````ts
```json

View File

@@ -1,5 +1,5 @@
{
"name": "vben-admin-pro",
"name": "vben-admin-monorepo",
"version": "5.4.1",
"private": true,
"keywords": [

View File

@@ -103,9 +103,9 @@ interface RouteMeta {
*/
order?: number;
/**
* 路由参数 对象形式
* 菜单所携带的参数
*/
query?: Record<string, any>;
query?: Recordable;
/**
* 标题名称
*/

View File

@@ -29,6 +29,7 @@ export class ModalApi {
} = options;
const defaultState: ModalState = {
bordered: false,
centered: false,
class: '',
closeOnClickModal: true,

View File

@@ -3,15 +3,22 @@ import type { ModalApi } from './modal-api';
import type { Component, Ref } from 'vue';
export interface ModalProps {
/**
* 是否显示边框
* @default false
*/
bordered?: boolean;
/**
* 取消按钮文字
*/
cancelText?: string;
/**
* 是否居中
* @default false
*/
centered?: boolean;
class?: string;
/**
* 是否显示右上角的关闭按钮

View File

@@ -52,6 +52,7 @@ const { isMobile } = useIsMobile();
const state = props.modalApi?.useStore?.();
const {
bordered,
cancelText,
centered,
class: modalClass,
@@ -170,9 +171,11 @@ function handleFocusOutside(e: Event) {
ref="contentRef"
:class="
cn(
'border-border left-0 right-0 top-[10vh] mx-auto flex max-h-[80%] w-[520px] flex-col border p-0',
'left-0 right-0 top-[10vh] mx-auto flex max-h-[80%] w-[520px] flex-col p-0 sm:rounded-2xl',
modalClass,
{
'border-border border': bordered,
'shadow-3xl': !bordered,
'left-0 top-0 size-full max-h-full !translate-x-0 !translate-y-0':
shouldFullscreen,
'top-1/2 !-translate-y-1/2': centered && !shouldFullscreen,
@@ -195,8 +198,9 @@ function handleFocusOutside(e: Event) {
ref="headerRef"
:class="
cn(
'border-b px-5 py-4',
'px-5 py-4',
{
'border-b': bordered,
hidden: !header,
'cursor-move select-none': shouldDraggable,
},

View File

@@ -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:"

View File

@@ -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 '';

View File

@@ -1,22 +1,27 @@
import { useRouter } from 'vue-router';
import { isHttpUrl, isObject, openWindow } from '@vben/utils';
import { isHttpUrl, openWindow } from '@vben/utils';
function useNavigation() {
const router = useRouter();
const allRoutes = router.getRoutes();
const routes = router.getRoutes();
const routeMetaMap = new Map<string, any>();
routes.forEach((route) => {
routeMetaMap.set(route.path, route.meta);
});
const navigation = async (path: string) => {
if (isHttpUrl(path)) {
openWindow(path, { target: '_blank' });
} else {
// 带路由参数
const found = allRoutes.find((item) => item.path === path);
if (found && isObject(found.meta.query)) {
await router.push({ path, query: found.meta.query });
return;
}
await router.push(path);
const meta = routeMetaMap.get(path);
const query = meta?.query ?? {};
await router.push({
path,
query,
});
}
};

View File

@@ -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>

View File

@@ -95,14 +95,18 @@ onMounted(() => {
<template>
<div>
<Modal :fullscreen-button="false" class="w-[600px]" header-class="py-2">
<Modal
:fullscreen-button="false"
class="w-[600px]"
header-class="py-2 border-b"
>
<template #title>
<div class="flex items-center">
<Search class="text-muted-foreground mr-2 size-4" />
<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 +117,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 +141,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"

View File

@@ -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')"

View File

@@ -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>

View File

@@ -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"

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);

View File

@@ -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,
};

View File

@@ -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,

View File

@@ -1,348 +0,0 @@
{
"page": {
"core": {
"login": "Login",
"register": "Register",
"codeLogin": "Code Login",
"qrcodeLogin": "Qr Code Login",
"forgetPassword": "Forget Password",
"oauthLogin": "Oauth Login"
},
"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.",
"apiRequestFailed": "The interface request failed, please try again later!",
"operationSuccess": "Operation Success",
"operationFailed": "Operation failed",
"errorTip": "Error Tip",
"successTip": "Success Tip"
}
},
"formRules": {
"required": "Please enter {0}",
"selectRequired": "Please select {0}"
},
"placeholder": {
"input": "Please enter",
"select": "Please select"
},
"widgets": {
"document": "Document",
"profile": "Profile",
"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",
"captcha": "Captcha",
"usernameTip": "Please enter username",
"passwordErrorTip": "Password is incorrect",
"passwordTip": "Please enter password",
"captchaTip": "Please enter captcha",
"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"
}
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}
}

View File

@@ -1,348 +0,0 @@
{
"page": {
"core": {
"login": "登录",
"register": "注册",
"codeLogin": "验证码登录",
"qrcodeLogin": "二维码登录",
"forgetPassword": "忘记密码",
"oauthLogin": "第三方登录"
},
"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": "内部服务器错误,请稍后再试。",
"apiRequestFailed": "请求出错,请稍候重试",
"operationSuccess": "操作成功",
"operationFailed": "操作失败",
"errorTip": "错误提示",
"successTip": "成功提示"
}
},
"formRules": {
"required": "请输入{0}",
"selectRequired": "请选择{0}"
},
"placeholder": {
"input": "请输入",
"select": "请选择"
},
"widgets": {
"document": "文档",
"profile": "个人中心",
"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": "密码",
"captcha": "验证码",
"usernameTip": "请输入账号",
"passwordTip": "请输入密码",
"captchaTip": "请输入验证码",
"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": "请依次点击"
}
}
}

View File

@@ -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": "居右"
}
}

View File

@@ -0,0 +1,13 @@
{
"back": "返回",
"backToHome": "返回首页",
"login": "登录",
"logout": "退出登录",
"prompt": "提示",
"cancel": "取消",
"confirm": "确认",
"noData": "暂无数据",
"refresh": "刷新",
"loadingMenu": "加载菜单中",
"query": "查询"
}

View File

@@ -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": "启用刷新"
}
}

View File

@@ -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": "进入系统"
}
}
}

View File

@@ -336,7 +336,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
* @zh_CN 重置标签页标题
*/
async resetTabTitle(tab: TabDefinition) {
if (!tab?.meta?.newTabTitle) {
if (tab?.meta?.newTabTitle) {
return;
}
const findTab = this.tabs.find(

View File

@@ -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);
};
};

View File

@@ -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;
},

View File

@@ -79,8 +79,7 @@ function createRequestClient(baseURL: string) {
if (status >= 200 && status < 400 && code === 0) {
return data;
}
const error = { response };
throw error;
throw Object.assign({}, response, { response });
},
});

View File

@@ -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'),
},
]);

View File

@@ -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,
);
/**
* 加载应用特有的语言包
* 这里也可以改造为从服务端获取翻译数据

View File

@@ -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:"
}
}
}
}

View File

@@ -0,0 +1,68 @@
{
"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": "FullScreen",
"clipboard": "Clipboard",
"menuWithQuery": "Menu With Query"
},
"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"
}
}

View File

@@ -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:"
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}
}
}

View File

@@ -0,0 +1,68 @@
{
"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": "全屏",
"clipboard": "剪贴板",
"menuWithQuery": "带参菜单"
},
"breadcrumb": {
"navigation": "面包屑导航",
"lateral": "平级模式",
"level": "层级模式",
"levelDetail": "层级模式详情",
"lateralDetail": "平级模式详情"
},
"vben": {
"title": "项目",
"about": "关于",
"document": "文档",
"antdv": "Ant Design Vue 版本",
"naive-ui": "Naive UI 版本",
"element-plus": "Element Plus 版本"
}
}

View File

@@ -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"
}
}

View File

@@ -0,0 +1,14 @@
{
"auth": {
"login": "登陆",
"register": "注册",
"codeLogin": "验证码登陆",
"qrcodeLogin": "二维码登陆",
"forgetPassword": "忘记密码"
},
"dashboard": {
"title": "概览",
"analytics": "分析页",
"workspace": "工作台"
}
}

View File

@@ -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'),
},
},
],

View File

@@ -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.title'),
},
},
{
@@ -184,7 +184,20 @@ 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'),
},
},
{
name: 'MenuQueryDemo',
path: '/demos/menu-query',
component: () =>
import('#/views/demos/features/menu-query/index.vue'),
meta: {
icon: 'lucide:curly-braces',
query: {
id: 1,
},
title: $t('demos.features.menuWithQuery'),
},
},
{
@@ -205,7 +218,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 +227,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 +238,7 @@ const routes: RouteRecordRaw[] = [
meta: {
activePath: '/demos/breadcrumb/lateral',
hideInMenu: true,
title: $t('page.demos.breadcrumb.lateralDetail'),
title: $t('demos.breadcrumb.lateralDetail'),
},
},
{
@@ -233,7 +246,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 +255,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 +266,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 +305,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 +316,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 +328,7 @@ const routes: RouteRecordRaw[] = [
meta: {
badgeType: 'dot',
icon: 'lucide:square-dot',
title: $t('page.demos.badge.dot'),
title: $t('demos.badge.dot'),
},
},
{
@@ -325,7 +338,7 @@ const routes: RouteRecordRaw[] = [
meta: {
badge: '10',
icon: 'lucide:square-dot',
title: $t('page.demos.badge.text'),
title: $t('demos.badge.text'),
},
},
{
@@ -336,7 +349,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 +359,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 +371,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 +380,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 +390,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 +422,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 +453,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 +465,7 @@ const routes: RouteRecordRaw[] = [
meta: {
icon: 'ic:round-menu',
keepAlive: true,
title: $t('page.demos.nested.menu1'),
title: $t('demos.nested.menu1'),
},
},
{
@@ -461,7 +474,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 +484,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 +494,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 +504,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 +512,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 +523,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'),
},
},
],

Some files were not shown because too many files have changed in this diff Show More