mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
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:
@ -47,7 +47,7 @@ const AnnotationCtrlButton: FC<Props> = ({
|
||||
answer,
|
||||
})
|
||||
Toast.notify({
|
||||
message: t('common.api.actionSuccess') as string,
|
||||
message: t('api.actionSuccess', { ns: 'common' }) as string,
|
||||
type: 'success',
|
||||
})
|
||||
onAdded(res.id, res.account?.name ?? '')
|
||||
@ -57,7 +57,7 @@ const AnnotationCtrlButton: FC<Props> = ({
|
||||
<>
|
||||
{cached && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.annotation.edit')}
|
||||
popupContent={t('feature.annotation.edit', { ns: 'appDebug' })}
|
||||
>
|
||||
<ActionButton onClick={onEdit}>
|
||||
<RiEditLine className="h-4 w-4" />
|
||||
@ -66,7 +66,7 @@ const AnnotationCtrlButton: FC<Props> = ({
|
||||
)}
|
||||
{!cached && answer && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.annotation.add')}
|
||||
popupContent={t('feature.annotation.add', { ns: 'appDebug' })}
|
||||
>
|
||||
<ActionButton onClick={handleAdd}>
|
||||
<RiFileEditLine className="h-4 w-4" />
|
||||
|
||||
@ -61,7 +61,7 @@ const ConfigParamModal: FC<Props> = ({
|
||||
const handleSave = async () => {
|
||||
if (!embeddingModel || !embeddingModel.modelName || (embeddingModel.modelName === embeddingsDefaultModel?.model && !isEmbeddingsDefaultModelValid)) {
|
||||
Toast.notify({
|
||||
message: t('common.modelProvider.embeddingModel.required'),
|
||||
message: t('modelProvider.embeddingModel.required', { ns: 'common' }),
|
||||
type: 'error',
|
||||
})
|
||||
return
|
||||
@ -81,13 +81,13 @@ const ConfigParamModal: FC<Props> = ({
|
||||
className="!mt-14 !w-[640px] !max-w-none !p-6"
|
||||
>
|
||||
<div className="title-2xl-semi-bold mb-2 text-text-primary">
|
||||
{t(`appAnnotation.initSetup.${isInit ? 'title' : 'configTitle'}`)}
|
||||
{t(`initSetup.${isInit ? 'title' : 'configTitle'}`, { ns: 'appAnnotation' })}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 space-y-3">
|
||||
<Item
|
||||
title={t('appDebug.feature.annotation.scoreThreshold.title')}
|
||||
tooltip={t('appDebug.feature.annotation.scoreThreshold.description')}
|
||||
title={t('feature.annotation.scoreThreshold.title', { ns: 'appDebug' })}
|
||||
tooltip={t('feature.annotation.scoreThreshold.description', { ns: 'appDebug' })}
|
||||
>
|
||||
<ScoreSlider
|
||||
className="mt-1"
|
||||
@ -102,8 +102,8 @@ const ConfigParamModal: FC<Props> = ({
|
||||
</Item>
|
||||
|
||||
<Item
|
||||
title={t('common.modelProvider.embeddingModel.key')}
|
||||
tooltip={t('appAnnotation.embeddingModelSwitchTip')}
|
||||
title={t('modelProvider.embeddingModel.key', { ns: 'common' })}
|
||||
tooltip={t('embeddingModelSwitchTip', { ns: 'appAnnotation' })}
|
||||
>
|
||||
<div className="pt-1">
|
||||
<ModelSelector
|
||||
@ -124,14 +124,14 @@ const ConfigParamModal: FC<Props> = ({
|
||||
</div>
|
||||
|
||||
<div className="mt-6 flex justify-end gap-2">
|
||||
<Button onClick={onHide}>{t('common.operation.cancel')}</Button>
|
||||
<Button onClick={onHide}>{t('operation.cancel', { ns: 'common' })}</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleSave}
|
||||
loading={isLoading}
|
||||
>
|
||||
<div></div>
|
||||
<div>{t(`appAnnotation.initSetup.${isInit ? 'confirmBtn' : 'configConfirmBtn'}`)}</div>
|
||||
<div>{t(`initSetup.${isInit ? 'confirmBtn' : 'configConfirmBtn'}`, { ns: 'appAnnotation' })}</div>
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@ -83,7 +83,7 @@ const AnnotationReply = ({
|
||||
<MessageFast className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.annotation.title')}
|
||||
title={t('feature.annotation.title', { ns: 'appDebug' })}
|
||||
value={!!annotationReply?.enabled}
|
||||
onChange={state => handleSwitch(state)}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
@ -92,19 +92,19 @@ const AnnotationReply = ({
|
||||
>
|
||||
<>
|
||||
{!annotationReply?.enabled && (
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('appDebug.feature.annotation.description')}</div>
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('feature.annotation.description', { ns: 'appDebug' })}</div>
|
||||
)}
|
||||
{!!annotationReply?.enabled && (
|
||||
<>
|
||||
{!isHovering && (
|
||||
<div className="flex items-center gap-4 pt-0.5">
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.feature.annotation.scoreThreshold.title')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('feature.annotation.scoreThreshold.title', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{annotationReply.score_threshold || '-'}</div>
|
||||
</div>
|
||||
<div className="h-[27px] w-px rotate-12 bg-divider-subtle"></div>
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('common.modelProvider.embeddingModel.key')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('modelProvider.embeddingModel.key', { ns: 'common' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{annotationReply.embedding_model?.embedding_model_name}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -113,7 +113,7 @@ const AnnotationReply = ({
|
||||
<div className="flex items-center justify-between">
|
||||
<Button className="w-[178px]" onClick={() => setIsShowAnnotationConfigInit(true)} disabled={disabled}>
|
||||
<RiEqualizer2Line className="mr-1 h-4 w-4" />
|
||||
{t('common.operation.params')}
|
||||
{t('operation.params', { ns: 'common' })}
|
||||
</Button>
|
||||
<Button
|
||||
className="w-[178px]"
|
||||
@ -122,7 +122,7 @@ const AnnotationReply = ({
|
||||
}}
|
||||
>
|
||||
<RiExternalLinkLine className="mr-1 h-4 w-4" />
|
||||
{t('appDebug.feature.annotation.cacheManagement')}
|
||||
{t('feature.annotation.cacheManagement', { ns: 'appDebug' })}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -32,12 +32,12 @@ const ScoreSlider: FC<Props> = ({
|
||||
<div className="flex space-x-1 text-util-colors-cyan-cyan-500">
|
||||
<div>0.8</div>
|
||||
<div>·</div>
|
||||
<div>{t('appDebug.feature.annotation.scoreThreshold.easyMatch')}</div>
|
||||
<div>{t('feature.annotation.scoreThreshold.easyMatch', { ns: 'appDebug' })}</div>
|
||||
</div>
|
||||
<div className="flex space-x-1 text-util-colors-blue-blue-500">
|
||||
<div>1.0</div>
|
||||
<div>·</div>
|
||||
<div>{t('appDebug.feature.annotation.scoreThreshold.accurateMatch')}</div>
|
||||
<div>{t('feature.annotation.scoreThreshold.accurateMatch', { ns: 'appDebug' })}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -45,9 +45,9 @@ const Citation = ({
|
||||
<Citations className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.citation.title')}
|
||||
title={t('feature.citation.title', { ns: 'appDebug' })}
|
||||
value={!!features.citation?.enabled}
|
||||
description={t('appDebug.feature.citation.description')!}
|
||||
description={t('feature.citation.description', { ns: 'appDebug' })!}
|
||||
onChange={state => handleChange(FeatureEnum.citation, state)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
@ -86,7 +86,7 @@ const ConversationOpener = ({
|
||||
<LoveMessage className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.conversationOpener.title')}
|
||||
title={t('feature.conversationOpener.title', { ns: 'appDebug' })}
|
||||
value={!!opening?.enabled}
|
||||
onChange={state => handleChange(FeatureEnum.opening, state)}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
@ -95,19 +95,19 @@ const ConversationOpener = ({
|
||||
>
|
||||
<>
|
||||
{!opening?.enabled && (
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('appDebug.feature.conversationOpener.description')}</div>
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('feature.conversationOpener.description', { ns: 'appDebug' })}</div>
|
||||
)}
|
||||
{!!opening?.enabled && (
|
||||
<>
|
||||
{!isHovering && (
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">
|
||||
{opening.opening_statement || t('appDebug.openingStatement.placeholder')}
|
||||
{opening.opening_statement || t('openingStatement.placeholder', { ns: 'appDebug' })}
|
||||
</div>
|
||||
)}
|
||||
{isHovering && (
|
||||
<Button className="w-full" onClick={handleOpenOpeningModal} disabled={disabled}>
|
||||
<RiEditLine className="mr-1 h-4 w-4" />
|
||||
{t('appDebug.openingStatement.writeOpener')}
|
||||
{t('openingStatement.writeOpener', { ns: 'appDebug' })}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
|
||||
@ -106,7 +106,7 @@ const OpeningSettingModal = ({
|
||||
<div>
|
||||
<div className="flex items-center py-2">
|
||||
<div className="flex shrink-0 space-x-0.5 text-xs font-medium leading-[18px] text-text-tertiary">
|
||||
<div className="uppercase">{t('appDebug.openingStatement.openingQuestion')}</div>
|
||||
<div className="uppercase">{t('openingStatement.openingQuestion', { ns: 'appDebug' })}</div>
|
||||
<div>·</div>
|
||||
<div>
|
||||
{tempSuggestedQuestions.length}
|
||||
@ -143,7 +143,7 @@ const OpeningSettingModal = ({
|
||||
<input
|
||||
type="input"
|
||||
value={question || ''}
|
||||
placeholder={t('appDebug.openingStatement.openingQuestionPlaceholder') as string}
|
||||
placeholder={t('openingStatement.openingQuestionPlaceholder', { ns: 'appDebug' }) as string}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
setTempSuggestedQuestions(tempSuggestedQuestions.map((item, i) => {
|
||||
@ -178,7 +178,7 @@ const OpeningSettingModal = ({
|
||||
className="mt-1 flex h-9 cursor-pointer items-center gap-2 rounded-lg bg-components-button-tertiary-bg px-3 text-components-button-tertiary-text hover:bg-components-button-tertiary-bg-hover"
|
||||
>
|
||||
<RiAddLine className="h-4 w-4" />
|
||||
<div className="system-sm-medium text-[13px]">{t('appDebug.variableConfig.addOption')}</div>
|
||||
<div className="system-sm-medium text-[13px]">{t('variableConfig.addOption', { ns: 'appDebug' })}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@ -192,7 +192,7 @@ const OpeningSettingModal = ({
|
||||
className="!mt-14 !w-[640px] !max-w-none !bg-components-panel-bg-blur !p-6"
|
||||
>
|
||||
<div className="mb-6 flex items-center justify-between">
|
||||
<div className="title-2xl-semi-bold text-text-primary">{t('appDebug.feature.conversationOpener.title')}</div>
|
||||
<div className="title-2xl-semi-bold text-text-primary">{t('feature.conversationOpener.title', { ns: 'appDebug' })}</div>
|
||||
<div className="cursor-pointer p-1" onClick={onCancel}><RiCloseLine className="h-4 w-4 text-text-tertiary" /></div>
|
||||
</div>
|
||||
<div className="mb-8 flex gap-2">
|
||||
@ -203,7 +203,7 @@ const OpeningSettingModal = ({
|
||||
<PromptEditor
|
||||
value={tempValue}
|
||||
onChange={setTempValue}
|
||||
placeholder={t('appDebug.openingStatement.placeholder') as string}
|
||||
placeholder={t('openingStatement.placeholder', { ns: 'appDebug' }) as string}
|
||||
variableBlock={{
|
||||
show: true,
|
||||
variables: [
|
||||
@ -228,14 +228,14 @@ const OpeningSettingModal = ({
|
||||
onClick={onCancel}
|
||||
className="mr-2"
|
||||
>
|
||||
{t('common.operation.cancel')}
|
||||
{t('operation.cancel', { ns: 'common' })}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => handleSave()}
|
||||
disabled={isSaveDisabled}
|
||||
>
|
||||
{t('common.operation.save')}
|
||||
{t('operation.save', { ns: 'common' })}
|
||||
</Button>
|
||||
</div>
|
||||
{isShowConfirmAddVar && (
|
||||
|
||||
@ -41,7 +41,7 @@ const FeatureBar = ({
|
||||
{noFeatureEnabled && (
|
||||
<div className="flex cursor-pointer items-end gap-1" onClick={() => onFeatureBarClick?.(true)}>
|
||||
<RiApps2AddLine className="h-3.5 w-3.5 text-text-accent" />
|
||||
<div className="body-xs-medium text-text-accent">{t('appDebug.feature.bar.empty')}</div>
|
||||
<div className="body-xs-medium text-text-accent">{t('feature.bar.empty', { ns: 'appDebug' })}</div>
|
||||
<RiArrowRightLine className="h-3.5 w-3.5 text-text-accent" />
|
||||
</div>
|
||||
)}
|
||||
@ -50,7 +50,7 @@ const FeatureBar = ({
|
||||
<div className="flex shrink-0 items-center gap-0.5">
|
||||
{!!features.moreLikeThis?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.moreLikeThis.title')}
|
||||
popupContent={t('feature.moreLikeThis.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<RiSparklingFill className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
@ -59,7 +59,7 @@ const FeatureBar = ({
|
||||
)}
|
||||
{!!features.opening?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.conversationOpener.title')}
|
||||
popupContent={t('feature.conversationOpener.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<LoveMessage className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
@ -68,7 +68,7 @@ const FeatureBar = ({
|
||||
)}
|
||||
{!!features.moderation?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.moderation.title')}
|
||||
popupContent={t('feature.moderation.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-text-success p-1 shadow-xs">
|
||||
<ContentModeration className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
@ -77,7 +77,7 @@ const FeatureBar = ({
|
||||
)}
|
||||
{!!features.speech2text?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.speechToText.title')}
|
||||
popupContent={t('feature.speechToText.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-violet-violet-600 p-1 shadow-xs">
|
||||
<Microphone01 className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
@ -87,7 +87,7 @@ const FeatureBar = ({
|
||||
{!!features.text2speech?.enabled && (
|
||||
<VoiceSettings placementLeft={false} open={modalOpen && !disabled} onOpen={setModalOpen}>
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.textToSpeech.title')}
|
||||
popupContent={t('feature.textToSpeech.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className={cn('shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-violet-violet-600 p-1 shadow-xs', !disabled && 'cursor-pointer')}>
|
||||
<TextToAudio className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
@ -97,7 +97,7 @@ const FeatureBar = ({
|
||||
)}
|
||||
{showFileUpload && !!features.file?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.fileUpload.title')}
|
||||
popupContent={t('feature.fileUpload.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-blue-600 p-1 shadow-xs">
|
||||
<FolderUpload className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
@ -106,7 +106,7 @@ const FeatureBar = ({
|
||||
)}
|
||||
{!!features.suggested?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}
|
||||
popupContent={t('feature.suggestedQuestionsAfterAnswer.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-light-blue-light-500 p-1 shadow-xs">
|
||||
<VirtualAssistant className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
@ -115,7 +115,7 @@ const FeatureBar = ({
|
||||
)}
|
||||
{isChatMode && !!features.citation?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.citation.title')}
|
||||
popupContent={t('feature.citation.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-warning-warning-500 p-1 shadow-xs">
|
||||
<Citations className="h-4 w-4 text-text-primary-on-surface" />
|
||||
@ -124,7 +124,7 @@ const FeatureBar = ({
|
||||
)}
|
||||
{isChatMode && !!features.annotationReply?.enabled && (
|
||||
<Tooltip
|
||||
popupContent={t('appDebug.feature.annotation.title')}
|
||||
popupContent={t('feature.annotation.title', { ns: 'appDebug' })}
|
||||
>
|
||||
<div className="shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-indigo-indigo-600 p-1 shadow-xs">
|
||||
<MessageFast className="h-3.5 w-3.5 text-text-primary-on-surface" />
|
||||
@ -132,9 +132,9 @@ const FeatureBar = ({
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<div className="body-xs-regular grow text-text-tertiary">{t('appDebug.feature.bar.enableText')}</div>
|
||||
<div className="body-xs-regular grow text-text-tertiary">{t('feature.bar.enableText', { ns: 'appDebug' })}</div>
|
||||
<Button className="shrink-0" variant="ghost-accent" size="small" onClick={() => onFeatureBarClick?.(true)}>
|
||||
<div className="mx-1">{t('appDebug.feature.bar.manage')}</div>
|
||||
<div className="mx-1">{t('feature.bar.manage', { ns: 'appDebug' })}</div>
|
||||
<RiArrowRightLine className="h-3.5 w-3.5 text-text-accent" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@ -55,7 +55,7 @@ const FileUpload = ({
|
||||
<FolderUpload className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.fileUpload.title')}
|
||||
title={t('feature.fileUpload.title', { ns: 'appDebug' })}
|
||||
value={file?.enabled}
|
||||
onChange={state => handleChange(FeatureEnum.file, state)}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
@ -64,19 +64,19 @@ const FileUpload = ({
|
||||
>
|
||||
<>
|
||||
{!file?.enabled && (
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('appDebug.feature.fileUpload.description')}</div>
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('feature.fileUpload.description', { ns: 'appDebug' })}</div>
|
||||
)}
|
||||
{file?.enabled && (
|
||||
<>
|
||||
{!isHovering && !modalOpen && (
|
||||
<div className="flex items-center gap-4 pt-0.5">
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.feature.fileUpload.supportedTypes')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('feature.fileUpload.supportedTypes', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{supportedTypes}</div>
|
||||
</div>
|
||||
<div className="h-[27px] w-px rotate-12 bg-divider-subtle"></div>
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.feature.fileUpload.numberLimit')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('feature.fileUpload.numberLimit', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{file?.number_limits}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -92,7 +92,7 @@ const FileUpload = ({
|
||||
>
|
||||
<Button className="w-full" disabled={disabled}>
|
||||
<RiEqualizer2Line className="mr-1 h-4 w-4" />
|
||||
{t('common.operation.settings')}
|
||||
{t('operation.settings', { ns: 'common' })}
|
||||
</Button>
|
||||
</SettingModal>
|
||||
)}
|
||||
|
||||
@ -58,7 +58,7 @@ const SettingContent = ({
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<div className="system-xl-semibold text-text-primary">{!imageUpload ? t('appDebug.feature.fileUpload.modalTitle') : t('appDebug.feature.imageUpload.modalTitle')}</div>
|
||||
<div className="system-xl-semibold text-text-primary">{!imageUpload ? t('feature.fileUpload.modalTitle', { ns: 'appDebug' }) : t('feature.imageUpload.modalTitle', { ns: 'appDebug' })}</div>
|
||||
<div className="cursor-pointer p-1" onClick={onClose}><RiCloseLine className="h-4 w-4 text-text-tertiary" /></div>
|
||||
</div>
|
||||
<FileUploadSetting
|
||||
@ -73,14 +73,14 @@ const SettingContent = ({
|
||||
onClick={onClose}
|
||||
className="mr-2"
|
||||
>
|
||||
{t('common.operation.cancel')}
|
||||
{t('operation.cancel', { ns: 'common' })}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleChange}
|
||||
disabled={tempPayload.allowed_file_types.length === 0}
|
||||
>
|
||||
{t('common.operation.save')}
|
||||
{t('operation.save', { ns: 'common' })}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -45,9 +45,9 @@ const FollowUp = ({
|
||||
<VirtualAssistant className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}
|
||||
title={t('feature.suggestedQuestionsAfterAnswer.title', { ns: 'appDebug' })}
|
||||
value={!!features.suggested?.enabled}
|
||||
description={t('appDebug.feature.suggestedQuestionsAfterAnswer.description')!}
|
||||
description={t('feature.suggestedQuestionsAfterAnswer.description', { ns: 'appDebug' })!}
|
||||
onChange={state => handleChange(FeatureEnum.suggested, state)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
@ -57,7 +57,7 @@ const FileUpload = ({
|
||||
)}
|
||||
title={(
|
||||
<div className="flex items-center">
|
||||
{t('appDebug.feature.imageUpload.title')}
|
||||
{t('feature.imageUpload.title', { ns: 'appDebug' })}
|
||||
<Badge
|
||||
text="LEGACY"
|
||||
className="mx-1 shrink-0 border-text-accent-secondary text-text-accent-secondary"
|
||||
@ -72,19 +72,19 @@ const FileUpload = ({
|
||||
>
|
||||
<>
|
||||
{!file?.enabled && (
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('appDebug.feature.imageUpload.description')}</div>
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('feature.imageUpload.description', { ns: 'appDebug' })}</div>
|
||||
)}
|
||||
{file?.enabled && (
|
||||
<>
|
||||
{!isHovering && !modalOpen && (
|
||||
<div className="flex items-center gap-4 pt-0.5">
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.feature.imageUpload.supportedTypes')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('feature.imageUpload.supportedTypes', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{supportedTypes}</div>
|
||||
</div>
|
||||
<div className="h-[27px] w-px rotate-12 bg-divider-subtle"></div>
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.feature.imageUpload.numberLimit')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('feature.imageUpload.numberLimit', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{file?.number_limits}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -101,7 +101,7 @@ const FileUpload = ({
|
||||
>
|
||||
<Button className="w-full" disabled={disabled}>
|
||||
<RiEqualizer2Line className="mr-1 h-4 w-4" />
|
||||
{t('common.operation.settings')}
|
||||
{t('operation.settings', { ns: 'common' })}
|
||||
</Button>
|
||||
</SettingModal>
|
||||
)}
|
||||
|
||||
@ -60,8 +60,8 @@ const NewFeaturePanel = ({
|
||||
{/* header */}
|
||||
<div className="flex shrink-0 justify-between p-4 pb-3">
|
||||
<div>
|
||||
<div className="system-xl-semibold text-text-primary">{t('workflow.common.features')}</div>
|
||||
<div className="body-xs-regular text-text-tertiary">{t('workflow.common.featuresDescription')}</div>
|
||||
<div className="system-xl-semibold text-text-primary">{t('common.features', { ns: 'workflow' })}</div>
|
||||
<div className="body-xs-regular text-text-tertiary">{t('common.featuresDescription', { ns: 'workflow' })}</div>
|
||||
</div>
|
||||
<div className="h-8 w-8 cursor-pointer p-2" onClick={onClose}><RiCloseLine className="h-4 w-4 text-text-tertiary" /></div>
|
||||
</div>
|
||||
@ -75,14 +75,14 @@ const NewFeaturePanel = ({
|
||||
<RiInformation2Fill className="h-5 w-5 text-text-accent" />
|
||||
</div>
|
||||
<div className="system-xs-medium p-1 text-text-primary">
|
||||
<span>{isChatMode ? t('workflow.common.fileUploadTip') : t('workflow.common.ImageUploadLegacyTip')}</span>
|
||||
<span>{isChatMode ? t('common.fileUploadTip', { ns: 'workflow' }) : t('common.ImageUploadLegacyTip', { ns: 'workflow' })}</span>
|
||||
<a
|
||||
className="text-text-accent"
|
||||
href={docLink('/guides/workflow/bulletin')}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{t('workflow.common.featuresDocLink')}
|
||||
{t('common.featuresDocLink', { ns: 'workflow' })}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -106,22 +106,22 @@ const Moderation = ({
|
||||
|
||||
const providerContent = useMemo(() => {
|
||||
if (moderation?.type === 'openai_moderation')
|
||||
return t('appDebug.feature.moderation.modal.provider.openai')
|
||||
return t('feature.moderation.modal.provider.openai', { ns: 'appDebug' })
|
||||
else if (moderation?.type === 'keywords')
|
||||
return t('appDebug.feature.moderation.modal.provider.keywords')
|
||||
return t('feature.moderation.modal.provider.keywords', { ns: 'appDebug' })
|
||||
else if (moderation?.type === 'api')
|
||||
return t('common.apiBasedExtension.selector.title')
|
||||
return t('apiBasedExtension.selector.title', { ns: 'common' })
|
||||
else
|
||||
return codeBasedExtensionList?.data.find(item => item.name === moderation?.type)?.label[locale] || '-'
|
||||
}, [codeBasedExtensionList?.data, locale, moderation?.type, t])
|
||||
|
||||
const enableContent = useMemo(() => {
|
||||
if (moderation?.config?.inputs_config?.enabled && moderation.config?.outputs_config?.enabled)
|
||||
return t('appDebug.feature.moderation.allEnabled')
|
||||
return t('feature.moderation.allEnabled', { ns: 'appDebug' })
|
||||
else if (moderation?.config?.inputs_config?.enabled)
|
||||
return t('appDebug.feature.moderation.inputEnabled')
|
||||
return t('feature.moderation.inputEnabled', { ns: 'appDebug' })
|
||||
else if (moderation?.config?.outputs_config?.enabled)
|
||||
return t('appDebug.feature.moderation.outputEnabled')
|
||||
return t('feature.moderation.outputEnabled', { ns: 'appDebug' })
|
||||
}, [moderation?.config?.inputs_config?.enabled, moderation?.config?.outputs_config?.enabled, t])
|
||||
|
||||
return (
|
||||
@ -131,7 +131,7 @@ const Moderation = ({
|
||||
<ContentModeration className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.moderation.title')}
|
||||
title={t('feature.moderation.title', { ns: 'appDebug' })}
|
||||
value={!!moderation?.enabled}
|
||||
onChange={state => handleChange(FeatureEnum.moderation, state)}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
@ -140,19 +140,19 @@ const Moderation = ({
|
||||
>
|
||||
<>
|
||||
{!moderation?.enabled && (
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('appDebug.feature.moderation.description')}</div>
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('feature.moderation.description', { ns: 'appDebug' })}</div>
|
||||
)}
|
||||
{!!moderation?.enabled && (
|
||||
<>
|
||||
{!isHovering && (
|
||||
<div className="flex items-center gap-4 pt-0.5">
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.feature.moderation.modal.provider.title')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('feature.moderation.modal.provider.title', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{providerContent}</div>
|
||||
</div>
|
||||
<div className="h-[27px] w-px rotate-12 bg-divider-subtle"></div>
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.feature.moderation.contentEnableLabel')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('feature.moderation.contentEnableLabel', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{enableContent}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -160,7 +160,7 @@ const Moderation = ({
|
||||
{isHovering && (
|
||||
<Button className="w-full" onClick={handleOpenModerationSettingModal} disabled={disabled}>
|
||||
<RiEqualizer2Line className="mr-1 h-4 w-4" />
|
||||
{t('common.operation.settings')}
|
||||
{t('operation.settings', { ns: 'common' })}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
|
||||
@ -47,14 +47,14 @@ const ModerationContent: FC<ModerationContentProps> = ({
|
||||
config.enabled && showPreset && (
|
||||
<div className="rounded-lg bg-components-panel-bg px-3 pb-3 pt-1">
|
||||
<div className="flex h-8 items-center justify-between text-[13px] font-medium text-text-secondary">
|
||||
{t('appDebug.feature.moderation.modal.content.preset')}
|
||||
<span className="text-xs font-normal text-text-tertiary">{t('appDebug.feature.moderation.modal.content.supportMarkdown')}</span>
|
||||
{t('feature.moderation.modal.content.preset', { ns: 'appDebug' })}
|
||||
<span className="text-xs font-normal text-text-tertiary">{t('feature.moderation.modal.content.supportMarkdown', { ns: 'appDebug' })}</span>
|
||||
</div>
|
||||
<div className="relative h-20 rounded-lg bg-components-input-bg-normal px-3 py-2">
|
||||
<textarea
|
||||
value={config.preset_response || ''}
|
||||
className="block h-full w-full resize-none appearance-none bg-transparent text-sm text-text-secondary outline-none"
|
||||
placeholder={t('appDebug.feature.moderation.modal.content.placeholder') || ''}
|
||||
placeholder={t('feature.moderation.modal.content.placeholder', { ns: 'appDebug' }) || ''}
|
||||
onChange={e => handleConfigChange('preset_response', e.target.value)}
|
||||
/>
|
||||
<div className="absolute bottom-2 right-2 flex h-5 items-center rounded-md bg-background-section px-1 text-xs font-medium text-text-quaternary">
|
||||
|
||||
@ -67,15 +67,15 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
const providers: Provider[] = [
|
||||
{
|
||||
key: 'openai_moderation',
|
||||
name: t('appDebug.feature.moderation.modal.provider.openai'),
|
||||
name: t('feature.moderation.modal.provider.openai', { ns: 'appDebug' }),
|
||||
},
|
||||
{
|
||||
key: 'keywords',
|
||||
name: t('appDebug.feature.moderation.modal.provider.keywords'),
|
||||
name: t('feature.moderation.modal.provider.keywords', { ns: 'appDebug' }),
|
||||
},
|
||||
{
|
||||
key: 'api',
|
||||
name: t('common.apiBasedExtension.selector.title'),
|
||||
name: t('apiBasedExtension.selector.title', { ns: 'common' }),
|
||||
},
|
||||
...(
|
||||
codeBasedExtensionList
|
||||
@ -193,17 +193,17 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
return
|
||||
|
||||
if (!localeData.config?.inputs_config?.enabled && !localeData.config?.outputs_config?.enabled) {
|
||||
notify({ type: 'error', message: t('appDebug.feature.moderation.modal.content.condition') })
|
||||
notify({ type: 'error', message: t('feature.moderation.modal.content.condition', { ns: 'appDebug' }) })
|
||||
return
|
||||
}
|
||||
|
||||
if (localeData.type === 'keywords' && !localeData.config.keywords) {
|
||||
notify({ type: 'error', message: t('appDebug.errorMessage.valueOfVarRequired', { key: locale !== LanguagesSupported[1] ? 'keywords' : '关键词' }) })
|
||||
notify({ type: 'error', message: t('errorMessage.valueOfVarRequired', { ns: 'appDebug', key: locale !== LanguagesSupported[1] ? 'keywords' : '关键词' }) })
|
||||
return
|
||||
}
|
||||
|
||||
if (localeData.type === 'api' && !localeData.config.api_based_extension_id) {
|
||||
notify({ type: 'error', message: t('appDebug.errorMessage.valueOfVarRequired', { key: locale !== LanguagesSupported[1] ? 'API Extension' : 'API 扩展' }) })
|
||||
notify({ type: 'error', message: t('errorMessage.valueOfVarRequired', { ns: 'appDebug', key: locale !== LanguagesSupported[1] ? 'API Extension' : 'API 扩展' }) })
|
||||
return
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
if (!localeData.config?.[currentProvider.form_schema[i].variable] && currentProvider.form_schema[i].required) {
|
||||
notify({
|
||||
type: 'error',
|
||||
message: t('appDebug.errorMessage.valueOfVarRequired', { key: locale !== LanguagesSupported[1] ? currentProvider.form_schema[i].label['en-US'] : currentProvider.form_schema[i].label['zh-Hans'] }),
|
||||
message: t('errorMessage.valueOfVarRequired', { ns: 'appDebug', key: locale !== LanguagesSupported[1] ? currentProvider.form_schema[i].label['en-US'] : currentProvider.form_schema[i].label['zh-Hans'] }),
|
||||
})
|
||||
return
|
||||
}
|
||||
@ -220,12 +220,12 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
}
|
||||
|
||||
if (localeData.config.inputs_config?.enabled && !localeData.config.inputs_config.preset_response && localeData.type !== 'api') {
|
||||
notify({ type: 'error', message: t('appDebug.feature.moderation.modal.content.errorMessage') })
|
||||
notify({ type: 'error', message: t('feature.moderation.modal.content.errorMessage', { ns: 'appDebug' }) })
|
||||
return
|
||||
}
|
||||
|
||||
if (localeData.config.outputs_config?.enabled && !localeData.config.outputs_config.preset_response && localeData.type !== 'api') {
|
||||
notify({ type: 'error', message: t('appDebug.feature.moderation.modal.content.errorMessage') })
|
||||
notify({ type: 'error', message: t('feature.moderation.modal.content.errorMessage', { ns: 'appDebug' }) })
|
||||
return
|
||||
}
|
||||
|
||||
@ -239,12 +239,12 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
className="!mt-14 !w-[600px] !max-w-none !p-6"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="title-2xl-semi-bold text-text-primary">{t('appDebug.feature.moderation.modal.title')}</div>
|
||||
<div className="title-2xl-semi-bold text-text-primary">{t('feature.moderation.modal.title', { ns: 'appDebug' })}</div>
|
||||
<div className="cursor-pointer p-1" onClick={onCancel}><RiCloseLine className="h-4 w-4 text-text-tertiary" /></div>
|
||||
</div>
|
||||
<div className="py-2">
|
||||
<div className="text-sm font-medium leading-9 text-text-primary">
|
||||
{t('appDebug.feature.moderation.modal.provider.title')}
|
||||
{t('feature.moderation.modal.provider.title', { ns: 'appDebug' })}
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2.5">
|
||||
{
|
||||
@ -275,16 +275,16 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
<div className="mt-2 flex items-center rounded-lg border border-[#FEF0C7] bg-[#FFFAEB] px-3 py-2">
|
||||
<InfoCircle className="mr-1 h-4 w-4 text-[#F79009]" />
|
||||
<div className="flex items-center text-xs font-medium text-gray-700">
|
||||
{t('appDebug.feature.moderation.modal.openaiNotConfig.before')}
|
||||
{t('feature.moderation.modal.openaiNotConfig.before', { ns: 'appDebug' })}
|
||||
<span
|
||||
className="cursor-pointer text-primary-600"
|
||||
onClick={handleOpenSettingsModal}
|
||||
>
|
||||
|
||||
{t('common.settings.provider')}
|
||||
{t('settings.provider', { ns: 'common' })}
|
||||
|
||||
</span>
|
||||
{t('appDebug.feature.moderation.modal.openaiNotConfig.after')}
|
||||
{t('feature.moderation.modal.openaiNotConfig.after', { ns: 'appDebug' })}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@ -293,21 +293,21 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
{
|
||||
localeData.type === 'keywords' && (
|
||||
<div className="py-2">
|
||||
<div className="mb-1 text-sm font-medium text-text-primary">{t('appDebug.feature.moderation.modal.provider.keywords')}</div>
|
||||
<div className="mb-2 text-xs text-text-tertiary">{t('appDebug.feature.moderation.modal.keywords.tip')}</div>
|
||||
<div className="mb-1 text-sm font-medium text-text-primary">{t('feature.moderation.modal.provider.keywords', { ns: 'appDebug' })}</div>
|
||||
<div className="mb-2 text-xs text-text-tertiary">{t('feature.moderation.modal.keywords.tip', { ns: 'appDebug' })}</div>
|
||||
<div className="relative h-[88px] rounded-lg bg-components-input-bg-normal px-3 py-2">
|
||||
<textarea
|
||||
value={localeData.config?.keywords || ''}
|
||||
onChange={handleDataKeywordsChange}
|
||||
className="block h-full w-full resize-none appearance-none bg-transparent text-sm text-text-secondary outline-none"
|
||||
placeholder={t('appDebug.feature.moderation.modal.keywords.placeholder') || ''}
|
||||
placeholder={t('feature.moderation.modal.keywords.placeholder', { ns: 'appDebug' }) || ''}
|
||||
/>
|
||||
<div className="absolute bottom-2 right-2 flex h-5 items-center rounded-md bg-background-section px-1 text-xs font-medium text-text-quaternary">
|
||||
<span>{(localeData.config?.keywords || '').split('\n').filter(Boolean).length}</span>
|
||||
/
|
||||
<span className="text-text-tertiary">
|
||||
100
|
||||
{t('appDebug.feature.moderation.modal.keywords.line')}
|
||||
{t('feature.moderation.modal.keywords.line', { ns: 'appDebug' })}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -318,7 +318,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
localeData.type === 'api' && (
|
||||
<div className="py-2">
|
||||
<div className="flex h-9 items-center justify-between">
|
||||
<div className="text-sm font-medium text-text-primary">{t('common.apiBasedExtension.selector.title')}</div>
|
||||
<div className="text-sm font-medium text-text-primary">{t('apiBasedExtension.selector.title', { ns: 'common' })}</div>
|
||||
<a
|
||||
href={docLink('/guides/extension/api-based-extension/README')}
|
||||
target="_blank"
|
||||
@ -326,7 +326,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
className="group flex items-center text-xs text-text-tertiary hover:text-primary-600"
|
||||
>
|
||||
<BookOpen01 className="mr-1 h-3 w-3 text-text-tertiary group-hover:text-primary-600" />
|
||||
{t('common.apiBasedExtension.link')}
|
||||
{t('apiBasedExtension.link', { ns: 'common' })}
|
||||
</a>
|
||||
</div>
|
||||
<ApiBasedExtensionSelector
|
||||
@ -349,33 +349,33 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
|
||||
}
|
||||
<Divider bgStyle="gradient" className="my-3 h-px" />
|
||||
<ModerationContent
|
||||
title={t('appDebug.feature.moderation.modal.content.input') || ''}
|
||||
title={t('feature.moderation.modal.content.input', { ns: 'appDebug' }) || ''}
|
||||
config={localeData.config?.inputs_config || { enabled: false, preset_response: '' }}
|
||||
onConfigChange={config => handleDataContentChange('inputs_config', config)}
|
||||
info={(localeData.type === 'api' && t('appDebug.feature.moderation.modal.content.fromApi')) || ''}
|
||||
info={(localeData.type === 'api' && t('feature.moderation.modal.content.fromApi', { ns: 'appDebug' })) || ''}
|
||||
showPreset={localeData.type !== 'api'}
|
||||
/>
|
||||
<ModerationContent
|
||||
title={t('appDebug.feature.moderation.modal.content.output') || ''}
|
||||
title={t('feature.moderation.modal.content.output', { ns: 'appDebug' }) || ''}
|
||||
config={localeData.config?.outputs_config || { enabled: false, preset_response: '' }}
|
||||
onConfigChange={config => handleDataContentChange('outputs_config', config)}
|
||||
info={(localeData.type === 'api' && t('appDebug.feature.moderation.modal.content.fromApi')) || ''}
|
||||
info={(localeData.type === 'api' && t('feature.moderation.modal.content.fromApi', { ns: 'appDebug' })) || ''}
|
||||
showPreset={localeData.type !== 'api'}
|
||||
/>
|
||||
<div className="mb-8 mt-1 text-xs font-medium text-text-tertiary">{t('appDebug.feature.moderation.modal.content.condition')}</div>
|
||||
<div className="mb-8 mt-1 text-xs font-medium text-text-tertiary">{t('feature.moderation.modal.content.condition', { ns: 'appDebug' })}</div>
|
||||
<div className="flex items-center justify-end">
|
||||
<Button
|
||||
onClick={onCancel}
|
||||
className="mr-2"
|
||||
>
|
||||
{t('common.operation.cancel')}
|
||||
{t('operation.cancel', { ns: 'common' })}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleSave}
|
||||
disabled={localeData.type === 'openai_moderation' && !isOpenAIProviderConfigured}
|
||||
>
|
||||
{t('common.operation.save')}
|
||||
{t('operation.save', { ns: 'common' })}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@ -45,10 +45,10 @@ const MoreLikeThis = ({
|
||||
<RiSparklingFill className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.moreLikeThis.title')}
|
||||
tooltip={t('appDebug.feature.moreLikeThis.tip')}
|
||||
title={t('feature.moreLikeThis.title', { ns: 'appDebug' })}
|
||||
tooltip={t('feature.moreLikeThis.tip', { ns: 'appDebug' })}
|
||||
value={!!features.moreLikeThis?.enabled}
|
||||
description={t('appDebug.feature.moreLikeThis.description')!}
|
||||
description={t('feature.moreLikeThis.description', { ns: 'appDebug' })!}
|
||||
onChange={state => handleChange(FeatureEnum.moreLikeThis, state)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
@ -45,9 +45,9 @@ const SpeechToText = ({
|
||||
<Microphone01 className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.speechToText.title')}
|
||||
title={t('feature.speechToText.title', { ns: 'appDebug' })}
|
||||
value={!!features.speech2text?.enabled}
|
||||
description={t('appDebug.feature.speechToText.description')!}
|
||||
description={t('feature.speechToText.description', { ns: 'appDebug' })!}
|
||||
onChange={state => handleChange(FeatureEnum.speech2text, state)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
@ -54,7 +54,7 @@ const TextToSpeech = ({
|
||||
<TextToAudio className="h-4 w-4 text-text-primary-on-surface" />
|
||||
</div>
|
||||
)}
|
||||
title={t('appDebug.feature.textToSpeech.title')}
|
||||
title={t('feature.textToSpeech.title', { ns: 'appDebug' })}
|
||||
value={!!features.text2speech?.enabled}
|
||||
onChange={state => handleChange(FeatureEnum.text2speech, state)}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
@ -63,25 +63,25 @@ const TextToSpeech = ({
|
||||
>
|
||||
<>
|
||||
{!features.text2speech?.enabled && (
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('appDebug.feature.textToSpeech.description')}</div>
|
||||
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{t('feature.textToSpeech.description', { ns: 'appDebug' })}</div>
|
||||
)}
|
||||
{!!features.text2speech?.enabled && (
|
||||
<>
|
||||
{!isHovering && !modalOpen && (
|
||||
<div className="flex items-center gap-4 pt-0.5">
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.voice.voiceSettings.language')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('voice.voiceSettings.language', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{languageInfo?.name || '-'}</div>
|
||||
</div>
|
||||
<div className="h-[27px] w-px rotate-12 bg-divider-subtle"></div>
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.voice.voiceSettings.voice')}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{features.text2speech?.voice || t('appDebug.voice.defaultDisplay')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('voice.voiceSettings.voice', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{features.text2speech?.voice || t('voice.defaultDisplay', { ns: 'appDebug' })}</div>
|
||||
</div>
|
||||
<div className="h-[27px] w-px rotate-12 bg-divider-subtle"></div>
|
||||
<div className="">
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('appDebug.voice.voiceSettings.autoPlay')}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{features.text2speech?.autoPlay === TtsAutoPlay.enabled ? t('appDebug.voice.voiceSettings.autoPlayEnabled') : t('appDebug.voice.voiceSettings.autoPlayDisabled')}</div>
|
||||
<div className="system-2xs-medium-uppercase mb-0.5 text-text-tertiary">{t('voice.voiceSettings.autoPlay', { ns: 'appDebug' })}</div>
|
||||
<div className="system-xs-regular text-text-secondary">{features.text2speech?.autoPlay === TtsAutoPlay.enabled ? t('voice.voiceSettings.autoPlayEnabled', { ns: 'appDebug' }) : t('voice.voiceSettings.autoPlayDisabled', { ns: 'appDebug' })}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@ -89,7 +89,7 @@ const TextToSpeech = ({
|
||||
<VoiceSettings open={modalOpen && !disabled} onOpen={setModalOpen} onChange={onChange}>
|
||||
<Button className="w-full" disabled={disabled}>
|
||||
<RiEqualizer2Line className="mr-1 h-4 w-4" />
|
||||
{t('appDebug.voice.voiceSettings.title')}
|
||||
{t('voice.voiceSettings.title', { ns: 'appDebug' })}
|
||||
</Button>
|
||||
</VoiceSettings>
|
||||
)}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
import type { OnFeaturesChange } from '@/app/components/base/features/types'
|
||||
import type { Item } from '@/app/components/base/select'
|
||||
import type { I18nKeysWithPrefix } from '@/types/i18n'
|
||||
import { Listbox, ListboxButton, ListboxOption, ListboxOptions, Transition } from '@headlessui/react'
|
||||
import { CheckIcon, ChevronDownIcon } from '@heroicons/react/20/solid'
|
||||
import { RiCloseLine } from '@remixicon/react'
|
||||
@ -9,6 +10,7 @@ import { usePathname } from 'next/navigation'
|
||||
import * as React from 'react'
|
||||
import { Fragment } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { replace } from 'string-ts'
|
||||
import AudioBtn from '@/app/components/base/audio-btn'
|
||||
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
@ -18,6 +20,8 @@ import { useAppVoices } from '@/service/use-apps'
|
||||
import { TtsAutoPlay } from '@/types/app'
|
||||
import { cn } from '@/utils/classnames'
|
||||
|
||||
type VoiceLanguageKey = I18nKeysWithPrefix<'common', 'voice.language.'>
|
||||
|
||||
type VoiceParamConfigProps = {
|
||||
onClose: () => void
|
||||
onChange?: OnFeaturesChange
|
||||
@ -36,14 +40,14 @@ const VoiceParamConfig = ({
|
||||
let languageItem = languages.find(item => item.value === text2speech?.language)
|
||||
if (languages && !languageItem)
|
||||
languageItem = languages[0]
|
||||
const localLanguagePlaceholder = languageItem?.name || t('common.placeholder.select')
|
||||
const localLanguagePlaceholder = languageItem?.name || t('placeholder.select', { ns: 'common' })
|
||||
|
||||
const language = languageItem?.value
|
||||
const { data: voiceItems } = useAppVoices(appId, language)
|
||||
let voiceItem = voiceItems?.find(item => item.value === text2speech?.voice)
|
||||
if (voiceItems && !voiceItem)
|
||||
voiceItem = voiceItems[0]
|
||||
const localVoicePlaceholder = voiceItem?.name || t('common.placeholder.select')
|
||||
const localVoicePlaceholder = voiceItem?.name || t('placeholder.select', { ns: 'common' })
|
||||
|
||||
const handleChange = (value: Record<string, string>) => {
|
||||
const {
|
||||
@ -66,16 +70,16 @@ const VoiceParamConfig = ({
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<div className="system-xl-semibold text-text-primary">{t('appDebug.voice.voiceSettings.title')}</div>
|
||||
<div className="system-xl-semibold text-text-primary">{t('voice.voiceSettings.title', { ns: 'appDebug' })}</div>
|
||||
<div className="cursor-pointer p-1" onClick={onClose}><RiCloseLine className="h-4 w-4 text-text-tertiary" /></div>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div className="system-sm-semibold mb-1 flex items-center py-1 text-text-secondary">
|
||||
{t('appDebug.voice.voiceSettings.language')}
|
||||
{t('voice.voiceSettings.language', { ns: 'appDebug' })}
|
||||
<Tooltip
|
||||
popupContent={(
|
||||
<div className="w-[180px]">
|
||||
{t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => (
|
||||
{t('voice.voiceSettings.resolutionTooltip', { ns: 'appDebug' }).split('\n').map(item => (
|
||||
<div key={item}>
|
||||
{item}
|
||||
</div>
|
||||
@ -97,7 +101,7 @@ const VoiceParamConfig = ({
|
||||
className="h-full w-full cursor-pointer rounded-lg border-0 bg-components-input-bg-normal py-1.5 pl-3 pr-10 focus-visible:bg-state-base-hover focus-visible:outline-none group-hover:bg-state-base-hover sm:text-sm sm:leading-6"
|
||||
>
|
||||
<span className={cn('block truncate text-left text-text-secondary', !languageItem?.name && 'text-text-tertiary')}>
|
||||
{languageItem?.name ? t(`common.voice.language.${languageItem?.value.replace('-', '')}` as any) as string : localLanguagePlaceholder}
|
||||
{languageItem?.name ? t(`voice.language.${replace(languageItem?.value, '-', '')}`, { ns: 'common' }) : localLanguagePlaceholder}
|
||||
</span>
|
||||
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
||||
<ChevronDownIcon
|
||||
@ -116,7 +120,7 @@ const VoiceParamConfig = ({
|
||||
<ListboxOptions
|
||||
className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md border-[0.5px] border-components-panel-border bg-components-panel-bg px-1 py-1 text-base shadow-lg focus:outline-none sm:text-sm"
|
||||
>
|
||||
{languages.map((item: Item) => (
|
||||
{languages.map(item => (
|
||||
<ListboxOption
|
||||
key={item.value}
|
||||
className="relative cursor-pointer select-none rounded-lg py-2 pl-3 pr-9 text-text-secondary hover:bg-state-base-hover data-[active]:bg-state-base-active"
|
||||
@ -128,7 +132,7 @@ const VoiceParamConfig = ({
|
||||
<span
|
||||
className={cn('block', selected && 'font-normal')}
|
||||
>
|
||||
{t(`common.voice.language.${(item.value).toString().replace('-', '')}` as any) as string}
|
||||
{t(`voice.language.${replace((item.value), '-', '')}`, { ns: 'common' })}
|
||||
</span>
|
||||
{(selected || item.value === text2speech?.language) && (
|
||||
<span
|
||||
@ -148,7 +152,7 @@ const VoiceParamConfig = ({
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div className="system-sm-semibold mb-1 py-1 text-text-secondary">
|
||||
{t('appDebug.voice.voiceSettings.voice')}
|
||||
{t('voice.voiceSettings.voice', { ns: 'appDebug' })}
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Listbox
|
||||
@ -225,7 +229,7 @@ const VoiceParamConfig = ({
|
||||
</div>
|
||||
<div>
|
||||
<div className="system-sm-semibold mb-1 py-1 text-text-secondary">
|
||||
{t('appDebug.voice.voiceSettings.autoPlay')}
|
||||
{t('voice.voiceSettings.autoPlay', { ns: 'appDebug' })}
|
||||
</div>
|
||||
<Switch
|
||||
className="shrink-0"
|
||||
|
||||
Reference in New Issue
Block a user