Quellcode durchsuchen

refactor: generalize method for getting doc link respecting locale and fix error link paths (#20801)

tags/1.4.3
Bowen Liang vor 4 Monaten
Ursprung
Commit
f4df759ba6
Es ist kein Account mit der E-Mail-Adresse des Committers verbunden
36 geänderte Dateien mit 149 neuen und 136 gelöschten Zeilen
  1. 3
    8
      web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx
  2. 4
    7
      web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx
  3. 3
    1
      web/app/components/app/configuration/dataset-config/settings-modal/index.tsx
  4. 3
    5
      web/app/components/app/configuration/prompt-mode/advanced-mode-waring.tsx
  5. 8
    5
      web/app/components/app/create-app-modal/index.tsx
  6. 3
    8
      web/app/components/app/overview/customize/index.tsx
  7. 5
    5
      web/app/components/app/overview/settings/index.tsx
  8. 3
    5
      web/app/components/base/features/new-feature-panel/index.tsx
  9. 5
    1
      web/app/components/datasets/create/step-two/index.tsx
  10. 3
    1
      web/app/components/datasets/create/website/base/url-input.tsx
  11. 3
    1
      web/app/components/datasets/create/website/jina-reader/base/url-input.tsx
  12. 3
    8
      web/app/components/datasets/documents/index.tsx
  13. 3
    1
      web/app/components/datasets/external-api/external-api-modal/Form.tsx
  14. 4
    1
      web/app/components/datasets/external-api/external-api-panel/index.tsx
  15. 7
    2
      web/app/components/datasets/external-knowledge-base/create/InfoPanel.tsx
  16. 3
    1
      web/app/components/datasets/external-knowledge-base/create/index.tsx
  17. 3
    1
      web/app/components/datasets/hit-testing/modify-retrieval-modal.tsx
  18. 3
    1
      web/app/components/datasets/settings/form/index.tsx
  19. 3
    3
      web/app/components/header/account-dropdown/index.tsx
  20. 3
    5
      web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx
  21. 5
    3
      web/app/components/tools/provider/custom-create-card.tsx
  22. 6
    9
      web/app/components/workflow/nodes/_base/components/agent-strategy.tsx
  23. 3
    1
      web/app/components/workflow/nodes/_base/components/error-handle/default-value.tsx
  24. 3
    1
      web/app/components/workflow/nodes/_base/components/error-handle/fail-branch-card.tsx
  25. 6
    6
      web/app/components/workflow/nodes/_base/components/variable/var-reference-popup.tsx
  26. 3
    5
      web/app/components/workflow/nodes/_base/hooks/use-node-help-link.ts
  27. 3
    3
      web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx
  28. 7
    6
      web/app/components/workflow/panel/chat-variable-panel/index.tsx
  29. 3
    1
      web/app/components/workflow/run/node.tsx
  30. 3
    1
      web/app/components/workflow/run/status.tsx
  31. 3
    13
      web/app/education-apply/education-apply-page.tsx
  32. 6
    13
      web/app/education-apply/verify-state-modal.tsx
  33. 3
    1
      web/app/install/installForm.tsx
  34. 4
    2
      web/app/signin/invite-settings/page.tsx
  35. 3
    1
      web/app/signin/oneMoreStep.tsx
  36. 13
    0
      web/context/i18n.ts

+ 3
- 8
web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx Datei anzeigen

import DatasetDetailContext from '@/context/dataset-detail' import DatasetDetailContext from '@/context/dataset-detail'
import { DataSourceType } from '@/models/datasets' import { DataSourceType } from '@/models/datasets'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { LanguagesSupported } from '@/i18n/language'
import { useStore } from '@/app/components/app/store' import { useStore } from '@/app/components/app/store'
import { getLocaleOnClient } from '@/i18n'
import { useDocLink } from '@/context/i18n'
import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import LinkedAppsPanel from '@/app/components/base/linked-apps-panel' import LinkedAppsPanel from '@/app/components/base/linked-apps-panel'
} }


const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => { const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => {
const locale = getLocaleOnClient()
const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile) const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile)
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()


const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0 const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0
const relatedAppsTotal = relatedApps?.data?.length || 0 const relatedAppsTotal = relatedApps?.data?.length || 0
<div className='my-2 text-xs text-text-tertiary'>{t('common.datasetMenus.emptyTip')}</div> <div className='my-2 text-xs text-text-tertiary'>{t('common.datasetMenus.emptyTip')}</div>
<a <a
className='mt-2 inline-flex cursor-pointer items-center text-xs text-text-accent' className='mt-2 inline-flex cursor-pointer items-center text-xs text-text-accent'
href={
locale === LanguagesSupported[1]
? 'https://docs.dify.ai/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
: 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application'
}
href={docLink('/guides/knowledge-base/integrate-knowledge-within-application')}
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
> >
<RiBookOpenLine className='mr-1 text-text-accent' /> <RiBookOpenLine className='mr-1 text-text-accent' />

+ 4
- 7
web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx Datei anzeigen

'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useContext } from 'use-context-selector'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import OperationBtn from '@/app/components/app/configuration/base/operation-btn' import OperationBtn from '@/app/components/app/configuration/base/operation-btn'
import Panel from '@/app/components/app/configuration/base/feature-panel' import Panel from '@/app/components/app/configuration/base/feature-panel'
import { MessageClockCircle } from '@/app/components/base/icons/src/vender/solid/general' import { MessageClockCircle } from '@/app/components/base/icons/src/vender/solid/general'
import I18n from '@/context/i18n'
import { LanguagesSupported } from '@/i18n/language'
import { useDocLink } from '@/context/i18n'


