refactor(i18n): use JSON with flattened key and namespace (#30114)

Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Stephen Zhou
2025-12-29 14:52:32 +08:00
committed by GitHub
parent 09be869f58
commit 6d0e36479b
2552 changed files with 111159 additions and 142972 deletions

View File

@ -46,31 +46,31 @@ type Props = {
batchId: string
documents?: FullDocumentDetail[]
indexingType?: string
retrievalMethod?: string
retrievalMethod?: RETRIEVE_METHOD
}
const RuleDetail: FC<{
sourceData?: ProcessRuleResponse
indexingType?: string
retrievalMethod?: string
retrievalMethod?: RETRIEVE_METHOD
}> = ({ sourceData, indexingType, retrievalMethod }) => {
const { t } = useTranslation()
const segmentationRuleMap = {
mode: t('datasetDocuments.embedding.mode'),
segmentLength: t('datasetDocuments.embedding.segmentLength'),
textCleaning: t('datasetDocuments.embedding.textCleaning'),
mode: t('embedding.mode', { ns: 'datasetDocuments' }),
segmentLength: t('embedding.segmentLength', { ns: 'datasetDocuments' }),
textCleaning: t('embedding.textCleaning', { ns: 'datasetDocuments' }),
}
const getRuleName = (key: string) => {
if (key === 'remove_extra_spaces')
return t('datasetCreation.stepTwo.removeExtraSpaces')
return t('stepTwo.removeExtraSpaces', { ns: 'datasetCreation' })
if (key === 'remove_urls_emails')
return t('datasetCreation.stepTwo.removeUrlEmails')
return t('stepTwo.removeUrlEmails', { ns: 'datasetCreation' })
if (key === 'remove_stopwords')
return t('datasetCreation.stepTwo.removeStopwords')
return t('stepTwo.removeStopwords', { ns: 'datasetCreation' })
}
const isNumber = (value: unknown) => {
@ -90,17 +90,17 @@ const RuleDetail: FC<{
value = !sourceData?.mode
? value
: sourceData.mode === ProcessMode.general
? (t('datasetDocuments.embedding.custom') as string)
: `${t('datasetDocuments.embedding.hierarchical')} · ${sourceData?.rules?.parent_mode === 'paragraph'
? t('dataset.parentMode.paragraph')
: t('dataset.parentMode.fullDoc')}`
? (t('embedding.custom', { ns: 'datasetDocuments' }) as string)
: `${t('embedding.hierarchical', { ns: 'datasetDocuments' })} · ${sourceData?.rules?.parent_mode === 'paragraph'
? t('parentMode.paragraph', { ns: 'dataset' })
: t('parentMode.fullDoc', { ns: 'dataset' })}`
break
case 'segmentLength':
value = !sourceData?.mode
? value
: sourceData.mode === ProcessMode.general
? maxTokens
: `${t('datasetDocuments.embedding.parentMaxTokens')} ${maxTokens}; ${t('datasetDocuments.embedding.childMaxTokens')} ${childMaxTokens}`
: `${t('embedding.parentMaxTokens', { ns: 'datasetDocuments' })} ${maxTokens}; ${t('embedding.childMaxTokens', { ns: 'datasetDocuments' })} ${childMaxTokens}`
break
default:
value = !sourceData?.mode
@ -124,8 +124,8 @@ const RuleDetail: FC<{
)
})}
<FieldInfo
label={t('datasetCreation.stepTwo.indexMode')}
displayedValue={t(`datasetCreation.stepTwo.${indexingType === IndexingType.ECONOMICAL ? 'economical' : 'qualified'}`) as string}
label={t('stepTwo.indexMode', { ns: 'datasetCreation' })}
displayedValue={t(`stepTwo.${indexingType === IndexingType.ECONOMICAL ? 'economical' : 'qualified'}`, { ns: 'datasetCreation' }) as string}
valueIcon={(
<Image
className="size-4"
@ -139,9 +139,9 @@ const RuleDetail: FC<{
)}
/>
<FieldInfo
label={t('datasetSettings.form.retrievalSetting.title')}
label={t('form.retrievalSetting.title', { ns: 'datasetSettings' })}
// displayedValue={t(`datasetSettings.form.retrievalSetting.${retrievalMethod}`) as string}
displayedValue={t(`dataset.retrieval.${indexingType === IndexingType.ECONOMICAL ? 'keyword_search' : retrievalMethod}.title` as any) as string}
displayedValue={t(`retrieval.${indexingType === IndexingType.ECONOMICAL ? 'keyword_search' : retrievalMethod ?? 'semantic_search'}.title`, { ns: 'dataset' })}
valueIcon={(
<Image
className="size-4"
@ -267,10 +267,10 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
{isEmbedding && (
<>
<RiLoader2Fill className="size-4 animate-spin" />
<span>{t('datasetDocuments.embedding.processing')}</span>
<span>{t('embedding.processing', { ns: 'datasetDocuments' })}</span>
</>
)}
{isEmbeddingCompleted && t('datasetDocuments.embedding.completed')}
{isEmbeddingCompleted && t('embedding.completed', { ns: 'datasetDocuments' })}
</div>
{
enableBilling && plan.type !== Plan.team && (
@ -279,7 +279,7 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
<ZapFast className="h-4 w-4 text-[#FB6514]" />
</div>
<div className="mx-3 grow text-[13px] font-medium text-gray-700">
{t('billing.plansCommon.documentProcessingPriorityUpgrade')}
{t('plansCommon.documentProcessingPriorityUpgrade', { ns: 'billing' })}
</div>
<UpgradeBtn loc="knowledge-speed-up" />
</div>
@ -372,7 +372,7 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
variant="primary"
onClick={navToDocumentList}
>
<span className="px-0.5">{t('datasetCreation.stepThree.navTo')}</span>
<span className="px-0.5">{t('stepThree.navTo', { ns: 'datasetCreation' })}</span>
<RiArrowRightLine className="size-4 stroke-current stroke-1" />
</Button>
</div>

View File

@ -32,11 +32,11 @@ const EmptyDatasetCreationModal = ({
const submit = async () => {
if (!inputValue) {
notify({ type: 'error', message: t('datasetCreation.stepOne.modal.nameNotEmpty') })
notify({ type: 'error', message: t('stepOne.modal.nameNotEmpty', { ns: 'datasetCreation' }) })
return
}
if (inputValue.length > 40) {
notify({ type: 'error', message: t('datasetCreation.stepOne.modal.nameLengthInvalid') })
notify({ type: 'error', message: t('stepOne.modal.nameLengthInvalid', { ns: 'datasetCreation' }) })
return
}
try {
@ -50,7 +50,7 @@ const EmptyDatasetCreationModal = ({
router.push(`/datasets/${dataset.id}/documents`)
}
catch {
notify({ type: 'error', message: t('datasetCreation.stepOne.modal.failed') })
notify({ type: 'error', message: t('stepOne.modal.failed', { ns: 'datasetCreation' }) })
}
}
@ -61,17 +61,17 @@ const EmptyDatasetCreationModal = ({
className={cn(s.modal, '!max-w-[520px]', 'px-8')}
>
<div className={s.modalHeader}>
<div className={s.title}>{t('datasetCreation.stepOne.modal.title')}</div>
<div className={s.title}>{t('stepOne.modal.title', { ns: 'datasetCreation' })}</div>
<span className={s.close} onClick={onHide} />
</div>
<div className={s.tip}>{t('datasetCreation.stepOne.modal.tip')}</div>
<div className={s.tip}>{t('stepOne.modal.tip', { ns: 'datasetCreation' })}</div>
<div className={s.form}>
<div className={s.label}>{t('datasetCreation.stepOne.modal.input')}</div>
<Input value={inputValue} placeholder={t('datasetCreation.stepOne.modal.placeholder') || ''} onChange={e => setInputValue(e.target.value)} />
<div className={s.label}>{t('stepOne.modal.input', { ns: 'datasetCreation' })}</div>
<Input value={inputValue} placeholder={t('stepOne.modal.placeholder', { ns: 'datasetCreation' }) || ''} onChange={e => setInputValue(e.target.value)} />
</div>
<div className="flex flex-row-reverse">
<Button className="ml-2 w-24" variant="primary" onClick={submit}>{t('datasetCreation.stepOne.modal.confirmButton')}</Button>
<Button className="w-24" onClick={onHide}>{t('datasetCreation.stepOne.modal.cancelButton')}</Button>
<Button className="ml-2 w-24" variant="primary" onClick={submit}>{t('stepOne.modal.confirmButton', { ns: 'datasetCreation' })}</Button>
<Button className="w-24" onClick={onHide}>{t('stepOne.modal.cancelButton', { ns: 'datasetCreation' })}</Button>
</div>
</Modal>
)

View File

@ -49,7 +49,7 @@ const FilePreview = ({
<div className={cn(s.filePreview, 'h-full')}>
<div className={cn(s.previewHeader)}>
<div className={cn(s.title, 'title-md-semi-bold')}>
<span>{t('datasetCreation.stepOne.filePreview')}</span>
<span>{t('stepOne.filePreview', { ns: 'datasetCreation' })}</span>
<div className="flex h-6 w-6 cursor-pointer items-center justify-center" onClick={hidePreview}>
<XMarkIcon className="h-4 w-4"></XMarkIcon>
</div>

View File

@ -96,11 +96,11 @@ const FileUploader = ({
const ext = `.${getFileType(file)}`
const isValidType = ACCEPTS.includes(ext.toLowerCase())
if (!isValidType)
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.typeError') })
notify({ type: 'error', message: t('stepOne.uploader.validation.typeError', { ns: 'datasetCreation' }) })
const isValidSize = size <= fileUploadConfig.file_size_limit * 1024 * 1024
if (!isValidSize)
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.size', { size: fileUploadConfig.file_size_limit }) })
notify({ type: 'error', message: t('stepOne.uploader.validation.size', { ns: 'datasetCreation', size: fileUploadConfig.file_size_limit }) })
return isValidType && isValidSize
}, [fileUploadConfig, notify, t, ACCEPTS])
@ -132,7 +132,7 @@ const FileUploader = ({
return Promise.resolve({ ...completeFile })
})
.catch((e) => {
const errorMessage = getFileUploadErrorMessage(e, t('datasetCreation.stepOne.uploader.failed'), t as any)
const errorMessage = getFileUploadErrorMessage(e, t('stepOne.uploader.failed', { ns: 'datasetCreation' }), t)
notify({ type: 'error', message: errorMessage })
onFileUpdate(fileItem, -2, fileListRef.current)
return Promise.resolve({ ...fileItem })
@ -168,7 +168,7 @@ const FileUploader = ({
return false
if (files.length + fileList.length > filesCountLimit && !IS_CE_EDITION) {
notify({ type: 'error', message: t('datasetCreation.stepOne.uploader.validation.filesNumber', { filesNumber: filesCountLimit }) })
notify({ type: 'error', message: t('stepOne.uploader.validation.filesNumber', { ns: 'datasetCreation', filesNumber: filesCountLimit }) })
return false
}
@ -313,7 +313,7 @@ const FileUploader = ({
/>
)}
<div className={cn('mb-1 text-sm font-semibold leading-6 text-text-secondary', titleClassName)}>{t('datasetCreation.stepOne.uploader.title')}</div>
<div className={cn('mb-1 text-sm font-semibold leading-6 text-text-secondary', titleClassName)}>{t('stepOne.uploader.title', { ns: 'datasetCreation' })}</div>
{!hideUpload && (
<div ref={dropRef} className={cn('relative mb-2 box-border flex min-h-20 max-w-[640px] flex-col items-center justify-center gap-1 rounded-xl border border-dashed border-components-dropzone-border bg-components-dropzone-bg px-4 py-3 text-xs leading-4 text-text-tertiary', dragging && 'border-components-dropzone-border-accent bg-components-dropzone-bg-accent')}>
@ -321,14 +321,15 @@ const FileUploader = ({
<RiUploadCloud2Line className="mr-2 size-5" />
<span>
{supportBatchUpload ? t('datasetCreation.stepOne.uploader.button') : t('datasetCreation.stepOne.uploader.buttonSingleFile')}
{supportBatchUpload ? t('stepOne.uploader.button', { ns: 'datasetCreation' }) : t('stepOne.uploader.buttonSingleFile', { ns: 'datasetCreation' })}
{supportTypes.length > 0 && (
<label className="ml-1 cursor-pointer text-text-accent" onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.browse')}</label>
<label className="ml-1 cursor-pointer text-text-accent" onClick={selectHandle}>{t('stepOne.uploader.browse', { ns: 'datasetCreation' })}</label>
)}
</span>
</div>
<div>
{t('datasetCreation.stepOne.uploader.tip', {
{t('stepOne.uploader.tip', {
ns: 'datasetCreation',
size: fileUploadConfig.file_size_limit,
supportTypes: supportTypesShowNames,
batchCount: fileUploadConfig.batch_count_limit,

View File

@ -21,7 +21,10 @@ const IndexingTypeValues = {
// Mock react-i18next (handled by global mock in web/vitest.setup.ts but we override for custom messages)
vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string) => key,
t: (key: string, options?: { ns?: string }) => {
const prefix = options?.ns ? `${options.ns}.` : ''
return `${prefix}${key}`
},
}),
}))

View File

@ -1,6 +1,7 @@
'use client'
import type { NotionPage } from '@/models/common'
import type { CrawlOptions, CrawlResultItem, createDocumentResponse, FileItem } from '@/models/datasets'
import type { RETRIEVE_METHOD } from '@/types/app'
import { produce } from 'immer'
import * as React from 'react'
import { useCallback, useState } from 'react'
@ -43,7 +44,7 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
const [dataSourceType, setDataSourceType] = useState<DataSourceType>(DataSourceType.FILE)
const [step, setStep] = useState(1)
const [indexingTypeCache, setIndexTypeCache] = useState('')
const [retrievalMethodCache, setRetrievalMethodCache] = useState('')
const [retrievalMethodCache, setRetrievalMethodCache] = useState<RETRIEVE_METHOD | ''>('')
const [fileList, setFiles] = useState<FileItem[]>([])
const [result, setResult] = useState<createDocumentResponse | undefined>()
const [notionPages, setNotionPages] = useState<NotionPage[]>([])
@ -90,7 +91,7 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
setResult(res)
}, [])
const updateRetrievalMethodCache = useCallback((method: string) => {
const updateRetrievalMethodCache = useCallback((method: RETRIEVE_METHOD | '') => {
setRetrievalMethodCache(method)
}, [])
@ -103,7 +104,7 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
}, [step, setStep])
if (fetchingAuthedDataSourceListError)
return <AppUnavailable code={500} unknownReason={t('datasetCreation.error.unavailable') as string} />
return <AppUnavailable code={500} unknownReason={t('error.unavailable', { ns: 'datasetCreation' }) as string} />
return (
<div className="flex flex-col overflow-hidden bg-components-panel-bg" style={{ height: 'calc(100vh - 56px)' }}>
@ -166,7 +167,7 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
datasetId={datasetId}
datasetName={datasetDetail?.name}
indexingType={datasetDetail?.indexing_technique || indexingTypeCache}
retrievalMethod={datasetDetail?.retrieval_model_dict?.search_method || retrievalMethodCache}
retrievalMethod={datasetDetail?.retrieval_model_dict?.search_method || retrievalMethodCache || undefined}
creationCache={result}
/>
)}

View File

@ -51,7 +51,7 @@ const NotionPagePreview = ({
<div className={cn(s.filePreview, 'h-full')}>
<div className={cn(s.previewHeader)}>
<div className={cn(s.title, 'title-md-semi-bold')}>
<span>{t('datasetCreation.stepOne.pagePreview')}</span>
<span>{t('stepOne.pagePreview', { ns: 'datasetCreation' })}</span>
<div className="flex h-6 w-6 cursor-pointer items-center justify-center" onClick={hidePreview}>
<XMarkIcon className="h-4 w-4"></XMarkIcon>
</div>

View File

@ -171,7 +171,7 @@ const StepOne = ({
{
shouldShowDataSourceTypeList && (
<div className={cn(s.stepHeader, 'system-md-semibold text-text-secondary')}>
{t('datasetCreation.steps.one')}
{t('steps.one', { ns: 'datasetCreation' })}
</div>
)
}
@ -195,10 +195,10 @@ const StepOne = ({
>
<span className={cn(s.datasetIcon)} />
<span
title={t('datasetCreation.stepOne.dataSourceType.file')!}
title={t('stepOne.dataSourceType.file', { ns: 'datasetCreation' })!}
className="truncate"
>
{t('datasetCreation.stepOne.dataSourceType.file')}
{t('stepOne.dataSourceType.file', { ns: 'datasetCreation' })}
</span>
</div>
<div
@ -218,10 +218,10 @@ const StepOne = ({
>
<span className={cn(s.datasetIcon, s.notion)} />
<span
title={t('datasetCreation.stepOne.dataSourceType.notion')!}
title={t('stepOne.dataSourceType.notion', { ns: 'datasetCreation' })!}
className="truncate"
>
{t('datasetCreation.stepOne.dataSourceType.notion')}
{t('stepOne.dataSourceType.notion', { ns: 'datasetCreation' })}
</span>
</div>
{(ENABLE_WEBSITE_FIRECRAWL || ENABLE_WEBSITE_JINAREADER || ENABLE_WEBSITE_WATERCRAWL) && (
@ -242,10 +242,10 @@ const StepOne = ({
>
<span className={cn(s.datasetIcon, s.web)} />
<span
title={t('datasetCreation.stepOne.dataSourceType.web')!}
title={t('stepOne.dataSourceType.web', { ns: 'datasetCreation' })!}
className="truncate"
>
{t('datasetCreation.stepOne.dataSourceType.web')}
{t('stepOne.dataSourceType.web', { ns: 'datasetCreation' })}
</span>
</div>
)}
@ -271,7 +271,7 @@ const StepOne = ({
<div className="flex max-w-[640px] justify-end gap-2">
<Button disabled={nextDisabled} variant="primary" onClick={onStepChange}>
<span className="flex gap-0.5 px-[10px]">
<span className="px-0.5">{t('datasetCreation.stepOne.button')}</span>
<span className="px-0.5">{t('stepOne.button', { ns: 'datasetCreation' })}</span>
<RiArrowRightLine className="size-4" />
</span>
</Button>
@ -309,7 +309,7 @@ const StepOne = ({
<div className="flex max-w-[640px] justify-end gap-2">
<Button disabled={isShowVectorSpaceFull || !notionPages.length} variant="primary" onClick={onStepChange}>
<span className="flex gap-0.5 px-[10px]">
<span className="px-0.5">{t('datasetCreation.stepOne.button')}</span>
<span className="px-0.5">{t('stepOne.button', { ns: 'datasetCreation' })}</span>
<RiArrowRightLine className="size-4" />
</span>
</Button>
@ -340,7 +340,7 @@ const StepOne = ({
<div className="flex max-w-[640px] justify-end gap-2">
<Button disabled={isShowVectorSpaceFull || !websitePages.length} variant="primary" onClick={onStepChange}>
<span className="flex gap-0.5 px-[10px]">
<span className="px-0.5">{t('datasetCreation.stepOne.button')}</span>
<span className="px-0.5">{t('stepOne.button', { ns: 'datasetCreation' })}</span>
<RiArrowRightLine className="size-4" />
</span>
</Button>
@ -352,7 +352,7 @@ const StepOne = ({
<div className="my-8 h-px max-w-[640px] bg-divider-regular" />
<span className="inline-flex cursor-pointer items-center text-[13px] leading-4 text-text-accent" onClick={modalShowHandle}>
<RiFolder6Line className="mr-1 size-4" />
{t('datasetCreation.stepOne.emptyDatasetCreation')}
{t('stepOne.emptyDatasetCreation', { ns: 'datasetCreation' })}
</span>
</>
)}
@ -374,8 +374,8 @@ const StepOne = ({
<PlanUpgradeModal
show
onClose={hidePlanUpgradeModal}
title={t('billing.upgrade.uploadMultiplePages.title')!}
description={t('billing.upgrade.uploadMultiplePages.description')!}
title={t('upgrade.uploadMultiplePages.title', { ns: 'billing' })!}
description={t('upgrade.uploadMultiplePages.description', { ns: 'billing' })!}
/>
)}
</div>

View File

@ -17,14 +17,14 @@ const UpgradeCard: FC = () => {
return (
<div className="flex items-center justify-between rounded-xl border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg py-3 pl-4 pr-3.5 shadow-xs backdrop-blur-[5px] ">
<div>
<div className="title-md-semi-bold bg-[linear-gradient(92deg,_var(--components-input-border-active-prompt-1,_#0BA5EC)_0%,_var(--components-input-border-active-prompt-2,_#155AEF)_99.21%)] bg-clip-text text-transparent">{t('billing.upgrade.uploadMultipleFiles.title')}</div>
<div className="system-xs-regular text-text-tertiary">{t('billing.upgrade.uploadMultipleFiles.description')}</div>
<div className="title-md-semi-bold bg-[linear-gradient(92deg,_var(--components-input-border-active-prompt-1,_#0BA5EC)_0%,_var(--components-input-border-active-prompt-2,_#155AEF)_99.21%)] bg-clip-text text-transparent">{t('upgrade.uploadMultipleFiles.title', { ns: 'billing' })}</div>
<div className="system-xs-regular text-text-tertiary">{t('upgrade.uploadMultipleFiles.description', { ns: 'billing' })}</div>
</div>
<UpgradeBtn
size="custom"
isShort
className="ml-3 !h-8 !rounded-lg px-2"
labelKey="billing.triggerLimitModal.upgrade"
labelKey="triggerLimitModal.upgrade"
loc="upload-multiple-files"
onClick={handleUpgrade}
/>

View File

@ -1,5 +1,6 @@
import type { createDocumentResponse, FullDocumentDetail, IconInfo } from '@/models/datasets'
import { render, screen } from '@testing-library/react'
import { RETRIEVE_METHOD } from '@/types/app'
import StepThree from './index'
// Mock the EmbeddingProcess component since it has complex async logic
@ -321,7 +322,7 @@ describe('StepThree', () => {
describe('retrievalMethod prop', () => {
it('should pass retrievalMethod to EmbeddingProcess', () => {
// Arrange & Act
renderStepThree({ retrievalMethod: 'semantic_search' })
renderStepThree({ retrievalMethod: RETRIEVE_METHOD.semantic })
// Assert
expect(screen.getByTestId('ep-retrieval-method')).toHaveTextContent('semantic_search')

View File

@ -1,9 +1,10 @@
'use client'
import type { createDocumentResponse, FullDocumentDetail } from '@/models/datasets'
import type { RETRIEVE_METHOD } from '@/types/app'
import { RiBookOpenLine } from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
import Divider from '@/app/components/base/divider'
import { useDocLink } from '@/context/i18n'
@ -14,7 +15,7 @@ type StepThreeProps = {
datasetId?: string
datasetName?: string
indexingType?: string
retrievalMethod?: string
retrievalMethod?: RETRIEVE_METHOD
creationCache?: createDocumentResponse
}
@ -38,8 +39,8 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
{!datasetId && (
<>
<div className="flex flex-col gap-y-1 pb-3">
<div className="title-2xl-semi-bold text-text-primary">{t('datasetCreation.stepThree.creationTitle')}</div>
<div className="system-sm-regular text-text-tertiary">{t('datasetCreation.stepThree.creationContent')}</div>
<div className="title-2xl-semi-bold text-text-primary">{t('stepThree.creationTitle', { ns: 'datasetCreation' })}</div>
<div className="system-sm-regular text-text-tertiary">{t('stepThree.creationContent', { ns: 'datasetCreation' })}</div>
</div>
<div className="flex items-center gap-x-4">
<AppIcon
@ -52,7 +53,7 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
/>
<div className="flex grow flex-col gap-y-1">
<div className="system-sm-semibold flex h-6 items-center text-text-secondary">
{t('datasetCreation.stepThree.label')}
{t('stepThree.label', { ns: 'datasetCreation' })}
</div>
<div className="system-sm-regular w-full truncate rounded-lg bg-components-input-bg-normal p-2 text-components-input-text-filled">
<span className="px-1">{datasetName || creationCache?.dataset?.name}</span>
@ -64,8 +65,8 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
)}
{datasetId && (
<div className="flex flex-col gap-y-1 pb-3">
<div className="title-2xl-semi-bold text-text-primary">{t('datasetCreation.stepThree.additionTitle')}</div>
<div className="system-sm-regular text-text-tertiary">{`${t('datasetCreation.stepThree.additionP1')} ${datasetName || creationCache?.dataset?.name} ${t('datasetCreation.stepThree.additionP2')}`}</div>
<div className="title-2xl-semi-bold text-text-primary">{t('stepThree.additionTitle', { ns: 'datasetCreation' })}</div>
<div className="system-sm-regular text-text-tertiary">{`${t('stepThree.additionP1', { ns: 'datasetCreation' })} ${datasetName || creationCache?.dataset?.name} ${t('stepThree.additionP2', { ns: 'datasetCreation' })}`}</div>
</div>
)}
<EmbeddingProcess
@ -83,15 +84,15 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
<div className="flex size-10 items-center justify-center rounded-[10px] bg-components-card-bg shadow-lg">
<RiBookOpenLine className="size-5 text-text-accent" />
</div>
<div className="text-base font-semibold text-text-secondary">{t('datasetCreation.stepThree.sideTipTitle')}</div>
<div className="text-text-tertiary">{t('datasetCreation.stepThree.sideTipContent')}</div>
<div className="text-base font-semibold text-text-secondary">{t('stepThree.sideTipTitle', { ns: 'datasetCreation' })}</div>
<div className="text-text-tertiary">{t('stepThree.sideTipContent', { ns: 'datasetCreation' })}</div>
<a
href={docLink('/guides/knowledge-base/integrate-knowledge-within-application')}
target="_blank"
rel="noreferrer noopener"
className="system-sm-regular text-text-accent"
>
{t('datasetPipeline.addDocuments.stepThree.learnMore')}
{t('addDocuments.stepThree.learnMore', { ns: 'datasetPipeline' })}
</a>
</div>
</div>

View File

@ -88,7 +88,7 @@ type StepTwoProps = {
websiteCrawlJobId?: string
onStepChange?: (delta: number) => void
updateIndexingTypeCache?: (type: string) => void
updateRetrievalMethodCache?: (method: string) => void
updateRetrievalMethodCache?: (method: RETRIEVE_METHOD | '') => void
updateResultCache?: (res: createDocumentResponse) => void
onSave?: () => void
onCancel?: () => void
@ -328,13 +328,13 @@ const StepTwo = ({
const getRuleName = (key: string) => {
if (key === 'remove_extra_spaces')
return t('datasetCreation.stepTwo.removeExtraSpaces')
return t('stepTwo.removeExtraSpaces', { ns: 'datasetCreation' })
if (key === 'remove_urls_emails')
return t('datasetCreation.stepTwo.removeUrlEmails')
return t('stepTwo.removeUrlEmails', { ns: 'datasetCreation' })
if (key === 'remove_stopwords')
return t('datasetCreation.stepTwo.removeStopwords')
return t('stepTwo.removeStopwords', { ns: 'datasetCreation' })
}
const ruleChangeHandle = (id: string) => {
const newRules = rules.map((rule) => {
@ -360,7 +360,7 @@ const StepTwo = ({
const updatePreview = () => {
if (segmentationType === ProcessMode.general && maxChunkLength > MAXIMUM_CHUNK_TOKEN_LENGTH) {
Toast.notify({ type: 'error', message: t('datasetCreation.stepTwo.maxLengthCheck', { limit: MAXIMUM_CHUNK_TOKEN_LENGTH }) })
Toast.notify({ type: 'error', message: t('stepTwo.maxLengthCheck', { ns: 'datasetCreation', limit: MAXIMUM_CHUNK_TOKEN_LENGTH }) })
return
}
fetchEstimate()
@ -415,11 +415,11 @@ const StepTwo = ({
const getCreationParams = () => {
let params
if (segmentationType === ProcessMode.general && overlap > maxChunkLength) {
Toast.notify({ type: 'error', message: t('datasetCreation.stepTwo.overlapCheck') })
Toast.notify({ type: 'error', message: t('stepTwo.overlapCheck', { ns: 'datasetCreation' }) })
return
}
if (segmentationType === ProcessMode.general && maxChunkLength > limitMaxChunkLength) {
Toast.notify({ type: 'error', message: t('datasetCreation.stepTwo.maxLengthCheck', { limit: limitMaxChunkLength }) })
Toast.notify({ type: 'error', message: t('stepTwo.maxLengthCheck', { ns: 'datasetCreation', limit: limitMaxChunkLength }) })
return
}
if (isSetting) {
@ -439,7 +439,7 @@ const StepTwo = ({
if (indexMethod === IndexingType.QUALIFIED && (!embeddingModel.model || !embeddingModel.provider)) {
Toast.notify({
type: 'error',
message: t('appDebug.datasetConfig.embeddingModelRequired'),
message: t('datasetConfig.embeddingModelRequired', { ns: 'appDebug' }),
})
return
}
@ -450,7 +450,7 @@ const StepTwo = ({
indexMethod: indexMethod as string,
})
) {
Toast.notify({ type: 'error', message: t('appDebug.datasetConfig.rerankModelRequired') })
Toast.notify({ type: 'error', message: t('datasetConfig.rerankModelRequired', { ns: 'appDebug' }) })
return
}
params = {
@ -552,7 +552,7 @@ const StepTwo = ({
onSuccess(data) {
updateIndexingTypeCache?.(indexType as string)
updateResultCache?.(data)
updateRetrievalMethodCache?.(retrievalConfig.search_method as string)
updateRetrievalMethodCache?.(retrievalConfig.search_method as RETRIEVE_METHOD)
},
},
)
@ -562,7 +562,7 @@ const StepTwo = ({
onSuccess(data) {
updateIndexingTypeCache?.(indexType as string)
updateResultCache?.(data)
updateRetrievalMethodCache?.(retrievalConfig.search_method as string)
updateRetrievalMethodCache?.(retrievalConfig.search_method as RETRIEVE_METHOD)
},
})
}
@ -616,17 +616,17 @@ const StepTwo = ({
return (
<div className="flex h-full w-full">
<div className={cn('relative h-full w-1/2 overflow-y-auto py-6', isMobile ? 'px-4' : 'px-12')}>
<div className="system-md-semibold mb-1 text-text-secondary">{t('datasetCreation.stepTwo.segmentation')}</div>
<div className="system-md-semibold mb-1 text-text-secondary">{t('stepTwo.segmentation', { ns: 'datasetCreation' })}</div>
{((isInUpload && [ChunkingMode.text, ChunkingMode.qa].includes(currentDataset!.doc_form))
|| isUploadInEmptyDataset
|| isInInit)
&& (
<OptionCard
className="mb-2 bg-background-section"
title={t('datasetCreation.stepTwo.general')}
icon={<Image width={20} height={20} src={SettingCog} alt={t('datasetCreation.stepTwo.general')} />}
title={t('stepTwo.general', { ns: 'datasetCreation' })}
icon={<Image width={20} height={20} src={SettingCog} alt={t('stepTwo.general', { ns: 'datasetCreation' })} />}
activeHeaderClassName="bg-dataset-option-card-blue-gradient"
description={t('datasetCreation.stepTwo.generalTip')}
description={t('stepTwo.generalTip', { ns: 'datasetCreation' })}
isActive={
[ChunkingMode.text, ChunkingMode.qa].includes(currentDocForm)
}
@ -636,10 +636,10 @@ const StepTwo = ({
<>
<Button variant="secondary-accent" onClick={() => updatePreview()}>
<RiSearchEyeLine className="mr-0.5 h-4 w-4" />
{t('datasetCreation.stepTwo.previewChunk')}
{t('stepTwo.previewChunk', { ns: 'datasetCreation' })}
</Button>
<Button variant="ghost" onClick={resetRules}>
{t('datasetCreation.stepTwo.reset')}
{t('stepTwo.reset', { ns: 'datasetCreation' })}
</Button>
</>
)}
@ -666,7 +666,7 @@ const StepTwo = ({
<div className="flex w-full flex-col">
<div className="flex items-center gap-x-2">
<div className="inline-flex shrink-0">
<TextLabel>{t('datasetCreation.stepTwo.rules')}</TextLabel>
<TextLabel>{t('stepTwo.rules', { ns: 'datasetCreation' })}</TextLabel>
</div>
<Divider className="grow" bgStyle="gradient" />
</div>
@ -705,7 +705,7 @@ const StepTwo = ({
disabled={!!currentDataset?.doc_form}
/>
<label className="system-sm-regular ml-2 cursor-pointer text-text-secondary">
{t('datasetCreation.stepTwo.useQALanguage')}
{t('stepTwo.useQALanguage', { ns: 'datasetCreation' })}
</label>
</div>
<LanguageSelect
@ -713,7 +713,7 @@ const StepTwo = ({
onSelect={setDocLanguage}
disabled={currentDocForm !== ChunkingMode.qa}
/>
<Tooltip popupContent={t('datasetCreation.stepTwo.QATip')} />
<Tooltip popupContent={t('stepTwo.QATip', { ns: 'datasetCreation' })} />
</div>
{currentDocForm === ChunkingMode.qa && (
<div
@ -724,7 +724,7 @@ const StepTwo = ({
>
<RiAlertFill className="size-4 text-text-warning-secondary" />
<span className="system-xs-medium text-text-primary">
{t('datasetCreation.stepTwo.QATip')}
{t('stepTwo.QATip', { ns: 'datasetCreation' })}
</span>
</div>
)}
@ -743,22 +743,22 @@ const StepTwo = ({
)
&& (
<OptionCard
title={t('datasetCreation.stepTwo.parentChild')}
title={t('stepTwo.parentChild', { ns: 'datasetCreation' })}
icon={<ParentChildChunk className="h-[20px] w-[20px]" />}
effectImg={BlueEffect.src}
className="text-util-colors-blue-light-blue-light-500"
activeHeaderClassName="bg-dataset-option-card-blue-gradient"
description={t('datasetCreation.stepTwo.parentChildTip')}
description={t('stepTwo.parentChildTip', { ns: 'datasetCreation' })}
isActive={currentDocForm === ChunkingMode.parentChild}
onSwitched={() => handleChangeDocform(ChunkingMode.parentChild)}
actions={(
<>
<Button variant="secondary-accent" onClick={() => updatePreview()}>
<RiSearchEyeLine className="mr-0.5 h-4 w-4" />
{t('datasetCreation.stepTwo.previewChunk')}
{t('stepTwo.previewChunk', { ns: 'datasetCreation' })}
</Button>
<Button variant="ghost" onClick={resetRules}>
{t('datasetCreation.stepTwo.reset')}
{t('stepTwo.reset', { ns: 'datasetCreation' })}
</Button>
</>
)}
@ -768,15 +768,15 @@ const StepTwo = ({
<div>
<div className="flex items-center gap-x-2">
<div className="inline-flex shrink-0">
<TextLabel>{t('datasetCreation.stepTwo.parentChunkForContext')}</TextLabel>
<TextLabel>{t('stepTwo.parentChunkForContext', { ns: 'datasetCreation' })}</TextLabel>
</div>
<Divider className="grow" bgStyle="gradient" />
</div>
<RadioCard
className="mt-1"
icon={<Image src={Note} alt="" />}
title={t('datasetCreation.stepTwo.paragraph')}
description={t('datasetCreation.stepTwo.paragraphTip')}
title={t('stepTwo.paragraph', { ns: 'datasetCreation' })}
description={t('stepTwo.paragraphTip', { ns: 'datasetCreation' })}
isChosen={parentChildConfig.chunkForContext === 'paragraph'}
onChosen={() => setParentChildConfig(
{
@ -788,7 +788,7 @@ const StepTwo = ({
<div className="flex gap-3">
<DelimiterInput
value={parentChildConfig.parent.delimiter}
tooltip={t('datasetCreation.stepTwo.parentChildDelimiterTip')!}
tooltip={t('stepTwo.parentChildDelimiterTip', { ns: 'datasetCreation' })!}
onChange={e => setParentChildConfig({
...parentChildConfig,
parent: {
@ -814,8 +814,8 @@ const StepTwo = ({
<RadioCard
className="mt-2"
icon={<Image src={FileList} alt="" />}
title={t('datasetCreation.stepTwo.fullDoc')}
description={t('datasetCreation.stepTwo.fullDocTip')}
title={t('stepTwo.fullDoc', { ns: 'datasetCreation' })}
description={t('stepTwo.fullDocTip', { ns: 'datasetCreation' })}
onChosen={() => setParentChildConfig(
{
...parentChildConfig,
@ -829,14 +829,14 @@ const StepTwo = ({
<div>
<div className="flex items-center gap-x-2">
<div className="inline-flex shrink-0">
<TextLabel>{t('datasetCreation.stepTwo.childChunkForRetrieval')}</TextLabel>
<TextLabel>{t('stepTwo.childChunkForRetrieval', { ns: 'datasetCreation' })}</TextLabel>
</div>
<Divider className="grow" bgStyle="gradient" />
</div>
<div className="mt-1 flex gap-3">
<DelimiterInput
value={parentChildConfig.child.delimiter}
tooltip={t('datasetCreation.stepTwo.parentChildChunkDelimiterTip')!}
tooltip={t('stepTwo.parentChildChunkDelimiterTip', { ns: 'datasetCreation' })!}
onChange={e => setParentChildConfig({
...parentChildConfig,
child: {
@ -861,7 +861,7 @@ const StepTwo = ({
<div>
<div className="flex items-center gap-x-2">
<div className="inline-flex shrink-0">
<TextLabel>{t('datasetCreation.stepTwo.rules')}</TextLabel>
<TextLabel>{t('stepTwo.rules', { ns: 'datasetCreation' })}</TextLabel>
</div>
<Divider className="grow" bgStyle="gradient" />
</div>
@ -887,23 +887,23 @@ const StepTwo = ({
)
}
<Divider className="my-5" />
<div className="system-md-semibold mb-1 text-text-secondary">{t('datasetCreation.stepTwo.indexMode')}</div>
<div className="system-md-semibold mb-1 text-text-secondary">{t('stepTwo.indexMode', { ns: 'datasetCreation' })}</div>
<div className="flex items-center gap-2">
{(!hasSetIndexType || (hasSetIndexType && indexingType === IndexingType.QUALIFIED)) && (
<OptionCard
className="flex-1 self-stretch"
title={(
<div className="flex items-center">
{t('datasetCreation.stepTwo.qualified')}
{t('stepTwo.qualified', { ns: 'datasetCreation' })}
<Badge className={cn('ml-1 h-[18px]', (!hasSetIndexType && indexType === IndexingType.QUALIFIED) ? 'border-text-accent-secondary text-text-accent-secondary' : '')} uppercase>
{t('datasetCreation.stepTwo.recommend')}
{t('stepTwo.recommend', { ns: 'datasetCreation' })}
</Badge>
<span className="ml-auto">
{!hasSetIndexType && <span className={cn(s.radio)} />}
</span>
</div>
)}
description={t('datasetCreation.stepTwo.qualifiedTip')}
description={t('stepTwo.qualifiedTip', { ns: 'datasetCreation' })}
icon={<Image src={indexMethodIcon.high_quality} alt="" />}
isActive={!hasSetIndexType && indexType === IndexingType.QUALIFIED}
disabled={hasSetIndexType}
@ -918,10 +918,10 @@ const StepTwo = ({
<CustomDialog show={isQAConfirmDialogOpen} onClose={() => setIsQAConfirmDialogOpen(false)} className="w-[432px]">
<header className="mb-4 pt-6">
<h2 className="text-lg font-semibold text-text-primary">
{t('datasetCreation.stepTwo.qaSwitchHighQualityTipTitle')}
{t('stepTwo.qaSwitchHighQualityTipTitle', { ns: 'datasetCreation' })}
</h2>
<p className="mt-2 text-sm font-normal text-text-secondary">
{t('datasetCreation.stepTwo.qaSwitchHighQualityTipContent')}
{t('stepTwo.qaSwitchHighQualityTipContent', { ns: 'datasetCreation' })}
</p>
</header>
<div className="flex gap-2 pb-6">
@ -931,7 +931,7 @@ const StepTwo = ({
setIsQAConfirmDialogOpen(false)
}}
>
{t('datasetCreation.stepTwo.cancel')}
{t('stepTwo.cancel', { ns: 'datasetCreation' })}
</Button>
<Button
variant="primary"
@ -941,7 +941,7 @@ const StepTwo = ({
setDocForm(ChunkingMode.qa)
}}
>
{t('datasetCreation.stepTwo.switch')}
{t('stepTwo.switch', { ns: 'datasetCreation' })}
</Button>
</div>
</CustomDialog>
@ -950,8 +950,8 @@ const StepTwo = ({
<div className="rounded-lg border-components-panel-border bg-components-tooltip-bg p-3 text-xs font-medium text-text-secondary shadow-lg">
{
docForm === ChunkingMode.qa
? t('datasetCreation.stepTwo.notAvailableForQA')
: t('datasetCreation.stepTwo.notAvailableForParentChild')
? t('stepTwo.notAvailableForQA', { ns: 'datasetCreation' })
: t('stepTwo.notAvailableForParentChild', { ns: 'datasetCreation' })
}
</div>
)}
@ -962,8 +962,8 @@ const StepTwo = ({
>
<OptionCard
className="h-full"
title={t('datasetCreation.stepTwo.economical')}
description={t('datasetCreation.stepTwo.economicalTip')}
title={t('stepTwo.economical', { ns: 'datasetCreation' })}
description={t('stepTwo.economicalTip', { ns: 'datasetCreation' })}
icon={<Image src={indexMethodIcon.economical} alt="" />}
isActive={!hasSetIndexType && indexType === IndexingType.ECONOMICAL}
disabled={hasSetIndexType || docForm !== ChunkingMode.text}
@ -981,19 +981,19 @@ const StepTwo = ({
<div className="p-1">
<AlertTriangle className="size-4 text-text-warning-secondary" />
</div>
<span className="system-xs-medium text-text-primary">{t('datasetCreation.stepTwo.highQualityTip')}</span>
<span className="system-xs-medium text-text-primary">{t('stepTwo.highQualityTip', { ns: 'datasetCreation' })}</span>
</div>
)}
{hasSetIndexType && indexType === IndexingType.ECONOMICAL && (
<div className="system-xs-medium mt-2 text-text-tertiary">
{t('datasetCreation.stepTwo.indexSettingTip')}
<Link className="text-text-accent" href={`/datasets/${datasetId}/settings`}>{t('datasetCreation.stepTwo.datasetSettingLink')}</Link>
{t('stepTwo.indexSettingTip', { ns: 'datasetCreation' })}
<Link className="text-text-accent" href={`/datasets/${datasetId}/settings`}>{t('stepTwo.datasetSettingLink', { ns: 'datasetCreation' })}</Link>
</div>
)}
{/* Embedding model */}
{indexType === IndexingType.QUALIFIED && (
<div className="mt-5">
<div className={cn('system-md-semibold mb-1 text-text-secondary', datasetId && 'flex items-center justify-between')}>{t('datasetSettings.form.embeddingModel')}</div>
<div className={cn('system-md-semibold mb-1 text-text-secondary', datasetId && 'flex items-center justify-between')}>{t('form.embeddingModel', { ns: 'datasetSettings' })}</div>
<ModelSelector
readonly={isModelAndRetrievalConfigDisabled}
triggerClassName={isModelAndRetrievalConfigDisabled ? 'opacity-50' : ''}
@ -1005,8 +1005,8 @@ const StepTwo = ({
/>
{isModelAndRetrievalConfigDisabled && (
<div className="system-xs-medium mt-2 text-text-tertiary">
{t('datasetCreation.stepTwo.indexSettingTip')}
<Link className="text-text-accent" href={`/datasets/${datasetId}/settings`}>{t('datasetCreation.stepTwo.datasetSettingLink')}</Link>
{t('stepTwo.indexSettingTip', { ns: 'datasetCreation' })}
<Link className="text-text-accent" href={`/datasets/${datasetId}/settings`}>{t('stepTwo.datasetSettingLink', { ns: 'datasetCreation' })}</Link>
</div>
)}
</div>
@ -1017,7 +1017,7 @@ const StepTwo = ({
{!isModelAndRetrievalConfigDisabled
? (
<div className="mb-1">
<div className="system-md-semibold mb-0.5 text-text-secondary">{t('datasetSettings.form.retrievalSetting.title')}</div>
<div className="system-md-semibold mb-0.5 text-text-secondary">{t('form.retrievalSetting.title', { ns: 'datasetSettings' })}</div>
<div className="body-xs-regular text-text-tertiary">
<a
target="_blank"
@ -1025,15 +1025,15 @@ const StepTwo = ({
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents')}
className="text-text-accent"
>
{t('datasetSettings.form.retrievalSetting.learnMore')}
{t('form.retrievalSetting.learnMore', { ns: 'datasetSettings' })}
</a>
{t('datasetSettings.form.retrievalSetting.longDescription')}
{t('form.retrievalSetting.longDescription', { ns: 'datasetSettings' })}
</div>
</div>
)
: (
<div className={cn('system-md-semibold mb-0.5 text-text-secondary', 'flex items-center justify-between')}>
<div>{t('datasetSettings.form.retrievalSetting.title')}</div>
<div>{t('form.retrievalSetting.title', { ns: 'datasetSettings' })}</div>
</div>
)}
@ -1064,15 +1064,15 @@ const StepTwo = ({
<div className="mt-8 flex items-center py-2">
<Button onClick={() => onStepChange?.(-1)}>
<RiArrowLeftLine className="mr-1 h-4 w-4" />
{t('datasetCreation.stepTwo.previousStep')}
{t('stepTwo.previousStep', { ns: 'datasetCreation' })}
</Button>
<Button className="ml-auto" loading={isCreating} variant="primary" onClick={createHandle}>{t('datasetCreation.stepTwo.nextStep')}</Button>
<Button className="ml-auto" loading={isCreating} variant="primary" onClick={createHandle}>{t('stepTwo.nextStep', { ns: 'datasetCreation' })}</Button>
</div>
)
: (
<div className="mt-8 flex items-center py-2">
<Button loading={isCreating} variant="primary" onClick={createHandle}>{t('datasetCreation.stepTwo.save')}</Button>
<Button className="ml-2" onClick={onCancel}>{t('datasetCreation.stepTwo.cancel')}</Button>
<Button loading={isCreating} variant="primary" onClick={createHandle}>{t('stepTwo.save', { ns: 'datasetCreation' })}</Button>
<Button className="ml-2" onClick={onCancel}>{t('stepTwo.cancel', { ns: 'datasetCreation' })}</Button>
</div>
)}
</div>
@ -1080,7 +1080,7 @@ const StepTwo = ({
<PreviewContainer
header={(
<PreviewHeader
title={t('datasetCreation.stepTwo.preview')}
title={t('stepTwo.preview', { ns: 'datasetCreation' })}
>
<div className="flex items-center gap-1">
{dataSourceType === DataSourceType.FILE
@ -1147,7 +1147,8 @@ const StepTwo = ({
{
currentDocForm !== ChunkingMode.qa
&& (
<Badge text={t('datasetCreation.stepTwo.previewChunkCount', {
<Badge text={t('stepTwo.previewChunkCount', {
ns: 'datasetCreation',
count: estimate?.total_segments || 0,
}) as string}
/>
@ -1217,7 +1218,7 @@ const StepTwo = ({
<div className="flex flex-col items-center justify-center gap-3">
<RiSearchEyeLine className="size-10 text-text-empty-state-icon" />
<p className="text-sm text-text-tertiary">
{t('datasetCreation.stepTwo.previewChunkTip')}
{t('stepTwo.previewChunkTip', { ns: 'datasetCreation' })}
</p>
</div>
</div>

View File

@ -24,11 +24,11 @@ export const DelimiterInput: FC<InputProps & { tooltip?: string }> = (props) =>
return (
<FormField label={(
<div className="mb-1 flex items-center">
<span className="system-sm-semibold mr-0.5">{t('datasetCreation.stepTwo.separator')}</span>
<span className="system-sm-semibold mr-0.5">{t('stepTwo.separator', { ns: 'datasetCreation' })}</span>
<Tooltip
popupContent={(
<div className="max-w-[200px]">
{props.tooltip || t('datasetCreation.stepTwo.separatorTip')}
{props.tooltip || t('stepTwo.separatorTip', { ns: 'datasetCreation' })}
</div>
)}
/>
@ -38,7 +38,7 @@ export const DelimiterInput: FC<InputProps & { tooltip?: string }> = (props) =>
<Input
type="text"
className="h-9"
placeholder={t('datasetCreation.stepTwo.separatorPlaceholder')!}
placeholder={t('stepTwo.separatorPlaceholder', { ns: 'datasetCreation' })!}
{...props}
/>
</FormField>
@ -52,7 +52,7 @@ export const MaxLengthInput: FC<InputNumberProps> = (props) => {
return (
<FormField label={(
<div className="system-sm-semibold mb-1">
{t('datasetCreation.stepTwo.maxLength')}
{t('stepTwo.maxLength', { ns: 'datasetCreation' })}
</div>
)}
>
@ -73,11 +73,11 @@ export const OverlapInput: FC<InputNumberProps> = (props) => {
return (
<FormField label={(
<div className="mb-1 flex items-center">
<span className="system-sm-semibold">{t('datasetCreation.stepTwo.overlap')}</span>
<span className="system-sm-semibold">{t('stepTwo.overlap', { ns: 'datasetCreation' })}</span>
<Tooltip
popupContent={(
<div className="max-w-[200px]">
{t('datasetCreation.stepTwo.overlapTip')}
{t('stepTwo.overlapTip', { ns: 'datasetCreation' })}
</div>
)}
/>
@ -87,7 +87,7 @@ export const OverlapInput: FC<InputNumberProps> = (props) => {
<InputNumber
type="number"
size="large"
placeholder={t('datasetCreation.stepTwo.overlap') || ''}
placeholder={t('stepTwo.overlap', { ns: 'datasetCreation' }) || ''}
min={1}
{...props}
/>

View File

@ -55,7 +55,7 @@ const PreviewItem: FC<IPreviewItemProps> = ({
<span>
{charNums}
{' '}
{t('datasetCreation.stepTwo.characters')}
{t('stepTwo.characters', { ns: 'datasetCreation' })}
</span>
</div>
</div>

View File

@ -32,11 +32,11 @@ const StopEmbeddingModal = ({
>
<div className={s.icon} />
<span className={s.close} onClick={onHide} />
<div className={s.title}>{t('datasetCreation.stepThree.modelTitle')}</div>
<div className={s.content}>{t('datasetCreation.stepThree.modelContent')}</div>
<div className={s.title}>{t('stepThree.modelTitle', { ns: 'datasetCreation' })}</div>
<div className={s.content}>{t('stepThree.modelContent', { ns: 'datasetCreation' })}</div>
<div className="flex flex-row-reverse">
<Button className="ml-2 w-24" variant="primary" onClick={submit}>{t('datasetCreation.stepThree.modelButtonConfirm')}</Button>
<Button className="w-24" onClick={onHide}>{t('datasetCreation.stepThree.modelButtonCancel')}</Button>
<Button className="ml-2 w-24" variant="primary" onClick={submit}>{t('stepThree.modelButtonConfirm', { ns: 'datasetCreation' })}</Button>
<Button className="w-24" onClick={onHide}>{t('stepThree.modelButtonCancel', { ns: 'datasetCreation' })}</Button>
</div>
</Modal>
)

View File

@ -12,11 +12,11 @@ export type TopBarProps = Pick<StepperProps, 'activeIndex'> & {
datasetId?: string
}
const STEP_T_MAP: Record<number, string> = {
1: 'datasetCreation.steps.one',
2: 'datasetCreation.steps.two',
3: 'datasetCreation.steps.three',
}
const STEP_T_MAP = {
1: 'steps.one',
2: 'steps.two',
3: 'steps.three',
} as const
export const TopBar: FC<TopBarProps> = (props) => {
const { className, datasetId, ...rest } = props
@ -33,13 +33,13 @@ export const TopBar: FC<TopBarProps> = (props) => {
<RiArrowLeftLine className="size-4 text-text-primary" />
</div>
<p className="system-sm-semibold-uppercase text-text-primary">
{t('datasetCreation.steps.header.fallbackRoute')}
{t('steps.header.fallbackRoute', { ns: 'datasetCreation' })}
</p>
</Link>
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
<Stepper
steps={Array.from({ length: 3 }, (_, i) => ({
name: t(STEP_T_MAP[i + 1] as any) as string,
name: t(STEP_T_MAP[(i + 1) as keyof typeof STEP_T_MAP], { ns: 'datasetCreation' }),
}))}
{...rest}
/>

View File

@ -54,7 +54,7 @@ const CrawledResultItem: FC<Props> = ({
onClick={onPreview}
className="right-0 top-0 hidden h-6 px-1.5 text-xs font-medium uppercase group-hover:absolute group-hover:block"
>
{t('datasetCreation.stepOne.website.preview')}
{t('stepOne.website.preview', { ns: 'datasetCreation' })}
</Button>
</div>
</div>

View File

@ -8,7 +8,7 @@ import { cn } from '@/utils/classnames'
import CheckboxWithLabel from './checkbox-with-label'
import CrawledResultItem from './crawled-result-item'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const I18N_PREFIX = 'stepOne.website'
type Props = {
className?: string
@ -63,12 +63,13 @@ const CrawledResult: FC<Props> = ({
<CheckboxWithLabel
isChecked={isCheckAll}
onChange={handleCheckedAll}
label={isCheckAll ? t(`${I18N_PREFIX}.resetAll`) : t(`${I18N_PREFIX}.selectAll`)}
label={isCheckAll ? t(`${I18N_PREFIX}.resetAll`, { ns: 'datasetCreation' }) : t(`${I18N_PREFIX}.selectAll`, { ns: 'datasetCreation' })}
labelClassName="system-[13px] leading-[16px] font-medium text-text-secondary"
testId="select-all"
/>
<div className="text-xs text-text-tertiary">
{t(`${I18N_PREFIX}.scrapTimeInfo`, {
ns: 'datasetCreation',
total: list.length,
time: usedTime.toFixed(1),
})}

View File

@ -22,7 +22,7 @@ const Crawling: FC<Props> = ({
<div className="flex h-[34px] items-center border-y-[0.5px] border-divider-regular px-4
text-xs text-text-tertiary shadow-xs shadow-shadow-shadow-3"
>
{t('datasetCreation.stepOne.website.totalPageScraped')}
{t('stepOne.website.totalPageScraped', { ns: 'datasetCreation' })}
{' '}
{crawledNum}
/

View File

@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next'
import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows'
import { cn } from '@/utils/classnames'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const I18N_PREFIX = 'stepOne.website'
type Props = {
className?: string
@ -40,7 +40,7 @@ const OptionsWrap: FC<Props> = ({
>
<div className="flex grow items-center">
<RiEqualizer2Line className="mr-1 h-4 w-4 text-text-secondary" />
<span className="text-[13px] font-semibold uppercase leading-[16px] text-text-secondary">{t(`${I18N_PREFIX}.options`)}</span>
<span className="text-[13px] font-semibold uppercase leading-[16px] text-text-secondary">{t(`${I18N_PREFIX}.options`, { ns: 'datasetCreation' })}</span>
</div>
<ChevronRight className={cn(!fold && 'rotate-90', 'h-4 w-4 shrink-0 text-text-tertiary')} />
</div>

View File

@ -7,7 +7,7 @@ import Button from '@/app/components/base/button'
import { useDocLink } from '@/context/i18n'
import Input from './input'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const I18N_PREFIX = 'stepOne.website'
type Props = {
isRunning: boolean
@ -43,7 +43,7 @@ const UrlInput: FC<Props> = ({
loading={isRunning}
spinnerClassName="!ml-0"
>
{!isRunning ? t(`${I18N_PREFIX}.run`) : ''}
{!isRunning ? t(`${I18N_PREFIX}.run`, { ns: 'datasetCreation' }) : ''}
</Button>
</div>
)

View File

@ -17,8 +17,8 @@ import OptionsWrap from '../base/options-wrap'
import UrlInput from '../base/url-input'
import Options from './options'
const ERROR_I18N_PREFIX = 'common.errorMsg'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const ERROR_I18N_PREFIX = 'errorMsg'
const I18N_PREFIX = 'stepOne.website'
type Props = {
onPreview: (payload: CrawlResultItem) => void
@ -61,16 +61,18 @@ const FireCrawl: FC<Props> = ({
let errorMsg = ''
if (!url) {
errorMsg = t(`${ERROR_I18N_PREFIX}.fieldRequired`, {
ns: 'common',
field: 'url',
})
}
if (!errorMsg && !((url.startsWith('http://') || url.startsWith('https://'))))
errorMsg = t(`${ERROR_I18N_PREFIX}.urlError`)
errorMsg = t(`${ERROR_I18N_PREFIX}.urlError`, { ns: 'common' })
if (!errorMsg && (crawlOptions.limit === null || crawlOptions.limit === undefined || crawlOptions.limit === '')) {
errorMsg = t(`${ERROR_I18N_PREFIX}.fieldRequired`, {
field: t(`${I18N_PREFIX}.limit`),
ns: 'common',
field: t(`${I18N_PREFIX}.limit`, { ns: 'datasetCreation' }),
})
}
@ -164,7 +166,7 @@ const FireCrawl: FC<Props> = ({
onJobIdChange(jobId)
const { isError, data, errorMessage } = await waitForCrawlFinished(jobId)
if (isError) {
setCrawlErrorMessage(errorMessage || t(`${I18N_PREFIX}.unknownError`))
setCrawlErrorMessage(errorMessage || t(`${I18N_PREFIX}.unknownError`, { ns: 'datasetCreation' }))
}
else {
setCrawlResult(data)
@ -173,7 +175,7 @@ const FireCrawl: FC<Props> = ({
}
}
catch (e) {
setCrawlErrorMessage(t(`${I18N_PREFIX}.unknownError`)!)
setCrawlErrorMessage(t(`${I18N_PREFIX}.unknownError`, { ns: 'datasetCreation' })!)
console.log(e)
}
finally {
@ -185,9 +187,9 @@ const FireCrawl: FC<Props> = ({
<div>
<Header
onClickConfiguration={handleSetting}
title={t(`${I18N_PREFIX}.firecrawlTitle`)}
buttonText={t(`${I18N_PREFIX}.configureFirecrawl`)}
docTitle={t(`${I18N_PREFIX}.firecrawlDoc`)}
title={t(`${I18N_PREFIX}.firecrawlTitle`, { ns: 'datasetCreation' })}
buttonText={t(`${I18N_PREFIX}.configureFirecrawl`, { ns: 'datasetCreation' })}
docTitle={t(`${I18N_PREFIX}.firecrawlDoc`, { ns: 'datasetCreation' })}
docLink="https://docs.firecrawl.dev/introduction"
/>
<div className="mt-2 rounded-xl border border-components-panel-border bg-background-default-subtle p-4 pb-0">
@ -210,7 +212,7 @@ const FireCrawl: FC<Props> = ({
/>
)}
{showError && (
<ErrorMessage className="rounded-b-xl" title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} />
<ErrorMessage className="rounded-b-xl" title={t(`${I18N_PREFIX}.exceptionErrorTitle`, { ns: 'datasetCreation' })} errorMsg={crawlErrorMessage} />
)}
{isCrawlFinished && !showError
&& (

View File

@ -8,7 +8,7 @@ import { cn } from '@/utils/classnames'
import CheckboxWithLabel from '../base/checkbox-with-label'
import Field from '../base/field'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const I18N_PREFIX = 'stepOne.website'
type Props = {
className?: string
@ -34,7 +34,7 @@ const Options: FC<Props> = ({
return (
<div className={cn(className, ' space-y-2')}>
<CheckboxWithLabel
label={t(`${I18N_PREFIX}.crawlSubPage`)}
label={t(`${I18N_PREFIX}.crawlSubPage`, { ns: 'datasetCreation' })}
isChecked={payload.crawl_sub_pages}
onChange={handleChange('crawl_sub_pages')}
labelClassName="text-[13px] leading-[16px] font-medium text-text-secondary"
@ -42,7 +42,7 @@ const Options: FC<Props> = ({
<div className="flex justify-between space-x-4">
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.limit`)}
label={t(`${I18N_PREFIX}.limit`, { ns: 'datasetCreation' })}
value={payload.limit}
onChange={handleChange('limit')}
isNumber
@ -50,32 +50,32 @@ const Options: FC<Props> = ({
/>
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.maxDepth`)}
label={t(`${I18N_PREFIX}.maxDepth`, { ns: 'datasetCreation' })}
value={payload.max_depth}
onChange={handleChange('max_depth')}
isNumber
tooltip={t(`${I18N_PREFIX}.maxDepthTooltip`)!}
tooltip={t(`${I18N_PREFIX}.maxDepthTooltip`, { ns: 'datasetCreation' })!}
/>
</div>
<div className="flex justify-between space-x-4">
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.excludePaths`)}
label={t(`${I18N_PREFIX}.excludePaths`, { ns: 'datasetCreation' })}
value={payload.excludes}
onChange={handleChange('excludes')}
placeholder="blog/*, /about/*"
/>
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.includeOnlyPaths`)}
label={t(`${I18N_PREFIX}.includeOnlyPaths`, { ns: 'datasetCreation' })}
value={payload.includes}
onChange={handleChange('includes')}
placeholder="articles/*"
/>
</div>
<CheckboxWithLabel
label={t(`${I18N_PREFIX}.extractOnlyMainContent`)}
label={t(`${I18N_PREFIX}.extractOnlyMainContent`, { ns: 'datasetCreation' })}
isChecked={payload.only_main_content}
onChange={handleChange('only_main_content')}
labelClassName="text-[13px] leading-[16px] font-medium text-text-secondary"

View File

@ -61,7 +61,7 @@ const Website: FC<Props> = ({
<div>
<div className="mb-4">
<div className="system-md-medium mb-2 text-text-secondary">
{t('datasetCreation.stepOne.website.chooseProvider')}
{t('stepOne.website.chooseProvider', { ns: 'datasetCreation' })}
</div>
<div className="flex space-x-2">
{ENABLE_WEBSITE_JINAREADER && (

View File

@ -7,7 +7,7 @@ import Button from '@/app/components/base/button'
import { useDocLink } from '@/context/i18n'
import Input from '../../base/input'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const I18N_PREFIX = 'stepOne.website'
type Props = {
isRunning: boolean
@ -44,7 +44,7 @@ const UrlInput: FC<Props> = ({
loading={isRunning}
data-testid="url-input-run-button"
>
{!isRunning ? t(`${I18N_PREFIX}.run`) : ''}
{!isRunning ? t(`${I18N_PREFIX}.run`, { ns: 'datasetCreation' }) : ''}
</Button>
</div>
)

View File

@ -17,8 +17,8 @@ import OptionsWrap from '../base/options-wrap'
import UrlInput from '../base/url-input'
import Options from './options'
const ERROR_I18N_PREFIX = 'common.errorMsg'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const ERROR_I18N_PREFIX = 'errorMsg'
const I18N_PREFIX = 'stepOne.website'
type Props = {
onPreview: (payload: CrawlResultItem) => void
@ -61,16 +61,18 @@ const JinaReader: FC<Props> = ({
let errorMsg = ''
if (!url) {
errorMsg = t(`${ERROR_I18N_PREFIX}.fieldRequired`, {
ns: 'common',
field: 'url',
})
}
if (!errorMsg && !((url.startsWith('http://') || url.startsWith('https://'))))
errorMsg = t(`${ERROR_I18N_PREFIX}.urlError`)
errorMsg = t(`${ERROR_I18N_PREFIX}.urlError`, { ns: 'common' })
if (!errorMsg && (crawlOptions.limit === null || crawlOptions.limit === undefined || crawlOptions.limit === '')) {
errorMsg = t(`${ERROR_I18N_PREFIX}.fieldRequired`, {
field: t(`${I18N_PREFIX}.limit`),
ns: 'common',
field: t(`${I18N_PREFIX}.limit`, { ns: 'datasetCreation' }),
})
}
@ -173,7 +175,7 @@ const JinaReader: FC<Props> = ({
onJobIdChange(jobId)
const { isError, data, errorMessage } = await waitForCrawlFinished(jobId)
if (isError) {
setCrawlErrorMessage(errorMessage || t(`${I18N_PREFIX}.unknownError`))
setCrawlErrorMessage(errorMessage || t(`${I18N_PREFIX}.unknownError`, { ns: 'datasetCreation' }))
}
else {
setCrawlResult(data)
@ -183,7 +185,7 @@ const JinaReader: FC<Props> = ({
}
}
catch (e) {
setCrawlErrorMessage(t(`${I18N_PREFIX}.unknownError`)!)
setCrawlErrorMessage(t(`${I18N_PREFIX}.unknownError`, { ns: 'datasetCreation' })!)
console.log(e)
}
finally {
@ -195,9 +197,9 @@ const JinaReader: FC<Props> = ({
<div>
<Header
onClickConfiguration={handleSetting}
title={t(`${I18N_PREFIX}.jinaReaderTitle`)}
buttonText={t(`${I18N_PREFIX}.configureJinaReader`)}
docTitle={t(`${I18N_PREFIX}.jinaReaderDoc`)}
title={t(`${I18N_PREFIX}.jinaReaderTitle`, { ns: 'datasetCreation' })}
buttonText={t(`${I18N_PREFIX}.configureJinaReader`, { ns: 'datasetCreation' })}
docTitle={t(`${I18N_PREFIX}.jinaReaderDoc`, { ns: 'datasetCreation' })}
docLink="https://jina.ai/reader"
/>
<div className="mt-2 rounded-xl border border-components-panel-border bg-background-default-subtle p-4 pb-0">
@ -220,7 +222,7 @@ const JinaReader: FC<Props> = ({
/>
)}
{showError && (
<ErrorMessage className="rounded-b-xl" title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} />
<ErrorMessage className="rounded-b-xl" title={t(`${I18N_PREFIX}.exceptionErrorTitle`, { ns: 'datasetCreation' })} errorMsg={crawlErrorMessage} />
)}
{isCrawlFinished && !showError
&& (

View File

@ -8,7 +8,7 @@ import { cn } from '@/utils/classnames'
import CheckboxWithLabel from '../base/checkbox-with-label'
import Field from '../base/field'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const I18N_PREFIX = 'stepOne.website'
type Props = {
className?: string
@ -34,24 +34,24 @@ const Options: FC<Props> = ({
return (
<div className={cn(className, ' space-y-2')}>
<CheckboxWithLabel
label={t(`${I18N_PREFIX}.crawlSubPage`)}
label={t(`${I18N_PREFIX}.crawlSubPage`, { ns: 'datasetCreation' })}
isChecked={payload.crawl_sub_pages}
onChange={handleChange('crawl_sub_pages')}
labelClassName="text-[13px] leading-[16px] font-medium text-text-secondary"
testId="crawl-sub-pages"
/>
<CheckboxWithLabel
label={t(`${I18N_PREFIX}.useSitemap`)}
label={t(`${I18N_PREFIX}.useSitemap`, { ns: 'datasetCreation' })}
isChecked={payload.use_sitemap}
onChange={handleChange('use_sitemap')}
tooltip={t(`${I18N_PREFIX}.useSitemapTooltip`) as string}
tooltip={t(`${I18N_PREFIX}.useSitemapTooltip`, { ns: 'datasetCreation' }) as string}
labelClassName="text-[13px] leading-[16px] font-medium text-text-secondary"
testId="use-sitemap"
/>
<div className="flex justify-between space-x-4">
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.limit`)}
label={t(`${I18N_PREFIX}.limit`, { ns: 'datasetCreation' })}
value={payload.limit}
onChange={handleChange('limit')}
isNumber

View File

@ -8,7 +8,7 @@ import { ENABLE_WEBSITE_FIRECRAWL, ENABLE_WEBSITE_JINAREADER, ENABLE_WEBSITE_WAT
import { DataSourceProvider } from '@/models/common'
import s from './index.module.css'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const I18N_PREFIX = 'stepOne.website'
type Props = {
onConfig: () => void
@ -29,22 +29,22 @@ const NoData: FC<Props> = ({
[DataSourceProvider.jinaReader]: ENABLE_WEBSITE_JINAREADER
? {
emoji: <span className={s.jinaLogo} />,
title: t(`${I18N_PREFIX}.jinaReaderNotConfigured`),
description: t(`${I18N_PREFIX}.jinaReaderNotConfiguredDescription`),
title: t(`${I18N_PREFIX}.jinaReaderNotConfigured`, { ns: 'datasetCreation' }),
description: t(`${I18N_PREFIX}.jinaReaderNotConfiguredDescription`, { ns: 'datasetCreation' }),
}
: null,
[DataSourceProvider.fireCrawl]: ENABLE_WEBSITE_FIRECRAWL
? {
emoji: '🔥',
title: t(`${I18N_PREFIX}.fireCrawlNotConfigured`),
description: t(`${I18N_PREFIX}.fireCrawlNotConfiguredDescription`),
title: t(`${I18N_PREFIX}.fireCrawlNotConfigured`, { ns: 'datasetCreation' }),
description: t(`${I18N_PREFIX}.fireCrawlNotConfiguredDescription`, { ns: 'datasetCreation' }),
}
: null,
[DataSourceProvider.waterCrawl]: ENABLE_WEBSITE_WATERCRAWL
? {
emoji: '💧',
title: t(`${I18N_PREFIX}.waterCrawlNotConfigured`),
description: t(`${I18N_PREFIX}.waterCrawlNotConfiguredDescription`),
title: t(`${I18N_PREFIX}.waterCrawlNotConfigured`, { ns: 'datasetCreation' }),
description: t(`${I18N_PREFIX}.waterCrawlNotConfiguredDescription`, { ns: 'datasetCreation' }),
}
: null,
}
@ -72,7 +72,7 @@ const NoData: FC<Props> = ({
</div>
</div>
<Button variant="primary" onClick={onConfig}>
{t(`${I18N_PREFIX}.configure`)}
{t(`${I18N_PREFIX}.configure`, { ns: 'datasetCreation' })}
</Button>
</div>
</>

View File

@ -21,7 +21,7 @@ const WebsitePreview = ({
<div className={cn(s.filePreview, 'h-full')}>
<div className={cn(s.previewHeader)}>
<div className={cn(s.title, 'title-md-semi-bold')}>
<span>{t('datasetCreation.stepOne.pagePreview')}</span>
<span>{t('stepOne.pagePreview', { ns: 'datasetCreation' })}</span>
<div className="flex h-6 w-6 cursor-pointer items-center justify-center" onClick={hidePreview}>
<XMarkIcon className="h-4 w-4"></XMarkIcon>
</div>

View File

@ -17,8 +17,8 @@ import OptionsWrap from '../base/options-wrap'
import UrlInput from '../base/url-input'
import Options from './options'
const ERROR_I18N_PREFIX = 'common.errorMsg'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const ERROR_I18N_PREFIX = 'errorMsg'
const I18N_PREFIX = 'stepOne.website'
type Props = {
onPreview: (payload: CrawlResultItem) => void
@ -61,16 +61,18 @@ const WaterCrawl: FC<Props> = ({
let errorMsg = ''
if (!url) {
errorMsg = t(`${ERROR_I18N_PREFIX}.fieldRequired`, {
ns: 'common',
field: 'url',
})
}
if (!errorMsg && !((url.startsWith('http://') || url.startsWith('https://'))))
errorMsg = t(`${ERROR_I18N_PREFIX}.urlError`)
errorMsg = t(`${ERROR_I18N_PREFIX}.urlError`, { ns: 'common' })
if (!errorMsg && (crawlOptions.limit === null || crawlOptions.limit === undefined || crawlOptions.limit === '')) {
errorMsg = t(`${ERROR_I18N_PREFIX}.fieldRequired`, {
field: t(`${I18N_PREFIX}.limit`),
ns: 'common',
field: t(`${I18N_PREFIX}.limit`, { ns: 'datasetCreation' }),
})
}
@ -160,7 +162,7 @@ const WaterCrawl: FC<Props> = ({
onJobIdChange(jobId)
const { isError, data, errorMessage } = await waitForCrawlFinished(jobId)
if (isError) {
setCrawlErrorMessage(errorMessage || t(`${I18N_PREFIX}.unknownError`))
setCrawlErrorMessage(errorMessage || t(`${I18N_PREFIX}.unknownError`, { ns: 'datasetCreation' }))
}
else {
setCrawlResult(data)
@ -169,7 +171,7 @@ const WaterCrawl: FC<Props> = ({
}
}
catch (e) {
setCrawlErrorMessage(t(`${I18N_PREFIX}.unknownError`)!)
setCrawlErrorMessage(t(`${I18N_PREFIX}.unknownError`, { ns: 'datasetCreation' })!)
console.log(e)
}
finally {
@ -181,9 +183,9 @@ const WaterCrawl: FC<Props> = ({
<div>
<Header
onClickConfiguration={handleSetting}
title={t(`${I18N_PREFIX}.watercrawlTitle`)}
buttonText={t(`${I18N_PREFIX}.configureWatercrawl`)}
docTitle={t(`${I18N_PREFIX}.watercrawlDoc`)}
title={t(`${I18N_PREFIX}.watercrawlTitle`, { ns: 'datasetCreation' })}
buttonText={t(`${I18N_PREFIX}.configureWatercrawl`, { ns: 'datasetCreation' })}
docTitle={t(`${I18N_PREFIX}.watercrawlDoc`, { ns: 'datasetCreation' })}
docLink="https://docs.watercrawl.dev/"
/>
<div className="mt-2 rounded-xl border border-components-panel-border bg-background-default-subtle p-4 pb-0">
@ -206,7 +208,7 @@ const WaterCrawl: FC<Props> = ({
/>
)}
{showError && (
<ErrorMessage className="rounded-b-xl" title={t(`${I18N_PREFIX}.exceptionErrorTitle`)} errorMsg={crawlErrorMessage} />
<ErrorMessage className="rounded-b-xl" title={t(`${I18N_PREFIX}.exceptionErrorTitle`, { ns: 'datasetCreation' })} errorMsg={crawlErrorMessage} />
)}
{isCrawlFinished && !showError
&& (

View File

@ -8,7 +8,7 @@ import { cn } from '@/utils/classnames'
import CheckboxWithLabel from '../base/checkbox-with-label'
import Field from '../base/field'
const I18N_PREFIX = 'datasetCreation.stepOne.website'
const I18N_PREFIX = 'stepOne.website'
type Props = {
className?: string
@ -34,7 +34,7 @@ const Options: FC<Props> = ({
return (
<div className={cn(className, ' space-y-2')}>
<CheckboxWithLabel
label={t(`${I18N_PREFIX}.crawlSubPage`)}
label={t(`${I18N_PREFIX}.crawlSubPage`, { ns: 'datasetCreation' })}
isChecked={payload.crawl_sub_pages}
onChange={handleChange('crawl_sub_pages')}
labelClassName="text-[13px] leading-[16px] font-medium text-text-secondary"
@ -43,7 +43,7 @@ const Options: FC<Props> = ({
<div className="flex justify-between space-x-4">
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.limit`)}
label={t(`${I18N_PREFIX}.limit`, { ns: 'datasetCreation' })}
value={payload.limit}
onChange={handleChange('limit')}
isNumber
@ -51,32 +51,32 @@ const Options: FC<Props> = ({
/>
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.maxDepth`)}
label={t(`${I18N_PREFIX}.maxDepth`, { ns: 'datasetCreation' })}
value={payload.max_depth}
onChange={handleChange('max_depth')}
isNumber
tooltip={t(`${I18N_PREFIX}.maxDepthTooltip`)!}
tooltip={t(`${I18N_PREFIX}.maxDepthTooltip`, { ns: 'datasetCreation' })!}
/>
</div>
<div className="flex justify-between space-x-4">
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.excludePaths`)}
label={t(`${I18N_PREFIX}.excludePaths`, { ns: 'datasetCreation' })}
value={payload.excludes}
onChange={handleChange('excludes')}
placeholder="blog/*, /about/*"
/>
<Field
className="shrink-0 grow"
label={t(`${I18N_PREFIX}.includeOnlyPaths`)}
label={t(`${I18N_PREFIX}.includeOnlyPaths`, { ns: 'datasetCreation' })}
value={payload.includes}
onChange={handleChange('includes')}
placeholder="articles/*"
/>
</div>
<CheckboxWithLabel
label={t(`${I18N_PREFIX}.extractOnlyMainContent`)}
label={t(`${I18N_PREFIX}.extractOnlyMainContent`, { ns: 'datasetCreation' })}
isChecked={payload.only_main_content}
onChange={handleChange('only_main_content')}
labelClassName="text-[13px] leading-[16px] font-medium text-text-secondary"