Detect docs product prefixes from generated paths

This commit is contained in:
Stephen Zhou
2026-06-17 12:27:42 +08:00
parent b868c7bbc0
commit bedbbda43e
4 changed files with 450 additions and 22 deletions

View File

@ -154,7 +154,7 @@ describe('useDocLink', () => {
})
describe('Product prefix handling', () => {
it('should add cloud product prefix for use-dify paths in cloud edition', () => {
it('should add cloud product prefix for product docs available in both editions', () => {
mockConfig.IS_CLOUD_EDITION = true
const { result } = renderHook(() => useDocLink())
@ -162,7 +162,7 @@ describe('useDocLink', () => {
expect(url).toBe(`${defaultDocBaseUrl}/en/cloud/use-dify/build/mcp`)
})
it('should add self-host product prefix for use-dify paths outside cloud edition', () => {
it('should add self-host product prefix for product docs available in both editions outside cloud edition', () => {
mockConfig.IS_CLOUD_EDITION = false
const { result } = renderHook(() => useDocLink())
@ -170,6 +170,30 @@ describe('useDocLink', () => {
expect(url).toBe(`${defaultDocBaseUrl}/en/self-host/use-dify/build/mcp`)
})
it('should use the existing cloud docs path for cloud-only product docs outside cloud edition', () => {
mockConfig.IS_CLOUD_EDITION = false
const { result } = renderHook(() => useDocLink())
const url = result.current('/use-dify/workspace/subscription-management#dify-for-education')
expect(url).toBe(`${defaultDocBaseUrl}/en/cloud/use-dify/workspace/subscription-management#dify-for-education`)
})
it('should use the existing self-host docs path for self-host-only product docs in cloud edition', () => {
mockConfig.IS_CLOUD_EDITION = true
const { result } = renderHook(() => useDocLink())
const url = result.current('/deploy/overview')
expect(url).toBe(`${defaultDocBaseUrl}/en/self-host/deploy/overview`)
})
it('should not add a product prefix for unknown productless paths', () => {
mockConfig.IS_CLOUD_EDITION = false
const { result } = renderHook(() => useDocLink())
const url = result.current('/use-dify/unknown-page' as DocPathWithoutLang)
expect(url).toBe(`${defaultDocBaseUrl}/en/use-dify/unknown-page`)
})
it('should open shared docs home when no path is provided outside cloud edition', () => {
mockConfig.IS_CLOUD_EDITION = false

View File

@ -1,10 +1,10 @@
import type { Locale } from '@/i18n-config/language'
import type { DocPathWithoutLang } from '@/types/doc-paths'
import type { DocPathWithoutLang, DocsProduct } from '@/types/doc-paths'
import { useCallback } from 'react'
import { useTranslation } from '#i18n'
import { IS_CLOUD_EDITION } from '@/config'
import { getDocLanguage, getLanguage, getPricingPageLanguage } from '@/i18n-config/language'
import { apiReferencePathTranslations } from '@/types/doc-paths'
import { apiReferencePathTranslations, docPathProductAvailability } from '@/types/doc-paths'
export const useLocale = () => {
const { i18n } = useTranslation()
@ -27,6 +27,42 @@ export type DocPathMap = Partial<Record<Locale, DocPathWithoutLang>>
export const getDocHomePath = () => '/home'
const getCurrentDocsProduct = (): DocsProduct => {
return IS_CLOUD_EDITION ? 'cloud' : 'self-host'
}
const splitPathHash = (path: string) => {
const hashIndex = path.indexOf('#')
if (hashIndex === -1) {
return {
pathname: path,
hash: '',
}
}
return {
pathname: path.slice(0, hashIndex),
hash: path.slice(hashIndex),
}
}
const getProductAwarePath = (path: string): string => {
const { pathname, hash } = splitPathHash(path)
const availableProducts = docPathProductAvailability[pathname]
if (!availableProducts?.length)
return path
const currentProduct = getCurrentDocsProduct()
const targetProduct = availableProducts.includes(currentProduct)
? currentProduct
: availableProducts[0]
if (!targetProduct)
return path
return `/${targetProduct}${pathname}${hash}`
}
export const useDocLink = (baseUrl?: string): ((path?: DocPathWithoutLang, pathMap?: DocPathMap) => string) => {
let baseDocUrl = baseUrl || defaultDocBaseUrl
baseDocUrl = (baseDocUrl.endsWith('/')) ? baseDocUrl.slice(0, -1) : baseDocUrl
@ -47,13 +83,12 @@ export const useDocLink = (baseUrl?: string): ((path?: DocPathWithoutLang, pathM
}
}
}
else if (targetPath === '/use-dify' || targetPath.startsWith('/use-dify/')) {
const productPrefix = IS_CLOUD_EDITION ? '/cloud' : '/self-host'
targetPath = `${productPrefix}${targetPath}`
}
else if (!targetPath) {
targetPath = getDocHomePath()
}
else {
targetPath = getProductAwarePath(targetPath)
}
return `${baseDocUrl}${languagePrefix}${targetPath}`
},

View File

@ -63,6 +63,14 @@ type DocsJson = {
}
const OPENAPI_BASE_URL = (process.env.DOCS_OPENAPI_BASE_URL || new URL('.', DOCS_JSON_URL).toString()).replace(/\/?$/, '/')
const DOCS_PRODUCTS = ['cloud', 'self-host'] as const
type DocsProduct = typeof DOCS_PRODUCTS[number]
type ProductAvailability = Record<string, Set<DocsProduct>>
function isDocsProduct(segment: string): segment is DocsProduct {
return DOCS_PRODUCTS.includes(segment as DocsProduct)
}
/**
* Convert summary to URL slug
@ -229,15 +237,41 @@ function extractPaths(item: NavItem | undefined, paths: Set<string> = new Set())
return paths
}
function addPathToGroup(groups: Record<string, Set<string>>, pathWithoutLang: string): void {
const parts = pathWithoutLang.split('/')
const section = parts[0]
if (!section)
return
if (!groups[section])
groups[section] = new Set()
groups[section]!.add(pathWithoutLang)
}
function getProductPathInfo(pathWithoutLang: string): { product: DocsProduct, pathWithoutProduct: string } | undefined {
const parts = pathWithoutLang.split('/')
const [product, ...rest] = parts
if (!product || !isDocsProduct(product) || rest.length === 0)
return undefined
return {
product,
pathWithoutProduct: rest.join('/'),
}
}
/**
* Group paths by their prefix structure
*/
function groupPathsBySection(paths: Set<string>): Record<string, Set<string>> {
function groupPathsBySection(paths: Set<string>): { groups: Record<string, Set<string>>, productAvailability: ProductAvailability } {
const groups: Record<string, Set<string>> = {}
const productAvailability: ProductAvailability = {}
for (const fullPath of paths) {
// Remove language prefix (en/, zh/, ja/)
let withoutLang = fullPath.replace(/^(en|zh|ja)\//, '')
const withoutLang = fullPath.replace(/^(en|zh|ja)\//, '')
if (!withoutLang || withoutLang === fullPath)
continue
@ -245,20 +279,26 @@ function groupPathsBySection(paths: Set<string>): Record<string, Set<string>> {
if (withoutLang.endsWith('.json') || withoutLang === 'None')
continue
// Product-specific use-dify docs are selected by useDocLink at runtime.
withoutLang = withoutLang.replace(/^(cloud|self-host)\/(?=use-dify(?:\/|$))/, '')
addPathToGroup(groups, withoutLang)
// Get section (first part of path)
const parts = withoutLang.split('/')
const section = parts[0]
const productPathInfo = getProductPathInfo(withoutLang)
if (productPathInfo) {
const productlessPath = productPathInfo.pathWithoutProduct
const normalizedPath = `/${productlessPath}`
if (!groups[section!])
groups[section!] = new Set()
addPathToGroup(groups, productlessPath)
groups[section!]!.add(withoutLang)
if (!productAvailability[normalizedPath])
productAvailability[normalizedPath] = new Set()
productAvailability[normalizedPath]!.add(productPathInfo.product)
}
}
return groups
return {
groups,
productAvailability,
}
}
/**
@ -276,6 +316,7 @@ function sectionToTypeName(section: string): string {
*/
function generateTypeDefinitions(
groups: Record<string, Set<string>>,
productAvailability: ProductAvailability,
apiReferencePaths: string[],
apiPathTranslations: Record<string, { zh?: string, ja?: string }>,
): string {
@ -288,6 +329,7 @@ function generateTypeDefinitions(
'',
'// Language prefixes',
'export type DocLanguage = \'en\' | \'zh\' | \'ja\'',
'export type DocsProduct = \'cloud\' | \'self-host\'',
'',
]
@ -352,6 +394,16 @@ function generateTypeDefinitions(
lines.push('export type DifyDocPath = `${DocLanguage}/${DocPathWithoutLang}`')
lines.push('')
// Generate product availability map for productless runtime links.
lines.push('// Product availability for productless docs paths')
lines.push('export const docPathProductAvailability: Record<string, readonly DocsProduct[]> = {')
for (const path of Object.keys(productAvailability).sort()) {
const products = [...productAvailability[path]!].sort((a, b) => DOCS_PRODUCTS.indexOf(a) - DOCS_PRODUCTS.indexOf(b))
lines.push(` '${path}': [${products.map(product => `'${product}'`).join(', ')}],`)
}
lines.push('}')
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 }> = {')
@ -448,12 +500,13 @@ async function main(): Promise<void> {
console.log(`Generated ${Object.keys(apiPathTranslations).length} API path translations`)
// Group by section
const groups = groupPathsBySection(allPaths)
const { groups, productAvailability } = groupPathsBySection(allPaths)
console.log(`Grouped into ${Object.keys(groups).length} sections:`, Object.keys(groups))
console.log(`Found ${Object.keys(productAvailability).length} product-aware paths`)
// Generate TypeScript
const tsContent = generateTypeDefinitions(groups, uniqueEnApiPaths, apiPathTranslations)
const tsContent = generateTypeDefinitions(groups, productAvailability, uniqueEnApiPaths, apiPathTranslations)
// Write to file
await writeFile(OUTPUT_PATH, tsContent, 'utf-8')

View File

@ -2,10 +2,107 @@
// DON NOT EDIT IT MANUALLY
//
// Generated from: https://raw.githubusercontent.com/langgenius/dify-docs/feat/audience-products/docs.json
// Generated at: 2026-06-17T03:36:53.584Z
// Generated at: 2026-06-17T04:25:20.766Z
// Language prefixes
export type DocLanguage = 'en' | 'zh' | 'ja'
export type DocsProduct = 'cloud' | 'self-host'
// Cloud paths
type CloudPath =
| '/cloud/use-dify/build/additional-features'
| '/cloud/use-dify/build/agent'
| '/cloud/use-dify/build/chatbot'
| '/cloud/use-dify/build/mcp'
| '/cloud/use-dify/build/orchestrate-node'
| '/cloud/use-dify/build/predefined-error-handling-logic'
| '/cloud/use-dify/build/shortcut-key'
| '/cloud/use-dify/build/text-generator'
| '/cloud/use-dify/build/version-control'
| '/cloud/use-dify/build/workflow-chatflow'
| '/cloud/use-dify/build/workflow-collaboration'
| '/cloud/use-dify/debug/error-type'
| '/cloud/use-dify/debug/history-and-logs'
| '/cloud/use-dify/debug/step-run'
| '/cloud/use-dify/debug/variable-inspect'
| '/cloud/use-dify/getting-started/introduction'
| '/cloud/use-dify/knowledge/connect-external-knowledge-base'
| '/cloud/use-dify/knowledge/create-knowledge/chunking-and-cleaning-text'
| '/cloud/use-dify/knowledge/create-knowledge/import-text-data/readme'
| '/cloud/use-dify/knowledge/create-knowledge/import-text-data/sync-from-notion'
| '/cloud/use-dify/knowledge/create-knowledge/import-text-data/sync-from-website'
| '/cloud/use-dify/knowledge/create-knowledge/introduction'
| '/cloud/use-dify/knowledge/create-knowledge/setting-indexing-methods'
| '/cloud/use-dify/knowledge/external-knowledge-api'
| '/cloud/use-dify/knowledge/integrate-knowledge-within-application'
| '/cloud/use-dify/knowledge/knowledge-pipeline/authorize-data-source'
| '/cloud/use-dify/knowledge/knowledge-pipeline/create-knowledge-pipeline'
| '/cloud/use-dify/knowledge/knowledge-pipeline/knowledge-pipeline-orchestration'
| '/cloud/use-dify/knowledge/knowledge-pipeline/manage-knowledge-base'
| '/cloud/use-dify/knowledge/knowledge-pipeline/publish-knowledge-pipeline'
| '/cloud/use-dify/knowledge/knowledge-pipeline/readme'
| '/cloud/use-dify/knowledge/knowledge-pipeline/upload-files'
| '/cloud/use-dify/knowledge/knowledge-request-rate-limit'
| '/cloud/use-dify/knowledge/manage-knowledge/introduction'
| '/cloud/use-dify/knowledge/manage-knowledge/maintain-dataset-via-api'
| '/cloud/use-dify/knowledge/manage-knowledge/maintain-knowledge-documents'
| '/cloud/use-dify/knowledge/metadata'
| '/cloud/use-dify/knowledge/readme'
| '/cloud/use-dify/knowledge/test-retrieval'
| '/cloud/use-dify/monitor/analysis'
| '/cloud/use-dify/monitor/annotation-reply'
| '/cloud/use-dify/monitor/integrations/integrate-aliyun'
| '/cloud/use-dify/monitor/integrations/integrate-arize'
| '/cloud/use-dify/monitor/integrations/integrate-langfuse'
| '/cloud/use-dify/monitor/integrations/integrate-langsmith'
| '/cloud/use-dify/monitor/integrations/integrate-opik'
| '/cloud/use-dify/monitor/integrations/integrate-phoenix'
| '/cloud/use-dify/monitor/integrations/integrate-weave'
| '/cloud/use-dify/monitor/logs'
| '/cloud/use-dify/nodes/agent'
| '/cloud/use-dify/nodes/answer'
| '/cloud/use-dify/nodes/code'
| '/cloud/use-dify/nodes/doc-extractor'
| '/cloud/use-dify/nodes/http-request'
| '/cloud/use-dify/nodes/human-input'
| '/cloud/use-dify/nodes/ifelse'
| '/cloud/use-dify/nodes/iteration'
| '/cloud/use-dify/nodes/knowledge-retrieval'
| '/cloud/use-dify/nodes/list-operator'
| '/cloud/use-dify/nodes/llm'
| '/cloud/use-dify/nodes/loop'
| '/cloud/use-dify/nodes/output'
| '/cloud/use-dify/nodes/parameter-extractor'
| '/cloud/use-dify/nodes/question-classifier'
| '/cloud/use-dify/nodes/template'
| '/cloud/use-dify/nodes/tools'
| '/cloud/use-dify/nodes/trigger/overview'
| '/cloud/use-dify/nodes/trigger/plugin-trigger'
| '/cloud/use-dify/nodes/trigger/schedule-trigger'
| '/cloud/use-dify/nodes/trigger/webhook-trigger'
| '/cloud/use-dify/nodes/user-input'
| '/cloud/use-dify/nodes/variable-aggregator'
| '/cloud/use-dify/nodes/variable-assigner'
| '/cloud/use-dify/publish/README'
| '/cloud/use-dify/publish/developing-with-apis'
| '/cloud/use-dify/publish/publish-mcp'
| '/cloud/use-dify/publish/publish-to-marketplace'
| '/cloud/use-dify/publish/webapp/chatflow-webapp'
| '/cloud/use-dify/publish/webapp/embedding-in-websites'
| '/cloud/use-dify/publish/webapp/web-app-settings'
| '/cloud/use-dify/publish/webapp/workflow-webapp'
| '/cloud/use-dify/workspace/api-extension/api-extension'
| '/cloud/use-dify/workspace/api-extension/cloudflare-worker'
| '/cloud/use-dify/workspace/api-extension/external-data-tool-api-extension'
| '/cloud/use-dify/workspace/api-extension/moderation-api-extension'
| '/cloud/use-dify/workspace/app-management'
| '/cloud/use-dify/workspace/model-providers'
| '/cloud/use-dify/workspace/personal-account-management'
| '/cloud/use-dify/workspace/plugins'
| '/cloud/use-dify/workspace/readme'
| '/cloud/use-dify/workspace/subscription-management'
| '/cloud/use-dify/workspace/team-members-management'
| '/cloud/use-dify/workspace/tools'
// UseDify paths
type UseDifyPath =
@ -196,6 +293,113 @@ type SelfHostPath =
| '/self-host/deploy/troubleshooting/integrations'
| '/self-host/deploy/troubleshooting/storage-and-migration'
| '/self-host/deploy/troubleshooting/weaviate-v4-migration'
| '/self-host/use-dify/build/additional-features'
| '/self-host/use-dify/build/agent'
| '/self-host/use-dify/build/chatbot'
| '/self-host/use-dify/build/mcp'
| '/self-host/use-dify/build/orchestrate-node'
| '/self-host/use-dify/build/predefined-error-handling-logic'
| '/self-host/use-dify/build/shortcut-key'
| '/self-host/use-dify/build/text-generator'
| '/self-host/use-dify/build/version-control'
| '/self-host/use-dify/build/workflow-chatflow'
| '/self-host/use-dify/build/workflow-collaboration'
| '/self-host/use-dify/debug/error-type'
| '/self-host/use-dify/debug/history-and-logs'
| '/self-host/use-dify/debug/step-run'
| '/self-host/use-dify/debug/variable-inspect'
| '/self-host/use-dify/getting-started/introduction'
| '/self-host/use-dify/knowledge/connect-external-knowledge-base'
| '/self-host/use-dify/knowledge/create-knowledge/chunking-and-cleaning-text'
| '/self-host/use-dify/knowledge/create-knowledge/import-text-data/readme'
| '/self-host/use-dify/knowledge/create-knowledge/import-text-data/sync-from-notion'
| '/self-host/use-dify/knowledge/create-knowledge/import-text-data/sync-from-website'
| '/self-host/use-dify/knowledge/create-knowledge/introduction'
| '/self-host/use-dify/knowledge/create-knowledge/setting-indexing-methods'
| '/self-host/use-dify/knowledge/external-knowledge-api'
| '/self-host/use-dify/knowledge/integrate-knowledge-within-application'
| '/self-host/use-dify/knowledge/knowledge-pipeline/authorize-data-source'
| '/self-host/use-dify/knowledge/knowledge-pipeline/create-knowledge-pipeline'
| '/self-host/use-dify/knowledge/knowledge-pipeline/knowledge-pipeline-orchestration'
| '/self-host/use-dify/knowledge/knowledge-pipeline/manage-knowledge-base'
| '/self-host/use-dify/knowledge/knowledge-pipeline/publish-knowledge-pipeline'
| '/self-host/use-dify/knowledge/knowledge-pipeline/readme'
| '/self-host/use-dify/knowledge/knowledge-pipeline/upload-files'
| '/self-host/use-dify/knowledge/manage-knowledge/introduction'
| '/self-host/use-dify/knowledge/manage-knowledge/maintain-dataset-via-api'
| '/self-host/use-dify/knowledge/manage-knowledge/maintain-knowledge-documents'
| '/self-host/use-dify/knowledge/metadata'
| '/self-host/use-dify/knowledge/readme'
| '/self-host/use-dify/knowledge/test-retrieval'
| '/self-host/use-dify/monitor/analysis'
| '/self-host/use-dify/monitor/annotation-reply'
| '/self-host/use-dify/monitor/integrations/integrate-aliyun'
| '/self-host/use-dify/monitor/integrations/integrate-arize'
| '/self-host/use-dify/monitor/integrations/integrate-langfuse'
| '/self-host/use-dify/monitor/integrations/integrate-langsmith'
| '/self-host/use-dify/monitor/integrations/integrate-opik'
| '/self-host/use-dify/monitor/integrations/integrate-phoenix'
| '/self-host/use-dify/monitor/integrations/integrate-weave'
| '/self-host/use-dify/monitor/logs'
| '/self-host/use-dify/nodes/agent'
| '/self-host/use-dify/nodes/answer'
| '/self-host/use-dify/nodes/code'
| '/self-host/use-dify/nodes/doc-extractor'
| '/self-host/use-dify/nodes/http-request'
| '/self-host/use-dify/nodes/human-input'
| '/self-host/use-dify/nodes/ifelse'
| '/self-host/use-dify/nodes/iteration'
| '/self-host/use-dify/nodes/knowledge-retrieval'
| '/self-host/use-dify/nodes/list-operator'
| '/self-host/use-dify/nodes/llm'
| '/self-host/use-dify/nodes/loop'
| '/self-host/use-dify/nodes/output'
| '/self-host/use-dify/nodes/parameter-extractor'
| '/self-host/use-dify/nodes/question-classifier'
| '/self-host/use-dify/nodes/template'
| '/self-host/use-dify/nodes/tools'
| '/self-host/use-dify/nodes/trigger/overview'
| '/self-host/use-dify/nodes/trigger/plugin-trigger'
| '/self-host/use-dify/nodes/trigger/schedule-trigger'
| '/self-host/use-dify/nodes/trigger/webhook-trigger'
| '/self-host/use-dify/nodes/user-input'
| '/self-host/use-dify/nodes/variable-aggregator'
| '/self-host/use-dify/nodes/variable-assigner'
| '/self-host/use-dify/publish/README'
| '/self-host/use-dify/publish/developing-with-apis'
| '/self-host/use-dify/publish/publish-mcp'
| '/self-host/use-dify/publish/publish-to-marketplace'
| '/self-host/use-dify/publish/webapp/chatflow-webapp'
| '/self-host/use-dify/publish/webapp/embedding-in-websites'
| '/self-host/use-dify/publish/webapp/web-app-settings'
| '/self-host/use-dify/publish/webapp/workflow-webapp'
| '/self-host/use-dify/workspace/api-extension/api-extension'
| '/self-host/use-dify/workspace/api-extension/cloudflare-worker'
| '/self-host/use-dify/workspace/api-extension/external-data-tool-api-extension'
| '/self-host/use-dify/workspace/api-extension/moderation-api-extension'
| '/self-host/use-dify/workspace/app-management'
| '/self-host/use-dify/workspace/model-providers'
| '/self-host/use-dify/workspace/personal-account-management'
| '/self-host/use-dify/workspace/plugins'
| '/self-host/use-dify/workspace/readme'
| '/self-host/use-dify/workspace/team-members-management'
| '/self-host/use-dify/workspace/tools'
// Deploy paths
type DeployPath =
| '/deploy/advanced-deployments/local-source-code'
| '/deploy/advanced-deployments/start-the-frontend-docker-container'
| '/deploy/configuration/environments'
| '/deploy/overview'
| '/deploy/platform-guides/bt-panel'
| '/deploy/platform-guides/dify-premium'
| '/deploy/quick-start/docker-compose'
| '/deploy/quick-start/faqs'
| '/deploy/troubleshooting/common-issues'
| '/deploy/troubleshooting/docker-issues'
| '/deploy/troubleshooting/integrations'
| '/deploy/troubleshooting/storage-and-migration'
| '/deploy/troubleshooting/weaviate-v4-migration'
// API Reference paths (English, use apiReferencePathTranslations for other languages)
type ApiReferencePath =
@ -289,6 +493,7 @@ type ApiReferencePath =
// Base path without language prefix
type DocPathWithoutLangBase =
| CloudPath
| UseDifyPath
| HomePath
| LearnPath
@ -296,6 +501,7 @@ type DocPathWithoutLangBase =
| CliPath
| DevelopPluginPath
| SelfHostPath
| DeployPath
| ApiReferencePath
// Combined path without language prefix (supports optional #anchor)
@ -306,6 +512,116 @@ export type DocPathWithoutLang =
// Full documentation path with language prefix
export type DifyDocPath = `${DocLanguage}/${DocPathWithoutLang}`
// Product availability for productless docs paths
export const docPathProductAvailability: Record<string, readonly DocsProduct[]> = {
'/deploy/advanced-deployments/local-source-code': ['self-host'],
'/deploy/advanced-deployments/start-the-frontend-docker-container': ['self-host'],
'/deploy/configuration/environments': ['self-host'],
'/deploy/overview': ['self-host'],
'/deploy/platform-guides/bt-panel': ['self-host'],
'/deploy/platform-guides/dify-premium': ['self-host'],
'/deploy/quick-start/docker-compose': ['self-host'],
'/deploy/quick-start/faqs': ['self-host'],
'/deploy/troubleshooting/common-issues': ['self-host'],
'/deploy/troubleshooting/docker-issues': ['self-host'],
'/deploy/troubleshooting/integrations': ['self-host'],
'/deploy/troubleshooting/storage-and-migration': ['self-host'],
'/deploy/troubleshooting/weaviate-v4-migration': ['self-host'],
'/use-dify/build/additional-features': ['cloud', 'self-host'],
'/use-dify/build/agent': ['cloud', 'self-host'],
'/use-dify/build/chatbot': ['cloud', 'self-host'],
'/use-dify/build/mcp': ['cloud', 'self-host'],
'/use-dify/build/orchestrate-node': ['cloud', 'self-host'],
'/use-dify/build/predefined-error-handling-logic': ['cloud', 'self-host'],
'/use-dify/build/shortcut-key': ['cloud', 'self-host'],
'/use-dify/build/text-generator': ['cloud', 'self-host'],
'/use-dify/build/version-control': ['cloud', 'self-host'],
'/use-dify/build/workflow-chatflow': ['cloud', 'self-host'],
'/use-dify/build/workflow-collaboration': ['cloud', 'self-host'],
'/use-dify/debug/error-type': ['cloud', 'self-host'],
'/use-dify/debug/history-and-logs': ['cloud', 'self-host'],
'/use-dify/debug/step-run': ['cloud', 'self-host'],
'/use-dify/debug/variable-inspect': ['cloud', 'self-host'],
'/use-dify/getting-started/introduction': ['cloud', 'self-host'],
'/use-dify/knowledge/connect-external-knowledge-base': ['cloud', 'self-host'],
'/use-dify/knowledge/create-knowledge/chunking-and-cleaning-text': ['cloud', 'self-host'],
'/use-dify/knowledge/create-knowledge/import-text-data/readme': ['cloud', 'self-host'],
'/use-dify/knowledge/create-knowledge/import-text-data/sync-from-notion': ['cloud', 'self-host'],
'/use-dify/knowledge/create-knowledge/import-text-data/sync-from-website': ['cloud', 'self-host'],
'/use-dify/knowledge/create-knowledge/introduction': ['cloud', 'self-host'],
'/use-dify/knowledge/create-knowledge/setting-indexing-methods': ['cloud', 'self-host'],
'/use-dify/knowledge/external-knowledge-api': ['cloud', 'self-host'],
'/use-dify/knowledge/integrate-knowledge-within-application': ['cloud', 'self-host'],
'/use-dify/knowledge/knowledge-pipeline/authorize-data-source': ['cloud', 'self-host'],
'/use-dify/knowledge/knowledge-pipeline/create-knowledge-pipeline': ['cloud', 'self-host'],
'/use-dify/knowledge/knowledge-pipeline/knowledge-pipeline-orchestration': ['cloud', 'self-host'],
'/use-dify/knowledge/knowledge-pipeline/manage-knowledge-base': ['cloud', 'self-host'],
'/use-dify/knowledge/knowledge-pipeline/publish-knowledge-pipeline': ['cloud', 'self-host'],
'/use-dify/knowledge/knowledge-pipeline/readme': ['cloud', 'self-host'],
'/use-dify/knowledge/knowledge-pipeline/upload-files': ['cloud', 'self-host'],
'/use-dify/knowledge/knowledge-request-rate-limit': ['cloud'],
'/use-dify/knowledge/manage-knowledge/introduction': ['cloud', 'self-host'],
'/use-dify/knowledge/manage-knowledge/maintain-dataset-via-api': ['cloud', 'self-host'],
'/use-dify/knowledge/manage-knowledge/maintain-knowledge-documents': ['cloud', 'self-host'],
'/use-dify/knowledge/metadata': ['cloud', 'self-host'],
'/use-dify/knowledge/readme': ['cloud', 'self-host'],
'/use-dify/knowledge/test-retrieval': ['cloud', 'self-host'],
'/use-dify/monitor/analysis': ['cloud', 'self-host'],
'/use-dify/monitor/annotation-reply': ['cloud', 'self-host'],
'/use-dify/monitor/integrations/integrate-aliyun': ['cloud', 'self-host'],
'/use-dify/monitor/integrations/integrate-arize': ['cloud', 'self-host'],
'/use-dify/monitor/integrations/integrate-langfuse': ['cloud', 'self-host'],
'/use-dify/monitor/integrations/integrate-langsmith': ['cloud', 'self-host'],
'/use-dify/monitor/integrations/integrate-opik': ['cloud', 'self-host'],
'/use-dify/monitor/integrations/integrate-phoenix': ['cloud', 'self-host'],
'/use-dify/monitor/integrations/integrate-weave': ['cloud', 'self-host'],
'/use-dify/monitor/logs': ['cloud', 'self-host'],
'/use-dify/nodes/agent': ['cloud', 'self-host'],
'/use-dify/nodes/answer': ['cloud', 'self-host'],
'/use-dify/nodes/code': ['cloud', 'self-host'],
'/use-dify/nodes/doc-extractor': ['cloud', 'self-host'],
'/use-dify/nodes/http-request': ['cloud', 'self-host'],
'/use-dify/nodes/human-input': ['cloud', 'self-host'],
'/use-dify/nodes/ifelse': ['cloud', 'self-host'],
'/use-dify/nodes/iteration': ['cloud', 'self-host'],
'/use-dify/nodes/knowledge-retrieval': ['cloud', 'self-host'],
'/use-dify/nodes/list-operator': ['cloud', 'self-host'],
'/use-dify/nodes/llm': ['cloud', 'self-host'],
'/use-dify/nodes/loop': ['cloud', 'self-host'],
'/use-dify/nodes/output': ['cloud', 'self-host'],
'/use-dify/nodes/parameter-extractor': ['cloud', 'self-host'],
'/use-dify/nodes/question-classifier': ['cloud', 'self-host'],
'/use-dify/nodes/template': ['cloud', 'self-host'],
'/use-dify/nodes/tools': ['cloud', 'self-host'],
'/use-dify/nodes/trigger/overview': ['cloud', 'self-host'],
'/use-dify/nodes/trigger/plugin-trigger': ['cloud', 'self-host'],
'/use-dify/nodes/trigger/schedule-trigger': ['cloud', 'self-host'],
'/use-dify/nodes/trigger/webhook-trigger': ['cloud', 'self-host'],
'/use-dify/nodes/user-input': ['cloud', 'self-host'],
'/use-dify/nodes/variable-aggregator': ['cloud', 'self-host'],
'/use-dify/nodes/variable-assigner': ['cloud', 'self-host'],
'/use-dify/publish/README': ['cloud', 'self-host'],
'/use-dify/publish/developing-with-apis': ['cloud', 'self-host'],
'/use-dify/publish/publish-mcp': ['cloud', 'self-host'],
'/use-dify/publish/publish-to-marketplace': ['cloud', 'self-host'],
'/use-dify/publish/webapp/chatflow-webapp': ['cloud', 'self-host'],
'/use-dify/publish/webapp/embedding-in-websites': ['cloud', 'self-host'],
'/use-dify/publish/webapp/web-app-settings': ['cloud', 'self-host'],
'/use-dify/publish/webapp/workflow-webapp': ['cloud', 'self-host'],
'/use-dify/workspace/api-extension/api-extension': ['cloud', 'self-host'],
'/use-dify/workspace/api-extension/cloudflare-worker': ['cloud', 'self-host'],
'/use-dify/workspace/api-extension/external-data-tool-api-extension': ['cloud', 'self-host'],
'/use-dify/workspace/api-extension/moderation-api-extension': ['cloud', 'self-host'],
'/use-dify/workspace/app-management': ['cloud', 'self-host'],
'/use-dify/workspace/model-providers': ['cloud', 'self-host'],
'/use-dify/workspace/personal-account-management': ['cloud', 'self-host'],
'/use-dify/workspace/plugins': ['cloud', 'self-host'],
'/use-dify/workspace/readme': ['cloud', 'self-host'],
'/use-dify/workspace/subscription-management': ['cloud'],
'/use-dify/workspace/team-members-management': ['cloud', 'self-host'],
'/use-dify/workspace/tools': ['cloud', 'self-host'],
}
// API Reference path translations (English -> other languages)
export const apiReferencePathTranslations: Record<string, { zh?: string; ja?: string }> = {
'/api-reference/annotations/configure-annotation-reply': { zh: '/api-reference/标注管理/配置标注回复', ja: '/api-reference/アノテーション管理/アノテーション返信を設定' },