= []
+
+export const localeConfigKey = 'MaxKB-locale'
+
+// 获取浏览器默认语言环境
+const languages = usePreferredLanguages()
+
+export function getBrowserLang() {
+ const browserLang = navigator.language ? navigator.language : languages.value[0]
+ let defaultBrowserLang = ''
+ if (browserLang === 'zh-HK' || browserLang === 'zh-TW') {
+ defaultBrowserLang = 'zh-Hant'
+ } else if (browserLang === 'zh-CN') {
+ defaultBrowserLang = 'zh-CN'
+ } else {
+ defaultBrowserLang = 'en-US'
+ }
+ return defaultBrowserLang
+}
+
+// 生成语言模块列表
+const generateLangModuleMap = () => {
+ const fullPaths = Object.keys(langModules)
+ fullPaths.forEach((fullPath) => {
+ const k = fullPath.replace('./lang', '')
+ const startIndex = 1
+ const lastIndex = k.lastIndexOf('/')
+ const code = k.substring(startIndex, lastIndex)
+ langCode.push(code)
+ langModuleMap.set(code, langModules[fullPath])
+ })
+}
+
+// 导出 Message
+const importMessages = computed(() => {
+ generateLangModuleMap()
+
+ const message: Recordable = {}
+ langModuleMap.forEach((value: any, key) => {
+ message[key] = value.default
+ })
+ return message
+})
+
+export const i18n = createI18n({
+ legacy: false,
+ locale: useLocalStorage(localeConfigKey, getBrowserLang()).value || getBrowserLang(),
+ fallbackLocale: getBrowserLang(),
+ messages: importMessages.value,
+ globalInjection: true
+})
+
+export const langList = computed(() => {
+ if (langModuleMap.size === 0) generateLangModuleMap()
+
+ const list: any = []
+ langModuleMap.forEach((value: any, key) => {
+ list.push({
+ label: value.default.lang,
+ value: key
+ })
+ })
+
+ return list
+})
+
+// @ts-ignore
+export const { t } = i18n.global
+
+export default i18n
diff --git a/ui/src/locales/lang/en-US/ai-chat.ts b/ui/src/locales/lang/en-US/ai-chat.ts
new file mode 100644
index 000000000..01c5c3c67
--- /dev/null
+++ b/ui/src/locales/lang/en-US/ai-chat.ts
@@ -0,0 +1,96 @@
+export default {
+ noHistory: 'No Chat History',
+ createChat: 'New Chat',
+ history: 'Chat History',
+ only20history: 'Showing only the last 20 chats',
+ question_count: 'Questions',
+ exportRecords: 'Export Chat History',
+ chatId: 'Chat ID',
+ userInput: 'User Input',
+ quote: 'Quote',
+ download: 'Click to Download',
+ passwordValidator: {
+ title: 'Enter Password to Access',
+ errorMessage1: 'Password cannot be empty',
+ errorMessage2: 'Incorrect password'
+ },
+ operation: {
+ play: 'Play',
+ pause: 'Pause',
+ regeneration: 'Regenerate Response',
+ like: 'Like',
+ cancelLike: 'Unlike',
+ oppose: 'Dislike',
+ cancelOppose: 'Undo Dislike',
+ continue: 'Continue',
+ stopChat: 'Stop Response',
+ startChat: 'Start Response',
+ },
+ tip: {
+ error500Message: 'Sorry, the service is currently under maintenance. Please try again later!',
+ errorIdentifyMessage: 'Unable to verify user identity',
+ errorLimitMessage: 'Sorry, you have reached the maximum number of questions. Please try again tomorrow!',
+ answerMessage: 'Sorry, no relevant content found. Please rephrase your question or provide more details.',
+ stopAnswer: 'Response Stopped',
+ answerLoading: 'Generating Response...',
+ recorderTip: `This feature requires microphone access. Browsers block recording on insecure pages. Solutions:
+1. Enable HTTPS;
+2. If HTTPS is not available, adjust browser security settings. For Chrome:
+(1) Enter chrome://flags/#unsafely-treat-insecure-origin-as-secure in the address bar;
+(2) Add your HTTP site, e.g., http://127.0.0.1:8080.
`,
+ recorderError: 'Recording Failed',
+ confirm: 'Got it',
+ requiredMessage: 'Please fill in all required fields',
+ inputParamMessage1: 'Please specify a parameter in the URL',
+ inputParamMessage2: 'value',
+ prologueMessage: 'Sorry, the service is currently under maintenance. Please try again later!'
+ },
+ inputPlaceholder: {
+ speaking: 'Speaking...',
+ recorderLoading: 'Transcribing...',
+ default: 'Type your question'
+ },
+ uploadFile: {
+ label: 'Upload File',
+ most: 'Maximum',
+ limit: 'files allowed, each up to',
+ fileType: 'File Type',
+ tipMessage: 'Please select allowed file types in the upload settings',
+ limitMessage1: 'You can upload up to',
+ limitMessage2: 'files',
+ sizeLimit: 'Each file must not exceed',
+ imageMessage: 'Please process the image content',
+ errorMessage: 'Upload Failed'
+ },
+ executionDetails: {
+ title: 'Execution Details',
+ paramOutputTooltip: 'Each document supports previewing up to 500 characters',
+ audioFile: 'Audio File',
+ searchContent: 'Search Query',
+ searchResult: 'Search Results',
+ conditionResult: 'Condition Evaluation',
+ currentChat: 'Current Chat',
+ answer: 'AI Response',
+ replyContent: 'Reply Content',
+ textContent: 'Text Content',
+ input: 'Input',
+ output: 'Output',
+ rerankerContent: 'Re-ranked Content',
+ rerankerResult: 'Re-ranking Results',
+ paragraph: 'Segment',
+ noSubmit: 'No submission from user',
+ errMessage: 'Error Log'
+ },
+ KnowledgeSource: {
+ title: 'Knowledge Source',
+ referenceParagraph: 'Cited Segment',
+ consume: 'Tokens',
+ consumeTime: 'Runtime'
+ },
+ paragraphSource: {
+ title: 'Knowledge Quote',
+ question: 'User Question',
+ optimizationQuestion: 'Optimized Question'
+ },
+ editTitle: 'Edit Title',
+}
diff --git a/ui/src/locales/lang/en-US/common.ts b/ui/src/locales/lang/en-US/common.ts
new file mode 100644
index 000000000..b00021ee0
--- /dev/null
+++ b/ui/src/locales/lang/en-US/common.ts
@@ -0,0 +1,64 @@
+export default {
+ create: 'Create',
+ createSuccess: 'Successful',
+ copy: 'Copy',
+ copySuccess: 'Successful',
+ copyError: 'Copy Failed',
+ save: 'Save',
+ saveSuccess: 'Successful',
+ delete: 'Delete',
+ deleteSuccess: 'Successful',
+ setting: 'Settings',
+ settingSuccess: 'Successful',
+ submit: 'Submit',
+ submitSuccess: 'Successful',
+ edit: 'Edit',
+ editSuccess: 'Successful',
+ modify: 'Modify',
+ modifySuccess: 'Successful',
+ cancel: 'Cancel',
+ confirm: 'OK',
+ tip: 'Tips',
+ add: 'Add',
+ refresh: 'Refresh',
+ search: 'Search',
+ clear: 'Clear',
+ professional: 'Purchase the Professional Edition',
+ createDate: 'Create Date',
+ createTime: 'Create Time',
+ operation: 'Action',
+ character: 'characters',
+ export: 'Export',
+ exportSuccess: 'Successful',
+ unavailable: '(Unavailable)',
+ public: 'Public',
+ private: 'Private',
+ paramSetting: 'Parameter Settings',
+ creator: 'Creator',
+ author: 'Author',
+ debug: 'Debug',
+ required: 'Required',
+ noData: 'No data',
+ result: 'Result',
+ fileUpload: {
+ document: 'Documents',
+ image: 'Image',
+ audio: 'Audio',
+ video: 'Video'
+ },
+ status: {
+ label: 'Status',
+ enableSuccess: 'Successful',
+ disableSuccess: 'Successful'
+ },
+ param: {
+ outputParam: 'Output Parameters',
+ inputParam: 'Input Parameters',
+ initParam: 'Startup Parameters',
+ },
+
+ inputPlaceholder: 'Please input',
+ title: 'Title',
+ content: 'Content',
+ rename: 'Rename'
+}
diff --git a/ui/src/locales/lang/en-US/components.ts b/ui/src/locales/lang/en-US/components.ts
new file mode 100644
index 000000000..7f794e1a1
--- /dev/null
+++ b/ui/src/locales/lang/en-US/components.ts
@@ -0,0 +1,12 @@
+export default {
+ quickCreatePlaceholder: 'Quickly create blank document',
+ quickCreateName: 'document name',
+ noData: 'No Data',
+ loading: 'Loading',
+ noMore: 'No more! ',
+ selectParagraph: {
+ title: 'Select Segments',
+ error: 'Process only the failed segments',
+ all: 'All Segments'
+ }
+}
diff --git a/ui/src/locales/lang/en-US/dynamics-form.ts b/ui/src/locales/lang/en-US/dynamics-form.ts
new file mode 100644
index 000000000..2cfcd8058
--- /dev/null
+++ b/ui/src/locales/lang/en-US/dynamics-form.ts
@@ -0,0 +1,102 @@
+export default {
+ input_type_list: {
+ TextInput: 'Input',
+ PasswordInput: 'Password',
+ Slider: 'Slider',
+ SwitchInput: 'Switch',
+ SingleSelect: 'Single Select',
+ MultiSelect: 'Multi Select',
+ DatePicker: 'Date Picker',
+ JsonInput: 'JSON',
+ RadioCard: 'Radio Card',
+ RadioRow: 'Radio Row'
+ },
+ default: {
+ label: 'Default',
+ placeholder: 'Please enter a default',
+ requiredMessage: ' is a required property',
+ show: 'Show Default'
+ },
+ tip: {
+ requiredMessage: 'cannot be empty',
+ jsonMessage: 'Incorrect JSON format'
+ },
+ searchBar: {
+ placeholder: 'Please enter keywords to search'
+ },
+ paramForm: {
+ field: {
+ label: 'Parameter',
+ placeholder: 'Please enter a parameter',
+ requiredMessage: 'Parameter is a required property',
+ requiredMessage2: 'Only letters, numbers, and underscores are allowed'
+ },
+ name: {
+ label: 'Name',
+ placeholder: 'Please enter a name',
+ requiredMessage: 'Name is a required property'
+ },
+ tooltip: {
+ label: 'Tooltip',
+ placeholder: 'Please enter a tooltip'
+ },
+ required: {
+ label: 'Required',
+ requiredMessage: 'Required is a required property'
+ },
+ input_type: {
+ label: 'Type',
+ placeholder: 'Please select a type',
+ requiredMessage: 'Type is a required property'
+ }
+ },
+ DatePicker: {
+ placeholder: 'Select Date',
+ year: 'Year',
+ month: 'Month',
+ date: 'Date',
+ datetime: 'Date Time',
+ dataType: {
+ label: 'Date Type',
+ placeholder: 'Please select a date type'
+ },
+ format: {
+ label: 'Format',
+ placeholder: 'Please select a format'
+ }
+ },
+ Select: {
+ label: 'Option Value',
+ placeholder: 'Please enter an option value'
+ },
+ tag: {
+ label: 'Tag',
+ placeholder: 'Please enter an option label'
+ },
+ Slider: {
+ showInput: {
+ label: 'Show Input Box'
+ },
+ valueRange: {
+ label: 'Value Range',
+ minRequired: 'Minimum value is required',
+ maxRequired: 'Maximum value is required'
+ },
+ step: {
+ label: 'Step Value',
+ requiredMessage1: 'Step value is required',
+ requiredMessage2: 'Step value cannot be 0'
+ }
+ },
+ TextInput: {
+ length: {
+ label: 'Text Length',
+ minRequired: 'Minimum length is required',
+ maxRequired: 'Maximum length is required',
+ requiredMessage1: 'Length must be between',
+ requiredMessage2: 'and',
+ requiredMessage3: 'characters',
+ requiredMessage4: 'Text length is a required parameter'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/en-US/index.ts b/ui/src/locales/lang/en-US/index.ts
new file mode 100644
index 000000000..bf56593e2
--- /dev/null
+++ b/ui/src/locales/lang/en-US/index.ts
@@ -0,0 +1,17 @@
+import en from 'element-plus/es/locale/lang/en'
+import components from './components'
+import layout from './layout'
+import views from './views'
+import common from './common'
+import dynamicsForm from './dynamics-form'
+import chat from './ai-chat'
+export default {
+ lang: 'English',
+ layout,
+ views,
+ components,
+ en,
+ common,
+ dynamicsForm,
+ chat
+}
diff --git a/ui/src/locales/lang/en-US/layout.ts b/ui/src/locales/lang/en-US/layout.ts
new file mode 100644
index 000000000..8ceecd753
--- /dev/null
+++ b/ui/src/locales/lang/en-US/layout.ts
@@ -0,0 +1,34 @@
+export default {
+ github: 'Project Address',
+ wiki: 'User Manual',
+ forum: 'Forum For Help',
+ logout: 'Log Out',
+ apiKey: 'API Key',
+ apiServiceAddress: 'API Service Address',
+ language: 'Language',
+ isExpire: 'License not uploaded or expired',
+ about: {
+ title: 'About',
+ expiredTime: 'Expiration Date',
+ edition: {
+ label: 'Edition',
+ community: 'Community Edition',
+ professional: 'Professional Edition'
+ },
+ version: 'Version',
+ serialNo: 'Serial No.',
+ remark: 'Remarks',
+ update: 'Update',
+ authorize: 'Authorized',
+
+ },
+ time: {
+ daysLater: 'days later',
+ hoursLater: 'hours later',
+ expired: 'expired',
+ expiringSoon: 'expiring soon'
+ },
+ copyright: 'Copyright © 2014-2025 FIT2CLOUD, All rights reserved.',
+ userManualUrl: 'http://docs.maxkb.hk/',
+ forumUrl: 'https://github.com/1Panel-dev/MaxKB/discussions'
+}
diff --git a/ui/src/locales/lang/en-US/views/404.ts b/ui/src/locales/lang/en-US/views/404.ts
new file mode 100644
index 000000000..0d4861a4a
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/404.ts
@@ -0,0 +1,5 @@
+export default {
+ title: "404",
+ message: "Unable to Access APP",
+ operate: "Back to Home",
+};
diff --git a/ui/src/locales/lang/en-US/views/application-overview.ts b/ui/src/locales/lang/en-US/views/application-overview.ts
new file mode 100644
index 000000000..7580cdd53
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/application-overview.ts
@@ -0,0 +1,114 @@
+export default {
+ title: 'Overview',
+ appInfo: {
+ header: 'App Information',
+ publicAccessLink: 'Public URL',
+ openText: 'On',
+ closeText: 'Off',
+ copyLinkText: 'Copy Link',
+ refreshLinkText: 'Refresh Link',
+ demo: 'Preview',
+ embedInWebsite: 'Get Embed Code',
+ accessControl: 'Access Control',
+ displaySetting: 'Display Settings',
+ apiAccessCredentials: 'API Access Credentials',
+ apiKey: 'API Key',
+ refreshToken: {
+ msgConfirm1: 'Are you sure you want to regenerate the public URL?',
+ msgConfirm2:
+ 'Regenerating the Public URL will affect any existing embedded codes on third-party sites. You will need to update the embed code and re-integrate it into those sites. Proceed with caution!',
+ refreshSuccess: 'Successfully Refreshed'
+ },
+ APIKeyDialog: {
+ saveSettings: 'Save Settings',
+ msgConfirm1: 'Are you sure you want to delete the API Key',
+ msgConfirm2:
+ 'This action is irreversible. Once deleted, the API Key cannot be recovered. Do you still want to proceed?',
+ enabledSuccess: 'Enabled',
+ disabledSuccess: 'Disabled'
+ },
+ EditAvatarDialog: {
+ title: 'App Logo',
+ customizeUpload: 'Custom Upload',
+ upload: 'Upload',
+ default: 'Default Logo',
+ custom: 'Custom',
+ sizeTip:
+ 'Recommended size: 32×32 pixels. Supports JPG, PNG, and GIF formats. Max size: 10 MB',
+ fileSizeExceeded: 'File size exceeds 10 MB',
+ uploadImagePrompt: 'Please upload an image'
+ },
+ EmbedDialog: {
+ fullscreenModeTitle: 'Fullscreen Mode',
+ copyInstructions: 'Copy the code below to embed',
+ floatingModeTitle: 'Floating Mode',
+ mobileModeTitle: 'Mobile Mode'
+ },
+ LimitDialog: {
+ dialogTitle: 'Access Restrictions',
+ showSourceLabel: 'Show Knowledge Source',
+ clientQueryLimitLabel: 'Query Limit per Client',
+ authentication: 'Authentication',
+ authenticationValue: 'Access Password',
+ timesDays: 'queries per day',
+ whitelistLabel: 'Allowed Domains',
+ whitelistPlaceholder:
+ 'Enter allowed third-party domains, one per line. For example:\nhttp://127.0.0.1:5678\nhttps://dataease.io'
+ },
+ SettingAPIKeyDialog: {
+ allowCrossDomainLabel: 'Allow Cross-Domain Access',
+ crossDomainPlaceholder:
+ 'Enter allowed cross-domain addresses. If enabled but left blank, no restrictions will apply.\nEnter one per line, e.g.:\nhttp://127.0.0.1:5678\nhttps://dataease.io'
+ },
+ SettingDisplayDialog: {
+ dialogTitle: 'Display Settings',
+ languageLabel: 'Language',
+ showSourceLabel: 'Show Knowledge Source',
+ showExecutionDetail: 'Show Execution Details',
+ restoreDefault: 'Restore Default',
+ customThemeColor: 'Custom Theme Color',
+ headerTitleFontColor: 'Header Title Font Color',
+ default: 'Default',
+ askUserAvatar: 'User Avatar (Asking)',
+ replace: 'Replace',
+ imageMessage:
+ 'Recommended size: 32×32 pixels. Supports JPG, PNG, and GIF formats. Max size: 10 MB',
+ AIAvatar: 'AI Avatar',
+ floatIcon: 'Floating Icon',
+ iconDefaultPosition: 'Default Icon Position',
+ iconPosition: {
+ left: 'Left',
+ right: 'Right',
+ bottom: 'Bottom',
+ top: 'Top'
+ },
+ draggablePosition: 'Draggable Position',
+ showHistory: 'Show Chat History',
+ displayGuide: 'Show Guide Image (Floating Mode)',
+ disclaimer: 'Disclaimer',
+ disclaimerValue: 'This content is AI-generated and for reference only.'
+ }
+ },
+ monitor: {
+ monitoringStatistics: 'Monitoring Statistics',
+ customRange: 'Custom Range',
+ startDatePlaceholder: 'Start Date',
+ endDatePlaceholder: 'End Date',
+ pastDayOptions: {
+ past7Days: 'Last 7 Days',
+ past30Days: 'Last 30 Days',
+ past90Days: 'Last 90 Days',
+ past183Days: 'Last 6 Months',
+ other: 'Custom'
+ },
+ charts: {
+ customerTotal: 'Total Users',
+ customerNew: 'New Users',
+ queryCount: 'Total Queries',
+ tokensTotal: 'Total Tokens Used',
+ userSatisfaction: 'User Feedback Metrics',
+ approval: 'Like',
+ disapproval: 'Dislike'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/application-workflow.ts b/ui/src/locales/lang/en-US/views/application-workflow.ts
new file mode 100644
index 000000000..6e1aa8c67
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/application-workflow.ts
@@ -0,0 +1,288 @@
+export default {
+ node: 'Node',
+ nodeName: 'Node Name',
+ baseComponent: 'Basic',
+ nodeSetting: 'Node Settings',
+ workflow: 'Workflow',
+ searchBar: {
+ placeholder: 'Search by name'
+ },
+ info: {
+ previewVersion: 'Preview Version:',
+ saveTime: 'Last Saved:'
+ },
+ setting: {
+ restoreVersion: 'Restore Previous Version"',
+ restoreCurrentVersion: 'Restore to This Version',
+ addComponent: 'Add',
+ public: 'Publish',
+ releaseHistory: 'Release History',
+ autoSave: 'Auto Save',
+ latestRelease: 'Latest Release',
+ copyParam: 'Copy Parameters',
+ debug: 'Run',
+ exit: 'Exit',
+ exitSave: 'Save & Exit',
+ },
+ tip: {
+ publicSuccess: 'Published successfully',
+ noData: 'No related results found',
+ nameMessage: 'Name cannot be empty!',
+ onlyRight: 'Connections can only be made from the right anchor',
+ notRecyclable: 'Loop connections are not allowed',
+ onlyLeft: 'Connections can only be made to the left anchor',
+ applicationNodeError: 'This application is unavailable',
+ functionNodeError: 'This function node is unavailable',
+ repeatedNodeError: 'A node with this name already exists',
+ cannotCopy: 'Cannot be copied',
+ copyError: 'Node already copied',
+ paramErrorMessage: 'Parameter already exists: ',
+ saveMessage: 'Current changes have not been saved. Save before exiting?',
+ },
+ delete: {
+ confirmTitle: 'Confirm to delete this node?',
+ deleteMessage: 'This node cannot be deleted'
+ },
+ control: {
+ zoomOut: 'Zoom Out',
+ zoomIn: 'Zoom In',
+ fitView: 'Fit to Screen',
+ retract: 'Collapse All',
+ extend: 'Expand All',
+ beautify: 'Auto-Arrange'
+ },
+ variable: {
+ label: 'Variable',
+ global: 'Global Variable',
+ Referencing: 'Referenced Variable',
+ ReferencingRequired: 'Referenced variable is required',
+ ReferencingError: 'Invalid referenced variable',
+ NoReferencing: 'Referenced variable does not exist',
+ placeholder: 'Please select a variable'
+ },
+ condition: {
+ title: 'Execution Condition',
+ front: 'Precondition',
+ AND: 'All',
+ OR: 'Any',
+ text: 'After the connected node is executed, execute the current node'
+ },
+ validate: {
+ startNodeRequired: 'Start node is required',
+ startNodeOnly: 'Only one start node is allowed',
+ baseNodeRequired: 'Base information node is required',
+ baseNodeOnly: 'Only one base information node is allowed',
+ notInWorkFlowNode: 'Node not in workflow',
+ noNextNode: 'Next node does not exist',
+ nodeUnavailable: 'Node unavailable',
+ needConnect1: 'The branch of the node needs to be connected',
+ cannotEndNode: 'This node cannot be used as an end node'
+ },
+ nodes: {
+ startNode: {
+ label: 'Start',
+ question: 'User Question',
+ currentTime: 'Current Time'
+ },
+ baseNode: {
+ label: 'Base Information',
+ appName: {
+ label: 'App Name'
+ },
+ appDescription: {
+ label: 'App Description'
+ },
+ fileUpload: {
+ label: 'File Upload',
+ tooltip: 'When enabled, the Q&A page will display a file upload button.'
+ },
+ FileUploadSetting: {
+ title: 'File Upload Settings',
+ maxFiles: 'Maximum number of files per upload',
+ fileLimit: 'Maximum size per file (MB)',
+ fileUploadType: {
+ label: 'File types allowed for upload',
+ documentText: 'Requires "Document Content Extraction" node to parse document content',
+ imageText: 'Requires "Image Understanding" node to parse image content',
+ audioText: 'Requires "Speech-to-Text" node to parse audio content'
+ }
+ }
+ },
+ aiChatNode: {
+ label: 'AI Chat',
+ text: 'Chat with an AI model',
+ answer: 'AI Content',
+ returnContent: {
+ label: 'Return Content',
+ tooltip: `If turned off, the content of this node will not be output to the user.
+ If you want the user to see the output of this node, please turn on the switch.`
+ },
+ defaultPrompt: 'Known Information',
+ think: 'Thinking Process'
+ },
+ searchDatasetNode: {
+ label: 'Knowledge Retrieval',
+ text: 'Allows you to query text content related to user questions from the Knowledge',
+ paragraph_list: 'List of retrieved segments',
+ is_hit_handling_method_list: 'List of segments that meet direct response criteria',
+ result: 'Search Result',
+ directly_return: 'Content of segments that meet direct response criteria',
+ searchParam: 'Retrieval Parameters',
+ searchQuestion: {
+ label: 'Question',
+ placeholder: 'Please select a search question',
+ requiredMessage: 'Please select a search question'
+ }
+ },
+ questionNode: {
+ label: 'Question Optimization',
+ text: 'Optimize and improve the current question based on historical chat records to better match knowledge segments',
+ result: 'Optimized Question Result',
+ defaultPrompt1: `Optimize and improve the user's question based on context:`,
+ defaultPrompt2: `Please output an optimized question.`,
+ systemDefault: 'You are a question optimization expert'
+ },
+ conditionNode: {
+ label: 'Conditional Branch',
+ text: 'Trigger different nodes based on conditions',
+ branch_name: 'Branch Name',
+ conditions: {
+ label: 'Conditions',
+ info: 'Meets the following',
+ requiredMessage: 'Please select conditions'
+ },
+ valueMessage: 'Please enter a value',
+ addCondition: 'Add Condition',
+ addBranch: 'Add Branch'
+ },
+ replyNode: {
+ label: 'Specified Reply',
+ text: 'Specify reply content, referenced variables will be converted to strings for output',
+ content: 'Content',
+ replyContent: {
+ label: 'Reply Content',
+ custom: 'Custom',
+ reference: 'Reference Variable'
+ }
+ },
+ rerankerNode: {
+ label: 'Multi-path Recall',
+ text: 'Use a re-ranking model to refine retrieval results from multiple knowledge sources',
+ result_list: 'Re-ranked Results List',
+ result: 'Re-ranking Result',
+ rerankerContent: {
+ label: 'Re-ranking Content',
+ requiredMessage: 'Please select re-ranking content'
+ },
+ higher: 'Higher',
+ ScoreTooltip: 'The higher the Score, the stronger the relevance.',
+ max_paragraph_char_number: 'Maximum Character',
+ reranker_model: {
+ label: 'Rerank',
+ placeholder: 'Please select a rerank'
+ }
+ },
+ formNode: {
+ label: 'Form Input',
+ text: 'Collect user input during Q&A and use it in subsequent processes',
+ form_content_format1: 'Hello, please fill out the form below:',
+ form_content_format2: 'Click the [Submit] button after filling it out.',
+ form_data: 'All Form Content',
+ formContent: {
+ label: 'Form Output Content',
+ requiredMessage:
+ 'Please set the output content of this node, { form } is a placeholder for the form.',
+ tooltip: 'Define the output content of this node. { form } is a placeholder for the form'
+ },
+ formAllContent: 'All Form Content',
+ formSetting: 'Form Configuration'
+ },
+ documentExtractNode: {
+ label: 'Document Content Extraction',
+ text: 'Extract content from documents',
+ content: 'Document Content'
+ },
+ imageUnderstandNode: {
+ label: 'Image Understanding',
+ text: 'Analyze images to identify objects, scenes, and provide answers',
+ answer: 'AI Content',
+ model: {
+ label: 'Vision Model',
+ requiredMessage: 'Please select a vision model'
+ },
+ image: {
+ label: 'Select Image',
+ requiredMessage: 'Please select an image'
+ }
+ },
+ variableAssignNode: {
+ label: 'Variable Assign',
+ text: 'Update the value of the global variable',
+ assign: 'Set Value'
+ },
+ imageGenerateNode: {
+ label: 'Image Generation',
+ text: 'Generate images based on provided text content',
+ answer: 'AI Content',
+ model: {
+ label: 'Image Generation Model',
+ requiredMessage: 'Please select an image generation model'
+ },
+ prompt: {
+ label: 'Positive Prompt',
+ tooltip: 'Describe elements and visual features you want in the generated image'
+ },
+ negative_prompt: {
+ label: 'Negative Prompt',
+ tooltip: 'Describe elements you want to exclude from the generated image',
+ placeholder:
+ 'Please describe content you do not want to generate, such as color, bloody content'
+ }
+ },
+ speechToTextNode: {
+ label: 'Speech2Text',
+ text: 'Convert audio to text through speech recognition model',
+ stt_model: {
+ label: 'Speech Recognition Model'
+ },
+ audio: {
+ label: 'Select Audio File',
+ placeholder: 'Please select an audio file'
+ }
+ },
+ textToSpeechNode: {
+ label: 'TTS',
+ text: 'Convert text to audio through speech synthesis model',
+ tts_model: {
+ label: 'Speech Synthesis Model'
+ },
+ content: {
+ label: 'Select Text Content'
+ }
+ },
+ functionNode: {
+ label: 'Custom Function',
+ text: 'Execute custom scripts to achieve data processing'
+ },
+ applicationNode: {
+ label: 'APP Node'
+ }
+ },
+ compare: {
+ is_null: 'Is null',
+ is_not_null: 'Is not null',
+ contain: 'Contains',
+ not_contain: 'Does not contain',
+ eq: 'Equal to',
+ ge: 'Greater than or equal to',
+ gt: 'Greater than',
+ le: 'Less than or equal to',
+ lt: 'Less than',
+ len_eq: 'Length equal to',
+ len_ge: 'Length greater than or equal to',
+ len_gt: 'Length greater than',
+ len_le: 'Length less than or equal to',
+ len_lt: 'Length less than'
+ },
+ FileUploadSetting: {}
+}
diff --git a/ui/src/locales/lang/en-US/views/application.ts b/ui/src/locales/lang/en-US/views/application.ts
new file mode 100644
index 000000000..ebc4ef7cd
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/application.ts
@@ -0,0 +1,228 @@
+export default {
+ title: 'APP',
+ createApplication: 'Create APP',
+ importApplication: 'Import APP',
+ copyApplication: 'Copy APP',
+ workflow: 'WORKFLOW',
+ simple: 'SIMPLE',
+ searchBar: {
+ placeholder: 'Search by name'
+ },
+
+ setting: {
+ demo: 'Demo'
+ },
+ delete: {
+ confirmTitle: 'Are you sure you want to delete this APP: ',
+ confirmMessage:
+ 'Deleting this APP will no longer provide its services. Please proceed with caution.'
+ },
+ tip: {
+ ExportError: 'Export Failed',
+ professionalMessage:
+ 'The Community Edition supports up to 5 APP. If you need more APP, please upgrade to the Professional Edition.',
+ saveErrorMessage: 'Saving failed, please check your input or try again later',
+ loadingErrorMessage: 'Failed to load configuration, please check your input or try again later'
+ },
+
+ applicationForm: {
+ title: {
+ appTest: 'Debug Preview',
+ copy: 'copy'
+ },
+ form: {
+ appName: {
+ label: 'Name',
+ placeholder: 'Please enter the APP name',
+ requiredMessage: 'APP name is required'
+ },
+ appDescription: {
+ label: 'Description',
+ placeholder:
+ 'Describe the APP scenario and use, e.g.: XXX assistant answering user questions about XXX product usage'
+ },
+ appType: {
+ label: 'Type',
+ simplePlaceholder: 'Suitable for beginners to create assistant.',
+ workflowPlaceholder: 'Suitable for advanced users to customize the workflow of assistant'
+ },
+ appTemplate: {
+ blankApp: 'Blank APP',
+ assistantApp: 'Knowledge Assistant'
+ },
+ aiModel: {
+ label: 'AI Model',
+ placeholder: 'Please select an AI model'
+ },
+ roleSettings: {
+ label: 'System Role',
+ placeholder: 'You are xxx assistant'
+ },
+
+ prompt: {
+ label: 'Prompt',
+ noReferences: '(No references Knowledge)',
+ references: ' (References Knowledge)',
+ placeholder: 'Please enter prompt',
+ requiredMessage: 'Please enter prompt',
+ tooltip:
+ 'By adjusting the content of the prompt, you can guide the direction of the large model chat.',
+
+ noReferencesTooltip:
+ 'By adjusting the content of the prompt, you can guide the direction of the large model chat. This prompt will be fixed at the beginning of the context. Variables used: {question} is the question posed by the user.',
+ referencesTooltip:
+ 'By adjusting the content of the prompt, you can guide the direction of the large model chat. This prompt will be fixed at the beginning of the context. Variables used: {data} carries known information from the knowledge; {question} is the question posed by the user.',
+ defaultPrompt: `Known information: {data}
+ Question: {question}
+ Response requirements:
+ - Please use concise and professional language to answer the user's question.
+ `
+ },
+ historyRecord: {
+ label: 'Chat History'
+ },
+ relatedKnowledge: {
+ label: 'Related Knowledge',
+ placeholder: 'Related knowledge are displayed here'
+ },
+ multipleRoundsDialogue: 'Multiple Rounds Dialogue',
+
+ prologue: 'Prologue',
+ defaultPrologue:
+ 'Hello, I am XXX Assistant. You can ask me questions about using XXX.\n- What are the main features of XXX?\n- Which LLM does XXX support?\n- What document types does XXX support?',
+ problemOptimization: {
+ label: 'Questions Optimization',
+ tooltip:
+ 'Optimize the current question based on historical chat to better match knowledge points.'
+ },
+
+ voiceInput: {
+ label: 'Voice Input',
+ placeholder: 'Please select a speech recognition model',
+ requiredMessage: 'Please select a speech input model',
+ autoSend: 'Automatic Sending'
+ },
+ voicePlay: {
+ label: 'Voice Playback',
+ placeholder: 'Please select a speech synthesis model',
+ requiredMessage: 'Please select a speech playback model',
+ autoPlay: 'Automatic Playback',
+ browser: 'Browser Playback (free)',
+ tts: 'TTS Model',
+ listeningTest: 'Preview'
+ },
+ reasoningContent: {
+ label: 'Output Thinking',
+ tooltip:
+ "Please set the thinking label based on the model's return, and the content in the middle of the label will be recognized as the thinking process.",
+ start: 'Start',
+ end: 'End'
+ }
+ },
+ buttons: {
+ publish: 'Save&Publish',
+ addModel: 'Add Model'
+ },
+ dialog: {
+ addDataset: 'Add Related Knowledge',
+ addDatasetPlaceholder: 'The selected knowledge must use the same embedding model',
+ selected: 'Selected',
+ countDataset: 'Knowledge',
+
+ selectSearchMode: 'Retrieval Mode',
+ vectorSearch: 'Vector Search',
+ vectorSearchTooltip:
+ 'Vector search is a retrieval method based on vector distance calculations, suitable for large data volumes in the knowledge.',
+ fullTextSearch: 'Full-text Search',
+ fullTextSearchTooltip:
+ 'Full-text search is a retrieval method based on text similarity, suitable for small data volumes in the knowledge.',
+ hybridSearch: 'Hybrid Search',
+ hybridSearchTooltip:
+ 'Hybrid search is a retrieval method based on both vector and text similarity, suitable for medium data volumes in the knowledge.',
+ similarityThreshold: 'Similarity higher than',
+ similarityTooltip: 'The higher the similarity, the stronger the correlation.',
+ topReferences: 'Top N Segments',
+ maxCharacters: 'Maximum Characters per Reference',
+ noReferencesAction: 'When there are no knowledge references',
+ continueQuestioning: 'Continue to ask questions to the Al model',
+ provideAnswer: 'Specify Reply Content',
+ designated_answer:
+ 'Hello, I am XXX Assistant. My knowledge only contains information related to XXX products. Please rephrase your question.',
+ defaultPrompt1:
+ "The content inside the parentheses () represents the user's question. Based on the context, please speculate and complete the user's question ({question}). The requirement is to output a completed question and place it",
+ defaultPrompt2: 'tag'
+ }
+ },
+ applicationAccess: {
+ title: 'APP Access',
+ wecom: 'WeCom',
+ wecomTip: 'Create WeCom intelligent APP',
+ dingtalk: 'DingTalk',
+ dingtalkTip: 'Create DingTalk intelligent APP',
+ wechat: 'WeChat',
+ wechatTip: 'Create WeChat intelligent APP',
+ lark: 'Lark',
+ larkTip: 'Create Lark intelligent APP',
+ setting: 'Setting',
+ callback: 'Callback Address',
+ callbackTip: 'Please fill in the callback address',
+ wecomPlatform: 'WeCom Open Platform',
+ wechatPlatform: 'WeChat Open Platform',
+ dingtalkPlatform: 'DingTalk Open Platform',
+ larkPlatform: 'Lark Open Platform',
+ slack: 'Slack',
+ slackTip: 'Create Slack intelligent APP',
+ wecomSetting: {
+ title: 'WeCom Configuration',
+ cropId: 'Crop ID',
+ cropIdPlaceholder: 'Please enter crop ID',
+ agentIdPlaceholder: 'Please enter agent ID',
+ secretPlaceholder: 'Please enter secret',
+ tokenPlaceholder: 'Please enter token',
+ encodingAesKeyPlaceholder: 'Please enter EncodingAESKey',
+ authenticationSuccessful: 'Successful',
+ urlInfo:
+ '-APP management-Self-built-Created APP-Receive messages-Set the "URL" received by the API'
+ },
+ dingtalkSetting: {
+ title: 'DingTalk Configuration',
+ clientIdPlaceholder: 'Please enter client ID',
+ clientSecretPlaceholder: 'Please enter client secret',
+ urlInfo:
+ '-On the robot page, set the "Message Receiving Mode" to HTTP mode, and fill in the above URL into the "Message Receiving Address"'
+ },
+ wechatSetting: {
+ title: 'WeChat Configuration',
+ appId: 'APP ID',
+ appIdPlaceholder: 'Please enter APP ID',
+ appSecret: 'APP SECRET',
+ appSecretPlaceholder: 'Please enter APP SECRET',
+ token: 'TOKEN',
+ tokenPlaceholder: 'Please enter TOKEN',
+ aesKey: 'Message Encryption Key',
+ aesKeyPlaceholder: 'Please enter the message encryption key',
+ urlInfo:
+ '-Settings and Development-Basic Configuration-"Server Address URL" in server configuration'
+ },
+ larkSetting: {
+ title: 'Lark Configuration',
+ appIdPlaceholder: 'Please enter APP ID',
+ appSecretPlaceholder: 'Please enter APP secret',
+ verificationTokenPlaceholder: 'Please enter verification token',
+ urlInfo:
+ '-Events and callbacks - event configuration - configure the "request address" of the subscription method'
+ },
+ slackSetting: {
+ title: 'Slack Configuration',
+ signingSecretPlaceholder: 'Please enter signing secret',
+ botUserTokenPlaceholder: 'Please enter bot user token'
+ },
+ copyUrl: 'Copy the link and fill it in'
+ },
+ hitTest: {
+ title: 'Retrieval Testing',
+ text: 'Test the hitting effect of the Knowledge based on the given query text.',
+ emptyMessage1: 'Retrieval Testing results will show here',
+ emptyMessage2: 'No matching sections found'
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/dataset.ts b/ui/src/locales/lang/en-US/views/dataset.ts
new file mode 100644
index 000000000..7764c7c54
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/dataset.ts
@@ -0,0 +1,86 @@
+export default {
+ title: 'Knowledge',
+ createDataset: 'Create Knowledge',
+ general: 'General',
+ web: 'Web Site',
+ relatedApplications: 'Linked App',
+ document_count: 'docs',
+ relatedApp_count: 'linked apps',
+ searchBar: {
+ placeholder: 'Search by name'
+ },
+ setting: {
+ vectorization: 'Vectorization',
+ sync: 'Sync'
+ },
+ tip: {
+ professionalMessage:
+ 'The community edition supports up to 50 knowledge. For more knowledge, please upgrade to the professional edition.',
+ syncSuccess: 'Sync task sent successfully',
+ updateModeMessage:
+ 'After modifying the knowledge vector model, you need to vectorize the knowledge. Do you want to continue saving?'
+ },
+ delete: {
+ confirmTitle: 'Confirm deletion of knowledge:',
+ confirmMessage1: 'This knowledge is related with',
+ confirmMessage2: 'APP. Deleting it will be irreversible, please proceed with caution.'
+ },
+ datasetForm: {
+ title: {
+ info: 'Knowledge Settings'
+ },
+ form: {
+ datasetName: {
+ label: 'Name',
+ placeholder: 'Please enter the knowledge name',
+ requiredMessage: 'Please enter the knowledge name'
+ },
+ datasetDescription: {
+ label: 'Description',
+ placeholder:
+ 'Describe the content of the knowledge. A detailed description will help AI understand the content better, improving the accuracy of content retrieval and hit rate.',
+ requiredMessage: 'Please enter the knowledge description'
+ },
+ EmbeddingModel: {
+ label: 'Embedding Model',
+ placeholder: 'Please select a embedding model',
+ requiredMessage: 'Please select the embedding model'
+ },
+ datasetType: {
+ label: 'Type',
+ generalInfo: 'Upload local documents',
+ webInfo: 'Sync text data from a web site'
+ },
+ source_url: {
+ label: 'Web Root URL',
+ placeholder: 'Please enter the web root URL',
+ requiredMessage: 'Please enter the web root URL'
+ },
+ selector: {
+ label: 'Selector',
+ placeholder: 'Default is body, can input .classname/#idname/tagname'
+ }
+ }
+ },
+ ResultSuccess: {
+ title: 'Knowledge Created Successfully',
+ paragraph: 'Segments',
+ paragraph_count: 'Segments',
+ documentList: 'Document List',
+ loading: 'Importing',
+ buttons: {
+ toDataset: 'Return to Knowledge List',
+ toDocument: 'Go to Document'
+ }
+ },
+ syncWeb: {
+ title: 'Sync Knowledge',
+ syncMethod: 'Sync Method',
+ replace: 'Replace Sync',
+ replaceText: 'Re-fetch Web site documents, replacing the documents in the local knowledge',
+ complete: 'Full Sync',
+ completeText:
+ 'Delete all documents in the local knowledge and re-fetch web site documents',
+ tip: 'Note: All syncs will delete existing data and re-fetch new data. Please proceed with caution.'
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/document.ts b/ui/src/locales/lang/en-US/views/document.ts
new file mode 100644
index 000000000..bbf6e35e9
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/document.ts
@@ -0,0 +1,178 @@
+export default {
+ uploadDocument: 'Upload Document',
+ importDocument: 'Import Document',
+ syncDocument: 'Sync Document',
+ selected: 'Selected',
+ items: 'Items',
+ searchBar: {
+ placeholder: 'Search by document name'
+ },
+ setting: {
+ migration: 'Move',
+ cancelGenerateQuestion: 'Cancel Generating Questions',
+ cancelVectorization: 'Cancel Vectorization',
+ cancelGenerate: 'Cancel Generation',
+ export: 'Export to'
+ },
+ tip: {
+ saveMessage: 'Current changes have not been saved. Confirm exit?',
+ cancelSuccess: 'Successful',
+ sendMessage: 'Successful',
+ vectorizationSuccess: 'Successful',
+ nameMessage: 'Document name cannot be empty!',
+ importMessage: 'Successful',
+ migrationSuccess: 'Successful'
+ },
+ upload: {
+ selectFile: 'Select File',
+ selectFiles: 'Select Folder',
+ uploadMessage: 'Drag and drop files here to upload or',
+ formats: 'Supported formats:',
+ requiredMessage: 'Please upload a file',
+ errorMessage1: 'The file size exceeds 100mb',
+ errorMessage2: 'Unsupported file format',
+ errorMessage3: 'File cannot be empty',
+ errorMessage4: 'Up to 50 files can be uploaded at once',
+ template: 'Template',
+ download: 'Download'
+ },
+
+ fileType: {
+ txt: {
+ label: 'Text File',
+ tip1: '1. It is recommended to standardize the segment markers in the file before uploading.',
+ tip2: '2. Up to 50 files can be uploaded at once, with each file not exceeding 100MB.'
+ },
+ table: {
+ label: 'Table',
+ tip1: '1. Click to download the corresponding template and complete the information:',
+ tip2: '2. The first row must be column headers, and the column headers must be meaningful terms. Each record in the table will be treated as a segment.',
+ tip3: '3. Each sheet in the uploaded spreadsheet file will be treated as a document, with the sheet name as the document name.',
+ tip4: '4. Up to 50 files can be uploaded at once, with each file not exceeding 100MB.'
+ },
+ QA: {
+ label: 'QA Pairs',
+ tip1: '1. Click to download the corresponding template and complete the information:',
+ tip2: '2. Each sheet in the uploaded spreadsheet file will be treated as a document, with the sheet name as the document name.',
+ tip3: '3. Up to 50 files can be uploaded at once, with each file not exceeding 100MB.'
+ }
+ },
+ setRules: {
+ title: {
+ setting: 'Set Segment Rules',
+ preview: 'Preview'
+ },
+ intelligent: {
+ label: 'Automatic Segmentation (Recommended)',
+ text: 'If you are unsure how to set segmentation rules, it is recommended to use automatic segmentation.'
+ },
+ advanced: {
+ label: 'Advanced Segmentation',
+ text: 'Users can customize segmentation delimiters, segment length, and cleaning rules based on document standards.'
+ },
+ patterns: {
+ label: 'Segment Delimiters',
+ tooltip:
+ 'Recursively split according to the selected symbols in order. If the split result exceeds the segment length, it will be truncated to the segment length.',
+ placeholder: 'Please select'
+ },
+ limit: {
+ label: 'Segment Length'
+ },
+ with_filter: {
+ label: 'Auto Clean',
+ text: 'Remove duplicate extra symbols, spaces, blank lines, and tab words.'
+ },
+ checkedConnect: {
+ label: 'Add "Related Questions" section for question-based QA pairs during import.'
+ }
+ },
+ buttons: {
+ prev: 'Previous',
+ next: 'Next',
+ import: 'Start Import',
+ preview: 'Apply'
+ },
+ table: {
+ name: 'Document Name',
+ char_length: 'Character',
+ paragraph: 'Segment',
+ all: 'All',
+ updateTime: 'Update Time'
+ },
+ fileStatus: {
+ label: 'File Status',
+ SUCCESS: 'Success',
+ FAILURE: 'Failure',
+ EMBEDDING: 'Indexing',
+ PENDING: 'Queuing',
+ GENERATE: 'Generating',
+ SYNC: 'Syncing',
+ REVOKE: 'Cancelling',
+ finish: 'Finish'
+ },
+ enableStatus: {
+ label: 'Status',
+ enable: 'Enabled',
+ close: 'Disabled'
+ },
+ sync: {
+ label: 'Sync',
+ confirmTitle: 'Confirm sync document?',
+ confirmMessage1:
+ 'Syncing will delete existing data and retrieve new data. Please proceed with caution.',
+ confirmMessage2: 'Cannot sync, please set the document URL first.',
+ successMessage: 'Successful'
+ },
+ delete: {
+ confirmTitle1: 'Confirm batch deletion of',
+ confirmTitle2: 'documents?',
+ confirmMessage:
+ 'Segments within the selected documents will also be deleted. Please proceed with caution.',
+ successMessage: 'Successful',
+ confirmTitle3: 'Confirm deleting document:',
+ confirmMessage1: 'Under this document',
+ confirmMessage2: 'All segments will be deleted, please operate with caution. '
+ },
+ form: {
+ source_url: {
+ label: 'Document URL',
+ placeholder: 'Enter document URL, one per line. Incorrect URL will cause import failure.',
+ requiredMessage: 'Please enter a document URL'
+ },
+ selector: {
+ label: 'Selector',
+ placeholder: 'Default is body, you can input .classname/#idname/tagname'
+ },
+ hit_handling_method: {
+ label: 'Retrieve-Respond',
+ tooltip: 'When user asks a question, handle matched segments according to the set method.'
+ },
+ similarity: {
+ label: 'Similarity Higher Than',
+ placeholder: 'Directly return segment content',
+ requiredMessage: 'Please enter similarity value'
+ }
+ },
+ hitHandlingMethod: {
+ optimization: 'Model optimization',
+ directly_return: 'Respond directly'
+ },
+ generateQuestion: {
+ title: 'Generate Questions',
+ successMessage: 'Successful',
+ tip1: 'The {data} in the prompt is a placeholder for segmented content, which is replaced by the segmented content when executed and sent to the AI model;',
+ tip2: 'The AI model generates relevant questions based on the segmented content. Please place the generated questions within the',
+ tip3: 'tags, and the system will automatically relate the questions within these tags;',
+ tip4: 'The generation effect depends on the selected model and prompt. Users can adjust to achieve the best effect.',
+ prompt1:
+ 'Content: {data}\n \n Please summarize the above and generate 5 questions based on the summary. \nAnswer requirements: \n - Please output only questions; \n - Please place each question in',
+ prompt2: 'tag.'
+ },
+ feishu: {
+ selectDocument: 'Select Document',
+ tip1: 'Only documents and tables are supported. Documents will be segmented based on titles, and tables will be converted to Markdown format before segmentation.',
+ tip2: 'The system does not store the original document. Before importing the document, it is recommended to standardize the document segmentation markers.',
+ allCheck: 'Select All'
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/function-lib.ts b/ui/src/locales/lang/en-US/views/function-lib.ts
new file mode 100644
index 000000000..1ca7103b3
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/function-lib.ts
@@ -0,0 +1,79 @@
+export default {
+ title: 'Function',
+ internalTitle: 'Internal Function',
+ added: 'Added',
+ createFunction: 'Create Function',
+ editFunction: 'Edit Function',
+ copyFunction: 'Copy Function',
+ importFunction: 'Import Function',
+ searchBar: {
+ placeholder: 'Search by function name'
+ },
+ setting: {
+ disabled: 'Disabled'
+ },
+ tip: {
+ saveMessage: 'Unsaved changes will be lost. Are you sure you want to exit?'
+ },
+ delete: {
+ confirmTitle: 'Confirm deletion of function:',
+ confirmMessage:
+ 'Deleting this function will cause errors in APP that reference it when they are queried. Please proceed with caution.'
+ },
+ disabled: {
+ confirmTitle: 'Confirm disable function:',
+ confirmMessage:
+ 'Disabling this function will cause errors in APP that reference it when they are queried. Please proceed with caution.'
+ },
+ functionForm: {
+ title: {
+ copy: 'Copy',
+ baseInfo: 'Basic Information'
+ },
+ form: {
+ functionName: {
+ label: 'Name',
+ placeholder: 'Please enter the function name',
+ requiredMessage: 'Please enter the function name'
+ },
+ functionDescription: {
+ label: 'Description',
+ placeholder: 'Please enter a description of the function'
+ },
+ permission_type: {
+ label: 'Permissions',
+ requiredMessage: 'Please select'
+ },
+ paramName: {
+ label: 'Parameter Name',
+ placeholder: 'Please enter the parameter name',
+ requiredMessage: 'Please enter the parameter name'
+ },
+ dataType: {
+ label: 'Data Type'
+ },
+ source: {
+ label: 'Source',
+ custom: 'Custom',
+ reference: 'Reference Parameter'
+ },
+ required: {
+ label: 'Required'
+ },
+ param: {
+ paramInfo1: 'Displayed when using the function',
+ paramInfo2: 'Not displayed when using the function',
+ code: 'Content (Python)',
+ selectPlaceholder: 'Please select parameter',
+ inputPlaceholder: 'Please enter parameter values',
+ },
+ debug: {
+ run: 'Run',
+ output: 'Output',
+ runResult: 'Run Result',
+ runSuccess: 'Successful',
+ runFailed: 'Run Failed'
+ }
+ }
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/index.ts b/ui/src/locales/lang/en-US/views/index.ts
new file mode 100644
index 000000000..c63d40492
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/index.ts
@@ -0,0 +1,34 @@
+import notFound from './404'
+import application from './application'
+import applicationOverview from './application-overview'
+import dataset from './dataset'
+import system from './system'
+import functionLib from './function-lib'
+import user from './user'
+import team from './team'
+import template from './template'
+import document from './document'
+import paragraph from './paragraph'
+import problem from './problem'
+import log from './log'
+import applicationWorkflow from './application-workflow'
+import login from './login'
+import operateLog from './operate-log'
+export default {
+ notFound,
+ application,
+ applicationOverview,
+ system,
+ functionLib,
+ user,
+ team,
+ template,
+ dataset,
+ applicationWorkflow,
+ document,
+ paragraph,
+ problem,
+ log,
+ login,
+ operateLog
+}
diff --git a/ui/src/locales/lang/en-US/views/log.ts b/ui/src/locales/lang/en-US/views/log.ts
new file mode 100644
index 000000000..9dfa40e00
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/log.ts
@@ -0,0 +1,41 @@
+export default {
+ title: 'Chat Logs',
+ delete: {
+ confirmTitle: 'Confirm deletion of question:',
+ confirmMessage1: 'Deleting this question will cancel the association of',
+ confirmMessage2: 'segments. Please proceed with caution.'
+ },
+ buttons: {
+ clearStrategy: 'Cleanup Strategy',
+ prev: 'Previous',
+ next: 'Next'
+ },
+ table: {
+ abstract: 'Title',
+ chat_record_count: 'Total Messages',
+ user: 'User',
+ feedback: {
+ label: 'User Feedback',
+ star: 'Agree',
+ trample: 'Disagree'
+ },
+ mark: 'Marks',
+ recenTimes: 'Last Chat Time'
+ },
+ addToDataset: 'Add to Knowledge',
+ daysText: 'Days ago',
+ selectDataset: 'Select Knowledge',
+ selectDatasetPlaceholder: 'Please select a knowledge',
+ saveToDocument: 'Save to Document',
+ documentPlaceholder: 'Please select a document',
+ editContent: 'Edit Content',
+ editMark: 'Edit Label',
+ form: {
+ content: {
+ placeholder: 'Please enter the content'
+ },
+ title: {
+ placeholder: 'Please set a title for the current content for management and viewing'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/login.ts b/ui/src/locales/lang/en-US/views/login.ts
new file mode 100644
index 000000000..dc2edba57
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/login.ts
@@ -0,0 +1,24 @@
+export default {
+ title: 'Login',
+ jump_tip: 'You will be redirected to the authentication source page for authentication',
+ jump: 'Redirect',
+ resetPassword: 'Change Password',
+ forgotPassword: 'Forgot Password',
+ userRegister: 'User Registration',
+ buttons: {
+ login: 'Login',
+ register: 'Register',
+ backLogin: 'Back to Login',
+ checkCode: 'Verify Now'
+ },
+ newPassword: 'New Password',
+ enterPassword: 'Please enter your new password',
+ useEmail: 'Use Email',
+ moreMethod: 'More Login Methods',
+ verificationCode: {
+ placeholder: 'Please enter the verification code',
+ getVerificationCode: 'Get Verification Code',
+ successMessage: 'Verification code sent successfully',
+ resend: 'Resend'
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/operate-log.ts b/ui/src/locales/lang/en-US/views/operate-log.ts
new file mode 100644
index 000000000..1dbd8175d
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/operate-log.ts
@@ -0,0 +1,30 @@
+export default {
+ title: 'Operate Logs',
+ table: {
+ menu: {
+ label: 'Operate menu'
+ },
+ operate: {
+ label: 'Operate'
+ },
+ user: {
+ label: 'Operate user'
+ },
+ status: {
+ label: 'Status',
+ success: 'Successful',
+ fail: 'Failed',
+ all: 'All'
+ },
+ ip_address: {
+ label: 'IP Address'
+ },
+ opt: {
+ label: 'API Details'
+ },
+ operateTime: {
+ label: 'Operate Time'
+ }
+ },
+ close: 'Close'
+}
diff --git a/ui/src/locales/lang/en-US/views/paragraph.ts b/ui/src/locales/lang/en-US/views/paragraph.ts
new file mode 100644
index 000000000..812e3ab68
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/paragraph.ts
@@ -0,0 +1,32 @@
+export default {
+ title: 'Segment',
+ paragraph_count: 'Segments',
+ editParagraph: 'Edit Segment',
+ addParagraph: 'Add Segment',
+ paragraphDetail: 'Segment Details',
+ character_count: 'characters',
+ setting: {
+ batchSelected: 'Batch Select',
+ cancelSelected: 'Cancel Selection'
+ },
+ delete: {
+ confirmTitle: 'Confirm deletion of segment:',
+ confirmMessage: 'Deletion cannot be undone. Please proceed with caution.'
+ },
+ relatedProblem: {
+ title: 'Related Questions',
+ placeholder: 'Please select a question'
+ },
+ form: {
+ paragraphTitle: {
+ label: 'Title',
+ placeholder: 'Please enter the segment title'
+ },
+ content: {
+ label: 'Content',
+ placeholder: 'Please enter the segment content',
+ requiredMessage1: 'Please enter the segment content',
+ requiredMessage2: 'Content must not exceed 100,000 words'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/problem.ts b/ui/src/locales/lang/en-US/views/problem.ts
new file mode 100644
index 000000000..cd9780b59
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/problem.ts
@@ -0,0 +1,37 @@
+export default {
+ title: 'Questions',
+ createProblem: 'Create Question',
+ detailProblem: 'Question Details',
+ quickCreateProblem: 'Quick Create',
+ quickCreateName: 'question',
+ tip: {
+ placeholder: 'Enter the question, support multiple entries, one per line.',
+ errorMessage: 'Question cannot be empty!',
+ requiredMessage: 'Please enter a question',
+ relatedSuccess: 'Successful'
+ },
+
+ setting: {
+ batchDelete: 'Bulk Delete',
+ cancelRelated: 'Cancel Association'
+ },
+ searchBar: {
+ placeholder: 'Search by name'
+ },
+ table: {
+ paragraph_count: 'Related Segments',
+ updateTime: 'Update Time'
+ },
+ delete: {
+ confirmTitle: 'Confirm deletion of question:',
+ confirmMessage1: 'Deleting this question will cancel the association of',
+ confirmMessage2: 'segments. Please proceed with caution.'
+ },
+ relateParagraph: {
+ title: 'Relate to Segment',
+ selectDocument: 'Select a Document',
+ placeholder: 'Search document by name',
+ selectedParagraph: 'Selected Segments',
+ count: 'Count'
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/system.ts b/ui/src/locales/lang/en-US/views/system.ts
new file mode 100644
index 000000000..303d1175d
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/system.ts
@@ -0,0 +1,153 @@
+export default {
+ title: 'System',
+ test: 'Test Connection',
+ testSuccess: 'Successful',
+ testFailed: 'Test connection failed',
+ password: 'Password',
+ authentication: {
+ title: 'Login Authentication',
+ ldap: {
+ title: 'LDAP',
+ address: 'LDAP Address',
+ serverPlaceholder: 'Please enter LDAP address',
+ bindDN: 'Bind DN',
+ bindDNPlaceholder: 'Please enter Bind DN',
+ ou: 'User OU',
+ ouPlaceholder: 'Please enter user OU',
+ ldap_filter: 'User Filter',
+ ldap_filterPlaceholder: 'Please enter user filter',
+ ldap_mapping: 'LDAP Attribute Mapping',
+ ldap_mappingPlaceholder: 'Please enter LDAP attribute mapping',
+ enableAuthentication: 'Enable LDAP Authentication'
+ },
+ cas: {
+ title: 'CAS',
+ ldpUri: 'ldpUri',
+ ldpUriPlaceholder: 'Please enter ldpUri',
+ validateUrl: 'Validation Address',
+ validateUrlPlaceholder: 'Please enter validation address',
+ redirectUrl: 'Callback Address',
+ redirectUrlPlaceholder: 'Please enter callback address',
+ enableAuthentication: 'Enable CAS Authentication'
+ },
+ oidc: {
+ title: 'OIDC',
+ authEndpoint: 'Auth Endpoint',
+ authEndpointPlaceholder: 'Please enter auth endpoint',
+ tokenEndpoint: 'Token Endpoint',
+ tokenEndpointPlaceholder: 'Please enter token endpoint',
+ userInfoEndpoint: 'User Information Endpoint',
+ userInfoEndpointPlaceholder: 'Please enter user information endpoint',
+ clientId: 'Client ID',
+ clientIdPlaceholder: 'Please enter client ID',
+ scopePlaceholder: 'Please enter scope',
+ clientSecret: 'Client Secret',
+ clientSecretPlaceholder: 'Please enter client secret',
+ logoutEndpoint: 'Logout Endpoint',
+ logoutEndpointPlaceholder: 'Please enter logout endpoint',
+ redirectUrl: 'Redirect URL',
+ redirectUrlPlaceholder: 'Please enter redirect URL',
+ enableAuthentication: 'Enable OIDC Authentication'
+ },
+
+ oauth2: {
+ title: 'OAuth2',
+ authEndpoint: 'Auth Endpoint',
+ authEndpointPlaceholder: 'Please enter auth endpoint',
+ tokenEndpoint: 'Token Endpoint',
+ tokenEndpointPlaceholder: 'Please enter token endpoint',
+ userInfoEndpoint: 'User Information Endpoint',
+ userInfoEndpointPlaceholder: 'Please enter user information endpoint',
+ scope: 'Scope',
+ scopePlaceholder: 'Please enter scope',
+ clientId: 'Client ID',
+ clientIdPlaceholder: 'Please enter client ID',
+ clientSecret: 'Client Secret',
+ clientSecretPlaceholder: 'Please enter client secret',
+ redirectUrl: 'Redirect URL',
+ redirectUrlPlaceholder: 'Please enter redirect URL',
+ filedMapping: 'Field Mapping',
+ filedMappingPlaceholder: 'Please enter field mapping',
+ enableAuthentication: 'Enable OAuth2 Authentication'
+ },
+ scanTheQRCode: {
+ title: 'Scan the QR code',
+ wecom: 'WeCom',
+ dingtalk: 'DingTalk',
+ lark: 'Lark',
+ effective: 'Effective',
+ alreadyTurnedOn: 'Turned On',
+ notEnabled: 'Not Enabled',
+ validate: 'Validate',
+ validateSuccess: 'Successful',
+ validateFailed: 'Validation failed',
+ validateFailedTip: 'Please fill in all required fields and ensure the format is correct',
+ appKeyPlaceholder: 'Please enter APP key',
+ appSecretPlaceholder: 'Please enter APP secret',
+ corpIdPlaceholder: 'Please enter corp ID',
+ agentIdPlaceholder: 'Please enter agent ID',
+ callbackWarning: 'Please enter a valid URL address',
+ larkQrCode: 'Lark Scan Code Login',
+ dingtalkQrCode: 'DingTalk Scan Code Login',
+ setting: ' Setting',
+ access: 'Access'
+ }
+ },
+ theme: {
+ title: 'Appearance Settings',
+ platformDisplayTheme: 'Platform Display Theme',
+ customTheme: 'Custom Theme',
+ platformLoginSettings: 'Platform Login Settings',
+ custom: 'Custom',
+ pagePreview: 'Page Preview',
+ default: 'Default',
+ restoreDefaults: 'Restore Defaults',
+ orange: 'Orange',
+ green: 'Green',
+ purple: 'Purple',
+ red: 'Red',
+ loginBackground: 'Login Background Image',
+ loginLogo: 'Login Logo',
+ websiteLogo: 'Website Logo',
+ replacePicture: 'Replace Image',
+ websiteLogoTip:
+ 'Logo displayed at the top of the website. Recommended size: 48x48. Supports JPG, PNG, GIF. Maximum size: 10MB',
+ loginLogoTip:
+ 'Logo on the right side of the login page. Recommended size: 204x52. Supports JPG, PNG, GIF. Maximum size: 10MB',
+ loginBackgroundTip:
+ 'Left-side background image. Vector graphics recommended size: 576x900; Bitmap recommended size: 1152x1800. Supports JPG, PNG, GIF. Maximum size: 10MB',
+ websiteName: 'Website Name',
+ websiteNamePlaceholder: 'Please enter the website name',
+ websiteNameTip: 'The platform name displayed in the web page tab',
+ websiteSlogan: 'Welcome Slogan',
+ websiteSloganPlaceholder: 'Please enter the welcome slogan',
+ websiteSloganTip: 'The welcome slogan below the product logo',
+ defaultSlogan: 'Ready-to-use, flexible RAG Chatbot',
+ defaultTip: 'The default is the MaxKB platform interface, supports custom settings',
+ logoDefaultTip: 'The default is the MaxKB login interface, supports custom settings',
+ platformSetting: 'Platform Settings',
+ showUserManual: 'Show User Manual',
+ showForum: 'Show Forum Support',
+ showProject: 'Show Project Address',
+ urlPlaceholder: 'Please enter the URL address',
+ abandonUpdate: 'Abandon Update',
+ saveAndApply: 'Save and Apply',
+ fileMessageError: 'File size exceeds 10MB',
+ saveSuccess: 'Appearance settings successfully applied'
+ },
+ email: {
+ title: 'Email Settings',
+ smtpHost: 'SMTP Host',
+ smtpHostPlaceholder: 'Please enter SMTP host',
+ smtpPort: 'SMTP Port',
+ smtpPortPlaceholder: 'Please enter SMTP port',
+ smtpUser: 'SMTP User',
+ smtpUserPlaceholder: 'Please enter SMTP user',
+ sendEmail: 'Sender\'s Email',
+ sendEmailPlaceholder: 'Please enter the sender\'s email',
+ smtpPassword: 'SMTP Password',
+ smtpPasswordPlaceholder: 'Please enter SMTP password',
+ enableSSL: 'Enable SSL (if the SMTP port is 465, you usually need to enable SSL)',
+ enableTLS: 'Enable TLS (if the SMTP port is 587, you usually need to enable TLS)'
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/team.ts b/ui/src/locales/lang/en-US/views/team.ts
new file mode 100644
index 000000000..d25df4bb3
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/team.ts
@@ -0,0 +1,30 @@
+export default {
+ title: 'Team Members',
+ member: 'Member',
+ manage: 'Owner',
+ permissionSetting: 'Permission Settings',
+ addMember: 'Add Member',
+ addSubTitle: 'Members can access the data you authorize after logging in.',
+ searchBar: {
+ placeholder: 'Enter username to search'
+ },
+ delete: {
+ button: 'Remove',
+ confirmTitle: 'Confirm removal of member:',
+ confirmMessage:
+ 'Removing the member will revoke their access to knowledge and APP.'
+ },
+ setting: {
+ management: 'Manage',
+ check: 'View'
+ },
+ teamForm: {
+ form: {
+ userName: {
+ label: 'Username/Email',
+ placeholder: "Enter the member's username or email",
+ requiredMessage: 'Enter the username/email'
+ }
+ }
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/template.ts b/ui/src/locales/lang/en-US/views/template.ts
new file mode 100644
index 000000000..0a89fcfb6
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/template.ts
@@ -0,0 +1,89 @@
+export default {
+ title: 'Models',
+ provider: 'Provider',
+ providerPlaceholder: 'Select Provider',
+ addModel: 'Add Model',
+ searchBar: {
+ placeholder: 'Search by name'
+ },
+ delete: {
+ confirmTitle: 'Delete Model',
+ confirmMessage: 'Are you sure you want to delete the model:'
+ },
+ tip: {
+ createSuccessMessage: 'Model created successfully',
+ createErrorMessage: 'There are errors in the basic information',
+ errorMessage: 'Variable already exists: ',
+ emptyMessage1: 'Please select the model type and base model in the basic information first',
+ emptyMessage2: 'The selected model does not support parameter settings',
+ updateSuccessMessage: 'Model updated successfully',
+ saveSuccessMessage: 'Model parameters saved successfully',
+ downloadError: 'Download failed',
+ noModel: 'Model does not exist in Ollama'
+ },
+ model: {
+ allModel: 'All Models',
+ publicModel: 'Public Models',
+ privateModel: 'Private Models',
+ LLM: 'LLM',
+ EMBEDDING: 'Embedding Model',
+ RERANKER: 'Rerank',
+ STT: 'Speech2Text',
+ TTS: 'TTS',
+ IMAGE: 'Vision Model',
+ TTI: 'Image Generation'
+ },
+ templateForm: {
+ title: {
+ baseInfo: 'Basic Information',
+ advancedInfo: 'Advanced Settings',
+ modelParams: 'Model Parameters',
+ editParam: 'Edit Parameter',
+ addParam: 'Add Parameter',
+ paramSetting: 'Model Parameter Settings',
+ apiParamPassing: 'Interface Parameters'
+ },
+ form: {
+ templateName: {
+ label: 'Model Name',
+ placeholder: 'Set a name for the base model',
+ tooltip: 'Custom model name in MaxKB',
+ requiredMessage: 'Model name cannot be empty'
+ },
+ permissionType: {
+ label: 'Permission',
+ privateDesc: 'Available only to current user',
+ publicDesc: 'Available to all users',
+ requiredMessage: 'Permission cannot be empty'
+ },
+ model_type: {
+ label: 'Model Type',
+ placeholder: 'Select a model type',
+ tooltip1:
+ 'LLM: An inference model for AI chats in the APP.',
+ tooltip2:
+ 'Embedding Model: A model for vectorizing document content in the knowledge.',
+ tooltip3: 'Speech2Text: A model used for speech recognition in the APP.',
+ tooltip4: 'TTS: A model used for TTS in the APP.',
+ tooltip5:
+ 'Rerank: A model used to reorder candidate segments when using multi-route recall in advanced orchestration APP.',
+ tooltip6:
+ 'Vision Model: A visual model used for image understanding in advanced orchestration APP.',
+ tooltip7:
+ 'Image Generation: A visual model used for image generation in advanced orchestration APP.',
+ requiredMessage: 'Model type cannot be empty'
+ },
+ base_model: {
+ label: 'Base Model',
+ tooltip:
+ 'For models not listed, enter the model name and press Enter',
+ placeholder: 'Enter the base model name and press Enter to add',
+ requiredMessage: 'Base model cannot be empty'
+ }
+ }
+ },
+ download: {
+ downloading: 'Downloading...',
+ cancelDownload: 'Cancel Download'
+ }
+}
diff --git a/ui/src/locales/lang/en-US/views/user.ts b/ui/src/locales/lang/en-US/views/user.ts
new file mode 100644
index 000000000..ae41fd564
--- /dev/null
+++ b/ui/src/locales/lang/en-US/views/user.ts
@@ -0,0 +1,70 @@
+export default {
+ title: 'User',
+ createUser: 'Create User',
+ editUser: 'Edit User',
+ setting: {
+ updatePwd: 'Change Password'
+ },
+ tip: {
+ professionalMessage:
+ 'The community edition supports up to 2 users. For more users, please upgrade to the professional edition.',
+ updatePwdSuccess: 'User password updated successfully'
+ },
+ delete: {
+ confirmTitle: 'Confirm deletion of user:',
+ confirmMessage:
+ 'Deleting this user will also delete all resources (APP, knowledge, models) created by this user. Please proceed with caution.'
+ },
+ disabled: {
+ confirmTitle: 'Confirm disable function:',
+ confirmMessage:
+ 'Disabling this function will cause errors when APP that reference it are queried. Please proceed with caution.'
+ },
+ userForm: {
+ form: {
+ username: {
+ label: 'Username',
+ placeholder: 'Please enter username',
+ requiredMessage: 'Please enter username',
+ lengthMessage: 'Length must be between 6 and 20 words'
+ },
+ nick_name: {
+ label: 'Name',
+ placeholder: 'Please enter name'
+ },
+ email: {
+ label: 'Email',
+ placeholder: 'Please enter email',
+ requiredMessage: 'Please enter email'
+ },
+ phone: {
+ label: 'Phone',
+ placeholder: 'Please enter phone'
+ },
+ password: {
+ label: 'Login Password',
+ placeholder: 'Please enter password',
+ requiredMessage: 'Please enter password',
+ lengthMessage: 'Length must be between 6 and 20 words'
+ },
+ new_password: {
+ label: 'New Password',
+ placeholder: 'Please enter new password',
+ requiredMessage: 'Please enter new password'
+ },
+ re_password: {
+ label: 'Confirm Password',
+ placeholder: 'Please enter confirm password',
+ requiredMessage: 'Please enter confirm password',
+ validatorMessage: 'Passwords do not match'
+ }
+ }
+ },
+ source: {
+ label: 'User Type',
+ local: 'System User',
+ wecom: 'WeCom',
+ lark: 'Lark',
+ dingtalk: 'DingTalk'
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/ai-chat.ts b/ui/src/locales/lang/zh-CN/ai-chat.ts
new file mode 100644
index 000000000..9277762c8
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/ai-chat.ts
@@ -0,0 +1,96 @@
+export default {
+ noHistory: '暂无历史记录',
+ createChat: '新建对话',
+ history: '历史记录',
+ only20history: '仅显示最近 20 条对话',
+ question_count: '条提问',
+ exportRecords: '导出聊天记录',
+ chatId: '对话 ID',
+ userInput: '用户输入',
+ quote: '引用',
+ download: '点击下载文件',
+ passwordValidator: {
+ title: '请输入密码打开链接',
+ errorMessage1: '密码不能为空',
+ errorMessage2: '密码错误'
+ },
+ operation: {
+ play: '点击播放',
+ pause: '停止',
+ regeneration: '换个答案',
+ like: '赞同',
+ cancelLike: '取消赞同',
+ oppose: '反对',
+ cancelOppose: '取消反对',
+ continue: '继续',
+ stopChat: '停止回答',
+ startChat: '开始回答',
+ },
+ tip: {
+ error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!',
+ errorIdentifyMessage: '无法识别用户身份',
+ errorLimitMessage: '抱歉,您的提问已达到最大限制,请明天再来吧!',
+ answerMessage: '抱歉,没有查找到相关内容,请重新描述您的问题或提供更多信息。',
+ stopAnswer: '已停止回答',
+ answerLoading: '回答中',
+ recorderTip: `该功能需要使用麦克风,浏览器禁止不安全页面录音,解决方案如下:
+1、可开启 https 解决;
+2、若无 https 配置则需要修改浏览器安全配置,Chrome 设置如下:
+(1) 地址栏输入chrome://flags/#unsafely-treat-insecure-origin-as-secure;
+(2) 将 http 站点配置在文本框中,例如: http://127.0.0.1:8080。
`,
+ recorderError: '录音失败',
+ confirm: '我知道了',
+ requiredMessage: '请填写所有必填字段',
+ inputParamMessage1: '请在URL中填写参数',
+ inputParamMessage2: '的值',
+ prologueMessage: '抱歉,当前正在维护,无法提供服务,请稍后再试!'
+ },
+ inputPlaceholder: {
+ speaking: '说话中',
+ recorderLoading: '转文字中',
+ default: '请输入问题'
+ },
+ uploadFile: {
+ label: '上传文件',
+ most: '最多',
+ limit: '个,每个文件限制',
+ fileType: '文件类型',
+ tipMessage: '请在文件上传配置中选择文件类型',
+ limitMessage1: '最多上传',
+ limitMessage2: '个文件',
+ sizeLimit: '单个文件大小不能超过',
+ imageMessage: '请解析图片内容',
+ errorMessage: '上传失败'
+ },
+ executionDetails: {
+ title: '执行详情',
+ paramOutputTooltip: '每个文档仅支持预览500字',
+ audioFile: '语音文件',
+ searchContent: '检索内容',
+ searchResult: '检索结果',
+ conditionResult: '判断结果',
+ currentChat: '本次对话',
+ answer: 'AI 回答',
+ replyContent: '回复内容',
+ textContent: '文本内容',
+ input: '输入',
+ output: '输出',
+ rerankerContent: '重排内容',
+ rerankerResult: '重排结果',
+ paragraph: '分段',
+ noSubmit: '用户未提交',
+ errMessage: '错误日志'
+ },
+ KnowledgeSource: {
+ title: '知识来源',
+ referenceParagraph: '引用分段',
+ consume: '消耗tokens',
+ consumeTime: '耗时'
+ },
+ paragraphSource: {
+ title: '知识库引用',
+ question: '用户问题',
+ optimizationQuestion: '优化后问题'
+ },
+ editTitle: '编辑标题',
+}
diff --git a/ui/src/locales/lang/zh-CN/common.ts b/ui/src/locales/lang/zh-CN/common.ts
new file mode 100644
index 000000000..ba790f282
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/common.ts
@@ -0,0 +1,63 @@
+export default {
+ create: '创建',
+ createSuccess: '创建成功',
+ copy: '复制',
+ copySuccess: '复制成功',
+ copyError: '复制失败',
+ save: '保存',
+ saveSuccess: '保存成功',
+ delete: '删除',
+ deleteSuccess: '删除成功',
+ setting: '设置',
+ settingSuccess: '设置成功',
+ submit: '提交',
+ submitSuccess: '提交成功',
+ edit: '编辑',
+ editSuccess: '编辑成功',
+ modify: '修改',
+ modifySuccess: '修改成功',
+ cancel: '取消',
+ confirm: '确定',
+ tip: '提示',
+ add: '添加',
+ refresh: '刷新',
+ search: '搜索',
+ clear: '清空',
+ professional: '购买专业版',
+ createDate: '创建日期',
+ createTime: '创建时间',
+ operation: '操作',
+ character: '字符',
+ export: '导出',
+ exportSuccess: '导出成功',
+ unavailable: '(不可用)',
+ public: '公有',
+ private: '私有',
+ paramSetting: '参数设置',
+ creator: '创建者',
+ author: '作者',
+ debug: '调试',
+ required: '必填',
+ noData: '暂无数据',
+ result: '结果',
+ fileUpload: {
+ document: '文档',
+ image: '图片',
+ audio: '音频',
+ video: '视频'
+ },
+ status: {
+ label: '状态',
+ enableSuccess: '启用成功',
+ disableSuccess: '禁用成功'
+ },
+ inputPlaceholder: '请输入',
+ title: '标题',
+ content: '内容',
+ param: {
+ outputParam: '输出参数',
+ inputParam: '输入参数',
+ initParam: '启动参数',
+ },
+ rename:'重命名'
+}
diff --git a/ui/src/locales/lang/zh-CN/components.ts b/ui/src/locales/lang/zh-CN/components.ts
new file mode 100644
index 000000000..5b871daf1
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/components.ts
@@ -0,0 +1,12 @@
+export default {
+ quickCreatePlaceholder: '快速创建空白文档',
+ quickCreateName: '文档名称',
+ noData: '无匹配数据',
+ loading: '加载中',
+ noMore: '到底啦!',
+ selectParagraph: {
+ title: '选择分段',
+ error: '仅执行未成功分段',
+ all: '全部分段'
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/dynamics-form.ts b/ui/src/locales/lang/zh-CN/dynamics-form.ts
new file mode 100644
index 000000000..9814c06eb
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/dynamics-form.ts
@@ -0,0 +1,102 @@
+export default {
+ input_type_list: {
+ TextInput: '文本框',
+ PasswordInput: '密码框',
+ Slider: '滑块',
+ SwitchInput: '开关',
+ SingleSelect: '单选框',
+ MultiSelect: '多选框',
+ DatePicker: '日期',
+ JsonInput: 'JSON文本框',
+ RadioCard: '选项卡',
+ RadioRow: '单行选项卡'
+ },
+ default: {
+ label: '默认值',
+ placeholder: '请输入默认值',
+ requiredMessage: '为必填属性',
+ show: '显示默认值'
+ },
+ tip: {
+ requiredMessage: '不能为空',
+ jsonMessage: 'JSON格式不正确'
+ },
+ searchBar: {
+ placeholder: '请输入关键字搜索'
+ },
+ paramForm: {
+ field: {
+ label: '参数',
+ placeholder: '请输入参数',
+ requiredMessage: '参数 为必填属性',
+ requiredMessage2: '只能输入字母数字和下划线'
+ },
+ name: {
+ label: '显示名称',
+ placeholder: '请输入显示名称',
+ requiredMessage: '显示名称 为必填属性'
+ },
+ tooltip: {
+ label: '参数提示说明',
+ placeholder: '请输入参数提示说明'
+ },
+ required: {
+ label: '是否必填',
+ requiredMessage: '是否必填 为必填属性'
+ },
+ input_type: {
+ label: '组件类型',
+ placeholder: '请选择组件类型',
+ requiredMessage: '组建类型 为必填属性'
+ }
+ },
+ DatePicker: {
+ placeholder: '选择日期',
+ year: '年',
+ month: '月',
+ date: '日期',
+ datetime: '日期时间',
+ dataType: {
+ label: '时间类型',
+ placeholder: '请选择时间类型'
+ },
+ format: {
+ label: '格式',
+ placeholder: '请选择格式'
+ }
+ },
+ Select: {
+ label: '选项值',
+ placeholder: '请输入选项值'
+ },
+ tag: {
+ label: '标签',
+ placeholder: '请输入选项标签'
+ },
+ Slider: {
+ showInput: {
+ label: '是否带输入框'
+ },
+ valueRange: {
+ label: '取值范围',
+ minRequired: '最小值必填',
+ maxRequired: '最大值必填'
+ },
+ step: {
+ label: '步长值',
+ requiredMessage1: '步长值必填',
+ requiredMessage2: '步长不能为0'
+ }
+ },
+ TextInput: {
+ length: {
+ label: '文本长度',
+ minRequired: '最小长度必填',
+ maxRequired: '最大长度必填',
+ requiredMessage1: '长度在',
+ requiredMessage2: '到',
+ requiredMessage3: '个字符',
+ requiredMessage4: '文本长度为必填参数'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/index.ts b/ui/src/locales/lang/zh-CN/index.ts
new file mode 100644
index 000000000..3df42d640
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/index.ts
@@ -0,0 +1,17 @@
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
+import components from './components'
+import layout from './layout'
+import views from './views'
+import common from './common'
+import dynamicsForm from './dynamics-form'
+import chat from './ai-chat'
+export default {
+ lang: '简体中文',
+ layout,
+ views,
+ components,
+ zhCn,
+ common,
+ dynamicsForm,
+ chat
+}
diff --git a/ui/src/locales/lang/zh-CN/layout.ts b/ui/src/locales/lang/zh-CN/layout.ts
new file mode 100644
index 000000000..fbf8e7e93
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/layout.ts
@@ -0,0 +1,33 @@
+export default {
+ github: '项目地址',
+ wiki: '用户手册',
+ forum: '论坛求助',
+ logout: '退出',
+ apiKey: 'API Key 管理',
+ apiServiceAddress: 'API 服务地址',
+ language: '语言',
+ isExpire: '未上传 License 或 License 已过期。',
+ about: {
+ title: '关于',
+ expiredTime: '到期时间',
+ edition: {
+ label: '版本',
+ community: '社区版',
+ professional: '专业版'
+ },
+ version: '版本号',
+ serialNo: '序列号',
+ remark: '备注',
+ update: '更新',
+ authorize: '授权给'
+ },
+ time: {
+ daysLater: '天后',
+ hoursLater: '小时后',
+ expired: '已过期',
+ expiringSoon: '即将到期'
+ },
+ copyright: '版权所有 © 2014-2025 杭州飞致云信息科技有限公司',
+ userManualUrl: 'https://maxkb.cn/docs/',
+ forumUrl: 'https://bbs.fit2cloud.com/c/mk/11'
+}
diff --git a/ui/src/locales/lang/zh-CN/views/404.ts b/ui/src/locales/lang/zh-CN/views/404.ts
new file mode 100644
index 000000000..a65dcbbd0
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/404.ts
@@ -0,0 +1,5 @@
+export default {
+ title: "404",
+ message: "无法访问应用",
+ operate: "返回首页",
+};
diff --git a/ui/src/locales/lang/zh-CN/views/application-overview.ts b/ui/src/locales/lang/zh-CN/views/application-overview.ts
new file mode 100644
index 000000000..5c23f9ee3
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/application-overview.ts
@@ -0,0 +1,112 @@
+export default {
+ title: '概览',
+ appInfo: {
+ header: '应用信息',
+ publicAccessLink: '公开访问链接',
+ openText: '开',
+ closeText: '关',
+ copyLinkText: '复制链接',
+ refreshLinkText: '刷新链接',
+ demo: '演示',
+ embedInWebsite: '嵌入第三方',
+ accessControl: '访问限制',
+ displaySetting: '显示设置',
+ apiAccessCredentials: 'API 访问凭据',
+ apiKey: 'API Key',
+ refreshToken: {
+ msgConfirm1: '是否重新生成公开访问链接?',
+ msgConfirm2:
+ '重新生成公开访问链接会影响嵌入第三方脚本变更,需要将新脚本重新嵌入第三方,请谨慎操作!',
+ refreshSuccess: '刷新成功'
+ },
+
+ APIKeyDialog: {
+ saveSettings: '保存设置',
+ msgConfirm1: '是否删除API Key',
+ msgConfirm2: '删除API Key后将无法恢复,请确认是否删除?',
+ enabledSuccess: '已启用',
+ disabledSuccess: '已禁用'
+ },
+ EditAvatarDialog: {
+ title: '应用头像',
+ customizeUpload: '自定义上传',
+ upload: '上传',
+ default: '默认logo',
+ custom: '自定义',
+ sizeTip: '建议尺寸 32*32,支持 JPG、PNG、GIF,大小不超过 10 MB',
+ fileSizeExceeded: '文件大小超过 10 MB',
+ uploadImagePrompt: '请上传一张图片'
+ },
+ EmbedDialog: {
+ fullscreenModeTitle: '全屏模式',
+ copyInstructions: '复制以下代码进行嵌入',
+ floatingModeTitle: '浮窗模式',
+ mobileModeTitle: '移动端模式'
+ },
+ LimitDialog: {
+ showSourceLabel: '显示知识来源',
+ clientQueryLimitLabel: '每个客户端提问限制',
+ timesDays: '次/天',
+ authentication: '身份验证',
+ authenticationValue: '验证密码',
+ whitelistLabel: '白名单',
+ whitelistPlaceholder:
+ '请输入允许嵌入第三方的源地址,一行一个,如:\nhttp://127.0.0.1:5678\nhttps://dataease.io'
+ },
+ SettingAPIKeyDialog: {
+ dialogTitle: '设置',
+ allowCrossDomainLabel: '允许跨域地址',
+ crossDomainPlaceholder:
+ '请输入允许的跨域地址,开启后不输入跨域地址则不限制。\n跨域地址一行一个,如:\nhttp://127.0.0.1:5678 \nhttps://dataease.io'
+ },
+ SettingDisplayDialog: {
+ dialogTitle: '显示设置',
+ languageLabel: '语言',
+ showSourceLabel: '显示知识来源',
+ showExecutionDetail: '显示执行详情',
+ restoreDefault: '恢复默认',
+ customThemeColor: '自定义主题色',
+ headerTitleFontColor: '头部标题字体颜色',
+ default: '默认',
+ askUserAvatar: '提问用户头像',
+ replace: '替换',
+ imageMessage: '建议尺寸 32*32,支持 JPG、PNG、GIF,大小不超过 10 MB',
+ AIAvatar: 'AI 回复头像',
+ floatIcon: '浮窗入口图标',
+ iconDefaultPosition: '图标默认位置',
+ iconPosition: {
+ left: '左',
+ right: '右',
+ bottom: '下',
+ top: '上'
+ },
+ draggablePosition: '可拖拽位置',
+ showHistory: '显示历史记录',
+ displayGuide: '显示引导图(浮窗模式)',
+ disclaimer: '免责声明',
+ disclaimerValue: '「以上内容均由 AI 生成,仅供参考和借鉴」'
+ }
+ },
+ monitor: {
+ monitoringStatistics: '监控统计',
+ customRange: '自定义范围',
+ startDatePlaceholder: '开始时间',
+ endDatePlaceholder: '结束时间',
+ pastDayOptions: {
+ past7Days: '过去7天',
+ past30Days: '过去30天',
+ past90Days: '过去90天',
+ past183Days: '过去半年',
+ other: '自定义'
+ },
+ charts: {
+ customerTotal: '用户总数',
+ customerNew: '用户新增数',
+ queryCount: '提问次数',
+ tokensTotal: 'Tokens 总数',
+ userSatisfaction: '用户满意度',
+ approval: '赞同',
+ disapproval: '反对'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/application-workflow.ts b/ui/src/locales/lang/zh-CN/views/application-workflow.ts
new file mode 100644
index 000000000..010964bb0
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/application-workflow.ts
@@ -0,0 +1,287 @@
+export default {
+ node: '节点',
+ nodeName: '节点名称',
+ baseComponent: '基础组件',
+ nodeSetting: '节点设置',
+ workflow: '工作流',
+ searchBar: {
+ placeholder: '按名称搜索'
+ },
+ info: {
+ previewVersion: '预览版本:',
+ saveTime: '保存时间:'
+ },
+ setting: {
+ restoreVersion: '恢复版本',
+ restoreCurrentVersion: '恢复此版本',
+ addComponent: '添加组件',
+ public: '发布',
+ releaseHistory: '发布历史',
+ autoSave: '自动保存',
+ latestRelease: '最近发布',
+ copyParam: '复制参数',
+ debug: '调试',
+ exit: '直接退出',
+ exitSave: '保存并退出',
+ },
+ tip: {
+ publicSuccess: '发布成功',
+ noData: '没有找到相关结果',
+ nameMessage: '名字不能为空!',
+ onlyRight: '只允许从右边的锚点连出',
+ notRecyclable: '不可循环连线',
+ onlyLeft: '只允许连接左边的锚点',
+ applicationNodeError: '该应用不可用',
+ functionNodeError: '该函数不可用',
+ repeatedNodeError: '节点名称已存在!',
+ cannotCopy: '不能被复制',
+ copyError: '已复制节点',
+ paramErrorMessage: '参数已存在: ',
+ saveMessage: '当前的更改尚未保存,是否保存后退出?',
+ },
+ delete: {
+ confirmTitle: '确定删除该节点?',
+ deleteMessage: '节点不允许删除'
+ },
+ control: {
+ zoomOut: '缩小',
+ zoomIn: '放大',
+ fitView: '适应',
+ retract: '收起全部节点',
+ extend: '展开全部节点',
+ beautify: '一键美化'
+ },
+ variable: {
+ label: '变量',
+ global: '全局变量',
+ Referencing: '引用变量',
+ ReferencingRequired: '引用变量必填',
+ ReferencingError: '引用变量错误',
+ NoReferencing: '不存在的引用变量',
+ placeholder: '请选择变量'
+ },
+ condition: {
+ title: '执行条件',
+ front: '前置',
+ AND: '所有',
+ OR: '任一',
+ text: '连线节点执行完,执行当前节点'
+ },
+ validate: {
+ startNodeRequired: '开始节点必填',
+ startNodeOnly: '开始节点只能有一个',
+ baseNodeRequired: '基本信息节点必填',
+ baseNodeOnly: '基本信息节点只能有一个',
+ notInWorkFlowNode: '未在流程中的节点',
+ noNextNode: '不存在的下一个节点',
+ nodeUnavailable: '节点不可用',
+ needConnect1: '节点的',
+ needConnect2: '分支需要连接',
+ cannotEndNode: '节点不能当做结束节点'
+ },
+ nodes: {
+ startNode: {
+ label: '开始',
+ question: '用户问题',
+ currentTime: '当前时间'
+ },
+ baseNode: {
+ label: '基本信息',
+ appName: {
+ label: '应用名称'
+ },
+ appDescription: {
+ label: '应用描述'
+ },
+ fileUpload: {
+ label: '文件上传',
+ tooltip: '开启后,问答页面会显示上传文件的按钮。'
+ },
+ FileUploadSetting: {
+ title: '文件上传设置',
+ maxFiles: '单次上传最多文件数',
+ fileLimit: '每个文件最大(MB)',
+ fileUploadType: {
+ label: '上传的文件类型',
+ documentText: '需要使用“文档内容提取”节点解析文档内容',
+ imageText: '需要使用“视觉模型”节点解析图片内容',
+ audioText: '需要使用“语音转文本”节点解析音频内容'
+ }
+ }
+ },
+ aiChatNode: {
+ label: 'AI 对话',
+ text: '与 AI 大模型进行对话',
+ answer: 'AI 回答内容',
+ returnContent: {
+ label: '返回内容',
+ tooltip: `关闭后该节点的内容则不输出给用户。
+ 如果你想让用户看到该节点的输出内容,请打开开关。`
+ },
+ defaultPrompt: '已知信息',
+ think: '思考过程'
+ },
+ searchDatasetNode: {
+ label: '知识库检索',
+ text: '关联知识库,查找与问题相关的分段',
+ paragraph_list: '检索结果的分段列表',
+ is_hit_handling_method_list: '满足直接回答的分段列表',
+ result: '检索结果',
+ directly_return: '满足直接回答的分段内容',
+ searchParam: '检索参数',
+ searchQuestion: {
+ label: '检索问题',
+ placeholder: '请选择检索问题',
+ requiredMessage: '请选择检索问题'
+ }
+ },
+ questionNode: {
+ label: '问题优化',
+ text: '根据历史聊天记录优化完善当前问题,更利于匹配知识库分段',
+ result: '问题优化结果',
+ defaultPrompt1: `根据上下文优化和完善用户问题`,
+ defaultPrompt2: `请输出一个优化后的问题。`,
+ systemDefault: '你是一个问题优化大师'
+ },
+ conditionNode: {
+ label: '判断器',
+ text: '根据不同条件执行不同的节点',
+ branch_name: '分支名称',
+ conditions: {
+ label: '条件',
+ info: '符合以下',
+ requiredMessage: '请选择条件'
+ },
+ valueMessage: '请输入值',
+ addCondition: '添加条件',
+ addBranch: '添加分支'
+ },
+ replyNode: {
+ label: '指定回复',
+ text: '指定回复内容,引用变量会转换为字符串进行输出',
+ content: '内容',
+ replyContent: {
+ label: '回复内容',
+ custom: '自定义',
+ reference: '引用变量'
+ }
+ },
+ rerankerNode: {
+ label: '多路召回',
+ text: '使用重排模型对多个知识库的检索结果进行二次召回',
+ result_list: '重排结果列表',
+ result: '重排结果',
+ rerankerContent: {
+ label: '重排内容',
+ requiredMessage: '请选择重排内容'
+ },
+ higher: '高于',
+ ScoreTooltip: 'Score越高相关性越强。',
+ max_paragraph_char_number: '最大引用字符数',
+ reranker_model: {
+ label: '重排模型',
+ placeholder: '请选择重排模型'
+ }
+ },
+ formNode: {
+ label: '表单收集',
+ text: '在问答过程中用于收集用户信息,可以根据收集到表单数据执行后续流程',
+ form_content_format1: '你好,请先填写下面表单内容:',
+ form_content_format2: '填写后请点击【提交】按钮进行提交。',
+ form_data: '表单全部内容',
+ formContent: {
+ label: '表单输出内容',
+ requiredMessage: '请表单输出内容',
+ tooltip: '设置执行该节点输出的内容,{ form } 为表单的占位符。'
+ },
+ formAllContent: '表单全部内容',
+ formSetting: '表单配置'
+ },
+ documentExtractNode: {
+ label: '文档内容提取',
+ text: '提取文档中的内容',
+ content: '文档内容'
+ },
+ imageUnderstandNode: {
+ label: '图片理解',
+ text: '识别出图片中的对象、场景等信息回答用户问题',
+ answer: 'AI 回答内容',
+ model: {
+ label: '视觉模型',
+ requiredMessage: '请选择视觉模型'
+ },
+ image: {
+ label: '选择图片',
+ requiredMessage: '请选择图片'
+ }
+ },
+ variableAssignNode: {
+ label: '变量赋值',
+ text: '更新全局变量的值',
+ assign: '赋值'
+ },
+ imageGenerateNode: {
+ label: '图片生成',
+ text: '根据提供的文本内容生成图片',
+ answer: 'AI 回答内容',
+ model: {
+ label: '图片生成模型',
+ requiredMessage: '请选择图片生成模型'
+ },
+ prompt: {
+ label: '提示词(正向)',
+ tooltip: '正向提示词,用来描述生成图像中期望包含的元素和视觉特点'
+ },
+ negative_prompt: {
+ label: '提示词(负向)',
+ tooltip: '反向提示词,用来描述不希望在画面中看到的内容,可以对画面进行限制。',
+ placeholder: '请描述不想生成的图片内容,比如:颜色、血腥内容'
+ }
+ },
+ speechToTextNode: {
+ label: '语音转文本',
+ text: '将音频通过语音识别模型转换为文本',
+ stt_model: {
+ label: '语音识别模型'
+ },
+ audio: {
+ label: '选择语音文件',
+ placeholder: '请选择语音文件'
+ }
+ },
+ textToSpeechNode: {
+ label: '文本转语音',
+ text: '将文本通过语音合成模型转换为音频',
+ tts_model: {
+ label: '语音识别模型'
+ },
+ content: {
+ label: '选择文本内容'
+ }
+ },
+ functionNode: {
+ label: '自定义函数',
+ text: '通过执行自定义脚本,实现数据处理'
+ },
+ applicationNode: {
+ label: '应用节点'
+ }
+ },
+ compare: {
+ is_null: '为空',
+ is_not_null: '不为空',
+ contain: '包含',
+ not_contain: '不包含',
+ eq: '等于',
+ ge: '大于等于',
+ gt: '大于',
+ le: '小于等于',
+ lt: '小于',
+ len_eq: '长度等于',
+ len_ge: '长度大于等于',
+ len_gt: '长度大于',
+ len_le: '长度小于等于',
+ len_lt: '长度小于'
+ },
+ FileUploadSetting: {}
+}
diff --git a/ui/src/locales/lang/zh-CN/views/application.ts b/ui/src/locales/lang/zh-CN/views/application.ts
new file mode 100644
index 000000000..b818827e3
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/application.ts
@@ -0,0 +1,215 @@
+export default {
+ title: '应用',
+ createApplication: '创建应用',
+ importApplication: '导入应用',
+ copyApplication: '复制应用',
+ workflow: '高级编排',
+ simple: '简单配置',
+ searchBar: {
+ placeholder: '按名称搜索'
+ },
+ setting: {
+ demo: '演示'
+ },
+ delete: {
+ confirmTitle: '是否删除应用:',
+ confirmMessage: '删除后该应用将不再提供服务,请谨慎操作。'
+ },
+ tip: {
+ ExportError: '导出失败',
+ professionalMessage: '社区版最多支持 5 个应用,如需拥有更多应用,请升级为专业版。',
+ saveErrorMessage: '保存失败,请检查输入或稍后再试',
+ loadingErrorMessage: '加载配置失败,请检查输入或稍后再试'
+ },
+ applicationForm: {
+ title: {
+ appTest: '调试预览',
+ copy: '副本'
+ },
+ form: {
+ appName: {
+ label: '名称',
+ placeholder: '请输入应用名称',
+ requiredMessage: '请输入应用名称'
+ },
+ appDescription: {
+ label: '描述',
+ placeholder: '描述该应用的应用场景及用途,如:XXX 小助手回答用户提出的 XXX 产品使用问题'
+ },
+ appType: {
+ label: '类型',
+ simplePlaceholder: '适合新手创建小助手',
+ workflowPlaceholder: '适合高级用户自定义小助手的工作流'
+ },
+ appTemplate: {
+ blankApp: '空白应用',
+ assistantApp: '知识库问答助手'
+ },
+ aiModel: {
+ label: 'AI 模型',
+ placeholder: '请选择 AI 模型'
+ },
+ roleSettings: {
+ label: '系统角色',
+ placeholder: '你是 xxx 小助手'
+ },
+ prompt: {
+ label: '提示词',
+ noReferences: ' (无引用知识库)',
+ references: ' (引用知识库)',
+ placeholder: '请输入提示词',
+ requiredMessage: '请输入提示词',
+ tooltip:
+ '通过调整提示词内容,可以引导大模型聊天方向,该提示词会被固定在上下文的开头,可以使用变量。',
+ noReferencesTooltip:
+ '通过调整提示词内容,可以引导大模型聊天方向,该提示词会被固定在上下文的开头。可以使用变量:{question} 是用户提出问题的占位符。',
+ referencesTooltip:
+ '通过调整提示词内容,可以引导大模型聊天方向,该提示词会被固定在上下文的开头。可以使用变量:{data} 是引用知识库中分段的占位符;{question} 是用户提出问题的占位符。',
+ defaultPrompt: `已知信息:{data}
+用户问题:{question}
+回答要求:
+ - 请使用中文回答用户问题`
+ },
+ historyRecord: {
+ label: '历史聊天记录'
+ },
+ relatedKnowledge: {
+ label: '关联知识库',
+ placeholder: '关联的知识库展示在这里'
+ },
+ multipleRoundsDialogue: '多轮对话',
+
+ prologue: '开场白',
+ defaultPrologue:
+ '您好,我是 XXX 小助手,您可以向我提出 XXX 使用问题。\n- XXX 主要功能有什么?\n- XXX 如何收费?\n- 需要转人工服务',
+
+ problemOptimization: {
+ label: '问题优化',
+ tooltip: '根据历史聊天优化完善当前问题,更利于匹配知识点。'
+ },
+ voiceInput: {
+ label: '语音输入',
+ placeholder: '请选择语音识别模型',
+ requiredMessage: '请选择语音输入模型',
+ autoSend: '自动发送'
+ },
+ voicePlay: {
+ label: '语音播放',
+ placeholder: '请选择语音合成模型',
+ requiredMessage: '请选择语音播放模型',
+ autoPlay: '自动播放',
+ browser: '浏览器播放(免费)',
+ tts: 'TTS模型',
+ listeningTest: '试听'
+ },
+ reasoningContent: {
+ label: '输出思考',
+ tooltip: '请根据模型返回的思考标签设置,标签中间的内容将会认定为思考过程',
+ start: '开始',
+ end: '结束'
+ }
+ },
+ buttons: {
+ publish: '保存并发布',
+
+ addModel: '添加模型'
+ },
+
+ dialog: {
+ addDataset: '添加关联知识库',
+ addDatasetPlaceholder: '所选知识库必须使用相同的 Embedding 模型',
+ selected: '已选',
+ countDataset: '个知识库',
+
+ selectSearchMode: '检索模式',
+ vectorSearch: '向量检索',
+ vectorSearchTooltip: '向量检索是一种基于向量相似度的检索方式,适用于知识库中的大数据量场景。',
+ fullTextSearch: '全文检索',
+ fullTextSearchTooltip:
+ '全文检索是一种基于文本相似度的检索方式,适用于知识库中的小数据量场景。',
+ hybridSearch: '混合检索',
+ hybridSearchTooltip:
+ '混合检索是一种基于向量和文本相似度的检索方式,适用于知识库中的中等数据量场景。',
+ similarityThreshold: '相似度高于',
+ similarityTooltip: '相似度越高相关性越强。',
+ topReferences: '引用分段数 TOP',
+ maxCharacters: '最多引用字符数',
+ noReferencesAction: '无引用知识库分段时',
+ continueQuestioning: '继续向 AI 模型提问',
+ provideAnswer: '指定回答内容',
+ designated_answer:
+ '你好,我是 XXX 小助手,我的知识库只包含了 XXX 产品相关知识,请重新描述您的问题。',
+ defaultPrompt1:
+ '()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在',
+ defaultPrompt2: '标签中'
+ }
+ },
+ applicationAccess: {
+ title: '应用接入',
+ wecom: '企业微信应用',
+ wecomTip: '打造企业微信智能应用',
+ dingtalk: '钉钉应用',
+ dingtalkTip: '打造钉钉智能应用',
+ wechat: '公众号',
+ wechatTip: '打造公众号智能应用',
+ lark: '飞书应用',
+ larkTip: '打造飞书智能应用',
+ slack: 'Slack',
+ slackTip: '打造 Slack 智能应用',
+ setting: '配置',
+ callback: '回调地址',
+ callbackTip: '请输入回调地址',
+ wecomPlatform: '企业微信后台',
+ wechatPlatform: '微信公众平台',
+ dingtalkPlatform: '钉钉开放平台',
+ larkPlatform: '飞书开放平台',
+ wecomSetting: {
+ title: '企业微信应用配置',
+ cropId: '企业 ID',
+ cropIdPlaceholder: '请输入企业 ID',
+ agentIdPlaceholder: '请输入Agent ID',
+ secretPlaceholder: '请输入Secret',
+ tokenPlaceholder: '请输入Token',
+ encodingAesKeyPlaceholder: '请输入EncodingAESKey',
+ authenticationSuccessful: '认证成功',
+ urlInfo: '-应用管理-自建-创建的应用-接收消息-设置 API 接收的 "URL" 中'
+ },
+ dingtalkSetting: {
+ title: '钉钉应用配置',
+ clientIdPlaceholder: '请输入Client ID',
+ clientSecretPlaceholder: '请输入Client Secret',
+ urlInfo: '-机器人页面,设置 "消息接收模式" 为 HTTP模式 ,并把上面URL填写到"消息接收地址"中'
+ },
+ wechatSetting: {
+ title: '公众号应用配置',
+ appId: '开发者ID (APP ID)',
+ appIdPlaceholder: '请输入开发者ID (APP ID)',
+ appSecret: '开发者密钥 (APP SECRET)',
+ appSecretPlaceholder: '请输入开发者密钥 (APP SECRET)',
+ token: '令牌 (TOKEN)',
+ tokenPlaceholder: '请输入令牌 (TOKEN)',
+ aesKey: '消息加解密密钥',
+ aesKeyPlaceholder: '请输入消息加解密密钥',
+ urlInfo: '-设置与开发-基本配置-服务器配置的 "服务器地址URL" 中'
+ },
+ larkSetting: {
+ title: '飞书应用配置',
+ appIdPlaceholder: '请输入App ID',
+ appSecretPlaceholder: '请输入App Secret',
+ verificationTokenPlaceholder: '请输入Verification Token',
+ urlInfo: '-事件与回调-事件配置-配置订阅方式的 "请求地址" 中'
+ },
+ slackSetting: {
+ title: 'Slack 应用配置',
+ signingSecretPlaceholder: '请输入 Signing Secret',
+ botUserTokenPlaceholder: '请输入 Bot User Token'
+ },
+ copyUrl: '复制链接填入到'
+ },
+ hitTest: {
+ title: '命中测试',
+ text: '针对用户提问调试段落匹配情况,保障回答效果。',
+ emptyMessage1: '命中段落显示在这里',
+ emptyMessage2: '没有命中的分段'
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/dataset.ts b/ui/src/locales/lang/zh-CN/views/dataset.ts
new file mode 100644
index 000000000..5ca010525
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/dataset.ts
@@ -0,0 +1,84 @@
+export default {
+ title: '知识库',
+ createDataset: '创建知识库',
+ general: '通用型',
+ web: 'web 站点',
+ relatedApplications: '关联应用',
+ document_count: '文档数',
+ relatedApp_count: '关联应用',
+ searchBar: {
+ placeholder: '按名称搜索'
+ },
+ setting: {
+ vectorization: '向量化',
+ sync: '同步'
+ },
+ tip: {
+ professionalMessage: '社区版最多支持 50 个知识库,如需拥有更多知识库,请升级为专业版。',
+ syncSuccess: '同步任务发送成功',
+ updateModeMessage: '修改知识库向量模型后,需要对知识库向量化,是否继续保存?'
+ },
+ delete: {
+ confirmTitle: '是否删除知识库:',
+ confirmMessage1: '此知识库关联',
+ confirmMessage2: '个应用,删除后无法恢复,请谨慎操作。'
+ },
+
+ datasetForm: {
+ title: {
+ info: '基本信息'
+ },
+ form: {
+ datasetName: {
+ label: '知识库名称',
+ placeholder: '请输入知识库名称',
+ requiredMessage: '请输入应用名称'
+ },
+ datasetDescription: {
+ label: '知识库描述',
+ placeholder:
+ '描述知识库的内容,详尽的描述将帮助AI能深入理解该知识库的内容,能更准确的检索到内容,提高该知识库的命中率。',
+ requiredMessage: '请输入知识库描述'
+ },
+ EmbeddingModel: {
+ label: '向量模型',
+ placeholder: '请选择向量模型',
+ requiredMessage: '请输入Embedding模型'
+ },
+ datasetType: {
+ label: '知识库类型',
+ generalInfo: '上传本地文档',
+ webInfo: '同步Web网站文本数据'
+ },
+ source_url: {
+ label: 'Web 根地址',
+ placeholder: '请输入 Web 根地址',
+ requiredMessage: ' 请输入 Web 根地址'
+ },
+ selector: {
+ label: '选择器',
+ placeholder: '默认为 body,可输入 .classname/#idname/tagname'
+ }
+ }
+ },
+ ResultSuccess: {
+ title: '知识库创建成功',
+ paragraph: '分段',
+ paragraph_count: '个分段',
+ documentList: '文档列表',
+ loading: '导入中',
+ buttons: {
+ toDataset: '返回知识库列表',
+ toDocument: '前往文档'
+ }
+ },
+ syncWeb: {
+ title: '同步知识库',
+ syncMethod: '同步方式',
+ replace: '替换同步',
+ replaceText: '重新获取 Web 站点文档,覆盖替换本地知识库中的文档',
+ complete: '整体同步',
+ completeText: '先删除本地知识库所有文档,重新获取 Web 站点文档',
+ tip: '注意:所有同步都会删除已有数据重新获取新数据,请谨慎操作。'
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/document.ts b/ui/src/locales/lang/zh-CN/views/document.ts
new file mode 100644
index 000000000..154ca5745
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/document.ts
@@ -0,0 +1,174 @@
+export default {
+ uploadDocument: '上传文档',
+ importDocument: '导入文档',
+ syncDocument: '同步文档',
+ selected: '已选',
+ items: '项',
+ searchBar: {
+ placeholder: '按 文档名称 搜索'
+ },
+ setting: {
+ migration: '迁移',
+ cancelGenerateQuestion: '取消生成问题',
+ cancelVectorization: '取消向量化',
+ cancelGenerate: '取消生成',
+ export: '导出'
+ },
+ tip: {
+ saveMessage: '当前的更改尚未保存,确认退出吗?',
+ cancelSuccess: '批量取消成功',
+ sendMessage: '发送成功',
+ vectorizationSuccess: '批量向量化成功',
+ nameMessage: '文件名称不能为空!',
+ importMessage: '导入成功',
+ migrationSuccess: '迁移成功'
+ },
+ upload: {
+ selectFile: '选择文件',
+ selectFiles: '选择文件夹',
+ uploadMessage: '拖拽文件至此上传或',
+ formats: '支持格式:',
+ requiredMessage: '请上传文件',
+ errorMessage1: '文件大小超过 100MB',
+ errorMessage2: '文件格式不支持',
+ errorMessage3: '文件不能为空',
+ errorMessage4: '每次最多上传50个文件',
+ template: '模版',
+ download: '下载'
+ },
+
+ fileType: {
+ txt: {
+ label: '文本文件',
+ tip1: '1、文件上传前,建议规范文件的分段标识',
+ tip2: '2、每次最多上传 50 个文件,每个文件不超过 100MB'
+ },
+ table: {
+ label: '表格',
+ tip1: '1、点击下载对应模版并完善信息:',
+ tip2: '2、第一行必须是列标题,且列标题必须是有意义的术语,表中每条记录将作为一个分段',
+ tip3: '3、上传的表格文件中每个 sheet 会作为一个文档,sheet名称为文档名称',
+ tip4: '4、每次最多上传 50 个文件,每个文件不超过 100MB'
+ },
+ QA: {
+ label: 'QA 问答对',
+ tip1: '1、点击下载对应模版并完善信息',
+ tip2: '2、上传的表格文件中每个 sheet 会作为一个文档,sheet名称为文档名称',
+ tip3: '3、每次最多上传 50 个文件,每个文件不超过 100MB'
+ }
+ },
+ setRules: {
+ title: {
+ setting: '设置分段规则',
+ preview: '分段预览'
+ },
+ intelligent: {
+ label: '智能分段(推荐)',
+ text: '不了解如何设置分段规则推荐使用智能分段'
+ },
+ advanced: {
+ label: '高级分段',
+ text: '用户可根据文档规范自行设置分段标识符、分段长度以及清洗规则'
+ },
+ patterns: {
+ label: '分段标识',
+ tooltip: '按照所选符号先后顺序做递归分割,分割结果超出分段长度将截取至分段长度。',
+ placeholder: '请选择'
+ },
+ limit: {
+ label: '分段长度'
+ },
+ with_filter: {
+ label: '自动清洗',
+ text: '去掉重复多余符号空格、空行、制表符'
+ },
+ checkedConnect: {
+ label: '导入时添加分段标题为关联问题(适用于标题为问题的问答对)'
+ }
+ },
+ buttons: {
+ prev: '上一步',
+ next: '下一步',
+ import: '开始导入',
+ preview: '生成预览'
+ },
+ table: {
+ name: '文件名称',
+ char_length: '字符数',
+ paragraph: '分段',
+ all: '全部',
+ updateTime: '更新时间'
+ },
+ fileStatus: {
+ label: '文件状态',
+ SUCCESS: '成功',
+ FAILURE: '失败',
+ EMBEDDING: '索引中',
+ PENDING: '排队中',
+ GENERATE: '生成中',
+ SYNC: '同步中',
+ REVOKE: '取消中',
+ finish: '完成'
+ },
+ enableStatus: {
+ label: '启用状态',
+ enable: '开启',
+ close: '关闭'
+ },
+ sync: {
+ label: '同步',
+ confirmTitle: '确认同步文档?',
+ confirmMessage1: '同步将删除已有数据重新获取新数据,请谨慎操作。',
+ confirmMessage2: '无法同步,请先去设置文档 URL地址',
+ successMessage: '同步文档成功'
+ },
+ delete: {
+ confirmTitle1: '是否批量删除',
+ confirmTitle2: '个文档?',
+ confirmMessage: '所选文档中的分段会跟随删除,请谨慎操作。',
+ successMessage: '批量删除成功',
+ confirmTitle3: '是否删除文档:',
+ confirmMessage1: '此文档下的',
+ confirmMessage2: '个分段都会被删除,请谨慎操作。'
+ },
+ form: {
+ source_url: {
+ label: '文档地址',
+ placeholder: '请输入文档地址,一行一个,地址不正确文档会导入失败。',
+ requiredMessage: '请输入文档地址'
+ },
+ selector: {
+ label: '选择器',
+ placeholder: '默认为 body,可输入 .classname/#idname/tagname'
+ },
+ hit_handling_method: {
+ label: '命中处理方式',
+ tooltip: '用户提问时,命中文档下的分段时按照设置的方式进行处理。'
+ },
+ similarity: {
+ label: '相似度高于',
+ placeholder: '直接返回分段内容',
+ requiredMessage: '请输入相似度'
+ }
+ },
+ hitHandlingMethod: {
+ optimization: '模型优化',
+ directly_return: '直接回答'
+ },
+ generateQuestion: {
+ title: '生成问题',
+ successMessage: '生成问题成功',
+ tip1: '提示词中的 {data} 为分段内容的占位符,执行时替换为分段内容发送给 AI 模型;',
+ tip2: 'AI 模型根据分段内容生成相关问题,请将生成的问题放至',
+ tip3: '标签中,系统会自动关联标签中的问题;',
+ tip4: '生成效果依赖于所选模型和提示词,用户可自行调整至最佳效果。',
+ prompt1: `内容:{data}\n\n请总结上面的内容,并根据内容总结生成 5 个问题。\n回答要求:\n- 请只输出问题;\n- 请将每个问题放置`,
+ prompt2: `标签中。`
+ },
+ feishu: {
+ selectDocument: '选择文档',
+ tip1: '仅支持文档和表格类型,文档会根据标题分段,表格会转为Markdown格式后再分段。',
+ tip2: '系统不存储原始文档,导入文档前,建议规范文档的分段标识。',
+ allCheck: '全选'
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/function-lib.ts b/ui/src/locales/lang/zh-CN/views/function-lib.ts
new file mode 100644
index 000000000..b0767b644
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/function-lib.ts
@@ -0,0 +1,77 @@
+export default {
+ title: '函数库',
+ internalTitle: '内置函数',
+ added: '已添加',
+ createFunction: '创建函数',
+ editFunction: '编辑函数',
+ copyFunction: '复制函数',
+ importFunction: '导入函数',
+ searchBar: {
+ placeholder: '按函数名称搜索'
+ },
+ setting: {
+ disabled: '禁用'
+ },
+ tip: {
+ saveMessage: '当前的更改尚未保存,确认退出吗?'
+ },
+ delete: {
+ confirmTitle: '是否删除函数:',
+ confirmMessage: '删除后,引用了该函数的应用提问时会报错 ,请谨慎操作。'
+ },
+ disabled: {
+ confirmTitle: '是否禁用函数:',
+ confirmMessage: '禁用后,引用了该函数的应用提问时会报错 ,请谨慎操作。'
+ },
+ functionForm: {
+ title: {
+ copy: '副本',
+ baseInfo: '基础信息'
+ },
+ form: {
+ functionName: {
+ label: '名称',
+ placeholder: '请输入函数名称',
+ requiredMessage: '请输入函数名称'
+ },
+ functionDescription: {
+ label: '描述',
+ placeholder: '请输入函数的描述'
+ },
+ permission_type: {
+ label: '权限',
+ requiredMessage: '请选择'
+ },
+ paramName: {
+ label: '参数名',
+ placeholder: '请输入参数名',
+ requiredMessage: '请输入参数名'
+ },
+ dataType: {
+ label: '数据类型'
+ },
+ source: {
+ label: '来源',
+ custom: '自定义',
+ reference: '引用参数'
+ },
+ required: {
+ label: '是否必填'
+ },
+ param: {
+ paramInfo1: '使用函数时显示',
+ paramInfo2: '使用函数时不显示',
+ code: '函数内容(Python)',
+ selectPlaceholder: '请选择参数',
+ inputPlaceholder: '请输入参数值',
+ },
+ debug: {
+ run: '运行',
+ output: '输出',
+ runResult: '运行结果',
+ runSuccess: '运行成功',
+ runFailed: '运行失败'
+ }
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/index.ts b/ui/src/locales/lang/zh-CN/views/index.ts
new file mode 100644
index 000000000..b8c85b031
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/index.ts
@@ -0,0 +1,34 @@
+import notFound from './404'
+import application from './application'
+import applicationOverview from './application-overview'
+import dataset from './dataset'
+import system from './system'
+import functionLib from './function-lib'
+import user from './user'
+import team from './team'
+import template from './template'
+import document from './document'
+import paragraph from './paragraph'
+import problem from './problem'
+import log from './log'
+import applicationWorkflow from './application-workflow'
+import login from './login'
+import operateLog from './operate-log'
+export default {
+ notFound,
+ application,
+ applicationOverview,
+ dataset,
+ system,
+ functionLib,
+ user,
+ team,
+ template,
+ document,
+ paragraph,
+ problem,
+ log,
+ applicationWorkflow,
+ login,
+ operateLog
+}
diff --git a/ui/src/locales/lang/zh-CN/views/log.ts b/ui/src/locales/lang/zh-CN/views/log.ts
new file mode 100644
index 000000000..c866a9551
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/log.ts
@@ -0,0 +1,41 @@
+export default {
+ title: '对话日志',
+ delete: {
+ confirmTitle: '是否删除问题:',
+ confirmMessage1: '删除问题关联的',
+ confirmMessage2: '个分段会被取消关联,请谨慎操作。'
+ },
+ buttons: {
+ clearStrategy: '清除策略',
+ prev: '上一条',
+ next: '下一条'
+ },
+ table: {
+ abstract: '摘要',
+ chat_record_count: '对话提问数',
+ user: '用户',
+ feedback: {
+ label: '用户反馈',
+ star: '赞同',
+ trample: '反对'
+ },
+ mark: '改进标注',
+ recenTimes: '最近对话时间'
+ },
+ addToDataset: '添加至知识库',
+ daysText: '天之前的对话记录',
+ selectDataset: '选择知识库',
+ selectDatasetPlaceholder: '请选择知识库',
+ saveToDocument: '保存至文档',
+ documentPlaceholder: '请选择文档',
+ editContent: '修改内容',
+ editMark: '修改标注',
+ form: {
+ content: {
+ placeholder: '请输入内容'
+ },
+ title: {
+ placeholder: '请给当前内容设置一个标题,以便管理查看'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/login.ts b/ui/src/locales/lang/zh-CN/views/login.ts
new file mode 100644
index 000000000..c3ccf725e
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/login.ts
@@ -0,0 +1,24 @@
+export default {
+ title: '普通登录',
+ jump_tip: '即将跳转至认证源页面进行认证',
+ jump: '跳转',
+ resetPassword: '修改密码',
+ forgotPassword: '忘记密码',
+ userRegister: '用户注册',
+ buttons: {
+ login: '登录',
+ register: '注册',
+ backLogin: '返回登录',
+ checkCode: '立即验证'
+ },
+ newPassword: '新密码',
+ enterPassword: '请输入修改密码',
+ useEmail: '使用邮箱',
+ moreMethod: '更多登录方式',
+ verificationCode: {
+ placeholder: '请输入验证码',
+ getVerificationCode: '获取验证码',
+ successMessage: '验证码发送成功',
+ resend: '重新发送'
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/operate-log.ts b/ui/src/locales/lang/zh-CN/views/operate-log.ts
new file mode 100644
index 000000000..880623057
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/operate-log.ts
@@ -0,0 +1,30 @@
+export default {
+ title: '操作日志',
+ table: {
+ menu: {
+ label: '操作菜单'
+ },
+ operate: {
+ label: '操作'
+ },
+ user: {
+ label: '操作用户'
+ },
+ status: {
+ label: '状态',
+ success: '成功',
+ fail: '失败',
+ all: '全部'
+ },
+ ip_address: {
+ label: 'IP地址'
+ },
+ opt: {
+ label: 'API详情'
+ },
+ operateTime: {
+ label: '操作时间'
+ }
+ },
+ close: '关闭'
+}
diff --git a/ui/src/locales/lang/zh-CN/views/paragraph.ts b/ui/src/locales/lang/zh-CN/views/paragraph.ts
new file mode 100644
index 000000000..cf38b908f
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/paragraph.ts
@@ -0,0 +1,32 @@
+export default {
+ title: '段落',
+ paragraph_count: '段落',
+ editParagraph: '编辑分段',
+ addParagraph: '添加分段',
+ paragraphDetail: '分段详情',
+ character_count: '个字符',
+ setting: {
+ batchSelected: '批量选择',
+ cancelSelected: '取消选择'
+ },
+ delete: {
+ confirmTitle: '是否删除段落:',
+ confirmMessage: '删除后无法恢复,请谨慎操作。'
+ },
+ relatedProblem: {
+ title: '关联问题',
+ placeholder: '请选择问题'
+ },
+ form: {
+ paragraphTitle: {
+ label: '分段标题',
+ placeholder: '请输入分段标题'
+ },
+ content: {
+ label: '分段内容',
+ placeholder: '请输入分段内容',
+ requiredMessage1: '请输入分段内容',
+ requiredMessage2: '内容最多不超过 100000 个字'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/problem.ts b/ui/src/locales/lang/zh-CN/views/problem.ts
new file mode 100644
index 000000000..bb53275aa
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/problem.ts
@@ -0,0 +1,37 @@
+export default {
+ title: '问题',
+ createProblem: '创建问题',
+ detailProblem: '问题详情',
+ quickCreateProblem: '快速创建问题',
+ quickCreateName: '问题',
+ tip: {
+ placeholder: '请输入问题,支持输入多个,一行一个。',
+ errorMessage: '问题不能为空!',
+ requiredMessage: '请输入问题',
+ relatedSuccess:'批量关联分段成功'
+ },
+
+ setting: {
+ batchDelete: '批量删除',
+ cancelRelated: '取消关联'
+ },
+ searchBar: {
+ placeholder: '按名称搜索'
+ },
+ table: {
+ paragraph_count: '关联分段数',
+ updateTime: '更新时间'
+ },
+ delete: {
+ confirmTitle: '是否删除问题:',
+ confirmMessage1: '删除问题关联的',
+ confirmMessage2: '个分段会被取消关联,请谨慎操作。'
+ },
+ relateParagraph: {
+ title: '关联分段',
+ selectDocument: '选择文档',
+ placeholder: '按 文档名称 搜索',
+ selectedParagraph: '已选分段',
+ count: '个'
+ },
+}
diff --git a/ui/src/locales/lang/zh-CN/views/system.ts b/ui/src/locales/lang/zh-CN/views/system.ts
new file mode 100644
index 000000000..9ce23d90d
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/system.ts
@@ -0,0 +1,151 @@
+export default {
+ title: '系统设置',
+ test: '测试连接',
+ testSuccess: '测试连接成功',
+ testFailed: '测试连接失败',
+ password: '密码',
+ authentication: {
+ title: '登录认证',
+ ldap: {
+ title: 'LDAP',
+ address: 'LDAP 地址',
+ serverPlaceholder: '请输入LDAP 地址',
+ bindDN: '绑定DN',
+ bindDNPlaceholder: '请输入绑定 DN',
+ ou: '用户OU',
+ ouPlaceholder: '请输入用户 OU',
+ ldap_filter: '用户过滤器',
+ ldap_filterPlaceholder: '请输入用户过滤器',
+ ldap_mapping: 'LDAP 属性映射',
+ ldap_mappingPlaceholder: '请输入 LDAP 属性映射',
+ enableAuthentication: '启用 LDAP 认证'
+ },
+ cas: {
+ title: 'CAS',
+ ldpUri: 'ldpUri',
+ ldpUriPlaceholder: '请输入ldpUri',
+ validateUrl: '验证地址',
+ validateUrlPlaceholder: '请输入验证地址',
+ redirectUrl: '回调地址',
+ redirectUrlPlaceholder: '请输入回调地址',
+ enableAuthentication: '启用 CAS 认证'
+ },
+ oidc: {
+ title: 'OIDC',
+ authEndpoint: '授权端地址',
+ authEndpointPlaceholder: '请输入授权端地址',
+ tokenEndpoint: 'Token端地址',
+ tokenEndpointPlaceholder: '请输入 Token 端地址',
+ userInfoEndpoint: '用户信息端地址',
+ userInfoEndpointPlaceholder: '请输入用户信息端地址',
+ scopePlaceholder: '请输入连接范围',
+ clientId: '客户端 ID',
+ clientIdPlaceholder: '请输入客户端 ID',
+ clientSecret: '客户端密钥',
+ clientSecretPlaceholder: '请输入客户端密钥',
+ logoutEndpoint: '注销端地址',
+ logoutEndpointPlaceholder: '请输入注销端地址',
+ redirectUrl: '回调地址',
+ redirectUrlPlaceholder: '请输入回调地址',
+ enableAuthentication: '启用 OIDC 认证'
+ },
+
+ oauth2: {
+ title: 'OAuth2',
+ authEndpoint: '授权端地址',
+ authEndpointPlaceholder: '请输入授权端地址',
+ tokenEndpoint: 'Token 端地址',
+ tokenEndpointPlaceholder: '请输入 Token 端地址',
+ userInfoEndpoint: '用户信息端地址',
+ userInfoEndpointPlaceholder: '请输入用户信息端地址',
+ scope: '连接范围',
+ scopePlaceholder: '请输入连接范围',
+ clientId: '客户端 ID',
+ clientIdPlaceholder: '请输入客户端 ID',
+ clientSecret: '客户端密钥',
+ clientSecretPlaceholder: '请输入客户端密钥',
+ redirectUrl: '回调地址',
+ redirectUrlPlaceholder: '请输入回调地址',
+ filedMapping: '字段映射',
+ filedMappingPlaceholder: '请输入字段映射',
+ enableAuthentication: '启用 OAuth2 认证'
+ },
+ scanTheQRCode: {
+ title: '扫码登录',
+ wecom: '企业微信',
+ dingtalk: '钉钉',
+ lark: '飞书',
+ effective: '有效',
+ alreadyTurnedOn: '已开启',
+ notEnabled: '未开启',
+ validate: '校验',
+ validateSuccess: '校验成功',
+ validateFailed: '校验失败',
+ validateFailedTip: '请填写所有必填项并确保格式正确',
+ appKeyPlaceholder: '请输入 App Key',
+ appSecretPlaceholder: '请输入 App Secret',
+ corpIdPlaceholder: '请输入 Corp Id',
+ agentIdPlaceholder: '请输入 Agent Id',
+ callbackWarning: '请输入有效的 URL 地址',
+ larkQrCode: '飞书扫码登录',
+ dingtalkQrCode: '钉钉扫码登录',
+ setting: '设置',
+ access: '接入'
+ }
+ },
+ theme: {
+ title: '外观设置',
+ platformDisplayTheme: '平台显示主题',
+ customTheme: '自定义主题',
+ platformLoginSettings: '平台登录设置',
+ custom: '自定义',
+ pagePreview: '页面预览',
+ default: '默认',
+ restoreDefaults: '恢复默认',
+ orange: '活力橙',
+ green: '松石绿',
+ purple: '神秘紫',
+ red: '胭脂红',
+ loginBackground: '登录背景图',
+ loginLogo: '登录 Logo',
+ websiteLogo: '网站 Logo',
+ replacePicture: '替换图片',
+ websiteLogoTip: '顶部网站显示的 Logo,建议尺寸 48*48,支持 JPG、PNG、GIF,大小不超过 10MB',
+ loginLogoTip: '登录页面右侧 Logo,建议尺寸 204*52,支持 JPG、PNG、GIF,大小不超过 10 MB',
+ loginBackgroundTip:
+ '左侧背景图,矢量图建议尺寸 576*900,位图建议尺寸 1152*1800;支持 JPG、PNG、GIF,大小不超过 10 MB',
+ websiteName: '网站名称',
+ websiteNamePlaceholder: '请输入网站名称',
+ websiteNameTip: '显示在网页 Tab 的平台名称',
+ websiteSlogan: '欢迎语',
+ websiteSloganPlaceholder: '请输入欢迎语',
+ websiteSloganTip: '产品 Logo 下的欢迎语',
+ defaultSlogan: '欢迎使用 MaxKB 智能知识库问答系统',
+ logoDefaultTip: '默认为 MaxKB 登录界面,支持自定义设置',
+ defaultTip: '默认为 MaxKB 平台界面,支持自定义设置',
+ platformSetting: '平台设置',
+ showUserManual: '显示用户手册',
+ showForum: '显示论坛求助',
+ showProject: '显示项目地址',
+ urlPlaceholder: '请输入 URL 地址',
+ abandonUpdate: '放弃更新',
+ saveAndApply: '保存并应用',
+ fileMessageError: '文件大小超过 10M',
+ saveSuccess: '外观设置成功'
+ },
+ email: {
+ title: '邮箱设置',
+ smtpHost: 'SMTP Host',
+ smtpHostPlaceholder: '请输入 SMTP Host',
+ smtpPort: 'SMTP Port',
+ smtpPortPlaceholder: '请输入 SMTP Port',
+ smtpUser: 'SMTP 账户',
+ smtpUserPlaceholder: '请输入 SMTP 账户',
+ sendEmail: '发件人邮箱',
+ sendEmailPlaceholder: '请输入发件人邮箱',
+ smtpPassword: '发件人密码',
+ smtpPasswordPlaceholder: '请输入发件人密码',
+ enableSSL: '启用 SSL(如果 SMTP 端口是 465,通常需要启用 SSL)',
+ enableTLS: '启用 TLS(如果 SMTP 端口是 587,通常需要启用 TLS)'
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/team.ts b/ui/src/locales/lang/zh-CN/views/team.ts
new file mode 100644
index 000000000..58a2bc30c
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/team.ts
@@ -0,0 +1,31 @@
+export default {
+ title: '团队成员',
+ member: '成员',
+ manage: '所有者',
+ permissionSetting: '权限设置',
+ addMember: '添加成员',
+ addSubTitle: '成员登录后可以访问到您授权的数据。',
+ searchBar: {
+ placeholder: '请输入用户名搜索'
+ },
+ delete: {
+ button: '移除',
+ confirmTitle: '是否移除成员:',
+ confirmMessage: '移除后将会取消成员拥有的知识库和应用权限。'
+ },
+ setting: {
+ management: '管理',
+ check: '查看'
+ },
+ teamForm: {
+ form: {
+ userName: {
+ label: '用户名/邮箱',
+ placeholder: '请输入成员的用户名或邮箱',
+ requiredMessage: '请输入用户名/邮箱'
+ },
+
+ },
+
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/template.ts b/ui/src/locales/lang/zh-CN/views/template.ts
new file mode 100644
index 000000000..84241990d
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/template.ts
@@ -0,0 +1,83 @@
+export default {
+ title: '模型设置',
+ provider: '供应商',
+ providerPlaceholder: '选择供应商',
+ addModel: '添加模型',
+ searchBar: {
+ placeholder: '按名称搜索'
+ },
+ delete: {
+ confirmTitle: '删除模型',
+ confirmMessage: '是否删除模型:'
+ },
+ tip: {
+ createSuccessMessage: '创建模型成功',
+ createErrorMessage: '基础信息有填写错误',
+ errorMessage: '变量已存在: ',
+ emptyMessage1: '请先选择基础信息的模型类型和基础模型',
+ emptyMessage2: '所选模型不支持参数设置',
+ updateSuccessMessage: '修改模型成功',
+ saveSuccessMessage: '模型参数保存成功',
+ downloadError: '下载失败',
+ noModel: '模型在Ollama不存在'
+ },
+ model: {
+ allModel: '全部模型',
+ publicModel: '公有模型',
+ privateModel: '私有模型',
+ LLM: '大语言模型',
+ EMBEDDING: '向量模型',
+ RERANKER: '重排模型',
+ STT: '语音识别',
+ TTS: '语音合成',
+ IMAGE: '视觉模型',
+ TTI: '图片生成'
+ },
+ templateForm: {
+ title: {
+ baseInfo: '基础信息',
+ advancedInfo: '高级设置',
+ modelParams: '模型参数',
+ editParam: '编辑参数',
+ addParam: '添加参数',
+ paramSetting: '模型参数设置',
+ apiParamPassing: '接口传参'
+ },
+ form: {
+ templateName: {
+ label: '模型名称',
+ placeholder: '请给基础模型设置一个名称',
+ tooltip: 'MaxKB 中自定义的模型名称',
+ requiredMessage: '模型名称不能为空'
+ },
+ permissionType: {
+ label: '权限',
+ privateDesc: '仅当前用户使用',
+ publicDesc: '所有用户都可使用',
+ requiredMessage: '权限不能为空'
+ },
+ model_type: {
+ label: '模型类型',
+ placeholder: '请选择模型类型',
+ tooltip1: '大语言模型:在应用中与AI对话的推理模型。',
+ tooltip2: '向量模型:在知识库中对文档内容进行向量化的模型。',
+ tooltip3: '语音识别:在应用中开启语音识别后用于语音转文字的模型。',
+ tooltip4: '语音合成:在应用中开启语音播放后用于文字转语音的模型。',
+ tooltip5: '重排模型:在高级编排应用中使用多路召回时,对候选分段进行重新排序的模型。',
+ tooltip6: '视觉模型:在高级编排应用中用于图片理解的视觉模型。',
+ tooltip7: '图片生成:在高级编排应用中用于图片生成的视觉模型。',
+ requiredMessage: '模型类型不能为空'
+ },
+ base_model: {
+ label: '基础模型',
+ tooltip: '列表中未列出的模型,直接输入模型名称,回车即可添加',
+ placeholder: '自定义输入基础模型后回车即可',
+ requiredMessage: '基础模型不能为空'
+ }
+ }
+ },
+ download: {
+ downloading: '正在下载中',
+ cancelDownload: '取消下载'
+ }
+}
diff --git a/ui/src/locales/lang/zh-CN/views/user.ts b/ui/src/locales/lang/zh-CN/views/user.ts
new file mode 100644
index 000000000..4e2a8760f
--- /dev/null
+++ b/ui/src/locales/lang/zh-CN/views/user.ts
@@ -0,0 +1,68 @@
+export default {
+ title: '用户管理',
+ createUser: '创建用户',
+ editUser: '编辑用户',
+ setting: {
+ updatePwd: '修改用户密码'
+ },
+ tip: {
+ professionalMessage: '社区版最多支持 2 个用户,如需拥有更多用户,请升级为专业版。',
+ updatePwdSuccess: '修改用户密码成功'
+ },
+ delete: {
+ confirmTitle: '是否删除用户:',
+ confirmMessage: '删除用户,该用户创建的资源(应用、知识库、模型)都会删除,请谨慎操作。'
+ },
+ disabled: {
+ confirmTitle: '是否禁用函数:',
+ confirmMessage: '禁用后,引用了该函数的应用提问时会报错 ,请谨慎操作。'
+ },
+ userForm: {
+ form: {
+ username: {
+ label: '用户名',
+ placeholder: '请输入用户名',
+ requiredMessage: '请输入用户名',
+ lengthMessage: '长度在 6 到 20 个字符'
+ },
+ nick_name: {
+ label: '姓名',
+ placeholder: '请输入姓名'
+ },
+ email: {
+ label: '邮箱',
+ placeholder: '请输入邮箱',
+ requiredMessage: '请输入邮箱',
+ validatorEmail: '请输入有效邮箱格式!',
+ },
+ phone: {
+ label: '手机号',
+ placeholder: '请输入手机号'
+ },
+ password: {
+ label: '登录密码',
+ placeholder: '请输入密码',
+ requiredMessage: '请输入密码',
+ lengthMessage: '长度在 6 到 20 个字符'
+ },
+ new_password: {
+ label: '新密码',
+ placeholder: '请输入新密码',
+ requiredMessage: '请输入新密码',
+ },
+ re_password: {
+ label: '确认密码',
+ placeholder: '请输入确认密码',
+ requiredMessage: '请输入确认密码',
+ validatorMessage: '密码不一致',
+ }
+ }
+ },
+ source: {
+ label: '用户类型',
+ local: '系统用户',
+ wecom: '企业微信',
+ lark: '飞书',
+ dingtalk: '钉钉'
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/ai-chat.ts b/ui/src/locales/lang/zh-Hant/ai-chat.ts
new file mode 100644
index 000000000..df43dd6f8
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/ai-chat.ts
@@ -0,0 +1,96 @@
+export default {
+ noHistory: '暫無歷史記錄',
+ createChat: '新建對話',
+ history: '歷史記錄',
+ only20history: '僅顯示最近 20 條對話',
+ question_count: '條提問',
+ exportRecords: '導出聊天記錄',
+ chatId: '對話 ID',
+ userInput: '用戶輸入',
+ quote: '引用',
+ download: '點擊下載文件',
+ passwordValidator: {
+ title: '請輸入密碼打開連結',
+ errorMessage1: '密碼不能為空',
+ errorMessage2: '密碼錯誤'
+ },
+ operation: {
+ play: '點擊播放',
+ pause: '停止',
+ regeneration: '換個答案',
+ like: '贊同',
+ cancelLike: '取消贊同',
+ oppose: '反對',
+ cancelOppose: '取消反對',
+ continue: '繼續',
+ stopChat: '停止回答',
+ startChat: '開始回答',
+ },
+ tip: {
+ error500Message: '抱歉,當前正在維護,無法提供服務,請稍後再試!',
+ errorIdentifyMessage: '無法識別用戶身份',
+ errorLimitMessage: '抱歉,您的提問已達最大限制,請明天再來吧!',
+ answerMessage: '抱歉,沒有查找到相關內容,請重新描述您的問題或提供更多資訊。',
+ stopAnswer: '已停止回答',
+ answerLoading: '回答中',
+ recorderTip: `該功能需要使用麥克風,瀏覽器禁止不安全頁面錄音,解決方案如下:
+1、可開啟 https 解決;
+2、若無 https 配置則需要修改瀏覽器安全配置,Chrome 設定如下:
+(1) 地址欄輸入 chrome://flags/#unsafely-treat-insecure-origin-as-secure;
+(2) 將 http 站點配置在文字框中,例如: http://127.0.0.1:8080。
`,
+ recorderError: '錄音失敗',
+ confirm: '我知道了',
+ requiredMessage: '請填寫所有必填欄位',
+ inputParamMessage1: '請在 URL 中填寫參數',
+ inputParamMessage2: '的值',
+ prologueMessage: '抱歉,當前正在維護,無法提供服務,請稍後再試!'
+ },
+ inputPlaceholder: {
+ speaking: '說話中',
+ recorderLoading: '轉文字中',
+ default: '請輸入問題'
+ },
+ uploadFile: {
+ label: '上傳文件',
+ most: '最多',
+ limit: '個,每個文件限制',
+ fileType: '文件類型',
+ tipMessage: '請在文件上傳配置中選擇文件類型',
+ limitMessage1: '最多上傳',
+ limitMessage2: '個文件',
+ sizeLimit: '單個文件大小不能超過',
+ imageMessage: '請解析圖片內容',
+ errorMessage: '上傳失敗'
+ },
+ executionDetails: {
+ title: '執行詳細',
+ paramOutputTooltip: '每個文件僅支持預覽 500 字',
+ audioFile: '語音文件',
+ searchContent: '檢索內容',
+ searchResult: '檢索結果',
+ conditionResult: '判斷結果',
+ currentChat: '本次對話',
+ answer: 'AI 回答',
+ replyContent: '回覆內容',
+ textContent: '文本內容',
+ input: '輸入',
+ output: '輸出',
+ rerankerContent: '重排內容',
+ rerankerResult: '重排結果',
+ paragraph: '段落',
+ noSubmit: '用戶未提交',
+ errMessage: '錯誤日誌'
+ },
+ KnowledgeSource: {
+ title: '知識來源',
+ referenceParagraph: '引用段落',
+ consume: '消耗tokens',
+ consumeTime: '耗時'
+ },
+ paragraphSource: {
+ title: '知識庫引用',
+ question: '用戶問題',
+ optimizationQuestion: '優化後問題'
+ },
+ editTitle: '編輯標題',
+}
diff --git a/ui/src/locales/lang/zh-Hant/common.ts b/ui/src/locales/lang/zh-Hant/common.ts
new file mode 100644
index 000000000..5775f5813
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/common.ts
@@ -0,0 +1,63 @@
+export default {
+ create: '創建',
+ createSuccess: '創建成功',
+ copy: '複製',
+ copySuccess: '複製成功',
+ copyError: '複製失敗',
+ save: '儲存',
+ saveSuccess: '儲存成功',
+ delete: '刪除',
+ deleteSuccess: '刪除成功',
+ setting: '設定',
+ settingSuccess: '設定成功',
+ submit: '提交',
+ submitSuccess: '提交成功',
+ edit: '編輯',
+ editSuccess: '編輯成功',
+ modify: '修改',
+ modifySuccess: '修改成功',
+ cancel: '取消',
+ confirm: '確認',
+ tip: '提示',
+ add: '新增',
+ refresh: '重新整理',
+ search: '搜尋',
+ clear: '清除',
+ professional: '購買專業版',
+ createDate: '創建日期',
+ createTime: '創建時間',
+ operation: '操作',
+ character: '字符',
+ export: '匯出',
+ exportSuccess: '匯出成功',
+ unavailable: '(不可用)',
+ public: '公有',
+ private: '私有',
+ paramSetting: '參數設定',
+ creator: '建立者',
+ author: '作者',
+ debug: '調試',
+ required: '必填',
+ noData: '暂无数据',
+ result: '結果',
+ fileUpload: {
+ document: '文檔',
+ image: '圖片',
+ audio: '音頻',
+ video: '視頻'
+ },
+ status: {
+ label: '狀態',
+ enableSuccess: '啟用成功',
+ disableSuccess: '停用成功'
+ },
+ inputPlaceholder: '請輸入',
+ title: '標題',
+ content: '内容',
+ param: {
+ outputParam: '輸出參數',
+ inputParam: '輸入參數',
+ initParam: '啟動參數',
+ },
+ rename: '重命名'
+}
diff --git a/ui/src/locales/lang/zh-Hant/components.ts b/ui/src/locales/lang/zh-Hant/components.ts
new file mode 100644
index 000000000..da25a3709
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/components.ts
@@ -0,0 +1,12 @@
+export default {
+ quickCreatePlaceholder: '快速創建空白文檔',
+ quickCreateName: '文檔名稱',
+ noData: '無匹配数据',
+ loading: '加載中',
+ noMore: '到底啦!',
+ selectParagraph: {
+ title: '選擇分段',
+ error: '僅執行未成功分段',
+ all: '全部分段'
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/dynamics-form.ts b/ui/src/locales/lang/zh-Hant/dynamics-form.ts
new file mode 100644
index 000000000..e75c2393d
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/dynamics-form.ts
@@ -0,0 +1,102 @@
+export default {
+ input_type_list: {
+ TextInput: '文字框',
+ PasswordInput: '密文框',
+ Slider: '滑桿',
+ SwitchInput: '開關',
+ SingleSelect: '單選框',
+ MultiSelect: '多選框',
+ DatePicker: '日期選擇器',
+ JsonInput: 'JSON文字框',
+ RadioCard: '選項卡',
+ RadioRow: '單行選項卡'
+ },
+ default: {
+ label: '預設值',
+ placeholder: '請輸入預設值',
+ requiredMessage: '為必填屬性',
+ show: '顯示預設值'
+ },
+ tip: {
+ requiredMessage: '不能為空',
+ jsonMessage: 'JSON格式不正確'
+ },
+ searchBar: {
+ placeholder: '請輸入關鍵字搜索'
+ },
+ paramForm: {
+ field: {
+ label: '參數',
+ placeholder: '請輸入參數',
+ requiredMessage: '參數 為必填屬性',
+ requiredMessage2: '只能輸入字母、數字和底線'
+ },
+ name: {
+ label: '顯示名稱',
+ placeholder: '請輸入顯示名稱',
+ requiredMessage: '顯示名稱 為必填屬性'
+ },
+ tooltip: {
+ label: '參數提示說明',
+ placeholder: '請輸入參數提示說明'
+ },
+ required: {
+ label: '是否必填',
+ requiredMessage: '是否必填 為必填屬性'
+ },
+ input_type: {
+ label: '組件類型',
+ placeholder: '請選擇組件類型',
+ requiredMessage: '組件類型 為必填屬性'
+ }
+ },
+ DatePicker: {
+ placeholder: '選擇日期',
+ year: '年',
+ month: '月',
+ date: '日期',
+ datetime: '日期時間',
+ dataType: {
+ label: '時間類型',
+ placeholder: '請選擇時間類型'
+ },
+ format: {
+ label: '格式',
+ placeholder: '請選擇格式'
+ }
+ },
+ Select: {
+ label: '選項值',
+ placeholder: '請輸入選項值'
+ },
+ tag: {
+ label: '標籤',
+ placeholder: '請輸入選項標籤'
+ },
+ Slider: {
+ showInput: {
+ label: '是否帶輸入框'
+ },
+ valueRange: {
+ label: '取值範圍',
+ minRequired: '最小值必填',
+ maxRequired: '最大值必填'
+ },
+ step: {
+ label: '步長值',
+ requiredMessage1: '步長值必填',
+ requiredMessage2: '步長不能為0'
+ }
+ },
+ TextInput: {
+ length: {
+ label: '文字長度',
+ minRequired: '最小長度必填',
+ maxRequired: '最大長度必填',
+ requiredMessage1: '長度在',
+ requiredMessage2: '到',
+ requiredMessage3: '個字元',
+ requiredMessage4: '文字長度為必填參數'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/index.ts b/ui/src/locales/lang/zh-Hant/index.ts
new file mode 100644
index 000000000..eb809475d
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/index.ts
@@ -0,0 +1,17 @@
+import zhTw from 'element-plus/es/locale/lang/zh-tw'
+import components from './components'
+import layout from './layout'
+import views from './views'
+import common from './common'
+import dynamicsForm from './dynamics-form'
+import chat from './ai-chat'
+export default {
+ lang: '繁體中文',
+ layout,
+ common,
+ views,
+ components,
+ zhTw,
+ dynamicsForm,
+ chat
+}
diff --git a/ui/src/locales/lang/zh-Hant/layout.ts b/ui/src/locales/lang/zh-Hant/layout.ts
new file mode 100644
index 000000000..2f8662f84
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/layout.ts
@@ -0,0 +1,34 @@
+export default {
+ github: '項目地址',
+ wiki: '使用者手冊',
+ forum: '論壇求助',
+ logout: '退出',
+
+ apiKey: 'API Key 管理',
+ apiServiceAddress: 'API 服務地址',
+ language: '語言',
+ isExpire: '未上傳 License 或 License 已過期。',
+ about: {
+ title: '關於',
+ expiredTime: '到期時間',
+ edition: {
+ label: '版本',
+ community: '社群版',
+ professional: '專業版'
+ },
+ version: '版本號',
+ serialNo: '序列號',
+ remark: '備註',
+ update: '更新',
+ authorize: '授權給'
+ },
+ time: {
+ daysLater: '天後',
+ hoursLater: '小時後',
+ expired: '已過期',
+ expiringSoon: '即將到期'
+ },
+ copyright: '版權所有 © 2014-2025 杭州飛致雲信息科技有限公司',
+ userManualUrl:'https://maxkb.cn/docs/',
+ forumUrl: 'https://github.com/1Panel-dev/MaxKB/discussions'
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/404.ts b/ui/src/locales/lang/zh-Hant/views/404.ts
new file mode 100644
index 000000000..e85fc2206
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/404.ts
@@ -0,0 +1,5 @@
+export default {
+ title: '404',
+ message: '無法訪問應用',
+ operate: '返回首頁'
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/application-overview.ts b/ui/src/locales/lang/zh-Hant/views/application-overview.ts
new file mode 100644
index 000000000..c402d9de3
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/application-overview.ts
@@ -0,0 +1,112 @@
+export default {
+ title: '概覽',
+ appInfo: {
+ header: '應用資訊',
+ publicAccessLink: '公開訪問連結',
+ openText: '開',
+ closeText: '關',
+ copyLinkText: '複製連結',
+ refreshLinkText: '重新整理連結',
+ demo: '示範',
+ embedInWebsite: '嵌入第三方',
+ accessControl: '訪問限制',
+ displaySetting: '顯示設定',
+ apiAccessCredentials: 'API 存取憑證',
+ apiKey: 'API Key',
+ refreshToken: {
+ msgConfirm1: '是否重新產生公開訪問連結?',
+ msgConfirm2:
+ '重新產生公開訪問連結會影響嵌入第三方腳本變更,需要將新腳本重新嵌入第三方,請謹慎操作!',
+ refreshSuccess: '重新整理成功'
+ },
+ APIKeyDialog: {
+ saveSettings: '儲存設定',
+ msgConfirm1: '是否刪除API Key',
+ msgConfirm2: '刪除API Key後將無法恢復,請確認是否刪除?',
+ enabledSuccess: '已啟用',
+ disabledSuccess: '已停用'
+ },
+ EditAvatarDialog: {
+ title: '應用頭像',
+ customizeUpload: '自訂上傳',
+ upload: '上傳',
+ default: '預設logo',
+ custom: '自訂',
+ sizeTip: '建議尺寸 32*32,支援 JPG、PNG、GIF,大小不超過 10 MB',
+ fileSizeExceeded: '檔案大小超過 10 MB',
+ uploadImagePrompt: '請上傳一張圖片'
+ },
+ EmbedDialog: {
+ fullscreenModeTitle: '全螢幕模式',
+ copyInstructions: '複製以下程式碼進行嵌入',
+ floatingModeTitle: '浮窗模式',
+ mobileModeTitle: '移動端模式'
+ },
+ LimitDialog: {
+ dialogTitle: '訪問限制',
+ showSourceLabel: '顯示知識來源',
+ clientQueryLimitLabel: '每個用戶端提問限制',
+ timesDays: '次/天',
+ authentication: '身份驗證',
+ authenticationValue: '驗證密碼',
+ whitelistLabel: '白名單',
+ whitelistPlaceholder:
+ '請輸入允許嵌入第三方的來源位址,一行一個,如:\nhttp://127.0.0.1:5678\nhttps://dataease.io'
+ },
+ SettingAPIKeyDialog: {
+ dialogTitle: '設定',
+ allowCrossDomainLabel: '允許跨域位址',
+ crossDomainPlaceholder:
+ '請輸入允許的跨域位址,開啟後不輸入跨域位址則不限制。\n跨域位址一行一個,如:\nhttp://127.0.0.1:5678 \nhttps://dataease.io'
+ },
+ SettingDisplayDialog: {
+ dialogTitle: '顯示設定',
+ languageLabel: '語言',
+ showSourceLabel: '顯示知識來源',
+ showExecutionDetail: '顯示執行細節',
+ restoreDefault: '恢復預設',
+ customThemeColor: '自訂主題色',
+ headerTitleFontColor: '標頭標題字體顏色',
+ default: '預設',
+ askUserAvatar: '提問用戶頭像',
+ replace: '取代',
+ imageMessage: '建議尺寸 32*32,支援 JPG、PNG、GIF,大小不超過 10 MB',
+ AIAvatar: 'AI 回覆頭像',
+ floatIcon: '浮窗入口圖示',
+ iconDefaultPosition: '圖示預設位置',
+ iconPosition: {
+ left: '左',
+ right: '右',
+ bottom: '下',
+ top: '上'
+ },
+ draggablePosition: '可拖曳位置',
+ showHistory: '顯示歷史紀錄',
+ displayGuide: '顯示引導圖(浮窗模式)',
+ disclaimer: '免責聲明',
+ disclaimerValue: '「以上內容均由 AI 生成,僅供參考和借鏡」'
+ }
+ },
+ monitor: {
+ monitoringStatistics: '監控統計',
+ customRange: '自訂範圍',
+ startDatePlaceholder: '開始時間',
+ endDatePlaceholder: '結束時間',
+ pastDayOptions: {
+ past7Days: '過去7天',
+ past30Days: '過去30天',
+ past90Days: '過去90天',
+ past183Days: '過去半年',
+ other: '自訂义'
+ },
+ charts: {
+ customerTotal: '用戶總數',
+ customerNew: '用戶新增數',
+ queryCount: '提問次數',
+ tokensTotal: 'Tokens 總數',
+ userSatisfaction: '用戶滿意度',
+ approval: '贊同',
+ disapproval: '反對'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/application-workflow.ts b/ui/src/locales/lang/zh-Hant/views/application-workflow.ts
new file mode 100644
index 000000000..b8cf46469
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/application-workflow.ts
@@ -0,0 +1,287 @@
+export default {
+ node: '節點',
+ nodeName: '節點名稱',
+ baseComponent: '基礎組件',
+ nodeSetting: '節點設置',
+ workflow: '工作流',
+ searchBar: {
+ placeholder: '按名稱搜索'
+ },
+ info: {
+ previewVersion: '預覽版本:',
+ saveTime: '保存時間:'
+ },
+ setting: {
+ restoreVersion: '恢復版本',
+ restoreCurrentVersion: '恢復此版本',
+ addComponent: '添加組件',
+ public: '發布',
+ releaseHistory: '發布歷史',
+ autoSave: '自動保存',
+ latestRelease: '最近發布',
+ copyParam: '複製參數',
+ debug: '調試',
+ exit: '直接退出',
+ exitSave: '保存並退出',
+ },
+ tip: {
+ publicSuccess: '發布成功',
+ noData: '沒有找到相關結果',
+ nameMessage: '名字不能為空!',
+ onlyRight: '只允許從右邊的錨點連出',
+ notRecyclable: '不可循環連線',
+ onlyLeft: '只允許連接左邊的錨點',
+ applicationNodeError: '該應用不可用',
+ functionNodeError: '該函數不可用',
+ repeatedNodeError: '節點名稱已存在!',
+ cannotCopy: '不能被複製',
+ copyError: '已複製節點',
+ paramErrorMessage: '參數已存在: ',
+ saveMessage: '當前修改未保存,是否保存後退出?',
+ },
+ delete: {
+ confirmTitle: '確定刪除該節點?',
+ deleteMessage: '節點不允許刪除'
+ },
+ control: {
+ zoomOut: '縮小',
+ zoomIn: '放大',
+ fitView: '適應',
+ retract: '收起全部節點',
+ extend: '展開全部節點',
+ beautify: '一鍵美化'
+ },
+ variable: {
+ label: '變量',
+ global: '全局變量',
+ Referencing: '引用變量',
+ ReferencingRequired: '引用變量必填',
+ ReferencingError: '引用變量錯誤',
+ NoReferencing: '不存在的引用變量',
+ placeholder: '請選擇變量'
+ },
+ condition: {
+ title: '執行條件',
+ front: '前置',
+ AND: '所有',
+ OR: '任一',
+ text: '連線節點執行完,執行當前節點'
+ },
+ validate: {
+ startNodeRequired: '開始節點必填',
+ startNodeOnly: '開始節點只能有一個',
+ baseNodeRequired: '基本信息節點必填',
+ baseNodeOnly: '基本信息節點只能有一個',
+ notInWorkFlowNode: '未在流程中的節點',
+ noNextNode: '不存在的下一個節點',
+ nodeUnavailable: '節點不可用',
+ needConnect1: '節點的',
+ needConnect2: '分支需要連接',
+ cannotEndNode: '節點不能當做結束節點'
+ },
+ nodes: {
+ startNode: {
+ label: '開始',
+ question: '用戶問題',
+ currentTime: '當前時間'
+ },
+ baseNode: {
+ label: '基本信息',
+ appName: {
+ label: '應用名稱'
+ },
+ appDescription: {
+ label: '應用描述'
+ },
+ fileUpload: {
+ label: '文件上傳',
+ tooltip: '開啟後,問答頁面會顯示上傳文件的按鈕。'
+ },
+ FileUploadSetting: {
+ title: '文件上傳設置',
+ maxFiles: '單次上傳最多文件數',
+ fileLimit: '每個文件最大(MB)',
+ fileUploadType: {
+ label: '上傳的文件類型',
+ documentText: '需要使用「文檔內容提取」節點解析文檔內容',
+ imageText: '需要使用「圖片理解」節點解析圖片內容',
+ audioText: '需要使用「語音轉文本」節點解析音頻內容'
+ }
+ }
+ },
+ aiChatNode: {
+ label: 'AI 對話',
+ text: '與 AI 大模型進行對話',
+ answer: 'AI 回答內容',
+ returnContent: {
+ label: '返回內容',
+ tooltip: `關閉後該節點的內容則不輸出給用戶。
+ 如果你想讓用戶看到該節點的輸出內容,請打開開關。`
+ },
+ defaultPrompt: '已知信息',
+ think: '思考過程'
+ },
+ searchDatasetNode: {
+ label: '知識庫檢索',
+ text: '關聯知識庫,查找與問題相關的分段',
+ paragraph_list: '檢索結果的分段列表',
+ is_hit_handling_method_list: '滿足直接回答的分段列表',
+ result: '檢索結果',
+ directly_return: '滿足直接回答的分段內容',
+ searchParam: '檢索參數',
+ searchQuestion: {
+ label: '檢索問題',
+ placeholder: '請選擇檢索問題',
+ requiredMessage: '請選擇檢索問題'
+ }
+ },
+ questionNode: {
+ label: '問題優化',
+ text: '根據歷史聊天記錄優化完善當前問題,更利於匹配知識庫分段',
+ result: '問題優化結果',
+ defaultPrompt1: `根據上下文優化和完善用戶問題:`,
+ defaultPrompt2: `請輸出一個優化後的問題。`,
+ systemDefault: '你是一個問題優化大師'
+ },
+ conditionNode: {
+ label: '判斷器',
+ text: '根據不同條件執行不同的節點',
+ branch_name: '分支名稱',
+ conditions: {
+ label: '條件',
+ info: '符合以下',
+ requiredMessage: '請選擇條件'
+ },
+ valueMessage: '請輸入值',
+ addCondition: '添加條件',
+ addBranch: '添加分支'
+ },
+ replyNode: {
+ label: '指定回覆',
+ text: '指定回覆內容,引用變量會轉換為字符串進行輸出',
+ content: '內容',
+ replyContent: {
+ label: '回覆內容',
+ custom: '自定義',
+ reference: '引用變量'
+ }
+ },
+ rerankerNode: {
+ label: '多路召回',
+ text: '使用重排模型對多個知識庫的檢索結果進行二次召回',
+ result_list: '重排結果列表',
+ result: '重排結果',
+ rerankerContent: {
+ label: '重排內容',
+ requiredMessage: '請選擇重排內容'
+ },
+ higher: '高於',
+ ScoreTooltip: 'Score越高相關性越強。',
+ max_paragraph_char_number: '最大引用字符數',
+ reranker_model: {
+ label: '重排模型',
+ placeholder: '請選擇重排模型'
+ }
+ },
+ formNode: {
+ label: '表單收集',
+ text: '在問答過程中用於收集用戶信息,可以根據收集到表單數據執行後續流程',
+ form_content_format1: '你好,請先填寫下面表單內容:',
+ form_content_format2: '填寫後請點擊【提交】按鈕進行提交。',
+ form_data: '表單全部內容',
+ formContent: {
+ label: '表單輸出內容',
+ requiredMessage: '請表單輸出內容',
+ tooltip: '設置執行該節點輸出的內容,{ form } 為表單的佔位符。'
+ },
+ formAllContent: '表單全部內容',
+ formSetting: '表單配置'
+ },
+ documentExtractNode: {
+ label: '文檔內容提取',
+ text: '提取文檔中的內容',
+ content: '文檔內容'
+ },
+ imageUnderstandNode: {
+ label: '圖片理解',
+ text: '識別出圖片中的物件、場景等信息回答用戶問題',
+ answer: 'AI 回答內容',
+ model: {
+ label: '圖片理解模型',
+ requiredMessage: '請選擇圖片理解模型'
+ },
+ image: {
+ label: '選擇圖片',
+ requiredMessage: '請選擇圖片'
+ }
+ },
+ variableAssignNode: {
+ label: '變數賦值',
+ text: '更新全域變數的值',
+ assign: '賦值'
+ },
+ imageGenerateNode: {
+ label: '圖片生成',
+ text: '根據提供的文本內容生成圖片',
+ answer: 'AI 回答內容',
+ model: {
+ label: '圖片生成模型',
+ requiredMessage: '請選擇圖片生成模型'
+ },
+ prompt: {
+ label: '提示詞(正向)',
+ tooltip: '正向提示詞,用來描述生成圖像中期望包含的元素和視覺特點'
+ },
+ negative_prompt: {
+ label: '提示詞(負向)',
+ tooltip: '反向提示詞,用來描述不希望在畫面中看到的內容,可以對畫面進行限制。',
+ placeholder: '請描述不想生成的圖片內容,比如:顏色、血腥內容'
+ }
+ },
+ speechToTextNode: {
+ label: '語音轉文本',
+ text: '將音頻通過語音識別模型轉換為文本',
+ stt_model: {
+ label: '語音識別模型'
+ },
+ audio: {
+ label: '選擇語音文件',
+ placeholder: '請選擇語音文件'
+ }
+ },
+ textToSpeechNode: {
+ label: '文本轉語音',
+ text: '將文本通過語音合成模型轉換為音頻',
+ tts_model: {
+ label: '語音合成模型'
+ },
+ content: {
+ label: '選擇文本內容'
+ }
+ },
+ functionNode: {
+ label: '自定義函數',
+ text: '通過執行自定義腳本,實現數據處理'
+ },
+ applicationNode: {
+ label: '應用節點'
+ }
+ },
+ compare: {
+ is_null: '為空',
+ is_not_null: '不為空',
+ contain: '包含',
+ not_contain: '不包含',
+ eq: '等於',
+ ge: '大於等於',
+ gt: '大於',
+ le: '小於等於',
+ lt: '小於',
+ len_eq: '長度等於',
+ len_ge: '長度大於等於',
+ len_gt: '長度大於',
+ len_le: '長度小於等於',
+ len_lt: '長度小於'
+ },
+ FileUploadSetting: {}
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/application.ts b/ui/src/locales/lang/zh-Hant/views/application.ts
new file mode 100644
index 000000000..192a6958f
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/application.ts
@@ -0,0 +1,214 @@
+export default {
+ title: '應用',
+ createApplication: '建立應用',
+ importApplication: '匯入應用',
+ copyApplication: '複製應用',
+ workflow: '進階編排',
+ simple: '簡單配置',
+ searchBar: {
+ placeholder: '按名稱搜尋'
+ },
+ setting: {
+ demo: '示範'
+ },
+ delete: {
+ confirmTitle: '是否刪除應用:',
+ confirmMessage: '刪除後該應用將不再提供服務,請謹慎操作。'
+ },
+ tip: {
+ ExportError: '匯出失敗',
+ professionalMessage: '社群版最多支援 5 個應用,如需擁有更多應用,請升級為專業版。',
+ saveErrorMessage: '儲存失敗,請檢查輸入或稍後再試',
+ loadingErrorMessage: '載入配置失敗,請檢查輸入或稍後再試'
+ },
+ applicationForm: {
+ title: {
+ appTest: '調試預覽',
+ copy: '副本'
+ },
+ form: {
+ appName: {
+ label: '名稱',
+ placeholder: '請輸入應用名稱',
+ requiredMessage: '請輸入應用名稱'
+ },
+ appDescription: {
+ label: '描述',
+ placeholder: '描述該應用的應用場景及用途,如:XXX 小助手回答用戶提出的 XXX 產品使用問題'
+ },
+ appType: {
+ label: '類型',
+ simplePlaceholder: '適合新手建立小助手',
+ workflowPlaceholder: '適合高階用戶自訂小助手的工作流程'
+ },
+ appTemplate: {
+ blankApp: '空白應用',
+ assistantApp: '知識庫問答助手'
+ },
+ aiModel: {
+ label: 'AI 模型',
+ placeholder: '請選擇 AI 模型'
+ },
+ roleSettings: {
+ label: '角色設定',
+ placeholder: '你是 xxx 小助手'
+ },
+ prompt: {
+ label: '提示詞',
+ noReferences: ' (無引用知識庫)',
+ references: ' (引用知識庫)',
+ placeholder: '請輸入提示詞',
+ requiredMessage: '請輸入提示詞',
+ tooltip:'透過調整提示詞內容,可以引導大模型對話方向,該提示詞會被固定在上下文的開頭。',
+
+ noReferencesTooltip:
+ '透過調整提示詞內容,可以引導大模型對話方向,該提示詞會被固定在上下文的開頭。可以使用變數:{question} 是用戶提出問題的佔位符。',
+ referencesTooltip:
+ '透過調整提示詞內容,可以引導大模型對話方向,該提示詞會被固定在上下文的開頭。可以使用變數:{data} 是引用知識庫中分段的佔位符;{question} 是用戶提出問題的佔位符。',
+ defaultPrompt: `已知資訊:{data}
+用戶問題:{question}
+回答要求:
+ - 請使用中文回答用戶問題`
+ },
+ historyRecord: {
+ label: '歷史對話紀錄'
+ },
+ relatedKnowledge: {
+ label: '關聯知識庫',
+ placeholder: '關聯的知識庫展示在這裡'
+ },
+ multipleRoundsDialogue: '多輪對話',
+
+ prologue: '開場白',
+ defaultPrologue:
+ '您好,我是 XXX 小助手,您可以向我提出 XXX 使用問題。\n- XXX 主要功能有什麼?\n- XXX 如何收費?\n- 需要轉人工服務',
+
+ problemOptimization: {
+ label: '問題優化',
+ tooltip: '根據歷史對話優化完善當前問題,更利於匹配知識點。'
+ },
+ voiceInput: {
+ label: '語音輸入',
+ placeholder: '請選擇語音辨識模型',
+ requiredMessage: '請選擇語音輸入模型',
+ autoSend: '自動發送'
+ },
+ voicePlay: {
+ label: '語音播放',
+ placeholder: '請選擇語音合成模型',
+ requiredMessage: '請選擇語音播放模型',
+ autoPlay: '自動播放',
+ browser: '瀏覽器播放(免費)',
+ tts: 'TTS模型',
+ listeningTest: '試聽'
+ },
+ reasoningContent: {
+ label: '輸出思考',
+ tooltip:'請根據模型返回的思考標簽設置,標簽中間的內容將會認定爲思考過程',
+ start: '開始',
+ end: '結束',
+ }
+ },
+ buttons: {
+ publish: '儲存並發佈',
+ addModel: '新增模型'
+ },
+
+ dialog: {
+ addDataset: '新增關聯知識庫',
+ addDatasetPlaceholder: '所選知識庫必須使用相同的 Embedding 模型',
+ selected: '已選',
+ countDataset: '個知識庫',
+
+ selectSearchMode: '檢索模式',
+ vectorSearch: '向量檢索',
+ vectorSearchTooltip: '向量檢索是一種基於向量相似度的檢索方式,適用於知識庫中的大數據量場景。',
+ fullTextSearch: '全文檢索',
+ fullTextSearchTooltip:
+ '全文檢索是一種基於文本相似度的檢索方式,適用於知識庫中的小數據量場景。',
+ hybridSearch: '混合檢索',
+ hybridSearchTooltip:
+ '混合檢索是一種基於向量和文本相似度的檢索方式,適用於知識庫中的中等數據量場景。',
+ similarityThreshold: '相似度高於',
+ similarityTooltip: '相似度越高相關性越強。',
+ topReferences: '引用分段數 TOP',
+ maxCharacters: '最多引用字元數',
+ noReferencesAction: '無引用知識庫分段時',
+ continueQuestioning: '繼續向 AI 模型提問',
+ provideAnswer: '指定回答內容',
+ designated_answer:
+ '你好,我是 XXX 小助手,我的知識庫只包含了 XXX 產品相關知識,請重新描述您的問題。',
+ defaultPrompt1:
+ '()裡面是用戶問題,根據上下文回答揣測用戶問題({question}) 要求: 輸出一個補全問題,並且放在',
+ defaultPrompt2: '標籤中'
+ }
+ },
+ applicationAccess: {
+ title: '應用接入',
+ wecom: '企業微信應用',
+ wecomTip: '打造企業微信智慧應用',
+ dingtalk: '釘釘應用',
+ dingtalkTip: '打造釘釘智慧應用',
+ wechat: '公眾號',
+ wechatTip: '打造公眾號智慧應用',
+ lark: '飛書應用',
+ larkTip: '打造飛書智慧應用',
+ slack: 'Slack',
+ slackTip: '打造 Slack 智慧應用',
+ setting: '配置',
+ callback: '回呼位址',
+ callbackTip: '請輸入回呼位址',
+ wecomPlatform: '企業微信後台',
+ wechatPlatform: '微信公众平台',
+ dingtalkPlatform: '釘釘開放平台',
+ larkPlatform: '飛書開放平台',
+ wecomSetting: {
+ title: '企業微信應用配置',
+ cropId: '企業 ID',
+ cropIdPlaceholder: '請輸入企業 ID',
+ agentIdPlaceholder: '請輸入Agent ID',
+ secretPlaceholder: '請輸入Secret',
+ tokenPlaceholder: '請輸入Token',
+ encodingAesKeyPlaceholder: '請輸入EncodingAESKey',
+ authenticationSuccessful: '認證成功',
+ urlInfo: '-應用管理-自建-建立的應用-接收消息-設定 API 接收的 "URL" 中'
+ },
+ dingtalkSetting: {
+ title: '釘釘應用配置',
+ clientIdPlaceholder: '請輸入Client ID',
+ clientSecretPlaceholder: '請輸入Client Secret',
+ urlInfo: '-機器人頁面,設定 "消息接收模式" 為 HTTP模式 ,並把上面URL填寫到"消息接收位址"中'
+ },
+ wechatSetting: {
+ title: '公眾號應用配置',
+ appId: '開發者ID (APP ID)',
+ appIdPlaceholder: '請輸入開發者ID (APP ID)',
+ appSecret: '開發者密鑰 (APP SECRET)',
+ appSecretPlaceholder: '請輸入開發者密鑰 (APP SECRET)',
+ token: '權杖 (TOKEN)',
+ tokenPlaceholder: '請輸入權杖 (TOKEN)',
+ aesKey: '消息加解密密鑰',
+ aesKeyPlaceholder: '請輸入消息加解密密鑰',
+ urlInfo: '-設定與開發-基本配置-伺服器配置的 "伺服器位址URL" 中'
+ },
+ larkSetting: {
+ title: '飛書應用配置',
+ appIdPlaceholder: '請輸入App ID',
+ appSecretPlaceholder: '請輸入App Secret',
+ verificationTokenPlaceholder: '請輸入Verification Token',
+ urlInfo: '-事件與回呼-事件配置-配置訂閱方式的 "請求位址" 中'
+ },
+ slackSetting: {
+ title: 'Slack 應用配置',
+ signingSecretPlaceholder: '請輸入 Signing Secret',
+ botUserTokenPlaceholder: '請輸入 Bot User Token',
+ },
+ copyUrl: '複製連結填入到'
+ },
+ hitTest: {
+ title: '命中測試',
+ text: '針對用戶提問調試段落匹配情況,保障回答效果。',
+ emptyMessage1: '命中的段落顯示在這裡',
+ emptyMessage2: '沒有命中的分段'
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/dataset.ts b/ui/src/locales/lang/zh-Hant/views/dataset.ts
new file mode 100644
index 000000000..0eace754b
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/dataset.ts
@@ -0,0 +1,83 @@
+export default {
+ title: '知識庫',
+ createDataset: '建立知識庫',
+ general: '通用型',
+ web: 'Web 站點',
+ relatedApplications: '關聯應用',
+ document_count: '文檔數',
+ relatedApp_count: '關聯應用',
+ searchBar: {
+ placeholder: '按名稱搜尋'
+ },
+ setting: {
+ vectorization: '向量化',
+ sync: '同步'
+ },
+ tip: {
+ professionalMessage: '社群版最多支援 50 個知識庫,如需擁有更多知識庫,請升級為專業版。',
+ syncSuccess: '同步任務發送成功',
+ updateModeMessage: '修改知識庫向量模型後,需要對知識庫向量化,是否繼續保存?'
+ },
+ delete: {
+ confirmTitle: '是否刪除知識庫:',
+ confirmMessage1: '此知識庫關聯',
+ confirmMessage2: '個應用,刪除後無法恢復,請謹慎操作。'
+ },
+ datasetForm: {
+ title: {
+ info: '基本資訊'
+ },
+ form: {
+ datasetName: {
+ label: '知識庫名稱',
+ placeholder: '請輸入知識庫名稱',
+ requiredMessage: '請輸入應用名稱'
+ },
+ datasetDescription: {
+ label: '知識庫描述',
+ placeholder:
+ '描述知識庫的內容,詳盡的描述將幫助AI能深入理解該知識庫的內容,能更準確的檢索到內容,提高該知識庫的命中率。',
+ requiredMessage: '請輸入知識庫描述'
+ },
+ EmbeddingModel: {
+ label: '向量模型',
+ placeholder: '請選擇向量模型',
+ requiredMessage: '請輸入Embedding模型'
+ },
+ datasetType: {
+ label: '知識庫類型',
+ generalInfo: '上傳本地檔案',
+ webInfo: '同步Web網站文字資料'
+ },
+ source_url: {
+ label: 'Web 根位址',
+ placeholder: '請輸入 Web 根位址',
+ requiredMessage: '請輸入 Web 根位址'
+ },
+ selector: {
+ label: '選擇器',
+ placeholder: '預設為 body,可輸入 .classname/#idname/tagname'
+ }
+ }
+ },
+ ResultSuccess: {
+ title: '知識庫建立成功',
+ paragraph: '段落',
+ paragraph_count: '個段落',
+ documentList: '文件列表',
+ loading: '正在導入',
+ buttons: {
+ toDataset: '返回知識庫列表',
+ toDocument: '前往文件'
+ }
+ },
+ syncWeb: {
+ title: '同步知識庫',
+ syncMethod: '同步方式',
+ replace: '替換同步',
+ replaceText: '重新獲取 Web 站點文件,覆蓋替換本地知識庫中的文件',
+ complete: '完整同步',
+ completeText: '先刪除本地知識庫所有文件,重新獲取 Web 站點文件',
+ tip: '注意:所有同步都會刪除現有數據並重新獲取新數據,請謹慎操作。'
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/document.ts b/ui/src/locales/lang/zh-Hant/views/document.ts
new file mode 100644
index 000000000..dc3d80407
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/document.ts
@@ -0,0 +1,174 @@
+export default {
+ uploadDocument: '上傳文檔',
+ importDocument: '導入文檔',
+ syncDocument: '同步文檔',
+ selected: '已選',
+ items: '項',
+ searchBar: {
+ placeholder: '按 文檔名稱 搜索'
+ },
+ setting: {
+ migration: '遷移',
+ cancelGenerateQuestion: '取消生成問題',
+ cancelVectorization: '取消向量化',
+ cancelGenerate: '取消生成',
+ export: '匯出',
+ },
+ tip: {
+ saveMessage: '當前的更改尚未保存,確認退出嗎?',
+ cancelSuccess: '批量取消成功',
+ sendMessage: '發送成功',
+ vectorizationSuccess: '批量向量化成功',
+ nameMessage: '文件名稱不能为空!',
+ importMessage: '導入成功',
+ migrationSuccess: '遷移成功'
+ },
+ upload: {
+ selectFile: '選擇文件',
+ selectFiles: '選擇文件夾',
+ uploadMessage: '拖拽文件至此上傳或',
+ formats: '支持格式:',
+ requiredMessage: '請上傳文件',
+ errorMessage1: '文件大小超過 100MB',
+ errorMessage2: '文件格式不支持',
+ errorMessage3: '文件不能为空',
+ errorMessage4: '每次最多上傳50個文件',
+ template: '模板',
+ download: '下載'
+ },
+
+ fileType: {
+ txt: {
+ label: '文本文件',
+ tip1: '1、文件上傳前,建議規範文件的分段標識',
+ tip2: '2、每次最多上傳 50 個文件,每個文件不超过 100MB'
+ },
+ table: {
+ label: '表格',
+ tip1: '1、點擊下載對應模板並完善信息:',
+ tip2: '2、第一行必須是列標題,且列標題必須是有意義的術語,表中每條記錄將作為一個分段',
+ tip3: '3、上傳的表格文件中每個 sheet 會作為一個文檔,sheet 名稱為文檔名稱',
+ tip4: '4、每次最多上傳 50 個文件,每個文件不超过 100MB'
+ },
+ QA: {
+ label: 'QA 問答對',
+ tip1: '1、點擊下載對應模板並完善信息',
+ tip2: '2、上傳的表格文件中每個 sheet 會作為一個文檔,sheet 名稱為文檔名稱',
+ tip3: '3、每次最多上傳 50 個文件,每個文件不超过 100MB'
+ }
+ },
+ setRules: {
+ title: {
+ setting: '設置分段規則',
+ preview: '分段預覽'
+ },
+ intelligent: {
+ label: '智能分段(推薦)',
+ text: '不了解如何設置分段規則推薦使用智能分段'
+ },
+ advanced: {
+ label: '高級分段',
+ text: '用戶可根據文檔規範自行設置分段標識符、分段長度以及清洗規則'
+ },
+ patterns: {
+ label: '分段標識',
+ tooltip: '按照所選符號先後順序做遞歸分割,分割結果超出分段長度將截取至分段長度。',
+ placeholder: '請選擇'
+ },
+ limit: {
+ label: '分段長度'
+ },
+ with_filter: {
+ label: '自動清洗',
+ text: '去掉重複多餘符號空格、空行、制表符'
+ },
+ checkedConnect: {
+ label: '導入時添加分段標題為關聯問題(適用於標題為問題的問答對)'
+ }
+ },
+ buttons: {
+ prev: '上一步',
+ next: '下一步',
+ import: '開始導入',
+ preview: '生成預覽'
+ },
+ table: {
+ name: '文件名稱',
+ char_length: '字符數',
+ paragraph: '分段',
+ all: '全部',
+ updateTime: '更新時間'
+ },
+ fileStatus: {
+ label: '文件狀態',
+ SUCCESS: '成功',
+ FAILURE: '失敗',
+ EMBEDDING: '索引中',
+ PENDING: '排隊中',
+ GENERATE: '生成中',
+ SYNC: '同步中',
+ REVOKE: '取消中',
+ finish: '完圓'
+ },
+ enableStatus: {
+ label: '啟用狀態',
+ enable: '開啟',
+ close: '關閉'
+ },
+ sync: {
+ label: '同步',
+ confirmTitle: '確認同步文檔?',
+ confirmMessage1: '同步將刪除已有數據重新獲取新數據,請謹慎操作。',
+ confirmMessage2: '無法同步,請先去設置文檔 URL地址',
+ successMessage: '同步文檔成功'
+ },
+ delete: {
+ confirmTitle1: '是否批量刪除',
+ confirmTitle2: '個文檔?',
+ confirmMessage: '所選文檔中的分段會跟隨刪除,請謹慎操作。',
+ successMessage: '批量刪除成功',
+ confirmTitle3: '是否刪除文檔:',
+ confirmMessage1: '此文檔下的',
+ confirmMessage2: '個分段都會被刪除,請謹慎操作。'
+ },
+ form: {
+ source_url: {
+ label: '文檔地址',
+ placeholder: '請輸入文檔地址,一行一個,地址不正確文檔會導入失敗。',
+ requiredMessage: '請輸入文檔地址'
+ },
+ selector: {
+ label: '選擇器',
+ placeholder: '默認為 body,可輸入 .classname/#idname/tagname'
+ },
+ hit_handling_method: {
+ label: '命中處理方式',
+ tooltip: '用戶提問時,命中文檔下的分段時按照設置的方式進行處理。'
+ },
+ similarity: {
+ label: '相似度高于',
+ placeholder: '直接返回分段内容',
+ requiredMessage: '请输入相似度'
+ },
+ },
+ hitHandlingMethod: {
+ optimization: '模型優化',
+ directly_return: '直接回答'
+ },
+ generateQuestion: {
+ title: '生成問題',
+ successMessage: '生成問題成功',
+ tip1: '提示詞中的 {data} 為分段內容的佔位符,執行時替換為分段內容並發送給 AI 模型;',
+ tip2: 'AI 模型根據分段內容生成相關問題,請將生成的問題放置於',
+ tip3: '標籤中,系統會自動關聯標籤中的問題;',
+ tip4: '生成效果取決於所選模型和提示詞,用戶可自行調整至最佳效果。',
+ prompt1: `內容:{data}\n\n請總結上面的內容,並根據內容總結生成 5 個問題。\n回答要求:\n - 請只輸出問題;\n - 請將每個問題放置在`,
+ prompt2: `標籤中。`,
+ },
+ feishu: {
+ selectDocument: '選擇文檔',
+ tip1: '僅支持文檔和表格類型,文檔會根據標題分段,表格會轉為Markdown格式後再分段。',
+ tip2: '系統不存儲原始文檔,導入文檔前,建議規範文檔的分段標識。',
+ allCheck: '全選'
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/function-lib.ts b/ui/src/locales/lang/zh-Hant/views/function-lib.ts
new file mode 100644
index 000000000..789cbf0ec
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/function-lib.ts
@@ -0,0 +1,77 @@
+export default {
+ title: '函數庫',
+ internalTitle: '內置函數',
+ added: '已新增',
+ createFunction: '建立函數',
+ editFunction: '編輯函數',
+ copyFunction: '複製函數',
+ importFunction: '匯入函數',
+ searchBar: {
+ placeholder: '按函數名稱搜尋'
+ },
+ setting: {
+ disabled: '停用'
+ },
+ tip: {
+ saveMessage: '當前的更改尚未保存,確認退出嗎?'
+ },
+ delete: {
+ confirmTitle: '是否刪除函數:',
+ confirmMessage: '刪除後,引用該函數的應用在查詢時會報錯,請謹慎操作。'
+ },
+ disabled: {
+ confirmTitle: '是否停用函數:',
+ confirmMessage: '停用後,引用該函數的應用在查詢時會報錯,請謹慎操作。'
+ },
+ functionForm: {
+ title: {
+ copy: '副本',
+ baseInfo: '基礎信息'
+ },
+ form: {
+ functionName: {
+ label: '名稱',
+ placeholder: '請輸入函數名稱',
+ requiredMessage: '請輸入函數名稱'
+ },
+ functionDescription: {
+ label: '描述',
+ placeholder: '請輸入函數的描述'
+ },
+ permission_type: {
+ label: '權限',
+ requiredMessage: '請選擇'
+ },
+ paramName: {
+ label: '參數名',
+ placeholder: '請輸入參數名',
+ requiredMessage: '請輸入參數名'
+ },
+ dataType: {
+ label: '數據類型'
+ },
+ source: {
+ label: '來源',
+ custom: '自定義',
+ reference: '引用參數'
+ },
+ required: {
+ label: '是否必填'
+ },
+ param: {
+ paramInfo1: '使用函數時顯示',
+ paramInfo2: '使用函數時不顯示',
+ code: '函数内容(Python)',
+ selectPlaceholder: '請选择參數',
+ inputPlaceholder: '請輸入參數值',
+ },
+ debug: {
+ run: '運行',
+ output: '輸出',
+ runResult: '運行結果',
+ runSuccess: '運行成功',
+ runFailed: '運行失敗'
+ }
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/index.ts b/ui/src/locales/lang/zh-Hant/views/index.ts
new file mode 100644
index 000000000..c63d40492
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/index.ts
@@ -0,0 +1,34 @@
+import notFound from './404'
+import application from './application'
+import applicationOverview from './application-overview'
+import dataset from './dataset'
+import system from './system'
+import functionLib from './function-lib'
+import user from './user'
+import team from './team'
+import template from './template'
+import document from './document'
+import paragraph from './paragraph'
+import problem from './problem'
+import log from './log'
+import applicationWorkflow from './application-workflow'
+import login from './login'
+import operateLog from './operate-log'
+export default {
+ notFound,
+ application,
+ applicationOverview,
+ system,
+ functionLib,
+ user,
+ team,
+ template,
+ dataset,
+ applicationWorkflow,
+ document,
+ paragraph,
+ problem,
+ log,
+ login,
+ operateLog
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/log.ts b/ui/src/locales/lang/zh-Hant/views/log.ts
new file mode 100644
index 000000000..5e84a698d
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/log.ts
@@ -0,0 +1,41 @@
+export default {
+ title: '對話日誌',
+ delete: {
+ confirmTitle: '是否刪除問題:',
+ confirmMessage1: '刪除問題關聯的',
+ confirmMessage2: '個分段會被取消關聯,請謹慎操作。'
+ },
+ buttons: {
+ clearStrategy: '清除策略',
+ prev: '上一條',
+ next: '下一條'
+ },
+ table: {
+ abstract: '摘要',
+ chat_record_count: '對話提問數',
+ user: '用戶',
+ feedback: {
+ label: '用戶反饋',
+ star: '贊同',
+ trample: '反對'
+ },
+ mark: '改進標註',
+ recenTimes: '最近對話時間'
+ },
+ addToDataset: '添加至知識庫',
+ daysText: '天之前的對話記錄',
+ selectDataset: '選擇知識庫',
+ selectDatasetPlaceholder: '請選擇知識庫',
+ saveToDocument: '保存至文件',
+ documentPlaceholder: '請選擇文件',
+ editContent: '修改內容',
+ editMark: '修改標註',
+ form: {
+ content: {
+ placeholder: '請輸入內容'
+ },
+ title: {
+ placeholder: '請給當前內容設定一個標題,以便管理查看'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/login.ts b/ui/src/locales/lang/zh-Hant/views/login.ts
new file mode 100644
index 000000000..dded54730
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/login.ts
@@ -0,0 +1,24 @@
+export default {
+ title: '普通登錄',
+ jump_tip: '即將跳轉至認證源頁面進行認證',
+ jump: '跳轉',
+ resetPassword: '修改密碼',
+ forgotPassword: '忘記密碼',
+ userRegister: '用戶註冊',
+ buttons: {
+ login: '登錄',
+ register: '註冊',
+ backLogin: '返回登錄',
+ checkCode: '立即驗證'
+ },
+ newPassword: '新密碼',
+ enterPassword: '請輸入新密碼',
+ useEmail: '使用電子郵箱',
+ moreMethod: '更多登錄方式',
+ verificationCode: {
+ placeholder: '請輸入驗證碼',
+ getVerificationCode: '獲取驗證碼',
+ successMessage: '驗證碼發送成功',
+ resend: '重新發送'
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/operate-log.ts b/ui/src/locales/lang/zh-Hant/views/operate-log.ts
new file mode 100644
index 000000000..510ab21dc
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/operate-log.ts
@@ -0,0 +1,30 @@
+export default {
+ title: '操作日誌',
+ table: {
+ menu: {
+ label: '操作菜單'
+ },
+ operate: {
+ label: '操作'
+ },
+ user: {
+ label: '操作用戶'
+ },
+ status: {
+ label: '狀態',
+ success: '成功',
+ fail: '失敗',
+ all: '全部'
+ },
+ ip_address: {
+ label: 'IP地址'
+ },
+ opt: {
+ label: 'API詳情'
+ },
+ operateTime: {
+ label: '操作時間'
+ }
+ },
+ close: '關閉'
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/paragraph.ts b/ui/src/locales/lang/zh-Hant/views/paragraph.ts
new file mode 100644
index 000000000..a5b4b3317
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/paragraph.ts
@@ -0,0 +1,32 @@
+export default {
+ title: '段落',
+ paragraph_count: '段落',
+ editParagraph: '編輯分段',
+ addParagraph: '添加分段',
+ paragraphDetail: '分段詳情',
+ character_count: '個字符',
+ setting: {
+ batchSelected: '批量選擇',
+ cancelSelected: '取消選擇'
+ },
+ delete: {
+ confirmTitle: '是否刪除段落:',
+ confirmMessage: '刪除後無法恢復,請謹慎操作。'
+ },
+ relatedProblem: {
+ title: '關聯問題',
+ placeholder: '請選擇問題'
+ },
+ form: {
+ paragraphTitle: {
+ label: '分段標題',
+ placeholder: '請輸入分段標題'
+ },
+ content: {
+ label: '分段內容',
+ placeholder: '請輸入分段內容',
+ requiredMessage1: '請輸入分段內容',
+ requiredMessage2: '內容最多不超過 100000 個字'
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/problem.ts b/ui/src/locales/lang/zh-Hant/views/problem.ts
new file mode 100644
index 000000000..12cb86020
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/problem.ts
@@ -0,0 +1,37 @@
+export default {
+ title: '問題',
+ createProblem: '建立問題',
+ detailProblem: '問題詳情',
+ quickCreateProblem: '快速建立問題',
+ quickCreateName: '問題',
+ tip: {
+ placeholder: '請輸入問題,支持輸入多個,一行一個。',
+ errorMessage: '問題不能為空!',
+ requiredMessage: '請輸入問題',
+ relatedSuccess: '批量關聯分段成功'
+ },
+
+ setting: {
+ batchDelete: '批量刪除',
+ cancelRelated: '取消關聯'
+ },
+ searchBar: {
+ placeholder: '按名稱搜尋'
+ },
+ table: {
+ paragraph_count: '關聯分段數',
+ updateTime: '更新時間'
+ },
+ delete: {
+ confirmTitle: '是否刪除問題:',
+ confirmMessage1: '刪除問題關聯的',
+ confirmMessage2: '個分段會被取消關聯,請謹慎操作。'
+ },
+ relateParagraph: {
+ title: '關聯分段',
+ selectDocument: '選擇文件',
+ placeholder: '按 文件名稱 搜尋',
+ selectedParagraph: '已選分段',
+ count: '個'
+ },
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/system.ts b/ui/src/locales/lang/zh-Hant/views/system.ts
new file mode 100644
index 000000000..10259390b
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/system.ts
@@ -0,0 +1,152 @@
+export default {
+ title: '系統設置',
+ test: '測試連線',
+ testSuccess: '測試連線成功',
+ testFailed: '測試連線失敗',
+ password: '密碼',
+ authentication: {
+ title: '登入認證',
+ ldap: {
+ title: 'LDAP',
+ address: 'LDAP 位址',
+ serverPlaceholder: '請輸入LDAP 位址',
+ bindDN: '綁定DN',
+ bindDNPlaceholder: '請輸入綁定 DN',
+
+ ou: '使用者OU',
+ ouPlaceholder: '請輸入使用者 OU',
+ ldap_filter: '使用者過濾器',
+ ldap_filterPlaceholder: '請輸入使用者過濾器',
+ ldap_mapping: 'LDAP 屬性對應',
+ ldap_mappingPlaceholder: '請輸入 LDAP 屬性對應',
+ enableAuthentication: '啟用 LDAP 認證'
+ },
+ cas: {
+ title: 'CAS',
+ ldpUri: 'ldpUri',
+ ldpUriPlaceholder: '請輸入ldpUri',
+ validateUrl: '驗證位址',
+ validateUrlPlaceholder: '請輸入驗證位址',
+ redirectUrl: '回呼位址',
+ redirectUrlPlaceholder: '請輸入回呼位址',
+ enableAuthentication: '啟用 CAS 認證'
+ },
+ oidc: {
+ title: 'OIDC',
+ authEndpoint: '授權端位址',
+ authEndpointPlaceholder: '請輸入授權端位址',
+ tokenEndpoint: 'Token端位址',
+ tokenEndpointPlaceholder: '請輸入 Token 端位址',
+ userInfoEndpoint: '使用者資訊端位址',
+ userInfoEndpointPlaceholder: '請輸入使用者資訊端位址',
+ clientId: '用戶端 ID',
+ scopePlaceholder: '請輸入連線範圍',
+ clientIdPlaceholder: '請輸入用戶端 ID',
+ clientSecret: '用戶端密鑰',
+ clientSecretPlaceholder: '請輸入用戶端密鑰',
+ logoutEndpoint: '登出端位址',
+ logoutEndpointPlaceholder: '請輸入登出端位址',
+ redirectUrl: '回呼位址',
+ redirectUrlPlaceholder: '請輸入回呼位址',
+ enableAuthentication: '啟用 OIDC 認證'
+ },
+
+ oauth2: {
+ title: 'OAuth2',
+ authEndpoint: '授權端位址',
+ authEndpointPlaceholder: '請輸入授權端位址',
+ tokenEndpoint: 'Token 端位址',
+ tokenEndpointPlaceholder: '請輸入 Token 端位址',
+ userInfoEndpoint: '使用者資訊端位址',
+ userInfoEndpointPlaceholder: '請輸入使用者資訊端位址',
+ scope: '連線範圍',
+ scopePlaceholder: '請輸入連線範圍',
+ clientId: '用戶端 ID',
+ clientIdPlaceholder: '請輸入用戶端 ID',
+ clientSecret: '用戶端密鑰',
+ clientSecretPlaceholder: '請輸入用戶端密鑰',
+ redirectUrl: '回呼位址',
+ redirectUrlPlaceholder: '請輸入回呼位址',
+ filedMapping: '欄位對應',
+ filedMappingPlaceholder: '請輸入欄位對應',
+ enableAuthentication: '啟用 OAuth2 認證'
+ },
+ scanTheQRCode: {
+ title: '掃碼登入',
+ wecom: '企業微信',
+ dingtalk: '釘釘',
+ lark: '飛書',
+ effective: '有效',
+ alreadyTurnedOn: '已開啟',
+ notEnabled: '未開啟',
+ validate: '驗證',
+ validateSuccess: '驗證成功',
+ validateFailed: '驗證失敗',
+ validateFailedTip: '請填寫所有必填項並確保格式正確',
+ appKeyPlaceholder: '請輸入 App Key',
+ appSecretPlaceholder: '請輸入 App Secret',
+ corpIdPlaceholder: '請輸入 Corp Id',
+ agentIdPlaceholder: '請輸入 Agent Id',
+ callbackWarning: '請輸入有效的 URL 位址',
+ larkQrCode: '飛書掃碼登錄',
+ dingtalkQrCode: '釘釘掃碼登錄',
+ setting: '設置',
+ access: '接入'
+ }
+ },
+ theme: {
+ title: '外觀設置',
+ platformDisplayTheme: '平台顯示主題',
+ customTheme: '自定義主題',
+ platformLoginSettings: '平台登錄設置',
+ custom: '自定義',
+ pagePreview: '頁面預覽',
+ default: '默認',
+ restoreDefaults: '恢復默認',
+ orange: '活力橙',
+ green: '松石綠',
+ purple: '神秘紫',
+ red: '胭脂紅',
+ loginBackground: '登錄背景圖',
+ loginLogo: '登錄 Logo',
+ websiteLogo: '網站 Logo',
+ replacePicture: '替換圖片',
+ websiteLogoTip: '頂部網站顯示的 Logo,建議尺寸 48*48,支持 JPG、PNG、GIF,大小不超過 10MB',
+ loginLogoTip: '登錄頁面右側 Logo,建議尺寸 204*52,支持 JPG、PNG、GIF,大小不超過 10 MB',
+ loginBackgroundTip:
+ '左側背景圖,矢量圖建議尺寸 576*900,位圖建議尺寸 1152*1800;支持 JPG、PNG、GIF,大小不超過 10 MB',
+ websiteName: '網站名稱',
+ websiteNamePlaceholder: '請輸入網站名稱',
+ websiteNameTip: '顯示在網頁 Tab 的平台名稱',
+ websiteSlogan: '歡迎語',
+ websiteSloganPlaceholder: '請輸入歡迎語',
+ websiteSloganTip: '產品 Logo 下的歡迎語',
+ logoDefaultTip: '默认为 MaxKB 登錄界面,支持自定义设置',
+ defaultSlogan: '歡迎使用 MaxKB 智能知識庫問答系統',
+ defaultTip: '默認為 MaxKB 平台界面,支持自定義設置',
+ platformSetting: '平台設置',
+ showUserManual: '顯示用戶手冊',
+ showForum: '顯示論壇求助',
+ showProject: '顯示項目地址',
+ urlPlaceholder: '請輸入 URL 地址',
+ abandonUpdate: '放棄更新',
+ saveAndApply: '保存並應用',
+ fileMessageError: '文件大小超過 10M',
+ saveSuccess: '外觀設置成功'
+ },
+ email: {
+ title: '郵箱設置',
+ smtpHost: 'SMTP Host',
+ smtpHostPlaceholder: '請輸入 SMTP Host',
+ smtpPort: 'SMTP Port',
+ smtpPortPlaceholder: '請輸入 SMTP Port',
+ smtpUser: 'SMTP 帳戶',
+ smtpUserPlaceholder: '請輸入 SMTP 帳戶',
+ sendEmail: '發件人信箱',
+ sendEmailPlaceholder: '請輸入發件人信箱',
+ smtpPassword: '發件人密碼',
+ smtpPasswordPlaceholder: '請輸入發件人密碼',
+ enableSSL: '啟用 SSL(如果 SMTP 端口是 465,通常需要啟用 SSL)',
+ enableTLS: '啟用 TLS(如果 SMTP 端口是 587,通常需要啟用 TLS)'
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/team.ts b/ui/src/locales/lang/zh-Hant/views/team.ts
new file mode 100644
index 000000000..1b1fb4192
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/team.ts
@@ -0,0 +1,29 @@
+export default {
+ title: '團隊成員',
+ member: '成員',
+ manage: '所有者',
+ permissionSetting: '權限設定',
+ addMember: '新增成員',
+ addSubTitle: '成員登入後可以存取您授權的資料。',
+ searchBar: {
+ placeholder: '請輸入使用者名稱搜尋'
+ },
+ delete: {
+ button: '移除',
+ confirmTitle: '是否移除成員:',
+ confirmMessage: '移除後將會取消成員擁有之知識庫和應用程式權限。'
+ },
+ setting: {
+ management: '管理',
+ check: '查看'
+ },
+ teamForm: {
+ form: {
+ userName: {
+ label: '使用者名稱/電子郵件',
+ placeholder: '請輸入成員的使用者名稱或電子郵件',
+ requiredMessage: '請輸入使用者名稱/電子郵件'
+ }
+ }
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/template.ts b/ui/src/locales/lang/zh-Hant/views/template.ts
new file mode 100644
index 000000000..241f9d8c5
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/template.ts
@@ -0,0 +1,83 @@
+export default {
+ title: '模型設定',
+ provider: '供應商',
+ providerPlaceholder: '選擇供應商',
+ addModel: '新增模型',
+ searchBar: {
+ placeholder: '按名稱搜尋'
+ },
+ delete: {
+ confirmTitle: '刪除模型',
+ confirmMessage: '是否刪除模型:'
+ },
+ tip: {
+ createSuccessMessage: '創建模型成功',
+ createErrorMessage: '基礎資訊有填寫錯誤',
+ errorMessage: '變數已存在: ',
+ emptyMessage1: '請先選擇基礎資訊的模型類型和基礎模型',
+ emptyMessage2: '所選模型不支援參數設定',
+ updateSuccessMessage: '修改模型成功',
+ saveSuccessMessage: '模型參數儲存成功',
+ downloadError: '下載失敗',
+ noModel: '模型在Ollama不存在'
+ },
+ model: {
+ allModel: '全部模型',
+ publicModel: '公有模型',
+ privateModel: '私有模型',
+ LLM: '大語言模型',
+ EMBEDDING: '向量模型',
+ RERANKER: '重排模型',
+ STT: '語音辨識',
+ TTS: '語音合成',
+ IMAGE: '圖片理解',
+ TTI: '圖片生成'
+ },
+ templateForm: {
+ title: {
+ baseInfo: '基礎資訊',
+ advancedInfo: '進階設定',
+ modelParams: '模型參數',
+ editParam: '編輯參數',
+ addParam: '新增參數',
+ paramSetting: '模型參數設定',
+ apiParamPassing: '接口傳參'
+ },
+ form: {
+ templateName: {
+ label: '模型名稱',
+ placeholder: '請給基礎模型設定一個名稱',
+ tooltip: 'MaxKB 中自訂的模型名稱',
+ requiredMessage: '模型名稱不能為空'
+ },
+ permissionType: {
+ label: '權限',
+ privateDesc: '僅當前使用者使用',
+ publicDesc: '所有使用者都可使用',
+ requiredMessage: '權限不能為空'
+ },
+ model_type: {
+ label: '模型類型',
+ placeholder: '請選擇模型類型',
+ tooltip1: '大語言模型:在應用中與AI對話的推理模型。',
+ tooltip2: '向量模型:在知識庫中對文件內容進行向量化化的模型。',
+ tooltip3: '語音辨識:在應用中開啟語音辨識後用於語音轉文字的模型。',
+ tooltip4: '語音合成:在應用中開啟語音播放後用於文字轉語音的模型。',
+ tooltip5: '重排模型:在高階編排應用中使用多路召回時,對候選分段進行重新排序的模型。',
+ tooltip6: '圖片理解:在高階編排應用中用於圖片理解的視覺模型。',
+ tooltip7: '圖片生成:在高階編排應用中用於圖片生成的視覺模型。',
+ requiredMessage: '模型類型不能為空'
+ },
+ base_model: {
+ label: '基礎模型',
+ tooltip: '列表中未列出的模型,直接輸入模型名稱,按 Enter 即可新增',
+ placeholder: '自訂輸入基礎模型後按 Enter 即可',
+ requiredMessage: '基礎模型不能為空'
+ }
+ }
+ },
+ download: {
+ downloading: '正在下載中',
+ cancelDownload: '取消下載'
+ }
+}
diff --git a/ui/src/locales/lang/zh-Hant/views/user.ts b/ui/src/locales/lang/zh-Hant/views/user.ts
new file mode 100644
index 000000000..18ea3326a
--- /dev/null
+++ b/ui/src/locales/lang/zh-Hant/views/user.ts
@@ -0,0 +1,68 @@
+export default {
+ title: '使用者管理',
+ createUser: '建立使用者',
+ editUser: '編輯使用者',
+ setting: {
+ updatePwd: '修改使用者密碼'
+ },
+ tip: {
+ professionalMessage: '社群版最多支援 2 個使用者,如需擁有更多使用者,請升級為專業版。',
+ updatePwdSuccess: '使用者密碼修改成功'
+ },
+ delete: {
+ confirmTitle: '是否刪除該使用者?',
+ confirmMessage:
+ '刪除該使用者後,該使用者建立的所有資源(應用、知識庫、模型)都會被刪除,請謹慎操作。'
+ },
+ disabled: {
+ confirmTitle: '是否停用函數?',
+ confirmMessage: '停用後,引用該函數的應用在查詢時會報錯,請謹慎操作。'
+ },
+ userForm: {
+ form: {
+ username: {
+ label: '使用者名稱',
+ placeholder: '請輸入使用者名稱',
+ requiredMessage: '請輸入使用者名稱',
+ lengthMessage: '長度須介於 6 到 20 個字元之間'
+ },
+ nick_name: {
+ label: '姓名',
+ placeholder: '請輸入姓名'
+ },
+ email: {
+ label: '電子信箱',
+ placeholder: '請輸入電子信箱',
+ requiredMessage: '請輸入電子信箱'
+ },
+ phone: {
+ label: '手機號碼',
+ placeholder: '請輸入手機號碼'
+ },
+ password: {
+ label: '登入密碼',
+ placeholder: '請輸入密碼',
+ requiredMessage: '請輸入密碼',
+ lengthMessage: '長度須介於 6 到 20 個字元之間'
+ },
+ new_password: {
+ label: '新密碼',
+ placeholder: '請輸入新密碼',
+ requiredMessage: '請輸入新密碼'
+ },
+ re_password: {
+ label: '確認密碼',
+ placeholder: '請輸入確認密碼',
+ requiredMessage: '請輸入確認密碼',
+ validatorMessage: '密碼不一致'
+ }
+ }
+ },
+ source: {
+ label: '使用者類型',
+ local: '系統使用者',
+ wecom: '企業微信',
+ lark: '飛書',
+ dingtalk: '釘釘'
+ }
+}
diff --git a/ui/src/locales/useLocale.ts b/ui/src/locales/useLocale.ts
new file mode 100644
index 000000000..d01ec8643
--- /dev/null
+++ b/ui/src/locales/useLocale.ts
@@ -0,0 +1,28 @@
+import { useLocalStorage } from '@vueuse/core';
+import { computed } from 'vue';
+import { useI18n } from 'vue-i18n';
+import { i18n, langCode, localeConfigKey } from '@/locales/index';
+
+export function useLocale() {
+ const { locale } = useI18n({ useScope: 'global' });
+ function changeLocale(lang: string) {
+ // 如果切换的语言不在对应语言文件里则默认为简体中文
+ if (!langCode.includes(lang)) {
+ lang = 'en-US';
+ }
+
+ locale.value = lang;
+ useLocalStorage(localeConfigKey, 'en-US').value = lang;
+ }
+
+ const getComponentsLocale = computed(() => {
+ const localeMessage = i18n.global.getLocaleMessage(locale.value) as Record;
+ return localeMessage.componentsLocale;
+ });
+
+ return {
+ changeLocale,
+ getComponentsLocale,
+ locale,
+ };
+}
diff --git a/ui/src/main.ts b/ui/src/main.ts
index 5dcad83c3..b47fbf0cf 100644
--- a/ui/src/main.ts
+++ b/ui/src/main.ts
@@ -1,14 +1,29 @@
-import './assets/main.css'
-
+import '@/styles/index.scss'
+import ElementPlus from 'element-plus'
+import * as ElementPlusIcons from '@element-plus/icons-vue'
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
+import enUs from 'element-plus/es/locale/lang/en'
+import zhTW from 'element-plus/es/locale/lang/zh-tw'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
-
import App from './App.vue'
-import router from './router'
-
+import router from '@/router'
+import i18n from '@/locales'
+import Components from '@/components'
const app = createApp(App)
-
app.use(createPinia())
+for (const [key, component] of Object.entries(ElementPlusIcons)) {
+ app.component(key, component)
+}
+const locale_map: any = {
+ 'zh-CN': zhCn,
+ 'zh-Hant': zhTW,
+ 'en-US': enUs
+}
+app.use(ElementPlus, {
+ locale: locale_map[localStorage.getItem('MaxKB-locale') || navigator.language || 'en-US']
+})
app.use(router)
-
+app.use(i18n)
+app.use(Components)
app.mount('#app')
diff --git a/ui/src/router/index.ts b/ui/src/router/index.ts
index 3e49915ca..40f33d09e 100644
--- a/ui/src/router/index.ts
+++ b/ui/src/router/index.ts
@@ -1,23 +1,9 @@
import { createRouter, createWebHistory } from 'vue-router'
-import HomeView from '../views/HomeView.vue'
+import { routes } from '@/router/routes'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
- routes: [
- {
- path: '/',
- name: 'home',
- component: HomeView,
- },
- {
- path: '/about',
- name: 'about',
- // route level code-splitting
- // this generates a separate chunk (About.[hash].js) for this route
- // which is lazy-loaded when the route is visited.
- component: () => import('../views/AboutView.vue'),
- },
- ],
+ routes: routes,
})
export default router
diff --git a/ui/src/router/routes.ts b/ui/src/router/routes.ts
new file mode 100644
index 000000000..e32cf4b1f
--- /dev/null
+++ b/ui/src/router/routes.ts
@@ -0,0 +1,32 @@
+import type { RouteRecordRaw } from 'vue-router'
+// const modules: any = import.meta.glob('./modules/*.ts', { eager: true })
+// const rolesRoutes: RouteRecordRaw[] = [...Object.keys(modules).map((key) => modules[key].default)]
+
+export const routes: Array = [
+ {
+ path: '/',
+ name: 'home',
+ component: () => import('@/views/HomeView.vue'),
+ },
+
+ {
+ path: '/login',
+ name: 'login',
+ component: () => import('@/views/login/index.vue'),
+ },
+ {
+ path: '/forget_password',
+ name: 'ForgetPassword',
+ component: () => import('@/views/login/ForgetPassword.vue')
+ },
+ {
+ path: '/reset_password/:code/:email',
+ name: 'ResetPassword',
+ component: () => import('@/views/login/ResetPassword.vue')
+ },
+ // {
+ // path: '/:pathMatch(.*)',
+ // name: '404',
+ // component: () => import('@/views/404/index.vue')
+ // }
+]
diff --git a/ui/src/stores/counter.ts b/ui/src/stores/counter.ts
deleted file mode 100644
index b6757ba57..000000000
--- a/ui/src/stores/counter.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { ref, computed } from 'vue'
-import { defineStore } from 'pinia'
-
-export const useCounterStore = defineStore('counter', () => {
- const count = ref(0)
- const doubleCount = computed(() => count.value * 2)
- function increment() {
- count.value++
- }
-
- return { count, doubleCount, increment }
-})
diff --git a/ui/src/stores/index.ts b/ui/src/stores/index.ts
new file mode 100644
index 000000000..9f0d07740
--- /dev/null
+++ b/ui/src/stores/index.ts
@@ -0,0 +1,9 @@
+import useLoginStore from './modules/login'
+import useUserStore from './modules/user'
+
+const useStore = () => ({
+ login: useLoginStore(),
+ user: useUserStore(),
+})
+
+export default useStore
diff --git a/ui/src/stores/modules/login.ts b/ui/src/stores/modules/login.ts
new file mode 100644
index 000000000..c116db2c9
--- /dev/null
+++ b/ui/src/stores/modules/login.ts
@@ -0,0 +1,210 @@
+import { defineStore } from 'pinia'
+import { type Ref } from 'vue'
+// import type { User } from '@/api/type/user'
+// import { cloneDeep } from 'lodash'
+// import UserApi from '@/api/user'
+// import ThemeApi from '@/api/theme'
+// import { useElementPlusTheme } from 'use-element-plus-theme'
+// import { defaultPlatformSetting } from '@/utils/theme'
+import { useLocalStorage } from '@vueuse/core'
+import { localeConfigKey, getBrowserLang } from '@/locales/index'
+export interface userStateTypes {
+ userType: number // 1 系统操作者 2 对话用户
+ // userInfo: User | null
+ token: any
+ version?: string
+ userAccessToken?: string
+ XPACK_LICENSE_IS_VALID: false
+ isXPack: false
+ themeInfo: any
+}
+
+const useLoginStore = defineStore('login',{
+ state: (): userStateTypes => ({
+ userType: 1,
+ // userInfo: null,
+ token: '',
+ version: '',
+ userAccessToken: '',
+ XPACK_LICENSE_IS_VALID: false,
+ isXPack: false,
+ themeInfo: null
+ }),
+ actions: {
+ // getLanguage() {
+ // return this.userType === 1
+ // ? localStorage.getItem('MaxKB-locale') || getBrowserLang()
+ // : sessionStorage.getItem('language') || getBrowserLang()
+ // },
+ // showXpack() {
+ // return this.isXPack
+ // },
+ // isDefaultTheme() {
+ // return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF'
+ // },
+ // setTheme(data: any) {
+ // const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme)
+ // changeTheme(data?.['theme'])
+ // this.themeInfo = cloneDeep(data)
+ // },
+ // isExpire() {
+ // return this.isXPack && !this.XPACK_LICENSE_IS_VALID
+ // },
+ // isEnterprise() {
+ // return this.isXPack && this.XPACK_LICENSE_IS_VALID
+ // },
+ // getToken(): String | null {
+ // if (this.token) {
+ // return this.token
+ // }
+ // return this.userType === 1 ? localStorage.getItem('token') : this.getAccessToken()
+ // },
+ // getAccessToken() {
+ // const token = sessionStorage.getItem(`${this.userAccessToken}-accessToken`)
+ // if (token) {
+ // return token
+ // }
+ // const local_token = localStorage.getItem(`${token}-accessToken`)
+ // if (local_token) {
+ // return local_token
+ // }
+ // return localStorage.getItem(`accessToken`)
+ // },
+
+ // getPermissions() {
+ // if (this.userInfo) {
+ // return this.isXPack && this.XPACK_LICENSE_IS_VALID
+ // ? [...this.userInfo?.permissions, 'x-pack']
+ // : this.userInfo?.permissions
+ // } else {
+ // return []
+ // }
+ // },
+ // getRole() {
+ // if (this.userInfo) {
+ // return this.userInfo?.role
+ // } else {
+ // return ''
+ // }
+ // },
+ // changeUserType(num: number, token?: string) {
+ // this.userType = num
+ // this.userAccessToken = token
+ // },
+
+ // async asyncGetProfile() {
+ // return new Promise((resolve, reject) => {
+ // UserApi.getProfile()
+ // .then(async (ok) => {
+ // this.version = ok.data?.version || '-'
+ // this.isXPack = ok.data?.IS_XPACK
+ // this.XPACK_LICENSE_IS_VALID = ok.data?.XPACK_LICENSE_IS_VALID
+
+ // if (this.isEnterprise()) {
+ // await this.theme()
+ // } else {
+ // this.themeInfo = {
+ // ...defaultPlatformSetting
+ // }
+ // }
+ // resolve(ok)
+ // })
+ // .catch((error) => {
+ // reject(error)
+ // })
+ // })
+ // },
+
+ // async theme(loading?: Ref) {
+ // return await ThemeApi.getThemeInfo(loading).then((ok) => {
+ // this.setTheme(ok.data)
+ // // window.document.title = this.themeInfo['title'] || 'MaxKB'
+ // // const link = document.querySelector('link[rel="icon"]') as any
+ // // if (link) {
+ // // link['href'] = this.themeInfo['icon'] || '/favicon.ico'
+ // // }
+ // })
+ // },
+
+ // async profile() {
+ // return UserApi.profile().then(async (ok) => {
+ // this.userInfo = ok.data
+ // useLocalStorage(localeConfigKey, 'en-US').value = ok.data?.language || this.getLanguage()
+ // return this.asyncGetProfile()
+ // })
+ // },
+
+ // async login(auth_type: string, username: string, password: string) {
+ // return UserApi.login(auth_type, { username, password }).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+ // async dingCallback(code: string) {
+ // return UserApi.getDingCallback(code).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+ // async dingOauth2Callback(code: string) {
+ // return UserApi.getDingOauth2Callback(code).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+ // async wecomCallback(code: string) {
+ // return UserApi.getWecomCallback(code).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+ // async larkCallback(code: string) {
+ // return UserApi.getlarkCallback(code).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+
+ // async logout() {
+ // return UserApi.logout().then(() => {
+ // localStorage.removeItem('token')
+ // return true
+ // })
+ // },
+ // async getAuthType() {
+ // return UserApi.getAuthType().then((ok) => {
+ // return ok.data
+ // })
+ // },
+ // async getQrType() {
+ // return UserApi.getQrType().then((ok) => {
+ // return ok.data
+ // })
+ // },
+ // async getQrSource() {
+ // return UserApi.getQrSource().then((ok) => {
+ // return ok.data
+ // })
+ // },
+ // async postUserLanguage(lang: string, loading?: Ref) {
+ // return new Promise((resolve, reject) => {
+ // UserApi.postLanguage({ language: lang }, loading)
+ // .then(async (ok) => {
+ // useLocalStorage(localeConfigKey, 'en-US').value = lang
+ // window.location.reload()
+ // resolve(ok)
+ // })
+ // .catch((error) => {
+ // reject(error)
+ // })
+ // })
+ // }
+ }
+})
+
+export default useLoginStore
diff --git a/ui/src/stores/modules/user.ts b/ui/src/stores/modules/user.ts
new file mode 100644
index 000000000..08ce5910b
--- /dev/null
+++ b/ui/src/stores/modules/user.ts
@@ -0,0 +1,210 @@
+import { defineStore } from 'pinia'
+import { type Ref } from 'vue'
+// import type { User } from '@/api/type/user'
+import { cloneDeep } from 'lodash'
+// import UserApi from '@/api/user'
+// import ThemeApi from '@/api/theme'
+// import { useElementPlusTheme } from 'use-element-plus-theme'
+// import { defaultPlatformSetting } from '@/utils/theme'
+import { useLocalStorage } from '@vueuse/core'
+import { localeConfigKey, getBrowserLang } from '@/locales/index'
+export interface userStateTypes {
+ userType: number // 1 系统操作者 2 对话用户
+ // userInfo: User | null
+ token: any
+ version?: string
+ userAccessToken?: string
+ XPACK_LICENSE_IS_VALID: false
+ isXPack: false
+ themeInfo: any
+}
+
+const useLoginStore = defineStore('user', {
+ state: (): userStateTypes => ({
+ userType: 1,
+ // userInfo: null,
+ token: '',
+ version: '',
+ userAccessToken: '',
+ XPACK_LICENSE_IS_VALID: false,
+ isXPack: false,
+ themeInfo: null
+ }),
+ actions: {
+ getLanguage() {
+ return this.userType === 1
+ ? localStorage.getItem('MaxKB-locale') || getBrowserLang()
+ : sessionStorage.getItem('language') || getBrowserLang()
+ },
+ // showXpack() {
+ // return this.isXPack
+ // },
+ isDefaultTheme() {
+ return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF'
+ },
+ // setTheme(data: any) {
+ // const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme)
+ // changeTheme(data?.['theme'])
+ // this.themeInfo = cloneDeep(data)
+ // },
+ // isExpire() {
+ // return this.isXPack && !this.XPACK_LICENSE_IS_VALID
+ // },
+ // isEnterprise() {
+ // return this.isXPack && this.XPACK_LICENSE_IS_VALID
+ // },
+ // getToken(): String | null {
+ // if (this.token) {
+ // return this.token
+ // }
+ // return this.userType === 1 ? localStorage.getItem('token') : this.getAccessToken()
+ // },
+ // getAccessToken() {
+ // const token = sessionStorage.getItem(`${this.userAccessToken}-accessToken`)
+ // if (token) {
+ // return token
+ // }
+ // const local_token = localStorage.getItem(`${token}-accessToken`)
+ // if (local_token) {
+ // return local_token
+ // }
+ // return localStorage.getItem(`accessToken`)
+ // },
+
+ // getPermissions() {
+ // if (this.userInfo) {
+ // return this.isXPack && this.XPACK_LICENSE_IS_VALID
+ // ? [...this.userInfo?.permissions, 'x-pack']
+ // : this.userInfo?.permissions
+ // } else {
+ // return []
+ // }
+ // },
+ // getRole() {
+ // if (this.userInfo) {
+ // return this.userInfo?.role
+ // } else {
+ // return ''
+ // }
+ // },
+ // changeUserType(num: number, token?: string) {
+ // this.userType = num
+ // this.userAccessToken = token
+ // },
+
+ // async asyncGetProfile() {
+ // return new Promise((resolve, reject) => {
+ // UserApi.getProfile()
+ // .then(async (ok) => {
+ // this.version = ok.data?.version || '-'
+ // this.isXPack = ok.data?.IS_XPACK
+ // this.XPACK_LICENSE_IS_VALID = ok.data?.XPACK_LICENSE_IS_VALID
+
+ // if (this.isEnterprise()) {
+ // await this.theme()
+ // } else {
+ // this.themeInfo = {
+ // ...defaultPlatformSetting
+ // }
+ // }
+ // resolve(ok)
+ // })
+ // .catch((error) => {
+ // reject(error)
+ // })
+ // })
+ // },
+
+ // async theme(loading?: Ref) {
+ // return await ThemeApi.getThemeInfo(loading).then((ok) => {
+ // this.setTheme(ok.data)
+ // // window.document.title = this.themeInfo['title'] || 'MaxKB'
+ // // const link = document.querySelector('link[rel="icon"]') as any
+ // // if (link) {
+ // // link['href'] = this.themeInfo['icon'] || '/favicon.ico'
+ // // }
+ // })
+ // },
+
+ // async profile() {
+ // return UserApi.profile().then(async (ok) => {
+ // this.userInfo = ok.data
+ // useLocalStorage(localeConfigKey, 'en-US').value = ok.data?.language || this.getLanguage()
+ // return this.asyncGetProfile()
+ // })
+ // },
+
+ // async login(auth_type: string, username: string, password: string) {
+ // return UserApi.login(auth_type, { username, password }).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+ // async dingCallback(code: string) {
+ // return UserApi.getDingCallback(code).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+ // async dingOauth2Callback(code: string) {
+ // return UserApi.getDingOauth2Callback(code).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+ // async wecomCallback(code: string) {
+ // return UserApi.getWecomCallback(code).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+ // async larkCallback(code: string) {
+ // return UserApi.getlarkCallback(code).then((ok) => {
+ // this.token = ok.data
+ // localStorage.setItem('token', ok.data)
+ // return this.profile()
+ // })
+ // },
+
+ // async logout() {
+ // return UserApi.logout().then(() => {
+ // localStorage.removeItem('token')
+ // return true
+ // })
+ // },
+ // async getAuthType() {
+ // return UserApi.getAuthType().then((ok) => {
+ // return ok.data
+ // })
+ // },
+ // async getQrType() {
+ // return UserApi.getQrType().then((ok) => {
+ // return ok.data
+ // })
+ // },
+ // async getQrSource() {
+ // return UserApi.getQrSource().then((ok) => {
+ // return ok.data
+ // })
+ // },
+ // async postUserLanguage(lang: string, loading?: Ref) {
+ // return new Promise((resolve, reject) => {
+ // UserApi.postLanguage({ language: lang }, loading)
+ // .then(async (ok) => {
+ // useLocalStorage(localeConfigKey, 'en-US').value = lang
+ // window.location.reload()
+ // resolve(ok)
+ // })
+ // .catch((error) => {
+ // reject(error)
+ // })
+ // })
+ // }
+ }
+})
+
+export default useLoginStore
diff --git a/ui/src/styles/app.scss b/ui/src/styles/app.scss
new file mode 100644
index 000000000..9d1e80bb5
--- /dev/null
+++ b/ui/src/styles/app.scss
@@ -0,0 +1,374 @@
+@font-face {
+ font-family: AlibabaPuHuiTi;
+ src:
+ url('./font/AlibabaPuHuiTi-3-55-Regular.woff') format('woff'),
+ url('./font/AlibabaPuHuiTi-3-55-Regular.ttf') format('truetype'),
+ url('./font/AlibabaPuHuiTi-3-55-Regular.eot') format('eot'),
+ url('./font/AlibabaPuHuiTi-3-55-Regular.otf') format('opentype'),
+ url('./font/AlibabaPuHuiTi-3-55-Regular.woff2') format('woff2');
+}
+* {
+ margin: 0;
+ padding: 0;
+}
+
+html {
+ height: 100%;
+ box-sizing: border-box;
+ font-size: 100%;
+}
+
+body {
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ font-family: 'PingFang SC', AlibabaPuHuiTi !important;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 500;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ color: var(--app-text-color);
+}
+
+#app {
+ height: 100%;
+}
+
+:focus {
+ outline: none;
+}
+
+a:active {
+ outline: none;
+}
+
+a,
+a:focus,
+a:hover {
+ cursor: pointer;
+ color: inherit;
+ text-decoration: none;
+}
+
+div:focus {
+ outline: none;
+}
+
+ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+/* 滚动条整体部分 */
+::-webkit-scrollbar {
+ width: 6px; // 纵向滚动条宽度
+ height: 6px; // 横向滚动条高度
+}
+
+/* 滑块 */
+::-webkit-scrollbar-thumb {
+ border-radius: 5px;
+}
+
+/* 轨道 */
+::-webkit-scrollbar-track {
+ border-radius: 5px;
+ background-color: transparent;
+}
+
+.clearfix:after {
+ content: '';
+ display: block;
+ clear: both;
+}
+
+h1 {
+ font-size: 24px;
+}
+
+h2 {
+ font-size: 20px;
+ font-weight: 500;
+}
+
+h3 {
+ font-size: 18px;
+}
+
+h4 {
+ font-size: 16px;
+}
+
+h5 {
+ font-size: 14px;
+ font-weight: 500;
+}
+
+.bold {
+ font-weight: 600;
+}
+.lighter {
+ font-weight: 400;
+}
+
+.w-full {
+ width: 100%;
+}
+.h-full {
+ height: 100%;
+}
+.w-120 {
+ width: 120px;
+}
+.w-240 {
+ width: 240px;
+}
+.w-280 {
+ width: 280px;
+}
+.w-500 {
+ width: 500px;
+}
+.max-w-200 {
+ max-width: 200px;
+}
+.max-w-350 {
+ max-width: 350px;
+}
+
+.mt-4 {
+ margin-top: calc(var(--app-base-px) - 4px);
+}
+
+.mt-8 {
+ margin-top: var(--app-base-px);
+}
+.mt-12 {
+ margin-top: calc(var(--app-base-px) + 4px);
+}
+.mt-16 {
+ margin-top: calc(var(--app-base-px) * 2);
+}
+.mt-20 {
+ margin-top: calc(var(--app-base-px) * 2 + 4px);
+}
+.mt-24 {
+ margin-top: calc(var(--app-base-px) * 3);
+}
+
+.mb-4 {
+ margin-bottom: calc(var(--app-base-px) - 4px);
+}
+.mb-8 {
+ margin-bottom: var(--app-base-px);
+}
+.mb-12 {
+ margin-bottom: calc(var(--app-base-px) + 4px);
+}
+.mb-16 {
+ margin-bottom: calc(var(--app-base-px) * 2);
+}
+.mb-24 {
+ margin-bottom: calc(var(--app-base-px) * 3);
+}
+.ml-4 {
+ margin-left: calc(var(--app-base-px) - 4px);
+}
+.ml-8 {
+ margin-left: var(--app-base-px);
+}
+.ml-12 {
+ margin-left: calc(var(--app-base-px) + 4px);
+}
+.ml-16 {
+ margin-left: calc(var(--app-base-px) * 2);
+}
+.ml-24 {
+ margin-left: calc(var(--app-base-px) * 3);
+}
+.mr-4 {
+ margin-right: calc(var(--app-base-px) - 4px);
+}
+.mr-8 {
+ margin-right: var(--app-base-px);
+}
+.mr-12 {
+ margin-right: calc(var(--app-base-px) + 4px);
+}
+.mr-16 {
+ margin-right: calc(var(--app-base-px) * 2);
+}
+.mr-24 {
+ margin-right: calc(var(--app-base-px) * 3);
+}
+.p-8 {
+ padding: var(--app-base-px);
+}
+.p-16 {
+ padding: calc(var(--app-base-px) * 2);
+}
+.p-24 {
+ padding: calc(var(--app-base-px) * 3);
+}
+.p-8-12 {
+ padding: calc(var(--app-base-px)) calc(var(--app-base-px) + 4px);
+}
+.p-12-16 {
+ padding: calc(var(--app-base-px) + 4px) calc(var(--app-base-px) * 2);
+}
+.p-12-24 {
+ padding: calc(var(--app-base-px) + 4px) calc(var(--app-base-px) * 3);
+}
+.p-16-24 {
+ padding: calc(var(--app-base-px) * 2) calc(var(--app-base-px) * 3);
+}
+
+.pt-0 {
+ padding-top: 0;
+}
+.pb-0 {
+ padding-bottom: 0;
+}
+
+.float-right {
+ float: right;
+}
+
+.flex {
+ display: flex;
+}
+
+.flex-center {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.flex-between {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.flex-wrap {
+ display: flex;
+ flex-wrap: wrap;
+ align-content: space-between;
+}
+
+.align-center {
+ align-items: center;
+}
+
+.align-baseline {
+ align-items: baseline;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.text-left {
+ text-align: left;
+}
+.text-center {
+ text-align: center;
+}
+.text-right {
+ text-align: right;
+}
+
+.vertical-middle {
+ vertical-align: middle;
+}
+
+.line-height-22 {
+ line-height: 22px;
+}
+
+.border {
+ border: 1px solid var(--el-border-color);
+}
+
+.border-l {
+ border-left: 1px solid var(--el-border-color);
+}
+
+.border-b {
+ border-bottom: 1px solid var(--el-border-color);
+}
+.border-r {
+ border-right: 1px solid var(--el-border-color);
+}
+.border-t {
+ border-top: 1px solid var(--el-border-color);
+}
+
+.border-b-light {
+ border-bottom: 1px solid var(--el-border-color-lighter);
+}
+.border-r-4 {
+ border-radius: 4px;
+}
+.border-r-8 {
+ border-radius: 8px;
+}
+
+.border-t-dashed {
+ border-top: 1px dashed var(--el-border-color);
+}
+.border-primary {
+ border: 1px solid var(--el-color-primary);
+ color: var(--el-color-primary);
+}
+
+.border-none {
+ border: none;
+}
+
+.cursor {
+ cursor: pointer;
+}
+.notAllowed {
+ cursor: not-allowed;
+}
+
+/*
+ 超出省略号
+*/
+
+.ellipsis {
+ display: inline-block;
+ max-width: 130px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+/*
+ 双行超出省略号,其他行数自定义 -webkit-line-clamp
+*/
+.ellipsis-2 {
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+}
+
+.ellipsis-1 {
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 1;
+ overflow: hidden;
+}
+
+.break-all {
+ word-break: break-all;
+}
+
+.pre-wrap {
+ white-space: pre-wrap;
+}
+
diff --git a/ui/src/styles/element-plus.scss b/ui/src/styles/element-plus.scss
new file mode 100644
index 000000000..e6e06542d
--- /dev/null
+++ b/ui/src/styles/element-plus.scss
@@ -0,0 +1,11 @@
+:root {
+ --el-color-primary: #3370ff;
+ // --el-menu-item-height: 45px;
+ // --el-box-shadow-light: 0px 2px 4px 0px rgba(31, 35, 41, 0.12);
+ // --el-border-color: #dee0e3;
+ // --el-text-color-regular: #1f2329;
+ // --el-color-info: #8f959e !important;
+ // --el-disabled-bg-color: #eff0f1 !important;
+ // --el-text-color-primary: #1f2329;
+ // --el-font-line-height-primary: 22px;
+}
diff --git a/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.eot b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.eot
new file mode 100644
index 000000000..82f27fd78
Binary files /dev/null and b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.eot differ
diff --git a/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.otf b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.otf
new file mode 100644
index 000000000..541e3c108
Binary files /dev/null and b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.otf differ
diff --git a/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.ttf b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.ttf
new file mode 100644
index 000000000..a6eaf3613
Binary files /dev/null and b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.ttf differ
diff --git a/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.woff b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.woff
new file mode 100644
index 000000000..f57637654
Binary files /dev/null and b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.woff differ
diff --git a/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.woff2 b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.woff2
new file mode 100644
index 000000000..4b574fbd8
Binary files /dev/null and b/ui/src/styles/font/AlibabaPuHuiTi-3-55-Regular.woff2 differ
diff --git a/ui/src/styles/index.scss b/ui/src/styles/index.scss
new file mode 100644
index 000000000..43afaf395
--- /dev/null
+++ b/ui/src/styles/index.scss
@@ -0,0 +1,4 @@
+@use 'element-plus/dist/index.css';
+@use './element-plus.scss';
+@use './variables.scss';
+@use './app.scss';
diff --git a/ui/src/styles/variables.scss b/ui/src/styles/variables.scss
new file mode 100644
index 000000000..f2c2a0ade
--- /dev/null
+++ b/ui/src/styles/variables.scss
@@ -0,0 +1,53 @@
+:root {
+ --app-base-px: 8px;
+ --app-layout-bg-color: #f5f6f7;
+ --app-text-color: #1f2329;
+ --app-text-color-light-1: rgba(31, 35, 41, 0.1);
+ --app-text-color-secondary: #646a73;
+ --app-text-color-disable: #bbbfc4;
+ --app-input-color-placeholder: #8f959e;
+ --app-view-padding: 24px;
+ --app-view-bg-color: #ffffff;
+ --app-border-color-dark: #bbbfc4;
+ --md-bk-hover-color:var(--el-border-color-hover);
+ /** header 组件 */
+ --app-header-height: 56px;
+ --app-header-padding: 0 20px;
+ --app-header-bg-color: linear-gradient(90deg, #ebf1ff 24.34%, #e5fbf8 56.18%, #f2ebfe 90.18%);
+ --app-logo-color: linear-gradient(180deg, #3370FF 0%, #7f3bf5 100%);
+ --app-avatar-gradient-color: linear-gradient(270deg, #9258f7 0%, #3370FF 100%);
+
+ /* 计算高度 */
+ --app-main-height: calc(100vh - var(--app-header-height) - var(--app-view-padding) * 2 - 40px);
+
+ /** sidebar 组件 */
+ --sidebar-bg-color: #ffffff;
+ --sidebar-width: 240px;
+ /** tag */
+ --tag-default-bg: rgba(51, 112, 255, 0.2);
+ --tag-default-color: #2b5fd9;
+ --tag-success-bg: rgba(52, 199, 36, 0.2);
+ --tag-success-color: #2ca91f;
+ --tag-warning-bg: rgba(255, 136, 0, 0.2);
+ --tag-warning-color: #d97400;
+ --tag-danger-bg: rgba(245, 74, 69, 0.2);
+
+ /** card */
+ --card-width: 330px;
+ --card-min-height: 166px;
+ --card-min-width: 220px;
+
+ /** setting */
+ --setting-left-width: 280px;
+
+ /** dataset */
+ --create-dataset-height: calc(var(--app-main-height) - 70px);
+
+ /** ai-chat */
+ --dialog-bg-gradient-color: linear-gradient(
+ 188deg,
+ rgba(235, 241, 255, 0.2) 39.6%,
+ rgba(231, 249, 255, 0.2) 94.3%
+ ),
+ #eff0f1;
+}
diff --git a/ui/src/utils/theme.ts b/ui/src/utils/theme.ts
new file mode 100644
index 000000000..067bf3a4a
--- /dev/null
+++ b/ui/src/utils/theme.ts
@@ -0,0 +1,65 @@
+import { t } from '@/locales'
+
+export const themeList = [
+ {
+ label: t('views.system.theme.default'),
+ value: '#3370FF',
+ loginBackground: 'default',
+ },
+ {
+ label: t('views.system.theme.orange'),
+ value: '#FF8800',
+ loginBackground: 'orange',
+ },
+ {
+ label: t('views.system.theme.green'),
+ value: '#00B69D',
+ loginBackground: 'green',
+ },
+ {
+ label: t('views.system.theme.purple'),
+ value: '#7F3BF5',
+ loginBackground: 'purple',
+ },
+ {
+ label: t('views.system.theme.red'),
+ value: '#F01D94',
+ loginBackground: 'red',
+ },
+]
+
+export function getThemeImg(val: string) {
+ if (!val) return 'default'
+ return themeList.filter((v) => v.value === val)?.[0]?.loginBackground || 'default'
+}
+
+export const defaultSetting = {
+ icon: '',
+ loginLogo: '',
+ loginImage: '',
+ title: 'MaxKB',
+ slogan: t('views.system.theme.defaultSlogan'),
+}
+
+export const defaultPlatformSetting = {
+ showUserManual: true,
+ userManualUrl: t('layout.userManualUrl'),
+ showForum: true,
+ forumUrl: t('layout.forumUrl'),
+ showProject: true,
+ projectUrl: 'https://github.com/1Panel-dev/MaxKB',
+}
+
+export function hexToRgba(hex?: string, alpha?: number) {
+ // 将16进制颜色值的两个字符一起转换成十进制
+ if (!hex) {
+ return ''
+ } else {
+ const r = parseInt(hex.slice(1, 3), 16)
+ const g = parseInt(hex.slice(3, 5), 16)
+ const b = parseInt(hex.slice(5, 7), 16)
+
+ // 返回RGBA格式的字符串
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`
+ }
+}
diff --git a/ui/src/views/AboutView.vue b/ui/src/views/AboutView.vue
deleted file mode 100644
index 756ad2a17..000000000
--- a/ui/src/views/AboutView.vue
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
This is an about page
-
-
-
-
diff --git a/ui/src/views/HomeView.vue b/ui/src/views/HomeView.vue
index d5c0217e4..197bae0e3 100644
--- a/ui/src/views/HomeView.vue
+++ b/ui/src/views/HomeView.vue
@@ -1,9 +1,3 @@
-
+
-
-
-
-
-
+首页
diff --git a/ui/src/views/login/ForgetPassword.vue b/ui/src/views/login/ForgetPassword.vue
new file mode 100644
index 000000000..2c2ff0257
--- /dev/null
+++ b/ui/src/views/login/ForgetPassword.vue
@@ -0,0 +1,135 @@
+
+
+
+ {{ $t('views.login.resetPassword') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ $t('common.confirm')
+ }}
+
+
+ {{ $t('views.login.buttons.backLogin') }}
+
+
+
+
+
+
+
diff --git a/ui/src/views/login/ResetPassword.vue b/ui/src/views/login/ResetPassword.vue
new file mode 100644
index 000000000..2c2ff0257
--- /dev/null
+++ b/ui/src/views/login/ResetPassword.vue
@@ -0,0 +1,135 @@
+
+
+
+ {{ $t('views.login.resetPassword') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ $t('common.confirm')
+ }}
+
+
+ {{ $t('views.login.buttons.backLogin') }}
+
+
+
+
+
+
+
diff --git a/ui/src/views/login/components/LoginContainer.vue b/ui/src/views/login/components/LoginContainer.vue
new file mode 100644
index 000000000..0415bdc96
--- /dev/null
+++ b/ui/src/views/login/components/LoginContainer.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
diff --git a/ui/src/views/login/components/LoginLayout.vue b/ui/src/views/login/components/LoginLayout.vue
new file mode 100644
index 000000000..e176cc943
--- /dev/null
+++ b/ui/src/views/login/components/LoginLayout.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ lang.label
+ }}
+
+
+
+
+
+
+
+
+ {{ currentLanguage }}
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/views/login/index.vue b/ui/src/views/login/index.vue
new file mode 100644
index 000000000..875bd4288
--- /dev/null
+++ b/ui/src/views/login/index.vue
@@ -0,0 +1,128 @@
+
+
+
+ {{ $t('views.login.title') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ $t('views.login.buttons.login') }}
+
+
+
+
+ {{ $t('views.login.forgotPassword') }}?
+
+
+
+
+
+
+
+
diff --git a/ui/vite.config.ts b/ui/vite.config.ts
index d49d70842..00e2415ab 100644
--- a/ui/vite.config.ts
+++ b/ui/vite.config.ts
@@ -1,20 +1,52 @@
import { fileURLToPath, URL } from 'node:url'
-
-import { defineConfig } from 'vite'
+import type { ProxyOptions } from 'vite'
+import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
-import vueDevTools from 'vite-plugin-vue-devtools'
+import DefineOptions from 'unplugin-vue-define-options/vite'
+// import vueDevTools from 'vite-plugin-vue-devtools'
+const envDir = './env'
// https://vite.dev/config/
-export default defineConfig({
- plugins: [
- vue(),
- vueJsx(),
- vueDevTools(),
- ],
- resolve: {
- alias: {
- '@': fileURLToPath(new URL('./src', import.meta.url))
+export default defineConfig(({ mode }) => {
+ const ENV = loadEnv(mode, envDir)
+ const prefix = process.env.VITE_DYNAMIC_PREFIX || ENV.VITE_BASE_PATH
+ const proxyConf: Record = {}
+ proxyConf['/api'] = {
+ target: 'http://127.0.0.1:8080',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'),
+ }
+ proxyConf['/doc'] = {
+ target: 'http://127.0.0.1:8080',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'),
+ }
+ proxyConf['/static'] = {
+ target: 'http://127.0.0.1:8080',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'),
+ }
+ return {
+ preflight: false,
+ lintOnSave: false,
+ base: prefix,
+ envDir: envDir,
+ plugins: [vue(), vueJsx(), DefineOptions()],
+ server: {
+ cors: true,
+ host: '0.0.0.0',
+ port: Number(ENV.VITE_APP_PORT),
+ strictPort: true,
+ proxy: proxyConf,
},
- },
+ build: {
+ outDir: 'dist/ui',
+ },
+ resolve: {
+ alias: {
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
+ },
+ },
+ }
})