type Props = { type Props = {
showWarning: boolean showWarning: boolean
onShowEditModal, onShowEditModal,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()


return ( return (
<Panel <Panel
{showWarning && ( {showWarning && (
<div className='flex justify-between rounded-b-xl bg-background-section-burn px-3 py-2 text-xs text-text-secondary'> <div className='flex justify-between rounded-b-xl bg-background-section-burn px-3 py-2 text-xs text-text-secondary'>
<div>{t('appDebug.feature.conversationHistory.tip')} <div>{t('appDebug.feature.conversationHistory.tip')}
<a href={`${locale === LanguagesSupported[1]
? 'https://docs.dify.ai/zh-hans/learn-more/extended-reading/prompt-engineering/README'
: 'https://docs.dify.ai/en/features/prompt-engineering'}`}
<a href={docLink('/learn-more/extended-reading/what-is-llmops',
{ 'zh-Hans': '/learn-more/extended-reading/prompt-engineering/README' })}
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
className='text-[#155EEF]'>{t('appDebug.feature.conversationHistory.learnMore')} className='text-[#155EEF]'>{t('appDebug.feature.conversationHistory.learnMore')}
</a> </a>

+ 3
- 1
web/app/components/app/configuration/dataset-config/settings-modal/index.tsx Datei anzeigen

import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { fetchMembers } from '@/service/common' import { fetchMembers } from '@/service/common'
import type { Member } from '@/models/common' import type { Member } from '@/models/common'
import { useDocLink } from '@/context/i18n'


type SettingsModalProps = { type SettingsModalProps = {
currentDataset: DataSet currentDataset: DataSet
currentModel: isRerankDefaultModelValid, currentModel: isRerankDefaultModelValid,
} = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.rerank) } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.rerank)
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const { notify } = useToastContext() const { notify } = useToastContext()
const ref = useRef(null) const ref = useRef(null)
const isExternal = currentDataset.provider === 'external' const isExternal = currentDataset.provider === 'external'
<div> <div>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.retrievalSetting.title')}</div> <div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.retrievalSetting.title')}</div>
<div className='text-xs font-normal leading-[18px] text-text-tertiary'> <div className='text-xs font-normal leading-[18px] text-text-tertiary'>
<a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
<a target='_blank' rel='noopener noreferrer' href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#setting-the-retrieval-setting')} className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
{t('datasetSettings.form.retrievalSetting.description')} {t('datasetSettings.form.retrievalSetting.description')}
</div> </div>
</div> </div>

+ 3
- 5
web/app/components/app/configuration/prompt-mode/advanced-mode-waring.tsx Datei anzeigen

import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import I18n from '@/context/i18n'
import { LanguagesSupported } from '@/i18n/language'
import { useDocLink } from '@/context/i18n'
type Props = { type Props = {
onReturnToSimpleMode: () => void onReturnToSimpleMode: () => void
} }
onReturnToSimpleMode, onReturnToSimpleMode,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()
const [show, setShow] = React.useState(true) const [show, setShow] = React.useState(true)
if (!show) if (!show)
return null return null
<span className='text-gray-700'>{t('appDebug.promptMode.advancedWarning.description')}</span> <span className='text-gray-700'>{t('appDebug.promptMode.advancedWarning.description')}</span>
<a <a
className='font-medium text-[#155EEF]' className='font-medium text-[#155EEF]'
href={`https://docs.dify.ai/${locale === LanguagesSupported[1] ? '/guides/features/prompt-engineering' : 'features/prompt-engineering'}`}
href={docLink('/guides/features/prompt-engineering')}
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
> >
{t('appDebug.promptMode.advancedWarning.learnMore')} {t('appDebug.promptMode.advancedWarning.learnMore')}

+ 8
- 5
web/app/components/app/create-app-modal/index.tsx Datei anzeigen

import { getRedirection } from '@/utils/app-redirection' import { getRedirection } from '@/utils/app-redirection'
import FullScreenModal from '@/app/components/base/fullscreen-modal' import FullScreenModal from '@/app/components/base/fullscreen-modal'
import useTheme from '@/hooks/use-theme' import useTheme from '@/hooks/use-theme'
import { useDocLink } from '@/context/i18n'


type CreateAppProps = { type CreateAppProps = {
onSuccess: () => void onSuccess: () => void


function AppPreview({ mode }: { mode: AppMode }) { function AppPreview({ mode }: { mode: AppMode }) {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const modeToPreviewInfoMap = { const modeToPreviewInfoMap = {
'chat': { 'chat': {
title: t('app.types.chatbot'), title: t('app.types.chatbot'),
description: t('app.newApp.chatbotUserDescription'), description: t('app.newApp.chatbotUserDescription'),
link: 'https://docs.dify.ai/guides/application-orchestrate/readme',
link: docLink('/guides/application-orchestrate/chatbot-application'),
}, },
'advanced-chat': { 'advanced-chat': {
title: t('app.types.advanced'), title: t('app.types.advanced'),
description: t('app.newApp.advancedUserDescription'), description: t('app.newApp.advancedUserDescription'),
link: 'https://docs.dify.ai/en/guides/workflow/README',
link: docLink('/guides/workflow/readme'),
}, },
'agent-chat': { 'agent-chat': {
title: t('app.types.agent'), title: t('app.types.agent'),
description: t('app.newApp.agentUserDescription'), description: t('app.newApp.agentUserDescription'),
link: 'https://docs.dify.ai/en/guides/application-orchestrate/agent',
link: docLink('/guides/application-orchestrate/agent'),
}, },
'completion': { 'completion': {
title: t('app.newApp.completeApp'), title: t('app.newApp.completeApp'),
description: t('app.newApp.completionUserDescription'), description: t('app.newApp.completionUserDescription'),
link: null,
link: docLink('/guides/application-orchestrate/text-generator',
{ 'zh-Hans': '/guides/application-orchestrate/readme' }),
}, },
'workflow': { 'workflow': {
title: t('app.types.workflow'), title: t('app.types.workflow'),
description: t('app.newApp.workflowUserDescription'), description: t('app.newApp.workflowUserDescription'),
link: 'https://docs.dify.ai/en/guides/workflow/README',
link: docLink('/guides/workflow/readme'),
}, },
} }
const previewInfo = modeToPreviewInfoMap[mode] const previewInfo = modeToPreviewInfoMap[mode]

+ 3
- 8
web/app/components/app/overview/customize/index.tsx Datei anzeigen

import React from 'react' import React from 'react'
import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline' import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { useDocLink } from '@/context/i18n'
import type { AppMode } from '@/types/app' import type { AppMode } from '@/types/app'
import I18n from '@/context/i18n'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import Modal from '@/app/components/base/modal' import Modal from '@/app/components/base/modal'
import Tag from '@/app/components/base/tag' import Tag from '@/app/components/base/tag'
import { LanguagesSupported } from '@/i18n/language'


type IShareLinkProps = { type IShareLinkProps = {
isShow: boolean isShow: boolean
mode, mode,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()
const isChatApp = mode === 'chat' || mode === 'advanced-chat' const isChatApp = mode === 'chat' || mode === 'advanced-chat'


return <Modal return <Modal
className='mt-2' className='mt-2'
onClick={() => onClick={() =>
window.open( window.open(
`https://docs.dify.ai/${locale !== LanguagesSupported[1]
? 'user-guide/launching-dify-apps/developing-with-apis'
: `${locale.toLowerCase()}/guides/application-publishing/developing-with-apis`
}`,
docLink('/guides/application-publishing/developing-with-apis'),
'_blank', '_blank',
) )
} }

+ 5
- 5
web/app/components/app/overview/settings/index.tsx Datei anzeigen

import { RiArrowRightSLine, RiCloseLine } from '@remixicon/react' import { RiArrowRightSLine, RiCloseLine } from '@remixicon/react'
import Link from 'next/link' import Link from 'next/link'
import { Trans, useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { SparklesSoft } from '@/app/components/base/icons/src/public/common' import { SparklesSoft } from '@/app/components/base/icons/src/public/common'
import Modal from '@/app/components/base/modal' import Modal from '@/app/components/base/modal'
import ActionButton from '@/app/components/base/action-button' import ActionButton from '@/app/components/base/action-button'
import type { AppDetailResponse } from '@/models/app' import type { AppDetailResponse } from '@/models/app'
import type { AppIconType, AppSSO, Language } from '@/types/app' import type { AppIconType, AppSSO, Language } from '@/types/app'
import { useToastContext } from '@/app/components/base/toast' import { useToastContext } from '@/app/components/base/toast'
import { LanguagesSupported, languages } from '@/i18n/language'
import { languages } from '@/i18n/language'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import { useModalContext } from '@/context/modal-context' import { useModalContext } from '@/context/modal-context'
import type { AppIconSelection } from '@/app/components/base/app-icon-picker' import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import AppIconPicker from '@/app/components/base/app-icon-picker' import AppIconPicker from '@/app/components/base/app-icon-picker'
import I18n from '@/context/i18n'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useDocLink } from '@/context/i18n'


export type ISettingsModalProps = { export type ISettingsModalProps = {
isChat: boolean isChat: boolean
const [language, setLanguage] = useState(default_language) const [language, setLanguage] = useState(default_language)
const [saveLoading, setSaveLoading] = useState(false) const [saveLoading, setSaveLoading] = useState(false)
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()


const [showAppIconPicker, setShowAppIconPicker] = useState(false) const [showAppIconPicker, setShowAppIconPicker] = useState(false)
const [appIcon, setAppIcon] = useState<AppIconSelection>( const [appIcon, setAppIcon] = useState<AppIconSelection>(
</div> </div>
<div className='system-xs-regular mt-0.5 text-text-tertiary'> <div className='system-xs-regular mt-0.5 text-text-tertiary'>
<span>{t(`${prefixSettings}.modalTip`)}</span> <span>{t(`${prefixSettings}.modalTip`)}</span>
<Link href={`${locale === LanguagesSupported[1] ? 'https://docs.dify.ai/zh-hans/guides/application-publishing/launch-your-webapp-quickly#she-zhi-ni-de-ai-zhan-dian' : 'https://docs.dify.ai/en/guides/application-publishing/launch-your-webapp-quickly/README'}`} target='_blank' rel='noopener noreferrer' className='text-text-accent'>{t('common.operation.learnMore')}</Link>
<Link href={docLink('/guides/application-publishing/launch-your-webapp-quickly/README')}
target='_blank' rel='noopener noreferrer' className='text-text-accent'>{t('common.operation.learnMore')}</Link>
</div> </div>
</div> </div>
{/* form body */} {/* form body */}

+ 3
- 5
web/app/components/base/features/new-feature-panel/index.tsx Datei anzeigen

import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { RiCloseLine, RiInformation2Fill } from '@remixicon/react' import { RiCloseLine, RiInformation2Fill } from '@remixicon/react'
import DialogWrapper from '@/app/components/base/features/new-feature-panel/dialog-wrapper' import DialogWrapper from '@/app/components/base/features/new-feature-panel/dialog-wrapper'
import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks' import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import AnnotationReply from '@/app/components/base/features/new-feature-panel/annotation-reply' import AnnotationReply from '@/app/components/base/features/new-feature-panel/annotation-reply'
import type { PromptVariable } from '@/models/debug' import type { PromptVariable } from '@/models/debug'
import type { InputVar } from '@/app/components/workflow/types' import type { InputVar } from '@/app/components/workflow/types'
import I18n from '@/context/i18n'
import { LanguagesSupported } from '@/i18n/language'
import { useDocLink } from '@/context/i18n'


type Props = { type Props = {
show: boolean show: boolean
onAutoAddPromptVariable, onAutoAddPromptVariable,
}: Props) => { }: Props) => {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()
const { data: speech2textDefaultModel } = useDefaultModel(ModelTypeEnum.speech2text) const { data: speech2textDefaultModel } = useDefaultModel(ModelTypeEnum.speech2text)
const { data: text2speechDefaultModel } = useDefaultModel(ModelTypeEnum.tts) const { data: text2speechDefaultModel } = useDefaultModel(ModelTypeEnum.tts)


<span>{isChatMode ? t('workflow.common.fileUploadTip') : t('workflow.common.ImageUploadLegacyTip')}</span> <span>{isChatMode ? t('workflow.common.fileUploadTip') : t('workflow.common.ImageUploadLegacyTip')}</span>
<a <a
className='text-text-accent' className='text-text-accent'
href={`https://docs.dify.ai/${locale === LanguagesSupported[1] ? 'v/zh-hans/' : ''}guides/workflow/bulletin`}
href={docLink('/guides/workflow/bulletin')}
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
>{t('workflow.common.featuresDocLink')}</a> >{t('workflow.common.featuresDocLink')}</a>
</div> </div>

+ 5
- 1
web/app/components/datasets/create/step-two/index.tsx Datei anzeigen

import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
import { noop } from 'lodash-es' import { noop } from 'lodash-es'
import { useDocLink } from '@/context/i18n'


const TextLabel: FC<PropsWithChildren> = (props) => { const TextLabel: FC<PropsWithChildren> = (props) => {
return <label className='system-sm-semibold text-text-secondary'>{props.children}</label> return <label className='system-sm-semibold text-text-secondary'>{props.children}</label>
updateRetrievalMethodCache, updateRetrievalMethodCache,
}: StepTwoProps) => { }: StepTwoProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const { locale } = useContext(I18n) const { locale } = useContext(I18n)
const media = useBreakpoints() const media = useBreakpoints()
const isMobile = media === MediaType.mobile const isMobile = media === MediaType.mobile
<div className={'mb-1'}> <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('datasetSettings.form.retrievalSetting.title')}</div>
<div className='body-xs-regular text-text-tertiary'> <div className='body-xs-regular text-text-tertiary'>
<a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
<a target='_blank' rel='noopener noreferrer'
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents')}
className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
{t('datasetSettings.form.retrievalSetting.longDescription')} {t('datasetSettings.form.retrievalSetting.longDescription')}
</div> </div>
</div> </div>

+ 3
- 1
web/app/components/datasets/create/website/base/url-input.tsx Datei anzeigen

import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Input from './input' import Input from './input'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { useDocLink } from '@/context/i18n'


const I18N_PREFIX = 'datasetCreation.stepOne.website' const I18N_PREFIX = 'datasetCreation.stepOne.website'


onRun, onRun,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const [url, setUrl] = useState('') const [url, setUrl] = useState('')
const handleUrlChange = useCallback((url: string | number) => { const handleUrlChange = useCallback((url: string | number) => {
setUrl(url as string) setUrl(url as string)
<Input <Input
value={url} value={url}
onChange={handleUrlChange} onChange={handleUrlChange}
placeholder='https://docs.dify.ai'
placeholder={docLink()}
/> />
<Button <Button
variant='primary' variant='primary'

+ 3
- 1
web/app/components/datasets/create/website/jina-reader/base/url-input.tsx Datei anzeigen

import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Input from './input' import Input from './input'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { useDocLink } from '@/context/i18n'


const I18N_PREFIX = 'datasetCreation.stepOne.website' const I18N_PREFIX = 'datasetCreation.stepOne.website'


onRun, onRun,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const [url, setUrl] = useState('') const [url, setUrl] = useState('')
const handleUrlChange = useCallback((url: string | number) => { const handleUrlChange = useCallback((url: string | number) => {
setUrl(url as string) setUrl(url as string)
<Input <Input
value={url} value={url}
onChange={handleUrlChange} onChange={handleUrlChange}
placeholder='https://docs.dify.ai'
placeholder={docLink()}
/> />
<Button <Button
variant='primary' variant='primary'

+ 3
- 8
web/app/components/datasets/documents/index.tsx Datei anzeigen

import useEditDocumentMetadata from '../metadata/hooks/use-edit-dataset-metadata' import useEditDocumentMetadata from '../metadata/hooks/use-edit-dataset-metadata'
import DatasetMetadataDrawer from '../metadata/metadata-dataset/dataset-metadata-drawer' import DatasetMetadataDrawer from '../metadata/metadata-dataset/dataset-metadata-drawer'
import StatusWithAction from '../common/document-status-with-action/status-with-action' import StatusWithAction from '../common/document-status-with-action/status-with-action'
import { LanguagesSupported } from '@/i18n/language'
import { getLocaleOnClient } from '@/i18n'
import { useDocLink } from '@/context/i18n'


const FolderPlusIcon = ({ className }: React.SVGProps<SVGElement>) => { const FolderPlusIcon = ({ className }: React.SVGProps<SVGElement>) => {
return <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}> return <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>


const Documents: FC<IDocumentsProps> = ({ datasetId }) => { const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const { plan } = useProviderContext() const { plan } = useProviderContext()
const isFreePlan = plan.type === 'sandbox' const isFreePlan = plan.type === 'sandbox'
const [inputValue, setInputValue] = useState<string>('') // the input value const [inputValue, setInputValue] = useState<string>('') // the input value
const isDataSourceWeb = dataset?.data_source_type === DataSourceType.WEB const isDataSourceWeb = dataset?.data_source_type === DataSourceType.WEB
const isDataSourceFile = dataset?.data_source_type === DataSourceType.FILE const isDataSourceFile = dataset?.data_source_type === DataSourceType.FILE
const embeddingAvailable = !!dataset?.embedding_available const embeddingAvailable = !!dataset?.embedding_available
const locale = getLocaleOnClient()
const debouncedSearchValue = useDebounce(searchValue, { wait: 500 }) const debouncedSearchValue = useDebounce(searchValue, { wait: 500 })


const { data: documentsRes, isFetching: isListLoading } = useDocumentList({ const { data: documentsRes, isFetching: isListLoading } = useDocumentList({
<a <a
className='flex items-center text-text-accent' className='flex items-center text-text-accent'
target='_blank' target='_blank'
href={
locale === LanguagesSupported[1]
? 'https://docs.dify.ai/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
: 'https://docs.dify.ai/en/guides/knowledge-base/integrate-knowledge-within-application'
}
href={docLink('/guides/knowledge-base/integrate-knowledge-within-application')}
> >
<span>{t('datasetDocuments.list.learnMore')}</span> <span>{t('datasetDocuments.list.learnMore')}</span>
<RiExternalLinkLine className='h-3 w-3' /> <RiExternalLinkLine className='h-3 w-3' />

+ 3
- 1
web/app/components/datasets/external-api/external-api-modal/Form.tsx Datei anzeigen

import type { CreateExternalAPIReq, FormSchema } from '../declarations' import type { CreateExternalAPIReq, FormSchema } from '../declarations'
import Input from '@/app/components/base/input' import Input from '@/app/components/base/input'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useDocLink } from '@/context/i18n'


type FormProps = { type FormProps = {
className?: string className?: string
inputClassName, inputClassName,
}) => { }) => {
const { t, i18n } = useTranslation() const { t, i18n } = useTranslation()
const docLink = useDocLink()
const [changeKey, setChangeKey] = useState('') const [changeKey, setChangeKey] = useState('')


const handleFormChange = (key: string, val: string) => { const handleFormChange = (key: string, val: string) => {
</label> </label>
{variable === 'endpoint' && ( {variable === 'endpoint' && (
<a <a
href={'https://docs.dify.ai/guides/knowledge-base/external-knowledge-api-documentation' || '/'}
href={docLink('/guides/knowledge-base/external-knowledge-api-documentation') || '/'}
target='_blank' target='_blank'
rel='noopener noreferrer' rel='noopener noreferrer'
className='body-xs-regular flex items-center text-text-accent' className='body-xs-regular flex items-center text-text-accent'

+ 4
- 1
web/app/components/datasets/external-api/external-api-panel/index.tsx Datei anzeigen

import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
import { useModalContext } from '@/context/modal-context' import { useModalContext } from '@/context/modal-context'
import { useDocLink } from '@/context/i18n'


type ExternalAPIPanelProps = { type ExternalAPIPanelProps = {
onClose: () => void onClose: () => void


const ExternalAPIPanel: React.FC<ExternalAPIPanelProps> = ({ onClose }) => { const ExternalAPIPanel: React.FC<ExternalAPIPanelProps> = ({ onClose }) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const { setShowExternalKnowledgeAPIModal } = useModalContext() const { setShowExternalKnowledgeAPIModal } = useModalContext()
const { externalKnowledgeApiList, mutateExternalKnowledgeApis, isLoading } = useExternalKnowledgeApi() const { externalKnowledgeApiList, mutateExternalKnowledgeApis, isLoading } = useExternalKnowledgeApi()


<div className='flex grow flex-col items-start gap-1'> <div className='flex grow flex-col items-start gap-1'>
<div className='system-xl-semibold self-stretch text-text-primary'>{t('dataset.externalAPIPanelTitle')}</div> <div className='system-xl-semibold self-stretch text-text-primary'>{t('dataset.externalAPIPanelTitle')}</div>
<div className='body-xs-regular self-stretch text-text-tertiary'>{t('dataset.externalAPIPanelDescription')}</div> <div className='body-xs-regular self-stretch text-text-tertiary'>{t('dataset.externalAPIPanelDescription')}</div>
<a className='flex cursor-pointer items-center justify-center gap-1 self-stretch' href='https://docs.dify.ai/guides/knowledge-base/external-knowledge-api-documentation' target='_blank'>
<a className='flex cursor-pointer items-center justify-center gap-1 self-stretch'
href={docLink('/guides/knowledge-base/external-knowledge-api-documentation')} target='_blank'>
<RiBookOpenLine className='h-3 w-3 text-text-accent' /> <RiBookOpenLine className='h-3 w-3 text-text-accent' />
<div className='body-xs-regular grow text-text-accent'>{t('dataset.externalAPIPanelDocumentation')}</div> <div className='body-xs-regular grow text-text-accent'>{t('dataset.externalAPIPanelDocumentation')}</div>
</a> </a>

+ 7
- 2
web/app/components/datasets/external-knowledge-base/create/InfoPanel.tsx Datei anzeigen

import { RiBookOpenLine } from '@remixicon/react' import { RiBookOpenLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useDocLink } from '@/context/i18n'


const InfoPanel = () => { const InfoPanel = () => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()


return ( return (
<div className='flex w-[360px] flex-col items-start pb-2 pr-8 pt-[108px]'> <div className='flex w-[360px] flex-col items-start pb-2 pr-8 pt-[108px]'>
</span> </span>
<span className='system-sm-regular text-text-tertiary'> <span className='system-sm-regular text-text-tertiary'>
{t('dataset.connectDatasetIntro.content.front')} {t('dataset.connectDatasetIntro.content.front')}
<a className='system-sm-regular ml-1 text-text-accent' href='https://docs.dify.ai/en/guides/knowledge-base/external-knowledge-api' target='_blank' rel="noopener noreferrer">
<a className='system-sm-regular ml-1 text-text-accent' href={docLink('/guides/knowledge-base/external-knowledge-api')} target='_blank' rel="noopener noreferrer">
{t('dataset.connectDatasetIntro.content.link')} {t('dataset.connectDatasetIntro.content.link')}
</a> </a>
{t('dataset.connectDatasetIntro.content.end')} {t('dataset.connectDatasetIntro.content.end')}
</span> </span>
<a className='system-sm-regular self-stretch text-text-accent' href='https://docs.dify.ai/en/guides/knowledge-base/connect-external-knowledge-base' target='_blank' rel="noopener noreferrer">
<a className='system-sm-regular self-stretch text-text-accent'
href={docLink('/guides/knowledge-base/connect-external-knowledge-base')}
target='_blank'
rel="noopener noreferrer">
{t('dataset.connectDatasetIntro.learnMore')} {t('dataset.connectDatasetIntro.learnMore')}
</a> </a>
</p> </p>

+ 3
- 1
web/app/components/datasets/external-knowledge-base/create/index.tsx Datei anzeigen

import type { CreateKnowledgeBaseReq } from './declarations' import type { CreateKnowledgeBaseReq } from './declarations'
import Divider from '@/app/components/base/divider' import Divider from '@/app/components/base/divider'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { useDocLink } from '@/context/i18n'


type ExternalKnowledgeBaseCreateProps = { type ExternalKnowledgeBaseCreateProps = {
onConnect: (formValue: CreateKnowledgeBaseReq) => void onConnect: (formValue: CreateKnowledgeBaseReq) => void


const ExternalKnowledgeBaseCreate: React.FC<ExternalKnowledgeBaseCreateProps> = ({ onConnect, loading }) => { const ExternalKnowledgeBaseCreate: React.FC<ExternalKnowledgeBaseCreateProps> = ({ onConnect, loading }) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const router = useRouter() const router = useRouter()
const [formData, setFormData] = useState<CreateKnowledgeBaseReq>({ const [formData, setFormData] = useState<CreateKnowledgeBaseReq>({
name: '', name: '',
<span>{t('dataset.connectHelper.helper1')}</span> <span>{t('dataset.connectHelper.helper1')}</span>
<span className='system-sm-medium text-text-secondary'>{t('dataset.connectHelper.helper2')}</span> <span className='system-sm-medium text-text-secondary'>{t('dataset.connectHelper.helper2')}</span>
<span>{t('dataset.connectHelper.helper3')}</span> <span>{t('dataset.connectHelper.helper3')}</span>
<a className='system-sm-regular self-stretch text-text-accent' href='https://docs.dify.ai/en/guides/knowledge-base/connect-external-knowledge-base' target='_blank' rel="noopener noreferrer">
<a className='system-sm-regular self-stretch text-text-accent' href={docLink('/guides/knowledge-base/connect-external-knowledge-base')} target='_blank' rel="noopener noreferrer">
{t('dataset.connectHelper.helper4')} {t('dataset.connectHelper.helper4')}
</a> </a>
<span>{t('dataset.connectHelper.helper5')} </span> <span>{t('dataset.connectHelper.helper5')} </span>

+ 3
- 1
web/app/components/datasets/hit-testing/modify-retrieval-modal.tsx Datei anzeigen

import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model' import { isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model'
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { useDocLink } from '@/context/i18n'


type Props = { type Props = {
indexMethod: string indexMethod: string
}) => { }) => {
const ref = useRef(null) const ref = useRef(null)
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const [retrievalConfig, setRetrievalConfig] = useState(value) const [retrievalConfig, setRetrievalConfig] = useState(value)


// useClickAway(() => { // useClickAway(() => {
<a <a
target='_blank' target='_blank'
rel='noopener noreferrer' rel='noopener noreferrer'
href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings'
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings')}
className='text-text-accent' className='text-text-accent'
> >
{t('datasetSettings.form.retrievalSetting.learnMore')} {t('datasetSettings.form.retrievalSetting.learnMore')}

+ 3
- 1
web/app/components/datasets/settings/form/index.tsx Datei anzeigen

import { fetchMembers } from '@/service/common' import { fetchMembers } from '@/service/common'
import type { Member } from '@/models/common' import type { Member } from '@/models/common'
import AlertTriangle from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback/AlertTriangle' import AlertTriangle from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback/AlertTriangle'
import { useDocLink } from '@/context/i18n'


const rowClass = 'flex' const rowClass = 'flex'
const labelClass = ` const labelClass = `


const Form = () => { const Form = () => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const { notify } = useContext(ToastContext) const { notify } = useContext(ToastContext)
const { mutate } = useSWRConfig() const { mutate } = useSWRConfig()
const { isCurrentWorkspaceDatasetOperator } = useAppContext() const { isCurrentWorkspaceDatasetOperator } = useAppContext()
<div> <div>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.retrievalSetting.title')}</div> <div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.retrievalSetting.title')}</div>
<div className='body-xs-regular text-text-tertiary'> <div className='body-xs-regular text-text-tertiary'>
<a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
<a target='_blank' rel='noopener noreferrer' href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings')} className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
{t('datasetSettings.form.retrievalSetting.description')} {t('datasetSettings.form.retrievalSetting.description')}
</div> </div>
</div> </div>

+ 3
- 3
web/app/components/header/account-dropdown/index.tsx Datei anzeigen

import Support from './support' import Support from './support'
import Compliance from './compliance' import Compliance from './compliance'
import PremiumBadge from '@/app/components/base/premium-badge' import PremiumBadge from '@/app/components/base/premium-badge'
import { useGetDocLanguage } from '@/context/i18n'
import Avatar from '@/app/components/base/avatar' import Avatar from '@/app/components/base/avatar'
import ThemeSwitcher from '@/app/components/base/theme-switcher' import ThemeSwitcher from '@/app/components/base/theme-switcher'
import { logout } from '@/service/common' import { logout } from '@/service/common'
import { IS_CLOUD_EDITION } from '@/config' import { IS_CLOUD_EDITION } from '@/config'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
import { useDocLink } from '@/context/i18n'


export default function AppSelector() { export default function AppSelector() {
const itemClassName = ` const itemClassName = `
const { systemFeatures } = useGlobalPublicStore() const { systemFeatures } = useGlobalPublicStore()


const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const { userProfile, langeniusVersionInfo, isCurrentWorkspaceOwner } = useAppContext() const { userProfile, langeniusVersionInfo, isCurrentWorkspaceOwner } = useAppContext()
const { isEducationAccount } = useProviderContext() const { isEducationAccount } = useProviderContext()
const { setShowAccountSettingModal } = useModalContext() const { setShowAccountSettingModal } = useModalContext()
const docLanguage = useGetDocLanguage()


const handleLogout = async () => { const handleLogout = async () => {
await logout({ await logout({
className={cn(itemClassName, 'group justify-between', className={cn(itemClassName, 'group justify-between',
'data-[active]:bg-state-base-hover', 'data-[active]:bg-state-base-hover',
)} )}
href={`https://docs.dify.ai/${docLanguage}/introduction`}
href={docLink('/introduction')}
target='_blank' rel='noopener noreferrer'> target='_blank' rel='noopener noreferrer'>
<RiBookOpenLine className='size-4 shrink-0 text-text-tertiary' /> <RiBookOpenLine className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.helpCenter')}</div> <div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.helpCenter')}</div>

+ 3
- 5
web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx Datei anzeigen

import React, { useMemo } from 'react' import React, { useMemo } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { useDocLink } from '@/context/i18n'
import { useBoolean } from 'ahooks' import { useBoolean } from 'ahooks'
import { import {
RiAddLine, RiAddLine,
useInvalidateEndpointList, useInvalidateEndpointList,
} from '@/service/use-endpoints' } from '@/service/use-endpoints'
import type { PluginDetail } from '@/app/components/plugins/types' import type { PluginDetail } from '@/app/components/plugins/types'
import { LanguagesSupported } from '@/i18n/language'
import I18n from '@/context/i18n'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'


type Props = { type Props = {
} }
const EndpointList = ({ detail }: Props) => { const EndpointList = ({ detail }: Props) => {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()
const pluginUniqueID = detail.plugin_unique_identifier const pluginUniqueID = detail.plugin_unique_identifier
const declaration = detail.declaration.endpoint const declaration = detail.declaration.endpoint
const showTopBorder = detail.declaration.tool const showTopBorder = detail.declaration.tool
</div> </div>
<div className='system-xs-regular text-text-tertiary'>{t('plugin.detailPanel.endpointsTip')}</div> <div className='system-xs-regular text-text-tertiary'>{t('plugin.detailPanel.endpointsTip')}</div>
<a <a
href={`https://docs.dify.ai/${locale === LanguagesSupported[1] ? 'v/zh-hans/' : ''}plugins/schema-definition/endpoint`}
href={docLink('/plugins/schema-definition/endpoint')}
target='_blank' target='_blank'
rel='noopener noreferrer' rel='noopener noreferrer'
> >

+ 5
- 3
web/app/components/tools/provider/custom-create-card.tsx Datei anzeigen

import { createCustomCollection } from '@/service/tools' import { createCustomCollection } from '@/service/tools'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import { useDocLink } from '@/context/i18n'


type Props = { type Props = {
onRefreshData: () => void onRefreshData: () => void
const language = getLanguage(locale) const language = getLanguage(locale)
const { isCurrentWorkspaceManager } = useAppContext() const { isCurrentWorkspaceManager } = useAppContext()


const docLink = useDocLink()
const linkUrl = useMemo(() => { const linkUrl = useMemo(() => {
if (language.startsWith('zh_'))
return 'https://docs.dify.ai/zh-hans/guides/tools#ru-he-chuang-jian-zi-ding-yi-gong-ju'
return 'https://docs.dify.ai/en/guides/tools#how-to-create-custom-tools'
return docLink('/guides/tools#how-to-create-custom-tools', {
'zh-Hans': '/guides/tools#ru-he-chuang-jian-zi-ding-yi-gong-ju',
})
}, [language]) }, [language])


const [isShowEditCollectionToolModal, setIsShowEditCustomCollectionModal] = useState(false) const [isShowEditCollectionToolModal, setIsShowEditCustomCollectionModal] = useState(false)

+ 6
- 9
web/app/components/workflow/nodes/_base/components/agent-strategy.tsx Datei anzeigen

import { useRenderI18nObject } from '@/hooks/use-i18n' import { useRenderI18nObject } from '@/hooks/use-i18n'
import type { NodeOutPutVar } from '../../../types' import type { NodeOutPutVar } from '../../../types'
import type { Node } from 'reactflow' import type { Node } from 'reactflow'
import { useContext } from 'use-context-selector'
import I18n from '@/context/i18n'
import { LanguagesSupported } from '@/i18n/language'
import { useDocLink } from '@/context/i18n'


export type Strategy = { export type Strategy = {
agent_strategy_provider_name: string agent_strategy_provider_name: string
export const AgentStrategy = memo((props: AgentStrategyProps) => { export const AgentStrategy = memo((props: AgentStrategyProps) => {
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange, nodeOutputVars, availableNodes, nodeId } = props const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange, nodeOutputVars, availableNodes, nodeId } = props
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()
const defaultModel = useDefaultModel(ModelTypeEnum.textGeneration) const defaultModel = useDefaultModel(ModelTypeEnum.textGeneration)
const renderI18nObject = useRenderI18nObject() const renderI18nObject = useRenderI18nObject()
const workflowStore = useWorkflowStore() const workflowStore = useWorkflowStore()
title={t('workflow.nodes.agent.strategy.configureTip')} title={t('workflow.nodes.agent.strategy.configureTip')}
description={<div className='text-xs text-text-tertiary'> description={<div className='text-xs text-text-tertiary'>
{t('workflow.nodes.agent.strategy.configureTipDesc')} <br /> {t('workflow.nodes.agent.strategy.configureTipDesc')} <br />
<Link href={
locale === LanguagesSupported[1]
? 'https://docs.dify.ai/zh-hans/guides/workflow/node/agent#xuan-ze-agent-ce-le'
: 'https://docs.dify.ai/en/guides/workflow/node/agent#select-an-agent-strategy'
} className='text-text-accent-secondary' target='_blank'>
<Link href={docLink('/guides/workflow/node/agent#select-an-agent-strategy', {
'zh-Hans': '/guides/workflow/node/agent#xuan-ze-agent-ce-le',
})}
className='text-text-accent-secondary' target='_blank'>
{t('workflow.nodes.agent.learnMore')} {t('workflow.nodes.agent.learnMore')}
</Link> </Link>
</div>} </div>}

+ 3
- 1
web/app/components/workflow/nodes/_base/components/error-handle/default-value.tsx Datei anzeigen

import { VarType } from '@/app/components/workflow/types' import { VarType } from '@/app/components/workflow/types'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { useDocLink } from '@/context/i18n'


type DefaultValueProps = { type DefaultValueProps = {
forms: DefaultValueForm[] forms: DefaultValueForm[]
onFormChange, onFormChange,
}: DefaultValueProps) => { }: DefaultValueProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const getFormChangeHandler = useCallback(({ key, type }: DefaultValueForm) => { const getFormChangeHandler = useCallback(({ key, type }: DefaultValueForm) => {
return (payload: any) => { return (payload: any) => {
let value let value
{t('workflow.nodes.common.errorHandle.defaultValue.desc')} {t('workflow.nodes.common.errorHandle.defaultValue.desc')}
&nbsp; &nbsp;
<a <a
href='https://docs.dify.ai/en/guides/workflow/error-handling/README'
href={docLink('/guides/workflow/error-handling/README')}
target='_blank' target='_blank'
className='text-text-accent' className='text-text-accent'
> >

+ 3
- 1
web/app/components/workflow/nodes/_base/components/error-handle/fail-branch-card.tsx Datei anzeigen

import { RiMindMap } from '@remixicon/react' import { RiMindMap } from '@remixicon/react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useDocLink } from '@/context/i18n'


const FailBranchCard = () => { const FailBranchCard = () => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()


return ( return (
<div className='px-4 pt-2'> <div className='px-4 pt-2'>
{t('workflow.nodes.common.errorHandle.failBranch.customizeTip')} {t('workflow.nodes.common.errorHandle.failBranch.customizeTip')}
&nbsp; &nbsp;
<a <a
href='https://docs.dify.ai/guides/workflow/error-handling'
href={docLink('/guides/workflow/error-handling/error-type')}
target='_blank' target='_blank'
className='text-text-accent' className='text-text-accent'
> >

+ 6
- 6
web/app/components/workflow/nodes/_base/components/variable/var-reference-popup.tsx Datei anzeigen

import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import VarReferenceVars from './var-reference-vars' import VarReferenceVars from './var-reference-vars'
import type { NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types' import type { NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types'
import ListEmpty from '@/app/components/base/list-empty' import ListEmpty from '@/app/components/base/list-empty'
import { LanguagesSupported } from '@/i18n/language'
import I18n from '@/context/i18n'
import { useDocLink } from '@/context/i18n'


type Props = { type Props = {
vars: NodeOutPutVar[] vars: NodeOutPutVar[]
isSupportFileVar = true, isSupportFileVar = true,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()
// max-h-[300px] overflow-y-auto todo: use portal to handle long list // max-h-[300px] overflow-y-auto todo: use portal to handle long list
return ( return (
<div className='space-y-1 rounded-lg border border-components-panel-border bg-components-panel-bg p-1 shadow-lg' style={{ <div className='space-y-1 rounded-lg border border-components-panel-border bg-components-panel-bg p-1 shadow-lg' style={{
description={<div className='system-xs-regular text-text-tertiary'> description={<div className='system-xs-regular text-text-tertiary'>
{t('workflow.variableReference.assignedVarsDescription')} {t('workflow.variableReference.assignedVarsDescription')}
<a target='_blank' rel='noopener noreferrer' <a target='_blank' rel='noopener noreferrer'
className='text-text-accent-secondary'
href={locale !== LanguagesSupported[1] ? 'https://docs.dify.ai/guides/workflow/variables#conversation-variables' : `https://docs.dify.ai/${locale.toLowerCase()}/guides/workflow/variables#hui-hua-bian-liang`}>{t('workflow.variableReference.conversationVars')}</a>
className='text-text-accent-secondary'
href={docLink('/guides/workflow/variables#conversation-variables', { 'zh-Hans': '/guides/workflow/variables#hui-hua-bian-liang' })}>
{t('workflow.variableReference.conversationVars')}
</a>
</div>} </div>}
/> />
)) ))

+ 3
- 5
web/app/components/workflow/nodes/_base/hooks/use-node-help-link.ts Datei anzeigen

import { useMemo } from 'react' import { useMemo } from 'react'
import { useGetLanguage } from '@/context/i18n'
import { useDocLink, useGetLanguage } from '@/context/i18n'
import { BlockEnum } from '@/app/components/workflow/types' import { BlockEnum } from '@/app/components/workflow/types'


export const useNodeHelpLink = (nodeType: BlockEnum) => { export const useNodeHelpLink = (nodeType: BlockEnum) => {
const language = useGetLanguage() const language = useGetLanguage()
const docLink = useDocLink()
const prefixLink = useMemo(() => { const prefixLink = useMemo(() => {
if (language === 'zh_Hans')
return 'https://docs.dify.ai/zh-hans/guides/workflow/node/'

return 'https://docs.dify.ai/en/guides/workflow/node/'
return docLink('/guides/workflow/node/')
}, [language]) }, [language])
const linkMap = useMemo(() => { const linkMap = useMemo(() => {
if (language === 'zh_Hans') { if (language === 'zh_Hans') {

+ 3
- 3
web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx Datei anzeigen

import ErrorMessage from './error-message' import ErrorMessage from './error-message'
import { useVisualEditorStore } from './visual-editor/store' import { useVisualEditorStore } from './visual-editor/store'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
import { useGetDocLanguage } from '@/context/i18n'
import { JSON_SCHEMA_MAX_DEPTH } from '@/config' import { JSON_SCHEMA_MAX_DEPTH } from '@/config'
import { useDocLink } from '@/context/i18n'


type JsonSchemaConfigProps = { type JsonSchemaConfigProps = {
defaultSchema?: SchemaRoot defaultSchema?: SchemaRoot
onClose, onClose,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLanguage = useGetDocLanguage()
const docLink = useDocLink()
const [currentTab, setCurrentTab] = useState(SchemaView.VisualEditor) const [currentTab, setCurrentTab] = useState(SchemaView.VisualEditor)
const [jsonSchema, setJsonSchema] = useState(defaultSchema || DEFAULT_SCHEMA) const [jsonSchema, setJsonSchema] = useState(defaultSchema || DEFAULT_SCHEMA)
const [json, setJson] = useState(JSON.stringify(jsonSchema, null, 2)) const [json, setJson] = useState(JSON.stringify(jsonSchema, null, 2))
<div className='flex items-center gap-x-2 p-6 pt-5'> <div className='flex items-center gap-x-2 p-6 pt-5'>
<a <a
className='flex grow items-center gap-x-1 text-text-accent' className='flex grow items-center gap-x-1 text-text-accent'
href={`https://docs.dify.ai/${docLanguage}/guides/workflow/structured-outputs`}
href={docLink('/guides/workflow/structured-outputs')}
target='_blank' target='_blank'
rel='noopener noreferrer' rel='noopener noreferrer'
> >

+ 7
- 6
web/app/components/workflow/panel/chat-variable-panel/index.tsx Datei anzeigen

useCallback, useCallback,
useState, useState,
} from 'react' } from 'react'
import { useContext } from 'use-context-selector'
import { import {
useStoreApi, useStoreApi,
} from 'reactflow' } from 'reactflow'
import { findUsedVarNodes, updateNodeVars } from '@/app/components/workflow/nodes/_base/components/variable/utils' import { findUsedVarNodes, updateNodeVars } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { useNodesSyncDraft } from '@/app/components/workflow/hooks/use-nodes-sync-draft' import { useNodesSyncDraft } from '@/app/components/workflow/hooks/use-nodes-sync-draft'
import { BlockEnum } from '@/app/components/workflow/types' import { BlockEnum } from '@/app/components/workflow/types'
import I18n from '@/context/i18n'
import { LanguagesSupported } from '@/i18n/language'
import { useDocLink } from '@/context/i18n'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'


const ChatVariablePanel = () => { const ChatVariablePanel = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const docLink = useDocLink()
const store = useStoreApi() const store = useStoreApi()
const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel) const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel)
const varList = useStore(s => s.conversationVariables) as ConversationVariable[] const varList = useStore(s => s.conversationVariables) as ConversationVariable[]
<div className='system-2xs-medium-uppercase inline-block rounded-[5px] border border-divider-deep px-[5px] py-[3px] text-text-tertiary'>TIPS</div> <div className='system-2xs-medium-uppercase inline-block rounded-[5px] border border-divider-deep px-[5px] py-[3px] text-text-tertiary'>TIPS</div>
<div className='system-sm-regular mb-4 mt-1 text-text-secondary'> <div className='system-sm-regular mb-4 mt-1 text-text-secondary'>
{t('workflow.chatVariable.panelDescription')} {t('workflow.chatVariable.panelDescription')}
<a target='_blank' rel='noopener noreferrer' className='text-text-accent' href={locale !== LanguagesSupported[1] ? 'https://docs.dify.ai/guides/workflow/variables#conversation-variables' : `https://docs.dify.ai/${locale.toLowerCase()}/guides/workflow/variables#hui-hua-bian-liang`}>{t('workflow.chatVariable.docLink')}</a>
</div>
<a target='_blank' rel='noopener noreferrer' className='text-text-accent'
href={docLink('/guides/workflow/variables#conversation-variables', { 'zh-Hans': '/guides/workflow/variables#hui-hua-bian-liang' })}>
{t('workflow.chatVariable.docLink')}
</a>
</div>
<div className='flex items-center gap-2'> <div className='flex items-center gap-2'>
<div className='radius-lg flex flex-col border border-workflow-block-border bg-workflow-block-bg p-3 pb-4 shadow-md'> <div className='radius-lg flex flex-col border border-workflow-block-border bg-workflow-block-bg p-3 pb-4 shadow-md'>
<BubbleX className='mb-1 h-4 w-4 shrink-0 text-util-colors-teal-teal-700' /> <BubbleX className='mb-1 h-4 w-4 shrink-0 text-util-colors-teal-teal-700' />

+ 3
- 1
web/app/components/workflow/run/node.tsx Datei anzeigen

} from '@/types/workflow' } from '@/types/workflow'
import ErrorHandleTip from '@/app/components/workflow/nodes/_base/components/error-handle/error-handle-tip' import ErrorHandleTip from '@/app/components/workflow/nodes/_base/components/error-handle/error-handle-tip'
import { hasRetryNode } from '@/app/components/workflow/utils' import { hasRetryNode } from '@/app/components/workflow/utils'
import { useDocLink } from '@/context/i18n'


type Props = { type Props = {
className?: string className?: string
doSetCollapseState(state) doSetCollapseState(state)
}, [hideProcessDetail]) }, [hideProcessDetail])
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()


const getTime = (time: number) => { const getTime = (time: number) => {
if (time < 1) if (time < 1)
<StatusContainer status='stopped'> <StatusContainer status='stopped'>
{nodeInfo.error} {nodeInfo.error}
<a <a
href='https://docs.dify.ai/guides/workflow/error-handling/error-type'
href={docLink('/guides/workflow/error-handling/error-type')}
target='_blank' target='_blank'
className='text-text-accent' className='text-text-accent'
> >

+ 3
- 1
web/app/components/workflow/run/status.tsx Datei anzeigen

import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import Indicator from '@/app/components/header/indicator' import Indicator from '@/app/components/header/indicator'
import StatusContainer from '@/app/components/workflow/run/status-container' import StatusContainer from '@/app/components/workflow/run/status-container'
import { useDocLink } from '@/context/i18n'


type ResultProps = { type ResultProps = {
status: string status: string
exceptionCounts, exceptionCounts,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()


return ( return (
<StatusContainer status={status}> <StatusContainer status={status}>
<div className='system-xs-medium text-text-warning'> <div className='system-xs-medium text-text-warning'>
{error} {error}
<a <a
href='https://docs.dify.ai/guides/workflow/error-handling/error-type'
href={docLink('/guides/workflow/error-handling/error-type')}
target='_blank' target='_blank'
className='text-text-accent' className='text-text-accent'
> >

+ 3
- 13
web/app/education-apply/education-apply-page.tsx Datei anzeigen

'use client' 'use client'


import { import {
useMemo,
useState, useState,
} from 'react' } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import { useToastContext } from '@/app/components/base/toast' import { useToastContext } from '@/app/components/base/toast'
import { EDUCATION_VERIFYING_LOCALSTORAGE_ITEM } from '@/app/education-apply/constants' import { EDUCATION_VERIFYING_LOCALSTORAGE_ITEM } from '@/app/education-apply/constants'
import { getLocaleOnClient } from '@/i18n'
import { noop } from 'lodash-es' import { noop } from 'lodash-es'
import DifyLogo from '../components/base/logo/dify-logo' import DifyLogo from '../components/base/logo/dify-logo'
import { useDocLink } from '@/context/i18n'
const EducationApplyAge = () => { const EducationApplyAge = () => {
const { t } = useTranslation() const { t } = useTranslation()
const locale = getLocaleOnClient()
const [schoolName, setSchoolName] = useState('') const [schoolName, setSchoolName] = useState('')
const [role, setRole] = useState('Student') const [role, setRole] = useState('Student')
const [ageChecked, setAgeChecked] = useState(false) const [ageChecked, setAgeChecked] = useState(false)
const updateEducationStatus = useInvalidateEducationStatus() const updateEducationStatus = useInvalidateEducationStatus()
const { notify } = useToastContext() const { notify } = useToastContext()
const router = useRouter() const router = useRouter()

const docLink = useMemo(() => {
if (locale === 'zh-Hans')
return 'https://docs.dify.ai/zh-hans/getting-started/dify-for-education'
if (locale === 'ja-JP')
return 'https://docs.dify.ai/ja-jp/getting-started/dify-for-education'
return 'https://docs.dify.ai/getting-started/dify-for-education'
}, [locale])
const docLink = useDocLink()


const handleModalConfirm = () => { const handleModalConfirm = () => {
setShowModal(undefined) setShowModal(undefined)
<div className='mb-4 mt-5 h-[1px] bg-gradient-to-r from-[rgba(16,24,40,0.08)]'></div> <div className='mb-4 mt-5 h-[1px] bg-gradient-to-r from-[rgba(16,24,40,0.08)]'></div>
<a <a
className='system-xs-regular flex items-center text-text-accent' className='system-xs-regular flex items-center text-text-accent'
href={docLink}
href={docLink('/getting-started/dify-for-education')}
target='_blank' target='_blank'
> >
{t('education.learn')} {t('education.learn')}

+ 6
- 13
web/app/education-apply/verify-state-modal.tsx Datei anzeigen

import React, { useEffect, useMemo, useRef, useState } from 'react'
import React, { useEffect, useRef, useState } from 'react'
import { createPortal } from 'react-dom' import { createPortal } from 'react-dom'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { import {
RiExternalLinkLine, RiExternalLinkLine,
} from '@remixicon/react' } from '@remixicon/react'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { getLocaleOnClient } from '@/i18n'
import { useDocLink } from '@/context/i18n'


export type IConfirm = { export type IConfirm = {
className?: string className?: string
email, email,
}: IConfirm) { }: IConfirm) {
const { t } = useTranslation() const { t } = useTranslation()
const locale = getLocaleOnClient()
const docLink = useDocLink()
const dialogRef = useRef<HTMLDivElement>(null) const dialogRef = useRef<HTMLDivElement>(null)
const [isVisible, setIsVisible] = useState(isShow) const [isVisible, setIsVisible] = useState(isShow)

const docLink = useMemo(() => {
if (locale === 'zh-Hans')
return 'https://docs.dify.ai/zh-hans/getting-started/dify-for-education'
if (locale === 'ja-JP')
return 'https://docs.dify.ai/ja-jp/getting-started/dify-for-education'
return 'https://docs.dify.ai/getting-started/dify-for-education'
}, [locale])
const eduDocLink = docLink('/getting-started/dify-for-education')


const handleClick = () => { const handleClick = () => {
window.open(docLink, '_blank', 'noopener,noreferrer')
window.open(eduDocLink, '_blank', 'noopener,noreferrer')
} }


useEffect(() => { useEffect(() => {
<div className='flex items-center gap-1'> <div className='flex items-center gap-1'>
{showLink && ( {showLink && (
<> <>
<a onClick={handleClick} href={docLink} target='_blank' className='system-xs-regular cursor-pointer text-text-accent'>{t('education.learn')}</a>
<a onClick={handleClick} href={eduDocLink} target='_blank' className='system-xs-regular cursor-pointer text-text-accent'>{t('education.learn')}</a>
<RiExternalLinkLine className='h-3 w-3 text-text-accent' /> <RiExternalLinkLine className='h-3 w-3 text-text-accent' />
</> </>
)} )}

+ 3
- 1
web/app/install/installForm.tsx Datei anzeigen

import { fetchInitValidateStatus, fetchSetupStatus, setup } from '@/service/common' import { fetchInitValidateStatus, fetchSetupStatus, setup } from '@/service/common'
import type { InitValidateStatusResponse, SetupStatusResponse } from '@/models/common' import type { InitValidateStatusResponse, SetupStatusResponse } from '@/models/common'
import useDocumentTitle from '@/hooks/use-document-title' import useDocumentTitle from '@/hooks/use-document-title'
import { useDocLink } from '@/context/i18n'


const validPassword = /^(?=.*[a-zA-Z])(?=.*\d).{8,}$/ const validPassword = /^(?=.*[a-zA-Z])(?=.*\d).{8,}$/


const InstallForm = () => { const InstallForm = () => {
useDocumentTitle('') useDocumentTitle('')
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const router = useRouter() const router = useRouter()
const [showPassword, setShowPassword] = React.useState(false) const [showPassword, setShowPassword] = React.useState(false)
const [loading, setLoading] = React.useState(true) const [loading, setLoading] = React.useState(true)
<Link <Link
className='text-text-accent' className='text-text-accent'
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
href={'https://docs.dify.ai/user-agreement/open-source'}
href={docLink('/policies/open-source')}
>{t('login.license.link')}</Link> >{t('login.license.link')}</Link>
</div> </div>
</div> </div>

+ 4
- 2
web/app/signin/invite-settings/page.tsx Datei anzeigen

'use client' 'use client'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useDocLink } from '@/context/i18n'
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import Link from 'next/link' import Link from 'next/link'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'


export default function InviteSettingsPage() { export default function InviteSettingsPage() {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const router = useRouter() const router = useRouter()
const searchParams = useSearchParams() const searchParams = useSearchParams()
const token = decodeURIComponent(searchParams.get('invite_token') as string) const token = decodeURIComponent(searchParams.get('invite_token') as string)
const { locale, setLocaleOnClient } = useContext(I18n)
const { setLocaleOnClient } = useContext(I18n)
const [name, setName] = useState('') const [name, setName] = useState('')
const [language, setLanguage] = useState(LanguagesSupported[0]) const [language, setLanguage] = useState(LanguagesSupported[0])
const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone || 'America/Los_Angeles') const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone || 'America/Los_Angeles')
<Link <Link
className='system-xs-medium text-text-accent-secondary' className='system-xs-medium text-text-accent-secondary'
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
href={`https://docs.dify.ai/${language !== LanguagesSupported[1] ? 'user-agreement' : `v/${locale.toLowerCase()}/policies`}/open-source`}
href={docLink('/policies/open-source')}
>{t('login.license.link')}</Link> >{t('login.license.link')}</Link>
</div> </div>
</div> </div>

+ 3
- 1
web/app/signin/oneMoreStep.tsx Datei anzeigen

import { LanguagesSupported, languages } from '@/i18n/language' import { LanguagesSupported, languages } from '@/i18n/language'
import { oneMoreStep } from '@/service/common' import { oneMoreStep } from '@/service/common'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
import { useDocLink } from '@/context/i18n'


type IState = { type IState = {
formState: 'processing' | 'error' | 'success' | 'initial' formState: 'processing' | 'error' | 'success' | 'initial'


const OneMoreStep = () => { const OneMoreStep = () => {
const { t } = useTranslation() const { t } = useTranslation()
const docLink = useDocLink()
const router = useRouter() const router = useRouter()
const searchParams = useSearchParams() const searchParams = useSearchParams()


<Link <Link
className='system-xs-medium text-text-accent-secondary' className='system-xs-medium text-text-accent-secondary'
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
href={'https://docs.dify.ai/en/policies/agreement/README'}
href={docLink('/policies/agreement/README')}
>{t('login.license.link')}</Link> >{t('login.license.link')}</Link>
</div> </div>
</div> </div>

+ 13
- 0
web/context/i18n.ts Datei anzeigen

return getPricingPageLanguage(locale) return getPricingPageLanguage(locale)
} }


const defaultDocBaseUrl = 'https://docs.dify.ai'
export const useDocLink = (baseUrl?: string): ((path?: string, pathMap?: { [index: string]: string }) => string) => {
let baseDocUrl = baseUrl || defaultDocBaseUrl
baseDocUrl = (baseDocUrl.endsWith('/')) ? baseDocUrl.slice(0, -1) : baseDocUrl
const { locale } = useI18N()
const docLanguage = getDocLanguage(locale)
return (path?: string, pathMap?: { [index: string]: string }): string => {
const pathUrl = path || ''
let targetPath = (pathMap) ? pathMap[locale] || pathUrl : pathUrl
targetPath = (targetPath.startsWith('/')) ? targetPath.slice(0, -1) : targetPath
return `${baseDocUrl}/${docLanguage}/${targetPath}`
}
}
export default I18NContext export default I18NContext

Laden…
Abbrechen
Speichern