Compare commits

...

10 Commits

Author SHA1 Message Date
Stephen Zhou
65e04f7342 readme 2026-01-14 13:08:38 +08:00
Stephen Zhou
ee2f5d3ad9 Merge branch 'main' into 1-12-doc-redirect 2026-01-14 13:07:23 +08:00
Stephen Zhou
58d9d2f38c migrate 2026-01-12 18:03:50 +08:00
Stephen Zhou
d540b14959 migrate 2026-01-12 18:00:04 +08:00
Stephen Zhou
31d27639ef prefix 2026-01-12 17:12:46 +08:00
Stephen Zhou
2d1de24baf no eslint 2026-01-12 16:47:53 +08:00
Stephen Zhou
d9a2ba2617 api-reference link 2026-01-12 16:39:39 +08:00
Stephen Zhou
10f10f4785 # support 2026-01-12 16:00:19 +08:00
Stephen Zhou
6890f7d09c calls 2026-01-12 15:51:44 +08:00
Stephen Zhou
46f0e3c07e lint and typecheck for doc link 2026-01-12 15:04:40 +08:00
65 changed files with 909 additions and 158 deletions

View File

@@ -138,7 +138,7 @@ This will help you determine the testing strategy. See [web/testing/testing.md](
## Documentation
Visit <https://docs.dify.ai/getting-started/readme> to view the full documentation.
Visit <https://docs.dify.ai> to view the full documentation.
## Community

View File

@@ -59,7 +59,7 @@ const CardView: FC<ICardViewProps> = ({ appId, isInPanel, className }) => {
const shouldRenderAppCards = !isWorkflowApp || hasTriggerNode === false
const disableAppCards = !shouldRenderAppCards
const triggerDocUrl = docLink('/guides/workflow/node/start')
const triggerDocUrl = docLink('/use-dify/getting-started/key-concepts#workflow')
const buildTriggerModeMessage = useCallback((featureName: string) => (
<div className="flex flex-col gap-1">
<div className="text-xs text-text-secondary">

View File

@@ -46,7 +46,7 @@ const HistoryPanel: FC<Props> = ({
<div>
{t('feature.conversationHistory.tip', { ns: 'appDebug' })}
<a
href={docLink('/learn-more/extended-reading/what-is-llmops', { 'zh-Hans': '/learn-more/extended-reading/prompt-engineering/README' })}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
className="text-[#155EEF]"

View File

@@ -237,7 +237,7 @@ describe('RetrievalSection', () => {
retrievalConfig={retrievalConfig}
showMultiModalTip
onRetrievalConfigChange={vi.fn()}
docLink={docLink}
docLink={docLink as any}
/>,
)
@@ -263,7 +263,7 @@ describe('RetrievalSection', () => {
retrievalConfig={createRetrievalConfig()}
showMultiModalTip={false}
onRetrievalConfigChange={handleRetrievalChange}
docLink={path => path}
docLink={path => path || ''}
/>,
)
const [topKIncrement] = screen.getAllByLabelText('increment')

View File

@@ -1,6 +1,7 @@
import type { FC } from 'react'
import type { DataSet } from '@/models/datasets'
import type { RetrievalConfig } from '@/types/app'
import type { DocPathWithoutLang } from '@/types/doc-paths'
import { RiCloseLine } from '@remixicon/react'
import Divider from '@/app/components/base/divider'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
@@ -84,7 +85,7 @@ type InternalRetrievalSectionProps = CommonSectionProps & {
retrievalConfig: RetrievalConfig
showMultiModalTip: boolean
onRetrievalConfigChange: (value: RetrievalConfig) => void
docLink: (path: string) => string
docLink: (path?: DocPathWithoutLang) => string
}
const InternalRetrievalSection: FC<InternalRetrievalSectionProps> = ({
@@ -102,7 +103,7 @@ const InternalRetrievalSection: FC<InternalRetrievalSectionProps> = ({
<div>
<div className="system-sm-semibold text-text-secondary">{t('form.retrievalSetting.title', { ns: 'datasetSettings' })}</div>
<div className="text-xs font-normal leading-[18px] text-text-tertiary">
<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('form.retrievalSetting.learnMore', { ns: 'datasetSettings' })}</a>
<a target="_blank" rel="noopener noreferrer" href={docLink('/use-dify/knowledge/create-knowledge/setting-indexing-methods#setting-the-retrieval-setting')} className="text-text-accent">{t('form.retrievalSetting.learnMore', { ns: 'datasetSettings' })}</a>
{t('form.retrievalSetting.description', { ns: 'datasetSettings' })}
</div>
</div>

View File

@@ -240,7 +240,7 @@ const ExternalDataToolModal: FC<ExternalDataToolModalProps> = ({
<div className="flex h-9 items-center justify-between text-sm font-medium text-text-primary">
{t('apiBasedExtension.selector.title', { ns: 'common' })}
<a
href={docLink('/guides/extension/api-based-extension/README')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
className="group flex items-center text-xs font-normal text-text-tertiary hover:text-text-accent"

View File

@@ -351,36 +351,27 @@ function AppPreview({ mode }: { mode: AppModeEnum }) {
[AppModeEnum.CHAT]: {
title: t('types.chatbot', { ns: 'app' }),
description: t('newApp.chatbotUserDescription', { ns: 'app' }),
link: docLink('/guides/application-orchestrate/chatbot-application'),
link: docLink('/use-dify/getting-started/introduction'),
},
[AppModeEnum.ADVANCED_CHAT]: {
title: t('types.advanced', { ns: 'app' }),
description: t('newApp.advancedUserDescription', { ns: 'app' }),
link: docLink('/guides/workflow/README', {
'zh-Hans': '/guides/workflow/readme',
'ja-JP': '/guides/workflow/concepts',
}),
link: docLink('/use-dify/getting-started/introduction'),
},
[AppModeEnum.AGENT_CHAT]: {
title: t('types.agent', { ns: 'app' }),
description: t('newApp.agentUserDescription', { ns: 'app' }),
link: docLink('/guides/application-orchestrate/agent'),
link: docLink('/use-dify/getting-started/introduction'),
},
[AppModeEnum.COMPLETION]: {
title: t('newApp.completeApp', { ns: 'app' }),
description: t('newApp.completionUserDescription', { ns: 'app' }),
link: docLink('/guides/application-orchestrate/text-generator', {
'zh-Hans': '/guides/application-orchestrate/readme',
'ja-JP': '/guides/application-orchestrate/README',
}),
link: docLink('/use-dify/getting-started/introduction'),
},
[AppModeEnum.WORKFLOW]: {
title: t('types.workflow', { ns: 'app' }),
description: t('newApp.workflowUserDescription', { ns: 'app' }),
link: docLink('/guides/workflow/README', {
'zh-Hans': '/guides/workflow/readme',
'ja-JP': '/guides/workflow/concepts',
}),
link: docLink('/use-dify/getting-started/introduction'),
},
}
const previewInfo = modeToPreviewInfoMap[mode]

View File

@@ -245,7 +245,7 @@ function AppCard({
</div>
<div
className="cursor-pointer text-xs font-normal text-text-accent hover:underline"
onClick={() => window.open(docLink('/guides/workflow/node/user-input'), '_blank')}
onClick={() => window.open(docLink('/use-dify/nodes/user-input'), '_blank')}
>
{t('overview.appInfo.enableTooltip.learnMore', { ns: 'appOverview' })}
</div>

View File

@@ -118,7 +118,7 @@ const CustomizeModal: FC<IShareLinkProps> = ({
className="mt-2"
onClick={() =>
window.open(
docLink('/guides/application-publishing/developing-with-apis'),
docLink('/use-dify/publish/developing-with-apis'),
'_blank',
)}
>

View File

@@ -241,9 +241,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
<div className="system-xs-regular mt-0.5 text-text-tertiary">
<span>{t(`${prefixSettings}.modalTip`, { ns: 'appOverview' })}</span>
<Link
href={docLink('/guides/application-publishing/launch-your-webapp-quickly/README', {
'zh-Hans': '/guides/application-publishing/launch-your-webapp-quickly/readme',
})}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
className="text-text-accent"

View File

@@ -208,7 +208,7 @@ function TriggerCard({ appInfo, onToggleResult }: ITriggerCardProps) {
{t('overview.triggerInfo.triggerStatusDescription', { ns: 'appOverview' })}
{' '}
<Link
href={docLink('/guides/workflow/node/trigger')}
href={docLink('/use-dify/nodes/trigger/overview')}
target="_blank"
rel="noopener noreferrer"
className="text-text-accent hover:underline"

View File

@@ -78,7 +78,7 @@ const NewFeaturePanel = ({
<span>{isChatMode ? t('common.fileUploadTip', { ns: 'workflow' }) : t('common.ImageUploadLegacyTip', { ns: 'workflow' })}</span>
<a
className="text-text-accent"
href={docLink('/guides/workflow/bulletin')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -319,7 +319,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
<div className="flex h-9 items-center justify-between">
<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')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
className="group flex items-center text-xs text-text-tertiary hover:text-primary-600"

View File

@@ -87,7 +87,7 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
<div className="text-base font-semibold text-text-secondary">{t('stepThree.sideTipTitle', { ns: 'datasetCreation' })}</div>
<div className="text-text-tertiary">{t('stepThree.sideTipContent', { ns: 'datasetCreation' })}</div>
<a
href={docLink('/guides/knowledge-base/integrate-knowledge-within-application')}
href={docLink('/use-dify/knowledge/integrate-knowledge-within-application')}
target="_blank"
rel="noreferrer noopener"
className="system-sm-regular text-text-accent"

View File

@@ -214,7 +214,7 @@ export const IndexingModeSection: FC<IndexingModeSectionProps> = ({
<a
target="_blank"
rel="noopener noreferrer"
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents')}
href={docLink('/use-dify/knowledge/create-knowledge/introduction')}
className="text-text-accent"
>
{t('form.retrievalSetting.learnMore', { ns: 'datasetSettings' })}

View File

@@ -138,7 +138,7 @@ const OnlineDocuments = ({
<div className="flex flex-col gap-y-2">
<Header
docTitle="Docs"
docLink={docLink('/guides/knowledge-base/knowledge-pipeline/authorize-data-source')}
docLink={docLink('/use-dify/knowledge/knowledge-pipeline/authorize-data-source')}
onClickConfiguration={handleSetting}
pluginName={nodeData.datasource_label}
currentCredentialId={currentCredentialId}

View File

@@ -196,7 +196,7 @@ const OnlineDrive = ({
<div className="flex flex-col gap-y-2">
<Header
docTitle="Docs"
docLink={docLink('/guides/knowledge-base/knowledge-pipeline/authorize-data-source')}
docLink={docLink('/use-dify/knowledge/knowledge-pipeline/authorize-data-source')}
onClickConfiguration={handleSetting}
pluginName={nodeData.datasource_label}
currentCredentialId={currentCredentialId}

View File

@@ -158,7 +158,7 @@ const WebsiteCrawl = ({
<div className="flex flex-col">
<Header
docTitle="Docs"
docLink={docLink('/guides/knowledge-base/knowledge-pipeline/authorize-data-source')}
docLink={docLink('/use-dify/knowledge/knowledge-pipeline/authorize-data-source')}
onClickConfiguration={handleSetting}
pluginName={nodeData.datasource_label}
currentCredentialId={currentCredentialId}

View File

@@ -44,7 +44,7 @@ const Processing = ({
<div className="system-xl-semibold text-text-secondary">{t('stepThree.sideTipTitle', { ns: 'datasetCreation' })}</div>
<div className="system-sm-regular text-text-tertiary">{t('stepThree.sideTipContent', { ns: 'datasetCreation' })}</div>
<a
href={docLink('/guides/knowledge-base/integrate-knowledge-within-application')}
href={docLink('/use-dify/knowledge/knowledge-pipeline/authorize-data-source')}
target="_blank"
rel="noreferrer noopener"
className="system-sm-regular text-text-accent"

View File

@@ -306,7 +306,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
<a
className="flex items-center text-text-accent"
target="_blank"
href={docLink('/guides/knowledge-base/integrate-knowledge-within-application')}
href={docLink('/use-dify/knowledge/integrate-knowledge-within-application')}
>
<span>{t('list.learnMore', { ns: 'datasetDocuments' })}</span>
<RiExternalLinkLine className="h-3 w-3" />

View File

@@ -57,7 +57,7 @@ const Form: FC<FormProps> = React.memo(({
</label>
{variable === 'endpoint' && (
<a
href={docLink('/guides/knowledge-base/connect-external-knowledge-base') || '/'}
href={docLink('/use-dify/knowledge/connect-external-knowledge-base') || '/'}
target="_blank"
rel="noopener noreferrer"
className="body-xs-regular flex items-center text-text-accent"

View File

@@ -54,7 +54,7 @@ const ExternalAPIPanel: React.FC<ExternalAPIPanelProps> = ({ onClose }) => {
<div className="body-xs-regular self-stretch text-text-tertiary">{t('externalAPIPanelDescription', { ns: 'dataset' })}</div>
<a
className="flex cursor-pointer items-center justify-center gap-1 self-stretch"
href={docLink('/guides/knowledge-base/connect-external-knowledge-base')}
href={docLink('/use-dify/knowledge/connect-external-knowledge-base')}
target="_blank"
>
<RiBookOpenLine className="h-3 w-3 text-text-accent" />

View File

@@ -18,14 +18,14 @@ const InfoPanel = () => {
</span>
<span className="system-sm-regular text-text-tertiary">
{t('connectDatasetIntro.content.front', { ns: 'dataset' })}
<a className="system-sm-regular ml-1 text-text-accent" href={docLink('/guides/knowledge-base/external-knowledge-api')} target="_blank" rel="noopener noreferrer">
<a className="system-sm-regular ml-1 text-text-accent" href={docLink('/use-dify/knowledge/external-knowledge-api')} target="_blank" rel="noopener noreferrer">
{t('connectDatasetIntro.content.link', { ns: 'dataset' })}
</a>
{t('connectDatasetIntro.content.end', { ns: 'dataset' })}
</span>
<a
className="system-sm-regular self-stretch text-text-accent"
href={docLink('/guides/knowledge-base/connect-external-knowledge-base')}
href={docLink('/use-dify/knowledge/connect-external-knowledge-base')}
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -61,7 +61,7 @@ const ExternalKnowledgeBaseCreate: React.FC<ExternalKnowledgeBaseCreateProps> =
<span>{t('connectHelper.helper1', { ns: 'dataset' })}</span>
<span className="system-sm-medium text-text-secondary">{t('connectHelper.helper2', { ns: 'dataset' })}</span>
<span>{t('connectHelper.helper3', { ns: 'dataset' })}</span>
<a className="system-sm-regular self-stretch text-text-accent" href={docLink('/guides/knowledge-base/connect-external-knowledge-base')} target="_blank" rel="noopener noreferrer">
<a className="system-sm-regular self-stretch text-text-accent" href={docLink('/use-dify/knowledge/connect-external-knowledge-base')} target="_blank" rel="noopener noreferrer">
{t('connectHelper.helper4', { ns: 'dataset' })}
</a>
<span>

View File

@@ -96,9 +96,9 @@ const ModifyRetrievalModal: FC<Props> = ({
<a
target="_blank"
rel="noopener noreferrer"
href={docLink('/guides/knowledge-base/retrieval-test-and-citation#modify-text-retrieval-setting', {
'zh-Hans': '/guides/knowledge-base/retrieval-test-and-citation#修改文本检索方式',
'ja-JP': '/guides/knowledge-base/retrieval-test-and-citation',
href={docLink('/use-dify/knowledge/test-retrieval#modify-text-retrieval-setting', {
'zh-Hans': '/use-dify/knowledge/test-retrieval#修改文本检索方式',
'ja-JP': '/use-dify/knowledge/test-retrieval',
})}
className="text-text-accent"
>

View File

@@ -15,7 +15,7 @@ const NoLinkedAppsPanel = () => {
<div className="my-2 text-xs text-text-tertiary">{t('datasetMenus.emptyTip', { ns: 'common' })}</div>
<a
className="mt-2 inline-flex cursor-pointer items-center text-xs text-text-accent"
href={docLink('/guides/knowledge-base/integrate-knowledge-within-application')}
href={docLink('/use-dify/knowledge/integrate-knowledge-within-application')}
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -281,7 +281,7 @@ const Form = () => {
<a
target="_blank"
rel="noopener noreferrer"
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents/chunking-and-cleaning-text')}
href={docLink('/use-dify/knowledge/create-knowledge/chunking-and-cleaning-text')}
className="text-text-accent"
>
{t('form.chunkStructure.learnMore', { ns: 'datasetSettings' })}
@@ -421,9 +421,9 @@ const Form = () => {
<a
target="_blank"
rel="noopener noreferrer"
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#setting-the-retrieval-setting', {
'zh-Hans': '/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#指定检索方式',
'ja-JP': '/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#検索方法の指定',
href={docLink('/use-dify/knowledge/create-knowledge/setting-indexing-methods#setting-the-retrieval-setting', {
'zh-Hans': '/use-dify/knowledge/create-knowledge/setting-indexing-methods#指定检索方式',
'ja-JP': '/use-dify/knowledge/create-knowledge/setting-indexing-methods#検索方法の指定',
})}
className="text-text-accent"
>

View File

@@ -137,7 +137,7 @@ export default function AppSelector() {
<MenuItem>
<Link
className={cn(itemClassName, 'group justify-between', 'data-[active]:bg-state-base-hover')}
href={docLink('/introduction')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -17,7 +17,7 @@ const Empty = () => {
<div className="system-sm-medium mb-1 text-text-secondary">{t('apiBasedExtension.title', { ns: 'common' })}</div>
<a
className="system-xs-regular flex items-center text-text-accent"
href={docLink('/guides/extension/api-based-extension/README')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -102,7 +102,7 @@ const ApiBasedExtensionModal: FC<ApiBasedExtensionModalProps> = ({
<div className="flex h-9 items-center justify-between text-sm font-medium text-text-primary">
{t('apiBasedExtension.modal.apiEndpoint.title', { ns: 'common' })}
<a
href={docLink('/guides/extension/api-based-extension/README')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
className="group flex items-center text-xs font-normal text-text-accent"

View File

@@ -77,7 +77,7 @@ const EndpointList = ({ detail }: Props) => {
</div>
<div className="system-xs-regular text-text-tertiary">{t('detailPanel.endpointsTip', { ns: 'plugin' })}</div>
<a
href={docLink('/plugins/schema-definition/endpoint')}
href={docLink('/develop-plugin/getting-started/getting-started-dify-plugin')}
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -8,8 +8,7 @@ import * as React from 'react'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import Tooltip from '@/app/components/base/tooltip'
import { getDocsUrl } from '@/app/components/plugins/utils'
import { useLocale } from '@/context/i18n'
import { useDocLink } from '@/context/i18n'
import { useDebugKey } from '@/service/use-plugins'
import KeyValueItem from '../base/key-value-item'
@@ -17,7 +16,7 @@ const i18nPrefix = 'debugInfo'
const DebugInfo: FC = () => {
const { t } = useTranslation()
const locale = useLocale()
const docLink = useDocLink()
const { data: info, isLoading } = useDebugKey()
// info.key likes 4580bdb7-b878-471c-a8a4-bfd760263a53 mask the middle part using *.
@@ -34,7 +33,7 @@ const DebugInfo: FC = () => {
<>
<div className="flex items-center gap-1 self-stretch">
<span className="system-sm-semibold flex shrink-0 grow basis-0 flex-col items-start justify-center text-text-secondary">{t(`${i18nPrefix}.title`, { ns: 'plugin' })}</span>
<a href={getDocsUrl(locale, '/plugins/quick-start/debug-plugin')} target="_blank" className="flex cursor-pointer items-center gap-0.5 text-text-accent-light-mode-only">
<a href={docLink('/use-dify/getting-started/introduction')} target="_blank" className="flex cursor-pointer items-center gap-0.5 text-text-accent-light-mode-only">
<span className="system-xs-medium">{t(`${i18nPrefix}.viewDocs`, { ns: 'plugin' })}</span>
<RiArrowRightUpLine className="h-3 w-3" />
</a>

View File

@@ -15,10 +15,9 @@ import Button from '@/app/components/base/button'
import TabSlider from '@/app/components/base/tab-slider'
import Tooltip from '@/app/components/base/tooltip'
import ReferenceSettingModal from '@/app/components/plugins/reference-setting-modal'
import { getDocsUrl } from '@/app/components/plugins/utils'
import { MARKETPLACE_API_PREFIX, SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { useLocale } from '@/context/i18n'
import { useDocLink } from '@/context/i18n'
import useDocumentTitle from '@/hooks/use-document-title'
import { usePluginInstallation } from '@/hooks/use-query-params'
import { fetchBundleInfoFromMarketPlace, fetchManifestFromMarketPlace } from '@/service/plugins'
@@ -47,7 +46,7 @@ const PluginPage = ({
marketplace,
}: PluginPageProps) => {
const { t } = useTranslation()
const locale = useLocale()
const docLink = useDocLink()
useDocumentTitle(t('metadata.title', { ns: 'plugin' }))
// Use nuqs hook for installation state
@@ -175,7 +174,7 @@ const PluginPage = ({
</Button>
</Link>
<Link
href={getDocsUrl(locale, '/plugins/publish-plugins/publish-to-dify-marketplace/README')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
>
<Button

View File

@@ -2,7 +2,6 @@ import type {
TagKey,
} from './constants'
import { LanguagesSupported } from '@/i18n-config/language'
import {
categoryKeys,
tagKeys,
@@ -15,15 +14,3 @@ export const getValidTagKeys = (tags: TagKey[]) => {
export const getValidCategoryKeys = (category?: string) => {
return categoryKeys.find(key => key === category)
}
export const getDocsUrl = (locale: string, path: string) => {
let localePath = 'en'
if (locale === LanguagesSupported[1])
localePath = 'zh-hans'
else if (locale === LanguagesSupported[7])
localePath = 'ja-jp'
return `https://docs.dify.ai/${localePath}${path}`
}

View File

@@ -34,6 +34,7 @@ import {
} from '@/app/components/workflow/store'
import { getKeyboardKeyCodeBySystem, getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { useDocLink } from '@/context/i18n'
import { useModalContextSelector } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
import { useDatasetApiAccessUrl } from '@/hooks/use-api-access-url'
@@ -55,6 +56,7 @@ const Popup = () => {
const { t } = useTranslation()
const { datasetId } = useParams()
const { push } = useRouter()
const docLink = useDocLink()
const publishedAt = useStore(s => s.publishedAt)
const draftUpdatedAt = useStore(s => s.draftUpdatedAt)
const pipelineId = useStore(s => s.pipelineId)
@@ -186,7 +188,7 @@ const Popup = () => {
{t('publishTemplate.success.tip', { ns: 'datasetPipeline' })}
</span>
<Link
href="https://docs.dify.ai"
href={docLink()}
target="_blank"
className="system-xs-medium-uppercase inline-block text-text-accent"
>

View File

@@ -6,11 +6,11 @@ import dataSourceEmptyDefault from '@/app/components/workflow/nodes/data-source-
import dataSourceDefault from '@/app/components/workflow/nodes/data-source/default'
import knowledgeBaseDefault from '@/app/components/workflow/nodes/knowledge-base/default'
import { BlockEnum } from '@/app/components/workflow/types'
import { useGetLanguage } from '@/context/i18n'
import { useDocLink } from '@/context/i18n'
export const useAvailableNodesMetaData = () => {
const { t } = useTranslation()
const language = useGetLanguage()
const docLink = useDocLink()
const mergedNodesMetaData = useMemo(() => [
...WORKFLOW_COMMON_NODES,
@@ -25,14 +25,9 @@ export const useAvailableNodesMetaData = () => {
dataSourceEmptyDefault,
], [])
const helpLinkUri = useMemo(() => {
if (language === 'zh_Hans')
return 'https://docs.dify.ai/zh-hans/guides/knowledge-base/knowledge-pipeline/knowledge-pipeline-orchestration#%E6%AD%A5%E9%AA%A4%E4%B8%80%EF%BC%9A%E6%95%B0%E6%8D%AE%E6%BA%90%E9%85%8D%E7%BD%AE'
if (language === 'ja_JP')
return 'https://docs.dify.ai/ja-jp/guides/knowledge-base/knowledge-pipeline/knowledge-pipeline-orchestration#%E3%82%B9%E3%83%86%E3%83%83%E3%83%971%EF%BC%9A%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E8%A8%AD%E5%AE%9A'
return 'https://docs.dify.ai/en/guides/knowledge-base/knowledge-pipeline/knowledge-pipeline-orchestration#step-1%3A-data-source'
}, [language])
const helpLinkUri = useMemo(() => docLink(
'/use-dify/getting-started/introduction',
), [docLink])
const availableNodesMetaData = useMemo(() => mergedNodesMetaData.map((node) => {
const { metaData } = node

View File

@@ -8,8 +8,7 @@ import {
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useAppContext } from '@/context/app-context'
import { useLocale } from '@/context/i18n'
import { getLanguage } from '@/i18n-config/language'
import { useDocLink } from '@/context/i18n'
import { useCreateMCP } from '@/service/use-tools'
import MCPModal from './modal'
@@ -19,8 +18,7 @@ type Props = {
const NewMCPCard = ({ handleCreate }: Props) => {
const { t } = useTranslation()
const locale = useLocale()
const language = getLanguage(locale)
const docLink = useDocLink()
const { isCurrentWorkspaceManager } = useAppContext()
const { mutateAsync: createMCP } = useCreateMCP()
@@ -30,13 +28,7 @@ const NewMCPCard = ({ handleCreate }: Props) => {
handleCreate(provider)
}
const linkUrl = useMemo(() => {
if (language.startsWith('zh_'))
return 'https://docs.dify.ai/zh-hans/guides/tools/mcp'
if (language.startsWith('ja_jp'))
return 'https://docs.dify.ai/ja_jp/guides/tools/mcp'
return 'https://docs.dify.ai/en/guides/tools/mcp'
}, [language])
const linkUrl = useMemo(() => docLink('/use-dify/getting-started/introduction'), [docLink])
const [showModal, setShowModal] = useState(false)

View File

@@ -200,7 +200,7 @@ function MCPServiceCard({
</div>
<div
className="cursor-pointer text-xs font-normal text-text-accent hover:underline"
onClick={() => window.open(docLink('/guides/workflow/node/user-input'), '_blank')}
onClick={() => window.open(docLink('/use-dify/nodes/user-input'), '_blank')}
>
{t('overview.appInfo.enableTooltip.learnMore', { ns: 'appOverview' })}
</div>

View File

@@ -5,13 +5,12 @@ import {
RiArrowRightUpLine,
RiBookOpenLine,
} from '@remixicon/react'
import { useMemo, useState } from 'react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import Toast from '@/app/components/base/toast'
import EditCustomToolModal from '@/app/components/tools/edit-custom-collection-modal'
import { useAppContext } from '@/context/app-context'
import { useDocLink, useLocale } from '@/context/i18n'
import { getLanguage } from '@/i18n-config/language'
import { useDocLink } from '@/context/i18n'
import { createCustomCollection } from '@/service/tools'
type Props = {
@@ -20,16 +19,10 @@ type Props = {
const Contribute = ({ onRefreshData }: Props) => {
const { t } = useTranslation()
const locale = useLocale()
const language = getLanguage(locale)
const { isCurrentWorkspaceManager } = useAppContext()
const docLink = useDocLink()
const linkUrl = useMemo(() => {
return docLink('/guides/tools#how-to-create-custom-tools', {
'zh-Hans': '/guides/tools#ru-he-chuang-jian-zi-ding-yi-gong-ju',
})
}, [language])
const linkUrl = docLink('/use-dify/getting-started/introduction')
const [isShowEditCollectionToolModal, setIsShowEditCustomCollectionModal] = useState(false)
const doCreateCustomToolCollection = async (data: CustomCollectionBackend) => {

View File

@@ -64,7 +64,7 @@ const WorkflowOnboardingModal: FC<WorkflowOnboardingModalProps> = ({
{t('onboarding.description', { ns: 'workflow' })}
{' '}
<a
href={docLink('/guides/workflow/node/start')}
href={docLink('/use-dify/getting-started/key-concepts#workflow')}
target="_blank"
rel="noopener noreferrer"
className="hover:text-text-accent-hover cursor-pointer text-text-accent underline"

View File

@@ -1,4 +1,5 @@
import type { AvailableNodesMetaData } from '@/app/components/workflow/hooks-store/store'
import type { DocPathWithoutLang } from '@/types/doc-paths'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { WORKFLOW_COMMON_NODES } from '@/app/components/workflow/constants/node'
@@ -44,7 +45,7 @@ export const useAvailableNodesMetaData = () => {
const { metaData } = node
const title = t(`blocks.${metaData.type}`, { ns: 'workflow' })
const description = t(`blocksAbout.${metaData.type}`, { ns: 'workflow' })
const helpLinkPath = `guides/workflow/node/${metaData.helpLinkUri}`
const helpLinkPath = `/use-dify/nodes/user-input/${metaData.helpLinkUri}` as DocPathWithoutLang
return {
...node,
metaData: {

View File

@@ -255,9 +255,9 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
{' '}
<br />
<Link
href={docLink('/guides/workflow/node/agent#select-an-agent-strategy', {
'zh-Hans': '/guides/workflow/node/agent#选择-agent-策略',
'ja-JP': '/guides/workflow/node/agent#エージェント戦略の選択',
href={docLink('/use-dify/nodes/agent#select-an-agent-strategy', {
'zh-Hans': '/use-dify/nodes/agent#选择-agent-策略',
'ja-JP': '/use-dify/nodes/agent#エージェント戦略の選択',
})}
className="text-text-accent-secondary"
target="_blank"

View File

@@ -36,9 +36,7 @@ const DefaultValue = ({
{t('nodes.common.errorHandle.defaultValue.desc', { ns: 'workflow' })}
&nbsp;
<a
href={docLink('/guides/workflow/error-handling/README', {
'zh-Hans': '/guides/workflow/error-handling/readme',
})}
href={docLink('/use-dify/build/predefined-error-handling-logic')}
target="_blank"
className="text-text-accent"
>

View File

@@ -19,7 +19,7 @@ const FailBranchCard = () => {
{t('nodes.common.errorHandle.failBranch.customizeTip', { ns: 'workflow' })}
&nbsp;
<a
href={docLink('/guides/workflow/error-handling/error-type')}
href={docLink('/use-dify/build/predefined-error-handling-logic')}
target="_blank"
className="text-text-accent"
>

View File

@@ -62,10 +62,7 @@ const VarReferencePopup: FC<Props> = ({
target="_blank"
rel="noopener noreferrer"
className="text-text-accent-secondary"
href={docLink('/guides/workflow/variables#conversation-variables', {
'zh-Hans': '/guides/workflow/variables#会话变量',
'ja-JP': '/guides/workflow/variables#会話変数',
})}
href={docLink('/use-dify/getting-started/introduction')}
>
{t('variableReference.conversationVars', { ns: 'workflow' })}
</a>

View File

@@ -31,7 +31,7 @@ const Instruction = ({
<div className="system-xs-regular">
<p className="text-text-tertiary">{t('nodes.knowledgeBase.chunkStructureTip.message', { ns: 'workflow' })}</p>
<a
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents/chunking-and-cleaning-text')}
href={docLink('/use-dify/knowledge/create-knowledge/chunking-and-cleaning-text')}
target="_blank"
rel="noopener noreferrer"
className="text-text-accent"

View File

@@ -11,6 +11,7 @@ import {
} from 'react'
import { useTranslation } from 'react-i18next'
import { Field } from '@/app/components/workflow/nodes/_base/components/layout'
import { useDocLink } from '@/context/i18n'
import { useRetrievalSetting } from './hooks'
import SearchMethodOption from './search-method-option'
@@ -50,6 +51,7 @@ const RetrievalSetting = ({
showMultiModalTip,
}: RetrievalSettingProps) => {
const { t } = useTranslation()
const docLink = useDocLink()
const {
options,
hybridSearchModeOptions,
@@ -61,7 +63,7 @@ const RetrievalSetting = ({
title: t('form.retrievalSetting.title', { ns: 'datasetSettings' }),
subTitle: (
<div className="body-xs-regular flex items-center 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('form.retrievalSetting.learnMore', { ns: 'datasetSettings' })}</a>
<a target="_blank" rel="noopener noreferrer" href={docLink('/use-dify/knowledge/create-knowledge/introduction#id-4-retrieval-settings')} className="text-text-accent">{t('form.retrievalSetting.learnMore', { ns: 'datasetSettings' })}</a>
&nbsp;
{t('nodes.knowledgeBase.aboutRetrieval', { ns: 'workflow' })}
</div>

View File

@@ -255,7 +255,7 @@ const JsonSchemaConfig: FC<JsonSchemaConfigProps> = ({
<div className="flex items-center gap-x-2 p-6 pt-5">
<a
className="flex grow items-center gap-x-1 text-text-accent"
href={docLink('/guides/workflow/structured-outputs')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -152,10 +152,7 @@ const ChatVariablePanel = () => {
target="_blank"
rel="noopener noreferrer"
className="text-text-accent"
href={docLink('/guides/workflow/variables#conversation-variables', {
'zh-Hans': '/guides/workflow/variables#会话变量',
'ja-JP': '/guides/workflow/variables#会話変数',
})}
href={docLink('/use-dify/getting-started/introduction')}
>
{t('chatVariable.docLink', { ns: 'workflow' })}
</a>

View File

@@ -211,7 +211,7 @@ const NodePanel: FC<Props> = ({
<StatusContainer status="stopped">
{nodeInfo.error}
<a
href={docLink('/guides/workflow/error-handling/error-type')}
href={docLink('/use-dify/build/predefined-error-handling-logic')}
target="_blank"
className="text-text-accent"
>

View File

@@ -139,7 +139,7 @@ const StatusPanel: FC<ResultProps> = ({
<div className="system-xs-medium text-text-warning">
{error}
<a
href={docLink('/guides/workflow/error-handling/error-type')}
href={docLink('/use-dify/getting-started/introduction')}
target="_blank"
className="text-text-accent"
>

View File

@@ -1,9 +1,11 @@
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
import { useDocLink } from '@/context/i18n'
const Empty: FC = () => {
const { t } = useTranslation()
const docLink = useDocLink()
return (
<div className="flex h-full flex-col gap-3 rounded-xl bg-background-section p-8">
@@ -15,7 +17,7 @@ const Empty: FC = () => {
<div className="system-xs-regular text-text-tertiary">{t('debug.variableInspect.emptyTip', { ns: 'workflow' })}</div>
<a
className="system-xs-regular cursor-pointer text-text-accent"
href="https://docs.dify.ai/en/guides/workflow/debug-and-preview/variable-inspect"
href={docLink('/use-dify/debug/variable-inspect')}
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -163,7 +163,7 @@ const EducationApplyAge = () => {
<div className="mb-4 mt-5 h-px bg-gradient-to-r from-[rgba(16,24,40,0.08)]"></div>
<a
className="system-xs-regular flex items-center text-text-accent"
href={docLink('/getting-started/dify-for-education')}
href={docLink('/use-dify/workspace/subscription-management#dify-for-education')}
target="_blank"
>
{t('learn', { ns: 'education' })}

View File

@@ -25,7 +25,7 @@ const i18nPrefix = 'notice'
const ExpireNoticeModal: React.FC<Props> = ({ expireAt, expired, onClose }) => {
const { t } = useTranslation()
const docLink = useDocLink()
const eduDocLink = docLink('/getting-started/dify-for-education')
const eduDocLink = docLink('/use-dify/workspace/subscription-management#dify-for-education')
const { formatTime } = useTimestamp()
const setShowPricingModal = useModalContextSelector(s => s.setShowPricingModal)
const { mutateAsync } = useEducationVerify()

View File

@@ -34,7 +34,7 @@ function Confirm({
const docLink = useDocLink()
const dialogRef = useRef<HTMLDivElement>(null)
const [isVisible, setIsVisible] = useState(isShow)
const eduDocLink = docLink('/getting-started/dify-for-education')
const eduDocLink = docLink('/use-dify/workspace/subscription-management#dify-for-education')
const handleClick = () => {
window.open(eduDocLink, '_blank', 'noopener,noreferrer')

View File

@@ -219,7 +219,7 @@ const InstallForm = () => {
className="text-text-accent"
target="_blank"
rel="noopener noreferrer"
href={docLink('/policies/open-source')}
href={docLink('/use-dify/getting-started/introduction')}
>
{t('license.link', { ns: 'login' })}
</Link>

View File

@@ -161,7 +161,7 @@ export default function InviteSettingsPage() {
className="system-xs-medium text-text-accent-secondary"
target="_blank"
rel="noopener noreferrer"
href={docLink('/policies/open-source')}
href={docLink('/use-dify/getting-started/introduction')}
>
{t('license.link', { ns: 'login' })}
</Link>

View File

@@ -159,7 +159,7 @@ const OneMoreStep = () => {
className="system-xs-medium text-text-accent-secondary"
target="_blank"
rel="noopener noreferrer"
href={docLink('/policies/agreement/README')}
href={docLink('/use-dify/getting-started/introduction')}
>
{t('license.link', { ns: 'login' })}
</Link>

View File

@@ -1,6 +1,8 @@
import type { Locale } from '@/i18n-config/language'
import type { DocPathWithoutLang } from '@/types/doc-paths'
import { useTranslation } from '#i18n'
import { getDocLanguage, getLanguage, getPricingPageLanguage } from '@/i18n-config/language'
import { apiReferencePathTranslations } from '@/types/doc-paths'
export const useLocale = () => {
const { i18n } = useTranslation()
@@ -19,15 +21,24 @@ export const useGetPricingPageLanguage = () => {
}
export const defaultDocBaseUrl = 'https://docs.dify.ai'
export const useDocLink = (baseUrl?: string): ((path?: string, pathMap?: { [index: string]: string }) => string) => {
export type DocPathMap = Partial<Record<Locale, DocPathWithoutLang>>
export const useDocLink = (baseUrl?: string): ((path?: DocPathWithoutLang, pathMap?: DocPathMap) => string) => {
let baseDocUrl = baseUrl || defaultDocBaseUrl
baseDocUrl = (baseDocUrl.endsWith('/')) ? baseDocUrl.slice(0, -1) : baseDocUrl
const locale = useLocale()
const docLanguage = getDocLanguage(locale)
return (path?: string, pathMap?: { [index: string]: string }): string => {
return (path?: DocPathWithoutLang, pathMap?: DocPathMap): string => {
const pathUrl = path || ''
let targetPath = (pathMap) ? pathMap[locale] || pathUrl : pathUrl
targetPath = (targetPath.startsWith('/')) ? targetPath.slice(1) : targetPath
return `${baseDocUrl}/${docLanguage}/${targetPath}`
// Translate API reference paths for non-English locales
if (targetPath.startsWith('/api-reference/') && docLanguage !== 'en') {
const translatedPath = apiReferencePathTranslations[targetPath]?.[docLanguage as 'zh' | 'ja']
if (translatedPath)
targetPath = translatedPath
}
return `${baseDocUrl}/${docLanguage}${targetPath}`
}
}

View File

@@ -35,7 +35,7 @@ export default antfu(
},
},
nextjs: true,
ignores: ['public'],
ignores: ['public', 'types/doc-paths.ts'],
typescript: {
overrides: {
'ts/consistent-type-definitions': ['error', 'type'],

View File

@@ -1,16 +1,7 @@
import { useMemo } from 'react'
import { useGetLanguage } from '@/context/i18n'
import { useDocLink } from '@/context/i18n'
export const useDatasetApiAccessUrl = () => {
const locale = useGetLanguage()
const docLink = useDocLink()
const apiReferenceUrl = useMemo(() => {
if (locale === 'zh_Hans')
return 'https://docs.dify.ai/api-reference/%E6%95%B0%E6%8D%AE%E9%9B%86'
if (locale === 'ja_JP')
return 'https://docs.dify.ai/api-reference/%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88'
return 'https://docs.dify.ai/api-reference/datasets'
}, [locale])
return apiReferenceUrl
return docLink('/api-reference/datasets/get-knowledge-base-list')
}

View File

@@ -1,3 +1,4 @@
import type { DocLanguage } from '@/types/doc-paths'
import data from './languages'
export type Item = {
@@ -22,9 +23,9 @@ export const getLanguage = (locale: Locale): Locale => {
return LanguagesSupported[0].replace('-', '_') as Locale
}
const DOC_LANGUAGE: Record<string, string> = {
'zh-Hans': 'zh-hans',
'ja-JP': 'ja-jp',
const DOC_LANGUAGE: Record<string, DocLanguage | undefined> = {
'zh-Hans': 'zh',
'ja-JP': 'ja',
'en-US': 'en',
}
@@ -56,7 +57,7 @@ export const localeMap: Record<Locale, string> = {
'ar-TN': 'ar',
}
export const getDocLanguage = (locale: string) => {
export const getDocLanguage = (locale: string): DocLanguage => {
return DOC_LANGUAGE[locale] || 'en'
}

View File

@@ -38,6 +38,7 @@
"type-check:tsgo": "tsgo --noEmit",
"prepare": "cd ../ && node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky ./web/.husky",
"gen-icons": "node ./scripts/gen-icons.mjs && eslint --fix app/components/base/icons/src/",
"gen-doc-paths": "tsx ./scripts/gen-doc-paths.ts",
"uglify-embed": "node ./bin/uglify-embed",
"i18n:check": "tsx ./scripts/check-i18n.js",
"test": "vitest run",

View File

@@ -0,0 +1,481 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
//
// This script fetches the docs.json from dify-docs repository
// and generates TypeScript types for documentation paths.
//
// Usage: pnpm gen-doc-paths
import { writeFile } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const DOCS_JSON_URL = 'https://raw.githubusercontent.com/langgenius/dify-docs/refs/heads/main/docs.json'
const OUTPUT_PATH = path.resolve(__dirname, '../types/doc-paths.ts')
type NavItem = string | NavObject | NavItem[]
type NavObject = {
pages?: NavItem[]
groups?: NavItem[]
dropdowns?: NavItem[]
languages?: NavItem[]
versions?: NavItem[]
openapi?: string
[key: string]: unknown
}
type OpenAPIOperation = {
summary?: string
operationId?: string
tags?: string[]
[key: string]: unknown
}
type OpenAPIPathItem = {
get?: OpenAPIOperation
post?: OpenAPIOperation
put?: OpenAPIOperation
patch?: OpenAPIOperation
delete?: OpenAPIOperation
[key: string]: unknown
}
type OpenAPISpec = {
paths?: Record<string, OpenAPIPathItem>
[key: string]: unknown
}
type Redirect = {
source: string
destination: string
}
type DocsJson = {
navigation?: NavItem
redirects?: Redirect[]
[key: string]: unknown
}
const OPENAPI_BASE_URL = 'https://raw.githubusercontent.com/langgenius/dify-docs/refs/heads/main/'
/**
* Convert summary to URL slug
* e.g., "Get Knowledge Base List" -> "get-knowledge-base-list"
* e.g., "获取知识库列表" -> "获取知识库列表"
*/
function summaryToSlug(summary: string): string {
return summary
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '')
}
/**
* Get the first path segment from an API path
* e.g., "/datasets/{dataset_id}/documents" -> "datasets"
*/
function getFirstPathSegment(apiPath: string): string {
const segments = apiPath.split('/').filter(Boolean)
return segments[0] || ''
}
/**
* Recursively extract OpenAPI file paths from navigation structure
*/
function extractOpenAPIPaths(item: NavItem | undefined, paths: Set<string> = new Set()): Set<string> {
if (!item)
return paths
if (Array.isArray(item)) {
for (const el of item)
extractOpenAPIPaths(el, paths)
return paths
}
if (typeof item === 'object') {
if (item.openapi && typeof item.openapi === 'string')
paths.add(item.openapi)
if (item.pages)
extractOpenAPIPaths(item.pages, paths)
if (item.groups)
extractOpenAPIPaths(item.groups, paths)
if (item.dropdowns)
extractOpenAPIPaths(item.dropdowns, paths)
if (item.languages)
extractOpenAPIPaths(item.languages, paths)
if (item.versions)
extractOpenAPIPaths(item.versions, paths)
}
return paths
}
type EndpointPathMap = Map<string, string> // key: `${apiPath}_${method}`, value: generated doc path
/**
* Fetch and parse OpenAPI spec, extract API reference paths with endpoint keys
*/
async function fetchOpenAPIAndExtractPaths(openapiPath: string): Promise<EndpointPathMap> {
const url = `${OPENAPI_BASE_URL}${openapiPath}`
const response = await fetch(url)
if (!response.ok) {
console.warn(`Failed to fetch ${url}: ${response.status}`)
return new Map()
}
const spec = await response.json() as OpenAPISpec
const pathMap: EndpointPathMap = new Map()
if (!spec.paths)
return pathMap
const httpMethods = ['get', 'post', 'put', 'patch', 'delete'] as const
for (const [apiPath, pathItem] of Object.entries(spec.paths)) {
for (const method of httpMethods) {
const operation = pathItem[method]
if (operation?.summary) {
// Try to get tag from operation, fallback to path segment
const tag = operation.tags?.[0]
const segment = tag ? summaryToSlug(tag) : getFirstPathSegment(apiPath)
if (!segment)
continue
const slug = summaryToSlug(operation.summary)
// Skip empty slugs
if (slug) {
const endpointKey = `${apiPath}_${method}`
pathMap.set(endpointKey, `/api-reference/${segment}/${slug}`)
}
}
}
}
return pathMap
}
/**
* Recursively extract all page paths from navigation structure
*/
function extractPaths(item: NavItem | undefined, paths: Set<string> = new Set()): Set<string> {
if (!item)
return paths
if (Array.isArray(item)) {
for (const el of item)
extractPaths(el, paths)
return paths
}
if (typeof item === 'string') {
paths.add(item)
return paths
}
if (typeof item === 'object') {
// Handle pages array
if (item.pages)
extractPaths(item.pages, paths)
// Handle groups array
if (item.groups)
extractPaths(item.groups, paths)
// Handle dropdowns
if (item.dropdowns)
extractPaths(item.dropdowns, paths)
// Handle languages
if (item.languages)
extractPaths(item.languages, paths)
// Handle versions in navigation
if (item.versions)
extractPaths(item.versions, paths)
}
return paths
}
/**
* Group paths by their prefix structure
*/
function groupPathsBySection(paths: Set<string>): Record<string, Set<string>> {
const groups: Record<string, Set<string>> = {}
for (const fullPath of paths) {
// Skip non-doc paths (like .json files for OpenAPI)
if (fullPath.endsWith('.json'))
continue
// Remove language prefix (en/, zh/, ja/)
const withoutLang = fullPath.replace(/^(en|zh|ja)\//, '')
if (!withoutLang || withoutLang === fullPath)
continue
// Get section (first part of path)
const parts = withoutLang.split('/')
const section = parts[0]
if (!groups[section])
groups[section] = new Set()
groups[section].add(withoutLang)
}
return groups
}
/**
* Convert section name to TypeScript type name
*/
function sectionToTypeName(section: string): string {
return section
.split('-')
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
.join('')
}
/**
* Generate TypeScript type definitions
*/
function generateTypeDefinitions(
groups: Record<string, Set<string>>,
apiReferencePaths: string[],
apiPathTranslations: Record<string, { zh?: string, ja?: string }>,
): string {
const lines: string[] = [
'// GENERATE BY script',
'// DON NOT EDIT IT MANUALLY',
'//',
'// Generated from: https://raw.githubusercontent.com/langgenius/dify-docs/refs/heads/main/docs.json',
`// Generated at: ${new Date().toISOString()}`,
'',
'// Language prefixes',
'export type DocLanguage = \'en\' | \'zh\' | \'ja\'',
'',
]
const typeNames: string[] = []
// Generate type for each section
for (const [section, pathsSet] of Object.entries(groups)) {
const paths = Array.from(pathsSet).sort()
const typeName = `${sectionToTypeName(section)}Path`
typeNames.push(typeName)
lines.push(`// ${sectionToTypeName(section)} paths`)
lines.push(`export type ${typeName} =`)
for (const p of paths) {
lines.push(` | '/${p}'`)
}
lines.push('')
}
// Generate API reference type (English paths only)
if (apiReferencePaths.length > 0) {
const sortedPaths = [...apiReferencePaths].sort()
lines.push('// API Reference paths (English, use apiReferencePathTranslations for other languages)')
lines.push('export type ApiReferencePath =')
for (const p of sortedPaths) {
lines.push(` | '${p}'`)
}
lines.push('')
typeNames.push('ApiReferencePath')
}
// Generate base combined type
lines.push('// Base path without language prefix')
lines.push('export type DocPathWithoutLangBase =')
for (const typeName of typeNames) {
lines.push(` | ${typeName}`)
}
lines.push('')
// Generate combined type with optional anchor support
lines.push('// Combined path without language prefix (supports optional #anchor)')
lines.push('export type DocPathWithoutLang =')
lines.push(' | DocPathWithoutLangBase')
// eslint-disable-next-line no-template-curly-in-string
lines.push(' | `${DocPathWithoutLangBase}#${string}`')
lines.push('')
// Generate full path type with language prefix
lines.push('// Full documentation path with language prefix')
// eslint-disable-next-line no-template-curly-in-string
lines.push('export type DifyDocPath = `${DocLanguage}/${DocPathWithoutLang}`')
lines.push('')
// Generate API reference path translations map
lines.push('// API Reference path translations (English -> other languages)')
lines.push('export const apiReferencePathTranslations: Record<string, { zh?: string; ja?: string }> = {')
const sortedEnPaths = Object.keys(apiPathTranslations).sort()
for (const enPath of sortedEnPaths) {
const translations = apiPathTranslations[enPath]
const parts: string[] = []
if (translations.zh)
parts.push(`zh: '${translations.zh}'`)
if (translations.ja)
parts.push(`ja: '${translations.ja}'`)
if (parts.length > 0)
lines.push(` '${enPath}': { ${parts.join(', ')} },`)
}
lines.push('}')
lines.push('')
return lines.join('\n')
}
/**
* Generate redirects map for ESLint rule
* Strips language prefix from paths for use with useDocLink
*/
function generateRedirectsModule(redirects: Redirect[]): string {
const lines: string[] = [
'// GENERATE BY script',
'// DON NOT EDIT IT MANUALLY',
'//',
'// Generated from: https://raw.githubusercontent.com/langgenius/dify-docs/refs/heads/main/docs.json',
`// Generated at: ${new Date().toISOString()}`,
'',
'/** @type {Map<string, string>} */',
'export const docRedirects = new Map([',
]
// Use a map to deduplicate paths (same path in different languages)
const pathMap = new Map<string, string>()
const langPrefixRegex = /^\/(en|zh|ja|zh-hans|ja-jp)\//
for (const redirect of redirects) {
// Skip wildcard redirects
if (redirect.source.includes(':slug'))
continue
// Strip language prefix from source and destination
const sourceWithoutLang = redirect.source.replace(langPrefixRegex, '')
const destWithoutLang = redirect.destination.replace(langPrefixRegex, '')
// Only add if we haven't seen this path yet
if (!pathMap.has(sourceWithoutLang))
pathMap.set(sourceWithoutLang, destWithoutLang)
}
for (const [source, dest] of pathMap) {
lines.push(` ['${source}', '${dest}'],`)
}
lines.push('])')
lines.push('')
return lines.join('\n')
}
async function main(): Promise<void> {
// eslint-disable-next-line no-console
console.log('Fetching docs.json from GitHub...')
const response = await fetch(DOCS_JSON_URL)
if (!response.ok)
throw new Error(`Failed to fetch docs.json: ${response.status} ${response.statusText}`)
const docsJson = await response.json() as DocsJson
// eslint-disable-next-line no-console
console.log('Successfully fetched docs.json')
// Extract paths from navigation
const allPaths = extractPaths(docsJson.navigation)
// eslint-disable-next-line no-console
console.log(`Found ${allPaths.size} total paths`)
// Extract OpenAPI file paths from navigation for all languages
const openApiPaths = extractOpenAPIPaths(docsJson.navigation)
// eslint-disable-next-line no-console
console.log(`Found ${openApiPaths.size} OpenAPI specs to process`)
// Fetch OpenAPI specs and extract API reference paths with endpoint keys
// Group by OpenAPI file name (without language prefix) to match endpoints across languages
const endpointMapsByLang: Record<string, Map<string, EndpointPathMap>> = {
en: new Map(),
zh: new Map(),
ja: new Map(),
}
for (const openapiPath of openApiPaths) {
// Determine language from path
const langMatch = openapiPath.match(/^(en|zh|ja)\//)
if (!langMatch)
continue
const lang = langMatch[1]
// Get file name without language prefix (e.g., "api-reference/openapi_knowledge.json")
const fileKey = openapiPath.replace(/^(en|zh|ja)\//, '')
// eslint-disable-next-line no-console
console.log(`Fetching OpenAPI spec: ${openapiPath}`)
const pathMap = await fetchOpenAPIAndExtractPaths(openapiPath)
endpointMapsByLang[lang].set(fileKey, pathMap)
}
// Build English paths and mapping to other languages
const enApiPaths: string[] = []
const apiPathTranslations: Record<string, { zh?: string, ja?: string }> = {}
// Iterate through English endpoint maps
for (const [fileKey, enPathMap] of endpointMapsByLang.en) {
const zhPathMap = endpointMapsByLang.zh.get(fileKey)
const jaPathMap = endpointMapsByLang.ja.get(fileKey)
for (const [endpointKey, enPath] of enPathMap) {
enApiPaths.push(enPath)
const zhPath = zhPathMap?.get(endpointKey)
const jaPath = jaPathMap?.get(endpointKey)
if (zhPath || jaPath) {
apiPathTranslations[enPath] = {}
if (zhPath)
apiPathTranslations[enPath].zh = zhPath
if (jaPath)
apiPathTranslations[enPath].ja = jaPath
}
}
}
// Deduplicate English API paths
const uniqueEnApiPaths = [...new Set(enApiPaths)]
// eslint-disable-next-line no-console
console.log(`Extracted ${uniqueEnApiPaths.length} unique English API reference paths`)
// eslint-disable-next-line no-console
console.log(`Generated ${Object.keys(apiPathTranslations).length} API path translations`)
// Group by section
const groups = groupPathsBySection(allPaths)
// eslint-disable-next-line no-console
console.log(`Grouped into ${Object.keys(groups).length} sections:`, Object.keys(groups))
// Generate TypeScript
const tsContent = generateTypeDefinitions(groups, uniqueEnApiPaths, apiPathTranslations)
// Write to file
await writeFile(OUTPUT_PATH, tsContent, 'utf-8')
// eslint-disable-next-line no-console
console.log(`Generated TypeScript types at: ${OUTPUT_PATH}`)
}
main().catch((err: Error) => {
console.error('Error:', err.message)
process.exit(1)
})

312
web/types/doc-paths.ts Normal file
View File

@@ -0,0 +1,312 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
//
// Generated from: https://raw.githubusercontent.com/langgenius/dify-docs/refs/heads/main/docs.json
// Generated at: 2026-01-12T09:11:29.762Z
// Language prefixes
export type DocLanguage = 'en' | 'zh' | 'ja'
// UseDify paths
export type UseDifyPath =
| '/use-dify/build/additional-features'
| '/use-dify/build/goto-anything'
| '/use-dify/build/mcp'
| '/use-dify/build/orchestrate-node'
| '/use-dify/build/predefined-error-handling-logic'
| '/use-dify/build/shortcut-key'
| '/use-dify/build/version-control'
| '/use-dify/debug/error-type'
| '/use-dify/debug/history-and-logs'
| '/use-dify/debug/step-run'
| '/use-dify/debug/variable-inspect'
| '/use-dify/getting-started/introduction'
| '/use-dify/getting-started/key-concepts'
| '/use-dify/getting-started/quick-start'
| '/use-dify/knowledge/connect-external-knowledge-base'
| '/use-dify/knowledge/create-knowledge/chunking-and-cleaning-text'
| '/use-dify/knowledge/create-knowledge/import-text-data/readme'
| '/use-dify/knowledge/create-knowledge/import-text-data/sync-from-notion'
| '/use-dify/knowledge/create-knowledge/import-text-data/sync-from-website'
| '/use-dify/knowledge/create-knowledge/introduction'
| '/use-dify/knowledge/create-knowledge/setting-indexing-methods'
| '/use-dify/knowledge/external-knowledge-api'
| '/use-dify/knowledge/integrate-knowledge-within-application'
| '/use-dify/knowledge/knowledge-pipeline/authorize-data-source'
| '/use-dify/knowledge/knowledge-pipeline/create-knowledge-pipeline'
| '/use-dify/knowledge/knowledge-pipeline/knowledge-pipeline-orchestration'
| '/use-dify/knowledge/knowledge-pipeline/manage-knowledge-base'
| '/use-dify/knowledge/knowledge-pipeline/publish-knowledge-pipeline'
| '/use-dify/knowledge/knowledge-pipeline/readme'
| '/use-dify/knowledge/knowledge-pipeline/upload-files'
| '/use-dify/knowledge/knowledge-request-rate-limit'
| '/use-dify/knowledge/manage-knowledge/introduction'
| '/use-dify/knowledge/manage-knowledge/maintain-dataset-via-api'
| '/use-dify/knowledge/manage-knowledge/maintain-knowledge-documents'
| '/use-dify/knowledge/metadata'
| '/use-dify/knowledge/readme'
| '/use-dify/knowledge/test-retrieval'
| '/use-dify/monitor/analysis'
| '/use-dify/monitor/annotation-reply'
| '/use-dify/monitor/integrations/integrate-aliyun'
| '/use-dify/monitor/integrations/integrate-arize'
| '/use-dify/monitor/integrations/integrate-langfuse'
| '/use-dify/monitor/integrations/integrate-langsmith'
| '/use-dify/monitor/integrations/integrate-opik'
| '/use-dify/monitor/integrations/integrate-phoenix'
| '/use-dify/monitor/integrations/integrate-weave'
| '/use-dify/monitor/logs'
| '/use-dify/nodes/agent'
| '/use-dify/nodes/answer'
| '/use-dify/nodes/code'
| '/use-dify/nodes/doc-extractor'
| '/use-dify/nodes/http-request'
| '/use-dify/nodes/ifelse'
| '/use-dify/nodes/iteration'
| '/use-dify/nodes/knowledge-retrieval'
| '/use-dify/nodes/list-operator'
| '/use-dify/nodes/llm'
| '/use-dify/nodes/loop'
| '/use-dify/nodes/output'
| '/use-dify/nodes/parameter-extractor'
| '/use-dify/nodes/question-classifier'
| '/use-dify/nodes/template'
| '/use-dify/nodes/tools'
| '/use-dify/nodes/trigger/overview'
| '/use-dify/nodes/trigger/plugin-trigger'
| '/use-dify/nodes/trigger/schedule-trigger'
| '/use-dify/nodes/trigger/webhook-trigger'
| '/use-dify/nodes/user-input'
| '/use-dify/nodes/variable-aggregator'
| '/use-dify/nodes/variable-assigner'
| '/use-dify/publish/README'
| '/use-dify/publish/developing-with-apis'
| '/use-dify/publish/publish-mcp'
| '/use-dify/publish/webapp/chatflow-webapp'
| '/use-dify/publish/webapp/embedding-in-websites'
| '/use-dify/publish/webapp/web-app-access'
| '/use-dify/publish/webapp/web-app-settings'
| '/use-dify/publish/webapp/workflow-webapp'
| '/use-dify/tutorials/article-reader'
| '/use-dify/tutorials/build-ai-image-generation-app'
| '/use-dify/tutorials/customer-service-bot'
| '/use-dify/tutorials/simple-chatbot'
| '/use-dify/tutorials/twitter-chatflow'
| '/use-dify/workspace/app-management'
| '/use-dify/workspace/model-providers'
| '/use-dify/workspace/personal-account-management'
| '/use-dify/workspace/plugins'
| '/use-dify/workspace/readme'
| '/use-dify/workspace/subscription-management'
| '/use-dify/workspace/team-members-management'
// SelfHost paths
export type SelfHostPath =
| '/self-host/advanced-deployments/local-source-code'
| '/self-host/advanced-deployments/start-the-frontend-docker-container'
| '/self-host/configuration/environments'
| '/self-host/platform-guides/bt-panel'
| '/self-host/platform-guides/dify-premium'
| '/self-host/quick-start/docker-compose'
| '/self-host/quick-start/faqs'
| '/self-host/troubleshooting/common-issues'
| '/self-host/troubleshooting/docker-issues'
| '/self-host/troubleshooting/integrations'
| '/self-host/troubleshooting/storage-and-migration'
| '/self-host/troubleshooting/weaviate-v4-migration'
// DevelopPlugin paths
export type DevelopPluginPath =
| '/develop-plugin/dev-guides-and-walkthroughs/agent-strategy-plugin'
| '/develop-plugin/dev-guides-and-walkthroughs/cheatsheet'
| '/develop-plugin/dev-guides-and-walkthroughs/creating-new-model-provider'
| '/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin'
| '/develop-plugin/dev-guides-and-walkthroughs/develop-a-slack-bot-plugin'
| '/develop-plugin/dev-guides-and-walkthroughs/develop-flomo-plugin'
| '/develop-plugin/dev-guides-and-walkthroughs/develop-md-exporter'
| '/develop-plugin/dev-guides-and-walkthroughs/develop-multimodal-data-processing-tool'
| '/develop-plugin/dev-guides-and-walkthroughs/endpoint'
| '/develop-plugin/dev-guides-and-walkthroughs/tool-oauth'
| '/develop-plugin/dev-guides-and-walkthroughs/tool-plugin'
| '/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin'
| '/develop-plugin/features-and-specs/advanced-development/bundle'
| '/develop-plugin/features-and-specs/advanced-development/customizable-model'
| '/develop-plugin/features-and-specs/advanced-development/reverse-invocation'
| '/develop-plugin/features-and-specs/advanced-development/reverse-invocation-app'
| '/develop-plugin/features-and-specs/advanced-development/reverse-invocation-model'
| '/develop-plugin/features-and-specs/advanced-development/reverse-invocation-node'
| '/develop-plugin/features-and-specs/advanced-development/reverse-invocation-tool'
| '/develop-plugin/features-and-specs/plugin-types/general-specifications'
| '/develop-plugin/features-and-specs/plugin-types/model-designing-rules'
| '/develop-plugin/features-and-specs/plugin-types/model-schema'
| '/develop-plugin/features-and-specs/plugin-types/multilingual-readme'
| '/develop-plugin/features-and-specs/plugin-types/persistent-storage-kv'
| '/develop-plugin/features-and-specs/plugin-types/plugin-info-by-manifest'
| '/develop-plugin/features-and-specs/plugin-types/plugin-logging'
| '/develop-plugin/features-and-specs/plugin-types/remote-debug-a-plugin'
| '/develop-plugin/features-and-specs/plugin-types/tool'
| '/develop-plugin/getting-started/cli'
| '/develop-plugin/getting-started/getting-started-dify-plugin'
| '/develop-plugin/publishing/faq/faq'
| '/develop-plugin/publishing/marketplace-listing/plugin-auto-publish-pr'
| '/develop-plugin/publishing/marketplace-listing/release-by-file'
| '/develop-plugin/publishing/marketplace-listing/release-overview'
| '/develop-plugin/publishing/marketplace-listing/release-to-dify-marketplace'
| '/develop-plugin/publishing/marketplace-listing/release-to-individual-github-repo'
| '/develop-plugin/publishing/standards/contributor-covenant-code-of-conduct'
| '/develop-plugin/publishing/standards/privacy-protection-guidelines'
| '/develop-plugin/publishing/standards/third-party-signature-verification'
// API Reference paths (English, use apiReferencePathTranslations for other languages)
export type ApiReferencePath =
| '/api-reference/annotations/create-annotation'
| '/api-reference/annotations/delete-annotation'
| '/api-reference/annotations/get-annotation-list'
| '/api-reference/annotations/initial-annotation-reply-settings'
| '/api-reference/annotations/query-initial-annotation-reply-settings-task-status'
| '/api-reference/annotations/update-annotation'
| '/api-reference/application/get-application-basic-information'
| '/api-reference/application/get-application-meta-information'
| '/api-reference/application/get-application-parameters-information'
| '/api-reference/application/get-application-webapp-settings'
| '/api-reference/chat/next-suggested-questions'
| '/api-reference/chat/send-chat-message'
| '/api-reference/chat/stop-chat-message-generation'
| '/api-reference/chatflow/next-suggested-questions'
| '/api-reference/chatflow/send-chat-message'
| '/api-reference/chatflow/stop-advanced-chat-message-generation'
| '/api-reference/chunks/add-chunks-to-a-document'
| '/api-reference/chunks/create-child-chunk'
| '/api-reference/chunks/delete-a-chunk-in-a-document'
| '/api-reference/chunks/delete-child-chunk'
| '/api-reference/chunks/get-a-chunk-details-in-a-document'
| '/api-reference/chunks/get-child-chunks'
| '/api-reference/chunks/get-chunks-from-a-document'
| '/api-reference/chunks/update-a-chunk-in-a-document'
| '/api-reference/chunks/update-child-chunk'
| '/api-reference/completion/create-completion-message'
| '/api-reference/completion/stop-generate'
| '/api-reference/conversations/conversation-rename'
| '/api-reference/conversations/delete-conversation'
| '/api-reference/conversations/get-conversation-history-messages'
| '/api-reference/conversations/get-conversation-variables'
| '/api-reference/conversations/get-conversations'
| '/api-reference/datasets/create-an-empty-knowledge-base'
| '/api-reference/datasets/delete-a-knowledge-base'
| '/api-reference/datasets/get-knowledge-base-details'
| '/api-reference/datasets/get-knowledge-base-list'
| '/api-reference/datasets/retrieve-chunks-from-a-knowledge-base-/-test-retrieval'
| '/api-reference/datasets/update-knowledge-base'
| '/api-reference/documents/create-a-document-from-a-file'
| '/api-reference/documents/create-a-document-from-text'
| '/api-reference/documents/delete-a-document'
| '/api-reference/documents/get-document-detail'
| '/api-reference/documents/get-document-embedding-status-(progress)'
| '/api-reference/documents/get-the-document-list-of-a-knowledge-base'
| '/api-reference/documents/update-a-document-with-a-file'
| '/api-reference/documents/update-a-document-with-text'
| '/api-reference/documents/update-document-status'
| '/api-reference/feedback/get-feedbacks-of-application'
| '/api-reference/feedback/message-feedback'
| '/api-reference/files/file-preview'
| '/api-reference/files/file-upload'
| '/api-reference/files/file-upload-for-workflow'
| '/api-reference/metadata-&-tags/bind-dataset-to-knowledge-base-type-tag'
| '/api-reference/metadata-&-tags/create-new-knowledge-base-type-tag'
| '/api-reference/metadata-&-tags/delete-knowledge-base-type-tag'
| '/api-reference/metadata-&-tags/get-knowledge-base-type-tags'
| '/api-reference/metadata-&-tags/modify-knowledge-base-type-tag-name'
| '/api-reference/metadata-&-tags/query-tags-bound-to-a-dataset'
| '/api-reference/metadata-&-tags/unbind-dataset-and-knowledge-base-type-tag'
| '/api-reference/models/get-available-embedding-models'
| '/api-reference/tts/speech-to-text'
| '/api-reference/tts/text-to-audio'
| '/api-reference/workflow-execution/execute-workflow'
| '/api-reference/workflow-execution/get-workflow-logs'
| '/api-reference/workflow-execution/get-workflow-run-detail'
| '/api-reference/workflow-execution/stop-workflow-task-generation'
// Base path without language prefix
export type DocPathWithoutLangBase =
| UseDifyPath
| SelfHostPath
| DevelopPluginPath
| ApiReferencePath
// Combined path without language prefix (supports optional #anchor)
export type DocPathWithoutLang =
| DocPathWithoutLangBase
| `${DocPathWithoutLangBase}#${string}`
// Full documentation path with language prefix
export type DifyDocPath = `${DocLanguage}/${DocPathWithoutLang}`
// API Reference path translations (English -> other languages)
export const apiReferencePathTranslations: Record<string, { zh?: string; ja?: string }> = {
'/api-reference/annotations/create-annotation': { zh: '/api-reference/标注管理/创建标注' },
'/api-reference/annotations/delete-annotation': { zh: '/api-reference/标注管理/删除标注' },
'/api-reference/annotations/get-annotation-list': { zh: '/api-reference/标注管理/获取标注列表' },
'/api-reference/annotations/initial-annotation-reply-settings': { zh: '/api-reference/标注管理/标注回复初始设置' },
'/api-reference/annotations/query-initial-annotation-reply-settings-task-status': { zh: '/api-reference/标注管理/查询标注回复初始设置任务状态' },
'/api-reference/annotations/update-annotation': { zh: '/api-reference/标注管理/更新标注' },
'/api-reference/application/get-application-basic-information': { zh: '/api-reference/应用设置/获取应用基本信息', ja: '/api-reference/アプリケーション情報/アプリケーションの基本情報を取得' },
'/api-reference/application/get-application-meta-information': { zh: '/api-reference/应用配置/获取应用meta信息', ja: '/api-reference/アプリケーション設定/アプリケーションのメタ情報を取得' },
'/api-reference/application/get-application-parameters-information': { zh: '/api-reference/应用设置/获取应用参数', ja: '/api-reference/アプリケーション情報/アプリケーションのパラメータ情報を取得' },
'/api-reference/application/get-application-webapp-settings': { zh: '/api-reference/应用设置/获取应用-webapp-设置', ja: '/api-reference/アプリケーション情報/アプリのwebapp設定を取得' },
'/api-reference/chat/next-suggested-questions': { zh: '/api-reference/对话消息/获取下一轮建议问题列表', ja: '/api-reference/チャットメッセージ/次の推奨質問' },
'/api-reference/chat/send-chat-message': { zh: '/api-reference/对话消息/发送对话消息', ja: '/api-reference/チャットメッセージ/チャットメッセージを送信' },
'/api-reference/chat/stop-chat-message-generation': { zh: '/api-reference/对话消息/停止响应', ja: '/api-reference/チャットメッセージ/生成停止' },
'/api-reference/chatflow/next-suggested-questions': { zh: '/api-reference/对话消息/获取下一轮建议问题列表', ja: '/api-reference/チャットメッセージ/次の推奨質問' },
'/api-reference/chatflow/send-chat-message': { zh: '/api-reference/对话消息/发送对话消息', ja: '/api-reference/チャットメッセージ/チャットメッセージを送信' },
'/api-reference/chatflow/stop-advanced-chat-message-generation': { zh: '/api-reference/对话消息/停止响应', ja: '/api-reference/チャットメッセージ/生成を停止' },
'/api-reference/chunks/add-chunks-to-a-document': { zh: '/api-reference/文档块/向文档添加块', ja: '/api-reference/チャンク/ドキュメントにチャンクを追加' },
'/api-reference/chunks/create-child-chunk': { zh: '/api-reference/文档块/创建子块', ja: '/api-reference/チャンク/子チャンクを作成' },
'/api-reference/chunks/delete-a-chunk-in-a-document': { zh: '/api-reference/文档块/删除文档中的块', ja: '/api-reference/チャンク/ドキュメント内のチャンクを削除' },
'/api-reference/chunks/delete-child-chunk': { zh: '/api-reference/文档块/删除子块', ja: '/api-reference/チャンク/子チャンクを削除' },
'/api-reference/chunks/get-a-chunk-details-in-a-document': { zh: '/api-reference/文档块/获取文档中的块详情', ja: '/api-reference/チャンク/ドキュメント内のチャンク詳細を取得' },
'/api-reference/chunks/get-child-chunks': { zh: '/api-reference/文档块/获取子块', ja: '/api-reference/チャンク/子チャンクを取得' },
'/api-reference/chunks/get-chunks-from-a-document': { zh: '/api-reference/文档块/从文档获取块', ja: '/api-reference/チャンク/ドキュメントからチャンクを取得' },
'/api-reference/chunks/update-a-chunk-in-a-document': { zh: '/api-reference/文档块/更新文档中的块', ja: '/api-reference/チャンク/ドキュメント内のチャンクを更新' },
'/api-reference/chunks/update-child-chunk': { zh: '/api-reference/文档块/更新子块', ja: '/api-reference/チャンク/子チャンクを更新' },
'/api-reference/completion/create-completion-message': { zh: '/api-reference/文本生成/发送消息', ja: '/api-reference/完了メッセージ/完了メッセージの作成' },
'/api-reference/completion/stop-generate': { zh: '/api-reference/文本生成/停止响应', ja: '/api-reference/完了メッセージ/生成の停止' },
'/api-reference/conversations/conversation-rename': { zh: '/api-reference/会话管理/会话重命名', ja: '/api-reference/会話管理/会話の名前を変更' },
'/api-reference/conversations/delete-conversation': { zh: '/api-reference/会话管理/删除会话', ja: '/api-reference/会話管理/会話を削除' },
'/api-reference/conversations/get-conversation-history-messages': { zh: '/api-reference/会话管理/获取会话历史消息', ja: '/api-reference/会話管理/会話履歴メッセージを取得' },
'/api-reference/conversations/get-conversation-variables': { zh: '/api-reference/会话管理/获取对话变量', ja: '/api-reference/会話管理/会話変数の取得' },
'/api-reference/conversations/get-conversations': { zh: '/api-reference/会话管理/获取会话列表', ja: '/api-reference/会話管理/会話を取得' },
'/api-reference/datasets/create-an-empty-knowledge-base': { zh: '/api-reference/数据集/创建空知识库', ja: '/api-reference/データセット/空のナレッジベースを作成' },
'/api-reference/datasets/delete-a-knowledge-base': { zh: '/api-reference/数据集/删除知识库', ja: '/api-reference/データセット/ナレッジベースを削除' },
'/api-reference/datasets/get-knowledge-base-details': { zh: '/api-reference/数据集/获取知识库详情', ja: '/api-reference/データセット/ナレッジベース詳細を取得' },
'/api-reference/datasets/get-knowledge-base-list': { zh: '/api-reference/数据集/获取知识库列表', ja: '/api-reference/データセット/ナレッジベースリストを取得' },
'/api-reference/datasets/retrieve-chunks-from-a-knowledge-base-/-test-retrieval': { zh: '/api-reference/数据集/从知识库检索块-/-测试检索', ja: '/api-reference/データセット/ナレッジベースからチャンクを取得-/-テスト検索' },
'/api-reference/datasets/update-knowledge-base': { zh: '/api-reference/数据集/更新知识库', ja: '/api-reference/データセット/ナレッジベースを更新' },
'/api-reference/documents/create-a-document-from-a-file': { zh: '/api-reference/文档/从文件创建文档', ja: '/api-reference/ドキュメント/ファイルからドキュメントを作成' },
'/api-reference/documents/create-a-document-from-text': { zh: '/api-reference/文档/从文本创建文档', ja: '/api-reference/ドキュメント/テキストからドキュメントを作成' },
'/api-reference/documents/delete-a-document': { zh: '/api-reference/文档/删除文档', ja: '/api-reference/ドキュメント/ドキュメントを削除' },
'/api-reference/documents/get-document-detail': { zh: '/api-reference/文档/获取文档详情', ja: '/api-reference/ドキュメント/ドキュメント詳細を取得' },
'/api-reference/documents/get-document-embedding-status-(progress)': { zh: '/api-reference/文档/获取文档嵌入状态(进度)', ja: '/api-reference/ドキュメント/ドキュメント埋め込みステータス(進捗)を取得' },
'/api-reference/documents/get-the-document-list-of-a-knowledge-base': { zh: '/api-reference/文档/获取知识库的文档列表', ja: '/api-reference/ドキュメント/ナレッジベースのドキュメントリストを取得' },
'/api-reference/documents/update-a-document-with-a-file': { zh: '/api-reference/文档/用文件更新文档', ja: '/api-reference/ドキュメント/ファイルでドキュメントを更新' },
'/api-reference/documents/update-a-document-with-text': { zh: '/api-reference/文档/用文本更新文档', ja: '/api-reference/ドキュメント/テキストでドキュメントを更新' },
'/api-reference/documents/update-document-status': { zh: '/api-reference/文档/更新文档状态', ja: '/api-reference/ドキュメント/ドキュメントステータスを更新' },
'/api-reference/feedback/get-feedbacks-of-application': { zh: '/api-reference/反馈/获取应用反馈列表', ja: '/api-reference/メッセージフィードバック/アプリのメッセージの「いいね」とフィードバックを取得' },
'/api-reference/feedback/message-feedback': { zh: '/api-reference/反馈/消息反馈(点赞)', ja: '/api-reference/メッセージフィードバック/メッセージフィードバック' },
'/api-reference/files/file-preview': { zh: '/api-reference/文件操作/文件预览', ja: '/api-reference/ファイル操作/ファイルプレビュー' },
'/api-reference/files/file-upload': { zh: '/api-reference/文件管理/上传文件', ja: '/api-reference/ファイル操作/ファイルアップロード' },
'/api-reference/files/file-upload-for-workflow': { zh: '/api-reference/文件操作-(workflow)/上传文件-(workflow)', ja: '/api-reference/ファイル操作-(ワークフロー)/ファイルアップロード-(ワークフロー用)' },
'/api-reference/metadata-&-tags/bind-dataset-to-knowledge-base-type-tag': { zh: '/api-reference/元数据和标签/将数据集绑定到知识库类型标签', ja: '/api-reference/メタデータ・タグ/データセットをナレッジベースタイプタグにバインド' },
'/api-reference/metadata-&-tags/create-new-knowledge-base-type-tag': { zh: '/api-reference/元数据和标签/创建新的知识库类型标签', ja: '/api-reference/メタデータ・タグ/新しいナレッジベースタイプタグを作成' },
'/api-reference/metadata-&-tags/delete-knowledge-base-type-tag': { zh: '/api-reference/元数据和标签/删除知识库类型标签', ja: '/api-reference/メタデータ・タグ/ナレッジベースタイプタグを削除' },
'/api-reference/metadata-&-tags/get-knowledge-base-type-tags': { zh: '/api-reference/元数据和标签/获取知识库类型标签', ja: '/api-reference/メタデータ・タグ/ナレッジベースタイプタグを取得' },
'/api-reference/metadata-&-tags/modify-knowledge-base-type-tag-name': { zh: '/api-reference/元数据和标签/修改知识库类型标签名称', ja: '/api-reference/メタデータ・タグ/ナレッジベースタイプタグ名を変更' },
'/api-reference/metadata-&-tags/query-tags-bound-to-a-dataset': { zh: '/api-reference/元数据和标签/查询绑定到数据集的标签', ja: '/api-reference/メタデータ・タグ/データセットにバインドされたタグをクエリ' },
'/api-reference/metadata-&-tags/unbind-dataset-and-knowledge-base-type-tag': { zh: '/api-reference/元数据和标签/解绑数据集和知识库类型标签', ja: '/api-reference/メタデータ・タグ/データセットとナレッジベースタイプタグのバインドを解除' },
'/api-reference/models/get-available-embedding-models': { zh: '/api-reference/模型/获取可用的嵌入模型', ja: '/api-reference/モデル/利用可能な埋め込みモデルを取得' },
'/api-reference/tts/speech-to-text': { zh: '/api-reference/语音与文字转换/语音转文字', ja: '/api-reference/音声・テキスト変換/音声からテキストへ' },
'/api-reference/tts/text-to-audio': { zh: '/api-reference/语音服务/文字转语音', ja: '/api-reference/音声変換/テキストから音声' },
'/api-reference/workflow-execution/execute-workflow': { zh: '/api-reference/工作流执行/执行-workflow', ja: '/api-reference/ワークフロー実行/ワークフローを実行' },
'/api-reference/workflow-execution/get-workflow-logs': { zh: '/api-reference/工作流执行/获取-workflow-日志', ja: '/api-reference/ワークフロー実行/ワークフローログを取得' },
'/api-reference/workflow-execution/get-workflow-run-detail': { zh: '/api-reference/工作流执行/获取workflow执行情况', ja: '/api-reference/ワークフロー実行/ワークフロー実行詳細を取得' },
'/api-reference/workflow-execution/stop-workflow-task-generation': { zh: '/api-reference/工作流执行/停止响应-(workflow-task)', ja: '/api-reference/ワークフロー実行/生成を停止-(ワークフロータスク)' },
}