From 3673a8c1084c8ff42eda9143f0e0ee039ab76b69 Mon Sep 17 00:00:00 2001 From: pixelmaxQM Date: Sun, 31 Aug 2025 16:55:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(i18n):=20=E6=B7=BB=E5=8A=A0=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=94=AF=E6=8C=81=E5=B9=B6=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E7=A1=AC=E7=BC=96=E7=A0=81=E9=94=99=E8=AF=AF=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将硬编码的错误消息替换为多语言翻译,支持中文、英文、俄文和阿拉伯文 新增翻译文件条目并更新相关服务逻辑以使用全局翻译功能 --- .vercel/project.json | 1 + server/resource/lang/ar.json | 314 +++++++++++++++ server/resource/lang/en.json | 27 ++ server/resource/lang/ru.json | 29 +- server/resource/lang/zh-TW.json | 27 ++ server/resource/lang/zh.json | 365 +++++++++++++++++- .../example/exa_attachment_category.go | 4 +- server/service/system/sys_dictionary.go | 8 +- server/service/system/sys_initdb.go | 11 +- server/source/system/menu.go | 11 +- server/utils/directory.go | 2 +- server/utils/jwt.go | 36 +- server/utils/upload/local.go | 2 +- server/utils/upload/minio_oss.go | 4 +- 14 files changed, 809 insertions(+), 32 deletions(-) create mode 100644 .vercel/project.json diff --git a/.vercel/project.json b/.vercel/project.json new file mode 100644 index 000000000..812014f7c --- /dev/null +++ b/.vercel/project.json @@ -0,0 +1 @@ +{"neverMindDeployCard":true} \ No newline at end of file diff --git a/server/resource/lang/ar.json b/server/resource/lang/ar.json index 52d975000..ddded355e 100644 --- a/server/resource/lang/ar.json +++ b/server/resource/lang/ar.json @@ -388,6 +388,9 @@ "packagePlugin": "تعيين حزمة المكون", "personalInfo": "معلومات شخصية", "pluginInstall": "تثبيت المكون", + "aiPageDraw": "رسم صفحة الذكاء الاصطناعي", + "mcpToolsTemplate": "قالب أدوات MCP", + "mcpToolsTest": "اختبار أدوات MCP", "pluginMarket": "سوق المكونات", "pluginSystem": "نظام المكونات", "resumableUpload": "تحميل قابل لإعادة الإضافة (إصدار مكون إضافي)", @@ -529,6 +532,317 @@ }, "router": { + }, + "database": { + "parentMenuInitFailed": "فشل في تهيئة القائمة الأساسية!", + "childMenuInitFailed": "فشل في تهيئة القائمة الفرعية!", + "userAuthorityAssocFailed": "فشل في إنشاء ارتباط [المستخدم-الصلاحية]، لم يتم العثور على بيانات تهيئة جدول الصلاحيات", + "menuAuthorityAssocFailed": "فشل في إنشاء ارتباط [القائمة-الصلاحية]، لم يتم العثور على بيانات تهيئة جدول الصلاحيات", + "menuAuthorityAssocFailedNoMenu": "فشل في إنشاء ارتباط [القائمة-الصلاحية]، لم يتم العثور على بيانات تهيئة جدول القائمة", + "superAdminMenuAssignFailed": "فشل في تعيين القوائم للمدير العام", + "normalUserMenuAssignFailed": "فشل في تعيين القوائم للمستخدم العادي", + "testRoleMenuAssignFailed": "فشل في تعيين القوائم لدور الاختبار", + "casbinInitFailed": "فشل في تهيئة بيانات جدول Casbin (%s)!", + "tableInitFailed": "فشل في تهيئة بيانات جدول %s!", + "dictionaryTableNotFound": "لم يتم العثور على بيانات تهيئة جدول %s" + }, + "menu": { + "buildMenuIdMapping": "بناء خريطة معرف القائمة للبحث السريع", + "assignDifferentPermissions": "تعيين صلاحيات مختلفة لأدوار مختلفة", + "superAdminRole": "دور المدير العام (888) - لديه جميع صلاحيات القائمة", + "normalUserRole": "دور المستخدم العادي (8881) - لديه قوائم الوظائف الأساسية فقط", + "selectParentMenus": "اختيار بعض القوائم الأساسية وقوائمها الفرعية فقط", + "addDashboardMenus": "إضافة قوائم لوحة التحكم وحولنا والمعلومات الشخصية", + "testRole": "دور الاختبار (9528) - لديه صلاحيات قائمة جزئية", + "addAllParentMenus": "إضافة جميع القوائم الأساسية", + "addPartialChildMenus": "إضافة قوائم فرعية جزئية - قوائم فرعية لأدوات النظام وملفات الأمثلة ووحدات أخرى" + }, + "system": { + "osInfo": "معلومات نظام التشغيل", + "cpuInfo": "معلومات المعالج", + "ramInfo": "معلومات الذاكرة", + "diskInfo": "معلومات القرص الصلب", + "readConfigFile": "قراءة ملف التكوين", + "setConfigFile": "تعيين ملف التكوين", + "getServerInfo": "الحصول على معلومات الخادم", + "clearDatabaseTables": "مسح بيانات جداول قاعدة البيانات", + "databaseTableData": "كائن قاعدة البيانات", + "tableName": "اسم الجدول", + "compareField": "حقل المقارنة", + "interval": "الفترة الزمنية" + }, + "user": { + "userRegistration": "تسجيل المستخدم", + "userLogin": "تسجيل دخول المستخدم", + "changeUserPassword": "تغيير كلمة مرور المستخدم", + "getPaginatedData": "الحصول على البيانات المقسمة على صفحات", + "setUserPermission": "تعيين صلاحية المستخدم", + "setUserPermissions": "تعيين صلاحيات المستخدم", + "deleteUser": "حذف المستخدم", + "setUserInfo": "تعيين معلومات المستخدم", + "setUserConfig": "تعيين تكوين المستخدم", + "getUserInfo": "الحصول على معلومات المستخدم", + "getUserInfoById": "الحصول على معلومات المستخدم بالمعرف", + "getUserInfoByUuid": "الحصول على معلومات المستخدم بـ UUID", + "resetUserPassword": "إعادة تعيين كلمة مرور المستخدم", + "adminRegister": "تسجيل حساب المدير", + "changePassword": "تغيير كلمة المرور للمستخدم", + "setUserAuthority": "تعيين صلاحية المستخدم", + "setSelfInfo": "تعيين المعلومات الذاتية", + "setUserAuthorities": "تعيين صلاحيات المستخدم", + "resetPassword": "إعادة تعيين كلمة المرور", + "setSelfSetting": "تكوين واجهة المستخدم", + "getUserList": "الحصول على قائمة المستخدمين المقسمة على صفحات", + "getSelfInfo": "الحصول على المعلومات الذاتية" + }, + "upload": { + "uploadFile": "رفع الملف", + "deleteFile": "حذف الملف", + "createFileDefer": "إنشاء ملف مع إغلاق مؤجل", + "fileNameFormat": "تنسيق اسم الملف، يمكنك تغييره بنفسك، يُنصح بضمان التفرد", + "qiniuConfig": "إرجاع تكوين Qiniu Cloud وفقاً لملف التكوين", + "qiniuZoneInit": "تهيئة غرفة الكمبيوتر المقابلة للمساحة وفقاً لملف التكوين", + "readLocalFile": "قراءة الملف المحلي", + "aliyunUploadPath": "تنسيق اسم ملف مسار رفع Aliyun، يمكنك تغييره بنفسك، يُنصح بضمان التفرد", + "uploadFileStream": "رفع تدفق الملف", + "deleteObjectName": "حذف ملف واحد. objectName يشير إلى أنه عند حذف ملفات OSS، تحتاج إلى تحديد المسار الكامل بما في ذلك امتداد الملف، مثل abc/efg/123.jpg", + "deleteFolderNote": "لحذف مجلد، يرجى تعيين objectName إلى اسم المجلد المقابل. إذا لم يكن المجلد فارغاً، تحتاج إلى حذف جميع الكائنات في المجلد قبل أن تتمكن من حذف المجلد", + "createOSSClient": "إنشاء مثيل OSSClient", + "getBucket": "الحصول على مساحة التخزين", + "readFileSuffix": "قراءة امتداد الملف", + "readFileNameEncrypt": "قراءة اسم الملف وتشفيره", + "combineNewFileName": "دمج اسم الملف الجديد", + "tryCreatePath": "محاولة إنشاء هذا المسار", + "combinePathFileName": "دمج المسار واسم الملف", + "readFile": "قراءة الملف", + "transferFile": "نقل (نسخ) الملف", + "keyCannotBeEmpty": "المفتاح لا يمكن أن يكون فارغاً", + "illegalKey": "مفتاح غير قانوني", + "fileNotExist": "الملف غير موجود", + "fileDeletionFailed": "فشل في حذف الملف", + "tryCreateBucket": "محاولة إنشاء bucket", + "readFileFailed": "فشل في قراءة الملف", + "encryptFileName": "تشفير اسم الملف للتخزين", + "setTimeout10Min": "تعيين المهلة الزمنية إلى 10 دقائق", + "uploadLargeFileNote": "رفع الملف باستخدام PutObject، الملفات الكبيرة تتحول تلقائياً إلى رفع متعدد الأجزاء", + "uploadToMinioFailed": "فشل في رفع الملف إلى minio", + "minioInitFailed": "فشل في تهيئة Minio", + "checkMinioConfig": "لقد قمت بتكوين استخدام minio، لكن التهيئة فشلت، يرجى التحقق من توفر minio أو تكوين الأمان", + "minioInitFailedSuggestion": "يُنصح بفعل هذا. إذا قام المستخدم بتكوين minio بنفسه وحدث خطأ، فمن الخطير أيضاً بدء الخدمة" + }, + "operation": { + "createRecord": "إنشاء سجل", + "batchDeleteRecords": "حذف السجلات بالدفعة", + "deleteOperationRecord": "حذف سجل العملية", + "getOperationRecordById": "الحصول على سجل عملية واحد بالمعرف", + "getPaginatedOperationRecords": "الحصول على قائمة سجلات العمليات المقسمة على صفحات", + "createDb": "إنشاء قاعدة بيانات", + "conditionalSearch": "إذا كان هناك بحث شرطي، سيتم إنشاء عبارات البحث تلقائياً أدناه" + }, + "params": { + "createSysParams": "إنشاء سجل معاملات النظام" + }, + "breakpoint": { + "frontendFileChunk": "جزء الملف المرسل من الواجهة الأمامية وأي جزء من أي ملف هو الجزء الحالي", + "backendCompareChunk": "بعد أن يحصل الخلفية عليه، قارن ما إذا كان هذا الجزء مرفوع أم أنه جزء غير مكتمل", + "frontendChunkSize": "حجم كل جزء مرسل من الواجهة الأمامية", + "frontendLastChunk": "الواجهة الأمامية تخبر ما إذا كان الجزء الأخير وما إذا كان مكتملاً", + "breakpointResume": "استئناف نقطة التوقف", + "checkMd5": "فحص Md5", + "canContinueUpload": "يمكن متابعة الرفع", + "chunkIncomplete": "الجزء غير مكتمل، تجاهل", + "createChunkContent": "إنشاء محتوى الجزء", + "fileNamePathIllegal": "اسم الملف أو المسار غير قانوني", + "createChunkFile": "إنشاء ملف الجزء", + "removeChunk": "إزالة الجزء" + }, + "validator": { + "registerCustomRules": "تسجيل مخطط القواعد المخصصة، يُنصح بالتسجيل في طبقة تهيئة المسار", + "notEmpty": "غير فارغ، لا يمكن أن يكون القيمة الصفرية لنوعه المقابل", + "regexValidation": "التحقق من التعبير النمطي، فحص ما إذا كان عنصر الإدخال يلبي التعبير النمطي", + "lessThan": "أقل من المعامل (<) إذا كان string array Slice، فهو مقارنة الطول، إذا كان int uint float، فهو مقارنة رقمية", + "lessThanEqual": "أقل من أو يساوي المعامل (<=) إذا كان string array Slice، فهو مقارنة الطول، إذا كان int uint float، فهو مقارنة رقمية", + "equal": "يساوي المعامل (==) إذا كان string array Slice، فهو مقارنة الطول، إذا كان int uint float، فهو مقارنة رقمية", + "notEqual": "لا يساوي المعامل (!=) إذا كان string array Slice، فهو مقارنة الطول، إذا كان int uint float، فهو مقارنة رقمية", + "greaterThanEqual": "أكبر من أو يساوي المعامل (>=) إذا كان string array Slice، فهو مقارنة الطول، إذا كان int uint float، فهو مقارنة رقمية", + "greaterThan": "أكبر من المعامل (>) إذا كان string array Slice، فهو مقارنة الطول، إذا كان int uint float، فهو مقارنة رقمية", + "validationMethod": "طريقة التحقق", + "lengthNumberValidation": "طريقة التحقق من الطول والرقم، التحقق التلقائي وفقاً للنوع", + "notEmptyValidation": "التحقق من عدم الفراغ", + "compareFunction": "دالة المقارنة" + }, + "jwt": { + "unknownError": "خطأ غير معروف", + "tokenExpired": "انتهت صلاحية الرمز المميز", + "tokenNotActive": "الرمز المميز ليس نشطاً بعد", + "notAToken": "هذا ليس رمزاً مميزاً", + "invalidSignature": "توقيع غير صالح", + "cannotProcessToken": "لا يمكن معالجة هذا الرمز المميز", + "bufferTime": "وقت التخزين المؤقت يوم واحد. خلال وقت التخزين المؤقت، سيتم الحصول على رمز تحديث جديد. في هذا الوقت، سيكون لدى المستخدم رمزان صالحان، لكن الواجهة الأمامية تحتفظ بواحد فقط، والآخر سيضيع", + "audience": "الجمهور", + "notBefore": "وقت فعالية التوقيع", + "expiresAt": "وقت انتهاء الصلاحية 7 أيام ملف التكوين", + "issuer": "مُصدر التوقيع", + "createToken": "إنشاء رمز مميز", + "createTokenByOldToken": "رمز قديم لرمز جديد، استخدم الدمج للعودة إلى المصدر لتجنب مشاكل التزامن", + "parseToken": "تحليل الرمز المميز", + "jwtRedisExpire": "تخزين jwt في redis وتعيين وقت انتهاء الصلاحية", + "expireTimeNote": "وقت انتهاء الصلاحية هنا يساوي وقت انتهاء صلاحية jwt" + }, + "hash": { + "bcryptHash": "استخدام bcrypt لتشفير كلمات المرور", + "bcryptCheck": "مقارنة كلمة المرور النصية مع قيمة التجزئة في قاعدة البيانات", + "md5Encrypt": "تشفير MD5" + }, + "claims": { + "addCookieToken": "إضافة cookie x-token إلى الويب المصدر", + "getUserIdFromContext": "الحصول على معرف المستخدم المحلل من jwt من Context الخاص بـ Gin", + "getUserUuidFromContext": "الحصول على UUID المستخدم المحلل من jwt من Context الخاص بـ Gin", + "getUserAuthorityIdFromContext": "الحصول على معرف دور المستخدم المحلل من jwt من Context الخاص بـ Gin", + "getUserInfoFromContext": "الحصول على معرف دور المستخدم المحلل من jwt من Context الخاص بـ Gin", + "getUserNameFromContext": "الحصول على اسم المستخدم المحلل من jwt من Context الخاص بـ Gin" + }, + "directory": { + "fileDirectoryExists": "ما إذا كان دليل الملف موجوداً", + "sameNameFileExists": "ملف بنفس الاسم موجود", + "batchCreateFolders": "إنشاء مجلدات بالدفعة", + "fileMoveExternal": "نقل الملف للاستدعاء الخارجي", + "srcDstParam": "src: الموقع المصدر، مسار مطلق أو نسبي، dst: الموقع الهدف، مسار مطلق أو نسبي، يجب أن يكون مجلداً", + "removeStructSpaces": "إزالة مسافات البنية", + "targetParam": "target: البنية الهدف، الإدخال يجب أن يكون نوع مؤشر", + "fileExist": "تحديد ما إذا كان الملف موجوداً" + }, + "format": { + "reflectStructToMap": "استخدام الانعكاس لتحويل البنية إلى خريطة", + "formatArrayToString": "تنسيق المصفوفة إلى نص", + "makeHump": "تحويل النص إلى تسمية الجمل", + "humpToUnderscore": "تحويل تسمية الجمل إلى وضع فصل الشرطة السفلية", + "addUnderscoreBeforeUppercase": "إضافة شرطة سفلية قبل الأحرف الكبيرة", + "convertToLowercase": "تحويل إلى أحرف صغيرة", + "randomString": "نص عشوائي", + "buildTree": "يُستخدم لبناء بنية شجرية", + "createBasicMap": "إنشاء خريطة أساسية" + }, + "json": { + "useJsonDecoder": "استخدام json.Decoder لتسجيل ترتيب المفاتيح أثناء التحليل", + "ensureDataIsObject": "التأكد من أن البيانات كائن", + "parseValue": "تحليل القيمة" + }, + "casbin": { + "getCasbinInstance": "الحصول على مثيل casbin", + "checkCasbinTableEngine": "فشل في تكييف قاعدة البيانات، يرجى التحقق من أن جدول casbin هو محرك InnoDB!", + "stringLoadModelFailed": "فشل في تحميل نموذج النص!" + }, + "zip": { + "decompress": "إلغاء الضغط" + }, + "request": { + "createUrl": "إنشاء URL", + "addQueryParams": "إضافة معاملات الاستعلام", + "encodeDataToJson": "ترميز البيانات إلى JSON", + "createRequest": "إنشاء طلب", + "sendRequest": "إرسال طلب", + "returnResponse": "إرجاع الاستجابة، دع المستدعي يتعامل معها" + }, + "timer": { + "findAllCron": "العثور على جميع Cron", + "addTaskMethodSecond": "إضافة طريقة المهمة بالثواني", + "addTaskFuncSecond": "إضافة دالة المهمة بالثواني", + "addTaskInterfaceSecond": "إضافة واجهة المهمة بالثواني", + "addTaskByFunc": "إضافة مهمة بطريقة الدالة", + "addTaskByInterface": "إضافة مهمة بطريقة الواجهة، تحتاج إلى تنفيذ واجهة مع طريقة Run للتشغيل", + "getCorrespondingCron": "الحصول على cron المقابل بـ taskName، قد يكون فارغاً", + "specifiedCronStart": "بدء تنفيذ cron المحدد", + "specifiedCronStop": "إيقاف تنفيذ cron المحدد", + "findSpecifiedTask": "العثور على مهمة محددة تحت cron محدد", + "deleteTaskById": "حذف مهمة محددة تحت cron محدد بالمعرف", + "deleteTaskByName": "حذف مهمة محددة تحت cron محدد بـ taskName", + "clearSpecifiedCron": "مسح cronName المحدد", + "stopAllCron": "إيقاف جميع cron", + "timerTaskManagement": "إدارة مهام المؤقت", + "addTaskByFuncMethod": "إضافة مهمة بطريقة الدالة", + "addTaskByFuncWithSecond": "إضافة مهمة بطريقة الدالة باستخدام WithSeconds", + "addTaskByJobMethod": "إضافة مهمة بطريقة الواجهة", + "addTaskByJobWithSeconds": "إضافة مهمة بطريقة الواجهة", + "findCron": "الحصول على cron المقابل بـ cronName، قد يكون فارغاً", + "findTask": "الحصول على cron المقابل بـ cronName، قد يكون فارغاً", + "findCronList": "الحصول على قائمة جميع المهام", + "startCron": "بدء المهمة", + "stopCron": "إيقاف المهمة", + "removeTask": "إزالة مهمة محددة من cronName", + "removeTaskByName": "إزالة مهمة محددة من cronName باستخدام taskName", + "clear": "مسح المهام", + "close": "تحرير الموارد", + "testMockFunc": "اختبار mockfunc", + "testJobMockFunc": "اختبار job mockfunc" + }, + "autocode": { + "getTemplateFuncMap": "إرجاع خريطة دالة القالب للاستخدام في القوالب", + "renderModelFields": "عرض الحقول في Model", + "buildGormTags": "بناء علامات gorm", + "buildFieldDefinitionByType": "بناء تعريفات حقول مختلفة وفقاً لنوع الحقل", + "addFieldDescription": "إضافة وصف الحقل", + "formatSearchCondition": "تنسيق عبارة شرط البحث", + "complexTypeBusinessLogic": "نوع البيانات هو نوع معقد، يرجى تنفيذ منطق استعلام النوع المعقد وفقاً لمتطلبات العمل", + "formatFrontendSearchCondition": "تنسيق شرط البحث للواجهة الأمامية", + "startBuildFormItem": "بدء بناء عنصر النموذج", + "generateInputTypeByField": "إنتاج أنواع إدخال مختلفة وفقاً لخصائص الحقل", + "pleaseSelect": "يرجى الاختيار", + "yes": "نعم", + "no": "لا", + "pleaseSelectField": "يرجى اختيار %s", + "minValue": "القيمة الدنيا", + "maxValue": "القيمة العليا", + "searchCondition": "شرط البحث", + "searchRangeNote": "نطاق البحث من تاريخ البداية (شامل) إلى تاريخ النهاية (غير شامل)", + "to": "إلى", + "startTime": "وقت البداية", + "endTime": "وقت النهاية", + "closeFormItem": "إغلاق عنصر النموذج", + "richTextContent": "محتوى النص الغني", + "startBuildFormItemForEdit": "بدء بناء عنصر النموذج", + "handleDifferentFieldTypes": "التعامل مع أنواع حقول مختلفة", + "pleaseEnter": "يرجى إدخال %s", + "jsonStructureNote": "هذا الحقل هو بنية json، يمكن للواجهة الأمامية التحكم في وضع العرض وربط البيانات بنفسها. مفتاح json الذي يحتاج إلى ربط هو formData.%s. الخلفية ستخزن وتسترد وفقاً لنوع json", + "selectDate": "اختيار التاريخ", + "closeFormItemForEdit": "إغلاق عنصر النموذج", + "startBuildDescriptionItem": "بدء بناء عنصر الوصف", + "closeDescriptionItem": "إغلاق عنصر الوصف", + "determineDefaultValueByFieldType": "تحديد القيمة الافتراضية وفقاً لنوع الحقل", + "checkDataSourceExists": "فحص ما إذا كان مصدر البيانات موجوداً", + "returnFormattedDefaultValue": "إرجاع نص القيمة الافتراضية المنسق", + "generateSearchFieldByAttribute": "إنتاج تعريف حقل بنية البحث وفقاً لخصائص الحقل", + "noSearchTypeReturnEmpty": "إذا لم يكن هناك نوع بحث، إرجاع نص فارغ", + "generateRangeSearchField": "إنتاج حقل البحث النطاقي", + "timeCase": "حالة الوقت", + "generateNormalSearchField": "إنتاج حقل البحث العادي" + }, + "directory": { + "fileExists": "يوجد ملف بنفس الاسم" + }, + "upload": { + "fileNotExists": "الملف غير موجود", + "readFileFailed": "فشل في قراءة الملف" + }, + "jwt": { + "unknownError": "خطأ غير معروف", + "tokenExpired": "انتهت صلاحية الرمز المميز", + "tokenNotValidYet": "الرمز المميز غير نشط بعد", + "tokenMalformed": "هذا ليس رمزاً مميزاً", + "invalidSignature": "توقيع غير صالح", + "tokenInvalid": "لا يمكن معالجة هذا الرمز المميز" + }, + "breakpoint": { + "invalidFileNameOrPath": "اسم الملف أو المسار غير صالح" + }, + "dictionary": { + "duplicateTypeNotAllowed": "يوجد نوع مكرر، الإنشاء غير مسموح", + "doNotCauseTrouble": "يرجى عدم إثارة المشاكل", + "queryDictDataFailed": "فشل في استعلام بيانات القاموس" + }, + "category": { + "nameAlreadyExists": "اسم الفئة موجود بالفعل", + "deleteChildrenFirst": "يرجى حذف العناصر الفرعية أولاً" } } diff --git a/server/resource/lang/en.json b/server/resource/lang/en.json index f5f422eb1..6b1375f7a 100644 --- a/server/resource/lang/en.json +++ b/server/resource/lang/en.json @@ -532,6 +532,33 @@ }, "router": { + }, + "directory": { + "fileExists": "File with the same name exists" + }, + "upload": { + "fileNotExists": "File does not exist", + "readFileFailed": "Failed to read file" + }, + "jwt": { + "unknownError": "Unknown error", + "tokenExpired": "Token has expired", + "tokenNotValidYet": "Token is not yet active", + "tokenMalformed": "This is not a token", + "invalidSignature": "Invalid signature", + "tokenInvalid": "Cannot process this token" + }, + "breakpoint": { + "invalidFileNameOrPath": "Invalid file name or path" + }, + "dictionary": { + "duplicateTypeNotAllowed": "Duplicate type exists, creation not allowed", + "doNotCauseTrouble": "Please do not cause trouble", + "queryDictDataFailed": "Failed to query dictionary data" + }, + "category": { + "nameAlreadyExists": "Category name already exists", + "deleteChildrenFirst": "Please delete children first" } } diff --git a/server/resource/lang/ru.json b/server/resource/lang/ru.json index 186fb145b..be94bdb43 100644 --- a/server/resource/lang/ru.json +++ b/server/resource/lang/ru.json @@ -530,5 +530,32 @@ "sysNoSupport": "Система не поддерживает", "fileNameInvalid": "Имя файла недействительно" }, - "router": {} + "router": {}, + "directory": { + "fileExists": "Файл с таким именем существует" + }, + "upload": { + "fileNotExists": "Файл не существует", + "readFileFailed": "Не удалось прочитать файл" + }, + "jwt": { + "unknownError": "Неизвестная ошибка", + "tokenExpired": "Срок действия токена истек", + "tokenNotValidYet": "Токен еще не активен", + "tokenMalformed": "Это не токен", + "invalidSignature": "Недействительная подпись", + "tokenInvalid": "Невозможно обработать этот токен" + }, + "breakpoint": { + "invalidFileNameOrPath": "Недействительное имя файла или путь" + }, + "dictionary": { + "duplicateTypeNotAllowed": "Существует дублирующийся тип, создание не разрешено", + "doNotCauseTrouble": "Пожалуйста, не создавайте проблем", + "queryDictDataFailed": "Не удалось запросить данные словаря" + }, + "category": { + "nameAlreadyExists": "Имя категории уже существует", + "deleteChildrenFirst": "Пожалуйста, сначала удалите дочерние элементы" + } } \ No newline at end of file diff --git a/server/resource/lang/zh-TW.json b/server/resource/lang/zh-TW.json index 805518652..63ea851a0 100644 --- a/server/resource/lang/zh-TW.json +++ b/server/resource/lang/zh-TW.json @@ -536,5 +536,32 @@ "lengthOrValueOutOfRange": "長度或值不在合法範圍", "sysNoSupport": "系統不支持", "fileNameInvalid": "文件名不合法" + }, + "directory": { + "fileExists": "存在相同名稱的檔案" + }, + "upload": { + "fileNotExists": "檔案不存在", + "readFileFailed": "讀取檔案失敗" + }, + "jwt": { + "unknownError": "未知錯誤", + "tokenExpired": "令牌已過期", + "tokenNotValidYet": "令牌尚未生效", + "tokenMalformed": "這不是一個令牌", + "invalidSignature": "無效簽名", + "tokenInvalid": "無法處理此令牌" + }, + "breakpoint": { + "invalidFileNameOrPath": "無效的檔案名稱或路徑" + }, + "dictionary": { + "duplicateTypeNotAllowed": "存在相同的type,不允許創建", + "doNotCauseTrouble": "請不要搗亂", + "queryDictDataFailed": "查詢字典數據失敗" + }, + "category": { + "nameAlreadyExists": "分類名稱已存在", + "deleteChildrenFirst": "請先刪除子級" } } \ No newline at end of file diff --git a/server/resource/lang/zh.json b/server/resource/lang/zh.json index b34efa87d..8b873dbe1 100644 --- a/server/resource/lang/zh.json +++ b/server/resource/lang/zh.json @@ -115,21 +115,25 @@ "description": "描述", "displayName": "展示名", "keywordNotice": "%s为go的关键字!", - + "pluginModeInterfaceV2": "插件模式接口化v2", + "startTime": "开始时间", + "autoRegisterGormMigration": "自动为 gorm.go 注册一个自动迁移", + "readLocalFile": "读取本地文件", + "readFileFailed": "读取文件失败", + "tokenExpired": "token已过期", + "defineAllMenus": "定义所有菜单", "nonStandardPlugin": "非标准插件,请按照文档自动迁移使用", "autoPathExists": "autoPath 已存在同名插件,请自行手动安装", "duplicatePlugin": "已存在同名插件,请自行手动安装", "pluginNameRequired": "插件名称不能为空", "webPathNotExist": "web路径不存在", "serverPathNotExist": "server路径不存在", - "duplicateRoleId": "存在相同角色ID", "queryRoleDataFailed": "查询角色数据失败", "roleNotExist": "该角色不存在", "roleInUse": "此角色有用户正在使用,禁止删除", "roleHasSubRoles": "此角色存在子角色,不允许删除", "invalidRoleId": "您提交的角色ID不合法", - "buttonInUse": "此按钮正在被使用无法删除", "menuHasSubMenu": "此菜单存在子菜单不可删除", "recordNotFound": "记录不存在", @@ -139,8 +143,40 @@ "stringLoadModelFailed": "字符串加载模型失败", "duplicateApi": "存在相同api,添加失败,请联系管理员", "apiNotInPermissionList": "存在api不在权限列表中", - "noAvailableInit": "无可用初始化过程,请检查初始化是否已执行完成" - }, + "noAvailableInit": "无可用初始化过程,请检查初始化是否已执行完成", + "createMenuAuthFail": "创建 [菜单-权限] 关联失败, 未找到权限表初始化数据", + "minioInitFail": "minio初始化失败", + "createMenuFail": "创建菜单失败!", + "userNickname": "系统用户", + "createUpdateFail": "创建/更新失败", + "createUpdateFailErr": "创建/更新失败:%s", + "queryDictDataFail": "查询字典数据失败", + "fileDeleteFailErr": "文件删除失败: %s", + "createUserAuthFail": "创建 [用户-权限] 关联失败, 未找到权限表初始化数据", + "createMCPClientFail": "创建MCP客户端失败:%s", + "queryPackageFail": "查询包失败!", + "createFolderFail": "[filepath:%s]创建文件夹失败!", + "writeFileFail": "写入文件失败", + "createMenuFail": "创建菜单失败", + "duplicateStructErr": "已经创建过此数据结构,请勿重复创建!", + "duplicateStructOrAbbrevErr": "已经创建过此数据结构或重复简称,请勿重复创建!", + "readTemplateFail": "读取模版文件失败!", + "generateFileFail": "生成文件失败!" + }, + "utils": { + "jwt": { + "unknownError": "未知错误", + "tokenExpired": "token已过期", + "tokenNotActivated": "token尚未激活", + "notAToken": "这不是一个token", + "invalidSignature": "无效签名", + "cannotProcessToken": "无法处理此token" + }, + "upload": { + "readFileFailed": "读取文件失败", + "uploadToMinioFailed": "上传文件到minio失败" + } + }, "sys_auto_code_history": { "rollbackSuccess": "回滚成功" }, @@ -328,7 +364,13 @@ "getParametersList": "获取参数列表", "categoryList": "分类列表", "addEditCategory": "添加/编辑分类", - "deleteCategory": "删除分类" + "deleteCategory": "删除分类", + "newSysDictionaryDetail": "新建SysDictionaryDetail", + "getSysDictionaryDetailList": "获取SysDictionaryDetail列表", + "updateSysDictionaryDetail": "更新SysDictionaryDetail", + "deleteSysDictionaryDetail": "删除SysDictionaryDetail", + "batchDeleteSysDictionaryDetail": "批量删除SysDictionaryDetail", + "getSysDictionaryDetailById": "根据ID获取SysDictionaryDetail" }, "group": { "announcement": "公告", @@ -380,6 +422,9 @@ "about": "关于我们", "adminTools": "超级管理员", "announcementManage": "公告管理[示例]", + "aiPageDraw": "AI页面绘制", + "mcpToolsTemplate": "Mcp Tools模板", + "mcpToolsTest": "Mcp Tools测试", "apiManage": "api管理", "autoCode": "代码生成器", "autoCodeEdit": "自动化代码(复用)", @@ -546,6 +591,314 @@ }, "router": { + }, + "database": { + "parentMenuInitFailed": "父级菜单初始化失败!", + "childMenuInitFailed": "子菜单初始化失败!", + "userAuthorityAssocFailed": "创建 [用户-权限] 关联失败, 未找到权限表初始化数据", + "menuAuthorityAssocFailed": "创建 [菜单-权限] 关联失败, 未找到权限表初始化数据", + "menuAuthorityAssocFailedNoMenu": "创建 [菜单-权限] 关联失败, 未找到菜单表初始化数据", + "superAdminMenuAssignFailed": "为超级管理员分配菜单失败", + "normalUserMenuAssignFailed": "为普通用户分配菜单失败", + "testRoleMenuAssignFailed": "为测试角色分配菜单失败", + "casbinInitFailed": "Casbin 表 (%s) 数据初始化失败!", + "tableInitFailed": "%s表数据初始化失败!", + "dictionaryTableNotFound": "未找到 %s 表初始化数据", + "initDataSuccess": "初始数据成功!", + "initDataExists": "的初始数据已存在!", + "initDataFailed": "初始数据失败!" + }, + "menu": { + "buildMenuIdMapping": "构建菜单ID映射,方便快速查找", + "assignDifferentPermissions": "为不同角色分配不同权限", + "superAdminRole": "超级管理员角色(888) - 拥有所有菜单权限", + "normalUserRole": "普通用户角色(8881) - 仅拥有基础功能菜单", + "selectParentMenus": "仅选择部分父级菜单及其子菜单", + "addDashboardMenus": "添加仪表盘、关于我们和个人信息菜单", + "testRole": "测试角色(9528) - 拥有部分菜单权限", + "addAllParentMenus": "添加所有父级菜单", + "addPartialChildMenus": "添加部分子菜单 - 系统工具、示例文件等模块的子菜单" + }, + "system": { + "osInfo": "OS信息", + "cpuInfo": "CPU信息", + "ramInfo": "RAM信息", + "diskInfo": "硬盘信息", + "readConfigFile": "读取配置文件", + "setConfigFile": "设置配置文件", + "getServerInfo": "获取服务器信息", + "clearDatabaseTables": "清理数据库表数据", + "databaseTableData": "数据库对象", + "tableName": "表名", + "compareField": "比较字段", + "interval": "间隔" + }, + "user": { + "userRegistration": "用户注册", + "userLogin": "用户登录", + "changeUserPassword": "修改用户密码", + "getPaginatedData": "分页获取数据", + "setUserPermission": "设置一个用户的权限", + "setUserPermissions": "设置一个用户的权限", + "deleteUser": "删除用户", + "setUserInfo": "设置用户信息", + "setUserConfig": "设置用户配置", + "getUserInfo": "获取用户信息", + "getUserInfoById": "通过id获取用户信息", + "getUserInfoByUuid": "通过uuid获取用户信息", + "resetUserPassword": "修改用户密码", + "adminRegister": "管理员注册账号", + "changePassword": "用户修改密码", + "setUserAuthority": "设置用户权限", + "setUserInfo": "设置用户信息", + "setSelfInfo": "设置自身信息", + "setUserAuthorities": "设置用户权限组", + "resetPassword": "设置用户权限组", + "setSelfSetting": "用户界面配置", + "getUserList": "分页获取用户列表", + "getUserInfo": "获取自身信息" + }, + "upload": { + "uploadFile": "上传文件", + "deleteFile": "删除文件", + "createFileDefer": "创建文件 defer 关闭", + "fileNameFormat": "文件名格式 自己可以改 建议保证唯一性", + "qiniuConfig": "根据配置文件进行返回七牛云的配置", + "qiniuZoneInit": "根据配置文件进行初始化空间对应的机房", + "readLocalFile": "读取本地文件", + "aliyunUploadPath": "上传阿里云路径 文件名格式 自己可以改 建议保证唯一性", + "uploadFileStream": "上传文件流", + "deleteObjectName": "删除单个文件。objectName表示删除OSS文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg", + "deleteFolderNote": "如需删除文件夹,请将objectName设置为对应的文件夹名称。如果文件夹非空,则需要将文件夹下的所有object删除后才能删除该文件夹", + "createOSSClient": "创建OSSClient实例", + "getBucket": "获取存储空间", + "readFileSuffix": "读取文件后缀", + "readFileNameEncrypt": "读取文件名并加密", + "combineNewFileName": "拼接新文件名", + "tryCreatePath": "尝试创建此路径", + "combinePathFileName": "拼接路径和文件名", + "readFile": "读取文件", + "transferFile": "传输(拷贝)文件", + "keyCannotBeEmpty": "key不能为空", + "illegalKey": "非法的key", + "fileNotExist": "文件不存在", + "fileDeletionFailed": "文件删除失败", + "tryCreateBucket": "尝试创建bucket", + "readFileFailed": "读取文件失败", + "encryptFileName": "对文件名进行加密存储", + "setTimeout10Min": "设置超时10分钟", + "uploadLargeFileNote": "Upload the file with PutObject 大文件自动切换为分片上传", + "uploadToMinioFailed": "上传文件到minio失败", + "minioInitFailed": "minio初始化失败", + "checkMinioConfig": "你配置了使用minio,但是初始化失败,请检查minio可用性或安全配置", + "minioInitFailedSuggestion": "建议这样做,用户自己配置了minio,如果报错了还要把服务开起来,使用起来也很危险", + "uploadFail": "上传失败", + "uploadSuccess": "上传成功", + "fileNotExists": "文件不存在" + }, + "operation": { + "createRecord": "创建记录", + "batchDeleteRecords": "批量删除记录", + "deleteOperationRecord": "删除操作记录", + "getOperationRecordById": "根据id获取单条操作记录", + "getPaginatedOperationRecords": "分页获取操作记录列表", + "createDb": "创建db", + "conditionalSearch": "如果有条件搜索 下方会自动创建搜索语句" + }, + "params": { + "createSysParams": "创建参数记录" + }, + "breakpoint": { + "frontendFileChunk": "前端传来文件片与当前片为什么文件的第几片", + "backendCompareChunk": "后端拿到以后比较次分片是否上传 或者是否为不完全片", + "frontendChunkSize": "前端发送每片多大", + "frontendLastChunk": "前端告知是否为最后一片且是否完成", + "breakpointResume": "断点续传", + "checkMd5": "检查Md5", + "canContinueUpload": "可以继续上传", + "chunkIncomplete": "切片不完整,废弃", + "createChunkContent": "创建切片内容", + "fileNamePathIllegal": "文件名或路径不合法", + "createChunkFile": "创建切片文件", + "removeChunk": "移除切片", +"breakpoint": { + "continueFail": "断点续传失败", + "continueSuccess": "断点续传成功", + "invalidFileNameOrPath": "文件名或路径不合法" + }, + "dictionary": { + "duplicateTypeNotAllowed": "存在相同的type,不允许创建", + "doNotCauseTrouble": "请不要搞事", + "queryDictDataFailed": "查询字典数据失败" + }, + "category": { + "nameAlreadyExists": "分类名称已存在", + "deleteChildrenFirst": "请先删除子级" + }, + "validator": { + "registerCustomRules": "注册自定义规则方案建议在路由初始化层即注册", + "notEmpty": "非空 不能为其对应类型的0值", + "regexValidation": "正则校验 校验输入项是否满足正则表达式", + "lessThan": "小于入参(<) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较", + "lessThanEqual": "小于等于入参(<=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较", + "equal": "等于入参(==) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较", + "notEqual": "不等于入参(!=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较", + "greaterThanEqual": "大于等于入参(>=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较", + "greaterThan": "大于入参(>) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较", + "validationMethod": "校验方法", + "lengthNumberValidation": "长度和数字的校验方法 根据类型自动校验", + "notEmptyValidation": "非空校验", + "compareFunction": "比较函数" + }, + "jwt": { + "unknownError": "未知错误", + "tokenExpired": "token已过期", + "tokenNotActive": "token尚未激活", + "notAToken": "这不是一个token", + "invalidSignature": "无效签名", + "cannotProcessToken": "无法处理此token", + "bufferTime": "缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失", + "audience": "受众", + "notBefore": "签名生效时间", + "expiresAt": "过期时间 7天 配置文件", + "issuer": "签名的发行者", + "createToken": "创建一个token", + "createTokenByOldToken": "旧token 换新token 使用归并回源避免并发问题", + "parseToken": "解析 token", + "jwtRedisExpire": "jwt存入redis并设置过期时间", + "expireTimeNote": "此处过期时间等于jwt过期时间" + }, + "hash": { + "bcryptHash": "使用 bcrypt 对密码进行加密", + "bcryptCheck": "对比明文密码和数据库的哈希值", + "md5Encrypt": "md5加密" + }, + "claims": { + "addCookieToken": "增加cookie x-token 向来源的web添加", + "getUserIdFromContext": "从Gin的Context中获取从jwt解析出来的用户ID", + "getUserUuidFromContext": "从Gin的Context中获取从jwt解析出来的用户UUID", + "getUserAuthorityIdFromContext": "从Gin的Context中获取从jwt解析出来的用户角色id", + "getUserInfoFromContext": "从Gin的Context中获取从jwt解析出来的用户角色id", + "getUserNameFromContext": "从Gin的Context中获取从jwt解析出来的用户名" + }, + "directory": { + "fileDirectoryExists": "文件目录是否存在", + "sameNameFileExists": "存在同名文件", + "batchCreateFolders": "批量创建文件夹", + "fileMoveExternal": "文件移动供外部调用", + "srcDstParam": "src: 源位置,绝对路径or相对路径, dst: 目标位置,绝对路径or相对路径,必须为文件夹", + "removeStructSpaces": "去除结构体空格", + "targetParam": "target: 目标结构体,传入必须是指针类型", + "fileExist": "判断文件是否存在", + "createFail": "创建目录失败", + "createSuccess": "创建目录成功", + "fileExists": "存在同名文件" + }, + "format": { + "reflectStructToMap": "利用反射将结构体转化为map", + "formatArrayToString": "将数组格式化为字符串", + "makeHump": "将字符串转换为驼峰命名", + "humpToUnderscore": "将驼峰命名转换为下划线分割模式", + "addUnderscoreBeforeUppercase": "在大写字母前添加下划线", + "convertToLowercase": "转小写", + "randomString": "随机字符串", + "buildTree": "用于构建一个树形结构", + "createBasicMap": "创建一个基本map" + }, + "json": { + "useJsonDecoder": "使用json.Decoder,以便在解析过程中记录键的顺序", + "ensureDataIsObject": "确保数据是一个对象", + "parseValue": "解析值" + }, + "casbin": { + "getCasbinInstance": "获取casbin实例", + "checkCasbinTableEngine": "适配数据库失败请检查casbin表是否为InnoDB引擎!", + "stringLoadModelFailed": "字符串加载模型失败!" + }, + "zip": { + "decompress": "解压" + }, + "request": { + "createUrl": "创建URL", + "addQueryParams": "添加查询参数", + "encodeDataToJson": "将数据编码为JSON", + "createRequest": "创建请求", + "sendRequest": "发送请求", + "returnResponse": "返回响应,让调用者处理" + }, + "timer": { + "findAllCron": "寻找所有Cron", + "addTaskMethodSecond": "添加Task 方法形式以秒的形式加入", + "addTaskFuncSecond": "添加Task Func以秒的形式加入", + "addTaskInterfaceSecond": "添加Task 接口形式以秒的形式加入", + "addTaskByFunc": "通过函数的方法添加任务", + "addTaskByInterface": "通过接口的方法添加任务 要实现一个带有 Run方法的接口触发", + "getCorrespondingCron": "获取对应taskName的cron 可能会为空", + "specifiedCronStart": "指定cron开始执行", + "specifiedCronStop": "指定cron停止执行", + "findSpecifiedTask": "查找指定cron下的指定task", + "deleteTaskById": "根据id删除指定cron下的指定task", + "deleteTaskByName": "根据taskName删除指定cron下的指定task", + "clearSpecifiedCron": "清理掉指定cronName", + "stopAllCron": "停止所有的cron", + "timerTaskManagement": "timer 定时任务管理", + "addTaskByFuncMethod": "通过函数的方法添加任务", + "addTaskByFuncWithSecond": "通过函数的方法使用WithSeconds添加任务", + "addTaskByJobMethod": "通过接口的方法添加任务", + "addTaskByJobWithSeconds": "通过接口的方法添加任务", + "findCron": "获取对应cronName的cron 可能会为空", + "findTask": "获取对应cronName的cron 可能会为空", + "findCronList": "获取所有的任务列表", + "startCron": "开始任务", + "stopCron": "停止任务", + "removeTask": "从cronName 删除指定任务", + "removeTaskByName": "从cronName 使用taskName 删除指定任务", + "clear": "清除任务", + "close": "释放资源", + "testMockFunc": "测试mockfunc", + "testJobMockFunc": "测试job mockfunc" + }, + "autocode": { + "getTemplateFuncMap": "返回模板函数映射,用于在模板中使用", + "renderModelFields": "渲染Model中的字段", + "buildGormTags": "构建gorm标签", + "buildFieldDefinitionByType": "根据字段类型构建不同的字段定义", + "addFieldDescription": "添加字段描述", + "formatSearchCondition": "格式化搜索条件语句", + "complexTypeBusinessLogic": "数据类型为复杂类型,请根据业务需求自行实现复杂类型的查询业务", + "formatFrontendSearchCondition": "格式化前端搜索条件", + "startBuildFormItem": "开始构建表单项", + "generateInputTypeByField": "根据字段属性生成不同的输入类型", + "pleaseSelect": "请选择", + "yes": "是", + "no": "否", + "pleaseSelectField": "请选择%s", + "minValue": "最小值", + "maxValue": "最大值", + "searchCondition": "搜索条件", + "searchRangeNote": "搜索范围是开始日期(包含)至结束日期(不包含)", + "to": "至", + "startTime": "开始时间", + "endTime": "结束时间", + "closeFormItem": "关闭表单项", + "richTextContent": "富文本内容", + "startBuildFormItemForEdit": "开始构建表单项", + "handleDifferentFieldTypes": "处理不同字段类型", + "pleaseEnter": "请输入%s", + "jsonStructureNote": "此字段为json结构,可以前端自行控制展示和数据绑定模式 需绑定json的key为 formData.%s 后端会按照json的类型进行存取", + "selectDate": "选择日期", + "closeFormItemForEdit": "关闭表单项", + "startBuildDescriptionItem": "开始构建描述项", + "closeDescriptionItem": "关闭描述项", + "determineDefaultValueByFieldType": "根据字段类型确定默认值", + "checkDataSourceExists": "检查数据源是否存在", + "returnFormattedDefaultValue": "返回格式化后的默认值字符串", + "generateSearchFieldByAttribute": "根据字段属性生成搜索结构体中的字段定义", + "noSearchTypeReturnEmpty": "如果没有搜索类型,返回空字符串", + "generateRangeSearchField": "生成范围搜索字段", + "timeCase": "time 的情况", + "generateNormalSearchField": "生成普通搜索字段" + } } } diff --git a/server/service/example/exa_attachment_category.go b/server/service/example/exa_attachment_category.go index 1e74fc942..7eb36a489 100644 --- a/server/service/example/exa_attachment_category.go +++ b/server/service/example/exa_attachment_category.go @@ -13,7 +13,7 @@ type AttachmentCategoryService struct{} func (a *AttachmentCategoryService) AddCategory(req *example.ExaAttachmentCategory) (err error) { // 检查是否已存在相同名称的分类 if (!errors.Is(global.GVA_DB.Take(&example.ExaAttachmentCategory{}, "name = ? and pid = ?", req.Name, req.Pid).Error, gorm.ErrRecordNotFound)) { - return errors.New("分类名称已存在") + return errors.New(global.Translate("category.nameAlreadyExists")) } if req.ID > 0 { if err = global.GVA_DB.Model(&example.ExaAttachmentCategory{}).Where("id = ?", req.ID).Updates(&example.ExaAttachmentCategory{ @@ -38,7 +38,7 @@ func (a *AttachmentCategoryService) DeleteCategory(id *int) error { var childCount int64 global.GVA_DB.Model(&example.ExaAttachmentCategory{}).Where("pid = ?", id).Count(&childCount) if childCount > 0 { - return errors.New("请先删除子级") + return errors.New(global.Translate("category.deleteChildrenFirst")) } return global.GVA_DB.Where("id = ?", id).Unscoped().Delete(&example.ExaAttachmentCategory{}).Error } diff --git a/server/service/system/sys_dictionary.go b/server/service/system/sys_dictionary.go index d4c0b780c..8f7f9dd24 100644 --- a/server/service/system/sys_dictionary.go +++ b/server/service/system/sys_dictionary.go @@ -20,7 +20,7 @@ var DictionaryServiceApp = new(DictionaryService) func (dictionaryService *DictionaryService) CreateSysDictionary(sysDictionary system.SysDictionary) (err error) { if (!errors.Is(global.GVA_DB.First(&system.SysDictionary{}, "type = ?", sysDictionary.Type).Error, gorm.ErrRecordNotFound)) { - return errors.New("存在相同的type,不允许创建") + return errors.New(global.Translate("dictionary.duplicateTypeNotAllowed")) } err = global.GVA_DB.Create(&sysDictionary).Error return err @@ -35,7 +35,7 @@ func (dictionaryService *DictionaryService) CreateSysDictionary(sysDictionary sy func (dictionaryService *DictionaryService) DeleteSysDictionary(sysDictionary system.SysDictionary) (err error) { err = global.GVA_DB.Where("id = ?", sysDictionary.ID).Preload("SysDictionaryDetails").First(&sysDictionary).Error if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { - return errors.New("请不要搞事") + return errors.New(global.Translate("dictionary.doNotCauseTrouble")) } if err != nil { return err @@ -68,11 +68,11 @@ func (dictionaryService *DictionaryService) UpdateSysDictionary(sysDictionary *s err = global.GVA_DB.Where("id = ?", sysDictionary.ID).First(&dict).Error if err != nil { global.GVA_LOG.Debug(err.Error()) - return errors.New("查询字典数据失败") + return errors.New(global.Translate("dictionary.queryDictDataFailed")) } if dict.Type != sysDictionary.Type { if !errors.Is(global.GVA_DB.First(&system.SysDictionary{}, "type = ?", sysDictionary.Type).Error, gorm.ErrRecordNotFound) { - return errors.New("存在相同的type,不允许创建") + return errors.New(global.Translate("dictionary.duplicateTypeNotAllowed")) } } err = global.GVA_DB.Model(&dict).Updates(sysDictionaryMap).Error diff --git a/server/service/system/sys_initdb.go b/server/service/system/sys_initdb.go index c1504287d..9f5ee99ba 100644 --- a/server/service/system/sys_initdb.go +++ b/server/service/system/sys_initdb.go @@ -16,10 +16,13 @@ const ( Pgsql = "pgsql" Sqlite = "sqlite" Mssql = "mssql" - InitSuccess = "\n[%v] --> 初始数据成功!\n" - InitDataExist = "\n[%v] --> %v 的初始数据已存在!\n" - InitDataFailed = "\n[%v] --> %v 初始数据失败! \nerr: %+v\n" - InitDataSuccess = "\n[%v] --> %v 初始数据成功!\n" +) + +var ( + InitSuccess = "\n[%v] --> " + global.Translate("database.initDataSuccess") + "\n" + InitDataExist = "\n[%v] --> %v " + global.Translate("database.initDataExists") + "\n" + InitDataFailed = "\n[%v] --> %v " + global.Translate("database.initDataFailed") + " \nerr: %+v\n" + InitDataSuccess = "\n[%v] --> %v " + global.Translate("database.initDataSuccess") + "\n" ) const ( diff --git a/server/source/system/menu.go b/server/source/system/menu.go index e8f024ed1..5b1b213c5 100644 --- a/server/source/system/menu.go +++ b/server/source/system/menu.go @@ -4,6 +4,7 @@ import ( "context" . "github.com/flipped-aurora/gin-vue-admin/server/model/system" + "github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/service/system" "github.com/pkg/errors" "gorm.io/gorm" @@ -66,7 +67,7 @@ func (i *initMenu) InitializeData(ctx context.Context) (next context.Context, er // 先创建父级菜单(ParentId = 0 的菜单) if err = db.Create(&allMenus).Error; err != nil { - return ctx, errors.Wrap(err, SysBaseMenu{}.TableName()+"父级菜单初始化失败!") + return ctx, errors.Wrap(err, SysBaseMenu{}.TableName()+global.Translate("database.parentMenuInitFailed")) } // 建立菜单映射 - 通过Name查找已创建的菜单及其ID @@ -99,9 +100,9 @@ func (i *initMenu) InitializeData(ctx context.Context) (next context.Context, er {MenuLevel: 1, Hidden: true, ParentId: menuNameMap["systemTools"], Path: "autoCodeEdit/:id", Name: "autoCodeEdit", Component: "view/systemTools/autoCode/index.vue", Sort: 0, Meta: Meta{Title: "system.menu.autoCodeEdit" + " - ${id}", Icon: "magic-stick"}}, {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["systemTools"], Path: "autoPkg", Name: "autoPkg", Component: "view/systemTools/autoPkg/autoPkg.vue", Sort: 0, Meta: Meta{Title: "system.menu.templateConfig", Icon: "folder"}}, {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["systemTools"], Path: "exportTemplate", Name: "exportTemplate", Component: "view/systemTools/exportTemplate/exportTemplate.vue", Sort: 5, Meta: Meta{Title: "system.menu.tableTemplate", Icon: "reading"}}, - {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["systemTools"], Path: "picture", Name: "picture", Component: "view/systemTools/autoCode/picture.vue", Sort: 6, Meta: Meta{Title: "AI页面绘制", Icon: "picture-filled"}}, - {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["systemTools"], Path: "mcpTool", Name: "mcpTool", Component: "view/systemTools/autoCode/mcp.vue", Sort: 7, Meta: Meta{Title: "Mcp Tools模板", Icon: "magnet"}}, - {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["systemTools"], Path: "mcpTest", Name: "mcpTest", Component: "view/systemTools/autoCode/mcpTest.vue", Sort: 7, Meta: Meta{Title: "Mcp Tools测试", Icon: "partly-cloudy"}}, + {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["systemTools"], Path: "picture", Name: "picture", Component: "view/systemTools/autoCode/picture.vue", Sort: 6, Meta: Meta{Title: "system.menu.aiPageDraw", Icon: "picture-filled"}}, + {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["systemTools"], Path: "mcpTool", Name: "mcpTool", Component: "view/systemTools/autoCode/mcp.vue", Sort: 7, Meta: Meta{Title: "system.menu.mcpToolsTemplate", Icon: "magnet"}}, + {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["systemTools"], Path: "mcpTest", Name: "mcpTest", Component: "view/systemTools/autoCode/mcpTest.vue", Sort: 7, Meta: Meta{Title: "system.menu.mcpToolsTest", Icon: "partly-cloudy"}}, {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["plugin"], Path: "https://plugin.gin-vue-admin.com/", Name: "https://plugin.gin-vue-admin.com/", Component: "https://plugin.gin-vue-admin.com/", Sort: 0, Meta: Meta{Title: "system.menu.pluginMarket", Icon: "shop"}}, {MenuLevel: 1, Hidden: false, ParentId: menuNameMap["plugin"], Path: "installPlugin", Name: "installPlugin", Component: "view/systemTools/installPlugin/index.vue", Sort: 1, Meta: Meta{Title: "system.menu.pluginInstall", Icon: "box"}}, @@ -112,7 +113,7 @@ func (i *initMenu) InitializeData(ctx context.Context) (next context.Context, er // 创建子菜单 if err = db.Create(&childMenus).Error; err != nil { - return ctx, errors.Wrap(err, SysBaseMenu{}.TableName()+"子菜单初始化失败!") + return ctx, errors.Wrap(err, SysBaseMenu{}.TableName()+global.Translate("database.childMenuInitFailed")) } // 组合所有菜单作为返回结果 diff --git a/server/utils/directory.go b/server/utils/directory.go index d419feefd..ab58cc8b4 100644 --- a/server/utils/directory.go +++ b/server/utils/directory.go @@ -23,7 +23,7 @@ func PathExists(path string) (bool, error) { if fi.IsDir() { return true, nil } - return false, errors.New("存在同名文件") + return false, errors.New(global.Translate("directory.fileExists")) } if os.IsNotExist(err) { return false, nil diff --git a/server/utils/jwt.go b/server/utils/jwt.go index b4e6b3b2b..7ba4838b1 100644 --- a/server/utils/jwt.go +++ b/server/utils/jwt.go @@ -14,13 +14,37 @@ type JWT struct { SigningKey []byte } +func GetTokenValid() error { + return errors.New(global.Translate("jwt.unknownError")) +} + +func GetTokenExpired() error { + return errors.New(global.Translate("jwt.tokenExpired")) +} + +func GetTokenNotValidYet() error { + return errors.New(global.Translate("jwt.tokenNotValidYet")) +} + +func GetTokenMalformed() error { + return errors.New(global.Translate("jwt.tokenMalformed")) +} + +func GetTokenSignatureInvalid() error { + return errors.New(global.Translate("jwt.invalidSignature")) +} + +func GetTokenInvalid() error { + return errors.New(global.Translate("jwt.tokenInvalid")) +} + var ( - TokenValid = errors.New("未知错误") - TokenExpired = errors.New("token已过期") - TokenNotValidYet = errors.New("token尚未激活") - TokenMalformed = errors.New("这不是一个token") - TokenSignatureInvalid = errors.New("无效签名") - TokenInvalid = errors.New("无法处理此token") + TokenValid = GetTokenValid() + TokenExpired = GetTokenExpired() + TokenNotValidYet = GetTokenNotValidYet() + TokenMalformed = GetTokenMalformed() + TokenSignatureInvalid = GetTokenSignatureInvalid() + TokenInvalid = GetTokenInvalid() ) func NewJWT() *JWT { diff --git a/server/utils/upload/local.go b/server/utils/upload/local.go index bb0784995..981926c66 100644 --- a/server/utils/upload/local.go +++ b/server/utils/upload/local.go @@ -93,7 +93,7 @@ func (*Local) DeleteFile(key string) error { // 检查文件是否存在 if _, err := os.Stat(p); os.IsNotExist(err) { - return errors.New("文件不存在") + return errors.New(global.Translate("upload.fileNotExists")) } // 使用文件锁防止并发删除 diff --git a/server/utils/upload/minio_oss.go b/server/utils/upload/minio_oss.go index 7ad5008ce..dff094f3a 100644 --- a/server/utils/upload/minio_oss.go +++ b/server/utils/upload/minio_oss.go @@ -62,8 +62,8 @@ func (m *Minio) UploadFile(file *multipart.FileHeader) (filePathres, key string, filecontent := bytes.Buffer{} _, err := io.Copy(&filecontent, f) if err != nil { - global.GVA_LOG.Error("读取文件失败", zap.Any("err", err.Error())) - return "", "", errors.New("读取文件失败, err:" + err.Error()) + global.GVA_LOG.Error(global.Translate("upload.readFileFailed"), zap.Any("err", err.Error())) + return "", "", errors.New(global.Translate("upload.readFileFailed") + ", err:" + err.Error()) } f.Close() // 创建文件 defer 关闭