From 10dcdb54912dde09a691347ab5086f68e0f9b33f Mon Sep 17 00:00:00 2001 From: papapatrick <109422393+Patrickill@users.noreply.github.com> Date: Mon, 5 Aug 2024 18:42:21 +0800 Subject: [PATCH] I18n Translations (#2267) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * rebase * i18n-1 * add error info i18n * fix * fix * refactor: 删除error.json * delete useI18n --- packages/global/common/error/code/app.ts | 6 +- packages/global/common/error/code/chat.ts | 4 +- packages/global/common/error/code/openapi.ts | 10 +- packages/global/common/error/code/outLink.ts | 13 +- packages/global/common/error/code/plugin.ts | 8 +- packages/global/common/error/code/system.ts | 6 +- packages/global/common/error/code/team.ts | 46 +++- packages/global/common/error/code/user.ts | 22 +- packages/global/common/error/errorCode.ts | 38 ++-- .../PromptEditor/modules/ComfirmVar/index.tsx | 9 +- packages/web/hooks/usePagination.tsx | 15 +- packages/web/hooks/useScrollPagination.tsx | 2 +- packages/web/i18n/en/app.json | 30 +++ packages/web/i18n/en/chat.json | 41 +++- packages/web/i18n/en/common.json | 202 ++++++++++++++++- packages/web/i18n/en/file.json | 7 +- packages/web/i18n/en/user.json | 65 +++++- packages/web/i18n/en/workflow.json | 3 + packages/web/i18n/zh/app.json | 32 ++- packages/web/i18n/zh/chat.json | 21 +- packages/web/i18n/zh/common.json | 210 ++++++++++++++++-- packages/web/i18n/zh/file.json | 5 +- packages/web/i18n/zh/user.json | 62 +++++- packages/web/i18n/zh/workflow.json | 5 +- packages/web/types/i18next.d.ts | 1 - .../src/components/CommunityModal/index.tsx | 2 +- .../src/components/PromptTemplate/index.tsx | 6 +- .../components/common/folder/SlideCard.tsx | 4 +- .../core/ai/AISettingModal/index.tsx | 4 +- .../core/app/ScheduledTriggerConfig.tsx | 67 +++--- .../ChatBox/components/ContextModal.tsx | 5 +- .../ChatBox/components/ResponseTags.tsx | 12 +- .../components/SelectMarkCollection.tsx | 2 +- .../ChatBox/hooks/useChatBox.tsx | 7 +- .../core/chat/ChatContainer/ChatBox/index.tsx | 4 +- .../PluginRunBox/components/RenderOutput.tsx | 8 +- .../components/RenderResponseDetail.tsx | 6 +- .../ChatContainer/PluginRunBox/context.tsx | 6 +- .../chat/components/WholeResponseModal.tsx | 2 +- .../src/components/support/apikey/Table.tsx | 6 +- .../support/laf/LafAccountModal.tsx | 6 +- .../permission/DefaultPerList/index.tsx | 13 +- .../MemberManager/AddMemberModal.tsx | 16 +- .../permission/MemberManager/ManageModal.tsx | 21 +- .../PermissionManage/AddManager.tsx | 8 +- .../components/PermissionManage/index.tsx | 6 +- .../support/user/team/TeamTagModal/index.tsx | 6 +- .../support/wallet/QRCodePayModal.tsx | 2 +- .../wallet/StandardPlanContentList.tsx | 4 +- .../app/src/global/core/chat/constants.ts | 4 +- projects/app/src/pages/_app.tsx | 6 +- .../pages/account/components/BillTable.tsx | 9 +- .../app/src/pages/account/components/Info.tsx | 14 +- .../pages/account/components/InformTable.tsx | 4 +- .../account/components/OpenAIAccountModal.tsx | 10 +- .../src/pages/account/components/PayModal.tsx | 8 +- .../pages/account/components/Promotion.tsx | 10 +- .../components/UpdateNotificationModal.tsx | 6 +- .../account/components/UpdatePswModal.tsx | 14 +- .../pages/account/components/UsageTable.tsx | 6 +- .../components/standardDetailModal.tsx | 6 +- projects/app/src/pages/account/index.tsx | 2 +- projects/app/src/pages/api/core/chat/init.ts | 3 +- .../src/pages/api/core/chat/outLink/init.ts | 3 +- .../app/src/pages/api/core/chat/team/init.ts | 3 +- .../pages/app/detail/components/InfoModal.tsx | 2 +- .../components/Logs/DetailLogsModal.tsx | 8 +- .../app/detail/components/Logs/index.tsx | 2 +- .../app/detail/components/Plugin/index.tsx | 4 +- .../Publish/FeiShu/FeiShuEditModal.tsx | 6 +- .../app/detail/components/Workflow/index.tsx | 4 +- .../WorkflowComponents/Flow/ChatTest.tsx | 2 +- .../Flow/ImportSettings.tsx | 6 +- .../Flow/NodeTemplatesModal.tsx | 4 +- .../Flow/SelectAppModal.tsx | 2 +- .../Flow/hooks/useDebug.tsx | 2 +- .../WorkflowComponents/Flow/index.tsx | 3 +- .../Flow/nodes/NodeCQNode.tsx | 2 +- .../Flow/nodes/NodeDatasetConcat.tsx | 5 +- .../Flow/nodes/NodeExtract/index.tsx | 10 +- .../Flow/nodes/NodeIfElse/ListItem.tsx | 2 +- .../WorkflowComponents/Flow/nodes/NodeLaf.tsx | 4 +- .../Flow/nodes/render/NodeCard.tsx | 2 +- .../render/RenderToolInput/EditFieldModal.tsx | 4 +- .../nodes/render/RenderToolInput/index.tsx | 6 +- .../components/WorkflowComponents/context.tsx | 4 +- .../pages/app/detail/components/constants.tsx | 6 +- .../src/pages/app/list/components/List.tsx | 8 +- .../chat/components/CustomPluginRunBox.tsx | 4 +- .../Import/components/FileSelector.tsx | 2 +- .../pages/dataset/detail/components/Test.tsx | 4 +- .../src/pages/dataset/list/component/List.tsx | 4 +- .../login/components/ForgetPasswordForm.tsx | 36 +-- .../login/components/LoginForm/LoginForm.tsx | 6 +- .../login/components/LoginForm/WechatForm.tsx | 2 +- .../pages/login/components/RegisterForm.tsx | 35 +-- projects/app/src/pages/login/fastlogin.tsx | 8 +- projects/app/src/pages/login/index.tsx | 3 +- projects/app/src/pages/login/provider.tsx | 6 +- .../src/pages/price/components/ExtraPlan.tsx | 14 +- .../app/src/pages/price/components/FAQ.tsx | 32 +-- .../app/src/pages/price/components/Points.tsx | 39 +++- .../src/pages/price/components/Standard.tsx | 31 ++- projects/app/src/pages/tools/index.tsx | 8 +- projects/app/src/web/common/utils/i18n.ts | 2 +- projects/app/src/web/core/app/constants.ts | 4 +- .../src/web/support/user/hooks/useSendCode.ts | 12 +- 107 files changed, 1128 insertions(+), 416 deletions(-) diff --git a/packages/global/common/error/code/app.ts b/packages/global/common/error/code/app.ts index e3dfdcf3a..65be4da30 100644 --- a/packages/global/common/error/code/app.ts +++ b/packages/global/common/error/code/app.ts @@ -1,5 +1,5 @@ import { ErrType } from '../errorCode'; - +import { i18nT } from '../../../../web/i18n/utils'; /* dataset: 502000 */ export enum AppErrEnum { unExist = 'appUnExist', @@ -8,11 +8,11 @@ export enum AppErrEnum { const appErrList = [ { statusText: AppErrEnum.unExist, - message: '应用不存在' + message: i18nT('common:code_error.app_error.not_exist') }, { statusText: AppErrEnum.unAuthApp, - message: '无权操作该应用' + message: i18nT('common:code_error.app_error.un_auth_app') } ]; export default appErrList.reduce((acc, cur, index) => { diff --git a/packages/global/common/error/code/chat.ts b/packages/global/common/error/code/chat.ts index 00f5c8aed..bbd810d9a 100644 --- a/packages/global/common/error/code/chat.ts +++ b/packages/global/common/error/code/chat.ts @@ -1,5 +1,5 @@ import { ErrType } from '../errorCode'; - +import { i18nT } from '../../../../web/i18n/utils'; /* dataset: 504000 */ export enum ChatErrEnum { unAuthChat = 'unAuthChat' @@ -7,7 +7,7 @@ export enum ChatErrEnum { const errList = [ { statusText: ChatErrEnum.unAuthChat, - message: '无权操作该对话记录' + message: i18nT('common:code_error.chat_error.un_auth') } ]; export default errList.reduce((acc, cur, index) => { diff --git a/packages/global/common/error/code/openapi.ts b/packages/global/common/error/code/openapi.ts index f4acb46de..4c490bdf2 100644 --- a/packages/global/common/error/code/openapi.ts +++ b/packages/global/common/error/code/openapi.ts @@ -1,25 +1,27 @@ import { ErrType } from '../errorCode'; - +import { i18nT } from '../../../../web/i18n/utils'; /* dataset: 506000 */ export enum OpenApiErrEnum { unExist = 'openapiUnExist', unAuth = 'openapiUnAuth', exceedLimit = 'openapiExceedLimit' } + const errList = [ { statusText: OpenApiErrEnum.unExist, - message: 'Api Key 不存在' + message: i18nT('common:code_error.openapi_error.api_key_not_exist') }, { statusText: OpenApiErrEnum.unAuth, - message: '无权操作该 Api Key' + message: i18nT('common:code_error.openapi_error.un_auth') }, { statusText: OpenApiErrEnum.exceedLimit, - message: '最多 10 组 API 密钥' + message: i18nT('common:code_error.openapi_error.exceed_limit') } ]; + export default errList.reduce((acc, cur, index) => { return { ...acc, diff --git a/packages/global/common/error/code/outLink.ts b/packages/global/common/error/code/outLink.ts index 25ee6fab8..e5f14229c 100644 --- a/packages/global/common/error/code/outLink.ts +++ b/packages/global/common/error/code/outLink.ts @@ -1,32 +1,33 @@ import { ErrType } from '../errorCode'; - +import { i18nT } from '../../../../web/i18n/utils'; /* dataset: 505000 */ export enum OutLinkErrEnum { unExist = 'outlinkUnExist', unAuthLink = 'unAuthLink', linkUnInvalid = 'linkUnInvalid', - unAuthUser = 'unAuthUser' } + const errList = [ { statusText: OutLinkErrEnum.unExist, - message: '分享链接不存在' + message: i18nT('common:code_error.outlink_error.link_not_exist') }, { statusText: OutLinkErrEnum.unAuthLink, - message: '分享链接无效' + message: i18nT('common:code_error.outlink_error.invalid_link') }, { code: 501, statusText: OutLinkErrEnum.linkUnInvalid, - message: '分享链接无效' + message: i18nT('common:code_error.outlink_error.invalid_link') // 使用相同的错误消息 }, { statusText: OutLinkErrEnum.unAuthUser, - message: '身份校验失败' + message: i18nT('common:code_error.outlink_error.un_auth_user') } ]; + export default errList.reduce((acc, cur, index) => { return { ...acc, diff --git a/packages/global/common/error/code/plugin.ts b/packages/global/common/error/code/plugin.ts index f2027b6aa..416b503ea 100644 --- a/packages/global/common/error/code/plugin.ts +++ b/packages/global/common/error/code/plugin.ts @@ -1,20 +1,22 @@ import { ErrType } from '../errorCode'; - +import { i18nT } from '../../../../web/i18n/utils'; /* dataset: 508000 */ export enum PluginErrEnum { unExist = 'pluginUnExist', unAuth = 'pluginUnAuth' } + const errList = [ { statusText: PluginErrEnum.unExist, - message: '插件不存在' + message: i18nT('common:code_error.plugin_error.not_exist') }, { statusText: PluginErrEnum.unAuth, - message: '无权操作该插件' + message: i18nT('common:code_error.plugin_error.un_auth') } ]; + export default errList.reduce((acc, cur, index) => { return { ...acc, diff --git a/packages/global/common/error/code/system.ts b/packages/global/common/error/code/system.ts index 700670382..88a655c4e 100644 --- a/packages/global/common/error/code/system.ts +++ b/packages/global/common/error/code/system.ts @@ -1,15 +1,17 @@ import { ErrType } from '../errorCode'; - +import { i18nT } from '../../../../web/i18n/utils'; /* dataset: 509000 */ export enum SystemErrEnum { communityVersionNumLimit = 'communityVersionNumLimit' } + const systemErr = [ { statusText: SystemErrEnum.communityVersionNumLimit, - message: '超出开源版数量限制,请升级商业版: https://fastgpt.in' + message: i18nT('common:code_error.system_error.community_version_num_limit') } ]; + export default systemErr.reduce((acc, cur, index) => { return { ...acc, diff --git a/packages/global/common/error/code/team.ts b/packages/global/common/error/code/team.ts index 80674304a..f404afe1a 100644 --- a/packages/global/common/error/code/team.ts +++ b/packages/global/common/error/code/team.ts @@ -1,5 +1,5 @@ import { ErrType } from '../errorCode'; - +import { i18nT } from '../../../../web/i18n/utils'; /* team: 500000 */ export enum TeamErrEnum { teamOverSize = 'teamOverSize', @@ -12,17 +12,43 @@ export enum TeamErrEnum { websiteSyncNotEnough = 'websiteSyncNotEnough', reRankNotEnough = 'reRankNotEnough' } + const teamErr = [ - { statusText: TeamErrEnum.teamOverSize, message: 'error.team.overSize' }, - { statusText: TeamErrEnum.unAuthTeam, message: '无权操作该团队' }, - { statusText: TeamErrEnum.aiPointsNotEnough, message: '' }, - { statusText: TeamErrEnum.datasetSizeNotEnough, message: '知识库容量不足,请先扩容~' }, - { statusText: TeamErrEnum.datasetAmountNotEnough, message: '知识库数量已达上限~' }, - { statusText: TeamErrEnum.appAmountNotEnough, message: '应用数量已达上限~' }, - { statusText: TeamErrEnum.pluginAmountNotEnough, message: '插件数量已达上限~' }, - { statusText: TeamErrEnum.websiteSyncNotEnough, message: '无权使用Web站点同步~' }, - { statusText: TeamErrEnum.reRankNotEnough, message: '无权使用检索重排~' } + { + statusText: TeamErrEnum.teamOverSize, + message: i18nT('common:code_error.team_error.over_size') + }, + { statusText: TeamErrEnum.unAuthTeam, message: i18nT('common:code_error.team_error.un_auth') }, + { + statusText: TeamErrEnum.aiPointsNotEnough, + message: i18nT('common:code_error.team_error.ai_points_not_enough') + }, // 需要定义或留空 + { + statusText: TeamErrEnum.datasetSizeNotEnough, + message: i18nT('common:code_error.team_error.dataset_size_not_enough') + }, + { + statusText: TeamErrEnum.datasetAmountNotEnough, + message: i18nT('common:code_error.team_error.dataset_amount_not_enough') + }, + { + statusText: TeamErrEnum.appAmountNotEnough, + message: i18nT('common:code_error.team_error.app_amount_not_enough') + }, + { + statusText: TeamErrEnum.pluginAmountNotEnough, + message: i18nT('common:code_error.team_error.plugin_amount_not_enough') + }, + { + statusText: TeamErrEnum.websiteSyncNotEnough, + message: i18nT('common:code_error.team_error.website_sync_not_enough') + }, + { + statusText: TeamErrEnum.reRankNotEnough, + message: i18nT('common:code_error.team_error.re_rank_not_enough') + } ]; + export default teamErr.reduce((acc, cur, index) => { return { ...acc, diff --git a/packages/global/common/error/code/user.ts b/packages/global/common/error/code/user.ts index 028b65273..88808c397 100644 --- a/packages/global/common/error/code/user.ts +++ b/packages/global/common/error/code/user.ts @@ -1,5 +1,5 @@ import { ErrType } from '../errorCode'; - +import { i18nT } from '../../../../web/i18n/utils'; /* team: 503000 */ export enum UserErrEnum { unAuthUser = 'unAuthUser', @@ -8,10 +8,22 @@ export enum UserErrEnum { balanceNotEnough = 'balanceNotEnough' } const errList = [ - { statusText: UserErrEnum.unAuthUser, message: '找不到该用户' }, - { statusText: UserErrEnum.binVisitor, message: '您的身份校验未通过' }, - { statusText: UserErrEnum.binVisitor, message: '您当前身份为游客,无权操作' }, - { statusText: UserErrEnum.balanceNotEnough, message: '账号余额不足~' } + { + statusText: UserErrEnum.unAuthUser, + message: i18nT('common:code_error.user_error.un_auth_user') + }, + { + statusText: UserErrEnum.binVisitor, + message: i18nT('common:code_error.user_error.bin_visitor') + }, // 身份校验未通过 + { + statusText: UserErrEnum.binVisitor, + message: i18nT('common:code_error.user_error.bin_visitor_guest') + }, // 游客身份 + { + statusText: UserErrEnum.balanceNotEnough, + message: i18nT('common:code_error.user_error.balance_not_enough') + } ]; export default errList.reduce((acc, cur, index) => { return { diff --git a/packages/global/common/error/errorCode.ts b/packages/global/common/error/errorCode.ts index bb6785119..e39ac887f 100644 --- a/packages/global/common/error/errorCode.ts +++ b/packages/global/common/error/errorCode.ts @@ -8,24 +8,25 @@ import teamErr from './code/team'; import userErr from './code/user'; import commonErr from './code/common'; import SystemErrEnum from './code/system'; +import { i18nT } from '../../../web/i18n/utils'; export const ERROR_CODE: { [key: number]: string } = { - 400: '请求失败', - 401: '无权访问', - 403: '紧张访问', - 404: '请求不存在', - 405: '请求方法错误', - 406: '请求的格式错误', - 410: '资源已删除', - 422: '验证错误', - 500: '服务器发生错误', - 502: '网关错误', - 503: '服务器暂时过载或维护', - 504: '网关超时' + 400: i18nT('common:code_error.error_code.400'), + 401: i18nT('common:code_error.error_code.401'), + 403: i18nT('common:code_error.error_code.403'), + 404: i18nT('common:code_error.error_code.404'), + 405: i18nT('common:code_error.error_code.405'), + 406: i18nT('common:code_error.error_code.406'), + 410: i18nT('common:code_error.error_code.410'), + 422: i18nT('common:code_error.error_code.422'), + 500: i18nT('common:code_error.error_code.500'), + 502: i18nT('common:code_error.error_code.502'), + 503: i18nT('common:code_error.error_code.503'), + 504: i18nT('common:code_error.error_code.504') }; export const TOKEN_ERROR_CODE: Record = { - 403: '登录状态无效,请重新登录' + 403: i18nT('common:code_error.token_error_code.403') }; export const proxyError: Record = { @@ -63,32 +64,31 @@ export const ERROR_RESPONSE: Record< [ERROR_ENUM.unAuthorization]: { code: 403, statusText: ERROR_ENUM.unAuthorization, - message: '凭证错误', + message: i18nT('common:code_error.error_message.403'), data: null }, [ERROR_ENUM.insufficientQuota]: { code: 510, statusText: ERROR_ENUM.insufficientQuota, - message: '账号余额不足', + message: i18nT('common:code_error.error_message.510'), data: null }, [ERROR_ENUM.unAuthModel]: { code: 511, statusText: ERROR_ENUM.unAuthModel, - message: '无权操作该模型', + message: i18nT('common:code_error.error_message.511'), data: null }, - [ERROR_ENUM.unAuthFile]: { code: 513, statusText: ERROR_ENUM.unAuthFile, - message: '无权阅读该文件', + message: i18nT('common:code_error.error_message.513'), data: null }, [ERROR_ENUM.unAuthApiKey]: { code: 514, statusText: ERROR_ENUM.unAuthApiKey, - message: 'Api Key 不合法', + message: i18nT('common:code_error.error_message.514'), data: null }, ...appErr, diff --git a/packages/web/components/common/Textarea/PromptEditor/modules/ComfirmVar/index.tsx b/packages/web/components/common/Textarea/PromptEditor/modules/ComfirmVar/index.tsx index a6f62658b..22c669f27 100644 --- a/packages/web/components/common/Textarea/PromptEditor/modules/ComfirmVar/index.tsx +++ b/packages/web/components/common/Textarea/PromptEditor/modules/ComfirmVar/index.tsx @@ -1,5 +1,5 @@ import { Box, Button, Image } from '@chakra-ui/react'; - +import { useTranslation } from 'next-i18next'; export default function ComfirmVar({ newVariables, onCancel, @@ -9,6 +9,7 @@ export default function ComfirmVar({ onCancel: () => void; onConfirm: () => void; }) { + const { t } = useTranslation(); return ( <> {''} - 引用了未定义的变量,是否自动添加? + {t('common:undefined_var')} diff --git a/packages/web/hooks/usePagination.tsx b/packages/web/hooks/usePagination.tsx index 056105436..c2cb1828e 100644 --- a/packages/web/hooks/usePagination.tsx +++ b/packages/web/hooks/usePagination.tsx @@ -2,7 +2,7 @@ import { useRef, useState, useCallback, useMemo, useEffect } from 'react'; import { IconButton, Flex, Box, Input } from '@chakra-ui/react'; import { ArrowBackIcon, ArrowForwardIcon } from '@chakra-ui/icons'; import { useMutation } from '@tanstack/react-query'; - +import { useTranslation } from 'react-i18next'; import { throttle } from 'lodash'; import { useToast } from './useToast'; import { getErrText } from '@fastgpt/global/common/error/utils'; @@ -34,6 +34,7 @@ export function usePagination({ elementRef?: React.RefObject; }) { const { toast } = useToast(); + const { t } = useTranslation(); const [pageNum, setPageNum] = useState(1); const pageNumRef = useRef(pageNum); pageNumRef.current = pageNum; @@ -63,7 +64,7 @@ export function usePagination({ onChange && onChange(num); } catch (error: any) { toast({ - title: getErrText(error, '获取数据异常'), + title: getErrText(error, t('common:core.chat.error.data_error')), status: 'error' }); console.log(error); @@ -138,9 +139,9 @@ export function usePagination({ const ScrollData = useCallback( ({ children, ...props }: { children: React.ReactNode }) => { const loadText = useMemo(() => { - if (isLoading) return '请求中……'; - if (total <= data.length) return '已加载全部'; - return '点击加载更多'; + if (isLoading) return t('common:common.is_requesting'); + if (total <= data.length) return t('common:common.request_end'); + return t('common:common.request_more'); }, []); return ( @@ -151,9 +152,9 @@ export function usePagination({ fontSize={'xs'} color={'blackAlpha.500'} textAlign={'center'} - cursor={loadText === '点击加载更多' ? 'pointer' : 'default'} + cursor={loadText === t('common:common.request_more') ? 'pointer' : 'default'} onClick={() => { - if (loadText !== '点击加载更多') return; + if (loadText !== t('common:common.request_more')) return; mutate(pageNum + 1); }} > diff --git a/packages/web/hooks/useScrollPagination.tsx b/packages/web/hooks/useScrollPagination.tsx index c8055dfc5..6185b0064 100644 --- a/packages/web/hooks/useScrollPagination.tsx +++ b/packages/web/hooks/useScrollPagination.tsx @@ -85,7 +85,7 @@ export function useScrollPagination< } } catch (error: any) { toast({ - title: getErrText(error, '获取数据异常'), + title: getErrText(error, t('common:core.chat.error.data_error')), status: 'error' }); console.log(error); diff --git a/packages/web/i18n/en/app.json b/packages/web/i18n/en/app.json index 7e2b3bd20..4aaa44401 100644 --- a/packages/web/i18n/en/app.json +++ b/packages/web/i18n/en/app.json @@ -17,9 +17,17 @@ "confirm_delete_folder_tip": "Are you sure to delete this folder? All the following applications and corresponding chat records will be deleted, please confirm!", "copy_one_app": "Copy", "create_copy_success": "Create copy success", + "cron": { + "every_day": "Executed every day", + "every_month": "Executed monthly", + "every_week": "Executed every week", + "interval": "interval execution" + }, "current_settings": "Current settings", + "day": "day", "edit_app": "Edit app", "edit_info": "Edit info", + "execute_time": "execution time", "export_config_successful": "Config copied, please check for important data", "export_configs": "Export Configs", "feedback_count": "User Feedback", @@ -27,6 +35,15 @@ "go_to_run": "Run", "import_configs": "Import Configs", "import_configs_failed": "Failed to import configs, please ensure configs are valid!", + "interval": { + "12_hours": "every 12 hours", + "2_hours": "every 2 hours", + "3_hours": "every 3 hours", + "4_hours": "every 4 hours", + "6_hours": "every 6 hours", + "per_hour": "per hour" + }, + "intro": "It is a large model application orchestration system that provides out-of-the-box data processing, model calling and other capabilities. It can quickly build a knowledge base and perform workflow orchestration through Flow visualization to realize complex knowledge base scenarios!", "logs_empty": "No logs yet~", "logs_message_total": "Total Messages", "logs_title": "Title", @@ -40,6 +57,9 @@ "modules": { "Title is required": "Module name cannot be empty" }, + "month": { + "unit": "Number" + }, "move_app": "Move app", "paste_config": "Paste Config", "plugin_cost_per_times": "{{cost}}/per time", @@ -53,6 +73,7 @@ "template": { "simple_robot": "Simple Robot" }, + "time_zone": "Time zone", "tool_input_param_tip": "Configure related information before the plugin runs properly", "transition_to_workflow": "Transition to workflow", "transition_to_workflow_create_new_placeholder": "Create a new application instead of modifying the current one", @@ -74,6 +95,15 @@ "version": { "Revert success": "Revert success" }, + "week": { + "Friday": "Friday", + "Monday": "Monday", + "Saturday": "Saturday", + "Sunday": "Sunday", + "Thursday": "Thursday", + "Tuesday": "Tuesday", + "Wednesday": "Wednesday" + }, "workflow": { "Input guide": "Input guide", "template": { diff --git a/packages/web/i18n/en/chat.json b/packages/web/i18n/en/chat.json index 21deccc98..e7af2cdfe 100644 --- a/packages/web/i18n/en/chat.json +++ b/packages/web/i18n/en/chat.json @@ -1,15 +1,34 @@ { "Delete_all": "Delete all", - "chat_input_guide_lexicon_is_empty": "The lexicon has not been configured", - "config_input_guide": "Configure input boot", - "config_input_guide_lexicon": "Config", - "config_input_guide_lexicon_title": "Config lexicon", - "csv_input_lexicon_tip": "Only CSV can be imported in batches. Click to download the template", - "custom_input_guide_url": "Custom lexicon url", "delete_all_input_guide_confirm": "Confirm to delete all input guide lexicons", - "input_guide": "Input guide", - "input_guide_lexicon": "Lexicon", - "input_guide_tip": "You can configure some preset questions. When the user enters a question, the relevant question is retrieved from these preset questions for prompt.", - "insert_input_guide,_some_data_already_exists": "Duplicate data, automatically filtered, insert: {{len}} data", - "new_input_guide_lexicon": "New lexicon" + "chat_history": "chat record", + "chat_input_guide_lexicon_is_empty": "No vocabulary has been configured yet", + "citations": "{{num}} citations", + "click_contextual_preview": "Click to see contextual preview", + "config_input_guide": "Configure input boot", + "config_input_guide_lexicon": "Configure thesaurus", + "config_input_guide_lexicon_title": "Configure thesaurus", + "content_empty": "Content is empty", + "contextual": "context", + "contextual_preview": "Contextual preview", + "csv_input_lexicon_tip": "Only supports CSV batch import, click to download the template", + "custom_input_guide_url": "Custom thesaurus address", + "empty_directory": "There is nothing left to choose from in this directory~", + "in_progress": "in progress", + "input_guide": "Enter boot", + "input_guide_lexicon": "vocabulary", + "input_guide_tip": "Some preset questions can be configured. \nWhen the user enters a question, relevant questions will be obtained from these preset questions for prompts.", + "insert_input_guide,_some_data_already_exists": "There is duplicate data, which has been automatically filtered. A total of {{len}} pieces of data have been inserted.", + "is_chatting": "Chatting...please wait for the end", + "items": "strip", + "module_runtime_and": "module run time and", + "multiple_AI_conversations": "Multiple AI conversations", + "new_chat": "new conversation", + "new_input_guide_lexicon": "New vocabulary", + "plugins_output": "Plugin output", + "question_tip": "From left to right, the response order of each module", + "rearrangement": "Search results rearranged", + "stream_output": "stream output", + "view_citations": "View citations", + "web_site_sync": "Web site synchronization" } diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 7df02d575..e30761170 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -1,6 +1,24 @@ { "App": "App", "Export": "Export", + "FAQ": { + "ai_point_a": "Every time the AI ​​model is called, a certain amount of AI points will be consumed. \nFor specific calculation standards, please refer to the \"AI Points Calculation Standards\" above.\n\nToken calculation uses the same formula as GPT3.5, 1Token≈0.7 Chinese characters≈0.9 English words. Continuous characters may be considered as 1 Tokens.", + "ai_point_expire_a": "will expire. \nAfter the current package expires, the AI ​​points will be cleared and updated to the AI ​​points of the new package. \nThe AI ​​points for the annual package last for 1 year, not every month.", + "ai_point_expire_q": "Will AI points expire?", + "ai_point_q": "What are AI points?", + "auto_renew_a": "After the current package expires, the system will automatically renew according to the \"future package\" and the system will try to deduct the fee from the account balance. If you need to automatically renew, please reserve a quota in the account balance.", + "auto_renew_q": "Will the subscription package automatically renew?", + "change_package_a": "When the current package price is greater than the new package, you cannot switch immediately. You will be switched in the form of \"renewal\" after the current package expires.\n\nWhen the current package price is lower than the new package, the system will automatically calculate the remaining balance of the current package, and you can pay the price difference to switch packages.", + "change_package_q": "Can I switch subscription plans?", + "dataset_compute_a": "1 knowledge base storage is equal to 1 knowledge base index. \nA piece of knowledge base data can contain one or more knowledge base indexes. \nDuring enhanced training, 1 piece of data will generate 5 indexes.", + "dataset_compute_q": "How to calculate knowledge base storage?", + "dataset_index_a": "Won't. \nHowever, when the knowledge base index exceeds, knowledge base content cannot be inserted and updated.", + "dataset_index_q": "Will the knowledge base index be deleted if it exceeds the limit?", + "free_user_clean_a": "After free version users (free version without purchasing additional packages) have no usage records for 30 days, the system will automatically clear all knowledge base content under the account.", + "free_user_clean_q": "Will the data in the free version be cleared?", + "package_overlay_a": "OK. \nEach resource package purchased is independent and will be used stacked within its validity period. \nAI points will be deducted from the resource package that expires first.", + "package_overlay_q": "Can additional resource packs be stacked?" + }, "Folder": "Folder", "Login": "Login", "Move": "Move", @@ -11,8 +29,78 @@ "UnKnow": "Unknown", "Warning": "Warning", "add_new": "Add new", + "chose_condition": "Selection criteria", + "chosen": "selected", + "classification": "Classification", "click_to_resume": "Resume", "code_editor": "Code edit", + "code_error": { + "app_error": { + "not_exist": "App does not exist", + "un_auth_app": "No permission to operate this application" + }, + "chat_error": { + "un_auth": "No permission to operate this conversation record" + }, + "error_code": { + "400": "Request failed", + "401": "No access", + "403": "Nervous visit", + "404": "Request does not exist", + "405": "Request method error", + "406": "Request format error", + "410": "Resource deleted", + "422": "Validation error", + "500": "Server error occurred", + "502": "Gateway error", + "503": "The server is temporarily overloaded or under maintenance", + "504": "Gateway timeout" + }, + "error_message": { + "403": "Credential error", + "510": "Insufficient account balance", + "511": "No permission to operate this model", + "513": "No permission to read the file", + "514": "Api Key is illegal" + }, + "openapi_error": { + "api_key_not_exist": "API Key does not exist", + "exceed_limit": "Up to 10 sets of API keys", + "un_auth": "No permission to operate this API Key" + }, + "outlink_error": { + "invalid_link": "Sharing link is invalid", + "link_not_exist": "Sharing link does not exist", + "un_auth_user": "Identity verification failed" + }, + "plugin_error": { + "not_exist": "Plugin does not exist", + "un_auth": "No permission to operate this plug-in" + }, + "system_error": { + "community_version_num_limit": "If the number limit of the open source version is exceeded, please upgrade to the commercial version: https://fastgpt.in" + }, + "team_error": { + "ai_points_not_enough": "", + "app_amount_not_enough": "The number of applications has reached the upper limit~", + "dataset_amount_not_enough": "The number of knowledge bases has reached the upper limit~", + "dataset_size_not_enough": "The capacity of the knowledge base is insufficient, please expand it first~", + "over_size": "error.team.overSize", + "plugin_amount_not_enough": "The number of plug-ins has reached the upper limit~", + "re_rank_not_enough": "Not authorized to use search rearrangement~", + "un_auth": "No permission to operate this team", + "website_sync_not_enough": "No permission to use Web site synchronization~" + }, + "token_error_code": { + "403": "Invalid login status, please log in again" + }, + "user_error": { + "balance_not_enough": "Account balance is insufficient~", + "bin_visitor": "Your identity verification failed", + "bin_visitor_guest": "You are currently a visitor and do not have permission to operate", + "un_auth_user": "The user cannot be found" + } + }, "common": { "Action": "Action", "Add": "Add", @@ -70,7 +158,7 @@ "Name": "Name", "Next Step": "Next Step", "No more data": "No more data~", - "Not open": "Not open", + "Not open": "Unopened", "OK": "OK", "Open": "Open", "Operation": "Operation", @@ -118,6 +206,7 @@ "Waiting": "Waiting", "Warning": "Warning", "Website": "Website", + "all_result": "full results", "avatar": { "Select Avatar": "Click to select avatar", "Select Failed": "Select avatar failed" @@ -136,6 +225,7 @@ "Select avatar failed": "Avatar selection failed", "unKnow": "An unexpected error occurred~" }, + "failed": "fail", "folder": { "Drag Tip": "Drag me", "Move Success": "Move successful", @@ -143,11 +233,13 @@ "No Folder": "No subdirectories, place here", "Open folder": "Open folder", "Root Path": "Root directory", - "empty": "This directory has nothing selectable~" + "empty": "This directory has nothing selectable~", + "open_dataset": "Open knowledge base" }, "input": { "Repeat Value": "Duplicate value" }, + "is_requesting": "Requesting...", "jsonEditor": { "Parse error": "JSON may be incorrect, please check carefully" }, @@ -156,10 +248,16 @@ }, "month": "Month", "name_is_empty": "Name cannot be empty", + "no_intro": "No introduction yet", + "not_support": "not support", + "page_center": "Center the page", + "request_end": "All loaded", + "request_more": "Click to load more", "speech": { "error tip": "Speech to text failed", "not support": "Your browser does not support speech input" }, + "support": "support", "system": { "Commercial version function": "Commercial version feature", "Help Chatbot": "Chatbot assistant", @@ -171,6 +269,7 @@ } } }, + "confirm_choice": "Confirm selection", "core": { "Chat": "Chat", "Max Token": "Max token per data", @@ -184,7 +283,8 @@ "Support tool": "Function call", "model": { "Dataset Agent Model": "File processing model", - "Vector Model": "Index model" + "Vector Model": "Index model", + "doc_index_and_dialog": "Document index" } }, "app": { @@ -242,6 +342,7 @@ "Query extension background prompt": "Conversation background description", "Query extension background tip": "Describe the scope of the current conversation to help the AI complete and expand the current question. The content filled in is usually for the assistant" }, + "edit_content": "Application information editing", "error": { "App name can not be empty": "App name cannot be empty", "Get app failed": "Failed to get app" @@ -250,9 +351,13 @@ "Custom feedback": "Custom feedback", "close custom feedback": "Close feedback" }, + "have_publish": "Published", + "loading": "loading", "logs": { "Source And Time": "Source & Time" }, + "no_app": "There is no application yet, go and create one!", + "not_published": "Unpublished", "outLink": { "Can Drag": "Icon draggable", "Default open": "Open by default", @@ -295,6 +400,11 @@ "variableTip": "You can ask the user to fill in some content as specific variables for this round of conversation before the conversation starts. This module is located after the opening guide.\nVariables can be injected into other module string type inputs through the form of {{variable key}}, such as: prompt words, limiting words, etc.", "welcomeTextTip": "Send an initial content before each conversation starts. Supports standard Markdown syntax, additional tags available:\n[Shortcut key]: User can click to send the question directly" }, + "tool_label": { + "doc": "Use documentation", + "github": "GitHub address", + "price": "Billing instructions" + }, "tts": { "Close": "Do not use", "Speech model": "Voice model", @@ -361,7 +471,8 @@ "Chat error": "Chat error", "Messages empty": "API content is empty, text may be too long~", "Select dataset empty": "You did not select a dataset", - "User input empty": "User question input is empty" + "User input empty": "User question input is empty", + "data_error": "Exception in getting data" }, "feedback": { "Close User Like": "User expressed approval\nClick to close this mark", @@ -501,6 +612,7 @@ "Search data placeholder": "Search related data", "Too Long": "Total length too long", "Total Amount": "{{total}} sets", + "group": "Group", "unit": "items" }, "embedding model tip": "The index model can convert natural language into vectors for semantic retrieval.\nNote, different index models cannot be used together, once you select an index model, it cannot be changed.", @@ -649,7 +761,8 @@ "Confirm Delete Node": "Confirm delete node?", "Data Type": "Data type", "Dataset quote": { - "label": "Knowledge base quote" + "label": "Knowledge base quote", + "select": "Select knowledge base reference" }, "Default Value": "Default value", "Default value": "Default value", @@ -772,7 +885,9 @@ "variable option is value is required": "Option content cannot be empty", "variable options": "Options" }, - "variable add option": "Add option" + "variable add option": "Add option", + "variable_update": "variable update", + "variable_update_info": "You can update the output value of the specified node or update global variables" }, "plugin": { "Custom headers": "Custom headers", @@ -781,6 +896,7 @@ "Http plugin intro placeholder": "For display only, no actual effect", "cost": "Plugin cost: " }, + "view_chat_detail": "View conversation details", "workflow": { "Can not delete node": "This node cannot be deleted", "Change input type tip": "Changing the input type will clear the filled values, please confirm!", @@ -840,6 +956,7 @@ "variable": "Variable" } }, + "create": "to create", "dataset": { "Confirm move the folder": "Confirm moving to the folder", "Confirm to delete the data": "Confirm to delete the data?", @@ -892,6 +1009,7 @@ "noResult": "No results found" } }, + "default_reply": "Default reply", "error": { "Create failed": "Create failed", "fileNotFound": "File not found~", @@ -901,9 +1019,30 @@ "overSize": "Team members exceed the limit" } }, + "extraction_results": "Extract results", "field_name": "Name", + "get_QR_failed": "Failed to obtain QR code", + "get_app_failed": "Failed to get app", + "get_laf_failed": "Failed to get Laf function list", + "has_verification": "Verified, click to cancel binding", + "info": { + "buy_extra": "Purchase additional packages", + "csv_download": "Click to download batch test template", + "csv_message": "Read the first column of the CSV file for batch testing, supporting up to 100 sets of data at a time.", + "felid_message": "The field key must be pure English letters or numbers, and cannot start with a number.", + "free_plan": "When free version users have no usage records for 30 days, the system will automatically clean up the account knowledge base.", + "include": "Includes standard package and additional resource package", + "node_info": "Adjusting this module will have an impact on the timing of tool calls.\n\nYou can guide the model to make tool calls by accurately describing the function of the module.", + "old_version_attention": "If it is detected that your advanced arrangement is an old version, the system will automatically format it into a new version of the workflow for you.\n\n\nDue to large version differences, some workflows may not be arranged normally. Please reconnect the workflows manually. \nIf the error persists, try deleting the corresponding node and adding it again.\n\n\nYou can directly click Debug to perform workflow testing, and click Publish after debugging is completed. \nThe new workflow will not actually save and take effect until you click Publish.\n\n\nAutosave will not take effect until you publish the new workflow.", + "open_api_notice": "You can fill in the relevant secret key of OpenAI/OneAPI. \nIf you fill in this content, the online platform will use [AI Dialogue], [Problem Classification] and [Content Extraction] to retrieve the Key you filled in, and no charges will be made. \nPlease pay attention to whether your Key has permission to access the corresponding model. \nThe GPT model can choose FastAI.", + "open_api_placeholder": "Request address, default is openai official. \nThe forwarding address can be filled in, but \"v1\" is not automatically completed.", + "resource": "Resource usage" + }, "invalid_variable": "Invalid variable", "is_open": "Opened", + "item_description": "Field description", + "item_name": "Field name", + "key_repetition": "key duplicate", "navbar": { "Account": "Account", "Chat": "Chat", @@ -913,6 +1052,23 @@ }, "new_create": "Create New", "no_data": "No data", + "no_laf_env": "The system is not configured with Laf environment", + "not_yet_introduced": "No introduction yet", + "pay": { + "amount": "Amount", + "balance": "Account balance", + "balance_notice": "Insufficient account balance", + "confirm_pay": "confirm payment", + "get_pay_QR": "Get the recharge QR code", + "need_pay": "Need to pay", + "new_package_price": "New package price", + "notice": "Do not close the page", + "old_package_price": "Old package price", + "other": "For other amounts, please round up the whole number", + "to_recharge": "Insufficient balance, please recharge", + "wechat": "Please scan the QR code on WeChat to pay:", + "yuan": "Yuan" + }, "permission": { "Collaborator": "collaborator", "Default permission": "Default permission", @@ -950,9 +1106,13 @@ "Plugin List": "Plugin list", "Search plugin": "Search plugin", "Set Name": "Name the plugin", + "contribute": "Contribute plugins", "go to laf": "Go to write", "path": "Path" }, + "reply_now": "Reply immediately", + "required": "must", + "resume_failed": "Recovery failed", "select_reference_variable": "Select Reference Variable", "share_link": "Share Link", "support": { @@ -1027,8 +1187,14 @@ "Terms": "Terms of service", "Username": "Username", "Wechat": "Login with Wechat", + "can_not_login": "Unable to log in, click to contact", + "error": "Login exception", + "security_failed": "Security check failed", "wx_qr_login": "Wechat QR code login" }, + "logout": { + "confirm": "Confirm to log out?" + }, "team": { "Dataset usage": "Knowledge base capacity", "Team Tags Async Success": "Synchronization complete", @@ -1046,6 +1212,7 @@ "Plan reset time": "Plan reset time", "Standard Plan Detail": "Plan details", "To read plan": "View plan", + "amount_0": "The purchase quantity cannot be 0", "bill": { "Number": "Order number", "Status": "Status", @@ -1062,6 +1229,7 @@ "success": "Payment successful" } }, + "buy_resource": "Purchase resource pack", "moduleName": { "index": "Index generation", "qa": "QA split" @@ -1093,6 +1261,7 @@ "Update extra ai points": "Extra AI points", "Update extra dataset size": "Extra storage", "Upgrade plan": "Upgrade plan", + "ai_model": "AI language model", "function": { "History store": "{{amount}} days of conversation history retention", "Max app": "{{amount}} apps", @@ -1107,6 +1276,7 @@ "Year": "Yearly", "Year sale": "Two months free" }, + "point": "integral", "standardSubLevel": { "enterprise": "Enterprise edition", "experience": "Experience edition", @@ -1114,6 +1284,7 @@ "free desc": "Basic functions can be used for free every month, and the knowledge base will be cleared if there is no usage record for 30 days", "team": "Team edition" }, + "token_compute": "Click to view the online Tokens calculator", "type": { "balance": "Balance recharge", "extraDatasetSize": "Knowledge base expansion", @@ -1152,6 +1323,12 @@ "Quote Prompt Tip": "You can use {{quote}} to insert the quote content template, and use {{question}} to insert the question. Here are the default values:\n{{default}}" }, "textarea_variable_picker_tip": "Input / to select variables", + "tool_field": "Tool field parameter configuration", + "undefined_var": "An undefined variable is referenced. Is it automatically added?", + "unit": { + "character": "character", + "minute": "minute" + }, "unusable_variable": "no usable variable", "user": { "Account": "Account", @@ -1192,6 +1369,13 @@ "apikey": { "key": "API key" }, + "confirm_password": "Confirm Password", + "new_password": "New Password", + "no_invite_records": "No invitation record yet", + "no_notice": "No notification yet", + "no_usage_records": "No usage record yet", + "old_password": "Old Password", + "password_message": "Password must be at least 4 characters and at most 60 characters", "team": { "Balance": "Team Balance", "Check Team": "Switch", @@ -1239,6 +1423,8 @@ "Owner": "Owner", "Visitor": "Visitor" } - } - } + }, + "type": "type" + }, + "verification": "verify" } diff --git a/packages/web/i18n/en/file.json b/packages/web/i18n/en/file.json index 8740f266b..6a2ca6907 100644 --- a/packages/web/i18n/en/file.json +++ b/packages/web/i18n/en/file.json @@ -1,9 +1,9 @@ { "click_to_view_raw_source": "View source", - "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", "file_name": "File Name", "file_size": "File Size", + "reached_max_file_count": "Maximum number of files reached", + "release_the_mouse_to_upload_the_file": "Release the mouse to upload the file", "select_and_drag_file_tip": "Click or drag files here to upload", "select_file_amount_limit": "You can select up to {{max}} files", "some_file_count_exceeds_limit": "Exceeds {{maxCount}} files, automatically truncated", @@ -11,5 +11,6 @@ "support_file_type": "Supports {{fileType}} type files", "support_max_count": "Supports up to {{maxCount}} files.", "support_max_size": "Maximum size per file: {{maxSize}}.", + "upload_error_description": "Only supports uploading multiple files or one folder at a time", "upload_failed": "Upload failed" -} \ No newline at end of file +} diff --git a/packages/web/i18n/en/user.json b/packages/web/i18n/en/user.json index 76e989b4e..408bc0814 100644 --- a/packages/web/i18n/en/user.json +++ b/packages/web/i18n/en/user.json @@ -1,15 +1,76 @@ { "bind_inform_account_error": "Abnormal binding notification account", "bind_inform_account_success": "Binding notification account successful", + "delete": { + "admin_failed": "Failed to delete administrator", + "admin_success": "Administrator deleted successfully" + }, + "has_chosen": "chosen", + "login": { + "error": "Login exception", + "failed": "Login failed", + "login_account": "Login to {{account}} account", + "login_error": "wrong user name or password", + "password_condition": "Password maximum 60 characters", + "success": "login successful", + "to_register": "If you don’t have an account, please register." + }, + "name": "name", + "notification": { + "Bind Notification Pipe Hint": "Bind the email address or mobile phone number for receiving notifications to ensure that you receive important system notifications in a timely manner." + }, + "operations": "operate", + "password": { + "change_error": "Exception when changing password", + "code_required": "verification code must be filled", + "code_send_error": "Verification code sending exception", + "code_sended": "Verification code sent", + "confirm": "Confirm Password", + "email_phone": "Email/Mobile phone number", + "email_phone_error": "Email/mobile phone number format error", + "email_phone_void": "Email/mobile phone number cannot be empty", + "get_code": "get verification code", + "get_code_again": "Reacquire after s", + "new_password": "New password (4~20 digits)", + "not_match": "Two passwords are inconsistent", + "password_condition": "Password must be at least 4 characters and at most 20 characters", + "password_required": "password can not be blank", + "retrieve": "Retrieve password", + "retrieved": "Password has been retrieved", + "retrieved_account": "Retrieve {{account}} account", + "to_login": "Go to login", + "verification_code": "Verification code" + }, "permission": { "Manage": "administrator", "Manage tip": "Team administrator, with full permissions", "Read": "Read only", "Read desc": "Members can only read related resources and cannot create new resources.", "Write": "Write", - "Write tip": "In addition to readable resources, you can also create new resources" + "Write tip": "In addition to readable resources, you can also create new resources", + "only_collaborators": "Collaborator access only", + "team_read": "Team accessible", + "team_write": "Team editable" + }, + "permissions": "Permissions", + "register": { + "confirm": "Confirm registration", + "error": "Registration exception", + "failed": "registration failed", + "register_account": "Register {{account}} account", + "success": "registration success", + "to_login": "Already have an account? Log in" + }, + "search_user": "Search username", + "synchronization": { + "button": "Sync now", + "placeholder": "Please enter sync label", + "title": "Fill in the tag synchronization link and click the sync button to synchronize" }, "team": { - "Add manager": "Add manager" + "Add manager": "Add manager", + "add_collaborator": "Add collaborators", + "manage_collaborators": "Manage collaborators", + "no_collaborators": "No collaborators yet" } } diff --git a/packages/web/i18n/en/workflow.json b/packages/web/i18n/en/workflow.json index c7757b0ef..529e6548f 100644 --- a/packages/web/i18n/en/workflow.json +++ b/packages/web/i18n/en/workflow.json @@ -6,7 +6,9 @@ "Reset template confirm": "Are you sure to restore the code template? All input and output to template values will be reset, please be careful to save the current code." }, "confirm_delete_field_tip": "Confirm to delete the field?", + "create_link_error": "Create link exception", "custom_input": "Custom input", + "delete_api": "Are you sure you want to delete this API key? \nAfter deletion, the key will become invalid immediately and the corresponding conversation log will not be deleted. Please confirm!", "edit_input": "Edit input", "field_description": "Field description", "field_description_placeholder": "Describes the functionality of this input field, which affects the quality of model generation if the parameter is called for a tool", @@ -28,5 +30,6 @@ "Error": "Error" }, "tool_input": "Tool", + "update_link_error": "Update link exception", "variable_picker_tips": "enter node name or variable name to search" } diff --git a/packages/web/i18n/zh/app.json b/packages/web/i18n/zh/app.json index 02cbd6a5c..12b415711 100644 --- a/packages/web/i18n/zh/app.json +++ b/packages/web/i18n/zh/app.json @@ -8,6 +8,7 @@ "has new version": "有新版本" } }, + "intro": "是一个大模型应用编排系统,提供开箱即用的数据处理、模型调用等能力,可以快速的构建知识库并通过 Flow 可视化进行工作流编排,实现复杂的知识库场景!", "app_detail": "应用详情", "chat_debug": "调试预览", "chat_logs": "对话日志", @@ -79,5 +80,34 @@ "template": { "communication": "通信" } - } + }, + "interval": { + "per_hour": "每小时", + "2_hours": "每2小时", + "3_hours": "每3小时", + "4_hours": "每4小时", + "6_hours": "每6小时", + "12_hours": "每12小时" + }, + "week": { + "Monday": "星期一", + "Tuesday": "星期二", + "Wednesday": "星期三", + "Thursday": "星期四", + "Friday": "星期五", + "Saturday": "星期六", + "Sunday": "星期日" + }, + "month": { + "unit": "号" + }, + "cron": { + "every_day": "每天执行", + "every_month": "每月执行", + "every_week": "每周执行", + "interval": "间隔执行" + }, + "day": "日", + "execute_time": "执行时间", + "time_zone": "时区" } diff --git a/packages/web/i18n/zh/chat.json b/packages/web/i18n/zh/chat.json index ad6a6f850..1c84e8f58 100644 --- a/packages/web/i18n/zh/chat.json +++ b/packages/web/i18n/zh/chat.json @@ -11,5 +11,24 @@ "input_guide_lexicon": "词库", "input_guide_tip": "可以配置一些预设的问题。在用户输入问题时,会从这些预设问题中获取相关问题进行提示。", "insert_input_guide,_some_data_already_exists": "有重复数据,已自动过滤,共插入 {{len}} 条数据", - "new_input_guide_lexicon": "新词库" + "new_input_guide_lexicon": "新词库", + "is_chatting": "正在聊天中...请等待结束", + "content_empty": "内容为空", + "contextual": "{{num}}条上下文", + "contextual_preview": "上下文预览 {{num}} 条", + "items": "条", + "view_citations": "查看引用", + "citations": "{{num}}条引用", + "click_contextual_preview": "点击查看上下文预览", + "multiple_AI_conversations": "多组 AI 对话", + "module_runtime_and": "模块运行时间和", + "empty_directory": "这个目录已经没东西可选了~", + "chat_history": "聊天记录", + "stream_output": "流输出", + "plugins_output": "插件输出", + "in_progress": "进行中", + "question_tip": "从上到下,为各个模块的响应顺序", + "rearrangement": "检索结果重排", + "web_site_sync": "Web站点同步", + "new_chat": "新对话" } diff --git a/packages/web/i18n/zh/common.json b/packages/web/i18n/zh/common.json index 550c1039c..9d1af2e47 100644 --- a/packages/web/i18n/zh/common.json +++ b/packages/web/i18n/zh/common.json @@ -1,19 +1,160 @@ { "App": "应用", + "click_to_resume": "点击恢复", + "code_editor": "代码编辑", "Export": "导出", "Folder": "文件夹", "Login": "登录", + "chosen": "已选", + "chose_condition": "选择条件", + "confirm_choice": "确认选择", "Move": "移动", "Name": "名称", + "create": "去创建", + "required": "必须", + "extraction_results": "提取结果", + "item_description": "字段描述", + "item_name": "字段名", + "tool_field": "工具字段参数配置", + "classification": "分类", + "get_laf_failed": "获取Laf函数列表失败", + "no_laf_env": "系统未配置Laf环境", + "get_app_failed": "获取应用失败", "Rename": "重命名", "Resume": "恢复", + "resume_failed": "恢复失败", "Running": "运行中", "UnKnow": "未知", "Warning": "提示", + "default_reply": "默认回复", + "reply_now": "立即回复", "add_new": "新增", - "click_to_resume": "点击恢复", - "code_editor": "代码编辑", + "verification": "验证", + "key_repetition": "key 重复", + "has_verification": "已验证,点击取消绑定", + "undefined_var": "引用了未定义的变量,是否自动添加?", + "not_yet_introduced": "暂无介绍", + "get_QR_failed": "获取二维码失败", + "unit": { + "character": "字符", + "minute": "分钟" + }, + "FAQ": { + "auto_renew_q": "订阅套餐会自动续费么?", + "auto_renew_a": "当前套餐过期后,系统会自动根据“未来套餐”进行续费,系统会尝试从账户余额进行扣费,如果您需要自动续费,请在账户余额中预留额度。", + "change_package_q": "能否切换订阅套餐?", + "change_package_a": "当前套餐价格大于新套餐时,无法立即切换,将会在当前套餐过期后以“续费”形式进行切换。\n当前套餐价格小于新套餐时,系统会自动计算当前套餐剩余余额,您可支付差价进行套餐切换。", + "ai_point_q": "什么是AI积分?", + "ai_point_a": "每次调用AI模型时,都会消耗一定的AI积分。具体的计算标准可参考上方的“AI 积分计算标准”。\nToken计算采用GPT3.5相同公式,1Token≈0.7中文字符≈0.9英文单词,连续出现的字符可能被认为是1个Tokens。", + "ai_point_expire_q": "AI积分会过期么?", + "ai_point_expire_a": "会过期。当前套餐过期后,AI积分将会清空,并更新为新套餐的AI积分。年度套餐的AI积分时长为1年,而不是每个月。", + "dataset_compute_q": "知识库存储怎么计算?", + "dataset_compute_a": "1条知识库存储等于1条知识库索引。一条知识库数据可以包含1条或多条知识库索引。增强训练中,1条数据会生成5条索引。", + "dataset_index_q": "知识库索引超出会删除么?", + "dataset_index_a": "不会。但知识库索引超出时,无法插入和更新知识库内容。", + "package_overlay_q": "额外资源包可以叠加么?", + "package_overlay_a": "可以的。每次购买的资源包都是独立的,在其有效期内将会叠加使用。AI积分会优先扣除最先过期的资源包。", + "free_user_clean_q": "免费版数据会清除么?", + "free_user_clean_a": "免费版用户(免费版且未购买额外套餐)30天无使用记录后,系统会自动清除账号下所有知识库内容。" + }, + "code_error": { + "app_error": { + "not_exist": "应用不存在", + "un_auth_app": "无权操作该应用" + }, + "chat_error": { + "un_auth": "没有权限操作此对话记录" + }, + "error_code": { + "400": "请求失败", + "401": "无访问权限", + "403": "紧张访问", + "404": "请求不存在", + "405": "请求方法错误", + "406": "请求格式错误", + "410": "资源已删除", + "422": "验证错误", + "500": "服务器发生错误", + "502": "网关错误", + "503": "服务器暂时过载或正在维护", + "504": "网关超时" + }, + "error_message": { + "403": "凭证错误", + "510": "账户余额不足", + "511": "没有权限操作此模型", + "513": "没有权限读取该文件", + "514": "Api Key 不合法" + }, + "token_error_code": { + "403": "登录状态无效,请重新登录" + }, + "openapi_error": { + "api_key_not_exist": "Api Key 不存在", + "un_auth": "无权操作该 Api Key", + "exceed_limit": "最多 10 组 API 密钥" + }, + "outlink_error": { + "link_not_exist": "分享链接不存在", + "invalid_link": "分享链接无效", + "un_auth_user": "身份校验失败" + }, + "plugin_error": { + "not_exist": "插件不存在", + "un_auth": "无权操作该插件" + }, + "system_error": { + "community_version_num_limit": "超出开源版数量限制,请升级商业版: https://fastgpt.in" + }, + "team_error": { + "over_size": "error.team.overSize", + "un_auth": "无权操作该团队", + "ai_points_not_enough": "", + "dataset_size_not_enough": "知识库容量不足,请先扩容~", + "dataset_amount_not_enough": "知识库数量已达上限~", + "app_amount_not_enough": "应用数量已达上限~", + "plugin_amount_not_enough": "插件数量已达上限~", + "website_sync_not_enough": "无权使用Web站点同步~", + "re_rank_not_enough": "无权使用检索重排~" + }, + "user_error": { + "un_auth_user": "找不到该用户", + "bin_visitor": "您的身份校验未通过", + "bin_visitor_guest": "您当前身份为游客,无权操作", + "balance_not_enough": "账号余额不足~" + } + }, + "pay": { + "wechat": "请微信扫码支付: {{price}}元,请勿关闭页面", + "yuan": "{{amount}}元", + "notice": "请勿关闭页面", + "get_pay_QR": "获取充值二维码", + "other": "其他金额,请取整数", + "amount": "金额", + "new_package_price": "新套餐价格", + "old_package_price": "旧套餐价格", + "need_pay": "需支付", + "balance": "账号余额", + "confirm_pay": "确认支付", + "balance_notice": "账号余额不足", + "to_recharge": "余额不足,去充值" + }, + "info": { + "free_plan": "免费版用户30天无任何使用记录时,系统会自动清理账号知识库。", + "resource": "资源用量", + "include": "包含标准套餐与额外资源包", + "buy_extra": "购买额外套餐", + "open_api_notice": "可以填写 OpenAI/OneAPI的相关秘钥。如果你填写了该内容,在线上平台使用【AI对话】、【问题分类】和【内容提取】将会走你填写的Key,不会计费。请注意你的Key 是否有访问对应模型的权限。GPT模型可以选择 FastAI。", + "open_api_placeholder": "请求地址,默认为 openai 官方。可填中转地址,未自动补全 \"v1\"", + "old_version_attention": "检测到您的高级编排为旧版,系统将为您自动格式化成新版工作流。\n\n由于版本差异较大,会导致一些工作流无法正常排布,请重新手动连接工作流。如仍异常,可尝试删除对应节点后重新添加。\n\n你可以直接点击调试进行工作流测试,调试完毕后点击发布。直到你点击发布,新工作流才会真正保存生效。\n\n在你发布新工作流前,自动保存不会生效。", + "node_info": "调整该模块会对工具调用时机有影响。\n你可以通过精确的描述该模块功能,引导模型进行工具调用。", + "felid_message": "字段key必须是纯英文字母或数字,并且不能以数字开头。", + "csv_message": "读取 CSV 文件第一列进行批量测试,单次最多支持 100 组数据。", + "csv_download": "点击下载批量测试模板" + }, "common": { + "support": "支持", + "not_support": "不支持", "Action": "操作", "Add": "添加", "Add New": "新增", @@ -58,12 +199,14 @@ "Input folder description": "文件夹描述", "Input name": "取个名字", "Intro": "介绍", + "no_intro": "暂无介绍", "Last Step": "上一步", "Last use time": "最后使用时间", "Load Failed": "加载失败", "Loading": "加载中...", "More": "更多", "Move": "移动", + "page_center": "页面居中", "MultipleRowSelect": { "No data": "没有可选值" }, @@ -76,6 +219,7 @@ "Operation": "操作", "Other": "其他", "Output": "输出", + "all_result": "完整结果", "Params": "参数", "Password inconsistency": "两次密码不一致", "Permission": "权限", @@ -85,13 +229,16 @@ "Remove": "移除", "Rename": "重命名", "Request Error": "请求异常", + "is_requesting": "请求中……", + "request_end": "已加载全部", + "request_more": "点击加载更多", "Require Input": "必填", "Restart": "重新开始", "Role": "权限", "Root folder": "根目录", "Run": "运行", "Save": "保存", - "Save Failed": "保存失败", + "Save Failed": "保存异常", "Save Success": "保存成功", "Search": "搜索", "Select File Failed": "选择文件异常", @@ -102,6 +249,7 @@ "Status": "状态", "Submit failed": "提交失败", "Success": "成功", + "failed": "失败", "Sync success": "同步成功", "Team": "团队", "Team Tags Set": "标签", @@ -142,6 +290,7 @@ "Move to": "移动到", "No Folder": "没有子目录了,就放这里吧", "Open folder": "打开文件夹", + "open_dataset": "打开知识库", "Root Path": "根目录", "empty": "这个目录已经没东西可选了~" }, @@ -173,6 +322,7 @@ }, "core": { "Chat": "对话", + "view_chat_detail": "查看对话详情", "Max Token": "单条数据上限", "ai": { "AI settings": "AI 配置", @@ -184,11 +334,15 @@ "Support tool": "函数调用", "model": { "Dataset Agent Model": "文件处理模型", - "Vector Model": "索引模型" + "Vector Model": "索引模型", + "doc_index_and_dialog": "文档索引 & 对话索引" } }, "app": { "Ai response": "返回 AI 内容", + "loading": "加载中", + "no_app": "还没有应用,快去创建一个吧!", + "edit_content": "应用信息编辑", "Api request": "API 访问", "Api request desc": "通过 API 接入到已有系统中,或企微、飞书等", "App intro": "应用介绍", @@ -204,6 +358,8 @@ "Name and avatar": "头像 & 名称", "Onclick to save": "点击保存", "Publish": "发布", + "have_publish": "已发布", + "not_published": "未发布", "Publish Confirm": "确认发布应用?会立即更新所有发布渠道的应用状态。", "Publish app tip": "发布应用后,所有发布渠道将会立即使用该版本", "Question Guide": "猜你想问", @@ -233,6 +389,11 @@ "System": "系统", "Team": "团队" }, + "tool_label": { + "github": "GitHub地址", + "doc": "使用文档", + "price": "计费说明" + }, "Welcome Text": "对话开场白", "Whisper": "语音输入", "Whisper config": "语音输入配置", @@ -359,6 +520,7 @@ "You need to a chat app": "你没有可用的应用", "error": { "Chat error": "对话出现异常", + "data_error": "获取数据异常", "Messages empty": "接口内容为空,可能文本超长了~", "Select dataset empty": "你没有选择知识库", "User input empty": "传入的用户问题为空" @@ -484,8 +646,7 @@ "success": "开始同步" } }, - "training": { - } + "training": {} }, "data": { "Auxiliary Data": "辅助数据", @@ -501,20 +662,21 @@ "Search data placeholder": "搜索相关数据", "Too Long": "总长度超长了", "Total Amount": "{{total}} 组", - "unit": "条" + "unit": "条", + "group": "组" }, "embedding model tip": "索引模型可以将自然语言转成向量,用于进行语义检索。\n注意,不同索引模型无法一起使用,选择完索引模型后将无法修改。", "error": { "Data not found": "数据不存在或已被删除", "Start Sync Failed": "开始同步失败", "Template does not exist": "模板不存在", - "invalidVectorModelOrQAModel": "VectorModel 或 QA 模型错误", "unAuthDataset": "无权操作该知识库", "unAuthDatasetCollection": "无权操作该数据集", "unAuthDatasetData": "无权操作该数据", "unAuthDatasetFile": "无权操作该文件", "unCreateCollection": "无权操作该数据", - "unLinkCollection": "不是网络链接集合" + "unLinkCollection": "不是网络链接集合", + "invalidVectorModelOrQAModel": "VectorModel 或 QA 模型错误" }, "externalFile": "外部文件库", "file": "文件", @@ -649,6 +811,7 @@ "Confirm Delete Node": "确认删除该节点?", "Data Type": "数据类型", "Dataset quote": { + "select": "选择知识库引用", "label": "知识库引用" }, "Default Value": "默认值", @@ -673,6 +836,8 @@ "Setting quote prompt": "配置引用提示词", "Variable": "全局变量", "Variable Setting": "变量设置", + "variable_update": "变量更新", + "variable_update_info": "可以更新指定节点的输出值或更新全局变量", "edit": { "Field Name Cannot Be Empty": "字段名不能为空" }, @@ -934,6 +1099,7 @@ "plugin": { "App": "选择应用", "Currentapp": "当前应用", + "contribute": "贡献插件", "Description": "描述", "Edit Http Plugin": "编辑 HTTP 插件", "Enter PAT": "请输入访问凭证(PAT)", @@ -995,8 +1161,6 @@ } }, "user": { - "Email Or Phone": "邮箱/手机号", - "Verify Code": "验证码", "Avatar": "头像", "Go laf env": "点击前往 {{env}} 获取 PAT 凭证。", "Laf account course": "查看绑定 laf 账号教程。", @@ -1010,6 +1174,9 @@ "inform": { "System message": "系统消息" }, + "logout": { + "confirm": "确认退出登录?" + }, "login": { "And": "和", "Email": "邮箱", @@ -1029,7 +1196,10 @@ "Terms": "服务协议", "Username": "用户名", "Wechat": "微信登录", - "wx_qr_login": "微信扫码登录" + "wx_qr_login": "微信扫码登录", + "error": "登录异常", + "can_not_login": "无法登录,点击联系", + "security_failed": "安全校验失败" }, "team": { "Dataset usage": "知识库容量", @@ -1042,6 +1212,8 @@ "Amount": "金额", "Bills": "账单", "Buy": "购买", + "buy_resource": "购买资源包", + "amount_0": "购买数量不能为0", "Confirm pay": "支付确认", "Not sufficient": "您的 AI 积分不足,请先升级套餐或购买额外 AI 积分后继续使用。", "Plan expired time": "套餐到期时间", @@ -1070,7 +1242,9 @@ }, "noBill": "无账单记录~", "subscription": { + "point": "积分", "AI points": "AI 积分", + "ai_model": "AI语言模型", "AI points click to read tip": "每次调用 AI 模型时,都会消耗一定的 AI 积分(类似于 token)。点击可查看详细计算规则。", "AI points usage": "AI 积分使用量", "AI points usage tip": "每次调用 AI 模型时,都会消耗一定的 AI 积分。具体的计算标准可参考上方的“计费标准”", @@ -1082,6 +1256,7 @@ "Extra plan": "额外资源包", "Extra plan tip": "标准套餐不够时,您可以购买额外资源包继续使用", "FAQ": "常见问题", + "token_compute": "点击查看在线 Tokens 计算器", "Month amount": "月数", "Next plan": "未来套餐", "Nonsupport": "无法切换", @@ -1095,6 +1270,7 @@ "Update extra ai points": "额外 AI 积分", "Update extra dataset size": "额外存储量", "Upgrade plan": "升级套餐", + "function": { "History store": "{{amount}} 天对话记录保留", "Max app": "{{amount}} 个应用&插件", @@ -1165,16 +1341,22 @@ "Copy invite url": "复制邀请链接", "Edit name": "点击修改昵称", "Invite Url": "邀请链接", + "no_invite_records": "暂无邀请记录", "Invite url tip": "通过该链接注册的好友将永久与你绑定,其充值时你会获得一定余额奖励。\n此外,好友使用手机号注册时,你将立即获得 5 元奖励。\n奖励会发送到您的默认团队中。", "Laf Account Setting": "laf 账号配置", "Language": "语言", "Member Name": "昵称", "Notice": "通知", "Notification Receive": "通知接收", - "Notification Receive Bind": "请绑定通知接收途径", + "Notification Receive Bind": "请先绑定通知接收途径", + "no_notice": "暂无通知", "Old password is error": "旧密码错误", "OpenAI Account Setting": "OpenAI 账号配置", "Password": "密码", + "new_password": "新密码", + "old_password": "旧密码", + "confirm_password": "确认密码", + "password_message": "密码最少 4 位最多 60 位", "Pay": "充值", "Personal Information": "个人信息", "Promotion": "促销", @@ -1186,11 +1368,13 @@ "Sign Out": "登出", "Team": "团队", "Time": "时间", + "type": "类型", "Timezone": "时区", "Update Password": "修改密码", "Update password failed": "修改密码异常", "Update password successful": "修改密码成功", "Usage Record": "使用记录", + "no_usage_records": "暂无使用记录", "apikey": { "key": "API 秘钥" }, diff --git a/packages/web/i18n/zh/file.json b/packages/web/i18n/zh/file.json index f30615db5..09923f9e1 100644 --- a/packages/web/i18n/zh/file.json +++ b/packages/web/i18n/zh/file.json @@ -11,5 +11,6 @@ "support_file_type": "支持 {{fileType}} 类型文件", "support_max_count": "最多支持 {{maxCount}} 个文件", "support_max_size": "单个文件最大 {{maxSize}}", - "upload_failed": "上传异常" -} \ No newline at end of file + "upload_failed": "上传异常", + "reached_max_file_count": "已达到最大文件数量" +} diff --git a/packages/web/i18n/zh/user.json b/packages/web/i18n/zh/user.json index b9ffa4e11..662094c31 100644 --- a/packages/web/i18n/zh/user.json +++ b/packages/web/i18n/zh/user.json @@ -10,9 +10,67 @@ "Read": "仅读", "Read desc": "成员仅可阅读相关资源,无法新建资源", "Write": "可写", - "Write tip": "除了可读资源外,还可以新建新的资源" + "Write tip": "除了可读资源外,还可以新建新的资源", + "only_collaborators": "仅协作者访问", + "team_read": "团队可访问", + "team_write": "团队可编辑" }, "team": { - "Add manager": "添加管理员" + "Add manager": "添加管理员", + "add_collaborator": "添加协作者", + "manage_collaborators": "管理协作者", + "no_collaborators": "暂无协作者" + }, + "search_user": "搜索用户名", + "has_chosen": "已选择", + "name": "名称", + "permissions": "权限", + "operations": "操作", + "delete": { + "admin_success": "删除管理员成功", + "admin_failed": "删除管理员失败" + }, + "synchronization": { + "title": "填写标签同步链接,点击同步按钮即可同步", + "placeholder": "请输入同步标签", + "button": "立即同步" + }, + "password": { + "retrieve": "找回密码", + "retrieved": "密码已找回", + "change_error": "修改密码异常", + "retrieved_account": "找回 {{account}} 账号", + "email_phone": "邮箱/手机号", + "email_phone_void": "邮箱/手机号不能为空", + "email_phone_error": "邮箱/手机号格式错误", + "code_required": "验证码不能为空", + "new_password": "新密码(4~20位)", + "password_required": "密码不能为空", + "password_condition": "密码最少 4 位最多 20 位", + "verification_code": "验证码", + "confirm": "确认密码", + "not_match": "两次密码不一致", + "to_login": "去登陆", + "get_code": "获取验证码", + "get_code_again": "s后重新获取", + "code_sended": "验证码已发送", + "code_send_error": "验证码发送异常" + }, + "register": { + "success": "注册成功", + "failed": "注册失败", + "error": "注册异常", + "register_account": "注册 {{account}} 账号", + "confirm": "确认注册", + "to_login": "已有账号,去登录" + }, + "login": { + "success": "登录成功", + "failed": "登录失败", + "error": "登录异常", + "login_account": "登录 {{account}} 账号", + "login_error": "用户名或密码错误", + "to_register": "没有账号,去注册", + "password_condition": "密码最多 60 位" } } diff --git a/packages/web/i18n/zh/workflow.json b/packages/web/i18n/zh/workflow.json index 28c01d506..4db9aabdb 100644 --- a/packages/web/i18n/zh/workflow.json +++ b/packages/web/i18n/zh/workflow.json @@ -28,5 +28,8 @@ "Error": "错误信息" }, "tool_input": "工具参数", - "variable_picker_tips": "可输入节点名或变量名搜索" + "variable_picker_tips": "可输入节点名或变量名搜索", + "delete_api": "确认删除该API密钥?删除后该密钥立即失效,对应的对话日志不会删除,请确认!", + "create_link_error": "创建链接异常", + "update_link_error": "更新链接异常" } diff --git a/packages/web/types/i18next.d.ts b/packages/web/types/i18next.d.ts index 3d2b7b68e..8b57cbc58 100644 --- a/packages/web/types/i18next.d.ts +++ b/packages/web/types/i18next.d.ts @@ -7,7 +7,6 @@ import publish from '../i18n/zh/publish.json'; import workflow from '../i18n/zh/workflow.json'; import user from '../i18n/zh/user.json'; import chat from '../i18n/zh/chat.json'; - export interface I18nNamespaces { common: typeof common; dataset: typeof dataset; diff --git a/projects/app/src/components/CommunityModal/index.tsx b/projects/app/src/components/CommunityModal/index.tsx index 1b2765b28..df8b52070 100644 --- a/projects/app/src/components/CommunityModal/index.tsx +++ b/projects/app/src/components/CommunityModal/index.tsx @@ -22,7 +22,7 @@ const CommunityModal = ({ onClose }: { onClose: () => void }) => { diff --git a/projects/app/src/components/PromptTemplate/index.tsx b/projects/app/src/components/PromptTemplate/index.tsx index 3a3bd352f..8ccaef153 100644 --- a/projects/app/src/components/PromptTemplate/index.tsx +++ b/projects/app/src/components/PromptTemplate/index.tsx @@ -3,7 +3,7 @@ import MyModal from '@fastgpt/web/components/common/MyModal'; import { Box, Button, Flex, Grid, useTheme } from '@chakra-ui/react'; import { PromptTemplateItem } from '@fastgpt/global/core/ai/type.d'; import { ModalBody, ModalFooter } from '@chakra-ui/react'; - +import { useTranslation } from 'next-i18next'; const PromptTemplate = ({ title, templates, @@ -17,7 +17,7 @@ const PromptTemplate = ({ }) => { const theme = useTheme(); const [selectTemplateTitle, setSelectTemplateTitle] = useState(); - + const { t } = useTranslation(); return ( @@ -55,7 +55,7 @@ const PromptTemplate = ({ onClose(); }} > - 确认选择 + {t('common:confirm_choice')} diff --git a/projects/app/src/components/common/folder/SlideCard.tsx b/projects/app/src/components/common/folder/SlideCard.tsx index c0448a0cc..1639e98fc 100644 --- a/projects/app/src/components/common/folder/SlideCard.tsx +++ b/projects/app/src/components/common/folder/SlideCard.tsx @@ -14,7 +14,6 @@ import CollaboratorContextProvider, { } from '../../support/permission/MemberManager/context'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { useSystemStore } from '@/web/common/system/useSystemStore'; -import { useI18n } from '@/web/context/I18n'; import ResumeInherit from '@/components/support/permission/ResumeInheritText'; const FolderSlideCard = ({ @@ -55,7 +54,6 @@ const FolderSlideCard = ({ }) => { const { t } = useTranslation(); const { feConfigs } = useSystemStore(); - const { commonT } = useI18n(); const { toast } = useToast(); const { ConfirmModal, openConfirm } = useConfirm({ @@ -78,7 +76,7 @@ const FolderSlideCard = ({ /> - {intro || '暂无介绍'} + {intro || t('common:not_yet_introduced')} diff --git a/projects/app/src/components/core/ai/AISettingModal/index.tsx b/projects/app/src/components/core/ai/AISettingModal/index.tsx index e50d391dc..511008ec8 100644 --- a/projects/app/src/components/core/ai/AISettingModal/index.tsx +++ b/projects/app/src/components/core/ai/AISettingModal/index.tsx @@ -135,7 +135,9 @@ const AIChatSettingsModal = ({ - {selectedModel?.toolChoice || selectedModel?.functionCall ? '支持' : '不支持'} + {selectedModel?.toolChoice || selectedModel?.functionCall + ? t('common:common.support') + : t('common:common.not_support')} diff --git a/projects/app/src/components/core/app/ScheduledTriggerConfig.tsx b/projects/app/src/components/core/app/ScheduledTriggerConfig.tsx index eef55dde7..45cc9ce5c 100644 --- a/projects/app/src/components/core/app/ScheduledTriggerConfig.tsx +++ b/projects/app/src/components/core/app/ScheduledTriggerConfig.tsx @@ -20,11 +20,10 @@ import type { MultipleSelectProps } from '@fastgpt/web/components/common/MySelec import { cronParser2Fields } from '@fastgpt/global/common/string/time'; import TimezoneSelect from '@fastgpt/web/components/common/MySelect/TimezoneSelect'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; - const MultipleRowSelect = dynamic( () => import('@fastgpt/web/components/common/MySelect/MultipleRowSelect') ); - +import { i18nT } from '@fastgpt/web/i18n/utils'; // options type: enum CronJobTypeEnum { month = 'month', @@ -40,17 +39,32 @@ const get24HoursOptions = () => { value: i })); }; + +const getRoute = (i: number) => { + switch (i) { + case 0: + return 'app:week.Sunday'; + case 1: + return 'app:week.Monday'; + case 2: + return 'app:week.Tuesday'; + case 3: + return 'app:week.Wednesday'; + case 4: + return 'app:week.Thursday'; + case 5: + return 'app:week.Friday'; + case 6: + return 'app:week.Saturday'; + default: + return 'app:week.Sunday'; + } +}; + const getWeekOptions = () => { return Array.from({ length: 7 }, (_, i) => { - if (i === 0) { - return { - label: '星期日', - value: i, - children: get24HoursOptions() - }; - } return { - label: `星期${i}`, + label: i18nT(getRoute(i)), value: i, children: get24HoursOptions() }; @@ -58,7 +72,7 @@ const getWeekOptions = () => { }; const getMonthOptions = () => { return Array.from({ length: 28 }, (_, i) => ({ - label: `${i + 1}号`, + label: `${i + 1}` + i18nT('app:month.unit'), value: i, children: get24HoursOptions() })); @@ -67,27 +81,27 @@ const getInterValOptions = () => { // 每n小时 return [ { - label: `每小时`, + label: i18nT('app:interval.per_hour'), value: 1 }, { - label: `每2小时`, + label: i18nT('app:interval.2_hours'), value: 2 }, { - label: `每3小时`, + label: i18nT('app:interval.3_hours'), value: 3 }, { - label: `每4小时`, + label: i18nT('app:interval.4_hours'), value: 4 }, { - label: `每6小时`, + label: i18nT('app:interval.6_hours'), value: 6 }, { - label: `每12小时`, + label: i18nT('app:interval.12_hours'), value: 12 } ]; @@ -113,22 +127,22 @@ const ScheduledTriggerConfig = ({ const cronSelectList = useRef([ { - label: '每天执行', + label: t('app:cron.every_day'), value: CronJobTypeEnum.day, children: get24HoursOptions() }, { - label: '每周执行', + label: t('app:cron.every_week'), value: CronJobTypeEnum.week, children: getWeekOptions() }, { - label: '每月执行', + label: t('app:cron.every_month'), value: CronJobTypeEnum.month, children: getMonthOptions() }, { - label: '间隔执行', + label: t('app:cron.interval'), value: CronJobTypeEnum.interval, children: getInterValOptions() } @@ -224,7 +238,7 @@ const ScheduledTriggerConfig = ({ } if (cronField[0] === 'week') { return t('core.app.schedule.Every week', { - day: cronField[1] === 0 ? '日' : cronField[1], + day: cronField[1] === 0 ? t('app:day') : cronField[1], hour: cronField[2] }); } @@ -279,10 +293,7 @@ const ScheduledTriggerConfig = ({ > - - {' '} - {t('common:core.app.schedule.Open schedule')} - + {t('common:core.app.schedule.Open schedule')} { @@ -297,7 +308,7 @@ const ScheduledTriggerConfig = ({ {isOpenSchedule && ( <> - 执行时间 + {t('app:execute_time')} - 时区 + {t('app:time_zone')} item.moduleType === FlowNodeTypeEnum.chatNode || item.moduleType === FlowNodeTypeEnum.tools; const ContextModal = ({ onClose, dataId }: { onClose: () => void; dataId: string }) => { const { getHistoryResponseData } = useContextSelector(ChatBoxContext, (v) => v); - + const { t } = useTranslation(); const { loading: isLoading, data: contextModalData } = useRequest2( () => getHistoryResponseData({ dataId }).then((res) => { @@ -34,7 +35,7 @@ const ContextModal = ({ onClose, dataId }: { onClose: () => void; dataId: string onClose={onClose} isLoading={isLoading} iconSrc="/imgs/modal/chatHistory.svg" - title={`上下文预览(${contextModalData?.length || 0}条)`} + title={t('chat:contextual_preview', { num: contextModalData?.length || 0 })} h={['90vh', '80vh']} minW={['90vw', '600px']} isCentered diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx index 2f5a66fe9..bc731d93f 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx @@ -175,28 +175,28 @@ const ResponseTags = ({ {showDetail && ( {quoteList.length > 0 && ( - + setQuoteModalData({ rawSearch: quoteList })} > - {quoteList.length}条引用 + {t('chat:citations', { num: quoteList.length })} )} {llmModuleAccount === 1 && ( <> {historyPreviewLength > 0 && ( - + - {historyPreviewLength}条上下文 + {t('chat:contextual', { num: historyPreviewLength })} )} @@ -204,12 +204,12 @@ const ResponseTags = ({ )} {llmModuleAccount > 1 && ( - 多组 AI 对话 + {t('chat:multiple_AI_conversations')} )} {isPc && runningTime > 0 && ( - + {runningTime}s diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/SelectMarkCollection.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/SelectMarkCollection.tsx index 925db604e..00d679d6a 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/SelectMarkCollection.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/SelectMarkCollection.tsx @@ -90,7 +90,7 @@ const SelectMarkCollection = ({ })() )} - {datasets.length === 0 && } + {datasets.length === 0 && } )} diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useChatBox.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useChatBox.tsx index 3023ab42c..5aeb248ec 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useChatBox.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useChatBox.tsx @@ -4,8 +4,9 @@ import { useCallback } from 'react'; import { htmlTemplate } from '@/web/core/chat/constants'; import { fileDownload } from '@/web/common/file/utils'; import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants'; - +import { useTranslation } from 'next-i18next'; export const useChatBox = () => { + const { t } = useTranslation(); const onExportChat = useCallback( ({ type, history }: { type: ExportChatType; history: ChatItemType[] }) => { const getHistoryHtml = () => { @@ -74,7 +75,7 @@ ${JSON.stringify(item.tools, null, 2)} fileDownload({ text: html, type: 'text/html', - filename: '聊天记录.html' + filename: `${t('chat:chat_history')}.html` }); }, pdf: () => { @@ -84,7 +85,7 @@ ${JSON.stringify(item.tools, null, 2)} // @ts-ignore html2pdf(html, { margin: 0, - filename: `聊天记录.pdf` + filename: `${t('chat:chat_history')}.pdf` }); } }; diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx index 1837b23b2..db55d3955 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx @@ -372,7 +372,7 @@ const ChatBox = ( if (!onStartChat) return; if (isChatting) { toast({ - title: '正在聊天中...请等待结束', + title: t('chat:is_chatting'), status: 'warning' }); return; @@ -384,7 +384,7 @@ const ChatBox = ( if (!text && files.length === 0) { toast({ - title: '内容为空', + title: t('chat:content_empty'), status: 'warning' }); return; diff --git a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderOutput.tsx b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderOutput.tsx index 86947060f..b78d76e61 100644 --- a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderOutput.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderOutput.tsx @@ -5,10 +5,10 @@ import { PluginRunContext } from '../context'; import Markdown from '@/components/Markdown'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import AIResponseBox from '../../../components/AIResponseBox'; - +import { useTranslation } from 'next-i18next'; const RenderOutput = () => { const { histories, isChatting } = useContextSelector(PluginRunContext, (v) => v); - + const { t } = useTranslation(); const pluginOutputs = useMemo(() => { const pluginOutputs = histories?.[1]?.responseData?.find( (item) => item.moduleType === FlowNodeTypeEnum.pluginOutput @@ -22,7 +22,7 @@ const RenderOutput = () => { - 流输出 + {t('chat:stream_output')} {histories.length > 0 && histories[1]?.value.length > 0 ? ( @@ -46,7 +46,7 @@ const RenderOutput = () => { - 插件输出 + {t('chat:plugins_output')} {histories.length > 0 && histories[1].responseData ? ( ) : null} diff --git a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderResponseDetail.tsx b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderResponseDetail.tsx index 48d572a0c..d3bc222cb 100644 --- a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderResponseDetail.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderResponseDetail.tsx @@ -3,14 +3,14 @@ import React from 'react'; import { useContextSelector } from 'use-context-selector'; import { PluginRunContext } from '../context'; import { Box } from '@chakra-ui/react'; - +import { useTranslation } from 'next-i18next'; const RenderResponseDetail = () => { const { histories, isChatting } = useContextSelector(PluginRunContext, (v) => v); - + const { t } = useTranslation(); const responseData = histories?.[1]?.responseData || []; return isChatting ? ( - <>{'进行中'} + <>{t('chat:in_progress')} ) : ( diff --git a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/context.tsx b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/context.tsx index 4d6686478..06c591f49 100644 --- a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/context.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/context.tsx @@ -11,7 +11,7 @@ import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/c import { generatingMessageProps } from '../type'; import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { getPluginRunContent } from '@fastgpt/global/core/app/plugin/utils'; - +import { useTranslation } from 'next-i18next'; type PluginRunContextType = PluginRunBoxProps & { isChatting: boolean; onSubmit: (e: FieldValues) => Promise; @@ -44,7 +44,7 @@ const PluginRunContextProvider = ({ const { toast } = useToast(); const chatController = useRef(new AbortController()); - + const { t } = useTranslation(); /* Abort chat completions, questionGuide */ const abortRequest = useCallback(() => { chatController.current?.abort('stop'); @@ -148,7 +148,7 @@ const PluginRunContextProvider = ({ if (!onStartChat) return; if (isChatting) { toast({ - title: '正在聊天中...请等待结束', + title: t('chat:is_chatting'), status: 'warning' }); return; diff --git a/projects/app/src/components/core/chat/components/WholeResponseModal.tsx b/projects/app/src/components/core/chat/components/WholeResponseModal.tsx index 5f844ab3c..ccfeffa17 100644 --- a/projects/app/src/components/core/chat/components/WholeResponseModal.tsx +++ b/projects/app/src/components/core/chat/components/WholeResponseModal.tsx @@ -119,7 +119,7 @@ const WholeResponseModal = ({ title={ {t('common:core.chat.response.Complete Response')} - + } > diff --git a/projects/app/src/components/support/apikey/Table.tsx b/projects/app/src/components/support/apikey/Table.tsx index af76eb713..ccc0f98b7 100644 --- a/projects/app/src/components/support/apikey/Table.tsx +++ b/projects/app/src/components/support/apikey/Table.tsx @@ -62,7 +62,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => { const [apiKey, setApiKey] = useState(''); const { ConfirmModal, openConfirm } = useConfirm({ type: 'delete', - content: '确认删除该API密钥?删除后该密钥立即失效,对应的对话日志不会删除,请确认!' + content: t('workflow:delete_api') }); const { mutate: onclickRemove, isLoading: isDeleting } = useMutation({ @@ -318,7 +318,7 @@ function EditKeyModal({ const { mutate: onclickCreate, isLoading: creating } = useRequest({ mutationFn: async (e: EditProps) => createAOpenApiKey(e), - errorToast: '创建链接异常', + errorToast: t('workflow:create_link_error'), onSuccess: onCreate }); const { mutate: onclickUpdate, isLoading: updating } = useRequest({ @@ -326,7 +326,7 @@ function EditKeyModal({ //@ts-ignore return putOpenApiKey(e); }, - errorToast: '更新链接异常', + errorToast: t('workflow:update_link_error'), onSuccess: onEdit }); diff --git a/projects/app/src/components/support/laf/LafAccountModal.tsx b/projects/app/src/components/support/laf/LafAccountModal.tsx index 8725aff2e..cb5e25e4b 100644 --- a/projects/app/src/components/support/laf/LafAccountModal.tsx +++ b/projects/app/src/components/support/laf/LafAccountModal.tsx @@ -73,7 +73,7 @@ const LafAccountModal = ({ onError: (err) => { onResetForm(); toast({ - title: getErrText(err, '获取应用列表失败'), + title: getErrText(err, t('common:get_app_failed')), status: 'error' }); } @@ -132,7 +132,7 @@ const LafAccountModal = ({ }} isLoading={isPatLoading} > - 验证 + {t('common:verification')} ) : ( @@ -145,7 +145,7 @@ const LafAccountModal = ({ }); }} > - 已验证,点击取消绑定 + {t('common:has_verification')} )} diff --git a/projects/app/src/components/support/permission/DefaultPerList/index.tsx b/projects/app/src/components/support/permission/DefaultPerList/index.tsx index 51d1e16cf..5eae667bc 100644 --- a/projects/app/src/components/support/permission/DefaultPerList/index.tsx +++ b/projects/app/src/components/support/permission/DefaultPerList/index.tsx @@ -5,7 +5,7 @@ import type { PermissionValueType } from '@fastgpt/global/support/permission/typ import { ReadPermissionVal, WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; -import { useI18n } from '@/web/context/I18n'; +import { useTranslation } from 'react-i18next'; export enum defaultPermissionEnum { private = 'private', @@ -34,12 +34,11 @@ const DefaultPermissionList = ({ ...styles }: Props) => { const { ConfirmModal, openConfirm } = useConfirm({}); - const { commonT } = useI18n(); - + const { t } = useTranslation(); const defaultPermissionSelectList = [ - { label: '仅协作者访问', value: defaultPer }, - { label: '团队可访问', value: readPer }, - { label: '团队可编辑', value: writePer } + { label: t('user:permission.only_collaborators'), value: defaultPer }, + { label: t('user:permission.team_read'), value: readPer }, + { label: t('user:permission.team_write'), value: writePer } ]; const { runAsync: onRequestChange, loading } = useRequest2((v: PermissionValueType) => @@ -58,7 +57,7 @@ const DefaultPermissionList = ({ openConfirm( () => onRequestChange(per), undefined, - commonT('permission.Remove InheritPermission Confirm') + t('common:permission.Remove InheritPermission Confirm') )(); } else { return onRequestChange(per); diff --git a/projects/app/src/components/support/permission/MemberManager/AddMemberModal.tsx b/projects/app/src/components/support/permission/MemberManager/AddMemberModal.tsx index c1ef73f36..d182914a1 100644 --- a/projects/app/src/components/support/permission/MemberManager/AddMemberModal.tsx +++ b/projects/app/src/components/support/permission/MemberManager/AddMemberModal.tsx @@ -79,7 +79,13 @@ function AddMemberModal({ onClose }: AddModalPropsType) { }); return ( - + setSearchText(e.target.value)} /> @@ -156,7 +162,9 @@ function AddMemberModal({ onClose }: AddModalPropsType) { - 已选: {selectedMemberIdList.length} + + {t('user:has_chosen') + ': '}+ {selectedMemberIdList.length} + {selectedMemberIdList.map((tmbId) => { const member = filterMembers.find((v) => v.tmbId === tmbId); @@ -211,7 +219,7 @@ function AddMemberModal({ onClose }: AddModalPropsType) { onChange={(v) => setSelectedPermission(v)} /> diff --git a/projects/app/src/components/support/permission/MemberManager/ManageModal.tsx b/projects/app/src/components/support/permission/MemberManager/ManageModal.tsx index ff8af158a..c801dc7c5 100644 --- a/projects/app/src/components/support/permission/MemberManager/ManageModal.tsx +++ b/projects/app/src/components/support/permission/MemberManager/ManageModal.tsx @@ -23,12 +23,13 @@ import { PermissionValueType } from '@fastgpt/global/support/permission/type'; import { useUserStore } from '@/web/support/user/useUserStore'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import Loading from '@fastgpt/web/components/common/MyLoading'; - +import { useTranslation } from 'next-i18next'; export type ManageModalProps = { onClose: () => void; }; function ManageModal({ onClose }: ManageModalProps) { + const { t } = useTranslation(); const { userInfo } = useUserStore(); const { permission, collaboratorList, onUpdateCollaborators, onDelOneCollaborator } = useContextSelector(CollaboratorContext, (v) => v); @@ -44,23 +45,29 @@ function ManageModal({ onClose }: ManageModalProps) { permission: per }); }, - successToast: '更新成功', + successToast: t('common.Update Success'), errorToast: 'Error' }); const loading = isDeleting || isUpdating; return ( - + - - + + @@ -109,7 +116,7 @@ function ManageModal({ onClose }: ManageModalProps) { })}
名称权限{t('user:name')}{t('user:permissions')} - 操作 + {t('user:operations')}
- {collaboratorList?.length === 0 && } + {collaboratorList?.length === 0 && }
{loading && }
diff --git a/projects/app/src/components/support/user/team/TeamManageModal/components/PermissionManage/AddManager.tsx b/projects/app/src/components/support/user/team/TeamManageModal/components/PermissionManage/AddManager.tsx index 561befec5..9e8f83d30 100644 --- a/projects/app/src/components/support/user/team/TeamManageModal/components/PermissionManage/AddManager.tsx +++ b/projects/app/src/components/support/user/team/TeamManageModal/components/PermissionManage/AddManager.tsx @@ -47,8 +47,8 @@ function AddManagerModal({ onClose, onSuccess }: { onClose: () => void; onSucces refetchMembers(); onSuccess(); }, - successToast: '成功', - errorToast: '失败' + successToast: t('common:common.Success'), + errorToast: t('common:common.failed') }); const filterMembers = useMemo(() => { @@ -83,7 +83,7 @@ function AddManagerModal({ onClose, onSuccess }: { onClose: () => void; onSucces { @@ -120,7 +120,7 @@ function AddManagerModal({ onClose, onSuccess }: { onClose: () => void; onSucces - 已选: {selected.length} 个 + {t('common:chosen') + ': ' + selected.length} {selected.map((member) => { return ( diff --git a/projects/app/src/components/support/user/team/TeamManageModal/components/PermissionManage/index.tsx b/projects/app/src/components/support/user/team/TeamManageModal/components/PermissionManage/index.tsx index e8d0438e2..732c5ae87 100644 --- a/projects/app/src/components/support/user/team/TeamManageModal/components/PermissionManage/index.tsx +++ b/projects/app/src/components/support/user/team/TeamManageModal/components/PermissionManage/index.tsx @@ -31,8 +31,8 @@ function PermissionManage() { mutationFn: async (memberId: string) => { return delMemberPermission(memberId); }, - successToast: '删除管理员成功', - errorToast: '删除管理员异常', + successToast: t('user:delete.admin_success'), + errorToast: t('user:delete.admin_failed'), onSuccess: () => { refetchMembers(); } @@ -75,7 +75,7 @@ function PermissionManage() { onOpenAddManager(); }} > - 添加管理员 + {t('user:team.Add manager')} )} diff --git a/projects/app/src/components/support/user/team/TeamTagModal/index.tsx b/projects/app/src/components/support/user/team/TeamTagModal/index.tsx index 54eb7e3ab..3d2396fe6 100644 --- a/projects/app/src/components/support/user/team/TeamTagModal/index.tsx +++ b/projects/app/src/components/support/user/team/TeamTagModal/index.tsx @@ -95,7 +95,7 @@ const TeamTagsAsync = ({ onClose }: { onClose: () => void }) => { {teamInfo?.teamName} - {'填写标签同步链接,点击同步按钮即可同步'} + {t('user:synchronization.title')} } @@ -110,7 +110,7 @@ const TeamTagsAsync = ({ onClose }: { onClose: () => void }) => { ml={4} autoFocus bg={'myWhite.600'} - placeholder="请输入同步标签" + placeholder={t('user:synchronization.placeholder')} {...register('teamDomain', { required: true })} @@ -181,7 +181,7 @@ const TeamTagsAsync = ({ onClose }: { onClose: () => void }) => { leftIcon={} onClick={handleSubmit((data) => onclickTagAsync(data))} > - 立即同步 + {t('user:synchronization.button')} diff --git a/projects/app/src/components/support/wallet/QRCodePayModal.tsx b/projects/app/src/components/support/wallet/QRCodePayModal.tsx index 9683d688d..60a86917f 100644 --- a/projects/app/src/components/support/wallet/QRCodePayModal.tsx +++ b/projects/app/src/components/support/wallet/QRCodePayModal.tsx @@ -73,7 +73,7 @@ const QRCodePayModal = ({ return ( - 请微信扫码支付: {readPrice}元,请勿关闭页面 + {t('common:pay.wechat', { price: readPrice })} diff --git a/projects/app/src/components/support/wallet/StandardPlanContentList.tsx b/projects/app/src/components/support/wallet/StandardPlanContentList.tsx index ed34dd32c..314e7b5cb 100644 --- a/projects/app/src/components/support/wallet/StandardPlanContentList.tsx +++ b/projects/app/src/components/support/wallet/StandardPlanContentList.tsx @@ -112,13 +112,13 @@ const StandardPlanContentList = ({ {!!planContent.permissionReRank && ( - 检索结果重排 + {t('chat:rearrangement')} )} {!!planContent.permissionWebsiteSync && ( - Web站点同步 + {t('chat:web_site_sync')} )} diff --git a/projects/app/src/global/core/chat/constants.ts b/projects/app/src/global/core/chat/constants.ts index f90c2c417..c9f4ba6b8 100644 --- a/projects/app/src/global/core/chat/constants.ts +++ b/projects/app/src/global/core/chat/constants.ts @@ -1,6 +1,6 @@ import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { InitChatResponse } from './api'; - +import { i18nT } from '@fastgpt/web/i18n/utils'; export const defaultChatData: InitChatResponse = { chatId: '', appId: '', @@ -12,7 +12,7 @@ export const defaultChatData: InitChatResponse = { type: AppTypeEnum.simple, pluginInputs: [] }, - title: '新对话', + title: i18nT('chat:new_chat'), variables: {}, history: [] }; diff --git a/projects/app/src/pages/_app.tsx b/projects/app/src/pages/_app.tsx index 5cccfa9ae..1174fe046 100644 --- a/projects/app/src/pages/_app.tsx +++ b/projects/app/src/pages/_app.tsx @@ -8,13 +8,13 @@ import QueryClientContext from '@/web/context/QueryClient'; import ChakraUIContext from '@/web/context/ChakraUI'; import I18nContextProvider from '@/web/context/I18n'; import { useInitApp } from '@/web/context/useInitApp'; - +import { useTranslation } from 'next-i18next'; import '@/web/styles/reset.scss'; import NextHead from '@/components/common/NextHead'; function App({ Component, pageProps }: AppProps) { const { feConfigs, scripts, title } = useInitApp(); - + const { t } = useTranslation(); return ( <> diff --git a/projects/app/src/pages/account/components/BillTable.tsx b/projects/app/src/pages/account/components/BillTable.tsx index 3eb9f34ca..94ac1aa50 100644 --- a/projects/app/src/pages/account/components/BillTable.tsx +++ b/projects/app/src/pages/account/components/BillTable.tsx @@ -33,9 +33,10 @@ import MySelect from '@fastgpt/web/components/common/MySelect'; import MyModal from '@fastgpt/web/components/common/MyModal'; import { usePagination } from '@fastgpt/web/hooks/usePagination'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; - +import { useI18n } from '@/web/context/I18n'; const BillTable = () => { const { t } = useTranslation(); + const { commonT } = useI18n(); const { toast } = useToast(); const [billType, setBillType] = useState(''); const [billDetail, setBillDetail] = useState(); @@ -134,7 +135,7 @@ const BillTable = () => { {item.createTime ? dayjs(item.createTime).format('YYYY/MM/DD HH:mm:ss') : '-'} - {formatStorePrice2Read(item.price)}元 + {commonT('common:pay.yuan', { amount: formatStorePrice2Read(item.price) })} {t(billStatusMap[item.status]?.label as any)} {item.status === 'NOTPAY' && ( @@ -181,7 +182,7 @@ export default BillTable; function BillDetailModal({ bill, onClose }: { bill: BillSchemaType; onClose: () => void }) { const { t } = useTranslation(); - + const { commonT } = useI18n(); return ( {t('common:support.wallet.Amount')}: - {formatStorePrice2Read(bill.price)}元 + {commonT('common:pay.yuan', { amount: formatStorePrice2Read(bill.price) })} {t('common:support.wallet.bill.Type')}: diff --git a/projects/app/src/pages/account/components/Info.tsx b/projects/app/src/pages/account/components/Info.tsx index 4cc37e9fd..c5e752dfc 100644 --- a/projects/app/src/pages/account/components/Info.tsx +++ b/projects/app/src/pages/account/components/Info.tsx @@ -435,7 +435,7 @@ const PlanUsage = () => { {formatTime2YMD(standardPlan?.expiredTime)} - 免费版用户30天无任何使用记录时,系统会自动清理账号知识库。 + {t('common:info.free_plan')} ) : ( @@ -470,9 +470,9 @@ const PlanUsage = () => { > - 资源用量 + {t('common:info.resource')} - (包含标准套餐与额外资源包) + {t('common:info.include')} { cursor={'pointer'} fontSize={'sm'} > - 购买额外套餐 + {t('common:info.buy_extra')} @@ -567,7 +567,7 @@ const Other = () => { }); reset(data); toast({ - title: '更新数据成功', + title: t('common:dataset.data.Update Success Tip'), status: 'success' }); }, @@ -637,7 +637,7 @@ const Other = () => { > laf - laf 账号 + {'laf' + t('common:navbar.Account')} { > - OpenAI/OneAPI 账号 + {'OpenAI / OneAPI' + t('common:navbar.Account')} { )} ))} - {!isLoading && informs.length === 0 && } + {!isLoading && informs.length === 0 && ( + + )} {total > pageSize && ( diff --git a/projects/app/src/pages/account/components/OpenAIAccountModal.tsx b/projects/app/src/pages/account/components/OpenAIAccountModal.tsx index c7a58a140..dce043472 100644 --- a/projects/app/src/pages/account/components/OpenAIAccountModal.tsx +++ b/projects/app/src/pages/account/components/OpenAIAccountModal.tsx @@ -37,9 +37,7 @@ const OpenAIAccountModal = ({ > - 可以填写 OpenAI/OneAPI - 的相关秘钥。如果你填写了该内容,在线上平台使用【AI对话】、【问题分类】和【内容提取】将会走你填写的Key,不会计费。请注意你的 - Key 是否有访问对应模型的权限。GPT模型可以选择 FastAI。 + {t('common:info.open_api_notice')} API Key: @@ -50,16 +48,16 @@ const OpenAIAccountModal = ({ diff --git a/projects/app/src/pages/account/components/PayModal.tsx b/projects/app/src/pages/account/components/PayModal.tsx index 8af857307..dfb3a9699 100644 --- a/projects/app/src/pages/account/components/PayModal.tsx +++ b/projects/app/src/pages/account/components/PayModal.tsx @@ -7,7 +7,6 @@ import { getErrText } from '@fastgpt/global/common/error/utils'; import { useTranslation } from 'next-i18next'; import MyModal from '@fastgpt/web/components/common/MyModal'; import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants'; - import QRCodePayModal, { type QRPayProps } from '@/components/support/wallet/QRCodePayModal'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { EXTRA_PLAN_CARD_ROUTE } from '@/web/support/wallet/sub/constants'; @@ -27,7 +26,6 @@ const PayModal = ({ const [inputVal, setInputVal] = useState(defaultValue); const [loading, setLoading] = useState(false); const [qrPayData, setQRPayData] = useState(); - const handleClickPay = useCallback(async () => { if (!inputVal || inputVal <= 0 || isNaN(+inputVal)) return; setLoading(true); @@ -79,7 +77,7 @@ const PayModal = ({ variant={item === inputVal ? 'solid' : 'outline'} onClick={() => setInputVal(item)} > - {item}元 + {t('common:pay.yuan', { amount: item })} ))} @@ -88,7 +86,7 @@ const PayModal = ({ value={inputVal} type={'number'} step={1} - placeholder={'其他金额,请取整数'} + placeholder={t('common:pay.other')} onChange={(e) => { setInputVal(Math.floor(+e.target.value)); }} @@ -106,7 +104,7 @@ const PayModal = ({ isDisabled={!inputVal || inputVal === 0} onClick={handleClickPay} > - 获取充值二维码 + {t('common:pay.get_pay_QR')} diff --git a/projects/app/src/pages/account/components/Promotion.tsx b/projects/app/src/pages/account/components/Promotion.tsx index e2a8edcfd..87dca1d3e 100644 --- a/projects/app/src/pages/account/components/Promotion.tsx +++ b/projects/app/src/pages/account/components/Promotion.tsx @@ -105,9 +105,9 @@ const Promotion = () => { - - - + + + @@ -124,7 +124,9 @@ const Promotion = () => {
时间类型金额(¥){t('common:user.Time')}{t('common:user.type')}{t('common:pay.amount')}
- {!isLoading && promotionRecords.length === 0 && } + {!isLoading && promotionRecords.length === 0 && ( + + )} {total > pageSize && ( diff --git a/projects/app/src/pages/account/components/UpdateNotificationModal.tsx b/projects/app/src/pages/account/components/UpdateNotificationModal.tsx index 0459ca88e..1a94cda8e 100644 --- a/projects/app/src/pages/account/components/UpdateNotificationModal.tsx +++ b/projects/app/src/pages/account/components/UpdateNotificationModal.tsx @@ -70,16 +70,16 @@ const UpdateNotificationModal = ({ onClose }: { onClose: () => void }) => { flex={1} bg={'myGray.50'} {...register('account', { required: true })} - placeholder={t('common:support.user.Email Or Phone')} + placeholder={t('user:password.email_phone')} > - {t('common:support.user.Verify Code')} + {t('user:password.verification_code')} void }) => { > - 旧密码: + {t('common:user.old_password') + ':'} - 新密码: + {t('common:user.new_password') + ':'} void }) => { required: true, maxLength: { value: 60, - message: '密码最少 4 位最多 60 位' + message: t('common:user.password_message') } })} > - 确认密码: + {t('common:user.confirm_password') + ':'} void }) => { required: true, maxLength: { value: 60, - message: '密码最少 4 位最多 60 位' + message: t('common:user.password_message') } })} > @@ -79,10 +79,10 @@ const UpdatePswModal = ({ onClose }: { onClose: () => void }) => {
diff --git a/projects/app/src/pages/account/components/UsageTable.tsx b/projects/app/src/pages/account/components/UsageTable.tsx index 2af918dad..148283e8d 100644 --- a/projects/app/src/pages/account/components/UsageTable.tsx +++ b/projects/app/src/pages/account/components/UsageTable.tsx @@ -174,7 +174,7 @@ const UsageTable = () => { {formatNumber(item.totalPoints) || 0} @@ -183,7 +183,9 @@ const UsageTable = () => { - {!isLoading && usages.length === 0 && } + {!isLoading && usages.length === 0 && ( + + )} {!!usageDetail && ( diff --git a/projects/app/src/pages/account/components/standardDetailModal.tsx b/projects/app/src/pages/account/components/standardDetailModal.tsx index b44599769..1ec755d16 100644 --- a/projects/app/src/pages/account/components/standardDetailModal.tsx +++ b/projects/app/src/pages/account/components/standardDetailModal.tsx @@ -77,10 +77,12 @@ const StandDetailModal = ({ onClose }: { onClose: () => void }) => { {currentSubLevel && `(${t(standardSubLevelMap[currentSubLevel]?.label as any)})`} - {datasetSize ? `${datasetSize}组` : '-'} + + {datasetSize ? `${datasetSize + t('common:core.dataset.data.group')}` : '-'} + {totalPoints - ? `${Math.round(totalPoints - surplusPoints)} / ${totalPoints} 积分` + ? `${Math.round(totalPoints - surplusPoints)} / ${totalPoints} ${t('common:support.wallet.subscription.point')}` : '-'} {formatTime2YMDHM(startTime)} diff --git a/projects/app/src/pages/account/index.tsx b/projects/app/src/pages/account/index.tsx index af58acf10..950d26da1 100644 --- a/projects/app/src/pages/account/index.tsx +++ b/projects/app/src/pages/account/index.tsx @@ -104,7 +104,7 @@ const Account = ({ currentTab }: { currentTab: TabEnum }) => { ]; const { openConfirm, ConfirmModal } = useConfirm({ - content: '确认退出登录?' + content: t('common:support.user.logout.confirm') }); const router = useRouter(); diff --git a/projects/app/src/pages/api/core/chat/init.ts b/projects/app/src/pages/api/core/chat/init.ts index a8a26f48c..624a8cb92 100644 --- a/projects/app/src/pages/api/core/chat/init.ts +++ b/projects/app/src/pages/api/core/chat/init.ts @@ -14,6 +14,7 @@ import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { transformPreviewHistories } from '@/global/core/chat/utils'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; +import { i18nT } from '@fastgpt/web/i18n/utils'; async function handler( req: NextApiRequest, res: NextApiResponse @@ -61,7 +62,7 @@ async function handler( return { chatId, appId, - title: chat?.title || '新对话', + title: chat?.title || i18nT('chat:new_chat'), userAvatar: undefined, variables: chat?.variables || {}, history: app.type === AppTypeEnum.plugin ? histories : transformPreviewHistories(histories), diff --git a/projects/app/src/pages/api/core/chat/outLink/init.ts b/projects/app/src/pages/api/core/chat/outLink/init.ts index eec0b25ed..71c451286 100644 --- a/projects/app/src/pages/api/core/chat/outLink/init.ts +++ b/projects/app/src/pages/api/core/chat/outLink/init.ts @@ -18,6 +18,7 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/controller'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { transformPreviewHistories } from '@/global/core/chat/utils'; +import { i18nT } from '@fastgpt/web/i18n/utils'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { await connectToDatabase(); @@ -69,7 +70,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) data: { chatId, appId: app._id, - title: chat?.title || '新对话', + title: chat?.title || i18nT('chat:new_chat'), //@ts-ignore userAvatar: tmb?.userId?.avatar, variables: chat?.variables || {}, diff --git a/projects/app/src/pages/api/core/chat/team/init.ts b/projects/app/src/pages/api/core/chat/team/init.ts index e93d631e7..44f5cef4c 100644 --- a/projects/app/src/pages/api/core/chat/team/init.ts +++ b/projects/app/src/pages/api/core/chat/team/init.ts @@ -18,6 +18,7 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/controller'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { transformPreviewHistories } from '@/global/core/chat/utils'; +import { i18nT } from '@fastgpt/web/i18n/utils'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { @@ -72,7 +73,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) data: { chatId, appId, - title: chat?.title || '新对话', + title: chat?.title || i18nT('chat:new_chat'), userAvatar: team?.avatar, variables: chat?.variables || {}, history: app.type === AppTypeEnum.plugin ? histories : transformPreviewHistories(histories), diff --git a/projects/app/src/pages/app/detail/components/InfoModal.tsx b/projects/app/src/pages/app/detail/components/InfoModal.tsx index bfbae9ad8..8c1e93a95 100644 --- a/projects/app/src/pages/app/detail/components/InfoModal.tsx +++ b/projects/app/src/pages/app/detail/components/InfoModal.tsx @@ -146,7 +146,7 @@ const InfoModal = ({ onClose }: { onClose: () => void }) => { () => resumeInheritPer(appDetail._id), // () => putAppById(appDetail._id, { inheritPermission: true }), { - errorToast: '恢复失败', + errorToast: t('common:resume_failed'), onSuccess: () => { reloadApp(); } diff --git a/projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx b/projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx index 28803af25..359809ec4 100644 --- a/projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx +++ b/projects/app/src/pages/app/detail/components/Logs/DetailLogsModal.tsx @@ -17,7 +17,6 @@ import CloseIcon from '@fastgpt/web/components/common/Icon/close'; import ChatBox from '@/components/core/chat/ChatContainer/ChatBox'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useQuery } from '@tanstack/react-query'; - const PluginRunBox = dynamic(() => import('@/components/core/chat/ChatContainer/PluginRunBox')); const DetailLogsModal = ({ @@ -32,7 +31,6 @@ const DetailLogsModal = ({ const { t } = useTranslation(); const { isPc } = useSystem(); const theme = useTheme(); - const { ChatBoxRef, chatRecords, @@ -101,7 +99,7 @@ const DetailLogsModal = ({ ...(chatRecords.length > 0 ? [ { label: t('common:common.Output'), value: PluginRunBoxTabEnum.output }, - { label: '完整结果', value: PluginRunBoxTabEnum.detail } + { label: t('common:common.all_result'), value: PluginRunBoxTabEnum.detail } ] : []) ]} @@ -133,7 +131,9 @@ const DetailLogsModal = ({ <> - {`${chatRecords.length}条记录`} + + {t('common:core.chat.History Amount', { amount: chatRecords.length })} + {!!chatModels && ( diff --git a/projects/app/src/pages/app/detail/components/Logs/index.tsx b/projects/app/src/pages/app/detail/components/Logs/index.tsx index 312a1d0fb..64f629388 100644 --- a/projects/app/src/pages/app/detail/components/Logs/index.tsx +++ b/projects/app/src/pages/app/detail/components/Logs/index.tsx @@ -122,7 +122,7 @@ const Logs = () => { key={item._id} _hover={{ bg: 'myWhite.600' }} cursor={'pointer'} - title={'点击查看对话详情'} + title={t('common:core.view_chat_detail')} onClick={() => setDetailLogsId(item.id)} > diff --git a/projects/app/src/pages/app/detail/components/Plugin/index.tsx b/projects/app/src/pages/app/detail/components/Plugin/index.tsx index 3d65f42cf..7a0e00274 100644 --- a/projects/app/src/pages/app/detail/components/Plugin/index.tsx +++ b/projects/app/src/pages/app/detail/components/Plugin/index.tsx @@ -13,6 +13,7 @@ import dynamic from 'next/dynamic'; import { cloneDeep } from 'lodash'; import Flow from '../WorkflowComponents/Flow'; +import { t } from 'i18next'; const Logs = dynamic(() => import('../Logs/index')); const PublishChannel = dynamic(() => import('../Publish')); @@ -22,8 +23,7 @@ const WorkflowEdit = () => { const { openConfirm, ConfirmModal } = useConfirm({ showCancel: false, - content: - '检测到您的高级编排为旧版,系统将为您自动格式化成新版工作流。\n\n由于版本差异较大,会导致一些工作流无法正常排布,请重新手动连接工作流。如仍异常,可尝试删除对应节点后重新添加。\n\n你可以直接点击调试进行工作流测试,调试完毕后点击发布。直到你点击发布,新工作流才会真正保存生效。\n\n在你发布新工作流前,自动保存不会生效。' + content: t('common:info.old_version_attention') }); const initData = useContextSelector(WorkflowContext, (v) => v.initData); diff --git a/projects/app/src/pages/app/detail/components/Publish/FeiShu/FeiShuEditModal.tsx b/projects/app/src/pages/app/detail/components/Publish/FeiShu/FeiShuEditModal.tsx index 83360b25d..8f7f9d467 100644 --- a/projects/app/src/pages/app/detail/components/Publish/FeiShu/FeiShuEditModal.tsx +++ b/projects/app/src/pages/app/detail/components/Publish/FeiShu/FeiShuEditModal.tsx @@ -123,8 +123,7 @@ const FeiShuEditModal = ({ - 默认回复 - {/* TODO: i18n */} + {t('common:default_reply')} - 立即回复 - {/* TODO: i18n */} + {t('common:reply_now')} import('../Logs/index')); const PublishChannel = dynamic(() => import('../Publish')); @@ -22,8 +23,7 @@ const WorkflowEdit = () => { const { openConfirm, ConfirmModal } = useConfirm({ showCancel: false, - content: - '检测到您的高级编排为旧版,系统将为您自动格式化成新版工作流。\n\n由于版本差异较大,会导致一些工作流无法正常排布,请重新手动连接工作流。如仍异常,可尝试删除对应节点后重新添加。\n\n你可以直接点击调试进行工作流测试,调试完毕后点击发布。直到你点击发布,新工作流才会真正保存生效。\n\n在你发布新工作流前,自动保存不会生效。' + content: t('common:info.old_version_attention') }); const initData = useContextSelector(WorkflowContext, (v) => v.initData); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ChatTest.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ChatTest.tsx index c44bbabe8..440e4cbf7 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ChatTest.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ChatTest.tsx @@ -77,7 +77,7 @@ const ChatTest = ({ ...(chatRecords.length > 0 ? [ { label: t('common:common.Output'), value: PluginRunBoxTabEnum.output }, - { label: '完整结果', value: PluginRunBoxTabEnum.detail } + { label: t('common:common.all_result'), value: PluginRunBoxTabEnum.detail } ] : []) ]} diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx index 1082afa45..8dd3c41e3 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx @@ -5,7 +5,7 @@ import { useToast } from '@fastgpt/web/hooks/useToast'; import { useContextSelector } from 'use-context-selector'; import { WorkflowContext } from '../context'; import { useI18n } from '@/web/context/I18n'; - +import { useTranslation } from 'next-i18next'; type Props = { onClose: () => void; }; @@ -15,7 +15,7 @@ const ImportSettings = ({ onClose }: Props) => { const { toast } = useToast(); const initData = useContextSelector(WorkflowContext, (v) => v.initData); const [value, setValue] = useState(''); - + const { t } = useTranslation(); return ( { } }} > - 确认 + {t('common:common.Confirm')} diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx index c1e1531c4..e2865a5e5 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/NodeTemplatesModal.tsx @@ -263,7 +263,7 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => { onClick={() => router.push('/app/list')} gap={1} > - 去创建 + {t('common:create')} )} @@ -279,7 +279,7 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => { onClick={() => window.open(feConfigs.systemPluginCourseUrl)} gap={1} > - 贡献插件 + {t('common:plugin.contribute')} )} diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/SelectAppModal.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/SelectAppModal.tsx index b449f5431..368b0606a 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/SelectAppModal.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/SelectAppModal.tsx @@ -47,7 +47,7 @@ const SelectAppModal = ({ return ( { })} - + ); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx index 974c9dab4..5fd5a8f4f 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx @@ -25,6 +25,7 @@ import { connectionLineStyle, defaultEdgeOptions } from '../constants'; import { useContextSelector } from 'use-context-selector'; import { WorkflowContext } from '../context'; import { useWorkflow } from './hooks/useWorkflow'; +import { t } from 'i18next'; const NodeSimple = dynamic(() => import('./nodes/NodeSimple')); const nodeTypes: Record = { @@ -171,7 +172,7 @@ const FlowController = React.memo(function FlowController() { showInteractive={false} showFitView={false} > - + fitView()}> diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeCQNode.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeCQNode.tsx index 91830f2ba..e58209af8 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeCQNode.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeCQNode.tsx @@ -64,7 +64,7 @@ const NodeCQNode = ({ data, selected }: NodeProps) => { /> - 分类{i + 1} + {t('common:classification') + (i + 1)} diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx index c0ca1668c..16f5d784e 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeDatasetConcat.tsx @@ -203,7 +203,10 @@ function Reference({ /> ) => { - 字段名 + {t('common:item_name')} - 字段描述 - 必须 + {t('common:item_description')} + {t('common:required')} @@ -197,7 +197,7 @@ const NodeExtract = ({ data }: NodeProps) => { const newOutput: FlowNodeOutputItemType = { id: getNanoid(), key: data.key, - label: `提取结果-${data.desc}`, + label: `${t('common:extraction_results')}-${data.desc}`, valueType: WorkflowIOValueTypeEnum.string, type: FlowNodeOutputTypeEnum.static }; @@ -215,7 +215,7 @@ const NodeExtract = ({ data }: NodeProps) => { key: data.key, value: { ...output, - label: `提取结果-${data.desc}` + label: `${t('common:extraction_results')}-${data.desc}` } }); } else { diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx index ab450cf27..a4093f8f5 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx @@ -392,7 +392,7 @@ const ConditionSelect = ({ list={filterQuiredConditionList} value={condition} onchange={onSelect} - placeholder="选择条件" + placeholder={t('common:chose_condition')} /> ); }; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeLaf.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeLaf.tsx index 2763eb935..b8a3e907d 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeLaf.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeLaf.tsx @@ -92,7 +92,7 @@ const NodeLaf = (props: NodeProps) => { onError(err) { toast({ status: 'error', - title: getErrText(err, '获取Laf函数列表失败') + title: getErrText(err, t('common:get_laf_failed')) }); } } @@ -298,7 +298,7 @@ const ConfigLaf = () => { )} ) : ( - 系统未配置Laf环境 + {t('common:no_laf_env')} ); }; diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx index f1ceefed9..4db2cb178 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx @@ -443,7 +443,7 @@ const NodeIntro = React.memo(function NodeIntro({ // edit intro const { onOpenModal: onOpenIntroModal, EditModal: EditIntroModal } = useEditTextarea({ title: t('common:core.module.Edit intro'), - tip: '调整该模块会对工具调用时机有影响。\n你可以通过精确的描述该模块功能,引导模型进行工具调用。', + tip: t('common:info.node_info'), canEmpty: false }); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx index 78a3a3728..056d22422 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/EditFieldModal.tsx @@ -85,7 +85,7 @@ const EditFieldModal = ({ ); return ( - + {t('common:common.Require Input')} @@ -111,7 +111,7 @@ const EditFieldModal = ({ required: true, pattern: { value: /^[a-zA-Z]+[0-9]*$/, - message: '字段key必须是纯英文字母或数字,并且不能以数字开头。' + message: t('common:info.felid_message') } })} /> diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx index d023e59da..cf6513739 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/RenderToolInput/index.tsx @@ -64,9 +64,9 @@ const RenderToolInput = ({ - - - + + + {dynamicInput && } diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/context.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/context.tsx index be812b1d4..41af938f0 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/context.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/context.tsx @@ -387,7 +387,7 @@ const WorkflowContextProvider = ({ if (input) { toast({ status: 'warning', - title: 'key 重复' + title: t('common:key_repetition') }); } else { updateObj.inputs.push(props.value); @@ -408,7 +408,7 @@ const WorkflowContextProvider = ({ if (output) { toast({ status: 'warning', - title: 'key 重复' + title: t('common:key_repetition') }); updateObj.outputs = node.data.outputs; } else { diff --git a/projects/app/src/pages/app/detail/components/constants.tsx b/projects/app/src/pages/app/detail/components/constants.tsx index fa25b22e6..b55d2c16d 100644 --- a/projects/app/src/pages/app/detail/components/constants.tsx +++ b/projects/app/src/pages/app/detail/components/constants.tsx @@ -1,5 +1,5 @@ import { BoxProps, FlexProps } from '@chakra-ui/react'; - +import { i18nT } from '@fastgpt/web/i18n/utils'; export const cardStyles: BoxProps = { borderRadius: 'lg', // overflow: 'hidden', @@ -20,11 +20,11 @@ export const workflowBoxStyles: FlexProps = { export const publishStatusStyle = { unPublish: { colorSchema: 'adora' as any, - text: '未发布' + text: i18nT('common:core.app.have_publish') }, published: { colorSchema: 'green' as any, - text: '已发布' + text: i18nT('common:core.app.not_published') } }; diff --git a/projects/app/src/pages/app/list/components/List.tsx b/projects/app/src/pages/app/list/components/List.tsx index ffde09776..eb59e51ad 100644 --- a/projects/app/src/pages/app/list/components/List.tsx +++ b/projects/app/src/pages/app/list/components/List.tsx @@ -215,7 +215,7 @@ const ListItem = () => { fontSize={'xs'} color={'myGray.500'} > - {app.intro || '还没写介绍~'} + {app.intro || t('common:common.no_intro')} { children: [ { icon: 'edit', - label: '编辑信息', + label: t('common:dataset.Edit Info'), onClick: () => { if (app.type === AppTypeEnum.httpPlugin) { setEditHttpPlugin({ @@ -383,14 +383,14 @@ const ListItem = () => { })} - {myApps.length === 0 && } + {myApps.length === 0 && } {!!editedApp && ( { setEditedApp(undefined); }} diff --git a/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx b/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx index b83b1d5e3..3772733d7 100644 --- a/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx +++ b/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx @@ -31,7 +31,7 @@ const CustomPluginRunBox = (props: PluginRunBoxProps) => { list={[ { label: t('common:common.Output'), value: PluginRunBoxTabEnum.output }, - { label: '完整结果', value: PluginRunBoxTabEnum.detail } + { label: t('common:common.all_result'), value: PluginRunBoxTabEnum.detail } ]} value={tab} onChange={setTab} @@ -52,7 +52,7 @@ const CustomPluginRunBox = (props: PluginRunBoxProps) => { list={[ { label: t('common:common.Input'), value: PluginRunBoxTabEnum.input }, { label: t('common:common.Output'), value: PluginRunBoxTabEnum.output }, - { label: '完整结果', value: PluginRunBoxTabEnum.detail } + { label: t('common:common.all_result'), value: PluginRunBoxTabEnum.detail } ]} value={tab} onChange={setTab} diff --git a/projects/app/src/pages/dataset/detail/components/Import/components/FileSelector.tsx b/projects/app/src/pages/dataset/detail/components/Import/components/FileSelector.tsx index a6a3f3df7..0c54d97f3 100644 --- a/projects/app/src/pages/dataset/detail/components/Import/components/FileSelector.tsx +++ b/projects/app/src/pages/dataset/detail/components/Import/components/FileSelector.tsx @@ -287,7 +287,7 @@ const FileSelector = ({ {isMaxSelected ? ( <> - 已达到最大文件数量 + {t('file:reached_max_file_count')} ) : ( diff --git a/projects/app/src/pages/dataset/detail/components/Test.tsx b/projects/app/src/pages/dataset/detail/components/Test.tsx index e3393a475..38aecbd9e 100644 --- a/projects/app/src/pages/dataset/detail/components/Test.tsx +++ b/projects/app/src/pages/dataset/detail/components/Test.tsx @@ -243,7 +243,7 @@ const Test = ({ datasetId }: { datasetId: string }) => { - 读取 CSV 文件第一列进行批量测试,单次最多支持 100 组数据。 + {t('common:info.csv_message')} { }); }} > - 点击下载批量测试模板 + {t('common:info.csv_download')} diff --git a/projects/app/src/pages/dataset/list/component/List.tsx b/projects/app/src/pages/dataset/list/component/List.tsx index 4d62a1f03..aaa4ce70e 100644 --- a/projects/app/src/pages/dataset/list/component/List.tsx +++ b/projects/app/src/pages/dataset/list/component/List.tsx @@ -154,7 +154,9 @@ function List() { label={ - {dataset.type === DatasetTypeEnum.folder ? '打开文件夹' : '打开知识库'} + {dataset.type === DatasetTypeEnum.folder + ? t('common.folder.Open folder') + : t('common.folder.open_dataset')} } diff --git a/projects/app/src/pages/login/components/ForgetPasswordForm.tsx b/projects/app/src/pages/login/components/ForgetPasswordForm.tsx index 1ac9ea7e0..234a91153 100644 --- a/projects/app/src/pages/login/components/ForgetPasswordForm.tsx +++ b/projects/app/src/pages/login/components/ForgetPasswordForm.tsx @@ -7,7 +7,7 @@ import { useSendCode } from '@/web/support/user/hooks/useSendCode'; import type { ResLogin } from '@/global/support/api/userRes.d'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { useSystemStore } from '@/web/common/system/useSystemStore'; - +import { useTranslation } from 'next-i18next'; interface Props { setPageType: Dispatch<`${LoginPageTypeEnum}`>; loginSuccess: (e: ResLogin) => void; @@ -22,6 +22,7 @@ interface RegisterType { const RegisterForm = ({ setPageType, loginSuccess }: Props) => { const { toast } = useToast(); + const { t } = useTranslation(); const { feConfigs } = useSystemStore(); const { register, @@ -58,12 +59,12 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { }) ); toast({ - title: `密码已找回`, + title: t('user:password.retrieved'), status: 'success' }); } catch (error: any) { toast({ - title: error.message || '修改密码异常', + title: error.message || t('user:password.change_error'), status: 'error' }); } @@ -75,7 +76,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { return ( <> - 找回 {feConfigs?.systemTitle} 账号 + {t('user:password.retrieved_account', { account: feConfigs?.systemTitle })} { @@ -110,9 +111,9 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { bg={'myGray.50'} flex={1} maxLength={8} - placeholder="验证码" + placeholder={t('user:password.verification_code')} {...register('code', { - required: '验证码不能为空' + required: t('user:password.code_required') })} > { @@ -155,9 +156,10 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { (getValues('password') === val ? true : '两次密码不一致') + validate: (val) => + getValues('password') === val ? true : t('user:password.not_match') })} > @@ -171,7 +173,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { isLoading={requesting} onClick={handleSubmit(onclickFindPassword)} > - 找回密码 + {t('user:password.retrieve')} { _hover={{ textDecoration: 'underline' }} onClick={() => setPageType(LoginPageTypeEnum.passwordLogin)} > - 去登录 + {t('user:password.to_login')} diff --git a/projects/app/src/pages/login/components/LoginForm/LoginForm.tsx b/projects/app/src/pages/login/components/LoginForm/LoginForm.tsx index 98ea8059c..7e2795031 100644 --- a/projects/app/src/pages/login/components/LoginForm/LoginForm.tsx +++ b/projects/app/src/pages/login/components/LoginForm/LoginForm.tsx @@ -43,12 +43,12 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => { }) ); toast({ - title: '登录成功', + title: t('user:login.success'), status: 'success' }); } catch (error: any) { toast({ - title: error.message || '登录异常', + title: error.message || t('user:login.error'), status: 'error' }); } @@ -101,7 +101,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => { required: true, maxLength: { value: 60, - message: '密码最多 60 位' + message: t('user:login.password_condition') } })} > diff --git a/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx b/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx index 6b79c2b27..4e84072bd 100644 --- a/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx +++ b/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx @@ -24,7 +24,7 @@ const WechatForm = ({ setPageType, loginSuccess }: Props) => { onError(err) { toast({ status: 'warning', - title: getErrText(err, '获取二维码失败') + title: getErrText(err, t('common:get_QR_failed')) }); } }); diff --git a/projects/app/src/pages/login/components/RegisterForm.tsx b/projects/app/src/pages/login/components/RegisterForm.tsx index d9c3edcfc..06a084e50 100644 --- a/projects/app/src/pages/login/components/RegisterForm.tsx +++ b/projects/app/src/pages/login/components/RegisterForm.tsx @@ -10,7 +10,6 @@ import { postCreateApp } from '@/web/core/app/api'; import { defaultAppTemplates } from '@/web/core/app/templates'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useTranslation } from 'next-i18next'; - interface Props { loginSuccess: (e: ResLogin) => void; setPageType: Dispatch<`${LoginPageTypeEnum}`>; @@ -26,6 +25,7 @@ interface RegisterType { const RegisterForm = ({ setPageType, loginSuccess }: Props) => { const { toast } = useToast(); const { t } = useTranslation(); + const { feConfigs } = useSystemStore(); const { register, @@ -63,7 +63,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { }) ); toast({ - title: `注册成功`, + title: t('user:register.success'), status: 'success' }); // auto register template app @@ -80,7 +80,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { }, 100); } catch (error: any) { toast({ - title: error.message || '注册异常', + title: error.message || t('user:register.error'), status: 'error' }); } @@ -92,7 +92,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { return ( <> - 注册 {feConfigs?.systemTitle} 账号 + {t('user:register.register_account', { account: feConfigs?.systemTitle })} { @@ -127,9 +127,9 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { bg={'myGray.50'} flex={1} maxLength={8} - placeholder="验证码" + placeholder={t('user:password.verification_code')} {...register('code', { - required: '验证码不能为空' + required: t('user:password.code_required') })} > { @@ -172,9 +172,10 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { (getValues('password') === val ? true : '两次密码不一致') + validate: (val) => + getValues('password') === val ? true : t('user:password.not_match') })} > @@ -187,7 +188,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => { isLoading={requesting} onClick={handleSubmit(onclickRegister)} > - 确认注册 + {t('user:register.confirm')} { _hover={{ textDecoration: 'underline' }} onClick={() => setPageType(LoginPageTypeEnum.passwordLogin)} > - 已有账号,去登录 + {t('user:register.to_login')} diff --git a/projects/app/src/pages/login/fastlogin.tsx b/projects/app/src/pages/login/fastlogin.tsx index d3c673026..796df7d66 100644 --- a/projects/app/src/pages/login/fastlogin.tsx +++ b/projects/app/src/pages/login/fastlogin.tsx @@ -9,7 +9,7 @@ import { useToast } from '@fastgpt/web/hooks/useToast'; import Loading from '@fastgpt/web/components/common/MyLoading'; import { serviceSideProps } from '@/web/common/utils/i18n'; import { getErrText } from '@fastgpt/global/common/error/utils'; - +import { useTranslation } from 'next-i18next'; const FastLogin = ({ code, token, @@ -23,7 +23,7 @@ const FastLogin = ({ const { setUserInfo } = useUserStore(); const router = useRouter(); const { toast } = useToast(); - + const { t } = useTranslation(); const loginSuccess = useCallback( (res: ResLogin) => { setToken(res.token); @@ -50,7 +50,7 @@ const FastLogin = ({ if (!res) { toast({ status: 'warning', - title: '登录异常' + title: t('common:support.user.login.error') }); return setTimeout(() => { router.replace('/login'); @@ -60,7 +60,7 @@ const FastLogin = ({ } catch (error) { toast({ status: 'warning', - title: getErrText(error, '登录异常') + title: getErrText(error, t('common:support.user.login.error')) }); setTimeout(() => { router.replace('/login'); diff --git a/projects/app/src/pages/login/index.tsx b/projects/app/src/pages/login/index.tsx index c57dbddf5..b78699e33 100644 --- a/projects/app/src/pages/login/index.tsx +++ b/projects/app/src/pages/login/index.tsx @@ -13,6 +13,7 @@ import { clearToken, setToken } from '@/web/support/user/auth'; import Script from 'next/script'; import Loading from '@fastgpt/web/components/common/MyLoading'; import { useMount } from 'ahooks'; +import { t } from 'i18next'; const RegisterForm = dynamic(() => import('./components/RegisterForm')); const ForgetPasswordForm = dynamic(() => import('./components/ForgetPasswordForm')); @@ -115,7 +116,7 @@ const Login = () => { textAlign={'center'} onClick={onOpen} > - 无法登录,点击联系 + {t('common:support.user.login.can_not_login')} )} diff --git a/projects/app/src/pages/login/provider.tsx b/projects/app/src/pages/login/provider.tsx index 7939b2bc3..eeca4618d 100644 --- a/projects/app/src/pages/login/provider.tsx +++ b/projects/app/src/pages/login/provider.tsx @@ -57,7 +57,7 @@ const provider = () => { if (!res) { toast({ status: 'warning', - title: '登录异常' + title: t('common:support.user.login.error') }); return setTimeout(() => { router.replace('/login'); @@ -67,7 +67,7 @@ const provider = () => { } catch (error) { toast({ status: 'warning', - title: getErrText(error, '登录异常') + title: getErrText(error, t('common:support.user.login.error')) }); setTimeout(() => { router.replace('/login'); @@ -95,7 +95,7 @@ const provider = () => { if (state !== loginStore?.state) { toast({ status: 'warning', - title: '安全校验失败' + title: t('common:support.user.login.security_failed') }); setTimeout(() => { router.replace('/login'); diff --git a/projects/app/src/pages/price/components/ExtraPlan.tsx b/projects/app/src/pages/price/components/ExtraPlan.tsx index a214fa0fb..16cbe3d8a 100644 --- a/projects/app/src/pages/price/components/ExtraPlan.tsx +++ b/projects/app/src/pages/price/components/ExtraPlan.tsx @@ -46,7 +46,7 @@ const ExtraPlan = () => { if (datasetSizePayAmount === 0) { return toast({ status: 'warning', - title: '购买数量不能为0' + title: t('common:support.wallet.amount_0') }); } setLoading(true); @@ -91,7 +91,7 @@ const ExtraPlan = () => { if (payAmount === 0) { return toast({ status: 'warning', - title: '购买数量不能为0' + title: t('common:support.wallet.amount_0') }); } setLoading(true); @@ -147,7 +147,7 @@ const ExtraPlan = () => { {t('common:support.wallet.subscription.Extra dataset size')} - ¥{extraDatasetPrice}/1000组{' '} + {`¥${extraDatasetPrice}/1000` + t('common:core.dataset.data.group')} /{t('common:common.month')} @@ -164,7 +164,7 @@ const ExtraPlan = () => { - 购买资源包 + {t('common:support.wallet.buy_resource')} @@ -252,7 +252,7 @@ const ExtraPlan = () => { {t('common:support.wallet.subscription.Extra ai points')} - ¥{extraPointsPrice}/1000积分{' '} + {`¥${extraDatasetPrice}/1000` + t('common:support.wallet.subscription.point')} /{t('common:common.month')} @@ -269,7 +269,7 @@ const ExtraPlan = () => { - 购买资源包 + {t('common:support.wallet.buy_resource')} {/* @@ -325,7 +325,7 @@ const ExtraPlan = () => { - 000积分 + {'000' + t('common:support.wallet.subscription.point')} diff --git a/projects/app/src/pages/price/components/FAQ.tsx b/projects/app/src/pages/price/components/FAQ.tsx index a634b47c5..d6b5d32f6 100644 --- a/projects/app/src/pages/price/components/FAQ.tsx +++ b/projects/app/src/pages/price/components/FAQ.tsx @@ -6,36 +6,36 @@ const FAQ = () => { const { t } = useTranslation(); const faqs = [ { - title: '订阅套餐会自动续费么?', - desc: '当前套餐过期后,系统会自动根据“未来套餐”进行续费,系统会尝试从账户余额进行扣费,如果您需要自动续费,请在账户余额中预留额度。' + title: t('common:FAQ.auto_renew_q'), + desc: t('common:FAQ.auto_renew_a') }, { - title: '能否切换订阅套餐?', - desc: '当前套餐价格大于新套餐时,无法立即切换,将会在当前套餐过期后以“续费”形式进行切换。\n当前套餐价格小于新套餐时,系统会自动计算当前套餐剩余余额,您可支付差价进行套餐切换。' + title: t('common:FAQ.change_package_q'), + desc: t('common:FAQ.change_package_a') }, { - title: '什么是AI积分?', - desc: '每次调用AI模型时,都会消耗一定的AI积分。具体的计算标准可参考上方的“AI 积分计算标准”。\nToken计算采用GPT3.5相同公式,1Token≈0.7中文字符≈0.9英文单词,连续出现的字符可能被认为是1个Tokens。' + title: t('common:FAQ.ai_point_q'), + desc: t('common:FAQ.ai_point_a') }, { - title: 'AI积分会过期么?', - desc: '会过期。当前套餐过期后,AI积分将会清空,并更新为新套餐的AI积分。年度套餐的AI积分时长为1年,而不是每个月。' + title: t('common:FAQ.ai_point_expire_q'), + desc: t('common:FAQ.ai_point_expire_a') }, { - title: '知识库存储怎么计算?', - desc: '1条知识库存储等于1条知识库索引。一条知识库数据可以包含1条或多条知识库索引。增强训练中,1条数据会生成5条索引。' + title: t('common:FAQ.dataset_compute_q'), + desc: t('common:FAQ.dataset_compute_a') }, { - title: '知识库索引超出会删除么?', - desc: '不会。但知识库索引超出时,无法插入和更新知识库内容。' + title: t('common:FAQ.dataset_index_q'), + desc: t('common:FAQ.dataset_index_a') }, { - title: '额外资源包可以叠加么?', - desc: '可以的。每次购买的资源包都是独立的,在其有效期内将会叠加使用。AI积分会优先扣除最先过期的资源包。' + title: t('common:FAQ.package_overlay_q'), + desc: t('common:FAQ.package_overlay_a') }, { - title: '免费版数据会清除么?', - desc: '免费版用户(免费版且未购买额外套餐)30天无使用记录后,系统会自动清除账号下所有知识库内容。' + title: t('common:FAQ.free_user_clean_q'), + desc: t('common:FAQ.free_user_clean_a') } ]; diff --git a/projects/app/src/pages/price/components/Points.tsx b/projects/app/src/pages/price/components/Points.tsx index 2126566df..40dde8f52 100644 --- a/projects/app/src/pages/price/components/Points.tsx +++ b/projects/app/src/pages/price/components/Points.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { Box, Flex, Grid, Link } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; - import { useSystemStore } from '@/web/common/system/useSystemStore'; const Points = () => { @@ -19,7 +18,7 @@ const Points = () => { {t('common:support.wallet.subscription.Ai points')} - 点击查看在线 Tokens 计算器 + {t('common:support.wallet.subscription.token_compute')} { fontSize={'md'} fontWeight={'bold'} > - AI语言模型 + {t('common:support.wallet.subscription.ai_model')} {llmModelList?.map((item, i) => ( {item.name} - {item.charsPointsPrice}积分 / 1000 Tokens + + {item.charsPointsPrice + + t('common:support.wallet.subscription.point') + + ' / 1000 Tokens'} + ))} @@ -60,17 +63,21 @@ const Points = () => { > - 索引模型 + {t('common:core.ai.model.Vector Model')} - 文档索引 & 对话索引 + {t('common:core.ai.model.doc_index_and_dialog')} {vectorModelList?.map((item, i) => ( {item.name} - {item.charsPointsPrice}积分 / 1000 Tokens + + {item.charsPointsPrice + + t('common:support.wallet.subscription.point') + + ' / 1000 Tokens'} + ))} @@ -85,14 +92,19 @@ const Points = () => { > - 语音播放 + {t('common:core.app.TTS')} {audioSpeechModelList?.map((item, i) => ( {item.name} - {item.charsPointsPrice}积分 / 1000字符 + + {item.charsPointsPrice + + t('common:support.wallet.subscription.point') + + ' / 1000' + + t('common:unit.character')} + ))} @@ -107,13 +119,18 @@ const Points = () => { > - 语音输入 + {t('common:core.app.Whisper')} {whisperModel?.name} - {whisperModel?.charsPointsPrice}积分 / 分钟 + + {whisperModel?.charsPointsPrice + + t('common:support.wallet.subscription.point') + + ' / 1000' + + t('common:unit.minute')} + diff --git a/projects/app/src/pages/price/components/Standard.tsx b/projects/app/src/pages/price/components/Standard.tsx index 7035bb627..8969ac6fe 100644 --- a/projects/app/src/pages/price/components/Standard.tsx +++ b/projects/app/src/pages/price/components/Standard.tsx @@ -309,6 +309,7 @@ const ConfirmPayModal = ({ onConfirmPay }: ConfirmPayModalProps & { onClose: () => void; onConfirmPay: () => void }) => { const { t } = useTranslation(); + const [qrPayData, setQRPayData] = useState(); const formatPayPrice = Math.ceil(formatStorePrice2Read(payPrice)); @@ -340,16 +341,24 @@ const ConfirmPayModal = ({ > - 新套餐价格 - {formatStorePrice2Read(totalPrice)}元 + {t('common:pay.new_package_price')} + {t('common:pay.yuan', { amount: formatStorePrice2Read(totalPrice) })} - 旧套餐余额 - {Math.floor(formatStorePrice2Read(totalPrice - payPrice))}元 + {t('common:pay.old_package_price')} + + {t('common:pay.yuan', { + amount: Math.floor(formatStorePrice2Read(totalPrice - payPrice)) + })} + - 需支付 - {formatPayPrice}元 + {t('common:pay.balance_notice')} + + {t('common:pay.yuan', { + amount: formatPayPrice + })} + - 账号余额: + {t('common:pay.balance') + ': '} - {formatTeamBalance}元 + {t('common:pay.yuan', { + amount: formatTeamBalance + })} {teamBalance >= payPrice ? ( ) : ( )} diff --git a/projects/app/src/pages/tools/index.tsx b/projects/app/src/pages/tools/index.tsx index 5e64798df..7edaedc4b 100644 --- a/projects/app/src/pages/tools/index.tsx +++ b/projects/app/src/pages/tools/index.tsx @@ -15,14 +15,14 @@ const Tools = () => { const list = [ { icon: 'core/dataset/datasetLight', - label: '我的知识库', + label: t('common:core.dataset.My Dataset'), link: '/dataset/list' }, ...(feConfigs?.show_git ? [ { icon: 'common/gitLight', - label: 'GitHub 地址', + label: t('common:core.app.tool_label.github'), link: 'https://github.com/labring/FastGPT' } ] @@ -31,7 +31,7 @@ const Tools = () => { ? [ { icon: 'common/courseLight', - label: '使用文档', + label: t('common:core.app.tool_label.doc'), link: getDocPath('/docs/intro') } ] @@ -40,7 +40,7 @@ const Tools = () => { ? [ { icon: 'support/bill/priceLight', - label: '计费说明', + label: t('common:core.app.tool_label.price'), link: '/price' } ] diff --git a/projects/app/src/web/common/utils/i18n.ts b/projects/app/src/web/common/utils/i18n.ts index 9b4c81575..506ad74c6 100644 --- a/projects/app/src/web/common/utils/i18n.ts +++ b/projects/app/src/web/common/utils/i18n.ts @@ -18,7 +18,7 @@ export const langMap = { }; export const serviceSideProps = (content: any, ns: I18nNsType = []) => { - return serverSideTranslations(content.locale, ['common', ...ns], null, content.locales); + return serverSideTranslations(content.locale, ['common', 'error', ...ns], null, content.locales); }; export const getLng = (lng: string) => { diff --git a/projects/app/src/web/core/app/constants.ts b/projects/app/src/web/core/app/constants.ts index b93698e02..22423b839 100644 --- a/projects/app/src/web/core/app/constants.ts +++ b/projects/app/src/web/core/app/constants.ts @@ -3,10 +3,10 @@ import { AppDetailType } from '@fastgpt/global/core/app/type.d'; import type { FeishuType, OutLinkEditType } from '@fastgpt/global/support/outLink/type.d'; import { AppPermission } from '@fastgpt/global/support/permission/app/controller'; import { NullPermission } from '@fastgpt/global/support/permission/constant'; - +import { i18nT } from '@fastgpt/web/i18n/utils'; export const defaultApp: AppDetailType = { _id: '', - name: '应用加载中', + name: i18nT('common:core.app.loading'), type: AppTypeEnum.simple, avatar: '/icon/logo.svg', intro: '', diff --git a/projects/app/src/web/support/user/hooks/useSendCode.ts b/projects/app/src/web/support/user/hooks/useSendCode.ts index 10184ffc6..51522debb 100644 --- a/projects/app/src/web/support/user/hooks/useSendCode.ts +++ b/projects/app/src/web/support/user/hooks/useSendCode.ts @@ -4,7 +4,7 @@ import { UserAuthTypeEnum } from '@fastgpt/global/support/user/auth/constants'; import { useTranslation } from 'next-i18next'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; - +import { i18nT } from '@fastgpt/web/i18n/utils'; let timer: NodeJS.Timeout; export const useSendCode = () => { @@ -29,8 +29,8 @@ export const useSendCode = () => { }, 1000); }, { - successToast: '验证码已发送', - errorToast: '验证码发送异常', + successToast: i18nT('user:password.code_sended'), + errorToast: i18nT('user:password.code_send_error'), refreshDeps: [codeCountDown, feConfigs?.googleClientVerKey] } ); @@ -38,12 +38,12 @@ export const useSendCode = () => { const sendCodeText = useMemo(() => { if (codeSending) return t('common:support.user.auth.Sending Code'); if (codeCountDown >= 10) { - return `${codeCountDown}s后重新获取`; + return `${codeCountDown}${t('user:password.get_code_again')}`; } if (codeCountDown > 0) { - return `0${codeCountDown}s后重新获取`; + return `0${codeCountDown}${t('user:password.get_code_again')}`; } - return '获取验证码'; + return t('user:password.get_code'); }, [codeCountDown, codeSending, t]); return {
字段名字段描述必须{t('common:item_name')}{t('common:item_description')}{t('common:required')}