feat: Optimize i18n keys and remove unused keys, supporting static files in I18nT (#2092)

* feat: packages web i18n

* delete file

* feat:i18n add i18nT

* handle keys

* delete unusedKeys

* fix build

* update dev.md
This commit is contained in:
jingyang
2024-07-19 16:28:07 +08:00
committed by GitHub
parent f7b55b501f
commit 57ff38e16f
64 changed files with 552 additions and 1547 deletions

View File

@@ -86,11 +86,11 @@ const InputGuideConfig = ({
<Flex alignItems={'center'}>
<MyIcon name={'core/app/inputGuides'} mr={2} w={'20px'} />
<Flex alignItems={'center'}>
<FormLabel>{chatT('Input guide')}</FormLabel>
<FormLabel>{chatT('input_guide')}</FormLabel>
<ChatFunctionTip type={'inputGuide'} />
</Flex>
<Box flex={1} />
<MyTooltip label={chatT('Config input guide')}>
<MyTooltip label={chatT('config_input_guide')}>
<Button
variant={'transparentBase'}
iconSpacing={1}
@@ -102,7 +102,7 @@ const InputGuideConfig = ({
</Button>
</MyTooltip>
<MyModal
title={chatT('Input guide')}
title={chatT('input_guide')}
iconSrc="core/app/inputGuides"
isOpen={isOpen}
onClose={onClose}
@@ -124,7 +124,7 @@ const InputGuideConfig = ({
{isOpenQuestionGuide && (
<>
<Flex mt={8} alignItems={'center'}>
<FormLabel>{chatT('Input guide lexicon')}</FormLabel>
<FormLabel>{chatT('input_guide_lexicon')}</FormLabel>
<Box fontSize={'xs'} px={2} bg={'myGray.100'} ml={1} rounded={'full'}>
{total}
</Box>
@@ -137,12 +137,12 @@ const InputGuideConfig = ({
onOpenLexiconConfig();
}}
>
{chatT('Config input guide lexicon')}
{chatT('config_input_guide_lexicon')}
</Button>
</Flex>
<>
<Flex mt={8} alignItems={'center'}>
<FormLabel>{chatT('Custom input guide url')}</FormLabel>
<FormLabel>{chatT('custom_input_guide_url')}</FormLabel>
<Flex
onClick={() => window.open(getDocPath('/docs/course/chat_input_guide'))}
color={'primary.700'}
@@ -226,7 +226,7 @@ const LexiconConfigModal = ({ appId, onClose }: { appId: string; onClose: () =>
if (res.insertLength < textList.length) {
toast({
status: 'warning',
title: chatT('Insert input guide, Some data already exists', { len: res.insertLength })
title: chatT('insert_input_guide,_some_data_already_exists', { len: res.insertLength })
});
} else {
toast({
@@ -289,7 +289,7 @@ const LexiconConfigModal = ({ appId, onClose }: { appId: string; onClose: () =>
return (
<MyModal
title={chatT('Config input guide lexicon title')}
title={chatT('config_input_guide_lexicon_title')}
iconSrc="core/app/inputGuides"
isOpen={true}
onClose={onClose}
@@ -326,7 +326,7 @@ const LexiconConfigModal = ({ appId, onClose }: { appId: string; onClose: () =>
});
}}
>
<QuestionTip ml={-2} label={chatT('Csv input lexicon tip')} />
<QuestionTip ml={-2} label={chatT('csv_input_lexicon_tip')} />
</Box>
</Flex>
<Box px={8}>
@@ -364,7 +364,7 @@ const LexiconConfigModal = ({ appId, onClose }: { appId: string; onClose: () =>
<MyInput
autoFocus
rightIcon={<MyIcon name={'save'} w={'14px'} cursor={'pointer'} />}
placeholder={chatT('New input guide lexicon')}
placeholder={chatT('new_input_guide_lexicon')}
onBlur={(e) => {
createNewData([e.target.value.trim()]);
}}
@@ -381,7 +381,7 @@ const LexiconConfigModal = ({ appId, onClose }: { appId: string; onClose: () =>
px={8}
flex={'1 0 0'}
fontSize={'sm'}
EmptyChildren={<EmptyTip text={chatT('Chat input guide lexicon is empty')} />}
EmptyChildren={<EmptyTip text={chatT('chat_input_guide_lexicon_is_empty')} />}
>
{list.map((data, index) => {
const item = data.data;

View File

@@ -19,8 +19,8 @@ const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => {
const map = useRef({
[FnTypeEnum.inputGuide]: {
icon: '/imgs/app/inputGuide-icon.svg',
title: chatT('Input guide'),
desc: chatT('Input guide tip'),
title: chatT('input_guide'),
desc: chatT('input_guide_tip'),
imgUrl: '/imgs/app/inputGuide.svg'
},
[FnTypeEnum.nextQuestion]: {

View File

@@ -2,7 +2,7 @@ import { Box, Flex, Divider } from '@chakra-ui/react';
import React from 'react';
import { useTranslation } from 'next-i18next';
const CoseTooltip = ({ cost }: { cost?: number }) => {
const CostTooltip = ({ cost }: { cost?: number }) => {
const { t } = useTranslation();
return (
<>
@@ -21,4 +21,4 @@ const CoseTooltip = ({ cost }: { cost?: number }) => {
);
};
export default CoseTooltip;
export default CostTooltip;

View File

@@ -65,7 +65,7 @@ export default function InputGuideBox({
>
<Flex alignItems={'center'} fontSize={'sm'} color={'myGray.600'} gap={2} mb={2} px={2}>
<MyIcon name={'union'} />
<Box>{chatT('Input guide')}</Box>
<Box>{chatT('input_guide')}</Box>
</Flex>
{data.map((item, index) => (
<Flex

View File

@@ -31,7 +31,7 @@ const RawSourceBox = ({
return (
<MyTooltip
label={canPreview ? fileT('Click to view raw source') : ''}
label={canPreview ? fileT('click_to_view_raw_source') : ''}
shouldWrapChildren={false}
>
<Box

View File

@@ -334,13 +334,13 @@ function EditKeyModal({
<MyModal
isOpen={true}
iconSrc="/imgs/modal/key.svg"
title={isEdit ? publishT('Edit API Key') : publishT('Create API Key')}
title={isEdit ? publishT('edit_api_key') : publishT('create_api_key')}
>
<ModalBody>
<Flex alignItems={'center'}>
<FormLabel flex={'0 0 90px'}>{t('common:Name')}</FormLabel>
<Input
placeholder={publishT('key alias') || 'key alias'}
placeholder={publishT('key_alias') || 'key_alias'}
maxLength={20}
{...register('name', {
required: t('common:common.name_is_empty') || 'name_is_empty'

View File

@@ -8,7 +8,7 @@ const ApiKey = () => {
const { publishT } = useI18n();
return (
<Box px={[4, 8]} py={[4, 6]}>
<ApiKeyTable tips={publishT('key tips')}></ApiKeyTable>
<ApiKeyTable tips={publishT('key_tips')}></ApiKeyTable>
</Box>
);
};

View File

@@ -116,7 +116,7 @@ const Promotion = () => {
<Td>
{item.createTime ? dayjs(item.createTime).format('YYYY/MM/DD HH:mm:ss') : '-'}
</Td>
<Td>{t(`user.promotion.${item.type}`)}</Td>
<Td>{t(`user.promotion.${item.type}` as any)}</Td>
<Td>{item.amount}</Td>
</Tr>
))}

View File

@@ -538,7 +538,7 @@ const authHeaderRequest = async ({
canWrite: apiKeyCanWrite
};
} else {
// token auth
// token_auth
if (!appId) {
return Promise.reject('appId is empty');
}

View File

@@ -76,10 +76,10 @@ const Logs = () => {
{isPc && (
<>
<Box fontWeight={'bold'} fontSize={['md', 'lg']} mb={2}>
{appT('Chat logs')}
{appT('chat_logs')}
</Box>
<Box color={'myGray.500'} fontSize={'sm'}>
{appT('Chat Logs Tips')},{' '}
{appT('chat_logs_tips')},{' '}
<Box
as={'span'}
mr={2}
@@ -109,11 +109,11 @@ const Logs = () => {
<Thead>
<Tr>
<Th>{t('common:core.app.logs.Source And Time')}</Th>
<Th>{appT('Logs Title')}</Th>
<Th>{appT('Logs Message Total')}</Th>
<Th>{appT('Feedback Count')}</Th>
<Th>{appT('logs_title')}</Th>
<Th>{appT('logs_message_total')}</Th>
<Th>{appT('feedback_count')}</Th>
<Th>{t('common:core.app.feedback.Custom feedback')}</Th>
<Th>{appT('Mark Count')}</Th>
<Th>{appT('mark_count')}</Th>
</Tr>
</Thead>
<Tbody fontSize={'xs'}>
@@ -183,7 +183,7 @@ const Logs = () => {
))}
</Tbody>
</Table>
{logs.length === 0 && !isLoading && <EmptyTip text={appT('Logs Empty')}></EmptyTip>}
{logs.length === 0 && !isLoading && <EmptyTip text={appT('logs_empty')}></EmptyTip>}
</TableContainer>
<HStack w={'100%'} mt={3} justifyContent={'flex-end'}>

View File

@@ -6,7 +6,7 @@ import { useI18n } from '@/web/context/I18n';
const API = ({ appId }: { appId: string }) => {
const { publishT } = useI18n();
return <ApiKeyTable tips={publishT('app key tips')} appId={appId} />;
return <ApiKeyTable tips={publishT('app_key_tips')} appId={appId} />;
};
export default API;

View File

@@ -60,13 +60,13 @@ const FeiShuEditModal = ({
<MyModal
isOpen={true}
iconSrc="/imgs/modal/shareFill.svg"
title={isEdit ? publishT('Edit Link') : publishT('Create Link')}
title={isEdit ? publishT('edit_link') : publishT('create_link')}
>
<ModalBody>
<Flex alignItems={'center'}>
<Box flex={'0 0 90px'}>{t('common:Name')}</Box>
<Input
placeholder={publishT('Feishu name') || 'Link Name'} // TODO: i18n
placeholder={publishT('feishu_name') || 'link_name'} // TODO: i18n
maxLength={20}
{...register('name', {
required: t('common:common.name_is_empty') || 'name_is_empty'
@@ -76,7 +76,7 @@ const FeiShuEditModal = ({
<Flex alignItems={'center'} mt={4}>
<Flex flex={'0 0 90px'} alignItems={'center'}>
QPM
<QuestionTip ml={1} label={publishT('QPM Tips' || '')}></QuestionTip>
<QuestionTip ml={1} label={publishT('qpm_tips' || '')}></QuestionTip>
</Flex>
<Input
max={1000}
@@ -84,7 +84,7 @@ const FeiShuEditModal = ({
min: 0,
max: 1000,
valueAsNumber: true,
required: publishT('QPM is empty') || ''
required: publishT('qpm_is_empty') || ''
})}
/>
</Flex>
@@ -127,7 +127,7 @@ const FeiShuEditModal = ({
{/* TODO: i18n */}
</Flex>
<Input
placeholder={publishT('Default Response') || 'Link Name'}
placeholder={publishT('default_response') || 'link_name'}
maxLength={20}
{...register('defaultResponse', {
required: true
@@ -140,7 +140,7 @@ const FeiShuEditModal = ({
{/* TODO: i18n */}
</Flex>
<Input
placeholder={publishT('Default Response') || 'Link Name'}
placeholder={publishT('default_response') || 'link_name'}
maxLength={20}
{...register('immediateResponse', {
required: true
@@ -150,7 +150,7 @@ const FeiShuEditModal = ({
<Flex alignItems={'center'} mt={4}>
<Box flex={'0 0 90px'}>{t('common:core.module.http.AppId')}</Box>
<Input
placeholder={t('common:core.module.http.AppId') || 'Link Name'}
placeholder={t('common:core.module.http.AppId') || 'link_name'}
// maxLength={20}
{...register('app.appId', {
required: true

View File

@@ -299,13 +299,13 @@ function EditLinkModal({
<MyModal
isOpen={true}
iconSrc="/imgs/modal/shareFill.svg"
title={isEdit ? publishT('Edit Link') : publishT('Create Link')}
title={isEdit ? publishT('edit_link') : publishT('create_link')}
>
<ModalBody>
<Flex alignItems={'center'}>
<FormLabel flex={'0 0 90px'}>{t('common:Name')}</FormLabel>
<Input
placeholder={publishT('Link Name')}
placeholder={publishT('link_name')}
maxLength={20}
{...register('name', {
required: t('common:common.name_is_empty') || 'name_is_empty'
@@ -333,7 +333,7 @@ function EditLinkModal({
<Flex alignItems={'center'} mt={4}>
<Flex flex={'0 0 90px'} alignItems={'center'}>
<FormLabel>QPM</FormLabel>
<QuestionTip ml={1} label={publishT('QPM Tips' || '')}></QuestionTip>
<QuestionTip ml={1} label={publishT('qpm_tips' || '')}></QuestionTip>
</Flex>
<Input
max={1000}
@@ -341,7 +341,7 @@ function EditLinkModal({
min: 0,
max: 1000,
valueAsNumber: true,
required: publishT('QPM is empty') || ''
required: publishT('qpm_is_empty') || ''
})}
/>
</Flex>
@@ -365,11 +365,11 @@ function EditLinkModal({
<Flex alignItems={'center'} mt={4}>
<Flex flex={'0 0 90px'} alignItems={'center'}>
<FormLabel>{publishT('token auth')}</FormLabel>
<QuestionTip ml={1} label={publishT('token auth Tips') || ''}></QuestionTip>
<FormLabel>{publishT('token_auth')}</FormLabel>
<QuestionTip ml={1} label={publishT('token_auth_tips') || ''}></QuestionTip>
</Flex>
<Input
placeholder={publishT('token auth Tips') || ''}
placeholder={publishT('token_auth_tips') || ''}
fontSize={'sm'}
{...register('limit.hookUrl')}
/>
@@ -380,7 +380,7 @@ function EditLinkModal({
fontSize={'xs'}
color={'myGray.500'}
>
{publishT('token auth use cases')}
{publishT('token_auth_use_cases')}
</Link>
</>
)}

View File

@@ -130,7 +130,7 @@ const PublishHistoriesSlider = ({
});
}}
>
{appT('Current settings')}
{appT('current_settings')}
</Button>
<ScrollList isLoading={showLoading} flex={'1 0 0'} px={5}>
{list.map((data, index) => {

View File

@@ -28,16 +28,16 @@ const RouteTab = () => {
const tabList = useMemo(
() => [
{
label: appDetail.type === AppTypeEnum.plugin ? appT('Setting plugin') : appT('Setting app'),
label: appDetail.type === AppTypeEnum.plugin ? appT('setting_plugin') : appT('setting_app'),
id: TabEnum.appEdit
},
...(appDetail.permission.hasManagePer
? [
{
label: appT('Publish channel'),
label: appT('publish_channel'),
id: TabEnum.publish
},
{ label: appT('Chat logs'), id: TabEnum.logs }
{ label: appT('chat_logs'), id: TabEnum.logs }
]
: [])
],

View File

@@ -122,7 +122,7 @@ const AppCard = () => {
children: [
{
icon: 'core/app/type/workflow',
label: appT('Transition to workflow'),
label: appT('transition_to_workflow'),
onClick: () => setTransitionCreateNew(true)
},
...(appDetail.permission.hasWritePer && feConfigs?.show_team_chat
@@ -163,12 +163,12 @@ const AppCard = () => {
</Box>
{TeamTagsSet && <TagsEditModal onClose={() => setTeamTagsSet(undefined)} />}
{transitionCreateNew !== undefined && (
<MyModal isOpen title={appT('Transition to workflow')} iconSrc="core/app/type/workflow">
<MyModal isOpen title={appT('transition_to_workflow')} iconSrc="core/app/type/workflow">
<ModalBody>
<Box mb={3}>{appT('Transition to workflow create new tip')}</Box>
<Box mb={3}>{appT('transition_to_workflow_create_new_tip')}</Box>
<HStack cursor={'pointer'} onClick={() => setTransitionCreateNew((state) => !state)}>
<Checkbox isChecked={transitionCreateNew} />
<Box>{appT('Transition to workflow create new placeholder')}</Box>
<Box>{appT('transition_to_workflow_create_new_placeholder')}</Box>
</HStack>
</ModalBody>
<ModalFooter>

View File

@@ -36,7 +36,7 @@ const ChatTest = ({ appForm }: { appForm: AppSimpleEditFormType }) => {
<Flex position={'relative'} flexDirection={'column'} h={'100%'} py={4}>
<Flex px={[2, 5]}>
<Box fontSize={['md', 'lg']} fontWeight={'bold'} flex={1} color={'myGray.900'}>
{appT('Chat Debug')}
{appT('chat_debug')}
</Box>
<MyTooltip label={t('common:core.chat.Restart')}>
<IconButton

View File

@@ -125,7 +125,7 @@ const EditForm = ({
<Flex alignItems={'center'}>
<MyIcon name={'core/app/simpleMode/ai'} w={'20px'} />
<FormLabel ml={2} flex={1}>
{appT('AI Settings')}
{appT('ai_settings')}
</FormLabel>
</Flex>
<Flex alignItems={'center'} mt={5}>
@@ -264,8 +264,8 @@ const EditForm = ({
<Flex alignItems={'center'}>
<Flex alignItems={'center'} flex={1}>
<MyIcon name={'core/app/toolCall'} w={'20px'} />
<FormLabel ml={2}>{appT('Plugin dispatch')}</FormLabel>
<QuestionTip ml={1} label={appT('Plugin dispatch tip')} />
<FormLabel ml={2}>{appT('plugin_dispatch')}</FormLabel>
<QuestionTip ml={1} label={appT('plugin_dispatch_tip')} />
</Flex>
<Button
variant={'transparentBase'}

View File

@@ -45,7 +45,7 @@ import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { getAppFolderPath } from '@/web/core/app/api/app';
import FolderPath from '@/components/common/folder/Path';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import CoseTooltip from '@/components/core/app/plugin/CoseTooltip';
import CostTooltip from '@/components/core/app/plugin/CostTooltip';
import { useSystemStore } from '@/web/common/system/useSystemStore';
type Props = {
@@ -233,7 +233,7 @@ const RenderList = React.memo(function RenderList({
<Box mt={2} color={'myGray.500'}>
{t(item.intro as any) || t('common:core.workflow.Not intro')}
</Box>
{showCost && <CoseTooltip cost={item.currentCost} />}
{showCost && <CostTooltip cost={item.currentCost} />}
</Box>
}
>

View File

@@ -43,7 +43,7 @@ const AppCard = ({ showSaveStatus }: { showSaveStatus: boolean }) => {
null,
2
),
appT('Export Config Successful')
appT('export_config_successful')
);
}
}, [appDetail.chatConfig, appT, copyData, flowData2StoreDataAndCheck]);
@@ -80,7 +80,7 @@ const AppCard = ({ showSaveStatus }: { showSaveStatus: boolean }) => {
children: [
{
icon: 'edit',
label: appT('Edit info'),
label: appT('edit_info'),
onClick: onOpenInfoEdit
},
{
@@ -95,12 +95,12 @@ const AppCard = ({ showSaveStatus }: { showSaveStatus: boolean }) => {
{
children: [
{
label: appT('Import Configs'),
label: appT('import_configs'),
icon: 'common/importLight',
onClick: onOpenImport
},
{
label: appT('Export Configs'),
label: appT('export_configs'),
icon: 'export',
onClick: onExportWorkflow
}

View File

@@ -22,11 +22,11 @@ const ImportSettings = ({ onClose }: Props) => {
w={'600px'}
onClose={onClose}
iconSrc="/imgs/modal/params.svg"
title={appT('Import Configs')}
title={appT('import_configs')}
>
<ModalBody>
<Textarea
placeholder={appT('Paste Config')}
placeholder={appT('paste_config')}
defaultValue={value}
rows={16}
onChange={(e) => setValue(e.target.value)}
@@ -45,7 +45,7 @@ const ImportSettings = ({ onClose }: Props) => {
onClose();
} catch (error) {
toast({
title: appT('Import Configs Failed')
title: appT('import_configs_failed')
});
}
}}

View File

@@ -46,7 +46,7 @@ import { useWorkflowUtils } from './hooks/useUtils';
import { moduleTemplatesFlat } from '@fastgpt/global/core/workflow/template/constants';
import { cloneDeep } from 'lodash';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import CoseTooltip from '@/components/core/app/plugin/CoseTooltip';
import CostTooltip from '@/components/core/app/plugin/CostTooltip';
type ModuleTemplateListProps = {
isOpen: boolean;
@@ -456,7 +456,7 @@ const RenderList = React.memo(function RenderList({
<Box mt={2} color={'myGray.500'}>
{t(template.intro as any) || t('common:core.workflow.Not intro')}
</Box>
{isSystemPlugin && <CoseTooltip cost={template.currentCost} />}
{isSystemPlugin && <CostTooltip cost={template.currentCost} />}
</Box>
}
>

View File

@@ -191,7 +191,7 @@ const FieldEditModal = ({
if (!isEdit || isChangeKey) {
toast({
status: 'warning',
title: workflowT('Field Name already exists')
title: workflowT('field_name_already_exists')
});
return;
}
@@ -241,7 +241,7 @@ const FieldEditModal = ({
<MyModal
isOpen={true}
iconSrc="/imgs/workflow/extract.png"
title={isEdit ? workflowT('Edit input') : workflowT('Add new input')}
title={isEdit ? workflowT('edit_input') : workflowT('add_new_input')}
maxW={['90vw', '800px']}
w={'100%'}
>
@@ -271,11 +271,11 @@ const FieldEditModal = ({
</Flex>
<Box alignItems={'flex-start'}>
<FormLabel flex={'0 0 70px'} mb={'1px'}>
{workflowT('Field description')}
{workflowT('field_description')}
</FormLabel>
<Textarea
bg={'myGray.50'}
placeholder={workflowT('Field description placeholder')}
placeholder={workflowT('field_description_placeholder')}
rows={4}
{...register('description', { required: isToolInput ? true : false })}
/>
@@ -303,7 +303,7 @@ const FieldEditModal = ({
{showRequired && (
<Flex alignItems={'center'} minH={'40px'}>
<FormLabel flex={'1'}>{workflowT('Field required')}</FormLabel>
<FormLabel flex={'1'}>{workflowT('field_required')}</FormLabel>
<Switch {...register('required')} />
</Flex>
)}
@@ -312,7 +312,7 @@ const FieldEditModal = ({
{inputType === FlowNodeInputTypeEnum.reference && (
<>
<Flex alignItems={'center'} minH={'40px'}>
<FormLabel flex={'1'}>{workflowT('Field used as tool input')}</FormLabel>
<FormLabel flex={'1'}>{workflowT('field_used_as_tool_input')}</FormLabel>
<Switch
isChecked={isToolInput}
onChange={(e) => {
@@ -410,13 +410,13 @@ const FieldEditModal = ({
<Flex alignItems={'center'}>
<FormLabel flex={'0 0 70px'}>{t('common:core.module.Input Type')}</FormLabel>
<Box flex={1} fontWeight={'bold'}>
{workflowT('Only the Reference type is supported')}
{workflowT('only_the_reference_type_is_supported')}
</Box>
</Flex>
<Box>
<HStack mb={1}>
<FormLabel>{workflowT('Optional value type')}</FormLabel>
<QuestionTip label={workflowT('Optional value type tip')} />
<FormLabel>{workflowT('optional_value_type')}</FormLabel>
<QuestionTip label={workflowT('optional_value_type_tip')} />
</HStack>
<MultipleSelect<WorkflowIOValueTypeEnum>
list={valueTypeSelectList}

View File

@@ -71,7 +71,7 @@ const NodePluginInput = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
type: FlowNodeOutputTypeEnum.hidden
};
// Add new input
// add_new_input
onChangeNode({
nodeId,
type: 'addInput',

View File

@@ -112,7 +112,7 @@ function Reference({
const { workflowT } = useI18n();
const { ConfirmModal, openConfirm } = useConfirm({
type: 'delete',
content: workflowT('Confirm delete field tip')
content: workflowT('confirm_delete_field_tip')
});
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);

View File

@@ -27,7 +27,7 @@ const VariableTable = ({
{t('common:core.module.variable.variable name')}
</Th>
<Th>{t('common:core.workflow.Value type')}</Th>
{showToolColumn && <Th>{workflowT('Tool input')}</Th>}
{showToolColumn && <Th>{workflowT('tool_input')}</Th>}
<Th borderBottomRightRadius={'none !important'}></Th>
</Tr>
</Thead>

View File

@@ -90,7 +90,7 @@ const FieldModal = ({
if (!isEdit || isChangeKey) {
toast({
status: 'warning',
title: workflowT('Field Name already exists')
title: workflowT('field_name_already_exists')
});
return;
}
@@ -126,7 +126,7 @@ const FieldModal = ({
<MyModal
isOpen={true}
iconSrc="/imgs/workflow/extract.png"
title={isEdit ? workflowT('Edit input') : workflowT('Add new input')}
title={isEdit ? workflowT('edit_input') : workflowT('add_new_input')}
overflow={'unset'}
>
<ModalBody w={'100%'} overflow={'auto'} display={'flex'} flexDirection={['column', 'row']}>
@@ -161,7 +161,7 @@ const FieldModal = ({
</Flex>
{customInputConfig.showDescription && (
<Flex mt={3} alignItems={'center'}>
<FormLabel flex={'0 0 70px'}>{workflowT('Input description')}</FormLabel>
<FormLabel flex={'0 0 70px'}>{workflowT('input_description')}</FormLabel>
<Textarea bg={'myGray.50'} {...register('description', {})} />
</Flex>
)}

View File

@@ -58,7 +58,7 @@ const DynamicInputs = (props: RenderInputProps) => {
<Box borderBottom={'base'} pb={3}>
<HStack className="nodrag" cursor={'default'} position={'relative'}>
<HStack spacing={1} position={'relative'} fontWeight={'medium'} color={'myGray.600'}>
<Box>{item.label || workflowT('Custom input')}</Box>
<Box>{item.label || workflowT('custom_input')}</Box>
{item.description && <QuestionTip label={t(item.description as any)} />}
</HStack>
<Box flex={'1 0 0'} />
@@ -115,7 +115,7 @@ function Reference({
const { workflowT } = useI18n();
const { ConfirmModal, openConfirm } = useConfirm({
type: 'delete',
content: workflowT('Confirm delete field tip')
content: workflowT('confirm_delete_field_tip')
});
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);

View File

@@ -83,7 +83,7 @@ const FieldModal = ({
if (!isEdit || isChangeKey) {
toast({
status: 'warning',
title: workflowT('Field Name already exists')
title: workflowT('field_name_already_exists')
});
return;
}
@@ -120,7 +120,7 @@ const FieldModal = ({
<MyModal
isOpen={true}
iconSrc="/imgs/workflow/extract.png"
title={isEdit ? workflowT('Edit input') : workflowT('Add new input')}
title={isEdit ? workflowT('edit_input') : workflowT('add_new_input')}
overflow={'unset'}
>
<ModalBody w={'100%'} overflow={'auto'} display={'flex'} flexDirection={['column', 'row']}>
@@ -156,7 +156,7 @@ const FieldModal = ({
</Flex>
{customFieldConfig.showDescription && (
<Flex mt={3} alignItems={'center'}>
<FormLabel flex={'0 0 70px'}>{workflowT('Input description')}</FormLabel>
<FormLabel flex={'0 0 70px'}>{workflowT('input_description')}</FormLabel>
<Textarea bg={'myGray.50'} {...register('description', {})} />
</Flex>
)}

View File

@@ -163,12 +163,12 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => {
reloadAppLatestVersion();
},
{
successToast: appT('Publish success')
successToast: appT('publish_success')
}
);
const { openConfirm: openConfirmDel, ConfirmModal: ConfirmDelModal } = useConfirm({
content: appT('Confirm Del App Tip'),
content: appT('confirm_del_app_tip'),
type: 'delete'
});
const { runAsync: deleteApp } = useRequest2(

View File

@@ -95,14 +95,14 @@ const ListItem = () => {
);
const { openConfirm: openConfirmCopy, ConfirmModal: ConfirmCopyModal } = useConfirm({
content: appT('Confirm copy app tip')
content: appT('confirm_copy_app_tip')
});
const { runAsync: onclickCopy } = useRequest2(postCopyApp, {
onSuccess({ appId }) {
router.push(`/app/detail?appId=${appId}`);
loadMyApps();
},
successToast: appT('Create copy success')
successToast: appT('create_copy_success')
});
const { data: members = [] } = useRequest2(getTeamMembers, {
@@ -144,8 +144,8 @@ const ListItem = () => {
app.type === AppTypeEnum.folder
? t('common:common.folder.Open folder')
: app.permission.hasWritePer
? appT('Edit app')
: appT('Go to chat')
? appT('edit_app')
: appT('go_to_chat')
}
>
<MyBox
@@ -262,7 +262,7 @@ const ListItem = () => {
children: [
{
icon: 'core/chat/chatLight',
label: appT('Go to chat'),
label: appT('go_to_chat'),
onClick: () => {
router.push(`/chat?appId=${app._id}`);
}
@@ -277,7 +277,7 @@ const ListItem = () => {
children: [
{
icon: 'core/chat/chatLight',
label: appT('Go to run'),
label: appT('go_to_run'),
onClick: () => {
router.push(`/chat?appId=${app._id}`);
}
@@ -337,7 +337,7 @@ const ListItem = () => {
children: [
{
icon: 'copy',
label: appT('Copy one app'),
label: appT('copy_one_app'),
onClick: () =>
openConfirmCopy(() => onclickCopy({ appId: app._id }))()
}
@@ -358,8 +358,8 @@ const ListItem = () => {
() => onclickDelApp(app._id),
undefined,
app.type === AppTypeEnum.folder
? appT('Confirm delete folder tip')
: appT('Confirm Del App Tip')
? appT('confirm_delete_folder_tip')
: appT('confirm_del_app_tip')
)()
}
]

View File

@@ -157,7 +157,7 @@ const AppListContextProvider = ({ children }: { children: ReactNode }) => {
<MoveModal
moveResourceId={moveAppId}
server={getAppFolderList}
title={appT('Move app')}
title={appT('move_app')}
onClose={() => setMoveAppId(undefined)}
onConfirm={onMoveApp}
/>

View File

@@ -104,7 +104,7 @@ const MyApps = () => {
<Input
value={searchKey}
onChange={(e) => setSearchKey(e.target.value)}
placeholder={appT('Search app')}
placeholder={appT('search_app')}
maxLength={30}
bg={'white'}
/>
@@ -258,7 +258,7 @@ const MyApps = () => {
});
}}
onMove={() => setMoveAppId(folderDetail._id)}
deleteTip={appT('Confirm delete folder tip')}
deleteTip={appT('confirm_delete_folder_tip')}
onDelete={() => onDeleFolder(folderDetail._id)}
defaultPer={{
value: folderDetail.defaultPermission,

View File

@@ -129,7 +129,7 @@ const ChatHistorySlider = ({
whiteSpace={'nowrap'}
>
{isPc && (
<MyTooltip label={canRouteToDetail ? appT('App Detail') : ''} offset={[0, 0]}>
<MyTooltip label={canRouteToDetail ? appT('app_detail') : ''} offset={[0, 0]}>
<Flex
pt={5}
pb={2}

View File

@@ -184,7 +184,7 @@ const DataCard = () => {
...(collection.tags
? [
{
label: datasetT('Collection tags'),
label: datasetT('collection_tags'),
value: collection.tags?.join(', ') || '-'
}
]

View File

@@ -142,7 +142,7 @@ const Upload = () => {
)
);
},
errorToast: fileT('Upload failed')
errorToast: fileT('upload_failed')
});
return (

View File

@@ -132,7 +132,7 @@ const FileSelector = ({
files = files.slice(0, maxCount - selectFiles.length);
toast({
status: 'warning',
title: fileT('Some file count exceeds limit', { maxCount })
title: fileT('some_file_count_exceeds_limit', { maxCount })
});
}
// size check
@@ -144,7 +144,7 @@ const FileSelector = ({
if (filterFiles.length < files.length) {
toast({
status: 'warning',
title: fileT('Some file size exceeds limit', { maxSize: formatFileSize(maxSize) })
title: fileT('some_file_size_exceeds_limit', { maxSize: formatFileSize(maxSize) })
});
}
@@ -229,7 +229,7 @@ const FileSelector = ({
let isErr = files.some((item) => item.type === '');
if (isErr) {
return toast({
title: fileT('upload error description'),
title: fileT('upload_error_description'),
status: 'error'
});
}
@@ -245,7 +245,7 @@ const FileSelector = ({
);
} else {
return toast({
title: fileT('upload error description'),
title: fileT('upload_error_description'),
status: 'error'
});
}
@@ -293,18 +293,18 @@ const FileSelector = ({
<>
<Box fontWeight={'bold'}>
{isDragging
? fileT('Release the mouse to upload the file')
: fileT('Select and drag file tip')}
? fileT('release_the_mouse_to_upload_the_file')
: fileT('select_and_drag_file_tip')}
</Box>
{/* file type */}
<Box color={'myGray.500'} fontSize={'xs'}>
{fileT('Support file type', { fileType })}
{fileT('support_file_type', { fileType })}
</Box>
<Box color={'myGray.500'} fontSize={'xs'}>
{/* max count */}
{maxCount && fileT('Support max count', { maxCount })}
{maxCount && fileT('support_max_count', { maxCount })}
{/* max size */}
{maxSize && fileT('Support max size', { maxSize: formatFileSize(maxSize) })}
{maxSize && fileT('support_max_size', { maxSize: formatFileSize(maxSize) })}
</Box>
<File

View File

@@ -40,13 +40,13 @@ export const RenderUploadFiles = ({
<Thead draggable={false}>
<Tr bg={'myGray.100'} mb={2}>
<Th borderLeftRadius={'md'} borderBottom={'none'} py={4}>
{fileT('File Name')}
{fileT('file_name')}
</Th>
<Th borderBottom={'none'} py={4}>
{t('common:core.dataset.import.Upload file progress')}
</Th>
<Th borderBottom={'none'} py={4}>
{fileT('File Size')}
{fileT('file_size')}
</Th>
<Th borderRightRadius={'md'} borderBottom={'none'} py={4}>
{t('common:common.Action')}

View File

@@ -93,8 +93,8 @@ const CustomLinkInput = () => {
<Table bg={'white'}>
<Thead>
<Tr bg={'myGray.50'}>
<Th>{datasetT('External url')}</Th>
<Th>{datasetT('External id')}</Th>
<Th>{datasetT('external_url')}</Th>
<Th>{datasetT('external_id')}</Th>
<Th>{datasetT('filename')}</Th>
<Th></Th>
</Tr>

View File

@@ -66,7 +66,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
});
const { openConfirm: onOpenConfirmRebuild, ConfirmModal: ConfirmRebuildModal } = useConfirm({
title: t('common:common.confirm.Common Tip'),
content: datasetT('Confirm to rebuild embedding tip'),
content: datasetT('confirm_to_rebuild_embedding_tip'),
type: 'delete'
});
@@ -128,7 +128,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
refetchDatasetTraining();
loadDatasetDetail(datasetId);
},
successToast: datasetT('Rebuild embedding start tip'),
successToast: datasetT('rebuild_embedding_start_tip'),
errorToast: t('common:common.Update Failed')
});
@@ -152,7 +152,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
value={vectorModel.model}
disableTip={
rebuildingCount > 0 || trainingCount > 0
? datasetT('The knowledge base has indexes that are being trained or being rebuilt')
? datasetT('the_knowledge_base_has_indexes_that_are_being_trained_or_being_rebuilt')
: undefined
}
list={vectorModelList.map((item) => ({
@@ -209,8 +209,8 @@ const Info = ({ datasetId }: { datasetId: string }) => {
gap={1}
alignItems={'center'}
>
<Box>{datasetT('External read url')}</Box>
<QuestionTip label={datasetT('External read url tip')} />
<Box>{datasetT('external_read_url')}</Box>
<QuestionTip label={datasetT('external_read_url_tip')} />
</FormLabel>
<Input
flex={[1, '0 0 320px']}

View File

@@ -92,7 +92,7 @@ const Slider = ({ currentTab }: { currentTab: TabEnum }) => {
{rebuildingCount > 0 && (
<Box mb={3}>
<Box fontSize={'sm'}>
{datasetT('Rebuilding index count', { count: rebuildingCount })}
{datasetT('rebuilding_index_count', { count: rebuildingCount })}
</Box>
</Box>
)}

View File

@@ -125,22 +125,22 @@ const CreateModal = ({ onClose, parentId }: { onClose: () => void; parentId?: st
gridTemplateColumns={'repeat(1,1fr)'}
list={[
{
title: datasetT('Common Dataset'),
title: datasetT('common_dataset'),
value: DatasetTypeEnum.dataset,
icon: 'core/dataset/commonDataset',
desc: datasetT('Common Dataset Desc')
desc: datasetT('common_dataset_desc')
},
{
title: datasetT('Website Dataset'),
title: datasetT('website_dataset'),
value: DatasetTypeEnum.websiteDataset,
icon: 'core/dataset/websiteDataset',
desc: datasetT('Website Dataset Desc')
desc: datasetT('website_dataset_desc')
},
{
title: datasetT('External File'),
title: datasetT('external_file'),
value: DatasetTypeEnum.externalFile,
icon: 'core/dataset/externalDataset',
desc: datasetT('External file Dataset Desc')
desc: datasetT('external_file_dataset_desc')
}
]}
value={datasetType}

View File

@@ -32,7 +32,7 @@ export const useSelectFile = (props?: {
if (fileList.length > maxCount) {
toast({
status: 'warning',
title: fileT('Select file amount limit', { max: maxCount })
title: fileT('select_file_amount_limit', { max: maxCount })
});
fileList = fileList.slice(0, maxCount);
}

View File

@@ -11,6 +11,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '@fastgpt/global/core/workflow/node/constant';
import { i18nT } from '@fastgpt/web/i18n/utils';
type TemplateType = (AppItemType & {
avatar: string;
@@ -23,7 +24,7 @@ export const simpleBotTemplates: TemplateType = [
{
id: 'simpleChat',
avatar: 'core/workflow/template/aiChat',
name: '简易机器人',
name: i18nT('app:template.simple_robot'),
intro: '一个极其简单的 AI 应用,你可以绑定知识库或工具。',
type: AppTypeEnum.simple,
modules: [