mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-22 04:06:18 +00:00
41
.vscode/i18n-ally-custom-framework.yml
vendored
Normal file
41
.vscode/i18n-ally-custom-framework.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# .vscode/i18n-ally-custom-framework.yml
|
||||||
|
|
||||||
|
# An array of strings which contain Language Ids defined by VS Code
|
||||||
|
# You can check available language ids here: https://code.visualstudio.com/docs/languages/identifiers
|
||||||
|
languageIds:
|
||||||
|
- javascript
|
||||||
|
- typescript
|
||||||
|
- javascriptreact
|
||||||
|
- typescriptreact
|
||||||
|
|
||||||
|
# An array of RegExes to find the key usage. **The key should be captured in the first match group**.
|
||||||
|
# You should unescape RegEx strings in order to fit in the YAML file
|
||||||
|
# To help with this, you can use https://www.freeformatter.com/json-escape.html
|
||||||
|
usageMatchRegex:
|
||||||
|
# The following example shows how to detect `t("your.i18n.keys")`
|
||||||
|
# the `{key}` will be placed by a proper keypath matching regex,
|
||||||
|
# you can ignore it and use your own matching rules as well
|
||||||
|
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
|
||||||
|
- "[^\\w\\d]commonT\\(['\"`]({key})['\"`]"
|
||||||
|
# 支持 appT("your.i18n.keys")
|
||||||
|
- "[^\\w\\d]appT\\(['\"`]({key})['\"`]"
|
||||||
|
# 支持 datasetT("your.i18n.keys")
|
||||||
|
- "[^\\w\\d]datasetT\\(['\"`]({key})['\"`]"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# useTranslation() hook.
|
||||||
|
# You should unescape RegEx strings in order to fit in the YAML file
|
||||||
|
# To help with this, you can use https://www.freeformatter.com/json-escape.html
|
||||||
|
scopeRangeRegex: "useTranslation\\(\\s*\\[?\\s*['\"`](.*?)['\"`]"
|
||||||
|
|
||||||
|
# An array of strings containing refactor templates.
|
||||||
|
# The "$1" will be replaced by the keypath specified.
|
||||||
|
# Optional: uncomment the following two lines to use
|
||||||
|
|
||||||
|
# refactorTemplates:
|
||||||
|
# - i18n.get("$1")
|
||||||
|
|
||||||
|
|
||||||
|
# If set to true, only enables this custom framework (will disable all built-in frameworks)
|
||||||
|
monopoly: true
|
@@ -28,6 +28,7 @@
|
|||||||
"papaparse": "^5.4.1",
|
"papaparse": "^5.4.1",
|
||||||
"pdfjs-dist": "4.0.269",
|
"pdfjs-dist": "4.0.269",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
"use-context-selector": "^1.4.4",
|
||||||
"react-day-picker": "^8.7.1",
|
"react-day-picker": "^8.7.1",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-i18next": "13.5.0",
|
"react-i18next": "13.5.0",
|
||||||
|
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -301,6 +301,9 @@ importers:
|
|||||||
react-i18next:
|
react-i18next:
|
||||||
specifier: 13.5.0
|
specifier: 13.5.0
|
||||||
version: 13.5.0(i18next@23.10.0)(react-dom@18.2.0)(react@18.2.0)
|
version: 13.5.0(i18next@23.10.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
use-context-selector:
|
||||||
|
specifier: ^1.4.4
|
||||||
|
version: 1.4.4(react-dom@18.2.0)(react@18.2.0)(scheduler@0.23.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/lodash':
|
'@types/lodash':
|
||||||
specifier: ^4.14.191
|
specifier: ^4.14.191
|
||||||
|
45
projects/app/i18n/en/app.json
Normal file
45
projects/app/i18n/en/app.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"AI Advanced Settings": "AI Advanced Settings",
|
||||||
|
"AI Settings": "AI Settings",
|
||||||
|
"Advance App TestTip": "Current app may be in advanced orchestration mode\nTo switch to【Simple Mode】please click the save button on the left",
|
||||||
|
"App Detail": "App Details",
|
||||||
|
"Apps Share": "Apps Share",
|
||||||
|
"Basic Settings": "Basic Settings",
|
||||||
|
"Chat Debug": "Chat Debug",
|
||||||
|
"Chat Logs Tips": "Logs will record online, shared and API (chatId required) conversation records for this app",
|
||||||
|
"Chat logs": "Chat Logs",
|
||||||
|
"Confirm Del App Tip": "Confirm to delete this app and all its chat records?",
|
||||||
|
"Connection is invalid": "Connection is invalid",
|
||||||
|
"Connection type is different": "Connection type is different",
|
||||||
|
"Copy Module Config": "Copy Config",
|
||||||
|
"Dataset Quote Template": "Knowledge Base QA Mode",
|
||||||
|
"Export Config Successful": "Config copied, please check for important data",
|
||||||
|
"Export Configs": "Export Configs",
|
||||||
|
"Feedback Count": "User Feedback",
|
||||||
|
"Import Configs": "Import Configs",
|
||||||
|
"Import Configs Failed": "Failed to import configs, please ensure configs are valid!",
|
||||||
|
"Input Field Settings": "Input Field Settings",
|
||||||
|
"Logs Empty": "No logs yet~",
|
||||||
|
"Logs Message Total": "Total Messages",
|
||||||
|
"Logs Source": "Source",
|
||||||
|
"Logs Time": "Time",
|
||||||
|
"Logs Title": "Title",
|
||||||
|
"Mark Count": "Marked Answer Count",
|
||||||
|
"My Apps": "My Apps",
|
||||||
|
"Output Field Settings": "Output Field Settings",
|
||||||
|
"Paste Config": "Paste Config",
|
||||||
|
"To Chat": "Go to Chat",
|
||||||
|
"To Settings": "View Details",
|
||||||
|
"Variable Key Repeat Tip": "Variable key is duplicate",
|
||||||
|
"module": {
|
||||||
|
"Combine Modules": "Combine Modules",
|
||||||
|
"Custom Title Tip": "This title will be displayed during the conversation",
|
||||||
|
"My Modules": "My Modules",
|
||||||
|
"No Modules": "No modules yet~",
|
||||||
|
"System Module": "System Module",
|
||||||
|
"type": "\"{{type}}\" type\n{{description}}"
|
||||||
|
},
|
||||||
|
"modules": {
|
||||||
|
"Title is required": "Module name cannot be empty"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
0
projects/app/i18n/en/dataset.json
Normal file
0
projects/app/i18n/en/dataset.json
Normal file
44
projects/app/i18n/zh/app.json
Normal file
44
projects/app/i18n/zh/app.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"AI Settings": "AI 配置",
|
||||||
|
"Advance App TestTip": "当前应用可能为高级编排模式\n如需切换为【简易模式】请点击左侧保存按键",
|
||||||
|
"App Detail": "应用详情",
|
||||||
|
"Apps Share": "应用分享",
|
||||||
|
"Basic Settings": "基本信息",
|
||||||
|
"Chat Debug": "调试预览",
|
||||||
|
"Chat Logs Tips": "日志会记录该应用的在线、分享和 API(需填写 chatId) 对话记录",
|
||||||
|
"Chat logs": "对话日志",
|
||||||
|
"Confirm Del App Tip": "确认删除该应用及其所有聊天记录?",
|
||||||
|
"Connection is invalid": "连接无效",
|
||||||
|
"Connection type is different": "连接的类型不一致",
|
||||||
|
"Copy Module Config": "复制配置",
|
||||||
|
"Dataset Quote Template": "知识库问答模式",
|
||||||
|
"Export Config Successful": "已复制配置,自动过滤部分敏感信息,请注意检查是否仍有敏感数据",
|
||||||
|
"Export Configs": "导出配置",
|
||||||
|
"Feedback Count": "用户反馈",
|
||||||
|
"Import Configs": "导入配置",
|
||||||
|
"Import Configs Failed": "导入配置失败,请确保配置正常!",
|
||||||
|
"Input Field Settings": "输入字段编辑",
|
||||||
|
"Logs Empty": "还没有日志噢~",
|
||||||
|
"Logs Message Total": "消息总数",
|
||||||
|
"Logs Source": "来源",
|
||||||
|
"Logs Time": "时间",
|
||||||
|
"Logs Title": "标题",
|
||||||
|
"Mark Count": "标注答案数量",
|
||||||
|
"My Apps": "我的应用",
|
||||||
|
"Output Field Settings": "输出字段编辑",
|
||||||
|
"Paste Config": "粘贴配置",
|
||||||
|
"To Chat": "前去对话",
|
||||||
|
"To Settings": "查看详情",
|
||||||
|
"Variable Key Repeat Tip": "变量 key 重复",
|
||||||
|
"module": {
|
||||||
|
"Combine Modules": "组合模块",
|
||||||
|
"Custom Title Tip": "该标题名字会展示在对话过程中",
|
||||||
|
"My Modules": "",
|
||||||
|
"No Modules": "还没有模块~",
|
||||||
|
"System Module": "系统模块",
|
||||||
|
"type": "\"{{type}}\"类型\n{{description}}"
|
||||||
|
},
|
||||||
|
"modules": {
|
||||||
|
"Title is required": "模块名不能为空"
|
||||||
|
}
|
||||||
|
}
|
@@ -8,51 +8,8 @@
|
|||||||
"Running": "运行中",
|
"Running": "运行中",
|
||||||
"UnKnow": "未知",
|
"UnKnow": "未知",
|
||||||
"Warning": "提示",
|
"Warning": "提示",
|
||||||
"app": {
|
"New Create": "新建",
|
||||||
"AI Advanced Settings": "AI 高级配置",
|
|
||||||
"AI Settings": "AI 配置",
|
|
||||||
"Advance App TestTip": "当前应用可能为高级编排模式\n如需切换为【简易模式】请点击左侧保存按键",
|
|
||||||
"App Detail": "应用详情",
|
|
||||||
"Apps Share": "应用分享",
|
|
||||||
"Basic Settings": "基本信息",
|
|
||||||
"Chat Debug": "调试预览",
|
|
||||||
"Chat Logs Tips": "日志会记录该应用的在线、分享和 API(需填写 chatId) 对话记录",
|
|
||||||
"Chat logs": "对话日志",
|
|
||||||
"Confirm Del App Tip": "确认删除该应用及其所有聊天记录?",
|
|
||||||
"Connection is invalid": "连接无效",
|
|
||||||
"Connection type is different": "连接的类型不一致",
|
|
||||||
"Copy Module Config": "复制配置",
|
|
||||||
"Dataset Quote Template": "知识库问答模式",
|
|
||||||
"Export Config Successful": "已复制配置,自动过滤部分敏感信息,请注意检查是否仍有敏感数据",
|
|
||||||
"Export Configs": "导出配置",
|
|
||||||
"Feedback Count": "用户反馈",
|
|
||||||
"Import Configs": "导入配置",
|
|
||||||
"Import Configs Failed": "导入配置失败,请确保配置正常!",
|
|
||||||
"Input Field Settings": "输入字段编辑",
|
|
||||||
"Logs Empty": "还没有日志噢~",
|
|
||||||
"Logs Message Total": "消息总数",
|
|
||||||
"Logs Source": "来源",
|
|
||||||
"Logs Time": "时间",
|
|
||||||
"Logs Title": "标题",
|
|
||||||
"Mark Count": "标注答案数量",
|
|
||||||
"My Apps": "我的应用",
|
|
||||||
"Output Field Settings": "输出字段编辑",
|
|
||||||
"Paste Config": "粘贴配置",
|
|
||||||
"To Chat": "前去对话",
|
|
||||||
"To Settings": "查看详情",
|
|
||||||
"Variable Key Repeat Tip": "变量 key 重复",
|
|
||||||
"module": {
|
|
||||||
"Combine Modules": "组合模块",
|
|
||||||
"Custom Title Tip": "该标题名字会展示在对话过程中",
|
|
||||||
"My Modules": "",
|
|
||||||
"No Modules": "还没有模块~",
|
|
||||||
"System Module": "系统模块",
|
|
||||||
"type": "\"{{type}}\"类型\n{{description}}"
|
|
||||||
},
|
|
||||||
"modules": {
|
|
||||||
"Title is required": "模块名不能为空"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"common": {
|
"common": {
|
||||||
"Action": "操作",
|
"Action": "操作",
|
||||||
"Add": "添加",
|
"Add": "添加",
|
||||||
@@ -113,7 +70,6 @@
|
|||||||
"Name": "名称",
|
"Name": "名称",
|
||||||
"Name Can": "名称不能为空",
|
"Name Can": "名称不能为空",
|
||||||
"Name is empty": "名称不能为空",
|
"Name is empty": "名称不能为空",
|
||||||
"New Create": "新建",
|
|
||||||
"Next Step": "下一步",
|
"Next Step": "下一步",
|
||||||
"No more data": "没有更多了~",
|
"No more data": "没有更多了~",
|
||||||
"Not open": "未开启",
|
"Not open": "未开启",
|
||||||
@@ -933,10 +889,10 @@
|
|||||||
"params": "Params"
|
"params": "Params"
|
||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
|
"Add Branch": "添加分支",
|
||||||
"Add Input": "添加入参",
|
"Add Input": "添加入参",
|
||||||
"Input Number": "入参: {{length}}",
|
"Input Number": "入参: {{length}}",
|
||||||
"add": "添加条件",
|
"add": "添加条件",
|
||||||
"Add Branch": "添加分支",
|
|
||||||
"description": {
|
"description": {
|
||||||
"Background": "你可以添加一些特定内容的介绍,从而更好的识别用户的问题类型。这个内容通常是给模型介绍一个它不知道的内容。",
|
"Background": "你可以添加一些特定内容的介绍,从而更好的识别用户的问题类型。这个内容通常是给模型介绍一个它不知道的内容。",
|
||||||
"HTTP Dynamic Input": "接收前方节点的输出值作为变量,这些变量可以被HTTP请求参数使用。",
|
"HTTP Dynamic Input": "接收前方节点的输出值作为变量,这些变量可以被HTTP请求参数使用。",
|
||||||
|
0
projects/app/i18n/zh/dataset.json
Normal file
0
projects/app/i18n/zh/dataset.json
Normal file
@@ -1,19 +1,18 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Textarea, Button, ModalBody, ModalFooter } from '@chakra-ui/react';
|
import { Textarea, Button, ModalBody, ModalFooter } from '@chakra-ui/react';
|
||||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||||
import { useTranslation } from 'next-i18next';
|
|
||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { WorkflowContext } from '../context';
|
import { WorkflowContext } from '../context';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ImportSettings = ({ onClose }: Props) => {
|
const ImportSettings = ({ onClose }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { appT } = useI18n();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const initData = useContextSelector(WorkflowContext, (v) => v.initData);
|
const initData = useContextSelector(WorkflowContext, (v) => v.initData);
|
||||||
const [value, setValue] = useState('');
|
const [value, setValue] = useState('');
|
||||||
|
|
||||||
@@ -23,11 +22,11 @@ const ImportSettings = ({ onClose }: Props) => {
|
|||||||
w={'600px'}
|
w={'600px'}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
iconSrc="/imgs/modal/params.svg"
|
iconSrc="/imgs/modal/params.svg"
|
||||||
title={t('app.Import Configs')}
|
title={appT('Import Configs')}
|
||||||
>
|
>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Textarea
|
<Textarea
|
||||||
placeholder={t('app.Paste Config') || 'app.Paste Config'}
|
placeholder={appT('Paste Config')}
|
||||||
defaultValue={value}
|
defaultValue={value}
|
||||||
rows={16}
|
rows={16}
|
||||||
onChange={(e) => setValue(e.target.value)}
|
onChange={(e) => setValue(e.target.value)}
|
||||||
@@ -46,7 +45,7 @@ const ImportSettings = ({ onClose }: Props) => {
|
|||||||
onClose();
|
onClose();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast({
|
toast({
|
||||||
title: t('app.Import Configs Failed')
|
title: appT('Import Configs Failed')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@@ -28,6 +28,7 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
|||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { WorkflowContext } from '../context';
|
import { WorkflowContext } from '../context';
|
||||||
import { useCreation } from 'ahooks';
|
import { useCreation } from 'ahooks';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
type ModuleTemplateListProps = {
|
type ModuleTemplateListProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -251,6 +252,8 @@ const RenderList = React.memo(function RenderList({
|
|||||||
setCurrentParent
|
setCurrentParent
|
||||||
}: RenderListProps) {
|
}: RenderListProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { isPc } = useSystemStore();
|
const { isPc } = useSystemStore();
|
||||||
const { x, y, zoom } = useViewport();
|
const { x, y, zoom } = useViewport();
|
||||||
const { setLoading } = useSystemStore();
|
const { setLoading } = useSystemStore();
|
||||||
@@ -323,7 +326,7 @@ const RenderList = React.memo(function RenderList({
|
|||||||
|
|
||||||
const Render = useMemo(() => {
|
const Render = useMemo(() => {
|
||||||
return templates.length === 0 ? (
|
return templates.length === 0 ? (
|
||||||
<EmptyTip text={t('app.module.No Modules')} />
|
<EmptyTip text={appT('module.No Modules')} />
|
||||||
) : (
|
) : (
|
||||||
<Box flex={'1 0 0'} overflow={'overlay'} px={'20px'}>
|
<Box flex={'1 0 0'} overflow={'overlay'} px={'20px'}>
|
||||||
<Box mx={'auto'}>
|
<Box mx={'auto'}>
|
||||||
|
@@ -203,16 +203,16 @@ const MyTargetHandle = React.memo(function MyTargetHandle({
|
|||||||
|
|
||||||
if (connectingEdge?.handleId && !connectingEdge.handleId?.includes('source')) return false;
|
if (connectingEdge?.handleId && !connectingEdge.handleId?.includes('source')) return false;
|
||||||
|
|
||||||
// From same source node
|
// From same source node and same handle
|
||||||
if (
|
if (
|
||||||
connectedEdges.some(
|
connectedEdges.some(
|
||||||
(item) => item.source === connectingEdge?.nodeId && item.target === nodeId
|
(item) => item.sourceHandle === connectingEdge?.handleId && item.target === nodeId
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, [connectedEdges, connectingEdge?.handleId, connectingEdge?.nodeId, edges, node, nodeId]);
|
}, [connectedEdges, connectingEdge?.handleId, edges, node, nodeId]);
|
||||||
|
|
||||||
const RenderHandle = useMemo(() => {
|
const RenderHandle = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
|
@@ -22,6 +22,7 @@ import { storeNode2FlowNode } from '@/web/core/workflow/utils';
|
|||||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { WorkflowContext } from '../../../context';
|
import { WorkflowContext } from '../../../context';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
type Props = FlowNodeItemType & {
|
type Props = FlowNodeItemType & {
|
||||||
children?: React.ReactNode | React.ReactNode[] | string;
|
children?: React.ReactNode | React.ReactNode[] | string;
|
||||||
@@ -38,6 +39,8 @@ type Props = FlowNodeItemType & {
|
|||||||
|
|
||||||
const NodeCard = (props: Props) => {
|
const NodeCard = (props: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -66,7 +69,7 @@ const NodeCard = (props: Props) => {
|
|||||||
// custom title edit
|
// custom title edit
|
||||||
const { onOpenModal: onOpenCustomTitleModal, EditModal: EditTitleModal } = useEditTitle({
|
const { onOpenModal: onOpenCustomTitleModal, EditModal: EditTitleModal } = useEditTitle({
|
||||||
title: t('common.Custom Title'),
|
title: t('common.Custom Title'),
|
||||||
placeholder: t('app.module.Custom Title Tip') || ''
|
placeholder: appT('module.Custom Title Tip') || ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const showToolHandle = useMemo(
|
const showToolHandle = useMemo(
|
||||||
@@ -105,7 +108,7 @@ const NodeCard = (props: Props) => {
|
|||||||
onSuccess: (e) => {
|
onSuccess: (e) => {
|
||||||
if (!e) {
|
if (!e) {
|
||||||
return toast({
|
return toast({
|
||||||
title: t('app.modules.Title is required'),
|
title: appT('modules.Title is required'),
|
||||||
status: 'warning'
|
status: 'warning'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -132,8 +135,8 @@ const NodeCard = (props: Props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
nodeId,
|
|
||||||
showToolHandle,
|
showToolHandle,
|
||||||
|
nodeId,
|
||||||
avatar,
|
avatar,
|
||||||
t,
|
t,
|
||||||
name,
|
name,
|
||||||
@@ -143,7 +146,8 @@ const NodeCard = (props: Props) => {
|
|||||||
intro,
|
intro,
|
||||||
onOpenCustomTitleModal,
|
onOpenCustomTitleModal,
|
||||||
onChangeNode,
|
onChangeNode,
|
||||||
toast
|
toast,
|
||||||
|
appT
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -135,7 +135,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t('common.New Create')}
|
{t('New Create')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -6,6 +6,7 @@ import { appWithTranslation } from 'next-i18next';
|
|||||||
|
|
||||||
import QueryClientContext from '@/web/context/QueryClient';
|
import QueryClientContext from '@/web/context/QueryClient';
|
||||||
import ChakraUIContext from '@/web/context/ChakraUI';
|
import ChakraUIContext from '@/web/context/ChakraUI';
|
||||||
|
import I18nContextProvider from '@/web/context/I18n';
|
||||||
import { useInitApp } from '@/web/context/useInitApp';
|
import { useInitApp } from '@/web/context/useInitApp';
|
||||||
|
|
||||||
import '@/web/styles/reset.scss';
|
import '@/web/styles/reset.scss';
|
||||||
@@ -34,11 +35,13 @@ function App({ Component, pageProps }: AppProps) {
|
|||||||
{scripts?.map((item, i) => <Script key={i} strategy="lazyOnload" {...item}></Script>)}
|
{scripts?.map((item, i) => <Script key={i} strategy="lazyOnload" {...item}></Script>)}
|
||||||
|
|
||||||
<QueryClientContext>
|
<QueryClientContext>
|
||||||
<ChakraUIContext>
|
<I18nContextProvider>
|
||||||
<Layout>
|
<ChakraUIContext>
|
||||||
<Component {...pageProps} />
|
<Layout>
|
||||||
</Layout>
|
<Component {...pageProps} />
|
||||||
</ChakraUIContext>
|
</Layout>
|
||||||
|
</ChakraUIContext>
|
||||||
|
</I18nContextProvider>
|
||||||
</QueryClientContext>
|
</QueryClientContext>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@@ -26,6 +26,7 @@ import { formatTime2HM } from '@fastgpt/global/common/string/time';
|
|||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { WorkflowContext, getWorkflowStore } from '@/components/core/workflow/context';
|
import { WorkflowContext, getWorkflowStore } from '@/components/core/workflow/context';
|
||||||
import { useInterval, useUpdateEffect } from 'ahooks';
|
import { useInterval, useUpdateEffect } from 'ahooks';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const ImportSettings = dynamic(() => import('@/components/core/workflow/Flow/ImportSettings'));
|
const ImportSettings = dynamic(() => import('@/components/core/workflow/Flow/ImportSettings'));
|
||||||
const PublishHistories = dynamic(
|
const PublishHistories = dynamic(
|
||||||
@@ -56,6 +57,8 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { copyData } = useCopyData();
|
const { copyData } = useCopyData();
|
||||||
const { openConfirm: openConfigPublish, ConfirmModal } = useConfirm({
|
const { openConfirm: openConfigPublish, ConfirmModal } = useConfirm({
|
||||||
content: t('core.app.Publish Confirm')
|
content: t('core.app.Publish Confirm')
|
||||||
@@ -177,10 +180,10 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
|
|||||||
null,
|
null,
|
||||||
2
|
2
|
||||||
),
|
),
|
||||||
t('app.Export Config Successful')
|
appT('Export Config Successful')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [copyData, flowData2StoreDataAndCheck, t]);
|
}, [appT, copyData, flowData2StoreDataAndCheck]);
|
||||||
|
|
||||||
// effect
|
// effect
|
||||||
useBeforeunload({
|
useBeforeunload({
|
||||||
@@ -254,12 +257,12 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
|
|||||||
}
|
}
|
||||||
menuList={[
|
menuList={[
|
||||||
{
|
{
|
||||||
label: t('app.Import Configs'),
|
label: appT('Import Configs'),
|
||||||
icon: 'common/importLight',
|
icon: 'common/importLight',
|
||||||
onClick: onOpenImport
|
onClick: onOpenImport
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('app.Export Configs'),
|
label: appT('Export Configs'),
|
||||||
icon: 'export',
|
icon: 'export',
|
||||||
onClick: onExportWorkflow
|
onClick: onExportWorkflow
|
||||||
}
|
}
|
||||||
@@ -316,6 +319,7 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
|
|||||||
isV2Workflow,
|
isV2Workflow,
|
||||||
t,
|
t,
|
||||||
saveLabel,
|
saveLabel,
|
||||||
|
appT,
|
||||||
onOpenImport,
|
onOpenImport,
|
||||||
onExportWorkflow,
|
onExportWorkflow,
|
||||||
openConfigPublish,
|
openConfigPublish,
|
||||||
|
@@ -33,9 +33,12 @@ import { usePagination } from '@fastgpt/web/hooks/usePagination';
|
|||||||
import DateRangePicker, { DateRangeType } from '@fastgpt/web/components/common/DateRangePicker';
|
import DateRangePicker, { DateRangeType } from '@fastgpt/web/components/common/DateRangePicker';
|
||||||
import { formatChatValue2InputType } from '@/components/ChatBox/utils';
|
import { formatChatValue2InputType } from '@/components/ChatBox/utils';
|
||||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const Logs = ({ appId }: { appId: string }) => {
|
const Logs = ({ appId }: { appId: string }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { isPc } = useSystemStore();
|
const { isPc } = useSystemStore();
|
||||||
|
|
||||||
const [dateRange, setDateRange] = useState<DateRangeType>({
|
const [dateRange, setDateRange] = useState<DateRangeType>({
|
||||||
@@ -73,10 +76,10 @@ const Logs = ({ appId }: { appId: string }) => {
|
|||||||
{isPc && (
|
{isPc && (
|
||||||
<>
|
<>
|
||||||
<Box fontWeight={'bold'} fontSize={['md', 'xl']} mb={2}>
|
<Box fontWeight={'bold'} fontSize={['md', 'xl']} mb={2}>
|
||||||
{t('app.Chat logs')}
|
{appT('Chat logs')}
|
||||||
</Box>
|
</Box>
|
||||||
<Box color={'myGray.500'} fontSize={'sm'}>
|
<Box color={'myGray.500'} fontSize={'sm'}>
|
||||||
{t('app.Chat Logs Tips')},{' '}
|
{appT('Chat Logs Tips')},{' '}
|
||||||
<Box
|
<Box
|
||||||
as={'span'}
|
as={'span'}
|
||||||
mr={2}
|
mr={2}
|
||||||
@@ -97,11 +100,11 @@ const Logs = ({ appId }: { appId: string }) => {
|
|||||||
<Thead>
|
<Thead>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Th>{t('core.app.logs.Source And Time')}</Th>
|
<Th>{t('core.app.logs.Source And Time')}</Th>
|
||||||
<Th>{t('app.Logs Title')}</Th>
|
<Th>{appT('Logs Title')}</Th>
|
||||||
<Th>{t('app.Logs Message Total')}</Th>
|
<Th>{appT('Logs Message Total')}</Th>
|
||||||
<Th>{t('app.Feedback Count')}</Th>
|
<Th>{appT('Feedback Count')}</Th>
|
||||||
<Th>{t('core.app.feedback.Custom feedback')}</Th>
|
<Th>{t('core.app.feedback.Custom feedback')}</Th>
|
||||||
<Th>{t('app.Mark Count')}</Th>
|
<Th>{appT('Mark Count')}</Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
@@ -176,7 +179,7 @@ const Logs = ({ appId }: { appId: string }) => {
|
|||||||
<Flex h={'100%'} flexDirection={'column'} alignItems={'center'} pt={'10vh'}>
|
<Flex h={'100%'} flexDirection={'column'} alignItems={'center'} pt={'10vh'}>
|
||||||
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
|
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
|
||||||
<Box mt={2} color={'myGray.500'}>
|
<Box mt={2} color={'myGray.500'}>
|
||||||
{t('app.Logs Empty')}
|
{appT('Logs Empty')}
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
|
@@ -15,11 +15,14 @@ import Avatar from '@/components/Avatar';
|
|||||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
import TagsEditModal from './TagsEditModal';
|
import TagsEditModal from './TagsEditModal';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
const InfoModal = dynamic(() => import('../InfoModal'));
|
const InfoModal = dynamic(() => import('../InfoModal'));
|
||||||
|
|
||||||
const AppCard = ({ appId }: { appId: string }) => {
|
const AppCard = ({ appId }: { appId: string }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { appDetail } = useAppStore();
|
const { appDetail } = useAppStore();
|
||||||
const { feConfigs } = useSystemStore();
|
const { feConfigs } = useSystemStore();
|
||||||
@@ -27,7 +30,7 @@ const AppCard = ({ appId }: { appId: string }) => {
|
|||||||
const [TeamTagsSet, setTeamTagsSet] = useState<AppSchema>();
|
const [TeamTagsSet, setTeamTagsSet] = useState<AppSchema>();
|
||||||
|
|
||||||
const { openConfirm: openConfirmDel, ConfirmModal: ConfirmDelModal } = useConfirm({
|
const { openConfirm: openConfirmDel, ConfirmModal: ConfirmDelModal } = useConfirm({
|
||||||
content: t('app.Confirm Del App Tip'),
|
content: appT('Confirm Del App Tip'),
|
||||||
type: 'delete'
|
type: 'delete'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -21,6 +21,7 @@ import { UseFormReturn } from 'react-hook-form';
|
|||||||
import { AppSimpleEditFormType } from '@fastgpt/global/core/app/type';
|
import { AppSimpleEditFormType } from '@fastgpt/global/core/app/type';
|
||||||
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
||||||
import { form2AppWorkflow } from '@/web/core/app/utils';
|
import { form2AppWorkflow } from '@/web/core/app/utils';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const ChatTest = ({
|
const ChatTest = ({
|
||||||
editForm,
|
editForm,
|
||||||
@@ -30,6 +31,8 @@ const ChatTest = ({
|
|||||||
appId: string;
|
appId: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { userInfo } = useUserStore();
|
const { userInfo } = useUserStore();
|
||||||
const ChatBoxRef = useRef<ComponentRef>(null);
|
const ChatBoxRef = useRef<ComponentRef>(null);
|
||||||
const { appDetail } = useAppStore();
|
const { appDetail } = useAppStore();
|
||||||
@@ -114,7 +117,7 @@ const ChatTest = ({
|
|||||||
>
|
>
|
||||||
<Flex px={[2, 5]}>
|
<Flex px={[2, 5]}>
|
||||||
<Box fontSize={['md', 'xl']} fontWeight={'bold'} flex={1}>
|
<Box fontSize={['md', 'xl']} fontWeight={'bold'} flex={1}>
|
||||||
{t('app.Chat Debug')}
|
{appT('Chat Debug')}
|
||||||
</Box>
|
</Box>
|
||||||
<MyTooltip label={t('core.chat.Restart')}>
|
<MyTooltip label={t('core.chat.Restart')}>
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -160,7 +163,7 @@ const ChatTest = ({
|
|||||||
whiteSpace={'pre-wrap'}
|
whiteSpace={'pre-wrap'}
|
||||||
textAlign={'center'}
|
textAlign={'center'}
|
||||||
>
|
>
|
||||||
<Box>{t('app.Advance App TestTip')}</Box>
|
<Box>{appT('Advance App TestTip')}</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@@ -29,6 +29,7 @@ import DeleteIcon, { hoverDeleteStyles } from '@fastgpt/web/components/common/Ic
|
|||||||
import { TTSTypeEnum } from '@/constants/app';
|
import { TTSTypeEnum } from '@/constants/app';
|
||||||
import { getSystemVariables } from '@/web/core/app/utils';
|
import { getSystemVariables } from '@/web/core/app/utils';
|
||||||
import { useUpdate } from 'ahooks';
|
import { useUpdate } from 'ahooks';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const DatasetSelectModal = dynamic(() => import('@/components/core/app/DatasetSelectModal'));
|
const DatasetSelectModal = dynamic(() => import('@/components/core/app/DatasetSelectModal'));
|
||||||
const DatasetParamsModal = dynamic(() => import('@/components/core/app/DatasetParamsModal'));
|
const DatasetParamsModal = dynamic(() => import('@/components/core/app/DatasetParamsModal'));
|
||||||
@@ -61,6 +62,8 @@ const EditForm = ({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { publishApp, appDetail } = useAppStore();
|
const { publishApp, appDetail } = useAppStore();
|
||||||
|
|
||||||
const { allDatasets } = useDatasetStore();
|
const { allDatasets } = useDatasetStore();
|
||||||
@@ -200,7 +203,7 @@ const EditForm = ({
|
|||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name={'core/app/simpleMode/ai'} w={'20px'} />
|
<MyIcon name={'core/app/simpleMode/ai'} w={'20px'} />
|
||||||
<Box ml={2} flex={1}>
|
<Box ml={2} flex={1}>
|
||||||
{t('app.AI Settings')}
|
{appT('AI Settings')}
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex alignItems={'center'} mt={5}>
|
<Flex alignItems={'center'} mt={5}>
|
||||||
|
@@ -17,6 +17,7 @@ import { serviceSideProps } from '@/web/common/utils/i18n';
|
|||||||
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const FlowEdit = dynamic(() => import('./components/FlowEdit'), {
|
const FlowEdit = dynamic(() => import('./components/FlowEdit'), {
|
||||||
loading: () => <Loading />
|
loading: () => <Loading />
|
||||||
@@ -34,6 +35,8 @@ enum TabEnum {
|
|||||||
|
|
||||||
const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { feConfigs } = useSystemStore();
|
const { feConfigs } = useSystemStore();
|
||||||
@@ -74,10 +77,10 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
|||||||
id: TabEnum.publish,
|
id: TabEnum.publish,
|
||||||
icon: 'support/outlink/shareLight'
|
icon: 'support/outlink/shareLight'
|
||||||
},
|
},
|
||||||
{ label: t('app.Chat logs'), id: TabEnum.logs, icon: 'core/app/logsLight' },
|
{ label: appT('Chat logs'), id: TabEnum.logs, icon: 'core/app/logsLight' },
|
||||||
{ label: t('core.Start chat'), id: TabEnum.startChat, icon: 'core/chat/chatLight' }
|
{ label: t('core.Start chat'), id: TabEnum.startChat, icon: 'core/chat/chatLight' }
|
||||||
],
|
],
|
||||||
[feConfigs?.hide_app_flow, t]
|
[appT, feConfigs?.hide_app_flow, t]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onCloseFlowEdit = useCallback(() => setCurrentTab(TabEnum.simpleEdit), [setCurrentTab]);
|
const onCloseFlowEdit = useCallback(() => setCurrentTab(TabEnum.simpleEdit), [setCurrentTab]);
|
||||||
@@ -150,7 +153,7 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
|||||||
borderRadius={'50%'}
|
borderRadius={'50%'}
|
||||||
aria-label={''}
|
aria-label={''}
|
||||||
/>
|
/>
|
||||||
{t('app.My Apps')}
|
{appT('My Apps')}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
{/* phone tab */}
|
{/* phone tab */}
|
||||||
@@ -193,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)) }
|
props: { currentTab, ...(await serviceSideProps(context, ['app'])) }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useState, useEffect } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Box, Grid, Flex, IconButton, Button, useDisclosure } from '@chakra-ui/react';
|
import { Box, Grid, Flex, IconButton, Button, useDisclosure } from '@chakra-ui/react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
@@ -7,7 +7,6 @@ import { delModelById } from '@/web/core/app/api';
|
|||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||||
import { useTranslation } from 'next-i18next';
|
|
||||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
import PageContainer from '@/components/PageContainer';
|
import PageContainer from '@/components/PageContainer';
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
@@ -16,10 +15,12 @@ import CreateModal from './component/CreateModal';
|
|||||||
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
||||||
import PermissionIconText from '@/components/support/permission/IconText';
|
import PermissionIconText from '@/components/support/permission/IconText';
|
||||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const MyApps = () => {
|
const MyApps = () => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { t } = useTranslation();
|
const { appT, commonT } = useI18n();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { userInfo } = useUserStore();
|
const { userInfo } = useUserStore();
|
||||||
const { myApps, loadMyApps } = useAppStore();
|
const { myApps, loadMyApps } = useAppStore();
|
||||||
@@ -62,10 +63,10 @@ const MyApps = () => {
|
|||||||
<PageContainer isLoading={isFetching} insertProps={{ px: [5, '48px'] }}>
|
<PageContainer isLoading={isFetching} insertProps={{ px: [5, '48px'] }}>
|
||||||
<Flex pt={[4, '30px']} alignItems={'center'} justifyContent={'space-between'}>
|
<Flex pt={[4, '30px']} alignItems={'center'} justifyContent={'space-between'}>
|
||||||
<Box letterSpacing={1} fontSize={['20px', '24px']} color={'myGray.900'}>
|
<Box letterSpacing={1} fontSize={['20px', '24px']} color={'myGray.900'}>
|
||||||
{t('app.My Apps')}
|
{appT('My Apps')}
|
||||||
</Box>
|
</Box>
|
||||||
<Button leftIcon={<AddIcon />} variant={'primaryOutline'} onClick={onOpenCreateModal}>
|
<Button leftIcon={<AddIcon />} variant={'primaryOutline'} onClick={onOpenCreateModal}>
|
||||||
{t('common.New Create')}
|
{commonT('New Create')}
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Grid
|
<Grid
|
||||||
@@ -76,7 +77,7 @@ const MyApps = () => {
|
|||||||
{myApps.map((app) => (
|
{myApps.map((app) => (
|
||||||
<MyTooltip
|
<MyTooltip
|
||||||
key={app._id}
|
key={app._id}
|
||||||
label={userInfo?.team.canWrite ? t('app.To Settings') : t('app.To Chat')}
|
label={userInfo?.team.canWrite ? appT('To Settings') : appT('To Chat')}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
lineHeight={1.5}
|
lineHeight={1.5}
|
||||||
@@ -168,9 +169,6 @@ const MyApps = () => {
|
|||||||
</MyTooltip>
|
</MyTooltip>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
{/* (
|
|
||||||
<ShareBox></ShareBox>
|
|
||||||
) */}
|
|
||||||
|
|
||||||
{myApps.length === 0 && (
|
{myApps.length === 0 && (
|
||||||
<Flex mt={'35vh'} flexDirection={'column'} alignItems={'center'}>
|
<Flex mt={'35vh'} flexDirection={'column'} alignItems={'center'}>
|
||||||
@@ -191,7 +189,7 @@ const MyApps = () => {
|
|||||||
export async function getServerSideProps(content: any) {
|
export async function getServerSideProps(content: any) {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
...(await serviceSideProps(content))
|
...(await serviceSideProps(content, ['app']))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import { useUserStore } from '@/web/support/user/useUserStore';
|
|||||||
import { AppListItemType } from '@fastgpt/global/core/app/type';
|
import { AppListItemType } from '@fastgpt/global/core/app/type';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
type HistoryItemType = {
|
type HistoryItemType = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -68,6 +69,8 @@ const ChatHistorySlider = ({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { isPc } = useSystemStore();
|
const { isPc } = useSystemStore();
|
||||||
const { userInfo } = useUserStore();
|
const { userInfo } = useUserStore();
|
||||||
|
|
||||||
@@ -86,7 +89,8 @@ const ChatHistorySlider = ({
|
|||||||
const concatHistory = useMemo<HistoryItemType[]>(
|
const concatHistory = useMemo<HistoryItemType[]>(
|
||||||
() =>
|
() =>
|
||||||
!activeChatId
|
!activeChatId
|
||||||
? [{ id: activeChatId, title: t('core.chat.New Chat') }].concat(history)
|
? //@ts-ignore
|
||||||
|
[{ id: activeChatId, title: t('core.chat.New Chat') }].concat(history)
|
||||||
: history,
|
: history,
|
||||||
[activeChatId, history, t]
|
[activeChatId, history, t]
|
||||||
);
|
);
|
||||||
@@ -115,7 +119,7 @@ const ChatHistorySlider = ({
|
|||||||
whiteSpace={'nowrap'}
|
whiteSpace={'nowrap'}
|
||||||
>
|
>
|
||||||
{isPc && (
|
{isPc && (
|
||||||
<MyTooltip label={canRouteToDetail ? t('app.App Detail') : ''} offset={[0, 0]}>
|
<MyTooltip label={canRouteToDetail ? appT('App Detail') : ''} offset={[0, 0]}>
|
||||||
<Flex
|
<Flex
|
||||||
pt={5}
|
pt={5}
|
||||||
pb={2}
|
pb={2}
|
||||||
|
@@ -17,6 +17,7 @@ import {
|
|||||||
} from '@/web/core/workflow/utils';
|
} from '@/web/core/workflow/utils';
|
||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { WorkflowContext, getWorkflowStore } from '@/components/core/workflow/context';
|
import { WorkflowContext, getWorkflowStore } from '@/components/core/workflow/context';
|
||||||
|
import { useI18n } from '@/web/context/I18n';
|
||||||
|
|
||||||
const ImportSettings = dynamic(() => import('@/components/core/workflow/Flow/ImportSettings'));
|
const ImportSettings = dynamic(() => import('@/components/core/workflow/Flow/ImportSettings'));
|
||||||
|
|
||||||
@@ -25,6 +26,8 @@ type Props = { plugin: PluginItemSchema; onClose: () => void };
|
|||||||
const Header = ({ plugin, onClose }: Props) => {
|
const Header = ({ plugin, onClose }: Props) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { appT } = useI18n();
|
||||||
|
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { copyData } = useCopyData();
|
const { copyData } = useCopyData();
|
||||||
const edges = useContextSelector(WorkflowContext, (v) => v.edges);
|
const edges = useContextSelector(WorkflowContext, (v) => v.edges);
|
||||||
@@ -77,10 +80,10 @@ const Header = ({ plugin, onClose }: Props) => {
|
|||||||
null,
|
null,
|
||||||
2
|
2
|
||||||
),
|
),
|
||||||
t('app.Export Config Successful')
|
appT('Export Config Successful')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [copyData, flowData2StoreDataAndCheck, t]);
|
}, [appT, copyData, flowData2StoreDataAndCheck]);
|
||||||
|
|
||||||
const Render = useMemo(() => {
|
const Render = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
@@ -118,9 +121,9 @@ const Header = ({ plugin, onClose }: Props) => {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
menuList={[
|
menuList={[
|
||||||
{ label: t('app.Import Configs'), icon: 'common/importLight', onClick: onOpenImport },
|
{ label: appT('Import Configs'), icon: 'common/importLight', onClick: onOpenImport },
|
||||||
{
|
{
|
||||||
label: t('app.Export Configs'),
|
label: appT('Export Configs'),
|
||||||
icon: 'export',
|
icon: 'export',
|
||||||
onClick: onCopy
|
onClick: onCopy
|
||||||
}
|
}
|
||||||
@@ -139,6 +142,7 @@ const Header = ({ plugin, onClose }: Props) => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
|
appT,
|
||||||
isLoading,
|
isLoading,
|
||||||
isOpenImport,
|
isOpenImport,
|
||||||
onClose,
|
onClose,
|
||||||
|
14
projects/app/src/types/i18n.d.ts
vendored
14
projects/app/src/types/i18n.d.ts
vendored
@@ -1,14 +1,20 @@
|
|||||||
import 'i18next';
|
import 'i18next';
|
||||||
//import common from '../../i18n/en/common.json';
|
import common from '../../i18n/en/common.json';
|
||||||
|
import dataset from '../../i18n/en/dataset.json';
|
||||||
|
import app from '../../i18n/en/app.json';
|
||||||
|
|
||||||
interface I18nNamespaces {
|
export interface I18nNamespaces {
|
||||||
common: any;
|
common: typeof common;
|
||||||
|
dataset: typeof dataset;
|
||||||
|
app: typeof app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type I18nNsType = (keyof I18nNamespaces)[];
|
||||||
|
|
||||||
declare module 'i18next' {
|
declare module 'i18next' {
|
||||||
interface CustomTypeOptions {
|
interface CustomTypeOptions {
|
||||||
returnNull: false;
|
returnNull: false;
|
||||||
defaultNs: 'common';
|
defaultNs: 'common';
|
||||||
// resources: I18nNamespaces;
|
resources: I18nNamespaces;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { I18nNsType } from '@/types/i18n';
|
||||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||||
|
|
||||||
export const LANG_KEY = 'NEXT_LOCALE_LANG';
|
export const LANG_KEY = 'NEXT_LOCALE_LANG';
|
||||||
@@ -16,8 +17,8 @@ export const langMap = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const serviceSideProps = (content: any) => {
|
export const serviceSideProps = (content: any, ns: I18nNsType = []) => {
|
||||||
return serverSideTranslations(content.locale, undefined, null, content.locales);
|
return serverSideTranslations(content.locale, ['common', ...ns], null, content.locales);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLng = (lng: string) => {
|
export const getLng = (lng: string) => {
|
||||||
|
38
projects/app/src/web/context/I18n.tsx
Normal file
38
projects/app/src/web/context/I18n.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { createContext, useContextSelector } from 'use-context-selector';
|
||||||
|
import { useTranslation } from 'next-i18next';
|
||||||
|
import { TFunction } from 'i18next';
|
||||||
|
|
||||||
|
type I18nContextType = {
|
||||||
|
commonT: TFunction<['common'], undefined>;
|
||||||
|
appT: TFunction<['app'], undefined>;
|
||||||
|
datasetT: TFunction<['dataset'], undefined>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const I18nContext = createContext<I18nContextType>({
|
||||||
|
// @ts-ignore
|
||||||
|
commonT: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
const I18nContextProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const { t: commonT } = useTranslation('common');
|
||||||
|
const { t: appT } = useTranslation('app');
|
||||||
|
const { t: datasetT } = useTranslation('dataset');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<I18nContext.Provider
|
||||||
|
value={{
|
||||||
|
commonT,
|
||||||
|
appT,
|
||||||
|
datasetT
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</I18nContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default I18nContextProvider;
|
||||||
|
|
||||||
|
export const useI18n = () => {
|
||||||
|
return useContextSelector(I18nContext, (ctx) => ctx);
|
||||||
|
};
|
Reference in New Issue
Block a user