mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-01 11:58:38 +00:00
I18n Translations (#2267)
* rebase * i18n-1 * add error info i18n * fix * fix * refactor: 删除error.json * delete useI18n
This commit is contained in:
@@ -22,7 +22,7 @@ const CommunityModal = ({ onClose }: { onClose: () => void }) => {
|
||||
|
||||
<ModalFooter>
|
||||
<Button variant={'whiteBase'} onClick={onClose}>
|
||||
关闭
|
||||
{t('common:common.Close')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
|
@@ -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<PromptTemplateItem>();
|
||||
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<MyModal isOpen title={title} onClose={onClose} iconSrc="/imgs/modal/prompt.svg">
|
||||
<ModalBody h="100%" w={'600px'} maxW={'90vw'} overflowY={'auto'}>
|
||||
@@ -55,7 +55,7 @@ const PromptTemplate = ({
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
确认选择
|
||||
{t('common:confirm_choice')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
|
@@ -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 = ({
|
||||
/>
|
||||
</HStack>
|
||||
<Box mt={3} fontSize={'sm'} color={'myGray.500'} cursor={'pointer'} onClick={onEdit}>
|
||||
{intro || '暂无介绍'}
|
||||
{intro || t('common:not_yet_introduced')}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
@@ -135,7 +135,9 @@ const AIChatSettingsModal = ({
|
||||
<QuestionTip ml={1} label={t('common:core.module.template.AI support tool tip')} />
|
||||
</Box>
|
||||
<Box flex={1} ml={'10px'}>
|
||||
{selectedModel?.toolChoice || selectedModel?.functionCall ? '支持' : '不支持'}
|
||||
{selectedModel?.toolChoice || selectedModel?.functionCall
|
||||
? t('common:common.support')
|
||||
: t('common:common.not_support')}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex mt={8}>
|
||||
|
@@ -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<MultipleSelectProps['list']>([
|
||||
{
|
||||
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 = ({
|
||||
>
|
||||
<ModalBody>
|
||||
<Flex justifyContent={'space-between'} alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 80px'}>
|
||||
{' '}
|
||||
{t('common:core.app.schedule.Open schedule')}
|
||||
</FormLabel>
|
||||
<FormLabel flex={'0 0 80px'}>{t('common:core.app.schedule.Open schedule')}</FormLabel>
|
||||
<Switch
|
||||
isChecked={isOpenSchedule}
|
||||
onChange={(e) => {
|
||||
@@ -297,7 +308,7 @@ const ScheduledTriggerConfig = ({
|
||||
{isOpenSchedule && (
|
||||
<>
|
||||
<Flex alignItems={'center'} mt={5}>
|
||||
<FormLabel flex={'0 0 80px'}>执行时间</FormLabel>
|
||||
<FormLabel flex={'0 0 80px'}>{t('app:execute_time')}</FormLabel>
|
||||
<Box flex={'1 0 0'}>
|
||||
<MultipleRowSelect
|
||||
label={formatLabel}
|
||||
@@ -310,7 +321,7 @@ const ScheduledTriggerConfig = ({
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={5}>
|
||||
<FormLabel flex={'0 0 80px'}>时区</FormLabel>
|
||||
<FormLabel flex={'0 0 80px'}>{t('app:time_zone')}</FormLabel>
|
||||
<Box flex={'1 0 0'}>
|
||||
<TimezoneSelect
|
||||
value={timezone}
|
||||
|
@@ -6,12 +6,13 @@ import { ChatBoxContext } from '../Provider';
|
||||
import { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
const isLLMNode = (item: ChatHistoryItemResType) =>
|
||||
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
|
||||
|
@@ -175,28 +175,28 @@ const ResponseTags = ({
|
||||
{showDetail && (
|
||||
<Flex alignItems={'center'} mt={3} flexWrap={'wrap'} gap={2}>
|
||||
{quoteList.length > 0 && (
|
||||
<MyTooltip label="查看引用">
|
||||
<MyTooltip label={t('chat:view_citations')}>
|
||||
<MyTag
|
||||
colorSchema="blue"
|
||||
type="borderSolid"
|
||||
cursor={'pointer'}
|
||||
onClick={() => setQuoteModalData({ rawSearch: quoteList })}
|
||||
>
|
||||
{quoteList.length}条引用
|
||||
{t('chat:citations', { num: quoteList.length })}
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
{llmModuleAccount === 1 && (
|
||||
<>
|
||||
{historyPreviewLength > 0 && (
|
||||
<MyTooltip label={'点击查看上下文预览'}>
|
||||
<MyTooltip label={t('chat:click_contextual_preview')}>
|
||||
<MyTag
|
||||
colorSchema="green"
|
||||
cursor={'pointer'}
|
||||
type="borderSolid"
|
||||
onClick={onOpenContextModal}
|
||||
>
|
||||
{historyPreviewLength}条上下文
|
||||
{t('chat:contextual', { num: historyPreviewLength })}
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
@@ -204,12 +204,12 @@ const ResponseTags = ({
|
||||
)}
|
||||
{llmModuleAccount > 1 && (
|
||||
<MyTag type="borderSolid" colorSchema="blue">
|
||||
多组 AI 对话
|
||||
{t('chat:multiple_AI_conversations')}
|
||||
</MyTag>
|
||||
)}
|
||||
|
||||
{isPc && runningTime > 0 && (
|
||||
<MyTooltip label={'模块运行时间和'}>
|
||||
<MyTooltip label={t('chat:module_runtime_and')}>
|
||||
<MyTag colorSchema="purple" type="borderSolid" cursor={'default'}>
|
||||
{runningTime}s
|
||||
</MyTag>
|
||||
|
@@ -90,7 +90,7 @@ const SelectMarkCollection = ({
|
||||
})()
|
||||
)}
|
||||
</Grid>
|
||||
{datasets.length === 0 && <EmptyTip text={'这个目录已经没东西可选了~'}></EmptyTip>}
|
||||
{datasets.length === 0 && <EmptyTip text={t('chat:empty_directory')}></EmptyTip>}
|
||||
</ModalBody>
|
||||
</DatasetSelectModal>
|
||||
)}
|
||||
|
@@ -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`
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@@ -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;
|
||||
|
@@ -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 = () => {
|
||||
<Box border={'base'} rounded={'md'} bg={'myGray.25'}>
|
||||
<Box p={4} color={'myGray.900'}>
|
||||
<Box color={'myGray.900'} fontWeight={'bold'}>
|
||||
流输出
|
||||
{t('chat:stream_output')}
|
||||
</Box>
|
||||
{histories.length > 0 && histories[1]?.value.length > 0 ? (
|
||||
<Box mt={2}>
|
||||
@@ -46,7 +46,7 @@ const RenderOutput = () => {
|
||||
</Box>
|
||||
<Box border={'base'} mt={4} rounded={'md'} bg={'myGray.25'}>
|
||||
<Box p={4} color={'myGray.900'} fontWeight={'bold'}>
|
||||
<Box>插件输出</Box>
|
||||
<Box>{t('chat:plugins_output')}</Box>
|
||||
{histories.length > 0 && histories[1].responseData ? (
|
||||
<Markdown source={`~~~json\n${pluginOutputs}`} />
|
||||
) : null}
|
||||
|
@@ -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')}</>
|
||||
) : (
|
||||
<Box flex={'1 0 0'} h={'100%'} overflow={'auto'}>
|
||||
<ResponseBox useMobile={true} response={responseData} showDetail={true} />
|
||||
|
@@ -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<any>;
|
||||
@@ -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;
|
||||
|
@@ -119,7 +119,7 @@ const WholeResponseModal = ({
|
||||
title={
|
||||
<Flex alignItems={'center'}>
|
||||
{t('common:core.chat.response.Complete Response')}
|
||||
<QuestionTip ml={2} label={'从上到下,为各个模块的响应顺序'}></QuestionTip>
|
||||
<QuestionTip ml={2} label={t('chat:question_tip')}></QuestionTip>
|
||||
</Flex>
|
||||
}
|
||||
>
|
||||
|
@@ -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
|
||||
});
|
||||
|
||||
|
@@ -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')}
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
@@ -145,7 +145,7 @@ const LafAccountModal = ({
|
||||
});
|
||||
}}
|
||||
>
|
||||
已验证,点击取消绑定
|
||||
{t('common:has_verification')}
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
|
@@ -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);
|
||||
|
@@ -79,7 +79,13 @@ function AddMemberModal({ onClose }: AddModalPropsType) {
|
||||
});
|
||||
|
||||
return (
|
||||
<MyModal isOpen onClose={onClose} iconSrc="modal/AddClb" title="添加协作者" minW="800px">
|
||||
<MyModal
|
||||
isOpen
|
||||
onClose={onClose}
|
||||
iconSrc="modal/AddClb"
|
||||
title={t('user:team.add_collaborator')}
|
||||
minW="800px"
|
||||
>
|
||||
<ModalBody>
|
||||
<MyBox
|
||||
isLoading={loadingMembers}
|
||||
@@ -103,7 +109,7 @@ function AddMemberModal({ onClose }: AddModalPropsType) {
|
||||
<MyIcon name="common/searchLight" w="16px" color={'myGray.500'} />
|
||||
</InputLeftElement>
|
||||
<Input
|
||||
placeholder="搜索用户名"
|
||||
placeholder={t('user:search_user')}
|
||||
bgColor="myGray.50"
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
/>
|
||||
@@ -156,7 +162,9 @@ function AddMemberModal({ onClose }: AddModalPropsType) {
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex p="4" flexDirection="column">
|
||||
<Box>已选: {selectedMemberIdList.length}</Box>
|
||||
<Box>
|
||||
{t('user:has_chosen') + ': '}+ {selectedMemberIdList.length}
|
||||
</Box>
|
||||
<Flex flexDirection="column" mt="2">
|
||||
{selectedMemberIdList.map((tmbId) => {
|
||||
const member = filterMembers.find((v) => v.tmbId === tmbId);
|
||||
@@ -211,7 +219,7 @@ function AddMemberModal({ onClose }: AddModalPropsType) {
|
||||
onChange={(v) => setSelectedPermission(v)}
|
||||
/>
|
||||
<Button isLoading={isUpdating} ml="4" h={'32px'} onClick={onConfirm}>
|
||||
确认
|
||||
{t('common:common.Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</MyModal>
|
||||
|
@@ -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 (
|
||||
<MyModal isOpen onClose={onClose} minW="600px" title="管理协作者" iconSrc="common/settingLight">
|
||||
<MyModal
|
||||
isOpen
|
||||
onClose={onClose}
|
||||
minW="600px"
|
||||
title={t('user:team.manage_collaborators')}
|
||||
iconSrc="common/settingLight"
|
||||
>
|
||||
<ModalBody>
|
||||
<TableContainer borderRadius="md" minH="400px">
|
||||
<Table>
|
||||
<Thead bg="myGray.100">
|
||||
<Tr>
|
||||
<Th border="none">名称</Th>
|
||||
<Th border="none">权限</Th>
|
||||
<Th border="none">{t('user:name')}</Th>
|
||||
<Th border="none">{t('user:permissions')}</Th>
|
||||
<Th border="none" w={'40px'}>
|
||||
操作
|
||||
{t('user:operations')}
|
||||
</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
@@ -109,7 +116,7 @@ function ManageModal({ onClose }: ManageModalProps) {
|
||||
})}
|
||||
</Tbody>
|
||||
</Table>
|
||||
{collaboratorList?.length === 0 && <EmptyTip text={'暂无协作者'} />}
|
||||
{collaboratorList?.length === 0 && <EmptyTip text={t('user:team.no_collaborators')} />}
|
||||
</TableContainer>
|
||||
{loading && <Loading fixed={false} />}
|
||||
</ModalBody>
|
||||
|
@@ -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
|
||||
<MyIcon name="common/searchLight" w="16px" color={'myGray.500'} />
|
||||
</InputLeftElement>
|
||||
<Input
|
||||
placeholder="搜索用户名"
|
||||
placeholder={t('user:search_user')}
|
||||
fontSize="sm"
|
||||
bg={'myGray.50'}
|
||||
onChange={(e) => {
|
||||
@@ -120,7 +120,7 @@ function AddManagerModal({ onClose, onSuccess }: { onClose: () => void; onSucces
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex borderLeft="1px" borderColor="myGray.200" flexDirection="column" p="4">
|
||||
<Box mt={3}>已选: {selected.length} 个</Box>
|
||||
<Box mt={3}>{t('common:chosen') + ': ' + selected.length} </Box>
|
||||
<Box mt={5}>
|
||||
{selected.map((member) => {
|
||||
return (
|
||||
|
@@ -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')}
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
|
@@ -95,7 +95,7 @@ const TeamTagsAsync = ({ onClose }: { onClose: () => void }) => {
|
||||
<Box>
|
||||
<Box>{teamInfo?.teamName}</Box>
|
||||
<Box color={'myGray.500'} fontSize={'xs'} fontWeight={'normal'}>
|
||||
{'填写标签同步链接,点击同步按钮即可同步'}
|
||||
{t('user:synchronization.title')}
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
@@ -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={<RepeatIcon />}
|
||||
onClick={handleSubmit((data) => onclickTagAsync(data))}
|
||||
>
|
||||
立即同步
|
||||
{t('user:synchronization.button')}
|
||||
</Button>
|
||||
</Flex>
|
||||
</ModalBody>
|
||||
|
@@ -73,7 +73,7 @@ const QRCodePayModal = ({
|
||||
return (
|
||||
<MyModal isOpen title={t('common:user.Pay')} iconSrc="/imgs/modal/pay.svg">
|
||||
<ModalBody textAlign={'center'}>
|
||||
<Box mb={3}>请微信扫码支付: {readPrice}元,请勿关闭页面</Box>
|
||||
<Box mb={3}>{t('common:pay.wechat', { price: readPrice })}</Box>
|
||||
<Box id={'payQRCode'} display={'inline-block'} h={'128px'}></Box>
|
||||
</ModalBody>
|
||||
<ModalFooter />
|
||||
|
@@ -112,13 +112,13 @@ const StandardPlanContentList = ({
|
||||
{!!planContent.permissionReRank && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>检索结果重排</Box>
|
||||
<Box color={'myGray.600'}>{t('chat:rearrangement')}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
{!!planContent.permissionWebsiteSync && (
|
||||
<Flex alignItems={'center'}>
|
||||
<MyIcon name={'price/right'} w={'16px'} mr={3} />
|
||||
<Box color={'myGray.600'}>Web站点同步</Box>
|
||||
<Box color={'myGray.600'}>{t('chat:web_site_sync')}</Box>
|
||||
</Flex>
|
||||
)}
|
||||
</Grid>
|
||||
|
Reference in New Issue
Block a user