mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
i18n (#1444)
* adapt not input type * adapt not input type * file i18n * publish i18n * translate * i18n
This commit is contained in:
2
.vscode/i18n-ally-custom-framework.yml
vendored
2
.vscode/i18n-ally-custom-framework.yml
vendored
@@ -21,6 +21,8 @@ usageMatchRegex:
|
|||||||
- "[^\\w\\d]appT\\(['\"`]({key})['\"`]"
|
- "[^\\w\\d]appT\\(['\"`]({key})['\"`]"
|
||||||
# 支持 datasetT("your.i18n.keys")
|
# 支持 datasetT("your.i18n.keys")
|
||||||
- "[^\\w\\d]datasetT\\(['\"`]({key})['\"`]"
|
- "[^\\w\\d]datasetT\\(['\"`]({key})['\"`]"
|
||||||
|
- "[^\\w\\d]fileT\\(['\"`]({key})['\"`]"
|
||||||
|
- "[^\\w\\d]publishT\\(['\"`]({key})['\"`]"
|
||||||
|
|
||||||
# A RegEx to set a custom scope range. This scope will be used as a prefix when detecting keys
|
# A RegEx to set a custom scope range. This scope will be used as a prefix when detecting keys
|
||||||
# and works like how the i18next framework identifies the namespace scope from the
|
# and works like how the i18next framework identifies the namespace scope from the
|
||||||
|
@@ -4,7 +4,7 @@ export enum BucketNameEnum {
|
|||||||
}
|
}
|
||||||
export const bucketNameMap = {
|
export const bucketNameMap = {
|
||||||
[BucketNameEnum.dataset]: {
|
[BucketNameEnum.dataset]: {
|
||||||
label: 'common.file.bucket.dataset'
|
label: 'file.bucket.dataset'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -13,36 +13,36 @@ export enum MongoImageTypeEnum {
|
|||||||
}
|
}
|
||||||
export const mongoImageTypeMap = {
|
export const mongoImageTypeMap = {
|
||||||
[MongoImageTypeEnum.systemAvatar]: {
|
[MongoImageTypeEnum.systemAvatar]: {
|
||||||
label: 'common.file.type.appAvatar',
|
label: 'appAvatar',
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
[MongoImageTypeEnum.appAvatar]: {
|
[MongoImageTypeEnum.appAvatar]: {
|
||||||
label: 'common.file.type.appAvatar',
|
label: 'appAvatar',
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
[MongoImageTypeEnum.pluginAvatar]: {
|
[MongoImageTypeEnum.pluginAvatar]: {
|
||||||
label: 'common.file.type.pluginAvatar',
|
label: 'pluginAvatar',
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
[MongoImageTypeEnum.datasetAvatar]: {
|
[MongoImageTypeEnum.datasetAvatar]: {
|
||||||
label: 'common.file.type.datasetAvatar',
|
label: 'datasetAvatar',
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
[MongoImageTypeEnum.userAvatar]: {
|
[MongoImageTypeEnum.userAvatar]: {
|
||||||
label: 'common.file.type.userAvatar',
|
label: 'userAvatar',
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
[MongoImageTypeEnum.teamAvatar]: {
|
[MongoImageTypeEnum.teamAvatar]: {
|
||||||
label: 'common.file.type.teamAvatar',
|
label: 'teamAvatar',
|
||||||
unique: true
|
unique: true
|
||||||
},
|
},
|
||||||
|
|
||||||
[MongoImageTypeEnum.chatImage]: {
|
[MongoImageTypeEnum.chatImage]: {
|
||||||
label: 'common.file.type.chatImage',
|
label: 'chatImage',
|
||||||
unique: false
|
unique: false
|
||||||
},
|
},
|
||||||
[MongoImageTypeEnum.collectionImage]: {
|
[MongoImageTypeEnum.collectionImage]: {
|
||||||
label: 'common.file.type.collectionImage',
|
label: 'collectionImage',
|
||||||
unique: false
|
unique: false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
23
projects/app/i18n/en/file.json
Normal file
23
projects/app/i18n/en/file.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"Click to view file": "Click to view the original file",
|
||||||
|
"Release the mouse to upload the file": "Release the mouse to upload the file",
|
||||||
|
"upload error description": "Only supports uploading multiple files or one folder at a time",
|
||||||
|
|
||||||
|
"Empty file tip": "The file content is empty, the file may not be readable or it may be a pure image file.",
|
||||||
|
"File Content": "File Content",
|
||||||
|
"File Name": "File Name",
|
||||||
|
"File Size": "File Size",
|
||||||
|
"File content can not be empty": "File content cannot be empty",
|
||||||
|
"Filename Can not Be Empty": "Filename cannot be empty",
|
||||||
|
"Read File Error": "File parsing failed",
|
||||||
|
"Select and drag file tip": "Click or drag files here to upload",
|
||||||
|
"Select failed": "File selection failed",
|
||||||
|
"Select file amount limit": "You can select up to {{max}} files",
|
||||||
|
"Select file amount limit 100": "You can select up to 100 files at a time",
|
||||||
|
"Some file count exceeds limit": "Exceeds {{maxCount}} files, automatically truncated",
|
||||||
|
"Some file size exceeds limit": "Some files exceed: {{maxSize}}, have been filtered",
|
||||||
|
"Support file type": "Supports {{fileType}} type files",
|
||||||
|
"Support max count": "Supports up to {{maxCount}} files.",
|
||||||
|
"Support max size": "Maximum size per file: {{maxSize}}.",
|
||||||
|
"Upload failed": "Upload failed"
|
||||||
|
}
|
22
projects/app/i18n/en/publish.json
Normal file
22
projects/app/i18n/en/publish.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"Copy IFrame": "Embed webpage",
|
||||||
|
"Copy Link": "Copy",
|
||||||
|
"Create API Key": "Create new Key",
|
||||||
|
"Create Link": "Create link",
|
||||||
|
"Default Response": "Default Response",
|
||||||
|
"Delete Link": "Delete link",
|
||||||
|
"Edit API Key": "Edit Key information",
|
||||||
|
"Edit IFrame Link": "Update embed link",
|
||||||
|
"Edit Link": "Edit",
|
||||||
|
"Edit Share Window": "Update share window",
|
||||||
|
"Feishu name": "Lark",
|
||||||
|
"Link Name": "Name of the share link",
|
||||||
|
"QPM Tips": "How many times per minute can each IP ask at most",
|
||||||
|
"QPM is empty": "QPM cannot be empty",
|
||||||
|
"app key tips": "These keys have the current application identification, refer to the document for specific use ",
|
||||||
|
"key alias": "key alias, for display only ",
|
||||||
|
"key tips": "You can use the API Key to access certain interfaces (you can't access the app, you need to use the API key within the app to access the app)",
|
||||||
|
"token auth": "Token authentication",
|
||||||
|
"token auth Tips": "Identity verification server address, if this value is filled, a request will be sent to the specified server before each conversation to perform identity verification",
|
||||||
|
"token auth use cases": "View usage instructions for identity verification"
|
||||||
|
}
|
@@ -149,26 +149,6 @@
|
|||||||
"Update error": "更新失败",
|
"Update error": "更新失败",
|
||||||
"unKnow": "出现了点意外~"
|
"unKnow": "出现了点意外~"
|
||||||
},
|
},
|
||||||
"export": "",
|
|
||||||
"file": {
|
|
||||||
"Empty file tip": "文件内容为空,可能该文件无法读取或为纯图片文件内容。",
|
|
||||||
"File Content": "文件内容",
|
|
||||||
"File Name": "文件名",
|
|
||||||
"File Size": "文件大小",
|
|
||||||
"File content can not be empty": "文件内容不能为空",
|
|
||||||
"Filename Can not Be Empty": "文件名不能为空",
|
|
||||||
"Read File Error": "解析文件失败",
|
|
||||||
"Select and drag file tip": "点击或拖动文件到此处上传",
|
|
||||||
"Select failed": "选择文件异常",
|
|
||||||
"Select file amount limit": "最多选择 {{max}} 个文件",
|
|
||||||
"Select file amount limit 100": "每次最多选择100个文件",
|
|
||||||
"Some file count exceeds limit": "超出{{maxCount}}个文件,已自动截取",
|
|
||||||
"Some file size exceeds limit": "部分文件超出: {{maxSize}},已被过滤",
|
|
||||||
"Support file type": "支持 {{fileType}} 类型文件",
|
|
||||||
"Support max count": "最多支持 {{maxCount}} 个文件。",
|
|
||||||
"Support max size": "单个文件最大 {{maxSize}}。",
|
|
||||||
"Upload failed": "上传异常"
|
|
||||||
},
|
|
||||||
"folder": {
|
"folder": {
|
||||||
"Drag Tip": "点我可拖动",
|
"Drag Tip": "点我可拖动",
|
||||||
"Move Success": "移动成功",
|
"Move Success": "移动成功",
|
||||||
@@ -663,7 +643,6 @@
|
|||||||
"Estimated Price Tips": "QA计费为\n输入: {{charsPointsPrice}}积分/1k Tokens",
|
"Estimated Price Tips": "QA计费为\n输入: {{charsPointsPrice}}积分/1k Tokens",
|
||||||
"Estimated points": "预估消耗 {{points}} 积分",
|
"Estimated points": "预估消耗 {{points}} 积分",
|
||||||
"Fetch Error": "获取链接失败",
|
"Fetch Error": "获取链接失败",
|
||||||
"Fetch Url": "网络链接",
|
|
||||||
"Fetch url placeholder": "最多10个链接,每行一个。",
|
"Fetch url placeholder": "最多10个链接,每行一个。",
|
||||||
"Fetch url tip": "仅支持读取静态链接,请注意检查结果",
|
"Fetch url tip": "仅支持读取静态链接,请注意检查结果",
|
||||||
"File chunk amount": "分段: {{amount}}",
|
"File chunk amount": "分段: {{amount}}",
|
||||||
@@ -1208,73 +1187,6 @@
|
|||||||
"overSize": "团队成员超出上限"
|
"overSize": "团队成员超出上限"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"file": {
|
|
||||||
"Click to download file template": "点击下载模板:{{name}}",
|
|
||||||
"Click to view file": "点击查看原始文件",
|
|
||||||
"Create File": "创建新文件",
|
|
||||||
"Create file": "创建文件",
|
|
||||||
"Drag and drop": "拖拽文件至此",
|
|
||||||
"Fetch Url": "链接读取",
|
|
||||||
"If the imported file is garbled, please convert CSV to UTF-8 encoding format": "如果导入文件乱码,请将 CSV 转成 UTF-8 编码格式",
|
|
||||||
"Parse": "{{name}} 解析中...",
|
|
||||||
"Release the mouse to upload the file": "松开鼠标上传文件",
|
|
||||||
"Select a maximum of 10 files": "最多选择10个文件",
|
|
||||||
"Uploading": "正在上传 {{name}},进度: {{percent}}%",
|
|
||||||
"max 10": "最多选择 10 个文件",
|
|
||||||
"select a document": "选择文件",
|
|
||||||
"support": "支持 {{fileExtension}} 文件",
|
|
||||||
"upload error description": "单次只支持上传多个文件或者一个文件夹"
|
|
||||||
},
|
|
||||||
"home": {
|
|
||||||
"AI Assistant": "AI 客服",
|
|
||||||
"AI Assistant Desc": "无论对内还是对外,AI 将 24 小时为您的用户提供服务",
|
|
||||||
"Advanced Settings": "高级编排",
|
|
||||||
"Advanced Settings Desc": "基于 Flow 的流程编排模式,让你的 AI 轻松实现数据库查询、IO 操作、联网通信等扩展能力",
|
|
||||||
"Choice Debug": "调试便捷",
|
|
||||||
"Choice Debug Desc": "拥有搜索测试、引用修改、完整对话预览等多种调试途径",
|
|
||||||
"Choice Desc": "",
|
|
||||||
"Choice Extension": "无限扩展",
|
|
||||||
"Choice Extension Desc": "基于 HTTP 实现扩展,轻松实现定制功能",
|
|
||||||
"Choice Fast": "开箱即用",
|
|
||||||
"Choice Fast Desc": "{{title}} 提供开箱即用的可视化操作,点点点即可构建 AI 应用",
|
|
||||||
"Choice Models": "支持多种模型",
|
|
||||||
"Choice Models Desc": "支持 GPT、Claude、Spark、ChatGLM等多模型",
|
|
||||||
"Choice Open": "更开放",
|
|
||||||
"Choice Open Desc": "{{title}} 遵循 Apache License 2.0 开源协议",
|
|
||||||
"Choice QA": "独特的 QA 结构",
|
|
||||||
"Choice QA Desc": "采用 QA 对的结构构建索引,适应问答、阅读等多种场景",
|
|
||||||
"Choice Visual": "可视化工作流",
|
|
||||||
"Choice Visual Desc": "可视化模块操作,轻松实现复杂工作流,让你的 AI 不再单一",
|
|
||||||
"Commercial": "商务咨询",
|
|
||||||
"Community": "社区",
|
|
||||||
"Dateset": "自动数据预处理",
|
|
||||||
"Dateset Desc": "提供手动输入、直接分段、LLM 自动处理和 CSV 等多种数据导入途径",
|
|
||||||
"Docs": "文档",
|
|
||||||
"FastGPT Ability": "{{title}} 能力",
|
|
||||||
"FastGPT Desc": "{{title}} 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!",
|
|
||||||
"Features": "特点",
|
|
||||||
"Footer Developer": "开发者",
|
|
||||||
"Footer Docs": "文档",
|
|
||||||
"Footer FastGPT Cloud": "{{title}} 线上服务",
|
|
||||||
"Footer Feedback": "反馈",
|
|
||||||
"Footer Git": "源码",
|
|
||||||
"Footer Product": "产品",
|
|
||||||
"Footer Support": "支持",
|
|
||||||
"Login": "登录",
|
|
||||||
"Open": "",
|
|
||||||
"OpenAPI": "OpenAPI",
|
|
||||||
"OpenAPI Desc": "与 GPT API 一致的对外接口,助你轻松接入已有应用",
|
|
||||||
"Quickly build AI question and answer library": "快速搭建 AI 问答系统",
|
|
||||||
"Start Now": "立即开始",
|
|
||||||
"Visual AI orchestration": "可视化 AI 编排",
|
|
||||||
"Why FastGPT": "为什么选择 {{title}}",
|
|
||||||
"desc": "基于 LLM 大模型的 AI 知识库问答平台",
|
|
||||||
"navbar": {
|
|
||||||
"Use guidance": "使用引导",
|
|
||||||
"chatbot": "问答机器人"
|
|
||||||
},
|
|
||||||
"slogan": "让 AI 更懂你的知识"
|
|
||||||
},
|
|
||||||
"module": {
|
"module": {
|
||||||
"Confirm Delete Module": "确认删除该自定义模块?",
|
"Confirm Delete Module": "确认删除该自定义模块?",
|
||||||
"Confirm Sync Plugin": "确认同步插件最新信息?插件的连线和输入的内容将会被清空,请确认!",
|
"Confirm Sync Plugin": "确认同步插件最新信息?插件的连线和输入的内容将会被清空,请确认!",
|
||||||
@@ -1299,30 +1211,6 @@
|
|||||||
"Store": "应用市场",
|
"Store": "应用市场",
|
||||||
"Tools": "工具"
|
"Tools": "工具"
|
||||||
},
|
},
|
||||||
"openapi": {
|
|
||||||
"app key tips": "这些 key 已有当前应用标识,具体使用可参考文档",
|
|
||||||
"key alias": "key 的别名,仅用于展示",
|
|
||||||
"key tips": "你可以使用 API 秘钥访问一些特定的接口(无法访问应用,访问应用需使用应用内的API Key)"
|
|
||||||
},
|
|
||||||
"outlink": {
|
|
||||||
"Copy IFrame": "嵌入网页",
|
|
||||||
"Copy Link": "复制",
|
|
||||||
"Create API Key": "创建新 Key",
|
|
||||||
"Create Link": "创建链接",
|
|
||||||
"Delete Link": "删除链接",
|
|
||||||
"Edit API Key": "编辑 Key 信息",
|
|
||||||
"Edit IFrame Link": "更新嵌入链接",
|
|
||||||
"Edit Link": "编辑",
|
|
||||||
"Edit Share Window": "更新分享窗口",
|
|
||||||
"Link Name": "分享链接的名字",
|
|
||||||
"Link is empty": "",
|
|
||||||
"QPM": "",
|
|
||||||
"QPM Tips": "每个 IP 每分钟最多提问多少次",
|
|
||||||
"QPM is empty": "QPM 不能为空",
|
|
||||||
"token auth": "身份验证",
|
|
||||||
"token auth Tips": "身份校验服务器地址,如填写该值,每次对话前都会向指定服务器发送一个请求,进行身份校验",
|
|
||||||
"token auth use cases": "查看身份验证使用说明"
|
|
||||||
},
|
|
||||||
"permission": {
|
"permission": {
|
||||||
"Private": "私有",
|
"Private": "私有",
|
||||||
"Private Tip": "仅自己可用",
|
"Private Tip": "仅自己可用",
|
||||||
|
23
projects/app/i18n/zh/file.json
Normal file
23
projects/app/i18n/zh/file.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"Click to view file": "点击查看原始文件",
|
||||||
|
"Release the mouse to upload the file": "松开鼠标上传文件",
|
||||||
|
"upload error description": "单次只支持上传多个文件或者一个文件夹",
|
||||||
|
|
||||||
|
"Empty file tip": "文件内容为空,可能该文件无法读取或为纯图片文件内容。",
|
||||||
|
"File Content": "文件内容",
|
||||||
|
"File Name": "文件名",
|
||||||
|
"File Size": "文件大小",
|
||||||
|
"File content can not be empty": "文件内容不能为空",
|
||||||
|
"Filename Can not Be Empty": "文件名不能为空",
|
||||||
|
"Read File Error": "解析文件失败",
|
||||||
|
"Select and drag file tip": "点击或拖动文件到此处上传",
|
||||||
|
"Select failed": "选择文件异常",
|
||||||
|
"Select file amount limit": "最多选择 {{max}} 个文件",
|
||||||
|
"Select file amount limit 100": "每次最多选择100个文件",
|
||||||
|
"Some file count exceeds limit": "超出{{maxCount}}个文件,已自动截取",
|
||||||
|
"Some file size exceeds limit": "部分文件超出: {{maxSize}},已被过滤",
|
||||||
|
"Support file type": "支持 {{fileType}} 类型文件",
|
||||||
|
"Support max count": "最多支持 {{maxCount}} 个文件。",
|
||||||
|
"Support max size": "单个文件最大 {{maxSize}}。",
|
||||||
|
"Upload failed": "上传异常"
|
||||||
|
}
|
20
projects/app/i18n/zh/publish.json
Normal file
20
projects/app/i18n/zh/publish.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"Create API Key": "创建新 Key",
|
||||||
|
"Create Link": "创建链接",
|
||||||
|
"Default Response": "默认回复",
|
||||||
|
"Delete Link": "删除链接",
|
||||||
|
"Edit API Key": "编辑 Key 信息",
|
||||||
|
"Edit IFrame Link": "更新嵌入链接",
|
||||||
|
"Edit Link": "编辑",
|
||||||
|
"Edit Share Window": "更新分享窗口",
|
||||||
|
"Feishu name": "飞书",
|
||||||
|
"Link Name": "分享链接的名字",
|
||||||
|
"QPM Tips": "每个 IP 每分钟最多提问多少次",
|
||||||
|
"QPM is empty": "QPM 不能为空",
|
||||||
|
"app key tips": "这些 key 已有当前应用标识,具体使用可参考文档",
|
||||||
|
"key alias": "key 的别名,仅用于展示",
|
||||||
|
"key tips": "你可以使用 API 秘钥访问一些特定的接口(无法访问应用,访问应用需使用应用内的API Key)",
|
||||||
|
"token auth": "身份验证",
|
||||||
|
"token auth Tips": "身份校验服务器地址,如填写该值,每次对话前都会向指定服务器发送一个请求,进行身份校验",
|
||||||
|
"token auth use cases": "查看身份验证使用说明"
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { type ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
|
import { type ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
|
||||||
import { DispatchNodeResponseType } from '@fastgpt/global/core/workflow/runtime/type.d';
|
import { DispatchNodeResponseType } from '@fastgpt/global/core/workflow/runtime/type.d';
|
||||||
import { Flex, BoxProps, useDisclosure, useTheme, Box } from '@chakra-ui/react';
|
import { Flex, useDisclosure, useTheme, Box } from '@chakra-ui/react';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Box, BoxProps, Image } from '@chakra-ui/react';
|
import { Box, BoxProps } from '@chakra-ui/react';
|
||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
@@ -8,6 +8,7 @@ import { getFileAndOpen } from '@/web/core/dataset/utils';
|
|||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
|
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
|
||||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
type Props = BoxProps & {
|
type Props = BoxProps & {
|
||||||
sourceName?: string;
|
sourceName?: string;
|
||||||
@@ -17,6 +18,7 @@ type Props = BoxProps & {
|
|||||||
|
|
||||||
const RawSourceBox = ({ sourceId, sourceName = '', canView = true, ...props }: Props) => {
|
const RawSourceBox = ({ sourceId, sourceName = '', canView = true, ...props }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { fileT } = useI18n();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { setLoading } = useSystemStore();
|
const { setLoading } = useSystemStore();
|
||||||
|
|
||||||
@@ -25,10 +27,7 @@ const RawSourceBox = ({ sourceId, sourceName = '', canView = true, ...props }: P
|
|||||||
const icon = useMemo(() => getSourceNameIcon({ sourceId, sourceName }), [sourceId, sourceName]);
|
const icon = useMemo(() => getSourceNameIcon({ sourceId, sourceName }), [sourceId, sourceName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MyTooltip
|
<MyTooltip label={canPreview ? fileT('Click to view file') : ''} shouldWrapChildren={false}>
|
||||||
label={canPreview ? t('file.Click to view file') || '' : ''}
|
|
||||||
shouldWrapChildren={false}
|
|
||||||
>
|
|
||||||
<Box
|
<Box
|
||||||
color={'myGray.900'}
|
color={'myGray.900'}
|
||||||
fontWeight={'medium'}
|
fontWeight={'medium'}
|
||||||
@@ -44,7 +43,7 @@ const RawSourceBox = ({ sourceId, sourceName = '', canView = true, ...props }: P
|
|||||||
await getFileAndOpen(sourceId as string);
|
await getFileAndOpen(sourceId as string);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast({
|
toast({
|
||||||
title: t(getErrText(error, 'error.fileNotFound')),
|
title: getErrText(error, t('error.fileNotFound')),
|
||||||
status: 'error'
|
status: 'error'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,7 @@ import MyTooltip from '@/components/MyTooltip';
|
|||||||
import { getDocPath } from '@/web/common/system/doc';
|
import { getDocPath } from '@/web/common/system/doc';
|
||||||
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
||||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
type EditProps = EditApiKeyProps & { _id?: string };
|
type EditProps = EditApiKeyProps & { _id?: string };
|
||||||
const defaultEditData: EditProps = {
|
const defaultEditData: EditProps = {
|
||||||
@@ -295,6 +296,7 @@ function EditKeyModal({
|
|||||||
onEdit: () => void;
|
onEdit: () => void;
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { publishT } = useI18n();
|
||||||
const isEdit = useMemo(() => !!defaultData._id, [defaultData]);
|
const isEdit = useMemo(() => !!defaultData._id, [defaultData]);
|
||||||
const { feConfigs } = useSystemStore();
|
const { feConfigs } = useSystemStore();
|
||||||
|
|
||||||
@@ -324,13 +326,13 @@ function EditKeyModal({
|
|||||||
<MyModal
|
<MyModal
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
iconSrc="/imgs/modal/key.svg"
|
iconSrc="/imgs/modal/key.svg"
|
||||||
title={isEdit ? t('outlink.Edit API Key') : t('outlink.Create API Key')}
|
title={isEdit ? publishT('Edit API Key') : publishT('Create API Key')}
|
||||||
>
|
>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<Box flex={'0 0 90px'}>{t('Name')}:</Box>
|
<Box flex={'0 0 90px'}>{t('Name')}:</Box>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('openapi.key alias') || 'key alias'}
|
placeholder={publishT('key alias') || 'key alias'}
|
||||||
maxLength={20}
|
maxLength={20}
|
||||||
{...register('name', {
|
{...register('name', {
|
||||||
required: t('common.Name is empty') || 'Name is empty'
|
required: t('common.Name is empty') || 'Name is empty'
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import ApiKeyTable from '@/components/support/apikey/Table';
|
import ApiKeyTable from '@/components/support/apikey/Table';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const ApiKey = () => {
|
const ApiKey = () => {
|
||||||
const { t } = useTranslation();
|
const { publishT } = useI18n();
|
||||||
return <ApiKeyTable tips={t('openapi.key tips')}></ApiKeyTable>;
|
return <ApiKeyTable tips={publishT('key tips')}></ApiKeyTable>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ApiKey;
|
export default ApiKey;
|
||||||
|
@@ -190,7 +190,7 @@ export async function getServerSideProps(content: any) {
|
|||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
currentTab: content?.query?.currentTab || TabEnum.info,
|
currentTab: content?.query?.currentTab || TabEnum.info,
|
||||||
...(await serviceSideProps(content))
|
...(await serviceSideProps(content, ['publish']))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -2,12 +2,13 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import ApiKeyTable from '@/components/support/apikey/Table';
|
import ApiKeyTable from '@/components/support/apikey/Table';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { Box } from '@chakra-ui/react';
|
import { Box } from '@chakra-ui/react';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const API = ({ appId }: { appId: string }) => {
|
const API = ({ appId }: { appId: string }) => {
|
||||||
const { t } = useTranslation();
|
const { publishT } = useI18n();
|
||||||
return (
|
return (
|
||||||
<Box pt={3}>
|
<Box pt={3}>
|
||||||
<ApiKeyTable tips={t('openapi.app key tips')} appId={appId} />
|
<ApiKeyTable tips={publishT('app key tips')} appId={appId} />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -10,6 +10,7 @@ import { useForm } from 'react-hook-form';
|
|||||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { createShareChat, updateShareChat } from '@/web/support/outLink/api';
|
import { createShareChat, updateShareChat } from '@/web/support/outLink/api';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const FeiShuEditModal = ({
|
const FeiShuEditModal = ({
|
||||||
appId,
|
appId,
|
||||||
@@ -25,6 +26,7 @@ const FeiShuEditModal = ({
|
|||||||
onEdit: () => void;
|
onEdit: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { publishT } = useI18n();
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
setValue,
|
setValue,
|
||||||
@@ -58,13 +60,13 @@ const FeiShuEditModal = ({
|
|||||||
<MyModal
|
<MyModal
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
iconSrc="/imgs/modal/shareFill.svg"
|
iconSrc="/imgs/modal/shareFill.svg"
|
||||||
title={isEdit ? t('outlink.Edit Link') : t('outlink.Create Link')}
|
title={isEdit ? publishT('Edit Link') : publishT('Create Link')}
|
||||||
>
|
>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<Box flex={'0 0 90px'}>{t('Name')}</Box>
|
<Box flex={'0 0 90px'}>{t('Name')}</Box>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('outlink.Feishu name') || 'Link Name'} // TODO: i18n
|
placeholder={publishT('Feishu name') || 'Link Name'} // TODO: i18n
|
||||||
maxLength={20}
|
maxLength={20}
|
||||||
{...register('name', {
|
{...register('name', {
|
||||||
required: t('common.Name is empty') || 'Name is empty'
|
required: t('common.Name is empty') || 'Name is empty'
|
||||||
@@ -74,7 +76,7 @@ const FeiShuEditModal = ({
|
|||||||
<Flex alignItems={'center'} mt={4}>
|
<Flex alignItems={'center'} mt={4}>
|
||||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||||
QPM
|
QPM
|
||||||
<MyTooltip label={t('outlink.QPM Tips' || '')}>
|
<MyTooltip label={publishT('QPM Tips' || '')}>
|
||||||
<QuestionOutlineIcon ml={1} />
|
<QuestionOutlineIcon ml={1} />
|
||||||
</MyTooltip>
|
</MyTooltip>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -84,7 +86,7 @@ const FeiShuEditModal = ({
|
|||||||
min: 0,
|
min: 0,
|
||||||
max: 1000,
|
max: 1000,
|
||||||
valueAsNumber: true,
|
valueAsNumber: true,
|
||||||
required: t('outlink.QPM is empty') || ''
|
required: publishT('QPM is empty') || ''
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -126,10 +128,10 @@ const FeiShuEditModal = ({
|
|||||||
{/* TODO: i18n */}
|
{/* TODO: i18n */}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('outlink.Default Response') || 'Link Name'}
|
placeholder={publishT('Default Response') || 'Link Name'}
|
||||||
maxLength={20}
|
maxLength={20}
|
||||||
{...register('defaultResponse', {
|
{...register('defaultResponse', {
|
||||||
required: t('common.default Response is empty') || 'Name is empty'
|
required: true
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -139,10 +141,10 @@ const FeiShuEditModal = ({
|
|||||||
{/* TODO: i18n */}
|
{/* TODO: i18n */}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('outlink.Default Response') || 'Link Name'}
|
placeholder={publishT('Default Response') || 'Link Name'}
|
||||||
maxLength={20}
|
maxLength={20}
|
||||||
{...register('immediateResponse', {
|
{...register('immediateResponse', {
|
||||||
required: t('common.default Response is empty') || 'Name is empty'
|
required: true
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -152,14 +154,14 @@ const FeiShuEditModal = ({
|
|||||||
placeholder={t('core.module.http.appId') || 'Link Name'}
|
placeholder={t('core.module.http.appId') || 'Link Name'}
|
||||||
// maxLength={20}
|
// maxLength={20}
|
||||||
{...register('app.appId', {
|
{...register('app.appId', {
|
||||||
required: t('common.Name is empty') || 'Name is empty'
|
required: true
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex alignItems={'center'} mt={4}>
|
<Flex alignItems={'center'} mt={4}>
|
||||||
<Box flex={'0 0 90px'}>{t('core.module.http.AppSecret')}</Box>
|
<Box flex={'0 0 90px'}>{t('core.module.http.AppSecret')}</Box>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('outlink.AppSecret') || 'Link Name'}
|
placeholder={'App Secret'}
|
||||||
// maxLength={20}
|
// maxLength={20}
|
||||||
{...register('app.appSecret', {
|
{...register('app.appSecret', {
|
||||||
required: t('common.Name is empty') || 'Name is empty'
|
required: t('common.Name is empty') || 'Name is empty'
|
||||||
|
@@ -44,6 +44,7 @@ import { getDocPath } from '@/web/common/system/doc';
|
|||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
||||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const SelectUsingWayModal = dynamic(() => import('./SelectUsingWayModal'));
|
const SelectUsingWayModal = dynamic(() => import('./SelectUsingWayModal'));
|
||||||
|
|
||||||
@@ -261,6 +262,7 @@ function EditLinkModal({
|
|||||||
}) {
|
}) {
|
||||||
const { feConfigs } = useSystemStore();
|
const { feConfigs } = useSystemStore();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { publishT } = useI18n();
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
setValue,
|
setValue,
|
||||||
@@ -293,13 +295,13 @@ function EditLinkModal({
|
|||||||
<MyModal
|
<MyModal
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
iconSrc="/imgs/modal/shareFill.svg"
|
iconSrc="/imgs/modal/shareFill.svg"
|
||||||
title={isEdit ? t('outlink.Edit Link') : t('outlink.Create Link')}
|
title={isEdit ? publishT('Edit Link') : publishT('Create Link')}
|
||||||
>
|
>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<Box flex={'0 0 90px'}>{t('Name')}</Box>
|
<Box flex={'0 0 90px'}>{t('Name')}</Box>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('outlink.Link Name') || 'Link Name'}
|
placeholder={publishT('Link Name')}
|
||||||
maxLength={20}
|
maxLength={20}
|
||||||
{...register('name', {
|
{...register('name', {
|
||||||
required: t('common.Name is empty') || 'Name is empty'
|
required: t('common.Name is empty') || 'Name is empty'
|
||||||
@@ -327,7 +329,7 @@ function EditLinkModal({
|
|||||||
<Flex alignItems={'center'} mt={4}>
|
<Flex alignItems={'center'} mt={4}>
|
||||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||||
QPM
|
QPM
|
||||||
<MyTooltip label={t('outlink.QPM Tips' || '')}>
|
<MyTooltip label={publishT('QPM Tips' || '')}>
|
||||||
<QuestionOutlineIcon ml={1} />
|
<QuestionOutlineIcon ml={1} />
|
||||||
</MyTooltip>
|
</MyTooltip>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -337,7 +339,7 @@ function EditLinkModal({
|
|||||||
min: 0,
|
min: 0,
|
||||||
max: 1000,
|
max: 1000,
|
||||||
valueAsNumber: true,
|
valueAsNumber: true,
|
||||||
required: t('outlink.QPM is empty') || ''
|
required: publishT('QPM is empty') || ''
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -360,13 +362,13 @@ function EditLinkModal({
|
|||||||
|
|
||||||
<Flex alignItems={'center'} mt={4}>
|
<Flex alignItems={'center'} mt={4}>
|
||||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||||
{t('outlink.token auth')}
|
{publishT('token auth')}
|
||||||
<MyTooltip label={t('outlink.token auth Tips') || ''}>
|
<MyTooltip label={publishT('token auth Tips') || ''}>
|
||||||
<QuestionOutlineIcon ml={1} />
|
<QuestionOutlineIcon ml={1} />
|
||||||
</MyTooltip>
|
</MyTooltip>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('outlink.token auth Tips') || ''}
|
placeholder={publishT('token auth Tips') || ''}
|
||||||
fontSize={'sm'}
|
fontSize={'sm'}
|
||||||
{...register('limit.hookUrl')}
|
{...register('limit.hookUrl')}
|
||||||
/>
|
/>
|
||||||
@@ -377,7 +379,7 @@ function EditLinkModal({
|
|||||||
fontSize={'sm'}
|
fontSize={'sm'}
|
||||||
color={'myGray.500'}
|
color={'myGray.500'}
|
||||||
>
|
>
|
||||||
{t('outlink.token auth use cases')}
|
{publishT('token auth use cases')}
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@@ -196,7 +196,7 @@ export async function getServerSideProps(context: any) {
|
|||||||
const currentTab = context?.query?.currentTab || TabEnum.simpleEdit;
|
const currentTab = context?.query?.currentTab || TabEnum.simpleEdit;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { currentTab, ...(await serviceSideProps(context, ['app'])) }
|
props: { currentTab, ...(await serviceSideProps(context, ['app', 'file', 'publish'])) }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -371,7 +371,7 @@ export async function getServerSideProps(context: any) {
|
|||||||
props: {
|
props: {
|
||||||
appId: context?.query?.appId || '',
|
appId: context?.query?.appId || '',
|
||||||
chatId: context?.query?.chatId || '',
|
chatId: context?.query?.chatId || '',
|
||||||
...(await serviceSideProps(context))
|
...(await serviceSideProps(context, ['file']))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -431,7 +431,7 @@ export async function getServerSideProps(context: any) {
|
|||||||
appName: app?.appId?.name || '',
|
appName: app?.appId?.name || '',
|
||||||
appAvatar: app?.appId?.avatar || '',
|
appAvatar: app?.appId?.avatar || '',
|
||||||
appIntro: app?.appId?.intro || '',
|
appIntro: app?.appId?.intro || '',
|
||||||
...(await serviceSideProps(context))
|
...(await serviceSideProps(context, ['file']))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -382,7 +382,7 @@ const OutLink = () => {
|
|||||||
export async function getServerSideProps(context: any) {
|
export async function getServerSideProps(context: any) {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
...(await serviceSideProps(context))
|
...(await serviceSideProps(context, ['file']))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -27,9 +27,11 @@ import {
|
|||||||
postCreateDatasetTextCollection
|
postCreateDatasetTextCollection
|
||||||
} from '@/web/core/dataset/api';
|
} from '@/web/core/dataset/api';
|
||||||
import Tag from '@fastgpt/web/components/common/Tag/index';
|
import Tag from '@fastgpt/web/components/common/Tag/index';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const Upload = () => {
|
const Upload = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { fileT } = useI18n();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { datasetDetail } = useDatasetStore();
|
const { datasetDetail } = useDatasetStore();
|
||||||
@@ -131,7 +133,7 @@ const Upload = () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
errorToast: t('common.file.Upload failed')
|
errorToast: fileT('Upload failed')
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -13,6 +13,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
|
|||||||
import { uploadFile2DB } from '@/web/common/file/controller';
|
import { uploadFile2DB } from '@/web/common/file/controller';
|
||||||
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
|
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
|
||||||
import { ImportSourceItemType } from '@/web/core/dataset/type';
|
import { ImportSourceItemType } from '@/web/core/dataset/type';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
export type SelectFileItemType = {
|
export type SelectFileItemType = {
|
||||||
fileId: string;
|
fileId: string;
|
||||||
@@ -35,6 +36,8 @@ const FileSelector = ({
|
|||||||
onFinishSelect: () => void;
|
onFinishSelect: () => void;
|
||||||
} & FlexProps) => {
|
} & FlexProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { fileT } = useI18n();
|
||||||
|
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { feConfigs } = useSystemStore();
|
const { feConfigs } = useSystemStore();
|
||||||
|
|
||||||
@@ -129,7 +132,7 @@ const FileSelector = ({
|
|||||||
files = files.slice(0, maxCount - selectFiles.length);
|
files = files.slice(0, maxCount - selectFiles.length);
|
||||||
toast({
|
toast({
|
||||||
status: 'warning',
|
status: 'warning',
|
||||||
title: t('common.file.Some file count exceeds limit', { maxCount })
|
title: fileT('Some file count exceeds limit', { maxCount })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// size check
|
// size check
|
||||||
@@ -141,7 +144,7 @@ const FileSelector = ({
|
|||||||
if (filterFiles.length < files.length) {
|
if (filterFiles.length < files.length) {
|
||||||
toast({
|
toast({
|
||||||
status: 'warning',
|
status: 'warning',
|
||||||
title: t('common.file.Some file size exceeds limit', { maxSize: formatFileSize(maxSize) })
|
title: fileT('Some file size exceeds limit', { maxSize: formatFileSize(maxSize) })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +206,7 @@ const FileSelector = ({
|
|||||||
let isErr = files.some((item) => item.type === '');
|
let isErr = files.some((item) => item.type === '');
|
||||||
if (isErr) {
|
if (isErr) {
|
||||||
return toast({
|
return toast({
|
||||||
title: t('file.upload error description'),
|
title: fileT('upload error description'),
|
||||||
status: 'error'
|
status: 'error'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -262,18 +265,18 @@ const FileSelector = ({
|
|||||||
<>
|
<>
|
||||||
<Box fontWeight={'bold'}>
|
<Box fontWeight={'bold'}>
|
||||||
{isDragging
|
{isDragging
|
||||||
? t('file.Release the mouse to upload the file')
|
? fileT('Release the mouse to upload the file')
|
||||||
: t('common.file.Select and drag file tip')}
|
: fileT('Select and drag file tip')}
|
||||||
</Box>
|
</Box>
|
||||||
{/* file type */}
|
{/* file type */}
|
||||||
<Box color={'myGray.500'} fontSize={'xs'}>
|
<Box color={'myGray.500'} fontSize={'xs'}>
|
||||||
{t('common.file.Support file type', { fileType })}
|
{fileT('Support file type', { fileType })}
|
||||||
</Box>
|
</Box>
|
||||||
<Box color={'myGray.500'} fontSize={'xs'}>
|
<Box color={'myGray.500'} fontSize={'xs'}>
|
||||||
{/* max count */}
|
{/* max count */}
|
||||||
{maxCount && t('common.file.Support max count', { maxCount })}
|
{maxCount && fileT('Support max count', { maxCount })}
|
||||||
{/* max size */}
|
{/* max size */}
|
||||||
{maxSize && t('common.file.Support max size', { maxSize: formatFileSize(maxSize) })}
|
{maxSize && fileT('Support max size', { maxSize: formatFileSize(maxSize) })}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<File
|
<File
|
||||||
|
@@ -16,6 +16,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
|
|||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const PreviewRawText = dynamic(() => import('./PreviewRawText'));
|
const PreviewRawText = dynamic(() => import('./PreviewRawText'));
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ export const RenderUploadFiles = ({
|
|||||||
showPreviewContent?: boolean;
|
showPreviewContent?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { fileT } = useI18n();
|
||||||
const [previewFile, setPreviewFile] = useState<ImportSourceItemType>();
|
const [previewFile, setPreviewFile] = useState<ImportSourceItemType>();
|
||||||
|
|
||||||
return files.length > 0 ? (
|
return files.length > 0 ? (
|
||||||
@@ -38,13 +40,13 @@ export const RenderUploadFiles = ({
|
|||||||
<Thead draggable={false}>
|
<Thead draggable={false}>
|
||||||
<Tr bg={'myGray.100'} mb={2}>
|
<Tr bg={'myGray.100'} mb={2}>
|
||||||
<Th borderLeftRadius={'md'} borderBottom={'none'} py={4}>
|
<Th borderLeftRadius={'md'} borderBottom={'none'} py={4}>
|
||||||
{t('common.file.File Name')}
|
{fileT('File Name')}
|
||||||
</Th>
|
</Th>
|
||||||
<Th borderBottom={'none'} py={4}>
|
<Th borderBottom={'none'} py={4}>
|
||||||
{t('core.dataset.import.Upload file progress')}
|
{t('core.dataset.import.Upload file progress')}
|
||||||
</Th>
|
</Th>
|
||||||
<Th borderBottom={'none'} py={4}>
|
<Th borderBottom={'none'} py={4}>
|
||||||
{t('common.file.File Size')}
|
{fileT('File Size')}
|
||||||
</Th>
|
</Th>
|
||||||
<Th borderRightRadius={'md'} borderBottom={'none'} py={4}>
|
<Th borderRightRadius={'md'} borderBottom={'none'} py={4}>
|
||||||
{t('common.Action')}
|
{t('common.Action')}
|
||||||
|
@@ -295,7 +295,7 @@ export async function getServerSideProps(context: any) {
|
|||||||
const datasetId = context?.query?.datasetId;
|
const datasetId = context?.query?.datasetId;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { currentTab, datasetId, ...(await serviceSideProps(context)) }
|
props: { currentTab, datasetId, ...(await serviceSideProps(context, ['file'])) }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
projects/app/src/types/i18n.d.ts
vendored
10
projects/app/src/types/i18n.d.ts
vendored
@@ -1,12 +1,16 @@
|
|||||||
import 'i18next';
|
import 'i18next';
|
||||||
import common from '../../i18n/en/common.json';
|
import common from '../../i18n/zh/common.json';
|
||||||
import dataset from '../../i18n/en/dataset.json';
|
import dataset from '../../i18n/zh/dataset.json';
|
||||||
import app from '../../i18n/en/app.json';
|
import app from '../../i18n/zh/app.json';
|
||||||
|
import file from '../../i18n/zh/file.json';
|
||||||
|
import publish from '../../i18n/zh/publish.json';
|
||||||
|
|
||||||
export interface I18nNamespaces {
|
export interface I18nNamespaces {
|
||||||
common: typeof common;
|
common: typeof common;
|
||||||
dataset: typeof dataset;
|
dataset: typeof dataset;
|
||||||
app: typeof app;
|
app: typeof app;
|
||||||
|
file: typeof file;
|
||||||
|
publish: typeof publish;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type I18nNsType = (keyof I18nNamespaces)[];
|
export type I18nNsType = (keyof I18nNamespaces)[];
|
||||||
|
@@ -2,6 +2,7 @@ import React, { useRef, useCallback } from 'react';
|
|||||||
import { Box } from '@chakra-ui/react';
|
import { Box } from '@chakra-ui/react';
|
||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
export const useSelectFile = (props?: {
|
export const useSelectFile = (props?: {
|
||||||
fileType?: string;
|
fileType?: string;
|
||||||
@@ -9,6 +10,7 @@ export const useSelectFile = (props?: {
|
|||||||
maxCount?: number;
|
maxCount?: number;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { fileT } = useI18n();
|
||||||
const { fileType = '*', multiple = false, maxCount = 10 } = props || {};
|
const { fileType = '*', multiple = false, maxCount = 10 } = props || {};
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const SelectFileDom = useRef<HTMLInputElement>(null);
|
const SelectFileDom = useRef<HTMLInputElement>(null);
|
||||||
@@ -30,7 +32,7 @@ export const useSelectFile = (props?: {
|
|||||||
if (fileList.length > maxCount) {
|
if (fileList.length > maxCount) {
|
||||||
toast({
|
toast({
|
||||||
status: 'warning',
|
status: 'warning',
|
||||||
title: t('common.file.Select file amount limit', { max: maxCount })
|
title: fileT('Select file amount limit', { max: maxCount })
|
||||||
});
|
});
|
||||||
fileList = fileList.slice(0, maxCount);
|
fileList = fileList.slice(0, maxCount);
|
||||||
}
|
}
|
||||||
@@ -39,7 +41,7 @@ export const useSelectFile = (props?: {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
[fileType, maxCount, multiple, t, toast]
|
[fileT, fileType, maxCount, multiple, toast]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onOpen = useCallback((sign?: any) => {
|
const onOpen = useCallback((sign?: any) => {
|
||||||
|
@@ -6,6 +6,8 @@ type I18nContextType = {
|
|||||||
commonT: TFunction<['common'], undefined>;
|
commonT: TFunction<['common'], undefined>;
|
||||||
appT: TFunction<['app'], undefined>;
|
appT: TFunction<['app'], undefined>;
|
||||||
datasetT: TFunction<['dataset'], undefined>;
|
datasetT: TFunction<['dataset'], undefined>;
|
||||||
|
fileT: TFunction<['file'], undefined>;
|
||||||
|
publishT: TFunction<['publish'], undefined>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const I18nContext = createContext<I18nContextType>({
|
export const I18nContext = createContext<I18nContextType>({
|
||||||
@@ -17,13 +19,17 @@ const I18nContextProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
const { t: commonT } = useTranslation('common');
|
const { t: commonT } = useTranslation('common');
|
||||||
const { t: appT } = useTranslation('app');
|
const { t: appT } = useTranslation('app');
|
||||||
const { t: datasetT } = useTranslation('dataset');
|
const { t: datasetT } = useTranslation('dataset');
|
||||||
|
const { t: fileT } = useTranslation('file');
|
||||||
|
const { t: publishT } = useTranslation('publish');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<I18nContext.Provider
|
<I18nContext.Provider
|
||||||
value={{
|
value={{
|
||||||
commonT,
|
commonT,
|
||||||
appT,
|
appT,
|
||||||
datasetT
|
datasetT,
|
||||||
|
fileT,
|
||||||
|
publishT
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
Reference in New Issue
Block a user